diff --git a/CHANGELOG.md b/CHANGELOG.md index abc8f19..8d92784 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,9 @@ * feature: Restructure plugin_monitor_dashboards to store filter state as a JSON `properties` object (migrating the legacy raw `url` into it and dropping the url column on upgrade), and construct dashboard URLs from that structure instead of persisting raw urls * feature: Render the Site and Device Template groupings as a responsive full-width grid of draggable card panels (up to 8 columns, shrinking on narrower screens) whose titles are coloured by each group's worst device status, persisting card order per dashboard or per user +* bug: Let a grouping card with many devices span several grid columns so it flows across the page instead of stacking into one tall, narrow column that scrolls off the screen +* bug: Render the Tree grouping as card panels (one per tree, plus a Non-Tree card) like the Site and Device Template groupings, instead of leaving it on the legacy section layout +* bug: Force the grouping card title colours with !important so Cacti core's device-status classes can no longer override them and leave unreadable low-contrast text on a coloured header (e.g. a device template with down devices) * feature: Add a distinct 'Service Check Failed' device status with its own legend chip, tile/list colour and status-filter coverage, driven by a realm-gated, schema-aware servcheck host set * feature: Add an Actions column to the List view that opens a device detail dialog of intropage-style panels (host information, data collection timing, service checks, thresholds, last-hour syslog, and device links) * feature: Add a plugin_servcheck integration so a triggered/failing service check on a device promotes its hover status and adds a hover glyph linking to the failing check, alongside the existing thold and syslog integrations diff --git a/css/monitor.css b/css/monitor.css index ef83dc0..6c4bd7e 100644 --- a/css/monitor.css +++ b/css/monitor.css @@ -644,13 +644,32 @@ } /* Grouping card grid: responsive, flows full screen up to ~8 columns and - shrinks to fewer columns as the viewport narrows. */ + shrinks to fewer columns as the viewport narrows. Large groups span several + columns (see data-span) so their devices flow across the page. */ .monitorGroupGrid { display: grid; - grid-template-columns: repeat(auto-fit, minmax(260px, 1fr)); + grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); + grid-auto-flow: row dense; gap: 10px; align-items: start; width: 100%; + container-type: inline-size; +} + +/* Cap each card's span to the number of 260px tracks the grid can actually + show at its current width (track + 10px gap), so a wide card never forces an + extra implicit track and horizontal overflow on narrow layouts. */ +@container (max-width: 529px) { + .monitorGroupCard { grid-column: auto !important; } +} + +@container (min-width: 530px) and (max-width: 799px) { + .monitorGroupCard[data-span="3"], + .monitorGroupCard[data-span="4"] { grid-column: span 2 !important; } +} + +@container (min-width: 800px) and (max-width: 1069px) { + .monitorGroupCard[data-span="4"] { grid-column: span 3 !important; } } .monitorGroupCard .monitorPanelBody { @@ -673,16 +692,19 @@ min-height: 60px; } -/* Group card titles coloured by the group's worst device status. */ -.monitorGroupTitle.deviceUp { background-color: #2b8235; color: #ffffff; } -.monitorGroupTitle.deviceDown { background-color: #a12820; color: #ffffff; } -.monitorGroupTitle.deviceDownMuted { background-color: #93302a; color: #ffffff; } -.monitorGroupTitle.deviceRecovering { background-color: #9a6a1a; color: #ffffff; } -.monitorGroupTitle.deviceThreshold { background-color: #a85712; color: #ffffff; } -.monitorGroupTitle.deviceThresholdMuted { background-color: #6a4a9c; color: #ffffff; } -.monitorGroupTitle.deviceWarning { background-color: #7d6f18; color: #ffffff; } -.monitorGroupTitle.deviceAlert { background-color: #86407a; color: #ffffff; } -.monitorGroupTitle.deviceUnknown { background-color: #5f5f57; color: #ffffff; } -.monitorGroupTitle.deviceUnmonitored { background-color: #3f6a8a; color: #ffffff; } -.monitorGroupTitle.deviceServiceCheck { background-color: #157f87; color: #ffffff; } +/* Group card titles coloured by the group's worst device status. Marked + !important so the Cacti core device-status classes (e.g. .deviceDown, which + force a red text/background) cannot override the title's palette and leave + unreadable low-contrast text on the coloured header. */ +.monitorGroupTitle.deviceUp { background-color: #2b8235 !important; color: #ffffff !important; } +.monitorGroupTitle.deviceDown { background-color: #a12820 !important; color: #ffffff !important; } +.monitorGroupTitle.deviceDownMuted { background-color: #93302a !important; color: #ffffff !important; } +.monitorGroupTitle.deviceRecovering { background-color: #9a6a1a !important; color: #ffffff !important; } +.monitorGroupTitle.deviceThreshold { background-color: #a85712 !important; color: #ffffff !important; } +.monitorGroupTitle.deviceThresholdMuted { background-color: #6a4a9c !important; color: #ffffff !important; } +.monitorGroupTitle.deviceWarning { background-color: #7d6f18 !important; color: #ffffff !important; } +.monitorGroupTitle.deviceAlert { background-color: #86407a !important; color: #ffffff !important; } +.monitorGroupTitle.deviceUnknown { background-color: #5f5f57 !important; color: #ffffff !important; } +.monitorGroupTitle.deviceUnmonitored { background-color: #3f6a8a !important; color: #ffffff !important; } +.monitorGroupTitle.deviceServiceCheck { background-color: #157f87 !important; color: #ffffff !important; } diff --git a/includes/controller.php b/includes/controller.php index 86622bb..7bd9501 100644 --- a/includes/controller.php +++ b/includes/controller.php @@ -105,7 +105,7 @@ function monitorDashboardOwnedByUser(int $dashboard): bool { function saveCardOrder(): void { $grouping = get_nfilter_request_var('grouping'); - if (!in_array($grouping, ['site', 'template'], true)) { + if (!in_array($grouping, ['site', 'template', 'tree'], true)) { return; } @@ -114,7 +114,14 @@ function saveCardOrder(): void { if (is_array($order)) { foreach ($order as $gid) { - $ids[] = (string) (int) $gid; + // Group ids may be numeric (site/template) or string tokens such as + // "tree_12" and "nontree", so preserve the string while stripping + // anything outside a safe id character set. + $gid = (string) preg_replace('/[^a-zA-Z0-9_]/', '', (string) $gid); + + if ($gid !== '') { + $ids[] = $gid; + } } } diff --git a/includes/render.php b/includes/render.php index 276a223..8a4d4c2 100644 --- a/includes/render.php +++ b/includes/render.php @@ -247,6 +247,10 @@ function monitorRenderGroupCards(string $grouping, array $groups, int $maxlen): foreach ($groups as $gid => $group) { $worst = monitorGroupWorstStatusClass($group['hosts']); + // Let groups with many devices span several grid columns so their tiles + // flow across the page instead of stacking into one tall, narrow column. + $span = (int) min(4, max(1, (int) ceil(cacti_sizeof($group['hosts']) / 6))); + $body = "