Skip to main content

Crate tablo_core

Crate tablo_core 

Source
Expand description

Tablo: a server-rendered admin toolkit on Topcoat and Toasty.

A Panel serves one Resource per Toasty model. A resource names the model, whose ModelColumns give its default table and detail page, and the record form its create and edit submissions parse into, which ModelForm derives from the model or RecordForm from a struct of its own. It declares the rest as one ResourceDef value: its Policy, which denies by default, and any Table, Schema or Detail that replaces or extends the defaults. The app mounts the panel on its own Topcoat router with RouterBuilderPanelExt::panel, which builds each def once and checks it against the database schema first; one router mounts any number of panels at distinct prefixes.

#[derive(Debug, Clone, toasty::Model, tablo_core::ModelColumns, tablo_core::ModelForm)]
pub struct Book {
    #[key]
    #[auto]
    pub id: uuid::Uuid,
    pub title: String,
}

pub struct BookResource;

impl Resource for BookResource {
    type Model = Book;
    type Form = BookForm;

    fn declare() -> ResourceDef<Self> {
        ResourceDef::new().policy(Allow)
    }
}

let router = Router::builder()
    .discover()
    .app_context(db)
    .panel(Panel::new("admin").resource::<BookResource>())?
    .build();

The user guide walks through a complete panel and each part of it. ResourceDef lists everything a resource declares, Resource the hooks it overrides, and Panel every builder call.

Modules§

auth
Authenticates panel users and gates panel routes.
csrf
CSRF protection via double-submit cookie.
db
The Db glue: how Tablo code reaches the pooled Toasty database, and the transaction a panel write runs its record fns and hooks in.
extend
The traits that add a new kind of building block to a declaration: a Column a table lists and a detail page shows, a Filter a table offers, a Control a Field::custom field renders, an OptionSource a relationship choice loads its options from, a TypedValue a text field parses, a FilterDate a DateFilter matches by day, and a FilterKey a SelectFilter matches. Includes, FilterInput, FilterValue, ControlFuture and ControlInput are what their methods take and return.
notification
Messages for a panel user: the toast a write flashes, and the StoredNotifications Notifications sends to the bell of a panel with Panel::notifications.
rich_text
Rich text (ADR-0032): the Tools a toolbar offers, the HTML each produces, and the cleaning that keeps a value to the elements its tools produce. A rich text field cleans what it reads and RichTextColumn what it renders; a page of the app’s own renders a stored value through clean.
url
URLs into the request’s panel, so app code never spells a prefix.

Macros§

lens
Build a Lens from a model and a field, or a chain of embedded fields.
models
toasty::models! with the models Tablo ships appended, so a panel’s Db holds every table auth reads.
relation
Build a RelationLens from a model and one of its relation fields.
t
A message spelled in the request’s locale: t!(cx, "id", name = value, ..) is text!("id", name = value, ..).localize(cx), for what takes a String, such as a Notification’s title.
text
A Text message with its arguments: text!("id", name = value, ..) is Text::message("id").arg("name", value)...

Structs§

