Round out the editor: head widgets, undo, group/split-column, site settings
- Head widgets are now first-class in dashboard edit mode: they get drag/edit/delete handles, their own SortableJS group (so they can't cross into columns), and the layout endpoint accepts a headWidgets[] sequence alongside columns[]. - New POST /edit/api/restore swaps glance.yml ↔ glance.yml.bak — effectively undo (and click again to redo). Surfaced as a "Restore previous version" button on /edit. - group and split-column are now editable inline via a new list-of-widgets schema type. Each item picks a widget type from a dropdown (excluding group/split-column to honor the backend's no-nesting rule) and renders that type's schema-driven sub-form. Switching the type re-renders the body. - New /edit/site-settings page with a form for branding (app name, logo, favicon, footer, app icon/background). POST applies via the same surgical yaml.Node update used for widgets. Theme/server intentionally still YAML for now. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
7f36f30dad
commit
e108feb74b
@@ -14,6 +14,7 @@ var (
|
||||
adminPageTemplate = mustParseTemplate("admin-page.html", "document.html", "footer.html")
|
||||
adminWidgetTemplate = mustParseTemplate("admin-widget.html", "document.html", "footer.html")
|
||||
adminPageSettingsTemplate = mustParseTemplate("admin-page-settings.html", "document.html", "footer.html")
|
||||
adminSiteSettingsTemplate = mustParseTemplate("admin-site-settings.html", "document.html", "footer.html")
|
||||
)
|
||||
|
||||
// allWidgetTypes mirrors the switch in newWidget(). Aliases ("stocks") omitted.
|
||||
@@ -249,6 +250,19 @@ type adminTemplateData struct {
|
||||
PageSettings *adminPageSettings
|
||||
IsFirstPage bool
|
||||
IsLastPage bool
|
||||
|
||||
SiteSettings *adminSiteSettings
|
||||
}
|
||||
|
||||
type adminSiteSettings struct {
|
||||
AppName string
|
||||
LogoText string
|
||||
LogoURL string
|
||||
FaviconURL string
|
||||
AppIconURL string
|
||||
AppBackgroundColor string
|
||||
HideFooter bool
|
||||
CustomFooter string
|
||||
}
|
||||
|
||||
func (a *application) handleAdminIndex(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -383,6 +397,26 @@ func (a *application) handleAdminWidget(w http.ResponseWriter, r *http.Request)
|
||||
})
|
||||
}
|
||||
|
||||
func (a *application) handleAdminSiteSettings(w http.ResponseWriter, r *http.Request) {
|
||||
if !a.adminAccessAllowed(w, r) {
|
||||
return
|
||||
}
|
||||
b := a.Config.Branding
|
||||
settings := &adminSiteSettings{
|
||||
AppName: b.AppName,
|
||||
LogoText: b.LogoText,
|
||||
LogoURL: b.LogoURL,
|
||||
FaviconURL: b.FaviconURL,
|
||||
AppIconURL: b.AppIconURL,
|
||||
AppBackgroundColor: b.AppBackgroundColor,
|
||||
HideFooter: b.HideFooter,
|
||||
CustomFooter: string(b.CustomFooter),
|
||||
}
|
||||
data := adminTemplateData{App: a, SiteSettings: settings}
|
||||
a.populateTemplateRequestData(&data.Request, r)
|
||||
renderAdminTemplate(w, adminSiteSettingsTemplate, data)
|
||||
}
|
||||
|
||||
func (a *application) handleAdminPageSettings(w http.ResponseWriter, r *http.Request) {
|
||||
if !a.adminAccessAllowed(w, r) {
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user