(ui) Extend page headers across utility views
Apply the shared page-header pattern to configuration, access, operations, retention, log, and changelog pages so the control panel uses one consistent title, context, and action structure. Add representative view assertions for the new page context on utility pages. Refs #28
This commit is contained in:
@@ -3,11 +3,16 @@
|
|||||||
{% block title %}Changelog - pobsync{% endblock %}
|
{% block title %}Changelog - pobsync{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<header class="page-header">
|
||||||
|
<div class="page-title">
|
||||||
|
<div class="page-kicker">Release notes</div>
|
||||||
<h1>Changelog</h1>
|
<h1>Changelog</h1>
|
||||||
|
<div class="page-subtitle">Installed release notes rendered from the repository changelog.</div>
|
||||||
|
</div>
|
||||||
<section class="actions" aria-label="Changelog actions">
|
<section class="actions" aria-label="Changelog actions">
|
||||||
<a class="button-link secondary" href="{% url 'dashboard' %}">Back to dashboard</a>
|
<a class="button-link secondary" href="{% url 'dashboard' %}">Back to dashboard</a>
|
||||||
</section>
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<div class="stack spaced">
|
<div class="stack spaced">
|
||||||
|
|||||||
@@ -3,11 +3,16 @@
|
|||||||
{% block title %}Global Config{% endblock %}
|
{% block title %}Global Config{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<header class="page-header">
|
||||||
|
<div class="page-title">
|
||||||
|
<div class="page-kicker">Configuration</div>
|
||||||
<h1>{% if global_config %}Global Config{% else %}Create Global Config{% endif %}</h1>
|
<h1>{% if global_config %}Global Config{% else %}Create Global Config{% endif %}</h1>
|
||||||
|
<div class="page-subtitle">Defaults used by hosts unless a host overrides them explicitly.</div>
|
||||||
|
</div>
|
||||||
<section class="actions" aria-label="Global config actions">
|
<section class="actions" aria-label="Global config actions">
|
||||||
<a class="button-link" href="{% url 'dashboard' %}">Back to dashboard</a>
|
<a class="button-link" href="{% url 'dashboard' %}">Back to dashboard</a>
|
||||||
</section>
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<h2>{% if global_config %}Edit Global Config{% else %}Create Global Config{% endif %}</h2>
|
<h2>{% if global_config %}Edit Global Config{% else %}Create Global Config{% endif %}</h2>
|
||||||
|
|||||||
@@ -3,8 +3,12 @@
|
|||||||
{% block title %}{% if host %}Config | {{ host.host }}{% else %}New Host{% endif %}{% endblock %}
|
{% block title %}{% if host %}Config | {{ host.host }}{% else %}New Host{% endif %}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<header class="page-header">
|
||||||
|
<div class="page-title">
|
||||||
|
<div class="page-kicker">Configuration</div>
|
||||||
<h1>{% if host %}Config: {{ host.host }}{% else %}New Host{% endif %}</h1>
|
<h1>{% if host %}Config: {{ host.host }}{% else %}New Host{% endif %}</h1>
|
||||||
|
<div class="page-subtitle">Host-specific backup, retention, SSH, include, and exclude settings.</div>
|
||||||
|
</div>
|
||||||
<section class="actions" aria-label="Config actions">
|
<section class="actions" aria-label="Config actions">
|
||||||
{% if host %}
|
{% if host %}
|
||||||
<a class="button-link" href="{% url 'host_detail' host.host %}">Back to host</a>
|
<a class="button-link" href="{% url 'host_detail' host.host %}">Back to host</a>
|
||||||
@@ -12,6 +16,7 @@
|
|||||||
<a class="button-link" href="{% url 'dashboard' %}">Back to dashboard</a>
|
<a class="button-link" href="{% url 'dashboard' %}">Back to dashboard</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</section>
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<h2>{% if host %}Edit Host Config{% else %}Create Host Config{% endif %}</h2>
|
<h2>{% if host %}Edit Host Config{% else %}Create Host Config{% endif %}</h2>
|
||||||
|
|||||||
@@ -3,11 +3,16 @@
|
|||||||
{% block title %}Logs | pobsync{% endblock %}
|
{% block title %}Logs | pobsync{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<header class="page-header">
|
||||||
|
<div class="page-title">
|
||||||
|
<div class="page-kicker">Operations</div>
|
||||||
<h1>Logs</h1>
|
<h1>Logs</h1>
|
||||||
|
<div class="page-subtitle">Filter pobsync service logs by unit, priority, host, run, or message content.</div>
|
||||||
|
</div>
|
||||||
<section class="actions" aria-label="Log actions">
|
<section class="actions" aria-label="Log actions">
|
||||||
<a class="button-link secondary" href="{% url 'dashboard' %}">Back to dashboard</a>
|
<a class="button-link secondary" href="{% url 'dashboard' %}">Back to dashboard</a>
|
||||||
</section>
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<h2>Filter</h2>
|
<h2>Filter</h2>
|
||||||
|
|||||||
@@ -3,11 +3,16 @@
|
|||||||
{% block title %}Purged Snapshots | pobsync{% endblock %}
|
{% block title %}Purged Snapshots | pobsync{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<header class="page-header">
|
||||||
|
<div class="page-title">
|
||||||
|
<div class="page-kicker">Retention</div>
|
||||||
<h1>Purged Snapshots</h1>
|
<h1>Purged Snapshots</h1>
|
||||||
|
<div class="page-subtitle">Audit trail for snapshots removed by retention or manual purge actions.</div>
|
||||||
|
</div>
|
||||||
<section class="actions" aria-label="Purged snapshot actions">
|
<section class="actions" aria-label="Purged snapshot actions">
|
||||||
<a class="button-link secondary" href="{% url 'dashboard' %}">Back to dashboard</a>
|
<a class="button-link secondary" href="{% url 'dashboard' %}">Back to dashboard</a>
|
||||||
</section>
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<h2>Filters</h2>
|
<h2>Filters</h2>
|
||||||
|
|||||||
@@ -3,11 +3,16 @@
|
|||||||
{% block title %}Schedule | {{ host.host }}{% endblock %}
|
{% block title %}Schedule | {{ host.host }}{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<h1>Schedule: {{ host.host }}</h1>
|
<header class="page-header">
|
||||||
|
<div class="page-title">
|
||||||
|
<div class="page-kicker">Schedule</div>
|
||||||
|
<h1>{{ host.host }}</h1>
|
||||||
|
<div class="page-subtitle">Automatic backup timing and scheduled prune behavior for this host.</div>
|
||||||
|
</div>
|
||||||
<section class="actions" aria-label="Schedule actions">
|
<section class="actions" aria-label="Schedule actions">
|
||||||
<a class="button-link" href="{% url 'host_detail' host.host %}">Back to host</a>
|
<a class="button-link" href="{% url 'host_detail' host.host %}">Back to host</a>
|
||||||
</section>
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<h2>{% if schedule %}Edit Schedule{% else %}Create Schedule{% endif %}</h2>
|
<h2>{% if schedule %}Edit Schedule{% else %}Create Schedule{% endif %}</h2>
|
||||||
|
|||||||
@@ -3,11 +3,16 @@
|
|||||||
{% block title %}Self Check | pobsync{% endblock %}
|
{% block title %}Self Check | pobsync{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<header class="page-header">
|
||||||
|
<div class="page-title">
|
||||||
|
<div class="page-kicker">Operations</div>
|
||||||
<h1>Self Check</h1>
|
<h1>Self Check</h1>
|
||||||
|
<div class="page-subtitle">Runtime, filesystem, service, and configuration checks for this pobsync installation.</div>
|
||||||
|
</div>
|
||||||
<section class="actions" aria-label="Self check actions">
|
<section class="actions" aria-label="Self check actions">
|
||||||
<a class="button-link secondary" href="{% url 'dashboard' %}">Back to dashboard</a>
|
<a class="button-link secondary" href="{% url 'dashboard' %}">Back to dashboard</a>
|
||||||
</section>
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="grid" aria-label="Self check summary">
|
<section class="grid" aria-label="Self check summary">
|
||||||
<div class="metric"><div class="label">OK</div><div class="value">{{ summary.ok }}</div></div>
|
<div class="metric"><div class="label">OK</div><div class="value">{{ summary.ok }}</div></div>
|
||||||
|
|||||||
@@ -3,11 +3,16 @@
|
|||||||
{% block title %}{% if credential %}SSH Key | {{ credential.name }}{% else %}New SSH Key{% endif %} | pobsync{% endblock %}
|
{% block title %}{% if credential %}SSH Key | {{ credential.name }}{% else %}New SSH Key{% endif %} | pobsync{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<header class="page-header">
|
||||||
|
<div class="page-title">
|
||||||
|
<div class="page-kicker">Access</div>
|
||||||
<h1>{% if credential %}SSH Key: {{ credential.name }}{% else %}New SSH Key{% endif %}</h1>
|
<h1>{% if credential %}SSH Key: {{ credential.name }}{% else %}New SSH Key{% endif %}</h1>
|
||||||
|
<div class="page-subtitle">{% if credential %}Review key metadata, known hosts, and deletion safety for this credential.{% else %}Register an existing private key for use by pobsync backups.{% endif %}</div>
|
||||||
|
</div>
|
||||||
<section class="actions" aria-label="SSH key form actions">
|
<section class="actions" aria-label="SSH key form actions">
|
||||||
<a class="button-link" href="{% url 'ssh_credentials' %}">Back to SSH keys</a>
|
<a class="button-link" href="{% url 'ssh_credentials' %}">Back to SSH keys</a>
|
||||||
</section>
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<h2>{% if credential %}Edit SSH Credential{% else %}Create SSH Credential{% endif %}</h2>
|
<h2>{% if credential %}Edit SSH Credential{% else %}Create SSH Credential{% endif %}</h2>
|
||||||
|
|||||||
@@ -3,11 +3,16 @@
|
|||||||
{% block title %}Generate SSH Key | pobsync{% endblock %}
|
{% block title %}Generate SSH Key | pobsync{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<header class="page-header">
|
||||||
|
<div class="page-title">
|
||||||
|
<div class="page-kicker">Access</div>
|
||||||
<h1>Generate SSH Key</h1>
|
<h1>Generate SSH Key</h1>
|
||||||
|
<div class="page-subtitle">Create a pobsync-managed SSH key pair for one or more backup targets.</div>
|
||||||
|
</div>
|
||||||
<section class="actions" aria-label="SSH key form actions">
|
<section class="actions" aria-label="SSH key form actions">
|
||||||
<a class="button-link" href="{% url 'ssh_credentials' %}">Back to SSH keys</a>
|
<a class="button-link" href="{% url 'ssh_credentials' %}">Back to SSH keys</a>
|
||||||
</section>
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<h2>Create Key Pair</h2>
|
<h2>Create Key Pair</h2>
|
||||||
|
|||||||
@@ -3,13 +3,18 @@
|
|||||||
{% block title %}SSH Keys | pobsync{% endblock %}
|
{% block title %}SSH Keys | pobsync{% endblock %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
|
<header class="page-header">
|
||||||
|
<div class="page-title">
|
||||||
|
<div class="page-kicker">Access</div>
|
||||||
<h1>SSH Keys</h1>
|
<h1>SSH Keys</h1>
|
||||||
|
<div class="page-subtitle">Manage the key pairs pobsync uses to reach backup targets.</div>
|
||||||
|
</div>
|
||||||
<section class="actions" aria-label="SSH key actions">
|
<section class="actions" aria-label="SSH key actions">
|
||||||
<a class="button-link" href="{% url 'generate_ssh_credential' %}">Generate SSH key</a>
|
<a class="button-link" href="{% url 'generate_ssh_credential' %}">Generate SSH key</a>
|
||||||
<a class="button-link secondary" href="{% url 'create_ssh_credential' %}">Add existing key</a>
|
<a class="button-link secondary" href="{% url 'create_ssh_credential' %}">Add existing key</a>
|
||||||
<a class="button-link secondary" href="{% url 'dashboard' %}">Back to dashboard</a>
|
<a class="button-link secondary" href="{% url 'dashboard' %}">Back to dashboard</a>
|
||||||
</section>
|
</section>
|
||||||
|
</header>
|
||||||
|
|
||||||
<section class="panel">
|
<section class="panel">
|
||||||
<h2>Credentials</h2>
|
<h2>Credentials</h2>
|
||||||
|
|||||||
@@ -295,6 +295,7 @@ class ViewTests(TestCase):
|
|||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertContains(response, "Self Check")
|
self.assertContains(response, "Self Check")
|
||||||
|
self.assertContains(response, "Runtime, filesystem, service, and configuration checks")
|
||||||
self.assertContains(response, "Django debug")
|
self.assertContains(response, "Django debug")
|
||||||
self.assertContains(response, "Database connection")
|
self.assertContains(response, "Database connection")
|
||||||
self.assertContains(response, "State root")
|
self.assertContains(response, "State root")
|
||||||
@@ -329,6 +330,7 @@ class ViewTests(TestCase):
|
|||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertContains(response, "Logs")
|
self.assertContains(response, "Logs")
|
||||||
|
self.assertContains(response, "Filter pobsync service logs")
|
||||||
self.assertContains(response, "web-01 failed backup run 12")
|
self.assertContains(response, "web-01 failed backup run 12")
|
||||||
self.assertNotContains(response, "web-02 failed backup run 12")
|
self.assertNotContains(response, "web-02 failed backup run 12")
|
||||||
self.assertNotContains(response, "started")
|
self.assertNotContains(response, "started")
|
||||||
@@ -358,6 +360,7 @@ class ViewTests(TestCase):
|
|||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertContains(response, "Purged Snapshots")
|
self.assertContains(response, "Purged Snapshots")
|
||||||
|
self.assertContains(response, "Audit trail for snapshots removed")
|
||||||
self.assertContains(response, "20260518-021500Z__OLDSNAP")
|
self.assertContains(response, "20260518-021500Z__OLDSNAP")
|
||||||
self.assertContains(response, "outside retention policy")
|
self.assertContains(response, "outside retention policy")
|
||||||
self.assertContains(response, "Scheduled")
|
self.assertContains(response, "Scheduled")
|
||||||
@@ -412,6 +415,7 @@ class ViewTests(TestCase):
|
|||||||
)
|
)
|
||||||
|
|
||||||
self.assertRedirects(response, reverse("ssh_credentials"))
|
self.assertRedirects(response, reverse("ssh_credentials"))
|
||||||
|
self.assertContains(response, "Manage the key pairs pobsync uses")
|
||||||
self.assertContains(response, "SSH credential saved for backup-key.")
|
self.assertContains(response, "SSH credential saved for backup-key.")
|
||||||
self.assertContains(response, "backup-key")
|
self.assertContains(response, "backup-key")
|
||||||
credential = SshCredential.objects.get(name="backup-key")
|
credential = SshCredential.objects.get(name="backup-key")
|
||||||
@@ -641,6 +645,7 @@ class ViewTests(TestCase):
|
|||||||
response = self.client.get(reverse("edit_global_config"))
|
response = self.client.get(reverse("edit_global_config"))
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertContains(response, "Defaults used by hosts unless a host overrides them")
|
||||||
self.assertContains(response, f'value="{credential.id}" selected')
|
self.assertContains(response, f'value="{credential.id}" selected')
|
||||||
self.assertContains(response, "--archive")
|
self.assertContains(response, "--archive")
|
||||||
self.assertContains(response, "/proc/***")
|
self.assertContains(response, "/proc/***")
|
||||||
@@ -2031,6 +2036,7 @@ class ViewTests(TestCase):
|
|||||||
response = self.client.get(reverse("edit_host_schedule", args=[host.host]))
|
response = self.client.get(reverse("edit_host_schedule", args=[host.host]))
|
||||||
|
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertContains(response, "Automatic backup timing and scheduled prune behavior")
|
||||||
self.assertContains(response, "Create Schedule")
|
self.assertContains(response, "Create Schedule")
|
||||||
self.assertContains(response, "Schedule expression")
|
self.assertContains(response, "Schedule expression")
|
||||||
self.assertContains(response, "evaluated by the pobsync scheduler service")
|
self.assertContains(response, "evaluated by the pobsync scheduler service")
|
||||||
|
|||||||
Reference in New Issue
Block a user