Domain DSL

v0.0.1

The MishkaGervaz.Domain extension sets defaults that every resource in an Ash domain inherits. Add it with extensions: [MishkaGervaz.Domain] and declare the defaults in a mishka_gervaz block. A resource sets any key itself and wins per key. This page lists every option of the block. For how inheritance works, see How domain defaults work.

Table defaults

Defaults for every table in the domain. It sits at mishka_gervaz.table.

OptionTypeDefaultDescription
ui_adapteratomMishkaGervaz.UIAdapters.TailwindDefault UI adapter module.
ui_adapter_optskeyword[]Default UI adapter options.
actor_keyatom:current_userDefault assign key for current user. Stored in the config. The components take the actor from their current_user assign, and no built-in code reads this key.
master_check(any -> any)noneDefault function to check if user is master. fn user -> boolean. Stored in the config. The built-in access modules do not call it: they treat a user whose site_id is nil as a master. To change the rule, override master_user?/1 in a custom access module.

actions

The default read, get and destroy actions. It sits at mishka_gervaz.table.actions.

OptionTypeDefaultDescription
readatom | {atom, atom}noneDefault read action. Atom (used for both master and tenant) or tuple {master_action, tenant_action}. Inherited by all resources in the domain.
getatom | {atom, atom}noneDefault get action. Atom or tuple {master_action, tenant_action}. Inherited by all resources in the domain.
destroyatom | {atom, atom}noneDefault destroy action. Atom or tuple {master_action, tenant_action}. Inherited by all resources in the domain.

archive

The default archive actions, for resources that use AshArchival.Resource. It sits at mishka_gervaz.table.archive.

OptionTypeDefaultDescription
enabledbooleantrueGervaz does not read the domain value. Archive is on for every resource that uses AshArchival.Resource, unless the resource's own archive block sets enabled false.
restrictedbooleanfalseDefault for restricting archive UI to master users only.
visibleboolean | (any -> any) | mfatrueControls the archive toggle. Only a boolean acts. Gervaz does not evaluate a function, and the toggle then shows.
read_actionatom | {atom, atom}{:master_archived, :archived}Default read archived action. Single atom or tuple {master_action, tenant_action}.
get_actionatom | {atom, atom}{:master_get_archived, :get_archived}Default get archived action.
restore_actionatom | {atom, atom}{:master_unarchive, :unarchive}Default restore action.
destroy_actionatom | {atom, atom}{:master_permanent_destroy, :permanent_destroy}Default permanent destroy action.

realtime

The default realtime settings. It sits at mishka_gervaz.table.realtime.

OptionTypeDefaultDescription
enabledbooleantrueDefault realtime enabled. When realtime section is defined, enabled is true by default.
pubsubatomnoneDefault PubSub module.

theme

The default table theme classes. It sits at mishka_gervaz.table.theme.

OptionTypeDefaultDescription
header_classString.tnoneDefault header CSS classes.
row_classString.tnoneDefault row CSS classes.
border_classString.tnoneDefault border CSS classes. The value is compiled into the config, but no built-in template or handler reads it.
extramap%{}Default extra theme options. The value is compiled into the config, but no built-in template or handler reads it.

url_sync

The default URL synchronization. It sits at mishka_gervaz.table.url_sync.

OptionTypeDefaultDescription
enabledbooleantrueEnable URL state synchronization. When url_sync section is defined, enabled is true by default.
mode:read_only | :bidirectional:read_only:read_only (the default) never writes the URL. The table still reads it again whenever the parent passes a new url_state. :bidirectional also updates the URL when the filters, the sort or the page change.
paramslist(:filters | :sort | :page | :page_size | :search | :template)[:filters, :sort, :page]Which state to sync to URL params.
prefixString.tnonePrefix for URL params to avoid conflicts.

refresh

The default auto-refresh. It sits at mishka_gervaz.table.refresh.

OptionTypeDefaultDescription
enabledbooleantrueEnable auto-refresh. When refresh section is defined, enabled is true by default.
intervalpos_integer30000Refresh interval in milliseconds. Default: 30 seconds.
pause_on_interactionbooleantruePause auto-refresh when user is interacting (filtering, selecting, etc.). The value is compiled into the config, but no built-in template or handler reads it.
show_indicatorbooleantrueShow a visual indicator when auto-refresh is active. The value is compiled into the config, but no built-in template or handler reads it.
pause_on_blurbooleantruePause auto-refresh when browser tab/window loses focus. The value is compiled into the config, but no built-in template or handler reads it.

