(ui) Standardize list filter actions
Give run, snapshot, schedule, purged snapshot, and log filters the same responsive form layout with consistent Apply/Clear actions. Refs #25
This commit is contained in:
@@ -690,6 +690,13 @@
|
||||
.message.error { border-color: #e8b4b4; background: #fff0f0; color: var(--failed); }
|
||||
.message.warning { border-color: #e7cf8a; background: #fff8df; color: var(--running); }
|
||||
.form-grid { display: grid; gap: 15px; max-width: 720px; }
|
||||
.filter-form {
|
||||
align-items: end;
|
||||
display: grid;
|
||||
gap: 15px;
|
||||
grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
|
||||
max-width: none;
|
||||
}
|
||||
.form-actions {
|
||||
align-items: center;
|
||||
border-top: 1px solid var(--border);
|
||||
@@ -700,6 +707,13 @@
|
||||
padding-top: 15px;
|
||||
}
|
||||
.form-actions .button-link.secondary { margin-left: auto; }
|
||||
.filter-form .form-actions {
|
||||
border-top: 0;
|
||||
justify-content: flex-end;
|
||||
margin-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
.filter-form .form-actions .button-link.secondary { margin-left: 0; }
|
||||
.field { display: grid; gap: 6px; }
|
||||
.field label { font-weight: 700; }
|
||||
.field input[type="text"], .field input[type="number"], .field select, .field textarea {
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<section class="panel">
|
||||
<h2>Filter</h2>
|
||||
<form method="get" class="form-grid">
|
||||
<form method="get" class="filter-form">
|
||||
<div class="field">
|
||||
<label for="unit">Unit</label>
|
||||
<select id="unit" name="unit">
|
||||
@@ -54,8 +54,9 @@
|
||||
<label for="q">Message contains</label>
|
||||
<input id="q" name="q" value="{{ query }}">
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<button type="submit">Filter logs</button>
|
||||
<a class="button-link secondary" href="{% url 'logs' %}">Clear</a>
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<section class="panel">
|
||||
<h2>Filters</h2>
|
||||
<form method="get" class="form-grid">
|
||||
<form method="get" class="filter-form">
|
||||
<div class="field">
|
||||
<label for="host">Host</label>
|
||||
<select id="host" name="host">
|
||||
@@ -35,7 +35,7 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<button type="submit">Apply filters</button>
|
||||
<a class="button-link secondary" href="{% url 'purged_snapshots' %}">Clear</a>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<section class="panel">
|
||||
<h2>Filters</h2>
|
||||
<form method="get" class="form-grid">
|
||||
<form method="get" class="filter-form">
|
||||
<div class="field">
|
||||
<label for="status">Status</label>
|
||||
<select id="status" name="status">
|
||||
@@ -52,7 +52,7 @@
|
||||
<option value="reviewed" {% if selected_review == "reviewed" %}selected{% endif %}>Reviewed</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<button type="submit">Apply filters</button>
|
||||
<a class="button-link secondary" href="{% url 'runs_list' %}">Clear</a>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<section class="panel">
|
||||
<h2>Filters</h2>
|
||||
<form method="get" class="form-grid">
|
||||
<form method="get" class="filter-form">
|
||||
<div class="field">
|
||||
<label for="host">Host</label>
|
||||
<select id="host" name="host">
|
||||
@@ -42,7 +42,7 @@
|
||||
<option value="no" {% if selected_prune == "no" %}selected{% endif %}>Prune disabled</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<button type="submit">Apply filters</button>
|
||||
<a class="button-link secondary" href="{% url 'schedules_list' %}">Clear</a>
|
||||
</div>
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
<section class="panel">
|
||||
<h2>Filters</h2>
|
||||
<form method="get" class="form-grid">
|
||||
<form method="get" class="filter-form">
|
||||
<div class="field">
|
||||
<label for="host">Host</label>
|
||||
<select id="host" name="host">
|
||||
@@ -44,7 +44,7 @@
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<div class="form-actions">
|
||||
<button type="submit">Apply filters</button>
|
||||
<a class="button-link secondary" href="{% url 'snapshots_list' %}">Clear</a>
|
||||
</div>
|
||||
|
||||
@@ -233,6 +233,9 @@ class ViewTests(TestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Runs")
|
||||
self.assertContains(response, "Review queued, running, completed")
|
||||
self.assertContains(response, "Apply filters")
|
||||
self.assertContains(response, reverse("runs_list"))
|
||||
self.assertContains(response, "Clear")
|
||||
self.assertContains(response, f"Run {failed.id}")
|
||||
self.assertContains(response, "web-01")
|
||||
self.assertContains(response, "needed")
|
||||
@@ -275,6 +278,9 @@ class ViewTests(TestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Snapshots")
|
||||
self.assertContains(response, "Browse discovered scheduled, manual, and incomplete snapshots")
|
||||
self.assertContains(response, "Apply filters")
|
||||
self.assertContains(response, reverse("snapshots_list"))
|
||||
self.assertContains(response, "Clear")
|
||||
self.assertContains(response, manual.dirname)
|
||||
self.assertContains(response, "web-01")
|
||||
self.assertNotContains(response, scheduled.dirname)
|
||||
@@ -291,6 +297,9 @@ class ViewTests(TestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Schedules")
|
||||
self.assertContains(response, "Review configured backup schedules")
|
||||
self.assertContains(response, "Apply filters")
|
||||
self.assertContains(response, reverse("schedules_list"))
|
||||
self.assertContains(response, "Clear")
|
||||
self.assertContains(response, "web-01")
|
||||
self.assertContains(response, "15 2 * * *")
|
||||
self.assertContains(response, "success")
|
||||
@@ -428,6 +437,9 @@ class ViewTests(TestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Logs")
|
||||
self.assertContains(response, "Filter pobsync service logs")
|
||||
self.assertContains(response, "Filter logs")
|
||||
self.assertContains(response, reverse("logs"))
|
||||
self.assertContains(response, "Clear")
|
||||
self.assertContains(response, "web-01 failed backup run 12")
|
||||
self.assertNotContains(response, "web-02 failed backup run 12")
|
||||
self.assertNotContains(response, "started")
|
||||
@@ -458,6 +470,9 @@ class ViewTests(TestCase):
|
||||
self.assertEqual(response.status_code, 200)
|
||||
self.assertContains(response, "Purged Snapshots")
|
||||
self.assertContains(response, "Audit trail for snapshots removed")
|
||||
self.assertContains(response, "Apply filters")
|
||||
self.assertContains(response, reverse("purged_snapshots"))
|
||||
self.assertContains(response, "Clear")
|
||||
self.assertContains(response, "20260518-021500Z__OLDSNAP")
|
||||
self.assertContains(response, "outside retention policy")
|
||||
self.assertContains(response, "Scheduled")
|
||||
|
||||
Reference in New Issue
Block a user