feat(12.1-02): permissioneditor field in radio or checkbox mode

- type: permissioneditor with mode radio (1, -1) or checkbox (1); the
  controller serves the options per request through
  cabana.PermissionEditorProvider and reads and stores the values
- a save answers 422 for a non-object, an unknown code or a value outside the
  mode's set and 403 for a changed locked code; stored codes that are not
  offered are kept
- record responses carry the stored permissions as an object
- SPA: PermissionEditorField with sections by tab, locked rows and a read-only
  mode for the preview
- README, docs, OpenAPI document, TS types and dist updated
This commit is contained in:
Jakub Zych
2026-10-05 10:44:50 +02:00
parent a1c6bb1ce6
commit f50d9b8f10
38 changed files with 1300 additions and 34 deletions

View File

@@ -765,7 +765,7 @@
"type": "string"
},
"mode": {
"description": "Mode is the fileupload mode (image or file, default file) or the\ndatepicker mode (date, datetime or time, default datetime).",
"description": "Mode is the fileupload mode (image or file, default file), the\ndatepicker mode (date, datetime or time, default datetime) or the\npermissioneditor mode (radio or checkbox).",
"type": "string"
},
"multiple": {
@@ -787,6 +787,13 @@
"description": "Path names the controller partial of a `type: partial` field: the\ntemplate {ConfigDir}/_{path}.htm (D-09).",
"type": "string"
},
"permissionOptions": {
"description": "PermissionOptions are the permissions a `type: permissioneditor` field\noffers the requesting administrator, in display order. They are filled\nper request by the form schema route.",
"items": {
"$ref": "#/components/schemas/cabana.PermissionOption"
},
"type": "array"
},
"preset": {
"allOf": [
{
@@ -1454,6 +1461,30 @@
],
"type": "object"
},
"cabana.PermissionOption": {
"properties": {
"code": {
"type": "string"
},
"comment": {
"type": "string"
},
"label": {
"type": "string"
},
"locked": {
"type": "boolean"
},
"tab": {
"type": "string"
}
},
"required": [
"code",
"label"
],
"type": "object"
},
"cabana.RecordAction": {
"properties": {
"confirm": {
@@ -3314,7 +3345,7 @@
},
"/{vendor}/{plugin}/{controller}/schema/form": {
"get": {
"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.",
"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. A `type: permissioneditor` field carries `permissionOptions`, the permissions the controller offers the requesting administrator; its value in a record response and in a save body is an object of permission code to integer (radio mode 1 or -1, checkbox mode 1).",
"parameters": [
{
"description": "Vendor",