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>
69 lines
3.6 KiB
HTML
69 lines
3.6 KiB
HTML
{# ansible/schedules.html — the Schedules tab (#5332): a verdict line, then
|
|
each schedule as one sentence (what runs where, how often, when next, how
|
|
it last went), failing first and paused last. The whole row opens the
|
|
schedule's page; Run now and Pause stay in the row. #}
|
|
{% extends "base.html" %}
|
|
{% from "_macros.html" import crumbs, page_header, status_badge, empty_state %}
|
|
{% from "ansible/_tabs.html" import ansible_tabs %}
|
|
{% from "ansible/_macros.html" import interval_words %}
|
|
{% block title %}Ansible Schedules — Steward{% endblock %}
|
|
{% block breadcrumb %}{{ crumbs([("Ansible", "/ansible/"), ("Schedules", "")]) }}{% endblock %}
|
|
{% block section_tabs %}{{ ansible_tabs("schedules") }}{% endblock %}
|
|
{% block content %}
|
|
{% set can_edit = session.user_role in ('operator', 'admin') %}
|
|
{% call page_header("Schedules") %}
|
|
{% if can_edit %}<a href="/ansible/schedules/new" class="btn">New schedule</a>{% endif %}
|
|
{% endcall %}
|
|
|
|
{% if not rows %}
|
|
<div class="card">{{ empty_state("Nothing runs on a schedule yet.", "New schedule" if can_edit else none, "/ansible/schedules/new" if can_edit else none) }}</div>
|
|
{% else %}
|
|
<p class="page-verdict">
|
|
{%- if failing %}<span class="tone-crit">{{ failing }} of {{ rows|length }} failing</span>
|
|
{%- else %}<span class="tone-ok">{{ rows|length }} schedule{{ 's' if rows|length != 1 }}, {{ 'none' if rows|length > 1 else 'not' }} failing</span>{% endif %}
|
|
{%- if paused %} · {{ paused }} paused{% endif %}
|
|
{%- if next %} · next: <a href="/ansible/schedules/{{ next.id }}">{{ next.name }}</a> {% if next.at %}{{ next.at|ago }}{% else %}due now{% endif %}{% endif -%}
|
|
</p>
|
|
<div class="card-flush">
|
|
<table class="table">
|
|
<thead><tr><th>Schedule</th><th>When</th><th>Last run</th><th></th></tr></thead>
|
|
<tbody>
|
|
{% for row in rows %}
|
|
{% set s = row.s %}
|
|
<tr class="row-link{% if not s.enabled %} row-off{% endif %}">
|
|
<td class="cell-name playbook-cell">
|
|
<a class="row-target" href="/ansible/schedules/{{ s.id }}">{{ s.name }}</a>
|
|
<div class="cell-sub"><span class="mono">{{ s.playbook_path }}</span> on {{ row.scope_label }}
|
|
{%- if (s.params or {}).get('check') %} · <span class="tone-info">dry run</span>{% endif %}</div>
|
|
</td>
|
|
<td class="nowrap">
|
|
{{ interval_words(s.interval_seconds) }}
|
|
<div class="cell-sub">{% if not s.enabled %}paused{% elif row.next and row.next.at %}next {{ row.next.at|ago }}{% else %}due now{% endif %}</div>
|
|
</td>
|
|
<td>
|
|
{%- if row.last_run %}{{ status_badge(row.last_run.status) }} <span class="tone-muted">{{ row.last_run.started_at|ago }}</span>
|
|
{%- elif not s.last_error %}<span class="tone-dim">never run</span>{% endif %}
|
|
{%- if s.last_error %}
|
|
{#- With a run beside it, the last firing was skipped because that run was
|
|
still going (#5158); without one, the firing couldn't start a run. #}
|
|
<div class="cell-sub {{ 'tone-muted' if row.last_run else 'tone-crit' }}" title="{{ s.last_error }}">{{ s.last_error }} · {{ s.last_run_at|ago }}</div>
|
|
{%- endif %}
|
|
</td>
|
|
<td class="td-actions">
|
|
{% if can_edit %}
|
|
<form method="post" action="/ansible/schedules/{{ s.id }}/run-now" class="inline-form">{{ csrf_field() }}
|
|
<button class="btn btn-sm btn-ghost" type="submit">Run now</button>
|
|
</form>
|
|
<form method="post" action="/ansible/schedules/{{ s.id }}/toggle" class="inline-form">{{ csrf_field() }}
|
|
<button class="btn btn-sm btn-ghost" type="submit">{{ "Pause" if s.enabled else "Resume" }}</button>
|
|
</form>
|
|
{% endif %}
|
|
</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
{% endif %}
|
|
{% endblock %}
|