Abilities
A policy that answers each Ability from the check declared for it, and denies every ability it declares none for.
Allow
Allows every ability.
And
The policy and returns: allows what both sides allow.
Auth
The panel’s authentication configuration (ADR-0013).
AuthMail
Where a panel’s auth mail comes from and where its links point, installed with Auth::mail: the sender, and the absolute URL every link starts with.
BooleanColumn
A column of a bool field rendered as an icon.
Brand
Branding for the panel’s shell: the sidebar header, the login card, and the topbar below md, where the sidebar folds into a sheet.
ChoiceField
A choice field: Field::choice, or a record form’s choice control (F is the form).
ColorColumn
A column of a String field holding a CSS color, rendered as a swatch beside the value.
ComputedColumn
A display-only column rendering any text from the row, with no query predicate.
CountColumn
A column counting the records of a Deferred has_many field that a source S shows, which declares the field’s include so every page that renders it loads the records.
Currency
How a money column spells its amounts: the symbol, where it goes, the decimals, and whether the field stores minor units.
CustomField
A field an app’s Control renders: Field::custom and Field::toggle, or a record form’s toggle (F is the form).
DateColumn
A column of a date field, rendered as a calendar day.
DateFilter
Date filter matching a date or time field by calendar day, or by a range of days; see FilterDate for the types.
DeclarationError
One declaration mistake: who declares it, where, and what is wrong.
Deny
Allows nothing: the default policy.
Detail
The declaration of a detail page: Columns, the same ones a Table lists, arranged in Section, Group, Grid and Tabs blocks.
DirUploader
Writes each upload into one directory as {uuid}-{basename} and stores its URL under url_prefix; Panel::uploads_dir installs it and serves the directory there.
EmailVerification
A panel’s email verification, installed with Auth::email_verification: the EmailVerifier, and how many links one account may ask for. The links go out through the panel’s AuthMail.
EmbeddedColumn
A column of an EmbeddedForm value.
Field
One form field binding a lens to the control editing it, offering only that control’s modifiers so a modifier on the wrong control does not compile.
FieldAccess
Who may view one field of a model’s records, and who may change it, which ResourceDef::field_access declares: every resource the panel mounts over the model obeys the rule.
FieldError
One key a submission was refused under: a form key, or a record form’s field enum in Resource::validate_record.
FieldErrors
A refused submission.
FileColumn
A column of a String field holding an uploaded file’s path, rendered as a link to the file.
FileField
A file field: Field::file, or a record form’s file control (F is the form).
FilterValue
What a request carries for one filter: the values its f.<name> parameter repeats, in the order the request carries them, and the parts its f.<name>.<part> parameters name.
FormField
One record-form field and the form keys it binds.
FormValues
What a form holds, one FormValue per key: a submission its schema read, or a stored record as its record form spells it.
GlobalSearch
How a resource’s records show in its panel’s global search, as ResourceDef::global_search declares it: the details listed under each result’s title.
Grid
A block of cols columns, clamped to 1..12, laying out a form’s fields or a detail page’s columns.
Group
An unlabelled block grouping a form’s fields or a detail page’s columns.
HeaderActions
The HeaderActions a page or a resource declares, in button order.
ImageColumn
A column of a String field holding an uploaded image’s path, rendered as a thumbnail.
Lens
A model field’s typed path, which queries filter and sort on, paired with the function that reads the field off a loaded record.
LoginThrottle
How many sign-in attempts one login may make from one client address in a window, as Auth::throttle sets it.
Membership
One tenant a user may act for: its id, and the name the tenant switcher shows. A PanelUser lists its memberships in tenants.
MountError
Why RouterBuilderPanelExt::panel refused a panel: every declaration mistake it found.
NavigationItem
A sidebar entry: a resource’s, from its ResourceDef, or a Page’s.
NoForm
The record form of a resource with no create or edit page.
Notification
A message for a panel user: flashed as a toast after a write, or stored for the bell with Notifications::send.
NotificationAction
A link a Notification offers under its text, such as “Download” or “View order”.
Notifications
Sends StoredNotifications to one panel’s users, and wakes their open bells. Cloning it is cheap.
Or
The policy or returns: allows what either side allows.
Outcome
What an Action or a HeaderAction asks of the response once its write commits: which notification it flashes and where it lands.
PageDef
What a Page declares: its slug, sidebar entry, access and header actions.
PagePosition
Where a page numbered by ?page= sits in its result set.
Panel
An admin panel: resources and pages under one prefix, framed by one shell and gated by one Auth.
PanelHandle
A panel’s mounted resources and its database, which a background job or a test keeps to build a context per run without declaring the panel again. A router’s mounted panel gives it through panel_handle, a panel no router mounts through Panel::handle. Cloning it is cheap.
PasswordAuth
Shipped default authenticator: Argon2id verification against AdminUser.
PasswordReset
A panel’s password reset, installed with Auth::password_reset: the PasswordResetter, and how many links one address may ask for. The links go out through the panel’s AuthMail.
PasswordSignUp
Registers an AdminUser from a SignUp, refusing a password new_password_errors refuses and an email another account holds. Install it with Auth::registration.
Places
Where an Action’s button renders: Action::PLACES.
Posted
An edit submission: the parsed form, and the fields the submission named.
Profile
The profile form PasswordAuth edits an AdminUser through, and a custom ProfileEditor can take as its input: a name, an email address, an optional new password typed twice, and the current password.
PublicLink
A record’s public page, linked from its detail and edit pages.
QueryFilter
A filter offering named predicates, such as an embedded-enum variant or any query the app names. Several values match a record any of their predicates selects, which multiple lets the control choose.
ReadOnly
Allows listing and viewing, and no write: no create, update, delete or custom action.
Reads
The fields of M a Column or a Filter reads, by the root field each path starts at: what field_access hides it by.
Relation
One relation of a parent resource’s records.
RelationColumn
A column showing the record of a Deferred belongs_to or has_one field as text, or the records of a has_many one (list), which declares the field’s include so every page that renders it loads them.
RelationLens
A relation field’s include, which loads it, paired with the function that reads the loaded relation off a record.
RepeaterColumn
A column of a list of FormInput items.
RepeaterField
A repeater: Field::repeater, or a record form’s #[form(repeat)] control (F is the form).
ResourceDef
What a Resource declares: its names, navigation, policy, tenancy, table, form, detail page, relations and actions.
RichTextColumn
A column of a String field holding a rich text field’s HTML. A detail page shows the formatted HTML; a table cell shows its text, cut to excerpt characters; an export holds the text.
RichTextField
A rich text field: Field::rich_text, or a record form’s text control made one with TextField::rich_text (F is the form).
Schema
Composes fields and layout blocks and resolves every field once into one list.
Section
A titled block holding a form’s fields (schema) or a detail page’s columns (columns, which detail declares).
SelectFilter
Select filter matching a field exactly: a String, any FormScalar such as an Options enum, or a foreign key to a relationship’s rows. Several values match a record holding any of them, which multiple lets the control choose.
SignUp
The sign-up form PasswordSignUp registers from, and a custom Registrar can take as its input: a name, an email address, and a new password typed twice.
Sort
A column and a direction to sort a table by: parsed from ?sort=<column>&dir=asc|desc, or declared as the table’s default.
Source
Holds the values and errors a schema’s controls render with.
Switch
Renders a bool field as a switch, a checkbox with the switch role drawn as an on/off track, preceded by a hidden false: what CustomField::switch renders.
Tab
One tab of a Tabs block: a titled trigger and the fields or columns it shows.
Table
Table description of a Resource’s list view declaring columns and how they map to queries.
TablePage
One executed page of rows for WiredTable::render.
TableState
Request-scoped table state, parsed from the list’s URL query.
Tabs
A block showing one Tab at a time, each holding a form’s fields (Tab::schema) or a detail page’s columns (Tab::columns).
Tenancy
How a resource’s rows belong to a tenant.
Tenant
Request-scoped tenant identifier.
TenantId
One tenant’s id, and the field type of a resource’s tenant column.
TenantRegistration
A panel’s tenant registration page, installed with Auth::tenant_registration: the TenantRegistrar that creates tenants, and whether a user who acts for none must create one first.
TernaryFilter
Ternary filter matching a bool field.
Text
A word a panel renders: plain text, or a message the request’s Locale spells.
TextColumn
A column of one field, rendered as text and bound through a Lens for sorting and search.
TextField
A text field: Field::text, or a record form’s text control (F is the form).
Toggle
Renders a bool field as a checkbox preceded by a hidden false.
TwoFactor
A panel’s two-factor sign-in, installed with Auth::two_factor: each signed-in user may add an authenticator app, or codes by email when the panel mails them, at {prefix}/two-factor, and an account that has one signs in with a code from it after its password.
When
The policy when returns.
WiredTable
A declared Table with one request’s actions and policy wired on: what the list page renders.

