Skip to content

Customization and polish

Export

Each index exports its current scoped-and-filtered view. The toolbar offers the enabled formats, and the export honours the active scope, filters, and sort.

  • GET /admin/<resource>/export.csv streams a CSV: a header row of column labels followed by one row per record, with values quoted when they contain a comma, quote, or newline. It is sent as a download attachment and streamed rather than buffered, so large result sets do not build a single string in memory.
  • GET /admin/<resource>/export.json returns the same view as JSON, rendered through the controller's custom-renderer registry. Each object carries the column values.
  • GET /admin/<resource>/export.xml returns the same view as XML through the renderer registry, one <record> per row.

Export columns

By default the export uses the index columns. A csv block declares an explicit set of export columns instead, applied to CSV, JSON, and XML alike:

1
2
3
4
csv({
  column('title');
  column('author', :display({ .author.name }));
});

Limiting the formats

The export is on by default with all three formats. Restrict or disable it per resource with the export option:

1
2
MVC::Keayl::Admin.register(Post, { ... }, export => <csv json>);   # only CSV and JSON
MVC::Keayl::Admin.register(Log,  { ... }, export => False);        # no export

Only the offered formats get a route and a toolbar link; a disabled format is a 404.

Standalone pages

A page has no backing model. It is registered with a block that returns HTML, rendered inside the admin layout, and added to the menu:

1
2
3
MVC::Keayl::Admin.page('reports', -> $controller {
  '<div class="card"><div class="card-body">Sales summary</div></div>'
}, title => 'Reports', group => 'Tools', icon => 'graph-up');

The block receives the controller, so it can read params or the current admin. Pass :hide to register the route without a menu entry. Page menu entries honour the same group, priority, and icon options as resources. A page's icon also appears in its heading, the same as a resource's icon.

Localization

All chrome, resource names, attribute labels, scope names, and action labels go through an I18n backend. Without translations they fall back to the humanized English defaults, so localization is opt-in. Humanizing title-cases each word and drops a trailing _id or _at suffix, so author_id becomes Author and created_at becomes Created.

Load locale files and select a locale:

1
2
MVC::Keayl::Admin.load-locales('config/locales');
MVC::Keayl::Admin.locale('fr');

The lookup keys are:

  • activerecord.models.<model> and activerecord.attributes.<model>.<attr> for resource and attribute names (shared with the ORM's conventions).
  • keayl_admin.chrome.<key> for chrome strings such as dashboard, actions, show, edit, delete, new, filters, and no-records.
  • keayl_admin.scopes.<name> for scope tab labels.
  • keayl_admin.actions.<name> for custom action labels.

Theming

Host view overrides

Register a view path that is searched before the engine's own views. A host template at the same name overrides the engine's:

1
MVC::Keayl::Admin.view-path('app/views/admin');

A file at app/views/admin/resource/index.html.haml then replaces the built-in index template, and likewise for any partial.

CSS variables

The admin layers a small stylesheet over the Bootstrap bundle that exposes a set of CSS variables:

  • --keayl-admin-sidebar-bg
  • --keayl-admin-sidebar-width
  • --keayl-admin-navbar-bg
  • --keayl-admin-accent
  • --keayl-admin-body-bg

Override them with a host stylesheet, which is loaded after the theme so its values win:

1
MVC::Keayl::Admin.use-stylesheet('/assets/admin-theme.css');
1
2
3
4
:root {
  --keayl-admin-navbar-bg: #1b1e21;
  --keayl-admin-accent: #6f42c1;
}