{# Reusable Jinja macros for paginated + sortable tables on /ui/. Ported from bty's ``ui/_table_macros.html`` so the nbdmux operator UI shares the same header-sort + inline pagination shape bty uses. Callers pass a ``SortState`` + ``PageState`` from ``nbdmux._table_state`` plus a ``preserved`` query-param dict so an active filter survives a header-click or pagination click. #} {% macro sort_header(label, column, sort, preserved, th_attrs='') %} {% set qs = build_query_string( preserved, {'sort': column, 'dir': sort.next_direction(column), 'page': None} ) %} {{ label }} {% if sort.is_active(column) %} {% else %} {% endif %} {% endmacro %} {% macro pagination_inline(page, preserved, label='rows') %}
{% if page.total == 0 %} No {{ label }}. {% else %} {{ page.first_row }}{{ page.last_row }} of {{ page.total }} {{ label }} {% endif %} {% if page.last_page > 1 %} {% endif %}
{% for k, v in preserved.items() %} {% if v and k not in ('per_page', 'page') %} {% endif %} {% endfor %}
{% endmacro %} {# Filter form snippet for the card-header toolbar. Emits hidden inputs for the currently-active sort so a filter submit preserves it, plus a Clear link when the filter is populated. #} {% macro filter_form(q, sort, page, per_page_choices, input_id, placeholder='Filter (substring on any column)') %}
{% if sort.column %}{% endif %} {% if sort.direction %}{% endif %} {% if page.per_page != per_page_choices[0] %}{% endif %} {% if q %} Clear {% endif %}
{% endmacro %}