Files
FabledSteward/steward/templates/ansible/playbooks.html
T
bvandeusenandClaude Opus 5.5 955450d33f
CI / lint (push) Successful in 2s
CI / integration (push) Successful in 55s
CI / unit (push) Successful in 1m22s
CI / publish (push) Successful in 1m36s
fix(ui): section tabs above the breadcrumb, so the Ansible tab strip holds still (#5214)
The tabs were drawn in each page's content block, which base.html renders
after the breadcrumb, so on every nested Ansible page the strip moved down a
line. base.html now has a section_tabs block above the breadcrumb, and every
Ansible page fills it. A guard in test_breadcrumbs.py fails any page that calls
a tabs macro outside that block.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 06:28:02 -04:00

58 lines
2.8 KiB
HTML

{# ansible/playbooks.html — the Playbooks tab (#5331): every playbook across
its sources in one list, what each says it does and how it last ran; the
whole row opens the playbook's page, where it is run. A source with no
playbooks is one quiet line under the list. #}
{% extends "base.html" %}
{% from "_macros.html" import crumbs, page_header, status_badge, empty_state %}
{% from "ansible/_tabs.html" import ansible_tabs %}
{% block title %}Playbooks — Steward{% endblock %}
{% block breadcrumb %}{{ crumbs([("Ansible", "/ansible/"), ("Playbooks", "")]) }}{% endblock %}
{% block section_tabs %}{{ ansible_tabs("playbooks") }}{% endblock %}
{% block content %}
{% call page_header("Playbooks") %}
{% if can_add %}<a href="/ansible/playbooks/new" class="btn">New playbook</a>{% endif %}
{% endcall %}
{% if not sources %}
<div class="card">{{ empty_state("No playbook sources are set up.", "Add one in Settings", "/settings/ansible/") }}</div>
{% else %}
{% set n_src = rows|map(attribute="source")|unique|list|length %}
{% set n_bad = rows|selectattr("confirm")|list|length %}
<p class="page-verdict">
{{- rows|length }} playbook{{ 's' if rows|length != 1 }}{% if n_src %} from {{ n_src }} source{{ 's' if n_src != 1 }}{% endif %}
{%- if n_bad %} · <span class="tone-warn">{{ n_bad }} flagged destructive by {{ 'their authors' if n_bad > 1 else 'its author' }}</span>{% endif -%}
</p>
{% if rows %}
<div class="card-flush">
<table class="table">
<thead><tr><th>Playbook</th><th>Source</th><th>Last run</th></tr></thead>
<tbody>
{% for r in rows %}
<tr class="row-link">
<td class="cell-name playbook-cell">
<a class="row-target mono" href="/ansible/playbooks/{{ r.source }}/{{ r.path }}" title="{{ r.path }}">{{ r.path }}</a>
{% if r.description %}<div class="cell-sub" title="{{ r.description }}">{{ r.description }}</div>{% endif %}
</td>
<td>
<span class="tone-muted">{{ r.source }}</span>
{%- if r.category %} <span class="chip">{{ r.category }}</span>{% endif %}
{%- if r.confirm %} {{ status_badge('warn', 'destructive', 'Its author flagged it as making significant or destructive changes: a real run asks for confirmation') }}{% endif %}
</td>
<td class="nowrap">
{%- if r.last %}{{ status_badge(r.last.status) }} <span class="tone-muted">{{ r.last.started_at|ago }}</span>
{%- else %}<span class="tone-dim">never run</span>{% endif -%}
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
{% for s in empty_sources %}
<p class="field-hint">{{ s.name }} (<span class="mono">{{ s.path }}</span>) has no playbooks yet.
{%- if can_add and s.editable %} <a href="/ansible/playbooks/new">Write one</a>{% endif %}</p>
{% endfor %}
{% endif %}
{% endblock %}