P2R-02 slice 1: host-detail sub-tab skeleton
Extract header/vitals/sub-tabs into a host_chrome partial that every host-detail tab page renders. Sources / Schedules / Repo go from inert divs to real <a> links backed by stub pages that share the chrome and a 'coming next' body — slices 2/3/4 fill them in. Also re-establishes the version indicator (host_schedule_version vs agent's applied_schedule_version) in the header. Drops the legacy fat-schedule list/edit templates that referenced fields removed by the P2 redesign (Manual / Paths / RetentionPolicy on Schedule); the new templates land in slice 3.
This commit is contained in:
@@ -397,9 +397,44 @@ type awaitingFragment struct {
|
||||
LastSeenAt *time.Time
|
||||
}
|
||||
|
||||
// hostChromeData is the field set the host_chrome partial reads from
|
||||
// every host-detail-tab page's Page struct. Embed it as the first
|
||||
// (anonymous) field of the page struct so .Page.Host / .Page.SubTab
|
||||
// resolve via field promotion in the template.
|
||||
type hostChromeData struct {
|
||||
Host store.Host
|
||||
SubTab string // snapshots | sources | schedules | repo
|
||||
Crumb string // breadcrumb tail ("snapshots" / "sources" / etc)
|
||||
SourceGroupCount int
|
||||
ScheduleCount int
|
||||
ScheduleVersion int64 // host_schedule_version (latest desired)
|
||||
}
|
||||
|
||||
// loadHostChrome fetches the per-tab counts that every host-detail tab
|
||||
// renders in the chrome (sub-tab badges + version indicator). On any
|
||||
// non-fatal store error it logs and degrades to zeros — better to
|
||||
// render the page with stale counts than 500 the whole tab.
|
||||
func (s *Server) loadHostChrome(r *stdhttp.Request, host store.Host, subtab, crumb string) hostChromeData {
|
||||
d := hostChromeData{Host: host, SubTab: subtab, Crumb: crumb}
|
||||
if groups, err := s.deps.Store.ListSourceGroupsByHost(r.Context(), host.ID); err == nil {
|
||||
d.SourceGroupCount = len(groups)
|
||||
} else {
|
||||
slog.Warn("ui chrome: list source groups", "host_id", host.ID, "err", err)
|
||||
}
|
||||
if scheds, err := s.deps.Store.ListSchedulesByHost(r.Context(), host.ID); err == nil {
|
||||
d.ScheduleCount = len(scheds)
|
||||
} else {
|
||||
slog.Warn("ui chrome: list schedules", "host_id", host.ID, "err", err)
|
||||
}
|
||||
if v, err := s.deps.Store.GetHostScheduleVersion(r.Context(), host.ID); err == nil {
|
||||
d.ScheduleVersion = v
|
||||
}
|
||||
return d
|
||||
}
|
||||
|
||||
// hostDetailPage carries everything the host detail template needs.
|
||||
type hostDetailPage struct {
|
||||
Host store.Host
|
||||
hostChromeData
|
||||
Snapshots []store.Snapshot
|
||||
// SnapshotsShown is the number rendered (we cap at ~50 for the
|
||||
// first slice; pagination lands when it matters).
|
||||
@@ -443,7 +478,7 @@ func (s *Server) handleUIHostDetail(w stdhttp.ResponseWriter, r *stdhttp.Request
|
||||
view := s.baseView(u, "dashboard")
|
||||
view.Title = host.Name + " · restic-manager"
|
||||
view.Page = hostDetailPage{
|
||||
Host: *host,
|
||||
hostChromeData: s.loadHostChrome(r, *host, "snapshots", "snapshots"),
|
||||
Snapshots: shown,
|
||||
SnapshotsShown: len(shown),
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user