Helper functions for MishkaGervaz.Table.Web.State.
Extracted from the __using__ macro so user overrides can reuse the
same primitives the default state implementation uses.
Example
defmodule MyApp.Table.State do
use MishkaGervaz.Table.Web.State
alias MishkaGervaz.Table.Web.State.Helpers, as: StateHelpers
def hydrate_relation_filter_labels(state) do
StateHelpers.hydrate_filter(filter, acc, state)
end
endSee MishkaGervaz.Table.Web.State,
MishkaGervaz.Table.Web.State.ColumnBuilder,
MishkaGervaz.Table.Web.State.FilterBuilder,
MishkaGervaz.Table.Web.State.ActionBuilder,
MishkaGervaz.Table.Web.State.Presentation,
MishkaGervaz.Table.Web.State.UrlSync,
MishkaGervaz.Table.Web.State.Access.
Summary
Functions
Maps each sortable column to the database fields it sorts by.
The selected ids for one filter, as strings, with blanks removed.
The stream name derived from a resource module when identity do stream_name … end is
omitted.
The archive block's visible flag, defaulting to true when it is not a plain boolean —
a function predicate is evaluated later, against live state.
The sort a table opens with.
The feature list this table runs with.
The filter_groups declared on the resource, or [].
Where the filter bar renders — :inline (the default), :sidebar, :modal or :drawer.
The table's layout do footer … end map, or nil when the resource declares none.
The table's layout do header … end map, or nil when the resource declares none.
Every layout do notice … end declared on the resource, in declaration order.
The ceiling a page size is clamped to — the guard against an oversized ?t_page_size= in
the URL.
The configured page size, or nil when pagination is off.
The page-size choices offered in the UI, or nil when no dropdown should be drawn.
The pagination labels as a MishkaGervaz.Table.Entities.Pagination.Ui struct.
The names of the columns declared sortable true.
Whether this reader may see the archive toggle.
Resolves the labels for one relation filter's currently selected ids and stores them under the filter's name.
The access module for a resource — its state do access … end override, or the default
passed in.
Asks the resource's relation loader for the records behind selected_ids and writes them
into acc as that filter's :selected_options.
The relation loader a resource uses — its data_loader do relation … end override, or
MishkaGervaz.Table.Web.DataLoader.RelationLoader.Default.
The URL-sync module for a resource — its state do url_sync … end override, or the default
passed in.
Functions
Maps each sortable column to the database fields it sorts by.
A column falls back to its own name unless it declared sort_field, which is what lets a
static true column sort by something it does not display.
iex> build_sort_field_map([%{name: :site_datetime, sortable: true, sort_field: [:inserted_at]}])
%{site_datetime: [:inserted_at]}
The selected ids for one filter, as strings, with blanks removed.
Accepts a single value or a list, so a :search and a :search_multi filter read the same.
iex> extract_selected_ids(%{site_id: ["a", "", nil]}, :site_id)
["a"]
The stream name derived from a resource module when identity do stream_name … end is
omitted.
iex> generate_stream_name(MyApp.Blog.Post)
:post_stream
The archive block's visible flag, defaulting to true when it is not a plain boolean —
a function predicate is evaluated later, against live state.
The sort a table opens with.
The resource's default_sort when it declared a non-empty list; otherwise newest-first if
there is a sortable :inserted_at column; otherwise no sort at all.
iex> get_default_sort(%{columns: %{default_sort: [featured: :desc]}}, [])
[featured: :desc]
The feature list this table runs with.
An explicit features [...] is taken as given. :all (the default) means the union of what
the current template and every switchable template support, so switching views never asks
for a feature the new template cannot draw. :paginate is dropped when the resource has no
pagination configured.
iex> get_features(%{presentation: %{features: [:sort, :filter]}}, MyTemplate)
[:sort, :filter]
The filter_groups declared on the resource, or [].
Where the filter bar renders — :inline (the default), :sidebar, :modal or :drawer.
The table's layout do header … end map, or nil when the resource declares none.
Every layout do notice … end declared on the resource, in declaration order.
@spec get_max_page_size(map()) :: pos_integer() | nil
The ceiling a page size is clamped to — the guard against an oversized ?t_page_size= in
the URL.
@spec get_page_size(map()) :: pos_integer() | nil
The configured page size, or nil when pagination is off.
@spec get_page_size_options(map()) :: [pos_integer()] | nil
The page-size choices offered in the UI, or nil when no dropdown should be drawn.
The pagination labels as a MishkaGervaz.Table.Entities.Pagination.Ui struct.
Always a struct: a resource that configured nothing gets one with the defaults, so a
template can read ui.load_more_label without checking for nil first.
The names of the columns declared sortable true.
iex> get_sortable_columns([%{name: :title, sortable: true}, %{name: :body, sortable: false}])
[:title]
Whether this reader may see the archive toggle.
false unless the resource enables archive; an archive do restricted true end narrows it
further to master users only.
@spec hydrate_filter(map(), map(), MishkaGervaz.Table.Web.State.t()) :: map()
Resolves the labels for one relation filter's currently selected ids and stores them under the filter's name.
Returns acc unchanged when the filter has no selection, which is what makes it safe to
fold over every filter.
Enum.reduce(state.static.filters, %{}, &StateHelpers.hydrate_filter(&1, &2, state))
The access module for a resource — its state do access … end override, or the default
passed in.
@spec resolve_and_store_labels( map(), map(), [String.t()], MishkaGervaz.Table.Web.State.t() ) :: map()
Asks the resource's relation loader for the records behind selected_ids and writes them
into acc as that filter's :selected_options.
The entry is shaped like a loaded page with an empty option list — the dropdown fills the options itself on first open; only the labels of what is already selected are needed here.
The relation loader a resource uses — its data_loader do relation … end override, or
MishkaGervaz.Table.Web.DataLoader.RelationLoader.Default.
loader = resolve_relation_loader(MyApp.Blog.Post)
loader.resolve_selected(filter_map, state, ["1", "2"])
The URL-sync module for a resource — its state do url_sync … end override, or the default
passed in.