Files
TheWitness 38bdabf90f monitor: use CSS Grid for truly equal-width legend chips (#263)
* monitor: use CSS Grid for truly equal-width legend chips

The .monitorLegend flex: 1 1 0 + flex-wrap layout distributes free space per wrapped line, so a partial last row stretched its chips wider than full rows. Switch to a grid (repeat(auto-fill, minmax(var(--monitor-chip-min), 1fr))) so every chip shares an equal column across all rows. The longest-label seed (--monitor-chip-min from includes/controller.php) still drives the column minimum.

* monitor: use auto-fit so chips fill the legend width when they fit on one row

Review follow-up (#263): auto-fill retains empty implicit columns on wide viewports, leaving unused slots so the chips do not fill the legend width. auto-fit collapses the empty tracks while keeping equal shared columns across wrapped rows.

* monitor: extract monitor_legend() and add unit coverage

The status legend was rendered inline in includes/controller.php, so it had no unit coverage like the thold/servcheck/mactrack/syslog legends. Extract it into monitor_legend(array \, array \) in includes/functions.php (in the phpunit coverage source set) and add MonitorLegendTest.php asserting the exact calc(Nch + 1.5rem) longest-label value. No behaviour change.

* monitor: escape status-legend chip labels at output

Defence-in-depth: wrap the legend chip display text in html_escape() so markup or HTML entities in a translated label cannot alter the legend DOM. Applied consistently across the thold/monitor/servcheck/mactrack/syslog fleet legends. The chip-min sizing still measures the unescaped label length, so layout is unchanged.
2026-10-07 13:20:26 -04:00

55 lines
2.5 KiB
PHP

<?php
/*
+-------------------------------------------------------------------------+
| Copyright (C) 2004-2026 The Cacti Group |
| |
| This program is free software; you can redistribute it and/or |
| modify it under the terms of the GNU General Public License |
| as published by the Free Software Foundation; either version 2 |
| of the License, or (at your option) any later version. |
| |
| This program is distributed in the hope that it will be useful, |
| but WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| GNU General Public License for more details. |
+-------------------------------------------------------------------------+
| Cacti: The Complete RRDtool-based Graphing Solution |
+-------------------------------------------------------------------------+
| This code is designed, written, and maintained by the Cacti Group. See |
| about.php and/or the AUTHORS file for specific developer information. |
+-------------------------------------------------------------------------+
| http://www.cacti.net/ |
+-------------------------------------------------------------------------+
*/
/*
* Unit coverage for monitor_legend(): one rounded .monitorLegendItem chip per
* status, and the container's --monitor-chip-min variable sized to the longest
* label.
*/
beforeAll(function () {
require_once __DIR__ . '/../../includes/functions.php';
});
it('sizes the monitor legend chips to the longest label', function () {
$iclasses = ['deviceUp', 'deviceDown', 'deviceRecovering'];
$icolorsdisplay = ['Up', 'Down', 'Recovering'];
$expected = 0;
foreach ($icolorsdisplay as $label) {
$expected = max($expected, mb_strlen($label));
}
ob_start();
monitor_legend($iclasses, $icolorsdisplay);
$output = ob_get_clean();
expect($output)->toContain("<div class='monitorLegend' style='--monitor-chip-min: calc(" . $expected . "ch + 1.5rem)'>");
expect(substr_count($output, 'monitorLegendItem'))->toBe(count($iclasses));
foreach ($iclasses as $index => $class) {
expect($output)->toContain("<div class='monitorLegendItem {$class}Full'>" . $icolorsdisplay[$index] . '</div>');
}
});