Enums§

Ability
One thing a policy is asked to allow; record abilities are asked once per loaded row, and a record that cannot be viewed cannot be written by guessing its key.
ActionInputFault
Why an action’s input cannot be served: DeclarationErrorKind::ActionInput.
ActionLayout
Where a table puts a row’s actions: its custom actions, View, Edit and Delete.
Alignment
Where a column’s header and cells align their content.
AuthMailFault
Why a panel’s auth mail cannot be sent: DeclarationErrorKind::AuthMail.
Change
What one write of a resource changed: the mutation and the rows it wrote.
Color
A semantic color for a badge, a status dot or a cell’s text.
ColumnToggle
Whether each reader may hide a Column from their list, and whether it starts shown.
ColumnWidth
How a Column takes the table’s width.
Cursor
A pagination cursor: the page after, or the page before, an encoded row.
DeclarationErrorKind
What is wrong with a declaration.
FieldAccessFault
Why a field_access cannot hide its field everywhere the panel shows it: DeclarationErrorKind::FieldAccess.
FieldErrorKind
Why a key was refused.
FieldRuleFault
Why a field’s declared rules cannot work: DeclarationErrorKind::FieldRule.
FormValue
One key’s value in FormValues, in the shape its control posts.
LocaleFault
Why a panel’s locales or translations cannot be served.
ManyToManyFault
Why a many-to-many field or relation cannot link records: DeclarationErrorKind::ManyToMany.
NavTarget
Where a sidebar entry points.
NotificationStatus
The kind of notification (status).
Number
A number as a cell reads it: an integer stays exact, a float is rounded when spelled.
Pagination
How a table pages through its rows.
ProfileFault
Why a panel’s profile page cannot be served: DeclarationErrorKind::Profile.
ProfileUpdate
What a ProfileEditor::save changed, which decides what happens to the user’s sessions.
ResetFault
Why a panel’s password reset cannot be served: DeclarationErrorKind::PasswordReset.
SegmentFault
Why a path segment cannot be a literal URL segment.
SignUpFault
Why a panel’s sign-up page cannot be served: DeclarationErrorKind::SignUp.
Site
The part of a declaration a DeclarationError is in.
TenancyFault
Why a resource’s tenancy cannot scope its rows: DeclarationErrorKind::Tenancy.
TenantProfileFault
Why a panel’s tenant settings page cannot be served: DeclarationErrorKind::TenantProfile.
TenantRegistrationFault
Why a panel’s tenant registration page cannot be served: DeclarationErrorKind::TenantRegistration.
Tool
One button of a rich text field’s toolbar. A tool is also a grant: the field keeps only the elements and attributes its tools produce, so a tool left off the toolbar cannot be typed, is dropped from a paste, and is removed from a forged post.
Trashed
Which records a query over a soft-deleting resource admits: the live ones, the trashed ones, or both.
TwoFactorFault
Why the panel’s two-factor sign-in cannot be served: DeclarationErrorKind::TwoFactor.
VerificationFault
Why a panel’s email verification cannot be served: DeclarationErrorKind::EmailVerification.
WriteError
Why a record fn or an action’s run wrote nothing: a refusal the form renders, or a failure.

