adminregistry

package
v0.8.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2026 License: MIT Imports: 6 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Display added in v0.4.0

type Display struct {
	Text string
	Href string
}

Display is what a changelist cell shows. Text is always HTML-escaped. Href, when set, makes the cell a link, but only if it is a relative URL or an absolute http or https URL; any other value falls back to plain text.

type DisplayFunc added in v0.4.0

type DisplayFunc func(context.Context, any) Display

DisplayFunc computes one changelist cell from a model row. The row is passed as a pointer to the model value (for example *Upload), so the function can read any of its fields, including ones that are not shown as columns. A panic in the function is the host's bug: admin does not recover it.

type FieldContext

type FieldContext struct {
	// Name is the model field's Go name — also the base name a simple
	// widget reads directly from the submitted form, and the stable prefix
	// a multi-input widget derives its own input names from.
	Name string
	// Label is the field's display label (from Options.Labels, or a
	// humanized default).
	Label string
	// HelpText is optional descriptive text for the field (from
	// Options.HelpText); empty if unset.
	HelpText string
	// Value is the field's current value, formatted for display. Empty for
	// a new (zero) instance.
	Value string
	// MaxLength is the field's declared maximum length in characters (a
	// tango:"varchar=n" string), or 0 when the field is unbounded. The
	// built-in input renders it as the maxlength attribute; the server stays
	// the authority, since browsers count in UTF-16 units.
	MaxLength int
	// Checked is the field's current boolean value, for checkbox-shaped
	// widgets.
	Checked bool
	// ReadOnly reports whether the field should render non-editably and
	// ignore submitted form data entirely (Options.ReadOnly). A Widget set
	// via Options.Widgets is never consulted for a ReadOnly field — the
	// admin package renders a single generic read-only presentation
	// instead, uniformly, regardless of which Widget the field would
	// otherwise use.
	ReadOnly bool
	// SelectOptions lists every row of the related model as a value/label
	// pair, populated only for a foreign key field whose related model is
	// registered — nil otherwise.
	SelectOptions []SelectOption
	// RelatedCreateURL links to the related model's admin create page for
	// foreign-key fields whose related model is also admin-registered.
	// Empty means no quick-create affordance should render.
	RelatedCreateURL string
	// PreviewURL is the absolute admin URL a preview widget posts its text
	// to; empty for a widget that is not a PreviewWidget.
	PreviewURL string
	// RelatedCreateLabel is the accessible label for RelatedCreateURL.
	// Empty means widgets may fall back to their own default.
	RelatedCreateLabel string
	// Error is the message the form shows beside this field after a failed
	// save, or empty when the field has no error. The built-in widgets mark
	// their control aria-invalid when it is set; a custom widget may do the
	// same.
	Error string
}

FieldContext carries what a Widget needs to render and parse one model field's create/edit form control. The same FieldContext is passed to both Render and Parse, so a widget can derive its own submitted form key(s) from Name identically on both sides — e.g. a multi-input widget might use Name+"_date" and Name+"_time" — rather than a render-time and parse-time convention drifting apart.

func (FieldContext) DescribedBy added in v0.4.0

func (f FieldContext) DescribedBy() string

DescribedBy returns the value for the control's aria-describedby: the ids of the field's help text and error element, in that order, separated by a space. It is empty when the field has neither.

type FieldValues

type FieldValues interface {
	Get(key string) string
	Has(key string) bool
}

FieldValues is the whole submitted form, so a Widget's Parse can read more than one input for a single Go field (see FieldContext.Name).

type ModelRegistration

type ModelRegistration struct {
	Model   model.ModelMeta
	Options Options
}

ModelRegistration is the admin metadata for a registered model.

type Options

