Files
restic-manager/web/templates/pages/host_schedules.html
T
steve 54528b9b15 P2R-02 follow-up: clickable rows on Sources/Schedules + cron-preset tooltips
Aligns Sources and Schedules tab rows with the dashboard's row-click
UX: whole-row click navigates to the row's edit page (mirroring
.host-row.clickable). Drops the redundant Edit buttons; Run-now and
Delete remain in .row-action cells that sit above the row-link
overlay via z-index.

Schedule edit form's cron preset chips now carry human-readable
title= tooltips ("Every day at 03:00", "Every Sunday at 03:00", etc).

tasks.md gets a binding row-design rule covering all current and
future list-row templates, and the P2R-02 entry is split into the
six slices already agreed with the operator (slices 1–3 marked
done, 4 next).
2026-05-03 12:01:55 +01:00

74 lines
3.4 KiB
HTML

{{define "title"}}{{.Title}}{{end}}
{{define "content"}}
{{template "host_chrome" .}}
{{$page := .Page}}
{{$host := $page.Host}}
{{$groupNames := $page.GroupNames}}
<div class="max-w-[1280px] mx-auto px-8 pb-14 pt-6">
<div class="flex items-center justify-between mb-4">
<p class="text-pretty text-[12.5px] text-ink-mute leading-[1.6] max-w-[760px]">
A schedule is a cron expression pointing at one or more source groups. When it fires, the agent runs a separate
<span class="mono text-ink-mid">restic backup</span> per chosen group — independent jobs, independent snapshots,
independent retention. Failure of one group doesn't fail the others.
</p>
<a href="/hosts/{{$host.ID}}/schedules/new" class="btn btn-primary whitespace-nowrap">+ New schedule</a>
</div>
{{if eq (len $page.Schedules) 0}}
<div class="panel rounded-[7px] empty-state" style="border-radius: 7px;">
<h3 class="text-base font-medium tracking-[-0.005em]">No schedules yet.</h3>
<p class="text-pretty text-ink-mute text-[13px] mt-2 mx-auto max-w-[480px] leading-[1.65]">
Add one and the agent will start running backups on whatever cron expression you give it.
Until then, Run-now from the Sources tab is the only way to trigger a backup.
</p>
<div class="mt-5">
<a href="/hosts/{{$host.ID}}/schedules/new" class="btn btn-primary">+ New schedule</a>
</div>
</div>
{{else}}
<div class="panel rounded-[7px] overflow-hidden">
<div class="schd-row head hairline">
<div>Status</div>
<div>Cron</div>
<div>Sources</div>
<div></div>
</div>
{{range $i, $sc := $page.Schedules}}
<div class="schd-row clickable {{if not (eq $i 0)}}hairline{{end}}">
<a href="/hosts/{{$host.ID}}/schedules/{{$sc.ID}}/edit" class="row-link" aria-label="Edit schedule">edit</a>
<div>
{{if $sc.Enabled}}
<span class="mono text-[11px] text-ok">enabled</span>
{{else}}
<span class="mono text-[11px] text-ink-fade">paused</span>
{{end}}
</div>
<div class="mono {{if $sc.Enabled}}text-ink{{else}}text-ink-mute{{end}}">{{$sc.CronExpr}}</div>
<div class="flex gap-1.5 flex-wrap">
{{range $sc.SourceGroupIDs}}
{{$name := index $groupNames .}}
<span class="tag" style="border-color: color-mix(in oklch, var(--accent), transparent 60%); color: var(--accent); {{if not $sc.Enabled}}opacity: 0.6;{{end}}">{{if $name}}{{$name}}{{else}}<span class="text-ink-fade">unknown</span>{{end}}</span>
{{end}}
</div>
<div class="flex gap-1.5 justify-end row-action">
{{if and $sc.Enabled (eq $host.Status "online")}}
<button class="btn btn-primary"
hx-post="/hosts/{{$host.ID}}/schedules/{{$sc.ID}}/run"
hx-swap="none"
hx-disabled-elt="this">Run now</button>
{{end}}
<form method="post" action="/hosts/{{$host.ID}}/schedules/{{$sc.ID}}/delete" style="display: inline;"
onsubmit="return confirm('Delete this schedule? Existing snapshots are not affected.');">
<button type="submit" class="btn btn-danger">Delete</button>
</form>
</div>
</div>
{{end}}
</div>
{{end}}
</div>
{{end}}