feat(32-01): cross-plugin admin form extensions (tracer)
- pact.AdminActionExtension.Form with AdminFormExtension: a fields document (fields.yaml format plus before:/after:/zone: and a tabs: list) given as an AdminFS path or YAML bytes, Load and Save hooks, AdminFormLoad/Save/SaveResult, AdminFormErrors and zone constants - cabana compileFormExtensions places extension fields at owner anchors at boot, regrouping an extended form by tab - save lifts extension values before any owner path and runs Save in the record's transaction after the owner row; show merges Load - TestFormExtensionTracer: c after a on a, b gives a, c, b through the admin API, stored in the contributor's table
This commit is contained in:
@@ -531,3 +531,20 @@ The admin merges the contributions at boot, after the target's own record action
|
||||
The start-up stops on an unknown controller ID, a target whose `config_form.yaml` has no `preview` block (record actions are offered on the preview screen), a name the target already registers (its owner's, or an earlier contribution's), a reserved name (`create`, `delete`), a name that is not an identifier, an action without `Run`, an empty label, or a prompt without a label. Prefix contributed names with your plugin (`acme_...`) so they cannot collide with names the owner adds later.
|
||||
|
||||
Contributions are compiled only when the admin is active, that is when some plugin registers admin controllers; a plugin that only adds actions does not switch the admin on.
|
||||
|
||||
## Adding fields to another controller's form
|
||||
|
||||
The same `pact.AdminActionExtension` carries form fields: set `Form` to a `pact.AdminFormExtension`. The extension describes its fields in a fields document, the `fields.yaml` format plus three placement keys, and stores their values itself through `Load` and `Save`. The owner's model, columns and tables are never touched.
|
||||
|
||||
```yaml
|
||||
# extensions/posts.yaml in the acme.extra plugin's AdminFS
|
||||
fields:
|
||||
subtitle:
|
||||
label: acme.extra::lang.subtitle
|
||||
type: text
|
||||
after: title # the owner's field; before: works the same way
|
||||
```
|
||||
|
||||
The plugin returns an extension with `Controller: "acme.blog.posts"` and `Form: &pact.AdminFormExtension{Fields: "extensions/posts.yaml", Load: ..., Save: ...}`, where `Load` takes a `pact.AdminFormLoad` and returns the values by field name, and `Save` takes a `pact.AdminFormSave` and returns a `pact.AdminFormSaveResult`.
|
||||
|
||||
The admin places `subtitle` between `title` and the field that followed it, and the form schema sends the fields in that order. On save, the extension's keys leave the request body before anything else reads it, so they never reach `Fill` or the owner's columns; after the owner row is written, `Save` runs inside the same transaction with `pact.AdminFormSave.Values`, and an error rolls the whole save back. On show, `Load` returns the values by field name.
|
||||
|
||||
Reference in New Issue
Block a user