pagination

The default pagination. It sits at mishka_gervaz.table.pagination.

OptionTypeDefaultDescription
enabledbooleannoneGervaz does not read it at the domain level. Set enabled false on a resource to turn its pagination off.
type:infinite | :numbered | :load_more:load_moreThe pagination style: :numbered (pages), :load_more (a button) or :infinite (loads on scroll). The schema text names :load_more as the default. A domain pagination block without a type gives :load_more, and a resource pagination block without a type, in a domain with no pagination block, gives :numbered. Set it yourself.
page_sizeinteger20Records per page. It must be one of page_size_options when both are set.
page_size_optionslist(integer)none (no page size selector)Page sizes the reader can pick. Without a list, the page size selector is not drawn.
max_page_sizepos_integer150The largest allowed page size. It clamps a page size that arrives in the URL, and it must be at least the largest entry of page_size_options.

pagination ui

Labels and options of the pagination controls. It sits at mishka_gervaz.table.pagination.ui.

OptionTypeDefaultDescription
load_more_labelString.t"Load More"Load more button text. The domain does not pass the pagination ui block to a resource.
loading_textString.t"Loading..."Loading indicator text. The domain does not pass the pagination ui block to a resource.
show_totalbooleantrueShows the total record count. A :numbered table counts whatever this says. For :load_more and :infinite, turn it off to skip the count query on a data layer that cannot count. The domain does not pass the pagination ui block to a resource.
prev_labelString.t"Previous"Previous page button text. The domain does not pass the pagination ui block to a resource.
next_labelString.t"Next"Next page button text. The domain does not pass the pagination ui block to a resource.
first_labelString.t"First"First page button text. The domain does not pass the pagination ui block to a resource.
last_labelString.t"Last"Last page button text. The domain does not pass the pagination ui block to a resource.
page_info_formatString.t"Page {page} of {total}"The page info text. Placeholders: {page}, {total} and {count}. Gervaz prints {from} and {to} as they are. The domain does not pass the pagination ui block to a resource.

Form defaults

Defaults for every form in the domain. It sits at mishka_gervaz.form.

OptionTypeDefaultDescription
ui_adapteratomMishkaGervaz.UIAdapters.TailwindDefault form UI adapter module.
ui_adapter_optskeyword[]Default form UI adapter options. The form does not read it.
actor_keyatom:current_userDefault assign key for current user. Stored in the config. The components take the actor from their current_user assign, and no built-in code reads this key.
master_check(any -> any)noneDefault function to check if user is master. fn user -> boolean. Stored in the config. The built-in access modules do not call it: they treat a user whose site_id is nil as a master. To change the rule, override master_user?/1 in a custom access module.
templateatomMishkaGervaz.Form.Templates.StandardDefault template module for form layout.
features:all | list(:validation | :uploads | :groups | :wizard | :autosave | :inline_errors):allDefault features to enable for forms. The built-in template does not check it.

actions

The default create, update and read actions. It sits at mishka_gervaz.form.actions.

OptionTypeDefaultDescription
createatom | {atom, atom}noneDefault create action. Atom (used for both master and tenant) or tuple {master_action, tenant_action}. Inherited by all form resources in the domain.
updateatom | {atom, atom}noneDefault update action. Atom or tuple {master_action, tenant_action}. Inherited by all form resources in the domain.
readatom | {atom, atom}noneDefault read/get action. Atom or tuple {master_action, tenant_action}. Inherited by all form resources in the domain.

theme

The default form theme classes. It sits at mishka_gervaz.form.theme.

OptionTypeDefaultDescription
form_classString.tnoneDefault form CSS classes. The value is compiled into the config, but no built-in template or handler reads it.
field_classString.tnoneDefault field CSS classes. The value is compiled into the config, but no built-in template or handler reads it.
label_classString.tnoneDefault label CSS classes. The value is compiled into the config, but no built-in template or handler reads it.
error_classString.tnoneDefault error message CSS classes. The value is compiled into the config, but no built-in template or handler reads it.
extramap%{}Default extra theme options. The value is compiled into the config, but no built-in template or handler reads it.

layout

The default layout settings. It sits at mishka_gervaz.form.layout.

