{% import "adminsite/_icons.html" as icons %} {% import "adminsite/_values.html" as values %}
{% if request.headers.get("hx-request") %} {% with oob = true %}{% include "adminsite/_records_total.html" %}{% endwith %} {% endif %}
{{ csrf_input | safe if csrf_input }}
{% if actions %} {% endif %} {#- The row's menu comes first, where it is in reach however many columns the table has. -#} {% for path in columns %} {% set state = sort_state(request, path) %} {#- An amount lines up on the right; a key is a name for its record, not an amount, so it reads from the start like text. -#} {% set numeric = view._fields.field_for(path).widget == 'number' and path not in view._schema.primary_key %} {% endfor %} {% for row in page %} {% with upward = loop.revindex <= 3 and loop.length > 5 %}{% include "adminsite/_row.html" %}{% endwith %} {% else %} {% endfor %}
{{ view.label_plural }}
{{ _('Actions') }} {% if view._pages.sortable(path) %} {{ view._fields.label_for(path) }} {% if state == "asc" %}{% endif %} {% if state == "desc" %}{% endif %} {% else %} {{ view._fields.label_for(path) }} {% endif %}
{{ _("No {things} to show.", things=view.label_plural|lower) }}
{#- On a phone each row is a card: its first column and its first badge on top, the rest below with the first amount at the end. -#} {%- set layout = namespace(badge=none, amount=none) -%} {%- for path in columns[1:] -%} {%- set kind = view._fields.field_for(path).widget -%} {%- if layout.badge is none and kind in ("select", "checkbox") %}{% set layout.badge = path %}{% endif -%} {%- if layout.amount is none and kind == "number" %}{% set layout.amount = path %}{% endif -%} {%- endfor -%}
    {% for row in page %} {% set key = view._fields.identity_of(row) %} {% set first = columns[0] %} {% set text = view._fields.display(row, first) %} {% set is_key = view._fields.field_for(first).widget == "number" and first in view._schema.primary_key %} {% set shown = ("#" ~ text if is_key and text else (text or view.get_record_title(row))) %} {% set opens = urls.detail(view, key) if can_detail else (urls.edit(view, key) if can_edit else "") %} {% set rest = [] %} {% for path in columns[1:] if path not in (layout.badge, layout.amount) and view._fields.field_for(path).widget not in ("image", "file") %} {% set value = view._fields.display(row, path) %} {% if value %}{% set ignored = rest.append(value|string) %}{% endif %} {% endfor %}
  • <{{ "a" if opens else "div" }} {% if opens %}href="{{ opens }}"{% endif %} class="flex flex-col gap-1 px-4 py-3 active:bg-subtle"> {{ shown }} {% if layout.badge and view._fields.display(row, layout.badge) and not view._fields.hides(row, layout.badge) %} {{ values.badge(view._fields.field_for(layout.badge), view._fields.value_at(row, layout.badge), view._fields.display(row, layout.badge)) }} {% endif %} {{ rest|join(" · ") }} {% if layout.amount %} {{ view._fields.display(row, layout.amount) }} {% endif %}
  • {% else %}
  • {{ _("No {things} to show.", things=view.label_plural|lower) }}
  • {% endfor %}
{% if actions %} {#- Floats over the table while rows are ticked, so the actions are where the eye already is. -#}
{{ _('selected') }} {% if page.total is not none %} {{ _("All {count} matching rows are selected.", count=total_text) }} {% endif %} {% if page.total is not none %} {% endif %} {% for item in actions %} {% if item.needs_dialog %} {% else %} {% endif %} {% endfor %}
{% endif %}
{#- Each dialog is its own form, so a required input in one dialog never stops another action from submitting. On submit it copies the ticked rows across from the table. -#} {% for item in actions if item.needs_dialog %} {% endfor %} {% include "adminsite/_action_forms.html" %}
{% if page.keyset %} {% if page.total is not none %}{{ total_text }} {{ view.label_plural|lower }}{% endif %} {% elif page.total is not none %} {{ _("{first} to {last} of {total}", first=page.first_position, last=page.last_position, total=total_text) }} {% else %} {{ _("{first} to {last}", first=page.first_position, last=page.last_position) }} {% endif %} {% if page_sizes %} {% endif %} {% if page.keyset %} {% set previous = urls.here(page=None, after=None, before=page.previous_cursor or None) %} {% set next = urls.here(page=None, before=None, after=page.next_cursor or None) %} {% else %} {% set previous = urls.here(page=page_number - 1 if page_number > 2 else None) %} {% set next = urls.here(page=page_number + 1) %} {% endif %}