Make dashboard cards link to operational lists #31

Merged
parkel merged 3 commits from issue-23-dashboard-list-pages into master 2026-05-21 12:49:15 +02:00
3 changed files with 35 additions and 11 deletions
Showing only changes of commit 67d1af0baa - Show all commits

View File

@@ -297,6 +297,22 @@
.status-summary.warning, .status-summary.warning,
.status-summary.running { border-color: #e7cf8a; background: #fffaf0; color: var(--running); } .status-summary.running { border-color: #e7cf8a; background: #fffaf0; color: var(--running); }
.status-summary.queued { border-color: #b5cdea; background: #eef6ff; color: var(--link); } .status-summary.queued { border-color: #b5cdea; background: #eef6ff; color: var(--link); }
a.status-summary {
color: inherit;
text-decoration: none;
transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease;
}
a.status-summary:hover {
border-color: var(--border-strong);
box-shadow: var(--shadow-sm);
transform: translateY(-1px);
}
.status-summary .summary-action {
color: var(--muted-strong);
font-size: 12px;
font-weight: 650;
margin-left: auto;
}
.operator-state { .operator-state {
align-items: center; align-items: center;
display: flex; display: flex;

View File

@@ -43,33 +43,37 @@
<a class="metric metric-link {% if counts.failed_runs %}failed{% endif %}" href="{% url 'runs_list' %}?status=failed&amp;review=needed"><div class="label">Failed</div><div class="value">{{ counts.failed_runs }}</div></a> <a class="metric metric-link {% if counts.failed_runs %}failed{% endif %}" href="{% url 'runs_list' %}?status=failed&amp;review=needed"><div class="label">Failed</div><div class="value">{{ counts.failed_runs }}</div></a>
</section> </section>
<section class="panel" id="hosts"> <section class="panel">
<h2>Operational Status</h2> <h2>Operational Status</h2>
{% if counts.failed_runs or counts.warning_runs or counts.running_runs or counts.queued_runs %} {% if counts.failed_runs or counts.warning_runs or counts.running_runs or counts.queued_runs %}
<div class="status-overview"> <div class="status-overview">
{% if counts.failed_runs %} {% if counts.failed_runs %}
<div class="status-summary failed"> <a class="status-summary failed" href="{% url 'runs_list' %}?status=failed&amp;review=needed">
<span class="status failed">failed</span> <span class="status failed">failed</span>
<strong>{{ counts.failed_runs }} failed run{{ counts.failed_runs|pluralize }} need{{ counts.failed_runs|pluralize:"s," }} review.</strong> <strong>{{ counts.failed_runs }} failed run{{ counts.failed_runs|pluralize }} need{{ counts.failed_runs|pluralize:"s," }} review.</strong>
</div> <span class="summary-action">Review failed runs</span>
</a>
{% endif %} {% endif %}
{% if counts.warning_runs %} {% if counts.warning_runs %}
<div class="status-summary warning"> <a class="status-summary warning" href="{% url 'runs_list' %}?status=warning&amp;review=needed">
<span class="status warning">warning</span> <span class="status warning">warning</span>
<strong>{{ counts.warning_runs }} run{{ counts.warning_runs|pluralize }} completed with warnings.</strong> <strong>{{ counts.warning_runs }} run{{ counts.warning_runs|pluralize }} completed with warnings.</strong>
</div> <span class="summary-action">Review warnings</span>
</a>
{% endif %} {% endif %}
{% if counts.running_runs %} {% if counts.running_runs %}
<div class="status-summary running"> <a class="status-summary running" href="{% url 'runs_list' %}?status=running">
<span class="status running">running</span> <span class="status running">running</span>
<strong>{{ counts.running_runs }} backup run{{ counts.running_runs|pluralize }} in progress.</strong> <strong>{{ counts.running_runs }} backup run{{ counts.running_runs|pluralize }} in progress.</strong>
</div> <span class="summary-action">View running runs</span>
</a>
{% endif %} {% endif %}
{% if counts.queued_runs %} {% if counts.queued_runs %}
<div class="status-summary queued"> <a class="status-summary queued" href="{% url 'runs_list' %}?status=queued">
<span class="status queued">queued</span> <span class="status queued">queued</span>
<strong>{{ counts.queued_runs }} backup run{{ counts.queued_runs|pluralize }} waiting for the worker.</strong> <strong>{{ counts.queued_runs }} backup run{{ counts.queued_runs|pluralize }} waiting for the worker.</strong>
</div> <span class="summary-action">View queued runs</span>
</a>
{% endif %} {% endif %}
</div> </div>
{% elif counts.hosts %} {% elif counts.hosts %}
@@ -79,7 +83,7 @@
{% endif %} {% endif %}
</section> </section>
<section class="panel"> <section class="panel" id="hosts">
<h2>Backup Trends</h2> <h2>Backup Trends</h2>
{% if stats_summary.runs_sampled %} {% if stats_summary.runs_sampled %}
<div class="insight-grid" aria-label="Backup trends"> <div class="insight-grid" aria-label="Backup trends">

View File

@@ -125,6 +125,10 @@ class ViewTests(TestCase):
self.assertContains(response, "1 run completed with warnings.") self.assertContains(response, "1 run completed with warnings.")
self.assertContains(response, "1 backup run in progress.") self.assertContains(response, "1 backup run in progress.")
self.assertContains(response, "1 backup run waiting for the worker.") self.assertContains(response, "1 backup run waiting for the worker.")
self.assertContains(response, "Review failed runs")
self.assertContains(response, "Review warnings")
self.assertContains(response, "View running runs")
self.assertContains(response, "View queued runs")
self.assertContains(response, f'href="{reverse("runs_list")}"', html=False) self.assertContains(response, f'href="{reverse("runs_list")}"', html=False)
self.assertContains(response, f'href="{reverse("runs_list")}?status=queued"', html=False) self.assertContains(response, f'href="{reverse("runs_list")}?status=queued"', html=False)
self.assertContains(response, f'href="{reverse("runs_list")}?status=running"', html=False) self.assertContains(response, f'href="{reverse("runs_list")}?status=running"', html=False)