{# One template for every resource list. Applications, services, sites and databases are all the same shape: a dense list of rows carrying a state rail. Rendering them from one template is what keeps them looking and behaving alike, so an operator learns the screen once. The endpoints come from the context, already built. A template that concatenates "/api/" with a resource kind is a template that can be wrong about a route, and a button that posts to an address which does not exist is worse than no button. #} {% extends "base.html" %} {% import "_macros.html" as m %} {% block title %}{{ title }}{% endblock %} {% block content %} {% call m.page_head(title, subtitle) %} {% if action_label %} {{ action_label }} {% endif %} {% endcall %} {% if rows %}
{% for item in rows %} {% call m.row(item.domain, item.state, item.meta, item.href, "row-" ~ item.id, none, item.state_text) %} {% if item.log_url %} {{ m.follow_button("Logs", item.domain, item.log_url) }} {% endif %} {# Places to go, not verbs to fire: the unit and config editors are pages, so they travel as links the browser can open like any other, not as htmx posts. #} {% for link in item.links or [] %} {{ link.label }} {% endfor %} {% if item.restart_endpoint %} {{ m.action_button("Restart", item.restart_endpoint, none, "Restarted " ~ item.domain) }} {% endif %} {# What this record can actually be told to do right now. The shaper decides: a running unit offers Stop, a stopped one offers Start, and a row never offers a verb that would be a no-op. #} {% for action in item.actions or [] %} {{ m.action_button(action.label, action.endpoint, action.confirm, action.done) }} {% endfor %} {{ m.danger_button("Delete", item.delete_endpoint, item.domain, item.delete_consequence) }} {% endcall %} {% endfor %}
{% else %} {{ m.empty(empty_title, empty_body, action_label, action_href, command) }} {% endif %} {% endblock %}