Runique Admin
Documentation / Runique Admin / List view — Pagination, sorting, search and filters

List view — Pagination, sorting, search and filters

The admin list works at SQL level: pagination, sort, search and filters. Nothing is loaded into memory just to page.

The admin list works at SQL level: pagination, sort, search and filters. Nothing is loaded into memory just to page.

Config is declared on ModelAdmin via .list(|l| …).

Displayed columns

.list(|l| l.display([Title, Status, Views]))

Without display, every non-secret column appears (accounts: username, email, is_active), with dates and times last. A declared display keeps its order. A row's detail page follows that order, but always puts dates and times at the end.

Array order is header order.

.list(|l| l.display([Title, Status]).links([Title]))

No effect for now: links is accepted and checked (its columns must be in display), but the list shows each row as a card with its own link to the detail (and its menu), whatever the declared columns.

Sorting

Default SQL order:

.list(|l| {
    l.display([Title, CreatedAt])
        .ordering([(CreatedAt, Order::Desc), (Title, Order::Asc)])
})

Clickable sort from the UI / URL — only declared columns:

.sortable([Title, Status])

Any other ?sort_by= is ignored.

.list(|l| l.search([Title, Summary]))

Behaviour:

  • minimum 3 characters (shorter terms are ignored)
  • beyond the staging's .search_max_len(n) (150 by default), the term is truncated
  • without .search(...): text columns from display are used
  • .search([]) disables the search
  • .search_help("…") is accepted but not shown yet

Filters

.list(|l| l.filter([Status, Lang]))

Each filter offers distinct values in the allowed scope, page by page. URL prefix is filter_:

?filter_status=Published&filter_status=Draft&filter_lang=en

Several values of one column add up (Published or Draft), several columns combine (and). Clicking a value turns it on; clicking it again turns it off, the others stay. A column accepts at most 100 values from the URL.

Each group of the panel has its arrows, and a single selector, under the panel's title, sets the number of values of all groups:

LevelMethodDefault
SiteAdminStaging::filter_size(n)10
ModelListConfig::filter_size(n)inherits site
admin.filter_size(8)

.list(|l| l.filter([PageId]).filter_size(15))

The choice made in the selector (10, 25, 50 or 100) wins over these settings.

Bulk actions

.list(|l| {
    l.display([Title, Status])
        .action(Status, "Published", "Publish")
        .action(Status, "Archived", "Archive")
})

The UI sends the action index (a0, a1…), never the raw value. The value is fixed in code.

Boot constraints:

  • column writable on edit
  • no secret, no owner, no account rank flags

Pagination

LevelMethodDefault
SiteAdminStaging::page_size(n)10
ModelListConfig::per_page(n)inherits site
admin.page_size(15)

.list(|l| l.per_page(30))

The list's selector (10, 25, 50 or 100) wins over these settings. The URL can't ask for another size.

URL parameters

ParamRole
pagePage number (1-based)
sort_byColumn name (must be in sortable)
sort_dirasc or desc
searchFull-text term
per_pageRows per page (10, 25, 50 or 100)
filter_<col>Filter value, repeatable
fpage_<col>Page of values of the filter group <col>
fsizeValues per page of the filter groups (10, 25, 50 or 100)

Example:

/admin/blog/list?page=2&sort_by=title&sort_dir=asc&search=runique&filter_status=Published

Empty value

.list(|l| l.empty_value("—"))

No effect for now: accepted, but the list doesn't use this text yet.