v1.0.0
Some checks failed
release-tag / release-image (push) Successful in 4m8s
build-binaries / build (, amd64, linux) (push) Failing after 40s
build-binaries / build (, arm, 7, linux) (push) Failing after 37s
build-binaries / build (, arm64, linux) (push) Failing after 37s
build-binaries / build (.exe, amd64, windows) (push) Failing after 36s
build-binaries / release (push) Has been skipped
Some checks failed
release-tag / release-image (push) Successful in 4m8s
build-binaries / build (, amd64, linux) (push) Failing after 40s
build-binaries / build (, arm, 7, linux) (push) Failing after 37s
build-binaries / build (, arm64, linux) (push) Failing after 37s
build-binaries / build (.exe, amd64, windows) (push) Failing after 36s
build-binaries / release (push) Has been skipped
This commit is contained in:
117
main.go
117
main.go
@@ -245,12 +245,12 @@ var baseTpl = `{{define "base"}}
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>{{block "title" .}}Meldesystem{{end}}</title>
|
||||
<title>{{block "title" .}}Advocacy Watchlist{{end}}</title>
|
||||
<style>
|
||||
:root { --bg:#0f172a; --card:#111827; --muted:#9ca3af; --text:#e5e7eb; --acc:#06b6d4; --ok:#10b981; --warn:#f59e0b; --err:#ef4444; }
|
||||
*{box-sizing:border-box} body{margin:0;background:linear-gradient(180deg,#0b1220,#0f172a);color:var(--text);font:16px/1.45 system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial}
|
||||
a{color:var(--acc);text-decoration:none} a:hover{text-decoration:underline}
|
||||
.container{max-width:980px;margin:40px auto;padding:0 16px}
|
||||
.container{max-width:1200px;margin:40px auto;padding:0 16px}
|
||||
header{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px}
|
||||
.brand{font-weight:800;font-size:20px;letter-spacing:.2px}
|
||||
.card{background:var(--card);border:1px solid #1f2937;border-radius:16px;box-shadow:0 10px 30px rgba(0,0,0,.25);padding:20px;margin-bottom:16px}
|
||||
@@ -278,7 +278,7 @@ var baseTpl = `{{define "base"}}
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="brand">Meldesystem</div>
|
||||
<div class="brand">Advocacy Watchlist</div>
|
||||
<div class="flex">
|
||||
{{if .IsAdmin}}<a class="badge" href="/users">👥 Nutzer</a>{{end}}
|
||||
<a class="badge" href="/audit">🪪 Audit</a>
|
||||
@@ -288,7 +288,7 @@ var baseTpl = `{{define "base"}}
|
||||
</div>
|
||||
</header>
|
||||
{{template "content" .}}
|
||||
<footer>Ohne externe Assets · Zeit: {{.Now}}</footer>
|
||||
<footer>Advocacy Watchlist · Zeit: {{.Now}}</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -300,12 +300,24 @@ var loginTpl = `{{define "login"}}
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Login · Meldesystem</title>
|
||||
<style>*{box-sizing:border-box} body{margin:0;display:grid;place-items:center;height:100vh;background:linear-gradient(180deg,#0b1220,#0f172a);color:#e5e7eb;font:16px/1.45 system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial} .card{background:#111827;border:1px solid #1f2937;border-radius:16px;box-shadow:0 10px 30px rgba(0,0,0,.25);padding:24px;width:min(420px,94vw)} input{width:100%;max-width:100%;display:block;margin:0;border:1px solid #273244;border-radius:12px;background:#0b1220;color:#e5e7eb;padding:12px 14px} label{display:block;margin:8px 0 6px;color:#9ca3af} button{width:100%;margin-top:14px;padding:12px;border:0;border-radius:12px;background:#06b6d4;color:#001018;font-weight:800;cursor:pointer} .muted{color:#9ca3af;font-size:12px;text-align:center;margin-top:10px}</style>
|
||||
<title>Login · Advocacy Watchlist</title>
|
||||
<style>
|
||||
*{box-sizing:border-box}
|
||||
body{margin:0;display:grid;place-items:center;height:100vh;background:linear-gradient(180deg,#0b1220,#0f172a);color:#e5e7eb;font:16px/1.45 system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial}
|
||||
.card{background:#111827;border:1px solid #1f2937;border-radius:16px;box-shadow:0 10px 30px rgba(0,0,0,.25);padding:24px;width:min(420px,94vw)}
|
||||
input{width:100%;max-width:100%;display:block;margin:0;border:1px solid #273244;border-radius:12px;background:#0b1220;color:#e5e7eb;padding:12px 14px}
|
||||
label{display:block;margin:8px 0 6px;color:#9ca3af}
|
||||
button{width:100%;margin-top:14px;padding:12px;border:0;border-radius:12px;background:#06b6d4;color:#001018;font-weight:800;cursor:pointer}
|
||||
.badge{display:inline-flex;align-items:center;gap:6px;padding:4px 10px;border-radius:999px;background:#0b1220;border:1px solid #1f2937;color:#9ca3af;font-size:12px} <!-- NEU -->
|
||||
.muted{color:#9ca3af;font-size:12px;text-align:center;margin-top:10px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="card">
|
||||
<h2 style="margin:0 0 8px">Anmeldung</h2>
|
||||
<div style="margin-top:12px;text-align:center">
|
||||
<a class="badge" href="/public">🌐 View public Entries</a>
|
||||
</div>
|
||||
<form method="POST" action="/login">
|
||||
<label>Nutzername</label>
|
||||
<input name="username" required />
|
||||
@@ -422,7 +434,7 @@ var dashboardTpl = `{{define "dashboard"}}{{template "base" .}}{{end}}
|
||||
<button type="submit">Bestätigen</button>
|
||||
</form>
|
||||
{{else}}
|
||||
<span class="badge">⏳ Wartet auf Bestätigung durch andere</span>
|
||||
<span class="badge">⏳ Wartet auf Bestätigung</span>
|
||||
{{end}}
|
||||
{{else}}
|
||||
<span class="badge">✔ Bereits bestätigt</span>
|
||||
@@ -443,6 +455,65 @@ var dashboardTpl = `{{define "dashboard"}}{{template "base" .}}{{end}}
|
||||
</div>
|
||||
{{end}}`
|
||||
|
||||
var publicTpl = `{{define "public_page"}}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Advocacy Watchlist - Public</title>
|
||||
<style>
|
||||
:root { --bg:#0f172a; --card:#111827; --muted:#9ca3af; --text:#e5e7eb; --acc:#06b6d4; }
|
||||
*{box-sizing:border-box} body{margin:0;background:linear-gradient(180deg,#0b1220,#0f172a);color:var(--text);font:16px/1.45 system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial}
|
||||
.container{max-width:880px;margin:40px auto;padding:0 16px}
|
||||
header{display:flex;align-items:center;justify-content:space-between;margin-bottom:24px}
|
||||
.card{background:#111827;border:1px solid #1f2937;border-radius:16px;box-shadow:0 10px 30px rgba(0,0,0,.25);padding:20px;margin-bottom:16px}
|
||||
.row{display:flex;gap:12px;flex-wrap:wrap;align-items:center}
|
||||
input[type=text]{flex:1 1 260px;padding:12px 14px;border:1px solid #273244;border-radius:12px;background:#0b1220;color:#e5e7eb}
|
||||
button{padding:10px 14px;border:0;border-radius:12px;background:#06b6d4;color:#001018;font-weight:700;cursor:pointer}
|
||||
table{width:100%;border-collapse:separate;border-spacing:0}
|
||||
th,td{padding:12px 10px;border-bottom:1px solid #1f2937;font-size:14px}
|
||||
th{text-align:left;color:#9ca3af;font-weight:600}
|
||||
.muted{color:#9ca3af}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<header>
|
||||
<div class="brand">Advocacy Watchlist</div>
|
||||
<div class="flex">
|
||||
<a class="badge" href="/">🔒 Login</a>
|
||||
</div>
|
||||
</header>
|
||||
<div class="card">
|
||||
<h2 style="margin:0 0 10px">Public list of confirmed entries</h2>
|
||||
<form class="row" method="GET" action="/public">
|
||||
<input name="q" placeholder="Search…" value="{{.Q}}" />
|
||||
<button type="submit">Filter</button>
|
||||
</form>
|
||||
<div class="muted" style="margin-top:8px">Only <b>confirmed</b> entries are displayed.</div>
|
||||
</div>
|
||||
|
||||
<div class="card">
|
||||
<table>
|
||||
<thead><tr><th>Benutzername</th><th>Confirmed on</th></tr></thead>
|
||||
<tbody>
|
||||
{{range .Rows}}
|
||||
<tr>
|
||||
<td>{{.Name}}</td>
|
||||
<td class="muted">{{.Since}}</td>
|
||||
</tr>
|
||||
{{else}}
|
||||
<tr><td colspan="2" class="muted">No matching entries</td></tr>
|
||||
{{end}}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
{{end}}`
|
||||
|
||||
var auditTpl = `{{define "audit_page"}}
|
||||
<!doctype html>
|
||||
<html lang="de">
|
||||
@@ -625,8 +696,10 @@ func main() {
|
||||
template.Must(tpl.New("audit_bundle").Parse(auditTpl))
|
||||
template.Must(tpl.New("users_bundle").Parse(usersTpl))
|
||||
template.Must(tpl.New("me_bundle").Parse(meTpl))
|
||||
template.Must(tpl.New("public_bundle").Parse(publicTpl))
|
||||
|
||||
http.HandleFunc("/", withAuth(handleIndex))
|
||||
http.HandleFunc("/public", handlePublic)
|
||||
http.HandleFunc("/reasons/add", withAuth(handleReasonAdd))
|
||||
http.HandleFunc("/reasons/delete", withAuth(handleReasonDelete))
|
||||
http.HandleFunc("/report", withAuth(handleReport))
|
||||
@@ -895,6 +968,36 @@ func handleIndex(w http.ResponseWriter, r *http.Request) {
|
||||
_ = tpl.ExecuteTemplate(w, "dashboard", data)
|
||||
}
|
||||
|
||||
func handlePublic(w http.ResponseWriter, r *http.Request) {
|
||||
q := strings.TrimSpace(r.URL.Query().Get("q"))
|
||||
ql := strings.ToLower(q)
|
||||
|
||||
mu.Lock()
|
||||
reports := make([]Report, 0, len(db.Reports))
|
||||
for _, rep := range db.Reports {
|
||||
if rep.Status != StatusBestaetigt {
|
||||
continue // nur bestätigte öffentlich anzeigen
|
||||
}
|
||||
if q == "" || strings.Contains(strings.ToLower(rep.Name), ql) {
|
||||
reports = append(reports, rep)
|
||||
}
|
||||
}
|
||||
mu.Unlock()
|
||||
|
||||
rows := make([]map[string]any, 0, len(reports))
|
||||
for _, rep := range reports {
|
||||
rows = append(rows, map[string]any{
|
||||
"Name": template.HTMLEscapeString(rep.Name),
|
||||
"Since": time.Unix(rep.ConfirmedAt, 0).Format("02.01.2006 15:04"),
|
||||
})
|
||||
}
|
||||
|
||||
_ = tpl.ExecuteTemplate(w, "public_page", map[string]any{
|
||||
"Q": q,
|
||||
"Rows": rows,
|
||||
})
|
||||
}
|
||||
|
||||
func handleReport(w http.ResponseWriter, r *http.Request) {
|
||||
if r.Method != http.MethodPost {
|
||||
w.WriteHeader(http.StatusMethodNotAllowed)
|
||||
|
||||
Reference in New Issue
Block a user