feat(12.1-01): declared record actions with an applicability rule
- pact.HasAdminRecordActions with AdminRecordAction (Applies, Run)
- config_form.yaml recordActions, compiled fail-loud
- show response meta.actions lists the permitted actions that apply
- POST .../{controller}/{id}/actions/{action}: record loaded and locked
through the form scope; 404 out of scope, 409 when it does not apply
- RecordActions.vue with confirm and request flow (mounted by plan 02)
- roster fixture, smoke tests, OpenAPI, TS types, READMEs, docs
This commit is contained in:
@@ -299,6 +299,50 @@ type HasAdminBulkActions interface {
|
||||
AdminBulkActions() []AdminBulkAction
|
||||
}
|
||||
|
||||
// AdminRecordAction is one controller action an administrator runs on a
|
||||
// single record (config_form.yaml recordActions). The admin framework owns the
|
||||
// HTTP route, the CSRF check, authentication, the record lookup 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 record actions; create and delete are reserved, and a bulk
|
||||
// action may use the same name. Label and Confirm are phrase keys or literal
|
||||
// text; an empty Confirm means the framework's default confirm text.
|
||||
// Permissions are checked in addition to the controller's
|
||||
// RequiredPermissions. Applies reports whether the action applies to the
|
||||
// record in its current state: a nil Applies means the action always applies.
|
||||
// Applies must be a pure read, because it also runs when a record is shown, to
|
||||
// decide which actions the admin is offered.
|
||||
type AdminRecordAction struct {
|
||||
Name string
|
||||
Label string
|
||||
Confirm string
|
||||
Permissions []string
|
||||
Applies func(ctx context.Context, record any) (bool, error) `json:"-"`
|
||||
Run func(ctx context.Context, in AdminRecordActionInput) (AdminRecordActionResult, error) `json:"-"`
|
||||
}
|
||||
|
||||
// AdminRecordActionInput is what the framework hands an AdminRecordAction.
|
||||
// Record is the record the framework loaded through the controller's
|
||||
// FormExtendQuery scope with a row lock, inside the action's transaction;
|
||||
// RecordID is its primary key.
|
||||
type AdminRecordActionInput struct {
|
||||
RecordID uint64
|
||||
Record any
|
||||
}
|
||||
|
||||
// AdminRecordActionResult is a record 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.
|
||||
type AdminRecordActionResult struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
// HasAdminRecordActions is implemented by an admin controller that registers
|
||||
// named record actions for its config_form.yaml recordActions list.
|
||||
type HasAdminRecordActions interface {
|
||||
AdminRecordActions() []AdminRecordAction
|
||||
}
|
||||
|
||||
// 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