Files
FabledSteward/steward/templates/ansible/playbook.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

82 lines
3.9 KiB
HTML

{# ansible/playbook.html — one playbook's page (#5331): what it says it does
and how it last ran, the form that runs it (operators), the schedules that
use it, its recent runs, then the playbook itself, folded. #}
{% extends "base.html" %}
{% from "_macros.html" import crumbs, page_header, status_badge %}
{% from "ansible/_tabs.html" import ansible_tabs %}
{% from "ansible/_macros.html" import interval_words %}
{% block title %}{{ playbook_path }} — Steward{% endblock %}
{% block breadcrumb %}{{ crumbs([("Ansible", "/ansible/"), ("Playbooks", "/ansible/playbooks"), (playbook_path, "")]) }}{% endblock %}
{% block section_tabs %}{{ ansible_tabs("playbooks") }}{% endblock %}
{% block content %}
{% set can_run = session.user_role in ('operator', 'admin') %}
{% call page_header(playbook_path) %}
{% if editable and session.user_role == 'admin' %}
<a href="/ansible/playbooks/edit/{{ source_name }}/{{ playbook_path }}" class="btn btn-sm btn-ghost">Edit</a>
<form method="post" action="/ansible/playbooks/delete"
data-confirm="Delete {{ playbook_path }}? The file is removed from {{ source_name }}; its past runs stay in the list.">{{ csrf_field() }}
<input type="hidden" name="source_name" value="{{ source_name }}">
<input type="hidden" name="playbook_path" value="{{ playbook_path }}">
<button type="submit" class="btn btn-sm btn-danger">Delete</button>
</form>
{% endif %}
{% endcall %}
<p class="page-verdict">
{%- if category %}<span class="chip">{{ category }}</span> {% endif -%}
{{ description or "It says nothing about what it does." }}
{%- if confirm %} · <span class="tone-warn">flagged destructive by its author: a real run asks you to confirm</span>{% endif %}
· from <span class="mono">{{ source_name }}</span>
{%- if runs %} · last ran {{ runs[0].run.started_at|ago }} {{ status_badge(runs[0].run.status) }}{% else %} · never run{% endif -%}
</p>
{% if can_run %}
<section class="card" aria-labelledby="pb-run">
<h2 id="pb-run" class="section-title">Run it</h2>
{% include "ansible/_run_form.html" %}
</section>
{% endif %}
<section class="card-flush" aria-labelledby="pb-schedules">
<h2 id="pb-schedules" class="table-caption">Schedules
{%- if schedules %} <span class="tone-muted">{{ schedules|length }}</span>{% endif %}
{%- if can_run %} <a class="field-hint" href="/ansible/schedules/new?source={{ source_name|urlencode }}&amp;playbook={{ playbook_path|urlencode }}">Schedule it →</a>{% endif %}</h2>
{% if schedules %}
<table class="table">
<tbody>
{% for row in schedules %}{% set s = row.s %}
<tr class="row-link{% if not s.enabled %} row-off{% endif %}">
<td class="cell-name"><a class="row-target" href="/ansible/schedules/{{ s.id }}">{{ s.name }}</a></td>
<td>on {{ row.scope_label }} · {{ interval_words(s.interval_seconds) }}</td>
<td class="nowrap">{% if not s.enabled %}<span class="tone-dim">paused</span>
{%- elif row.next and row.next.at %}next {{ row.next.at|ago }}{% else %}due now{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% else %}
<p class="field-hint card-flush-note">No schedule runs it.</p>
{% endif %}
</section>
<section class="card-flush" aria-labelledby="pb-runs">
<h2 id="pb-runs" class="table-caption">Recent runs
{%- if runs %} <a class="field-hint" href="/ansible/?q={{ playbook_path|urlencode }}">All its runs →</a>{% endif %}</h2>
{% if runs %}
<table class="table">
<thead><tr><th>Run</th><th>Result</th><th>Started by</th><th>Started</th><th class="num">Took</th></tr></thead>
<tbody>
{% with compact=true, more_url=none %}{% include "ansible/_runs_page.html" %}{% endwith %}
</tbody>
</table>
{% else %}
<p class="field-hint card-flush-note">It has not been run yet.</p>
{% endif %}
</section>
<details class="card playbook-source">
<summary class="section-title">The playbook</summary>
<pre class="run-log">{{ contents }}</pre>
</details>
{% endblock %}