feat(12.1-01): declared bulk actions on admin lists
- pact.HasAdminBulkActions with AdminBulkAction, its input and result
- config_list.yaml bulkActions, compiled fail-loud, needs showCheckboxes
- POST .../{controller}/bulk/{action}: ids resolved and locked through the
list scope in one transaction; partial selection is 409
- list schema offers declared actions per principal, with confirm text
- admin SPA bulk actions menu with confirm, busy state and failure toasts
- acme.roster fixture, tracer test, OpenAPI, TS types, dist, READMEs, docs
This commit is contained in:
@@ -176,6 +176,9 @@
|
||||
},
|
||||
"cabana.BulkAction": {
|
||||
"properties": {
|
||||
"confirm": {
|
||||
"type": "string"
|
||||
},
|
||||
"label": {
|
||||
"type": "string"
|
||||
},
|
||||
@@ -188,6 +191,21 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"cabana.BulkActionResult": {
|
||||
"properties": {
|
||||
"affected": {
|
||||
"type": "integer"
|
||||
},
|
||||
"message": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"affected",
|
||||
"message"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"cabana.BulkResult": {
|
||||
"properties": {
|
||||
"deleted": {
|
||||
@@ -367,6 +385,21 @@
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"cabana.Envelope-cabana_BulkActionResult": {
|
||||
"properties": {
|
||||
"data": {
|
||||
"$ref": "#/components/schemas/cabana.BulkActionResult"
|
||||
},
|
||||
"meta": {
|
||||
"$ref": "#/components/schemas/cabana.SuccessMeta"
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
"data",
|
||||
"meta"
|
||||
],
|
||||
"type": "object"
|
||||
},
|
||||
"cabana.Envelope-cabana_BulkResult": {
|
||||
"properties": {
|
||||
"data": {
|
||||
@@ -2727,6 +2760,131 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/{vendor}/{plugin}/{controller}/bulk/{action}": {
|
||||
"post": {
|
||||
"description": "Runs a bulk action the controller registers and the list's bulkActions declares. The ids are resolved and row-locked through the controller's list scope in one transaction before the action runs: a selection that matches no scoped row answers affected 0 without running the action, and a partial selection is a 409 that changes nothing.",
|
||||
"parameters": [
|
||||
{
|
||||
"description": "Vendor",
|
||||
"in": "path",
|
||||
"name": "vendor",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Plugin",
|
||||
"in": "path",
|
||||
"name": "plugin",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Controller",
|
||||
"in": "path",
|
||||
"name": "controller",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
{
|
||||
"description": "Bulk action name",
|
||||
"in": "path",
|
||||
"name": "action",
|
||||
"required": true,
|
||||
"schema": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
],
|
||||
"requestBody": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.AdminIDsRequest"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Record ids",
|
||||
"required": true
|
||||
},
|
||||
"responses": {
|
||||
"200": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.Envelope-cabana_BulkActionResult"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "OK"
|
||||
},
|
||||
"401": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Unauthorized"
|
||||
},
|
||||
"403": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Forbidden"
|
||||
},
|
||||
"404": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Not Found"
|
||||
},
|
||||
"409": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Conflict"
|
||||
},
|
||||
"422": {
|
||||
"content": {
|
||||
"application/json": {
|
||||
"schema": {
|
||||
"$ref": "#/components/schemas/cabana.ErrorEnvelope"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Unprocessable Entity"
|
||||
}
|
||||
},
|
||||
"security": [
|
||||
{
|
||||
"BackendBearer": []
|
||||
}
|
||||
],
|
||||
"summary": "Run a declared bulk action",
|
||||
"tags": [
|
||||
"admin"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/{vendor}/{plugin}/{controller}/fields/{field}/options": {
|
||||
"get": {
|
||||
"description": "Choices for a writable `type: relation` field: value is the related id, label its nameFrom column. Read-only and non-relation fields answer 404.",
|
||||
|
||||
Reference in New Issue
Block a user