Documentation
¶
Overview ¶
Package resource renders CRUD-backed list, detail, and form screens from Config.
Index ¶
- func PublicIsland() appui.Policy
- type Config
- func (c Config) Detail(ctx context.Context, id string) render.HTML
- func (c Config) Form(ctx context.Context, id string) render.HTML
- func (c Config) List(ctx context.Context) render.HTML
- func (c Config) Table(ctx context.Context) render.HTML
- func (c Config) TableHandler() http.HandlerFunc
- func (c Config) WithActions(a ...render.HTML) Config
- func (c Config) WithColumns(keys ...string) Config
- func (c Config) WithCreate() Config
- func (c Config) WithEdit() Config
- func (c Config) WithEmpty(s string) Config
- func (c Config) WithFilters(fs ...Filter) Config
- func (c Config) WithHeading(s string) Config
- func (c Config) WithIsland(endpoint string) Config
- func (c Config) WithIslandPolicy(p appui.Policy) Config
- func (c Config) WithLimit(n int) Config
- func (c Config) WithSearch(field string) Config
- func (c Config) WithTransitions(ts ...Transition) Config
- type DataSource
- type Field
- type Filter
- type Registry
- func (r Registry) GroupBars(ctx context.Context, entity, groupBy string) []ui.BarChartBar
- func (r Registry) GroupSlices(ctx context.Context, entity, groupBy string) []ui.PieSlice
- func (r Registry) LineChart(ctx context.Context, entity, groupBy string) render.HTML
- func (r Registry) StatValue(ctx context.Context, entity, agg, field, filterStr, format string) string
- type RelatedList
- type Relation
- type Transition
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func PublicIsland ¶ added in v0.55.0
PublicIsland is the policy for a list on a screen anyone may view. It has to be stated rather than left nil: with no policy at all TableHandler requires sign-in, so an anonymous visitor's first sort click on a public list would come back 401.
Types ¶
type Config ¶
type Config struct {
Entity string
Title string
Singular string
BasePath string // app route, e.g. "/app/customers"
APIPath string // auto-CRUD JSON endpoint, e.g. "/api/customers"
Crud DataSource
Fields []Field
Search string
Filters []Filter // facet filters rendered as a toolbar above the table
PageSize int
Relations map[string]Relation
CanCreate bool // List shows "New"; a /new create form is mounted
CanEdit bool // Detail shows Edit + Delete; a /{id}/edit form is mounted
Heading string // overrides the list's title (the block's text:)
EmptyText string // overrides the empty-state description (the block's empty_text:)
Related []RelatedList // reverse relations surfaced on the detail page
Transitions []Transition // status-transition workflow buttons on the detail page
// ExtraActions are appended to the list page header's action cluster
// (e.g. a data-fui-open trigger for a quick-add modal).
ExtraActions []render.HTML
// IslandPath, when set, renders the list's DataTable in island mode:
// sort headers and pagination fire GET RPCs at this endpoint and the
// runtime swaps just the table — no document navigation. Mount
// TableHandler at the same path.
IslandPath string
// IslandPolicy gates the island endpoint. It MUST be the same policy
// that gates the screen showing this list: the island serves the same
// rows over a route the screen's policy never sees, so leaving it nil
// on a role-gated screen publishes that screen's data to every signed-in
// user. TableHandler enforces it before rendering.
IslandPolicy appui.Policy
}
Config drives the server-rendered list + detail + form screens for one entity.
func (Config) Form ¶
Form renders the create (id == "") or edit (id != "") form for one record. It submits as an island: data-fui-rpc posts/puts JSON to the entity's auto-CRUD endpoint, then SPA-navigates back to the list/detail on success.
func (Config) Table ¶
Table renders the list's DataTable for ctx's query state. It is shared by List (initial SSR) and TableHandler (island RPC responses), so a sort/page swap returns exactly the HTML the initial render painted.
func (Config) TableHandler ¶
func (c Config) TableHandler() http.HandlerFunc
TableHandler serves the island endpoint: it renders the same table HTML List paints, for the RPC's query string. The runtime writes the response into the island's data-fui-signal wrapper — no document navigation.
It is a SECOND route onto the rows the screen shows, so it repeats every gate the screen and the JSON API apply: sign-in, the screen's own policy (IslandPolicy), and the entity's declared read permission. A gate that lives only on the screen route is not a gate.
func (Config) WithActions ¶
WithActions appends extra page-header actions to the list screen.
func (Config) WithColumns ¶
WithColumns returns a copy showing only the named fields, in the given order.
func (Config) WithCreate ¶
func (Config) WithEdit ¶
WithEdit shows Edit + Delete on the detail screen (a /{id}/edit form is mounted).
func (Config) WithFilters ¶
WithFilters sets the facet filters shown in the toolbar above the list.
func (Config) WithHeading ¶
WithHeading overrides the list's title; WithEmpty overrides the empty-state text.
func (Config) WithIsland ¶
WithIsland turns the list's table into an island: sort + pagination RPC against endpoint instead of navigating. Register TableHandler there.
func (Config) WithIslandPolicy ¶ added in v0.55.0
WithIslandPolicy gates the island endpoint with the screen's own policy.
func (Config) WithSearch ¶
WithSearch sets the LIKE-search field. WithLimit sets the page size. WithCreate shows a "New" action linking to BasePath/new.
func (Config) WithTransitions ¶
func (c Config) WithTransitions(ts ...Transition) Config
WithTransitions sets the detail-page status-transition workflow buttons.
type DataSource ¶
type DataSource interface {
CountAll(context.Context, crud.ListOptions) (int, error)
ListAll(context.Context, crud.ListOptions) ([]map[string]any, error)
GetOne(context.Context, string, []string) (map[string]any, error)
}
DataSource is the CRUD read seam Config needs. *crud.CrudHandler satisfies it.
type Field ¶
type Field struct {
Key string
Label string
Type string // string,text,int,float,decimal,bool,enum,date,timestamp,uuid,relation,...
Values []string // enum: the allowed values (drives <option>s on the form)
NoQuery bool // shown in the grid, but the API refuses to filter or sort on it
}
Field is one displayed entity field.
type Filter ¶
type Filter struct {
Key string
Label string
Type string // "enum" | "bool" | "relation"
Values []string // enum: the allowed values
}
Filter is one facet-filter dimension on the list screen: a column the user can narrow the list by. Type is "enum", "bool", or "relation" — it selects both the facet control (pills vs select) and how options are sourced (Values for enums, yes/no for bools, related rows for relations).
type Registry ¶
Registry holds the resource configs used by generated screens and dashboard blocks.
func (Registry) GroupSlices ¶
type RelatedList ¶
type RelatedList struct {
Title string // e.g. "Invoices"
ForeignKey string // the FK column on the related entity, e.g. "customer_id"
BasePath string // the related entity's app route, e.g. "/app/invoices"
Crud DataSource
Fields []Field
Relations map[string]Relation // for resolving the related rows' own FKs
}
RelatedList is a reverse relation surfaced on a detail page: the records of another entity that point back at this one via ForeignKey. Turns a detail page from a row editor into an account view (a customer + their invoices).
type Relation ¶
type Relation struct {
Crud DataSource
Display string
}
Relation resolves a foreign-key column to a related record's label.
type Transition ¶
type Transition struct {
Label string
Status string
Variant string // "primary" | "secondary" | "danger" | "ghost" (default secondary)
Stamp string // optional date field stamped with today on transition
}
Transition is a status-change workflow action shown on a detail page — a button that PUTs {status: Status} to the entity, then refreshes (Mark paid).