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:
@@ -255,6 +255,50 @@ type HasAdminActions interface {
|
||||
AdminActions() []AdminAction
|
||||
}
|
||||
|
||||
// AdminBulkAction is one controller action an administrator runs on the rows
|
||||
// selected in a list (config_list.yaml bulkActions). The admin framework owns
|
||||
// the HTTP route, the CSRF check, authentication, the resolution of the posted
|
||||
// ids and the transaction; Run only carries the business logic and reads the
|
||||
// write transaction with cabana.TxFromContext. Name is an identifier unique
|
||||
// among the controller's bulk actions; create and delete are reserved, and a
|
||||
// record action may reuse a bulk action's name. Label and Confirm are phrase
|
||||
// keys or literal text: Label is the menu item, Confirm the confirmation
|
||||
// question, and an empty Confirm means the framework's default confirm text.
|
||||
// Permissions are checked in addition to the controller's
|
||||
// RequiredPermissions.
|
||||
type AdminBulkAction struct {
|
||||
Name string
|
||||
Label string
|
||||
Confirm string
|
||||
Permissions []string
|
||||
Run func(ctx context.Context, in AdminBulkActionInput) (AdminBulkActionResult, error) `json:"-"`
|
||||
}
|
||||
|
||||
// AdminBulkActionInput is what the framework hands an AdminBulkAction.
|
||||
// Records are pointers to the controller's model, loaded and row-locked
|
||||
// through the controller's ListExtendQuery scope and ordered by primary key.
|
||||
// A bulk action never receives ids, so an id list can never become an
|
||||
// unscoped lookup.
|
||||
type AdminBulkActionInput struct {
|
||||
Records []any
|
||||
}
|
||||
|
||||
// AdminBulkActionResult is a bulk action's answer. Message is a phrase key or
|
||||
// text, localized by the framework and shown as a toast; when it is empty the
|
||||
// admin shows its default text with Affected. Affected is the number of
|
||||
// records the action changed, which may be lower than the selection when the
|
||||
// action skips rows.
|
||||
type AdminBulkActionResult struct {
|
||||
Message string
|
||||
Affected int
|
||||
}
|
||||
|
||||
// HasAdminBulkActions is implemented by an admin controller that registers
|
||||
// named bulk actions for its config_list.yaml bulkActions list.
|
||||
type HasAdminBulkActions interface {
|
||||
AdminBulkActions() []AdminBulkAction
|
||||
}
|
||||
|
||||
// AdminPartialData supplies the view model a controller partial template
|
||||
// renders (config_list.yaml headerPartial, fields.yaml `type: partial`). name
|
||||
// is the partial name; record is the scoped record for a form partial on an
|
||||
|
||||
Reference in New Issue
Block a user