tidy up forrmatting on pages
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2026-01-15 12:11:01 +11:00
parent 0beafb5b00
commit 3f985dcd4d
5 changed files with 135 additions and 43 deletions

View File

@@ -92,6 +92,45 @@ templ Header() {
padding: 0.75rem 1rem;
box-shadow: none;
}
.web2-table {
width: 100%;
border-collapse: collapse;
font-size: 0.95rem;
}
.web2-table thead th {
text-align: left;
padding: 0.75rem 0.5rem;
font-weight: 700;
color: var(--web2-muted);
border-bottom: 1px solid var(--web2-border);
}
.web2-table tbody td {
padding: 0.9rem 0.5rem;
border-bottom: 1px solid var(--web2-border);
}
.web2-table tbody tr:nth-child(odd) {
background: #f8fafc;
}
.web2-table tbody tr:nth-child(even) {
background: #ffffff;
}
.web2-group-row td {
background: #e8eef5;
color: #0f172a;
border-bottom: 1px solid var(--web2-border);
padding: 0.65rem 0.5rem;
}
.web2-badge {
display: inline-flex;
align-items: center;
gap: 0.25rem;
border: 1px solid var(--web2-border);
padding: 0.15rem 0.45rem;
border-radius: 3px;
font-size: 0.8rem;
color: var(--web2-muted);
background: #f8fafc;
}
</style>
</head>
}

View File

