Step 6. The surfaces around the review loop. - Nine leaderboards, ordered and limited in SQL, each with a deterministic tie-break so a tied board doesn't reshuffle between reloads. Min 3 reviews to qualify, for reviewer boards too - Profiles show counts and history-wide averages and the member's songs, never a list of their reviews — per-song opinion stays gated - Avatars: 5MB in, 256px JPEG out, ffmpeg's re-encode being the validation. No upload still means initials, and avatars are public - Changing your own password requires the current one and drops your other sessions - Palaute: free text plus the page you were on, carried in a footer link, and the user agent from the header. Reporters see their own; the admin resolves them with a timestamp rather than a status enum - Admin gained the song list with delete, the reports page, and an open-report count on the dashboard Two theme fixes the screenshots caught: leaderboard ranks need a CSS counter because display:grid suppresses list markers, and count-based boards were printing 3.0 where they mean 3.
93 lines
3.2 KiB
HTML
93 lines
3.2 KiB
HTML
{{define "content"}}
|
|
<h1>Ylläpito</h1>
|
|
<p><a href="/admin/reports">Palautteet</a>{{if .Data.OpenCount}} <span class="badge pending">{{.Data.OpenCount}} avointa</span>{{end}}</p>
|
|
|
|
<section class="adminsection">
|
|
<header>
|
|
<h2>Kutsut</h2>
|
|
<form method="post" action="/admin/invites"><button type="submit">Luo kutsukoodi</button></form>
|
|
</header>
|
|
<div class="body">
|
|
<table>
|
|
<thead><tr><th>Kutsulinkki</th><th>Tila</th><th>Luotu</th></tr></thead>
|
|
<tbody>
|
|
{{range .Data.Invites}}
|
|
<tr>
|
|
<td>
|
|
{{if .IsValid}}
|
|
<a href="{{.Link}}">{{.Link}}</a>
|
|
{{else}}
|
|
<code class="muted">{{.Code}}</code>
|
|
{{end}}
|
|
</td>
|
|
<td class="nowrap"><span class="dot {{if .IsValid}}on{{else}}off{{end}}"></span> {{if .IsValid}}käyttämätön{{else}}käytetty{{end}}</td>
|
|
<td>{{fidate .CreatedAt}}</td>
|
|
</tr>
|
|
{{else}}
|
|
<tr><td colspan="3" class="muted">Ei kutsuja.</td></tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
<p class="muted small">Lähetä linkki kaverille — se avaa liittymislomakkeen koodi valmiiksi täytettynä.</p>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="adminsection">
|
|
<header><h2>Jäsenet</h2></header>
|
|
<div class="body">
|
|
<table>
|
|
<thead><tr><th>Nimi</th><th>Sähköposti</th><th>Liittyi</th><th>Toiminnot</th></tr></thead>
|
|
<tbody>
|
|
{{range .Data.Members}}
|
|
<tr{{if .Banned}} class="banned"{{end}}>
|
|
<td>{{.Name}}{{if .Banned}} <span class="badge pending">estetty</span>{{end}}</td>
|
|
<td>{{.Email}}</td>
|
|
<td>{{fidate .CreatedAt}}</td>
|
|
<td class="actions">
|
|
<form method="post" action="/admin/users/{{.ID}}/ban">
|
|
<button type="submit" class="ghost">{{if .Banned}}Poista esto{{else}}Estä{{end}}</button>
|
|
</form>
|
|
<form method="post" action="/admin/users/{{.ID}}/password">
|
|
<input type="password" name="password" placeholder="uusi salasana" required>
|
|
<button type="submit" class="ghost">Vaihda salasana</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{{else}}
|
|
<tr><td colspan="4" class="muted">Ei jäseniä. Luo kutsukoodi ja lähetä se jollekulle.</td></tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="adminsection">
|
|
<header><h2>Kappaleet</h2></header>
|
|
<div class="body">
|
|
<table>
|
|
<thead><tr><th>Kappale</th><th>Lähettäjä</th><th>Arvostelut</th><th>Julkaistu</th><th></th></tr></thead>
|
|
<tbody>
|
|
{{range .Data.Songs}}
|
|
<tr>
|
|
<td>{{.Title}} <span class="muted">— {{.Artist}}</span></td>
|
|
<td>{{.Submitter}}</td>
|
|
<td>{{.Reviews}}</td>
|
|
<td class="nowrap">{{fidate .CreatedAt}}</td>
|
|
<td class="actions">
|
|
<a href="/admin/audio/{{.ID}}">Kuuntele</a>
|
|
<form method="post" action="/admin/songs/{{.ID}}/delete"
|
|
onsubmit="return confirm('Poistetaanko kappale ja kaikki sen arvostelut?')">
|
|
<button type="submit" class="ghost danger">Poista</button>
|
|
</form>
|
|
</td>
|
|
</tr>
|
|
{{else}}
|
|
<tr><td colspan="5" class="muted">Ei kappaleita.</td></tr>
|
|
{{end}}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
{{end}}
|