pub struct ResourceDef<R: Resource> { /* private fields */ }Expand description
What a Resource declares: its names, navigation, policy, tenancy, table, form, detail page,
relations and actions.
Resource::declare returns one, and Panel::resource_with
adjusts it for one panel. Every setting has a default, so a resource sets only what differs:
use tablo_core::{ReadOnly, RecordForm, Resource, ResourceDef, TernaryFilter, lens};
impl Resource for PostResource {
type Model = Post;
type Form = PostForm;
fn declare() -> ResourceDef<Self> {
ResourceDef::new()
.label("Blog post")
.policy(ReadOnly)
.table(PostForm::table().filters(TernaryFilter::new(lens!(Post.featured))))
}
}The panel builds the def once when it mounts, binding the paths it names to the database schema, and serves the result to every request.
Implementations§
Source§impl<R: Resource> ResourceDef<R>
impl<R: Resource> ResourceDef<R>
Sourcepub fn new() -> Self
pub fn new() -> Self
A def with every default: the policy denies all, rows belong to no tenant, and the record form derives the table, the form and the detail page.
Sourcepub fn slug(self, slug: impl Into<String>) -> Self
pub fn slug(self, slug: impl Into<String>) -> Self
The URL slug for the resource’s pages: "users" mounts the list at {panel prefix}/users.
Defaults to the resource type’s name without a trailing Resource, pluralized and
kebab-cased: UserResource → users, BlogPostResource → blog-posts.
Sourcepub fn label(self, label: impl Into<String>) -> Self
pub fn label(self, label: impl Into<String>) -> Self
One record’s name, the noun in the “Create {label}” and “Edit {label}” titles.
Defaults to the model’s type name in sentence case: BlogPost → Blog post, APIKey →
API key.
Sourcepub fn plural_label(self, label: impl Into<String>) -> Self
pub fn plural_label(self, label: impl Into<String>) -> Self
The list title and sidebar label.
Defaults to the pluralized label: Category → Categories, Person →
People.
Sourcepub fn icon(self, icon: IconData) -> Self
pub fn icon(self, icon: IconData) -> Self
The icon of the resource’s sidebar entry, replacing the icon of a
navigation item.
Where the sidebar entry sorts among the panel’s entries, lowest first; defaults to 0, and
entries of equal order keep their registration order. It replaces the order of a
navigation item.
Replaces the sidebar entry, for one that links somewhere other than the list page:
NavigationItem::at("Drafts", "/admin/posts?f.status=draft"). icon and
navigation_order still apply to it.
Sourcepub fn policy(self, policy: impl Policy<R::Model>) -> Self
pub fn policy(self, policy: impl Policy<R::Model>) -> Self
Gates every handler; defaults to Deny. Row scoping belongs in
Resource::query, not the policy.
Sourcepub fn tenancy(self, tenancy: Tenancy<R::Model>) -> Self
pub fn tenancy(self, tenancy: Tenancy<R::Model>) -> Self
How rows belong to a tenant; defaults to Tenancy::none.
Sourcepub fn table(self, table: Table<R::Model>) -> Self
pub fn table(self, table: Table<R::Model>) -> Self
The list table; defaults to the record form’s derived table (RecordForm::table).
Sourcepub fn form(self, form: Schema<R::Form>) -> Self
pub fn form(self, form: Schema<R::Form>) -> Self
Arranges the create and edit forms: the record form’s own controls, from its
controls(), in layout blocks.
A control the schema does not place follows the ones it does, in the record form’s declaration order and outside every layout block, so the default form renders one control per field, and a form that adjusts one control places only that one:
use tablo_core::{Resource, ResourceDef, Schema};
impl Resource for UserResource {
type Model = User;
type Form = UserForm;
fn declare() -> ResourceDef<Self> {
// `email`, then `name`.
ResourceDef::new().form(Schema::new(UserForm::controls().email.email()))
}
}Sourcepub fn view(self, view: Detail<R::Model>) -> Self
pub fn view(self, view: Detail<R::Model>) -> Self
The detail page: columns in layout blocks; defaults to the record form’s derived detail
page (RecordForm::detail), and Detail::empty turns the page off.
The page loads the relations its columns declare.
Sourcepub fn record_title<T>(self, lens: Lens<R::Model, T>) -> Self
pub fn record_title<T>(self, lens: Lens<R::Model, T>) -> Self
Titles each record with the text column lens reads, as in
.record_title(lens!(Post.title)): the detail page’s heading, each option of a
relationship choice over this resource, and each cell
of a RelationColumn::of it.
A record whose column is empty, and every record by default, is titled with the
label and its key, as in Blog Post 3f2a…. A relationship choice over this
resource also searches the column, besides the table’s searchable columns.
A title is display text, not a key: two records can share one, so it never replaces the primary key that keys the table’s rows and the action routes. A lens names one of the model’s own columns, never a relation, so the title reads on every record however it was loaded; a title built from several columns is a column the model stores.
Sourcepub fn public_link(
self,
link: impl Fn(&Cx, &R::Model) -> Option<PublicLink> + Send + Sync + 'static,
) -> Self
pub fn public_link( self, link: impl Fn(&Cx, &R::Model) -> Option<PublicLink> + Send + Sync + 'static, ) -> Self
Links a record’s public page from its detail and edit pages, for each record link
returns one for; defaults to no link.
The edit page loads the record without relations, so a link that reads one renders on the detail page only when its relation is loaded there.
Sourcepub fn relation(self, relation: Relation<R::Model>) -> Self
pub fn relation(self, relation: Relation<R::Model>) -> Self
Adds a related resource, rendered as its table narrowed to the record on the detail and edit pages.
Sourcepub fn action<A: Action<R>>(self) -> Self
pub fn action<A: Action<R>>(self) -> Self
Adds the custom Action A after the ones already declared.
The policy decides who may run it, through
Ability::RunAny and Ability::Run. An
A::NAME that is not a single URL path segment does not compile.
Sourcepub fn header_action<A: HeaderAction>(self) -> Self
pub fn header_action<A: HeaderAction>(self) -> Self
Adds the HeaderAction A, which acts on no record, to the list page’s header, after
the ones already declared.
The policy decides who may run it, through Ability::ViewAny
and Ability::RunHeader with its name, which no other action
of the resource may share. An A::NAME that is not
a single URL path segment does not compile.
Sourcepub fn create_column<T>(self, path: impl Into<Path<R::Model, T>>) -> Self
pub fn create_column<T>(self, path: impl Into<Path<R::Model, T>>) -> Self
Declares a column an overriding Resource::create_record sets itself, beyond the form’s
fields: .create_column(lens!(Post.slug)). Call it once per column.
Mounting the panel refuses a path that names no one field of the model, and the tenant column, which the framework stamps.