feat(cabana): settings entries that link to an admin controller

pact.SettingsItem gains an additive Controller field, the equivalent of a
WinterCMS registerSettings 'url' => Backend::url(...) entry. A link entry
declares no Model, Form or NewModel and needs no AdminFS; start-up fails
when it combines Controller with a singleton form or a model, or names an
unregistered controller. Settings codes stay one namespace.

GET /settings lists a link entry with its controller only when the
principal passes the item's permissions and may open the controller.
Registry.Setting never returns a link entry, so the singleton settings
endpoints answer 404 for its code. SettingsEntry carries controller,
empty for singletons; the OpenAPI document, generated SPA types and
settings fixture follow, and the pact and cabana READMEs and the
settings docs describe the link.
This commit is contained in:
Jakub Zych
2026-10-07 18:22:01 +02:00
parent b040ee3a74
commit 4a9b0896b1
15 changed files with 338 additions and 14 deletions

View File

@@ -398,7 +398,9 @@ type HasNavigation interface {
Navigation() []NavigationItem
}
// SettingsItem is one registerSettings() entry.
// SettingsItem is one registerSettings() entry. An item is either a singleton
// settings form (Model, Form and NewModel) or a link to an admin controller
// (Controller), never both.
type SettingsItem struct {
Code string
Label string
@@ -409,8 +411,13 @@ type SettingsItem struct {
Order int
Keywords []string
Permissions []string
Form string `json:"-"`
NewModel func() any `json:"-"`
// Controller, when set, makes the entry a link to that admin controller
// ID (vendor.plugin.controller): the equivalent of a WinterCMS
// registerSettings 'url' => Backend::url(...) entry. A link entry
// declares no Model, Form or NewModel and is not a singleton.
Controller string
Form string `json:"-"`
NewModel func() any `json:"-"`
}
// HasSettings is implemented by plugins that declare settings screens.