feat(12.1-02): password and form-only fields, rules per operation and preset

- pact.FormVirtualFields lists form fields that are not model columns: never
  bound, filled or projected; their values reach the Form hooks through
  cabana.VirtualFieldsFromContext when the field's context allows the operation
- type: password is a masked field that must be listed as virtual
- pact.FormRules supplies the rule set per operation and replaces the model's
  Rules() for admin saves; a rule on a virtual field sees the submitted value
- preset on a text field follows another text field on the create form
- SPA: PasswordField, preset handling in FormView, empty password left out of
  an update
- README, docs, OpenAPI document, TS types and dist updated
This commit is contained in:
Jakub Zych
2026-10-05 10:35:08 +02:00
parent a65c670574
commit a1c6bb1ce6
42 changed files with 1284 additions and 49 deletions

View File

@@ -1216,7 +1216,7 @@ export interface paths {
};
/**
* Admin form schema
* @description The form of a controller, localized. `preview` is present when config_form.yaml declares a preview block: the form then has a read-only preview screen, which shows the fields whose context allows preview, the record actions and, when preview.headerPartial is set, that partial as a status hint.
* @description The form of a controller, localized. `preview` is present when config_form.yaml declares a preview block: the form then has a read-only preview screen, which shows the fields whose context allows preview, the record actions and, when preview.headerPartial is set, that partial as a status hint. A `type: password` field and every other field the controller lists as virtual is sent in a save body and never has a value in a record response. `preset` on a text field names the field it follows on the create form (type slug or exact) until the administrator edits it.
*/
get: {
parameters: {
@@ -4358,6 +4358,10 @@ export interface components {
"cabana.ErrorEnvelope": {
error: components["schemas"]["cabana.ErrorBody"];
};
"cabana.FieldPreset": {
field: string;
type: string;
};
"cabana.FileItem": {
content_type: string;
created_at: string;
@@ -4443,6 +4447,11 @@ export interface components {
* template {ConfigDir}/_{path}.htm (D-09).
*/
path?: string;
/**
* @description Preset makes a text field follow another field of the form while the
* administrator has not edited it, on create only (fields.yaml preset).
*/
preset?: components["schemas"]["cabana.FieldPreset"];
/** @description Prompt is the upload button text, localized per request. */
prompt?: string;
/**