{% extends "base.html" %}
{% block title %}{{ title }} - {{ shell.brand }}{% endblock %}
{% block content %}
<div class="lat-toolbar">
<h1>{{ title }}</h1>
{% if exportable || import_href.is_some() %}
{# Moving a whole resource in or out is the page's business, not the table's:
it belongs beside the title, while the row below acts on rows. #}
<div class="lat-toolbar__actions">
{% if let Some(href) = import_href %}<a class="lat-btn lat-btn--secondary lat-btn--sm" href="{{ href }}">{{ shell.t("Import") }}</a>{% endif %}
{% if exportable %}
<details class="lat-menu">
<summary class="lat-btn lat-btn--secondary lat-btn--sm">{{ shell.t("Export") }}</summary>
<div class="lat-menu__panel">
{# The export carries the current query, so the file matches this screen. #}
<a href="{{ path }}/export?format=csv{{ export_query }}">{{ shell.t("CSV") }}</a>
<a href="{{ path }}/export?format=json{{ export_query }}">{{ shell.t("JSON") }}</a>
</div>
</details>
{% endif %}
</div>
{% endif %}
</div>
{# The query form carries the search term, every filter and the current sort,
but holds none of the controls: the search box sits in the action row and the
filters in their own band, each bound back by `form=`. One form is what makes
narrowing by one control keep what another set, and it submits on Enter with
scripting off. It stays outside #lat-list, so a swap never steals the caret. #}
<form id="lat-list-query" method="get" action="{{ path }}" hidden
hx-get="{{ path }}" hx-target="#lat-list" hx-swap="outerHTML" hx-push-url="true"
hx-trigger="{% if searchable %}{% if !search_on_enter %}input changed delay:300ms from:#lat-list-search, {% endif %}search from:#lat-list-search, {% endif %}change from:#lat-list-filters select, change from:#lat-list-filters input, input changed delay:300ms from:#lat-list-filters input[type='text'], submit">
<input type="hidden" name="sort" value="{{ sort }}">
<input type="hidden" name="dir" value="{{ dir }}">
</form>
<div class="lat-listbar">
<div class="lat-listbar__actions">
{% for b in toolbar %}
<a class="lat-btn lat-btn--sm {% if b.primary %}lat-btn--primary{% else %}lat-btn--secondary{% endif %}" href="{{ b.href }}">{% if !b.icon.is_empty() %}<span class="lat-btn__icon">{{ b.icon|safe }}</span>{% endif %}{{ b.label }}</a>
{% endfor %}
{% if deletable %}
<span class="lat-listbar__divider" aria-hidden="true"></span>
{# Acts on rows inside the swapped region, so it starts disabled and follows
the checkboxes rather than being enabled by markup. #}
<button class="lat-btn lat-btn--danger lat-btn--sm" type="submit"
form="lat-list-actions" data-lat-widget="bulk-delete" disabled
data-lat-confirm='{{ shell.t("Delete the selected records? This cannot be undone.") }}'>
{{ shell.t("Delete") }}
</button>
{% endif %}
</div>
<div class="lat-listbar__tools">
{% if searchable %}
<input class="lat-input lat-listbar__search" id="lat-list-search" form="lat-list-query"
type="search" name="q" value="{{ q }}"
placeholder='{% if let Some(p) = search_prompt %}{{ p }}{% else %}{{ shell.t("Search") }}{% endif %}' aria-label='{% if let Some(p) = search_prompt %}{{ p }}{% else %}{{ shell.t("Search") }}{% endif %}'>
{% endif %}
{% if !pickers.is_empty() %}
{# The list setup: which columns, and how many rows. A native disclosure, so
it needs no script; both choices are remembered per operator. #}
<details class="lat-menu">
<summary class="lat-btn lat-btn--secondary lat-btn--sm lat-btn--icon"
title='{{ shell.t("List setup") }}' aria-label='{{ shell.t("List setup") }}'>{{ shell.icon("sliders-horizontal")|safe }}</summary>
<div class="lat-colpicker">
<form method="post" action="{{ path }}/columns">
{% include "_csrf.html" %}
{% for c in pickers %}
<label class="lat-check">
<input type="checkbox" name="column" value="{{ c.field }}"{% if c.shown %} checked{% endif %}>
<span>{{ c.label }}</span>
</label>
{% endfor %}
{% if !per_page_options.is_empty() %}
<label class="lat-colpicker__size">
<span>{{ shell.t("Rows per page") }}</span>
<select class="lat-input lat-select" name="per_page">
{% for n in per_page_options %}<option value="{{ n }}"{% if *n == per_page %} selected{% endif %}>{{ n }}</option>{% endfor %}
</select>
</label>
{% endif %}
<button class="lat-btn lat-btn--primary lat-btn--sm" type="submit">{{ shell.t("Apply") }}</button>
</form>
</div>
</details>
{% endif %}
<noscript><button class="lat-btn lat-btn--secondary lat-btn--sm" type="submit" form="lat-list-query">{{ shell.t("Apply") }}</button></noscript>
</div>
</div>
{% if !filters.is_empty() %}
{# Its own band: a resource with four filters must not push the actions around.
The bar sits outside the swapped region and cannot re-render per swap, so the
region declares whether anything narrows the list and CSS reads it. #}
<div class="lat-filterbar" id="lat-list-filters">
{% for f in filters %}
<label class="lat-filterbar__filter">
<span class="lat-filterbar__label">{{ f.label }}</span>
{% if f.options.is_empty() %}
<input class="lat-input" type="{{ f.input_type }}" name="{{ f.param }}" value="{{ f.value }}" form="lat-list-query">
{% else %}
<select class="lat-input lat-select" name="{{ f.param }}" form="lat-list-query">
<option value="">{{ shell.t("Any") }}</option>
{% for o in f.options %}
<option value="{{ o.value }}"{% if o.value == f.value %} selected{% endif %}>{{ o.label }}</option>
{% endfor %}
</select>
{% endif %}
</label>
{% endfor %}
<a class="lat-filterbar__clear" href="{{ path }}">{{ shell.t("Clear") }}</a>
</div>
{% endif %}
{% if deletable %}
{# Holds only the token: the rows carry `form="lat-list-actions"` from inside the
swapped region, so a swap replaces the checkboxes without destroying the form
they belong to, and the button above posts it from the action row. #}
<form id="lat-list-actions" method="post" action="{{ path }}/delete" hidden>
{% include "_csrf.html" %}
</form>
{% endif %}
{% include "_list_table.html" %}
{% endblock %}