Constants§

DEFAULT_PAGE_SIZE
The page size of a table that declares none with Table::paginate.
DEFAULT_PER_PAGE_OPTIONS
The page sizes a table offers a reader by default, beside its own Table::paginate size.
MAX_IMPORT_ROWS
The most rows one CSV import creates: every row writes in the request’s one transaction, so a longer file is refused whole.
MAX_RELATIONSHIP_OPTIONS
Caps the options a relationship choice field loads instead of scanning a large table per select.
MAX_REPEATER_ROWS
The most rows one repeater takes: each renders in full when the form comes back refused, so an unbounded list would let a small submission render a page of any size.

Traits§

Action
A mutation beyond create, update and delete: “publish”, “archive”, “resend the invite”.
Authenticator
How a panel loads its users (ADR-0013).
DateValue
The field types a DateColumn spells as a calendar day: jiff::civil::Date, jiff::civil::DateTime, jiff::Timestamp (read in the request’s time_zone, as a DateFilter reads it) and an Option of any of them.
EmbeddedForm
Reads an embedded value from and writes it to FormValues, one key per leaf; derive it to generate the value’s schema.
ForeignKey
A foreign-key column type referencing a primary key of type K: K itself, or Option<K> for an optional reference. Sealed: these are the only two.
FormInput
A typed value a form posts under its own keys, which no column binds: what an Action asks for before it runs, what a sign-up reads, one item of a repeater.
FormScalar
A type one form key reads and writes: String, every TypedValue type, every enum deriving Options, and an Option of any of them.
HeaderAction
A mutation that acts on no record, run from a button in a page’s header: “import posts”, “clear the cache”, “recompute the totals”.
IntoColumns
Convert a single built-in column, a tuple of any Columns, a Vec or slice of boxed columns, or () for none yet, into a table’s column list.
IntoDetail
Converts a column, a layout block of columns, a tuple of either, or a Detail into a Detail.
IntoFilters
Convert a single built-in filter, or a tuple of any Filters, into a table’s filter list.
IntoFormValue
A value a field’s default takes: any FormScalar or a &str or &String in the form spelling, or an array or Vec of them for a multiple choice.
IntoOptions
A choice’s static options as (value, label) pairs, in display order. A value listed alone is its own label; a label is a Text, so a message translates it.
IntoSchema
Converts a field, a layout block, a tuple of either, or a schema into a Schema.
ModelColumns
The table and detail page a model reads as when its resource declares none: what a ResourceDef without a table lists and without a detail shows.
Numeric
A field a TextColumn can spell as a number or an amount of money: every integer and float type, and an Option of one, which reads as the table’s dash when None.
Options
A closed set of values, each with its label.
Page
A panel page that is not a resource, mounted at {prefix}/{slug} with a sidebar entry; the panel owns the route and entry while the page owns its markup.
PanelUser
A signed-in user, as the panel knows it (ADR-0013).
Policy
Decides which Abilitys the current user has over a resource’s records.
ProfileEditor
How a panel lets the signed-in user edit their own account on its profile page, installed with Auth::profile.
RecordForm
The typed value a resource’s form submission parses into.
Registrar
How a panel creates accounts from its sign-up page, installed with Auth::registration.
Resource
Maps one Toasty Model to its admin UI.
RouterBuilderPanelExt
Mounts a Panel on a router the app owns.
TenantColumn
A field type a tenancy names: TenantId, or Option<TenantId> for a nullable column.
ToOneRelation
A to-one relation field to T a RelationColumn reads: Deferred<T>, or Deferred<Option<T>> for a nullable relation.
Uploader
Stores one uploaded file and names the value a record stores; installed once per panel with Panel::uploads.
Watched
A field a condition can watch: a text, choice or custom field of the form F, passed to visible_when by reference.