OptionTypeDefaultDescription
navigation:sequential | :free:sequentialDefault wizard navigation mode.
persistence:none | :ets | :client_token:noneDefault wizard step persistence. The value is compiled into the config, but no built-in template or handler reads it.
columnspos_integer1Default number of form columns. Only 1 to 4 change the grid. Any other value gives one column.
responsivebooleantrueDefault responsive layout behavior. The value is compiled into the config, but no built-in template or handler reads it.

submit

The default submit row. Each button merges per button with the resource. See How domain defaults work. It sits at mishka_gervaz.form.submit.

OptionTypeDefaultDescription
position:top | :bottom | :both:bottomButton position. The value is compiled into the config, but no built-in template or handler reads it.

submit.create

The create button. It sits at mishka_gervaz.form.submit.create.

OptionTypeDefaultDescription
labelString.t | (-> any)noneButton label. String or zero-arity function.
activeboolean | (any -> any)trueWhether the button is active. Boolean or fn state -> boolean end. Set to false to suppress a button inherited from the domain. Resource-only.
disabledboolean | (any -> any)falseDisable button. Boolean or fn state -> boolean end.
visibleboolean | (any -> any)trueStatic or dynamic visibility. fn state -> boolean() end.
restrictedboolean | (any -> any)falseRestrict to master users. true or fn state -> boolean() end.

submit.update

The update button. It sits at mishka_gervaz.form.submit.update.

OptionTypeDefaultDescription
labelString.t | (-> any)noneButton label. String or zero-arity function.
activeboolean | (any -> any)trueWhether the button is active. Boolean or fn state -> boolean end. Set to false to suppress a button inherited from the domain. Resource-only.
disabledboolean | (any -> any)falseDisable button. Boolean or fn state -> boolean end.
visibleboolean | (any -> any)trueStatic or dynamic visibility. fn state -> boolean() end.
restrictedboolean | (any -> any)falseRestrict to master users. true or fn state -> boolean() end.

submit.cancel

The cancel button. It sits at mishka_gervaz.form.submit.cancel.

OptionTypeDefaultDescription
labelString.t | (-> any)noneButton label. String or zero-arity function.
activeboolean | (any -> any)trueWhether the button is active. Boolean or fn state -> boolean end. Set to false to suppress a button inherited from the domain. Resource-only.
disabledboolean | (any -> any)falseDisable button. Boolean or fn state -> boolean end.
visibleboolean | (any -> any)trueStatic or dynamic visibility. fn state -> boolean() end.
restrictedboolean | (any -> any)falseRestrict to master users. true or fn state -> boolean() end.

submit.ui

Classes for the submit row. It sits at mishka_gervaz.form.submit.ui.

OptionTypeDefaultDescription
submit_classString.tnoneSubmit button CSS classes. The value is compiled into the config, but no built-in template or handler reads it.
cancel_classString.tnoneCancel button CSS classes. The value is compiled into the config, but no built-in template or handler reads it.
wrapper_classString.tnoneButton wrapper CSS classes. The value is compiled into the config, but no built-in template or handler reads it.
extramap%{}Additional options. The value is compiled into the config, but no built-in template or handler reads it.

Example

The domain of Mishka Blog sets the table and form defaults once, and every blog resource inherits them.

elixir
defmodule MishkaBlog do
  use Ash.Domain,
    extensions: [MishkaGervaz.Domain]

  mishka_gervaz do
    table do
      actor_key :current_user
      ui_adapter MishkaGervaz.UIAdapters.Tailwind

      pagination do
        type :load_more
        page_size 20
        page_size_options [20, 50, 100, 150]
      end

      realtime do
        pubsub MishkaCmsCore.PubSub
      end

      actions do
        read {:master_read, :read}
        get {:master_get, :read}
        destroy {:master_destroy, :destroy}
      end

      archive do
        read_action {:master_archived, :archived}
        get_action {:master_get_archived, :get_archived}
        restore_action {:master_unarchive, :unarchive}
        destroy_action {:master_permanent_destroy, :permanent_destroy}
      end
    end

    form do
      actions do
        create {:master_create, :create}
        update {:master_update, :update}
        read {:master_get, :read}
      end

      submit do
        create label: fn -> dgettext("mishka_gervaz", "Create") end
        update label: fn -> dgettext("mishka_gervaz", "Save Changes") end
        cancel label: fn -> dgettext("mishka_gervaz", "Cancel") end
        position :bottom
      end
    end
  end
end