Add in-app edit UI for dashboard config
A web editor at /edit for managing pages and widgets without hand-editing YAML:
- Page list and per-page widget views with breadcrumb navigation
- Add/delete pages, add/delete/reorder widgets within a column
- Per-widget textarea editor with curated starter templates, widget-specific
help (example, full field reference, link to upstream docs), and inline
error rendering that preserves the user's edits on validation failure
- Pre-save validation via newConfigFromYAML; atomic temp+rename writes with
.bak backup; YAML edits go through yaml.Node so comments and unresolved
${env:X}/${secret:X} tokens survive round-trips
- Auth gate: editing requires auth.users to be configured, or
admin.allow-without-auth: true as an explicit opt-in for trusted networks
- Pencil button on the dashboard near the theme picker for quick access
- Admin views read fresh from disk so the list updates immediately after
saves rather than lagging the fsnotify watcher
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.7
parent
6c5b7a3f4c
commit
2e198a19b4
@@ -28,9 +28,10 @@ const STATIC_ASSETS_CACHE_DURATION = 24 * time.Hour
|
||||
var reservedPageSlugs = []string{"login", "logout"}
|
||||
|
||||
type application struct {
|
||||
Version string
|
||||
CreatedAt time.Time
|
||||
Config config
|
||||
Version string
|
||||
CreatedAt time.Time
|
||||
Config config
|
||||
ConfigPath string
|
||||
|
||||
parsedManifest []byte
|
||||
|
||||
@@ -44,11 +45,12 @@ type application struct {
|
||||
failedAuthAttempts map[string]*failedAuthAttempt
|
||||
}
|
||||
|
||||
func newApplication(c *config) (*application, error) {
|
||||
func newApplication(c *config, configPath string) (*application, error) {
|
||||
app := &application{
|
||||
Version: buildVersion,
|
||||
CreatedAt: time.Now(),
|
||||
Config: *c,
|
||||
ConfigPath: configPath,
|
||||
slugToPage: make(map[string]*page),
|
||||
widgetByID: make(map[uint64]widget),
|
||||
}
|
||||
@@ -450,6 +452,18 @@ func (a *application) server() (func() error, func() error) {
|
||||
w.WriteHeader(http.StatusOK)
|
||||
})
|
||||
|
||||
mux.HandleFunc("GET /edit", a.handleAdminIndex)
|
||||
mux.HandleFunc("GET /edit/pages/{page}", a.handleAdminPage)
|
||||
mux.HandleFunc("GET /edit/pages/{page}/widgets/{col}/{idx}", a.handleAdminWidget)
|
||||
|
||||
mux.HandleFunc("POST /edit/api/pages", a.handleAdminAddPage)
|
||||
mux.HandleFunc("POST /edit/api/pages/{page}/delete", a.handleAdminDeletePage)
|
||||
mux.HandleFunc("GET /edit/pages/{page}/widgets/{col}/new", a.handleAdminNewWidget)
|
||||
mux.HandleFunc("POST /edit/api/pages/{page}/widgets/{col}/new", a.handleAdminCreateWidget)
|
||||
mux.HandleFunc("POST /edit/api/pages/{page}/widgets/{col}/{idx}", a.handleAdminEditWidget)
|
||||
mux.HandleFunc("POST /edit/api/pages/{page}/widgets/{col}/{idx}/delete", a.handleAdminDeleteWidget)
|
||||
mux.HandleFunc("POST /edit/api/pages/{page}/widgets/{col}/{idx}/move", a.handleAdminMoveWidget)
|
||||
|
||||
if a.RequiresAuth {
|
||||
mux.HandleFunc("GET /login", a.handleLoginPageRequest)
|
||||
mux.HandleFunc("GET /logout", a.handleLogoutRequest)
|
||||
|
||||
Reference in New Issue
Block a user