Functions§

can
Whether R’s policy, as the context’s panel mounted it, allows ability; false when the panel does not mount R. Does not check sign-in or tenant scope.
can_list
Whether the current request may open R’s list: the request’s panel mounts R, and sign-in, tenant scope, and Ability::ViewAny allow it.
can_open
Whether the current request may open the page P: the request’s panel mounts P, and sign-in and PageDef::access allow it, the checks the page’s GET makes.
contains_expr
Escaped substring predicate for lens matching term.
header_action_buttons
The header buttons of the page P the request may run, for its page_actions:
navigation_item
R’s sidebar entry in the context’s panel, with its label, URL and icon; None when the panel does not register R.
parse_items
The items the repeater key holds in a submission read through its schema, none when it posts nothing: what a record form’s parse reads the repeater with, and what a hand-written one or an action input reads.
parse_list
Read the values a multiple choice posted, none when it posted nothing: what a record form’s parse reads a many-to-many field with.
parse_password
Read a password from a completed submission: required as parse_scalar reads a String, but kept as typed, with its outer spaces, since a login compares the password untrimmed.
parse_scalar
Read one scalar from a completed submission.
register_models
Register every model Tablo ships in models: AdminUser, AuthSession, ColumnPreference, AuthToken, AuthFactor and StoredNotification.
require_tenant
Requires a tenant, returning an error if missing (for tenant-owned resources).
sanitize_filename
Strips a client filename to a safe basename capped at 255 bytes, without control or bidirectional-override characters, rejecting ., .., and Windows reserved names to empty: what a file field’s Uploader receives, for a page that parses its own multipart body.
scoped_query
The tenant-scoped base query.
scoped_query_in
scoped_query admitting the records trashed names, as a restore or a trash list loads them, under the same tenant filter.
tenant_id
The tenant the request acts for, if any.
time_zone
The time zone the request reads and shows wall-clock times in: the signed-in user’s time_zone, else the request panel’s time_zone, else UTC.
when
Allows every ability while predicate holds for the request.
wired_table
Returns the panel’s list table for R, with the request’s row actions wired on, for a page that owns its table; render it over the page’s own query with WiredTable::render.
write_create
The derived create: the form’s builder, the request tenant stamped on the resource’s Tenancy::column, executed through ex, then a join row linking the record to each record its many-to-many fields hold.
write_items
The repeater’s value holding items: what a record form hydrates the repeater with, and what a hand-written one writes.
write_list
The values a multiple choice holds, as its one form key carries them: what a record form hydrates a many-to-many field with, and what a hand-written one writes.
write_update
The derived update: assign every named field and execute through ex, then link the record to the records each named many-to-many field holds, and unlink it from the others.

Derive Macros§

EmbeddedForm
Derives EmbeddedForm for an embedded struct or enum.
FormInput
Derives FormInput for a typed value a form posts under its own keys: what an Action asks for before it runs, what a sign-up reads, or one item of a repeater.
ModelColumns
Derive a model’s ModelColumns: the table a resource lists it in and the detail page it shows it on, when the resource declares neither.
ModelForm
Derive a model’s RecordForm struct from the model: the fields a person fills, named and typed as the model declares them.
Options
Derive Options for a unit-variant enum: the (value, label) list a choice field, a select filter and a column share, and the FormScalar that posts a variant as its value and reads it as its label.
RecordForm
Derive RecordForm for the typed value a resource’s form writes.