feat(32-02): record events and content descriptors (tracer)

- pact.RecordSaved/RecordDeleted/RecordChange, fired as pointers after commit
- pact.ContentDescriptor and request/result types; MenuItemType.Content
- AdminFormSave.Changes carries the owner's changes to extension Save
- cabana.EmitRecordSaved/EmitRecordDeleted; admin save snapshots columns and
  translated values and fires RecordSaved through lagoon.AfterCommit
- signpost validates Content and gains ContentTypes, ContentTypeForModel, Describe
This commit is contained in:
2026-10-26 22:22:25 +01:00
parent 1b0421de81
commit 753fb5969a
12 changed files with 612 additions and 7 deletions

View File

@@ -546,7 +546,10 @@ type AdminFormLoad struct {
// the JSON body (numbers as json.Number), a translatable field's a
// map[string]string of locale to text, a plugin field type's the value its
// Decode returned. Save runs on every create and update of a record whose
// administrator sees the extension, with or without values.
// administrator sees the extension, with or without values. Changes lists
// what the owner's save changed on the record, as RecordSaved.Changes will
// (a translated slug once per changed locale), so Save sees a slug change
// inside the save transaction.
type AdminFormSave struct {
DB *gorm.DB
Controller string
@@ -554,6 +557,7 @@ type AdminFormSave struct {
ID string
Created bool
Values map[string]any
Changes []RecordChange
}
// AdminFormSaveResult is Save's answer. Notices are non-blocking messages per
@@ -944,7 +948,9 @@ type DependentOptionsProvider interface {
// item generates its children from records. References, when set, returns the
// records an item of the type can point at as a tree; nil means the type takes
// no reference. Resolve is required and turns one item into its URL, title,
// alternates and children.
// alternates and children. Content, when set, describes the records behind a
// record type (ContentDescriptor) for consumers such as sitemaps; nil means
// the type takes no part in them.
type MenuItemType struct {
Key string
Label string
@@ -955,6 +961,7 @@ type MenuItemType struct {
DynamicItems bool
References func(ctx context.Context) ([]MenuItemReference, error) `json:"-"`
Resolve func(ctx context.Context, in MenuItemResolve) (*ResolvedMenuItem, error) `json:"-"`
Content *ContentDescriptor `json:"-"`
}
// MenuItemReference is one record a menu item can point at: the stored