Files
steve 28c8b58f93 ui: per-host Jobs sub-tab; drop unused Settings stub
Adds /hosts/{id}/jobs page listing recent jobs for the host (newest
first, capped at 100) with click-through to /jobs/{id}. Converts the
Jobs placeholder <div> to a real <a> nav link; removes the Settings
stub entirely. Also registers durationHuman template func and a
.jobs-row CSS grid to match the existing .schd-row idiom.
2026-05-07 22:49:10 +01:00

48 lines
1.2 KiB
Go

package http
import (
"log/slog"
stdhttp "net/http"
"gitea.dcglab.co.uk/steve/restic-manager/internal/store"
)
// hostJobsPage is the page-data struct for /hosts/{id}/jobs.
type hostJobsPage struct {
hostChromeData
Jobs []store.Job
}
// handleUIHostJobs renders the per-host jobs list. Read-only — no
// actions, just a click-through to the existing /jobs/{id} detail
// page for any row.
func (s *Server) handleUIHostJobs(w stdhttp.ResponseWriter, r *stdhttp.Request) {
u := s.requireUIUser(w, r)
if u == nil {
return
}
host, ok := s.loadHostForUI(w, r)
if !ok {
return
}
jobs, err := s.deps.Store.ListJobsByHost(r.Context(), host.ID, 100)
if err != nil {
slog.Error("ui host jobs: list", "host_id", host.ID, "err", err)
stdhttp.Error(w, "internal", stdhttp.StatusInternalServerError)
return
}
page := hostJobsPage{
hostChromeData: s.loadHostChrome(r, *host, "jobs", "jobs"),
Jobs: jobs,
}
view := s.baseView(r, u)
view.Title = host.Name + " jobs · restic-manager"
view.Page = page
if err := s.deps.UI.Render(w, "host_jobs", view); err != nil {
slog.Error("ui: render host_jobs", "err", err)
stdhttp.Error(w, "internal", stdhttp.StatusInternalServerError)
}
}