{% extends "admin/_base.html" %}
{# RustIO Console — model list. Masthead + command bar + data board,
# matching ui_kits/admin. Keeps the framework's real columns, search,
# filters, sort, saved views, bulk actions, and pagination + their
# admin.js hooks (data-rio-dropdown / data-rio-bulk / row actions). #}
{% macro filter_icon(kind) -%}
{%- if kind == "date_range" -%}{{ icon("clock", class="rio-icon") }}
{%- elif kind == "fk_autocomplete" -%}{{ icon("database", class="rio-icon") }}
{%- elif kind == "multi_select" -%}{{ icon("menu", class="rio-icon") }}
{%- else -%}{{ icon("flag", class="rio-icon") }}
{%- endif -%}
{%- endmacro %}
{% macro filter_active(group) -%}
{%- if group.kind == "date_range" and group.has_active_range -%}1
{%- elif group.kind == "multi_select" and group.multi_selected -%}1
{%- elif group.kind == "fk_autocomplete" and group.fk_selected_id -%}1
{%- elif group.kind not in ["date_range", "multi_select", "fk_autocomplete"] and group.current -%}1
{%- endif -%}
{%- endmacro %}
{% macro filter_body(group, admin_name, search_query, active_sort_field, active_sort_dir, active_per_page_override, csrf_token) %}
{% if group.kind == "fk_autocomplete" %}
<form method="get" action="/admin/{{ admin_name }}" class="rio-fk-autocomplete" data-rio-fk-autocomplete data-rio-fk-lookup-url="{{ group.fk_lookup_url }}" data-rio-fk-field-name="{{ group.field }}">
{% for pair in group.hidden_pairs %}<input type="hidden" name="{{ pair[0] }}" value="{{ pair[1] }}">{% endfor %}
{% if search_query %}<input type="hidden" name="q" value="{{ search_query }}">{% endif %}
{% if active_sort_field %}<input type="hidden" name="sort" value="{{ active_sort_field }}"><input type="hidden" name="dir" value="{{ active_sort_dir }}">{% endif %}
{% if active_per_page_override %}<input type="hidden" name="per_page" value="{{ active_per_page_override }}">{% endif %}
<input type="hidden" name="{{ group.field }}" value="{{ group.fk_selected_id }}" data-rio-fk-id>
<div class="rio-fk-autocomplete-wrap">
<input type="search" class="rio-input rio-fk-autocomplete-input" value="{{ group.fk_selected_label or group.fk_selected_id }}" placeholder="Search {{ group.fk_target_label }}…" autocomplete="off" data-rio-fk-search>
<ul class="rio-fk-autocomplete-results" data-rio-fk-results hidden></ul>
</div>
<div class="rio-fk-autocomplete-actions">
<button type="submit" class="rio-btn rio-btn--primary rio-btn--sm">Apply</button>
{% if group.fk_selected_id %}<a href="{{ group.all_link }}" class="rio-btn rio-btn--secondary rio-btn--sm">Clear</a>{% endif %}
</div>
</form>
{% elif group.kind == "multi_select" %}
<form method="get" action="/admin/{{ admin_name }}" class="rio-multi-select">
{% for pair in group.hidden_pairs %}<input type="hidden" name="{{ pair[0] }}" value="{{ pair[1] }}">{% endfor %}
{% if search_query %}<input type="hidden" name="q" value="{{ search_query }}">{% endif %}
{% if active_sort_field %}<input type="hidden" name="sort" value="{{ active_sort_field }}"><input type="hidden" name="dir" value="{{ active_sort_dir }}">{% endif %}
{% if active_per_page_override %}<input type="hidden" name="per_page" value="{{ active_per_page_override }}">{% endif %}
<ul class="rio-multi-select-options">
{% for opt in group.options %}
<li><label class="rio-multi-select-option"><input type="checkbox" name="{{ group.field }}" value="{{ opt.value }}"{% if opt.selected %} checked{% endif %}><span>{{ opt.label }}</span></label></li>
{% endfor %}
</ul>
<div class="rio-multi-select-actions">
<button type="submit" class="rio-btn rio-btn--primary rio-btn--sm">Apply</button>
{% if group.multi_selected %}<a href="{{ group.all_link }}" class="rio-btn rio-btn--secondary rio-btn--sm">Clear</a>{% endif %}
</div>
</form>
{% elif group.kind == "date_range" %}
<form method="get" action="/admin/{{ admin_name }}" class="rio-date-range">
{% for pair in group.hidden_pairs %}<input type="hidden" name="{{ pair[0] }}" value="{{ pair[1] }}">{% endfor %}
{% if search_query %}<input type="hidden" name="q" value="{{ search_query }}">{% endif %}
{% if active_sort_field %}<input type="hidden" name="sort" value="{{ active_sort_field }}"><input type="hidden" name="dir" value="{{ active_sort_dir }}">{% endif %}
{% if active_per_page_override %}<input type="hidden" name="per_page" value="{{ active_per_page_override }}">{% endif %}
<label class="rio-date-range-field"><span class="rio-date-range-label-text">From</span><input type="date" name="{{ group.date_from_name }}" value="{{ group.date_from_value }}" class="rio-input rio-date-range-input"></label>
<label class="rio-date-range-field"><span class="rio-date-range-label-text">To</span><input type="date" name="{{ group.date_to_name }}" value="{{ group.date_to_value }}" class="rio-input rio-date-range-input"></label>
<div class="rio-date-range-actions">
<button type="submit" class="rio-btn rio-btn--primary rio-btn--sm">Apply</button>
{% if group.has_active_range %}<a href="{{ group.all_link }}" class="rio-btn rio-btn--secondary rio-btn--sm">Clear</a>{% endif %}
</div>
</form>
{% else %}
<div class="rio-chip-row">
<a href="{{ group.all_link }}" class="rio-chip{% if not group.current %} is-active{% endif %}">All</a>
{% for opt in group.options %}
<a href="{{ opt.link }}" class="rio-chip{% if opt.selected %} is-active{% endif %}">{{ opt.label }}</a>
{% endfor %}
</div>
{% endif %}
{% endmacro %}
{% block content %}
<nav class="rio-crumbs"><a href="/admin">Home</a><span class="rio-crumb-sep">·</span><span class="rio-crumb-current">{{ display_name }}</span></nav>
<div class="rio-masthead-top">
<div>
<h1>{{ display_name }}</h1>
<p class="rio-masthead-desc">Every {{ singular_name|lower }} rustio generated for {{ app_name }} — searchable, sortable, production-ready.</p>
</div>
<div class="rio-masthead-cta">
<a class="rio-btn rio-btn--secondary rio-btn--md" href="{{ csv_export_url }}" download>{{ icon("download") }} Export</a>
{% if not read_only %}
<a class="rio-btn rio-btn--primary rio-btn--md" href="/admin/{{ admin_name }}/new">{{ icon("plus") }} Add {{ singular_name }}</a>
{% endif %}
</div>
</div>
{# ---- Command bar ---- #}
<div class="rio-cmdbar">
<form method="get" action="/admin/{{ admin_name }}" class="rio-search rio-search--lg rio-search--hero{% if search_query %} rio-search--filled{% endif %}" role="search">
<span class="rio-search-icon">{{ icon("search") }}</span>
<input class="rio-input" type="search" name="q" value="{{ search_query }}" placeholder="Search {{ display_name|lower }}…" aria-label="Search">
{% for pair in active_filter_pairs %}<input type="hidden" name="{{ pair[0] }}" value="{{ pair[1] }}">{% endfor %}
{% if active_sort_field %}<input type="hidden" name="sort" value="{{ active_sort_field }}"><input type="hidden" name="dir" value="{{ active_sort_dir }}">{% endif %}
{% if active_per_page_override %}<input type="hidden" name="per_page" value="{{ active_per_page_override }}">{% endif %}
<button type="submit" class="rio-search-go" tabindex="-1">Search</button>
</form>
{% if filters %}
{% for group in filters %}{% if loop.index <= 2 %}
<div class="rio-dropdown" data-rio-dropdown>
<button type="button" class="rio-btn rio-btn--secondary rio-btn--lg rio-dropdown-toggle{% if filter_active(group) %} is-active{% endif %}" aria-haspopup="true" aria-expanded="false">{{ filter_icon(group.kind) }} {{ group.label }} {{ icon("chevron-down", class="rio-chev") }}</button>
<div class="rio-dropdown-panel rio-menu" role="dialog" aria-label="{{ group.label }}"><div class="rio-dropdown-section">{{ filter_body(group, admin_name, search_query, active_sort_field, active_sort_dir, active_per_page_override, csrf_token) }}</div></div>
</div>
{% endif %}{% endfor %}
{% if filters|length > 2 %}
<div class="rio-dropdown" data-rio-dropdown>
<button type="button" class="rio-btn rio-btn--secondary rio-btn--lg rio-dropdown-toggle" aria-haspopup="true" aria-expanded="false">{{ icon("filter") }} More filters{% if active_filter_count > 0 %} <span class="rio-dropdown-badge">{{ active_filter_count }}</span>{% endif %} {{ icon("chevron-down", class="rio-chev") }}</button>
<div class="rio-dropdown-panel rio-menu" role="dialog" aria-label="More filters">
{% for group in filters %}{% if loop.index > 2 %}<div class="rio-dropdown-section"><span class="rio-dropdown-label">{{ group.label }}</span>{{ filter_body(group, admin_name, search_query, active_sort_field, active_sort_dir, active_per_page_override, csrf_token) }}</div>{% endif %}{% endfor %}
{% if active_filter_count > 0 %}<div class="rio-dropdown-footer"><a href="{{ clear_all_filters_link }}" class="rio-btn rio-btn--secondary rio-btn--sm">Clear all</a></div>{% endif %}
</div>
</div>
{% endif %}
{% endif %}
{% if sort_fields %}
<div class="rio-dropdown" data-rio-dropdown>
<button type="button" class="rio-btn rio-btn--secondary rio-btn--lg rio-dropdown-toggle" aria-haspopup="true" aria-expanded="false">{{ icon("sliders") }} Sort: {{ current_sort_field_label }} {{ icon("chevron-down", class="rio-chev") }}</button>
<div class="rio-dropdown-panel rio-menu" role="dialog" aria-label="Sort">
<div class="rio-dropdown-section"><span class="rio-dropdown-label">Sort by</span>
<div class="rio-dropdown-menu">
<a href="{{ default_sort_link }}" class="rio-menu-item{% if not active_sort_field %} is-active{% endif %}">Default order</a>
{% for sf in sort_fields %}<a href="{{ sf.asc_link }}" class="rio-menu-item{% if sf.is_active %} is-active{% endif %}">{{ sf.label }}</a>{% endfor %}
</div>
</div>
</div>
</div>
{% if active_sort_field %}<a class="rio-btn rio-btn--secondary rio-btn--lg" href="{{ sort_dir_toggle_link }}" title="Switch direction">{{ icon("arrow-up-down") }} {{ current_sort_dir_label }}</a>{% endif %}
{% endif %}
{% if per_page_options %}
<div class="rio-dropdown" data-rio-dropdown>
<button type="button" class="rio-btn rio-btn--secondary rio-btn--lg rio-dropdown-toggle" aria-haspopup="true" aria-expanded="false">{{ icon("table") }} {{ current_per_page_label }} / page {{ icon("chevron-down", class="rio-chev") }}</button>
<div class="rio-dropdown-panel rio-menu" role="dialog" aria-label="Rows per page"><div class="rio-dropdown-section"><div class="rio-chip-row">{% for opt in per_page_options %}<a href="{{ opt.link }}" class="rio-chip{% if opt.is_active %} is-active{% endif %}">{{ opt.label }}</a>{% endfor %}</div></div></div>
</div>
{% endif %}
{% if search_query or active_filter_count > 0 %}<a class="rio-btn rio-btn--subtle rio-btn--lg" href="{{ clear_all_filters_link }}">{{ icon("rotate-ccw") }} Reset</a>{% endif %}
</div>
{% if active_filter_pills %}
<div class="rio-active-filters" role="region" aria-label="Active filters">
<span class="rio-active-filters-label">Active</span>
{% for pill in active_filter_pills %}<span class="rio-active-pill"><span class="rio-active-pill-key">{{ pill.label }}:</span> {{ pill.value_label }} <a href="{{ pill.remove_link }}" class="rio-active-pill-x" aria-label="Remove {{ pill.label }} filter">×</a></span>{% endfor %}
<a href="{{ clear_all_filters_link }}" class="rio-active-filters-clear">Clear all</a>
</div>
{% endif %}
{# ---- Board ---- #}
{% if not read_only %}
<form method="post" action="/admin/{{ admin_name }}/bulk_delete" class="rio-bulk-form" data-rio-bulk>
<input type="hidden" name="_csrf" value="{{ csrf_token }}">
<input type="hidden" name="_ids" value="" data-rio-bulk-ids>
<div class="rio-bulkbar" role="region" aria-live="polite" aria-label="Bulk actions">
<span class="rio-bulkbar-count"><strong data-rio-bulk-count>0</strong> selected</span>
<button type="button" class="rio-btn rio-btn--ghost rio-btn--sm" data-rio-bulk-clear>Clear</button>
<span style="margin-inline-start:auto;display:flex;gap:8px">
<button type="submit" class="rio-btn rio-btn--subtle rio-btn--sm" style="color:var(--rio-danger)">{{ icon("trash") }} Delete selected</button>
{% for btn in bulk_action_buttons %}<button type="submit" formaction="{{ btn.form_action }}" class="rio-btn rio-btn--secondary rio-btn--sm{% if btn.destructive %} rio-btn--danger{% endif %}">{{ btn.label }}</button>{% endfor %}
</span>
</div>
{% endif %}
<div class="rio-board">
{% if rows %}
<div style="overflow:auto">
<table class="rio-dtable">
<thead>
<tr>
{% if not read_only %}<th class="col-check"><input type="checkbox" class="rio-row-checkbox-all" data-rio-bulk-all aria-label="Select all"></th>{% endif %}
{% for f in fields %}<th class="rio-th--{{ f.kind }}{% if f.sort_active %} is-sort-{{ f.sort_active }}{% endif %}"><a href="{{ f.sort_link }}">{{ f.label }}{% if f.sort_active == "asc" %} ▲{% elif f.sort_active == "desc" %} ▼{% endif %}</a></th>{% endfor %}
<th class="col-act"> </th>
</tr>
</thead>
<tbody>
{% for row in rows %}
<tr>
{% if not read_only %}<td class="col-check"><input type="checkbox" class="rio-row-checkbox" data-rio-bulk-row value="{{ row.id }}" aria-label="Select row {{ row.id }}"></td>{% endif %}
{% for f in fields %}
<td class="rio-td--{{ f.kind }}">
{% if loop.first %}
<a class="rio-cell-primary" href="/admin/{{ admin_name }}/{{ row.id }}/edit">{% if row.highlights[f.name] %}{{ row.highlights[f.name]|safe }}{% else %}{{ row[f.name]|default(value=row.id) }}{% endif %}</a>
{% elif f.kind == "checkbox" %}
<span class="rio-pill rio-pill--{% if row[f.name] %}on{% else %}off{% endif %}">{% if row[f.name] %}Yes{% else %}No{% endif %}</span>
{% elif row.links[f.name] %}
<a class="rio-prod-name" href="{{ row.links[f.name] }}">{% if row.highlights[f.name] %}{{ row.highlights[f.name]|safe }}{% else %}{{ row[f.name]|default(value='') }}{% endif %}</a>
{% elif row.highlights[f.name] %}
{{ row.highlights[f.name]|safe }}
{% else %}
{{ row[f.name]|default(value='') }}
{% endif %}
</td>
{% endfor %}
<td class="col-act">
{% if not read_only %}
<span class="rio-row-actions">
<a class="rio-iconbtn rio-iconbtn--sm" href="/admin/{{ admin_name }}/{{ row.id }}/edit" aria-label="Edit">{{ icon("pencil") }}</a>
<a class="rio-iconbtn rio-iconbtn--sm" href="/admin/{{ admin_name }}/{{ row.id }}/delete" aria-label="Delete" style="color:var(--rio-danger)">{{ icon("trash") }}</a>
</span>
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="rio-board-foot">
<span style="font-size:13px;color:var(--rio-text-mute)">Showing <strong style="color:var(--rio-text-hi);font-weight:600">{{ rows|length }}</strong> of <strong style="color:var(--rio-text-hi);font-weight:600">{{ total_rows }}</strong> {{ display_name|lower }}</span>
{% if total_pages > 1 %}
<nav class="rio-pagination" aria-label="Pagination">
{% if prev_page_link %}<a class="rio-page" href="{{ prev_page_link }}" aria-label="Previous">{{ icon("arrow-left") }}</a>{% endif %}
{% for item in page_items %}{% if item.kind == "ellipsis" %}<span class="rio-page rio-page--ellipsis">…</span>{% elif item.is_active %}<span class="rio-page" aria-current="page">{{ item.number }}</span>{% else %}<a class="rio-page" href="{{ item.link }}">{{ item.number }}</a>{% endif %}{% endfor %}
{% if next_page_link %}<a class="rio-page rio-page--next" href="{{ next_page_link }}">Next {{ icon("arrow-right") }}</a>{% endif %}
</nav>
{% endif %}
</div>
{% else %}
<div class="rio-empty">
{{ icon("inbox") }}
<div class="rio-empty-title">No {{ display_name|lower }} yet</div>
<div>{% if read_only %}There are no records to display here.{% else %}Add the first {{ singular_name|lower }} to get started.{% endif %}</div>
{% if not read_only %}<div style="margin-block-start:14px"><a class="rio-btn rio-btn--primary rio-btn--md" href="/admin/{{ admin_name }}/new">{{ icon("plus") }} Add {{ singular_name }}</a></div>{% endif %}
</div>
{% endif %}
</div>
{% if not read_only %}</form>{% endif %}
{% endblock %}