type Options struct {
	ListDisplay []string
	// SingularName and PluralName name one row and several rows in messages
	// and confirmations, such as "Delete this book" and "3 books deleted".
	// Unset, each falls back to the humanized Go type name.
	SingularName string
	PluralName   string
	// Display computes changelist cells, keyed by a name in ListDisplay: a
	// registered field (overriding its value) or a synthetic column, which
	// needs a Labels entry for its header. See DisplayFunc.
	Display  map[string]DisplayFunc
	Search   []string
	Ordering []string
	// Label names one of this model's own fields to display whenever it is
	// shown as a related object elsewhere (e.g. on a Post's admin page for
	// a Post.AuthorID foreign key). Unset falls back to showing the raw
	// primary key value — never a hard error.
	Label string
	// Labels overrides a field's humanized default display label, keyed by
	// Go field name.
	Labels map[string]string
	// HelpText adds descriptive text below a field's form control, keyed by
	// Go field name.
	HelpText map[string]string
	// ReadOnly lists fields that render non-editably in create/edit forms.
	// On edit, a read-only field keeps its existing stored value regardless
	// of submitted form data; on create, it stays at its Go zero value.
	// Submitted data for a read-only field is always ignored, never parsed.
	ReadOnly []string
	// FieldOrder lists fields in the order they should render; fields not
	// listed keep their existing default order after the ordered ones.
	FieldOrder []string
	// Widgets overrides how a field renders and parses in create/edit
	// forms, keyed by Go field name. See Widget — best-effort, not a
	// stable contract.
	Widgets map[string]Widget
	// Filters lists boolean and foreign key fields the changelist can be
	// filtered by, in the order they appear above the list.
	Filters []string
	// BulkDelete lets a staff account delete the rows checked on one
	// changelist page, after a confirmation, in one all-or-nothing
	// transaction. Rows that reference a deleted row are deleted with it,
	// exactly as in a single-row delete. Off by default; it needs JavaScript
	// in the browser and never spans more than one page of rows.
	BulkDelete bool
}

Options controls how a model appears in the admin.

type PreviewWidget added in v0.4.0

type PreviewWidget interface {
	Preview(ctx context.Context, source string) (template.HTML, error)
}

PreviewWidget is the optional extension a Widget implements when its field can show a preview of the submitted text. Only the Markdown widget uses it today. Admin owns the preview route: it calls Preview for the one derived, staff-only endpoint of a preview field and wraps the result, so a widget cannot register a route. Preview receives a context derived from the request's and must not persist anything; the caller applies the deadline and output limits.

type Registry

type Registry struct {
	// contains filtered or unexported fields
}

Registry stores admin registrations by model name.

func NewRegistry

func NewRegistry(models *model.Registry) *Registry

NewRegistry returns an empty, ready-to-use admin Registry.

func (*Registry) Get

func (r *Registry) Get(name string) (ModelRegistration, bool)

Get returns an admin registration by model name.

func (*Registry) Register

func (r *Registry) Register(value any, opts Options) error

Register stores admin presentation options for a model.

func (*Registry) Registrations

func (r *Registry) Registrations() []ModelRegistration

Registrations returns every registered model in unspecified order.

type SelectOption

type SelectOption struct {
	Value    string
	Text     string
	Selected bool
}

SelectOption is one <option> in a foreign key field's <select>.

type Widget

type Widget interface {
	Render(ctx context.Context, f FieldContext) template.HTML
	Parse(ctx context.Context, f FieldContext, form FieldValues, dest reflect.Value) error
}

Widget renders one model field's create/edit form control and parses its submitted value back into the Go field, replacing tanGO's default behavior for that field alone — nothing else about the form changes. ctx is the request's context: a widget translates its own messages with i18n.T(ctx, key, fallback), so a host catalog can word them. tanGO's built-in field behaviors (a generic text/number/date-time input, a checkbox, a textarea, and the foreign-key select) are themselves Widgets, set via Options.Widgets like any custom one.

This interface, the built-in widgets other than JSON and Markdown, and Options' Widgets/Labels/HelpText/ReadOnly/FieldOrder fields are best-effort, not a stable contract; see docs/compatibility.md. A widget's Render output may include its own <link>/<script> tags for CSS/JS (served via its owning app's own embed.FS route, per the convention reusable apps already use for static assets); since there is no shared deduplication, that output must be idempotent — safe to emit once per rendered instance — because the same widget on multiple fields will render its tags more than once.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL