Lyrics, versioning, and the song page's fact line. - Lyrics are suggested at submission and never imposed: the worker makes one LRCLIB lookup, and Hae sanoitukset re-queries with whatever title and artist are typed. Neither overwrites what the submitter wrote. They live on the submission, travel to the song at publish, and stay editable after the song locks — the lock freezes what a song claims to be, and nobody reviewed the lyrics - The review strip reads and writes side by side: lyrics left, review right. Synced LRC highlights the playing line and seeks on click; plain text scrolls continuously with a nudge knob. Following can be turned off - CalVer YYYY.MM.DD-N, injected from the git tag with -ldflags, shown in the footer, the startup log and /healthz - The song page's metadata became four labelled cells instead of one flat run of five different kinds of fact Fixes: publishing wiped lyrics the worker had just fetched (a request that omitted a field cleared it), lyric auto-scroll landed in the wrong place, and the fader shifted the deck sideways at score 100.
83 lines
3.4 KiB
HTML
83 lines
3.4 KiB
HTML
<!doctype html>
|
|
<html lang="fi">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>{{.Title}} — Levyraati</title>
|
|
<link rel="icon" href="/static/favicon.svg" type="image/svg+xml">
|
|
<link rel="preload" href="/static/fonts/oswald.woff2" as="font" type="font/woff2" crossorigin>
|
|
<link rel="stylesheet" href="/static/style.css">
|
|
<script src="/static/htmx.min.js" defer></script>
|
|
<script src="/static/player.js" defer></script>
|
|
<script src="/static/lyrics.js" defer></script>
|
|
</head>
|
|
<body>
|
|
<header class="topbar">
|
|
<div class="topbar-inner">
|
|
<a class="brand" href="/">Levyraati{{if .Admin}} <span class="badge admin">ylläpito</span>{{end}}</a>
|
|
|
|
{{if .Admin}}
|
|
<nav class="navlinks"><a href="/admin" aria-current="page">Ylläpito</a></nav>
|
|
<span></span>
|
|
{{else if .Member}}
|
|
<nav class="navlinks">
|
|
<a href="/" {{if eq .Path "/"}}aria-current="page"{{end}}>Jono{{if .Queued}} <span class="count">{{.Queued}}</span>{{end}}</a>
|
|
<a href="/songs" {{if eq .Path "/songs"}}aria-current="page"{{end}}>Kappaleet</a>
|
|
<a href="/submit" {{if eq .Path "/submit"}}aria-current="page"{{end}}>Lähetä</a>
|
|
<a href="/stats" {{if eq .Path "/stats"}}aria-current="page"{{end}}>Tilastot</a>
|
|
</nav>
|
|
<div class="userblock">
|
|
<span class="lines">
|
|
<span class="name">{{.Member.Name}}</span>
|
|
<span class="email">{{.Member.Email}}</span>
|
|
</span>
|
|
<a href="/profile" title="{{.Member.Name}}">
|
|
{{if .Member.Avatar}}<img class="avatar" src="/avatars/{{.Member.ID}}" alt="Oma profiili">
|
|
{{else}}<span class="avatar">{{.Member.Initials}}</span>{{end}}
|
|
</a>
|
|
<form method="post" action="/logout"><button class="link">Kirjaudu ulos</button></form>
|
|
|
|
<!-- <details> is the mobile panel: no JS, and Esc/click-away come free. -->
|
|
<details class="mobilenav">
|
|
<summary aria-label="Valikko">☰</summary>
|
|
<div class="panel">
|
|
<a href="/">Jono{{if .Queued}} <span class="count">{{.Queued}}</span>{{end}}</a>
|
|
<a href="/songs">Kappaleet</a>
|
|
<a href="/submit">Lähetä</a>
|
|
<a href="/stats">Tilastot</a>
|
|
<a href="/profile">Oma profiili</a>
|
|
<form method="post" action="/logout"><button type="submit">Kirjaudu ulos</button></form>
|
|
</div>
|
|
</details>
|
|
</div>
|
|
{{else}}
|
|
<span></span>
|
|
<nav class="navlinks"><a href="/login">Kirjaudu</a></nav>
|
|
{{end}}
|
|
</div>
|
|
</header>
|
|
|
|
<main {{if .Narrow}}class="narrow"{{end}}>{{template "content" .}}</main>
|
|
|
|
<footer class="sitefooter">
|
|
{{if .Member}}
|
|
<!-- The server already knows where they were, so the path travels in the link — no JS. -->
|
|
<a href="/report?from={{.Path}}">Ilmoita ongelmasta</a> ·
|
|
{{end}}
|
|
<span class="slogan">We know good music, baby!</span>
|
|
<span class="copyright">© Kessinen</span>
|
|
<span class="version" title="Käytössä oleva versio">v{{.Version}}</span>
|
|
</footer>
|
|
|
|
{{with .Flash}}
|
|
<div class="toasts">
|
|
<div class="toast" role="status">
|
|
<p>{{.}}</p>
|
|
<button class="dismiss" aria-label="Sulje"
|
|
onclick="this.closest('.toast').remove()">×</button>
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</body>
|
|
</html>
|