diff --git a/src/pobsync_backend/templates/pobsync_backend/base.html b/src/pobsync_backend/templates/pobsync_backend/base.html index 7a343fe..9a670b1 100644 --- a/src/pobsync_backend/templates/pobsync_backend/base.html +++ b/src/pobsync_backend/templates/pobsync_backend/base.html @@ -179,10 +179,23 @@ box-shadow: var(--shadow); transform: translateY(-1px); } - .metric-link:focus-visible { - outline: 3px solid #93c5fd; - outline-offset: 2px; - } + .metric-link:focus-visible { + outline: 3px solid #93c5fd; + outline-offset: 2px; + } + .dashboard-summary-grid { + grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); + } + .dashboard-summary-grid .metric { + min-height: 78px; + } + .dashboard-summary-grid .metric .value { + font-size: 25px; + } + .dashboard-trends-panel, + .dashboard-hosts-panel { + overflow: visible; + } .panel { margin-bottom: 18px; overflow: auto; @@ -304,17 +317,23 @@ } .inline-form { margin: 0; } .dashboard-priority-grid { + align-items: start; display: grid; gap: 14px; - grid-template-columns: minmax(280px, 1.25fr) repeat(3, minmax(220px, 1fr)); + grid-template-columns: repeat(2, minmax(0, 1fr)); margin-bottom: 20px; } .priority-panel { display: grid; gap: 12px; margin-bottom: 0; + min-width: 0; + overflow: visible; + } + .priority-panel > h2:first-child { + flex-wrap: wrap; + margin-bottom: 0; } - .priority-panel > h2:first-child { margin-bottom: 0; } .action-list, .activity-list, .schedule-list { @@ -385,6 +404,9 @@ .activity-row { grid-template-columns: max-content minmax(0, 1fr); } + .activity-row .status { + justify-self: start; + } .schedule-row { grid-template-columns: minmax(0, 1fr) max-content; } @@ -404,6 +426,14 @@ gap: 2px; min-width: 0; } + .action-row strong, + .action-row .muted, + .activity-row strong, + .activity-row .muted, + .schedule-row strong, + .schedule-row .muted { + overflow-wrap: anywhere; + } .schedule-time { justify-items: end; text-align: right; @@ -436,6 +466,10 @@ justify-content: space-between; padding-top: 8px; } + .storage-priority-facts strong { + text-align: right; + overflow-wrap: anywhere; + } .host-control-grid { display: grid; gap: 14px; @@ -572,6 +606,7 @@ border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm); + min-width: 0; padding: 16px; } .host-card:hover { @@ -605,8 +640,8 @@ } .host-card-layout { display: grid; - gap: 24px; - grid-template-columns: minmax(0, 2fr) minmax(260px, 1fr); + gap: 18px; + grid-template-columns: minmax(0, 1.7fr) minmax(240px, 0.9fr); } .host-card-section { align-content: start; @@ -623,7 +658,7 @@ .host-card-timeline { display: grid; gap: 16px 22px; - grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); + grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); } .host-card-stats { align-content: start; @@ -649,6 +684,10 @@ .host-card-item .value { overflow-wrap: anywhere; } + .host-card-item .value a { + overflow-wrap: anywhere; + word-break: break-word; + } .host-card-stat { display: grid; gap: 3px; @@ -679,6 +718,9 @@ margin-top: 14px; padding: 10px; } + .host-card-warning > * { + min-width: 0; + } .messages { display: grid; gap: 8px; margin-bottom: 18px; } .message { background: var(--panel); @@ -778,6 +820,46 @@ .host-card-stats { grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); } .insight-grid { grid-template-columns: 1fr; } } + @media (max-width: 1100px) { + .dashboard-priority-grid { + grid-template-columns: 1fr; + } + .dashboard-summary-grid { + grid-template-columns: repeat(3, minmax(0, 1fr)); + } + .host-card-layout { + grid-template-columns: 1fr; + } + .host-card-status { + justify-content: flex-start; + max-width: none; + } + .schedule-row { + grid-template-columns: 1fr; + } + .schedule-time { + justify-items: start; + text-align: left; + } + } + @media (max-width: 560px) { + .dashboard-summary-grid { + grid-template-columns: repeat(2, minmax(0, 1fr)); + } + .metric { + min-height: 76px; + padding: 12px; + } + .metric .value { + font-size: 24px; + } + .host-card { + padding: 13px; + } + .host-card-stats { + grid-template-columns: 1fr; + } + } diff --git a/src/pobsync_backend/templates/pobsync_backend/dashboard.html b/src/pobsync_backend/templates/pobsync_backend/dashboard.html index 97324f8..cefa769 100644 --- a/src/pobsync_backend/templates/pobsync_backend/dashboard.html +++ b/src/pobsync_backend/templates/pobsync_backend/dashboard.html @@ -33,7 +33,7 @@ {% endif %}
-
+

Required Action

{% if action_items %}
@@ -70,7 +70,7 @@ {% endif %}
-
+

Next Scheduled Work View all

{% if next_schedule_rows %}
@@ -96,7 +96,7 @@ {% endif %}
-
+

Recent Activity View all

{% if recent_runs %}
@@ -115,7 +115,7 @@ {% endif %}
-
+

Storage Pressure

{% if stats_summary.runs_sampled %}
@@ -163,7 +163,7 @@
-
+
Hosts
{{ counts.enabled_hosts }}/{{ counts.hosts }}
Schedules
{{ counts.enabled_schedules }}/{{ counts.schedules }}
Snapshots
{{ counts.snapshots }}
@@ -172,7 +172,7 @@
Failed
{{ counts.failed_runs }}
-
+ -
+

Hosts

{% for host in hosts %} diff --git a/src/pobsync_backend/tests/test_views.py b/src/pobsync_backend/tests/test_views.py index e221eeb..68c64d2 100644 --- a/src/pobsync_backend/tests/test_views.py +++ b/src/pobsync_backend/tests/test_views.py @@ -103,6 +103,13 @@ class ViewTests(TestCase): self.assertEqual(response.status_code, 200) self.assertContains(response, "Control panel") self.assertContains(response, "Backup health, required action, storage pressure, and recent activity in one place.") + self.assertContains(response, "dashboard-panel-required") + self.assertContains(response, "dashboard-panel-schedules") + self.assertContains(response, "dashboard-panel-activity") + self.assertContains(response, "dashboard-panel-storage") + self.assertContains(response, "dashboard-summary-grid") + self.assertContains(response, "dashboard-trends-panel") + self.assertContains(response, "dashboard-hosts-panel") self.assertContains(response, "Dashboard") self.assertContains(response, "web-01") self.assertContains(response, "20260519-021500Z__ABCDEFGH")