feat(cabana): widget action payload and data channel (quick-261006-eyj)
- pact.AdminActionInput.Payload (json.RawMessage) carries the widget's own JSON value untouched; pact.AdminActionResult.Data is passed through as data - cabana decodes payload with a 64 KiB cap (422 on body), refuses it on the toolbar and record routes, and embeds Data once encoded with a 256 KiB cap (opaque 500 when larger or unencodable); fill stays filtered - root .swaggo overrides json.RawMessage so swag keeps record_id and values; admin.json and schema.d.ts regenerated (payload?: unknown, data?: unknown) - TestWidgetPayloadAndData covers pass-through, cap, refusal and data 500 - cabana and pact READMEs, partials-and-widgets and admin-spa docs updated
This commit is contained in:
@@ -15,6 +15,8 @@ package cabana
|
||||
// http.go is the runtime route table, and TestPhase09PermissionMatrix plus
|
||||
// TestPhase09ContractInventory fail if the two lists diverge.
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
// ErrorBody is one D-10 error object.
|
||||
type ErrorBody struct {
|
||||
Code string `json:"code"`
|
||||
@@ -423,7 +425,7 @@ func AdminBulkAction() {}
|
||||
// AdminRecordAction documents the declared record action route.
|
||||
//
|
||||
// @Summary Run a declared record action
|
||||
// @Description Runs a record action the controller registers and the form's recordActions declares. The record is loaded and row-locked through the controller's form scope in one transaction (404 when missing or out of scope); an action that does not apply to the record's current state answers 409. The body must be {} and the answer's fill is always empty.
|
||||
// @Description Runs a record action the controller registers and the form's recordActions declares. The record is loaded and row-locked through the controller's form scope in one transaction (404 when missing or out of scope); an action that does not apply to the record's current state answers 409. The body must be {}: record_id, values and payload are all refused, and the answer's fill is always empty.
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
@@ -446,10 +448,14 @@ func AdminRecordAction() {}
|
||||
// AdminActionRequest is the body of a widget or toolbar action. record_id is
|
||||
// the record a widget on the update form belongs to (absent on create and
|
||||
// always absent for a toolbar action); values is the widget's snapshot of its
|
||||
// fill fields.
|
||||
// fill fields; payload is the widget's own JSON value.
|
||||
type AdminActionRequest struct {
|
||||
RecordID *uint64 `json:"record_id,omitempty"`
|
||||
Values map[string]any `json:"values,omitempty"`
|
||||
// Payload is the widget's own JSON value (the summer-action event's
|
||||
// detail.payload): any JSON, at most 64 KiB, handed to the action as-is.
|
||||
// Toolbar and record routes refuse it.
|
||||
Payload json.RawMessage `json:"payload,omitempty"`
|
||||
}
|
||||
|
||||
// AdminActionResult is an action's answer: a localized message for the toast
|
||||
@@ -458,12 +464,15 @@ type AdminActionRequest struct {
|
||||
type AdminActionResult struct {
|
||||
Message string `json:"message"`
|
||||
Fill map[string]any `json:"fill"`
|
||||
// Data is the action's structured answer for the widget: any JSON value,
|
||||
// not filtered by fill, absent when the action returned none.
|
||||
Data any `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
// AdminWidgetAction documents the widget action route.
|
||||
//
|
||||
// @Summary Run a widget action
|
||||
// @Description Runs the controller action a `type: widget` field declares. The record is loaded through the controller's form scope (404 when out of scope); only the field's fill keys with scalar values reach the action and the response.
|
||||
// @Description Runs the controller action a `type: widget` field declares. The record is loaded through the controller's form scope (404 when out of scope); only the field's fill keys with scalar values reach the action and the response. An optional payload (any JSON value, at most 64 KiB) is accepted and handed to the action as-is; the response may carry data, the action's own JSON answer, which is not subject to the fill filter.
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
@@ -472,7 +481,7 @@ type AdminActionResult struct {
|
||||
// @Param plugin path string true "Plugin"
|
||||
// @Param controller path string true "Controller"
|
||||
// @Param field path string true "Widget field name"
|
||||
// @Param body body AdminActionRequest true "Record id and fill snapshot"
|
||||
// @Param body body AdminActionRequest true "Record id, fill snapshot and optional payload"
|
||||
// @Success 200 {object} Envelope[AdminActionResult]
|
||||
// @Failure 401 {object} ErrorEnvelope
|
||||
// @Failure 403 {object} ErrorEnvelope
|
||||
@@ -484,7 +493,7 @@ func AdminWidgetAction() {}
|
||||
// AdminToolbarAction documents the toolbar action route.
|
||||
//
|
||||
// @Summary Run a toolbar action
|
||||
// @Description Runs a controller-registered action that the list's toolbar.buttons declares. The body must be {}: a toolbar action takes no record ids or values, and its fill is always empty.
|
||||
// @Description Runs a controller-registered action that the list's toolbar.buttons declares. The body must be {}: record_id, values and payload are all refused, and the answer's fill is always empty.
|
||||
// @Tags admin
|
||||
// @Accept json
|
||||
// @Produce json
|
||||
|
||||
Reference in New Issue
Block a user