Add Overview page with kind-grouped node cards and RAM/disk metrics.

Batch-fetch action widgets so the dashboard can show free/total memory and disk usage without N+1 requests.
This commit is contained in:
2026-07-20 21:25:55 +02:00
parent be255341e5
commit 6eef839526
10 changed files with 888 additions and 1 deletions
@@ -24,3 +24,51 @@ func (app *App) actionWidgetsListHandler(writer http.ResponseWriter, request *ht
Widgets: settings.WidgetsForNode(store, node.ID),
})
}
// actionWidgetsListAllHandler returns widget snapshots for every node the caller can access.
func (app *App) actionWidgetsListAllHandler(writer http.ResponseWriter, request *http.Request) {
if err := app.authorizeNodesRead(request); err != nil {
writeJSON(writer, http.StatusForbidden, apiErrorResponse{Error: err.Error()})
return
}
user, ok := UserFromContext(request.Context())
if !ok {
writeJSON(writer, http.StatusUnauthorized, apiErrorResponse{Error: "authentication required"})
return
}
settingsPayload, err := loadSettingsOrDefault(app.ConfigDir)
if err != nil {
writeJSON(writer, http.StatusInternalServerError, apiErrorResponse{Error: err.Error()})
return
}
nodesStore, err := settings.LoadNodesOrEmpty(app.ConfigDir)
if err != nil {
writeJSON(writer, http.StatusInternalServerError, apiErrorResponse{Error: err.Error()})
return
}
accessibleNodeIDs := make(map[string]struct{}, len(nodesStore.Nodes))
for _, node := range nodesStore.Nodes {
if userCanAccessNode(user, settingsPayload.Groups, node) {
accessibleNodeIDs[node.ID] = struct{}{}
}
}
widgetStore, err := settings.LoadActionWidgetsOrEmpty(app.ConfigDir)
if err != nil {
writeJSON(writer, http.StatusInternalServerError, apiErrorResponse{Error: err.Error()})
return
}
filtered := make([]settings.ActionWidgetSnapshot, 0)
for _, widget := range widgetStore.Widgets {
if _, ok := accessibleNodeIDs[widget.NodeID]; ok {
filtered = append(filtered, widget)
}
}
writeJSON(writer, http.StatusOK, actionWidgetsResponse{Widgets: filtered})
}