@@ -44,7 +44,7 @@ func Header() templ.Component {
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" rel=\"stylesheet\"><style>\n\t\t\t:root {\n\t\t\t\t--web2-blue: #1d9bf0;\n\t\t\t\t--web2-slate: #0f172a;\n\t\t\t\t--web2-muted: #64748b;\n\t\t\t\t--web2-card: #ffffff;\n\t\t\t\t--web2-border: #e5e7eb;\n\t\t\t}\n\t\t\tbody {\n\t\t\t\tfont-family: \"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif;\n\t\t\t\tcolor: var(--web2-slate);\n\t\t\t}\n\t\t\t.web2-bg {\n\t\t\t\tbackground: #ffffff;\n\t\t\t}\n\t\t\t.web2-shell {\n\t\t\t\tmax-width: 1100px;\n\t\t\t\tmargin: 0 auto;\n\t\t\t\tpadding: 2rem 1.5rem 4rem;\n\t\t\t}\n\t\t\t.web2-header {\n\t\t\t\tbackground: var(--web2-card);\n\t\t\t\tborder: 1px solid var(--web2-border);\n\t\t\t\tborder-radius: 4px;\n\t\t\t\tpadding: 1.5rem 2rem;\n\t\t\t}\n\t\t\t.web2-card {\n\t\t\t\tbackground: var(--web2-card);\n\t\t\t\tborder: 1px solid var(--web2-border);\n\t\t\t\tborder-radius: 4px;\n\t\t\t\tpadding: 1.5rem 1.75rem;\n\t\t\t}\n\t\t\t.web2-pill {\n\t\t\t\tdisplay: inline-flex;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: 0.4rem;\n\t\t\t\tbackground: #f8fafc;\n\t\t\t\tborder: 1px solid var(--web2-border);\n\t\t\t\tcolor: var(--web2-muted);\n\t\t\t\tpadding: 0.2rem 0.6rem;\n\t\t\t\tborder-radius: 3px;\n\t\t\t\tfont-size: 0.85rem;\n\t\t\t\tletter-spacing: 0.02em;\n\t\t\t}\n\t\t\t.web2-link {\n\t\t\t\tcolor: var(--web2-blue);\n\t\t\t\ttext-decoration: none;\n\t\t\t\tfont-weight: 600;\n\t\t\t}\n\t\t\t.web2-link:hover {\n\t\t\t\ttext-decoration: underline;\n\t\t\t}\n\t\t\t.web2-button {\n\t\t\t\tbackground: var(--web2-blue);\n\t\t\t\tcolor: #fff;\n\t\t\t\tpadding: 0.45rem 0.9rem;\n\t\t\t\tborder-radius: 3px;\n\t\t\t\tborder: 1px solid #1482d0;\n\t\t\t\tbox-shadow: none;\n\t\t\t\tfont-weight: 600;\n\t\t\t\ttext-decoration: none;\n\t\t\t}\n\t\t\t.web2-button:hover {\n\t\t\t\tbackground: #1787d4;\n\t\t\t}\n\t\t\t.web2-button-group {\n\t\t\t\tdisplay: flex;\n\t\t\t\tflex-wrap: wrap;\n\t\t\t}\n\t\t\t.web2-button-group .web2-button {\n\t\t\t\tmargin: 0 0.5rem 0.5rem 0;\n\t\t\t}\n\t\t\t.web2-list li {\n\t\t\t\tbackground: #ffffff;\n\t\t\t\tborder: 1px solid var(--web2-border);\n\t\t\t\tborder-radius: 3px;\n\t\t\t\tpadding: 0.75rem 1rem;\n\t\t\t\tbox-shadow: none;\n\t\t\t}\n\t\t</style></head>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" rel=\"stylesheet\"><style>\n\t\t\t:root {\n\t\t\t\t--web2-blue: #1d9bf0;\n\t\t\t\t--web2-slate: #0f172a;\n\t\t\t\t--web2-muted: #64748b;\n\t\t\t\t--web2-card: #ffffff;\n\t\t\t\t--web2-border: #e5e7eb;\n\t\t\t}\n\t\t\tbody {\n\t\t\t\tfont-family: \"Segoe UI\", \"Helvetica Neue\", Arial, sans-serif;\n\t\t\t\tcolor: var(--web2-slate);\n\t\t\t}\n\t\t\t.web2-bg {\n\t\t\t\tbackground: #ffffff;\n\t\t\t}\n\t\t\t.web2-shell {\n\t\t\t\tmax-width: 1100px;\n\t\t\t\tmargin: 0 auto;\n\t\t\t\tpadding: 2rem 1.5rem 4rem;\n\t\t\t}\n\t\t\t.web2-header {\n\t\t\t\tbackground: var(--web2-card);\n\t\t\t\tborder: 1px solid var(--web2-border);\n\t\t\t\tborder-radius: 4px;\n\t\t\t\tpadding: 1.5rem 2rem;\n\t\t\t}\n\t\t\t.web2-card {\n\t\t\t\tbackground: var(--web2-card);\n\t\t\t\tborder: 1px solid var(--web2-border);\n\t\t\t\tborder-radius: 4px;\n\t\t\t\tpadding: 1.5rem 1.75rem;\n\t\t\t}\n\t\t\t.web2-pill {\n\t\t\t\tdisplay: inline-flex;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: 0.4rem;\n\t\t\t\tbackground: #f8fafc;\n\t\t\t\tborder: 1px solid var(--web2-border);\n\t\t\t\tcolor: var(--web2-muted);\n\t\t\t\tpadding: 0.2rem 0.6rem;\n\t\t\t\tborder-radius: 3px;\n\t\t\t\tfont-size: 0.85rem;\n\t\t\t\tletter-spacing: 0.02em;\n\t\t\t}\n\t\t\t.web2-link {\n\t\t\t\tcolor: var(--web2-blue);\n\t\t\t\ttext-decoration: none;\n\t\t\t\tfont-weight: 600;\n\t\t\t}\n\t\t\t.web2-link:hover {\n\t\t\t\ttext-decoration: underline;\n\t\t\t}\n\t\t\t.web2-button {\n\t\t\t\tbackground: var(--web2-blue);\n\t\t\t\tcolor: #fff;\n\t\t\t\tpadding: 0.45rem 0.9rem;\n\t\t\t\tborder-radius: 3px;\n\t\t\t\tborder: 1px solid #1482d0;\n\t\t\t\tbox-shadow: none;\n\t\t\t\tfont-weight: 600;\n\t\t\t\ttext-decoration: none;\n\t\t\t}\n\t\t\t.web2-button:hover {\n\t\t\t\tbackground: #1787d4;\n\t\t\t}\n\t\t\t.web2-button-group {\n\t\t\t\tdisplay: flex;\n\t\t\t\tflex-wrap: wrap;\n\t\t\t}\n\t\t\t.web2-button-group .web2-button {\n\t\t\t\tmargin: 0 0.5rem 0.5rem 0;\n\t\t\t}\n\t\t\t.web2-list li {\n\t\t\t\tbackground: #ffffff;\n\t\t\t\tborder: 1px solid var(--web2-border);\n\t\t\t\tborder-radius: 3px;\n\t\t\t\tpadding: 0.75rem 1rem;\n\t\t\t\tbox-shadow: none;\n\t\t\t}\n\t\t\t.web2-table {\n\t\t\t\twidth: 100%;\n\t\t\t\tborder-collapse: collapse;\n\t\t\t\tfont-size: 0.95rem;\n\t\t\t}\n\t\t\t.web2-table thead th {\n\t\t\t\ttext-align: left;\n\t\t\t\tpadding: 0.75rem 0.5rem;\n\t\t\t\tfont-weight: 700;\n\t\t\t\tcolor: var(--web2-muted);\n\t\t\t\tborder-bottom: 1px solid var(--web2-border);\n\t\t\t}\n\t\t\t.web2-table tbody td {\n\t\t\t\tpadding: 0.9rem 0.5rem;\n\t\t\t\tborder-bottom: 1px solid var(--web2-border);\n\t\t\t}\n\t\t\t.web2-table tbody tr:nth-child(odd) {\n\t\t\t\tbackground: #f8fafc;\n\t\t\t}\n\t\t\t.web2-table tbody tr:nth-child(even) {\n\t\t\t\tbackground: #ffffff;\n\t\t\t}\n\t\t\t.web2-group-row td {\n\t\t\t\tbackground: #e8eef5;\n\t\t\t\tcolor: #0f172a;\n\t\t\t\tborder-bottom: 1px solid var(--web2-border);\n\t\t\t\tpadding: 0.65rem 0.5rem;\n\t\t\t}\n\t\t\t.web2-badge {\n\t\t\t\tdisplay: inline-flex;\n\t\t\t\talign-items: center;\n\t\t\t\tgap: 0.25rem;\n\t\t\t\tborder: 1px solid var(--web2-border);\n\t\t\t\tpadding: 0.15rem 0.45rem;\n\t\t\t\tborder-radius: 3px;\n\t\t\t\tfont-size: 0.8rem;\n\t\t\t\tcolor: var(--web2-muted);\n\t\t\t\tbackground: #f8fafc;\n\t\t\t}\n\t\t</style></head>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}

View File

@@ -8,6 +8,7 @@ type SnapshotEntry struct {
Label string
Link string
Count int64
Group string
}
templ SnapshotHourlyList(entries []SnapshotEntry) {
@@ -40,21 +41,43 @@ templ SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) {
</section>
<section class="web2-card">
<div class="flex items-center justify-between gap-3">
<h2 class="text-lg font-semibold">Available Exports&nbsp;</h2>
<span class="text-xs uppercase tracking-[0.2em] text-slate-400">{len(entries)} files</span>
<div class="flex items-center justify-between gap-3 mb-4 flex-wrap">
<h2 class="text-lg font-semibold">Available Exports</h2>
<span class="web2-badge">{len(entries)} files</span>
</div>
<div class="overflow-hidden border border-slate-200 rounded">
<table class="web2-table">
<thead>
<tr>
<th>Snapshot</th>
<th>Records</th>
<th class="text-right">Download</th>
</tr>
</thead>
<tbody>
for i, entry := range entries {
if entry.Group != "" && (i == 0 || entries[i-1].Group != entry.Group) {
<tr class="web2-group-row">
<td colspan="3" class="font-semibold text-slate-700">{entry.Group}</td>
</tr>
}
<tr>
<td>
<div class="flex flex-col">
<span class="text-sm font-semibold text-slate-700">{entry.Label}</span>
</div>
</td>
<td>
<span class="web2-badge">{entry.Count} records</span>
</td>
<td class="text-right">
<a class="web2-link" href={entry.Link}>Download XLSX</a>
</td>
</tr>
}
</tbody>
</table>
</div>
<ul class="mt-6 space-y-3 web2-list">
for _, entry := range entries {
<li class="flex items-center justify-between gap-4">
<div class="flex flex-col">
<span class="text-sm font-semibold text-slate-700">{entry.Label}</span>
<span class="text-xs text-slate-500">{entry.Count} records</span>
</div>
<a class="web2-link" href={entry.Link}>Download XLSX</a>
</li>
}
</ul>
</section>
</main>
</body>

View File

@@ -16,6 +16,7 @@ type SnapshotEntry struct {
Label string
Link string
Count int64
Group string
}
func SnapshotHourlyList(entries []SnapshotEntry) templ.Component {
@@ -141,7 +142,7 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te
var templ_7745c5c3_Var5 string
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 35, Col: 49}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 36, Col: 49}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
if templ_7745c5c3_Err != nil {
@@ -154,75 +155,94 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te
var templ_7745c5c3_Var6 string
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(subtitle)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 36, Col: 55}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 37, Col: 55}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p></div><a class=\"web2-button\" href=\"/\">Back to Dashboard</a></div></section><section class=\"web2-card\"><div class=\"flex items-center justify-between gap-3\"><h2 class=\"text-lg font-semibold\">Available Exports&nbsp;</h2><span class=\"text-xs uppercase tracking-[0.2em] text-slate-400\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p></div><a class=\"web2-button\" href=\"/\">Back to Dashboard</a></div></section><section class=\"web2-card\"><div class=\"flex items-center justify-between gap-3 mb-4 flex-wrap\"><h2 class=\"text-lg font-semibold\">Available Exports</h2><span class=\"web2-badge\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var7 string
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(len(entries))
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 45, Col: 83}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 46, Col: 44}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " files</span></div><ul class=\"mt-6 space-y-3 web2-list\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, " files</span></div><div class=\"overflow-hidden border border-slate-200 rounded\"><table class=\"web2-table\"><thead><tr><th>Snapshot</th><th>Records</th><th class=\"text-right\">Download</th></tr></thead> <tbody>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
for _, entry := range entries {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<li class=\"flex items-center justify-between gap-4\"><div class=\"flex flex-col\"><span class=\"text-sm font-semibold text-slate-700\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
for i, entry := range entries {
if entry.Group != "" && (i == 0 || entries[i-1].Group != entry.Group) {
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<tr class=\"web2-group-row\"><td colspan=\"3\" class=\"font-semibold text-slate-700\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Group)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 61, Col: 76}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
var templ_7745c5c3_Var8 string
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Label)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 51, Col: 72}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</span> <span class=\"text-xs text-slate-500\">")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, " <tr><td><div class=\"flex flex-col\"><span class=\"text-sm font-semibold text-slate-700\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var9 string
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Count)
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Label)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 52, Col: 58}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 67, Col: 75}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, " records</span></div><a class=\"web2-link\" href=\"")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</span></div></td><td><span class=\"web2-badge\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var10 templ.SafeURL
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinURLErrs(entry.Link)
var templ_7745c5c3_Var10 string
templ_7745c5c3_Var10, templ_7745c5c3_Err = templ.JoinStringErrs(entry.Count)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 54, Col: 45}
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 71, Col: 48}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var10))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\">Download XLSX</a></li>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, " records</span></td><td class=\"text-right\"><a class=\"web2-link\" href=\"")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var11 templ.SafeURL
templ_7745c5c3_Var11, templ_7745c5c3_Err = templ.JoinURLErrs(entry.Link)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `views/snapshots.templ`, Line: 74, Col: 48}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var11))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "\">Download XLSX</a></td></tr>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</ul></section></main></body>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 12, "</tbody></table></div></section></main></body>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
@@ -230,7 +250,7 @@ func SnapshotListPage(title string, subtitle string, entries []SnapshotEntry) te
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</html>")
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 13, "</html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}

View File

@@ -109,10 +109,20 @@ func (h *Handler) renderSnapshotList(w http.ResponseWriter, r *http.Request, sna
entries := make([]views.SnapshotEntry, 0, len(records))
for _, record := range records {
label := report.FormatSnapshotLabel(snapshotType, record.SnapshotTime, record.TableName)
group := ""
switch snapshotType {
case "hourly":
group = record.SnapshotTime.Format("2006-01-02")
case "daily":
group = record.SnapshotTime.Format("January 2006")
case "monthly":
group = record.SnapshotTime.Format("2006")
}
entries = append(entries, views.SnapshotEntry{
Label: label,
Link: "/reports/" + url.PathEscape(record.TableName) + ".xlsx",
Count: record.SnapshotCount,
Group: group,
})
}