64d2fcf7a3
CI / Test (linux/amd64) (pull_request) Successful in 1m57s
CI / Lint (pull_request) Failing after 15s
CI / Build (windows/amd64) (pull_request) Successful in 22s
CI / Build (linux/amd64) (pull_request) Successful in 22s
CI / Build (linux/arm64) (pull_request) Successful in 22s
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).
92 lines
4.9 KiB
HTML
92 lines
4.9 KiB
HTML
{{define "title"}}{{.Title}}{{end}}
|
|
|
|
{{define "content"}}
|
|
{{template "host_chrome" .}}
|
|
{{$page := .Page}}
|
|
{{$host := $page.Host}}
|
|
<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-[720px]">
|
|
Each source group is a named bundle of paths plus the rule for how long its snapshots stick around.
|
|
Schedules point at one or more groups — one <span class="mono text-ink-mid">restic backup</span> runs per group,
|
|
tagged by name so <span class="mono text-ink-mid">forget</span> can apply retention cleanly.
|
|
</p>
|
|
<a href="/hosts/{{$host.ID}}/sources/new" class="btn btn-primary whitespace-nowrap">+ New source group</a>
|
|
</div>
|
|
|
|
{{if eq (len $page.Groups) 0}}
|
|
<div class="panel rounded-[7px] empty-state" style="border-radius: 7px;">
|
|
<h3 class="text-base font-medium tracking-[-0.005em]">No source groups yet.</h3>
|
|
<p class="text-pretty text-ink-mute text-[13px] mt-2 mx-auto max-w-[480px] leading-[1.65]">
|
|
Create one to tell the agent what to back up. The group's name doubles as the snapshot tag.
|
|
</p>
|
|
<div class="mt-5">
|
|
<a href="/hosts/{{$host.ID}}/sources/new" class="btn btn-primary">+ New source group</a>
|
|
</div>
|
|
</div>
|
|
{{else}}
|
|
<div class="panel rounded-[7px] overflow-hidden">
|
|
{{range $i, $row := $page.Groups}}
|
|
{{$g := $row.Group}}
|
|
<div class="src-row clickable {{if not (eq $i 0)}}hairline{{end}}">
|
|
<a href="/hosts/{{$host.ID}}/sources/{{$g.ID}}/edit" class="row-link" aria-label="Edit {{$g.Name}}">{{$g.Name}}</a>
|
|
<div>
|
|
<div class="flex items-center" style="gap: 10px;">
|
|
<span class="tag mono" style="border-color: color-mix(in oklch, var(--accent), transparent 60%); color: var(--accent);">{{$g.Name}}</span>
|
|
{{if $g.ConflictDimension}}
|
|
<span class="tag" title="keep-{{$g.ConflictDimension}} is set, but no schedule pointing at this group fires often enough to populate that bucket. Either drop the keep-{{$g.ConflictDimension}} value or add a finer-grained schedule."
|
|
style="border-color: color-mix(in oklch, var(--warn), transparent 60%); color: var(--warn); cursor: help;">keep-{{$g.ConflictDimension}} · cadence mismatch</span>
|
|
{{end}}
|
|
</div>
|
|
<div class="mono text-[12px] text-ink-mid mt-2">
|
|
{{len $g.Includes}} include{{if ne (len $g.Includes) 1}}s{{end}} ·
|
|
{{len $g.Excludes}} exclude{{if ne (len $g.Excludes) 1}}s{{end}} ·
|
|
{{$g.RetentionPolicy.Summary}}
|
|
</div>
|
|
<div class="text-[11.5px] text-ink-fade mt-1">
|
|
{{if eq $row.UsedBy 0}}
|
|
used by 0 schedules
|
|
{{else}}
|
|
used by {{$row.UsedBy}} schedule{{if ne $row.UsedBy 1}}s{{end}}
|
|
{{end}}
|
|
{{if gt $row.SnapshotCount 0}} · <span class="mono">{{$row.SnapshotCount}}</span> snapshot{{if ne $row.SnapshotCount 1}}s{{end}}{{end}}
|
|
</div>
|
|
</div>
|
|
<div class="flex justify-end row-action" style="gap: 6px;">
|
|
{{if and (gt (len $g.Includes) 0) (eq $host.Status "online")}}
|
|
<button class="btn btn-primary"
|
|
hx-post="/hosts/{{$host.ID}}/source-groups/{{$g.ID}}/run"
|
|
hx-swap="none"
|
|
hx-disabled-elt="this">Run now</button>
|
|
{{else}}
|
|
<button class="btn" disabled
|
|
title="{{if eq (len $g.Includes) 0}}add at least one include path before running{{else}}host is offline{{end}}">Run now</button>
|
|
{{end}}
|
|
{{if gt $row.UsedBy 0}}
|
|
<button class="btn btn-danger" disabled
|
|
title="remove this group from {{$row.UsedBy}} schedule{{if ne $row.UsedBy 1}}s{{end}} first">Delete</button>
|
|
{{else if eq (len $page.Groups) 1}}
|
|
<button class="btn btn-danger" disabled
|
|
title="this is the host's only source group — create another one first">Delete</button>
|
|
{{else}}
|
|
<form method="post" action="/hosts/{{$host.ID}}/sources/{{$g.ID}}/delete" style="display: inline;"
|
|
onsubmit="return confirm('Delete source group "{{$g.Name}}"? Existing snapshots are not affected.');">
|
|
<button type="submit" class="btn btn-danger">Delete</button>
|
|
</form>
|
|
{{end}}
|
|
</div>
|
|
</div>
|
|
{{end}}
|
|
</div>
|
|
|
|
<div class="text-[11.5px] text-ink-fade mt-4 leading-[1.65]">
|
|
Run-now on a row dispatches one immediate backup using that group's paths and tag.
|
|
Group <span class="mono text-ink-mid">name</span> is used as the snapshot tag — renaming a group
|
|
doesn't retag existing snapshots.
|
|
</div>
|
|
{{end}}
|
|
|
|
</div>
|
|
{{end}}
|