diff --git a/CHANGELOG.md b/CHANGELOG.md index c836d6c1..1c95a8c6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ * feature: Add Remote Data Collector processing, rules-sync, and record-storage options to the setup advisor; reject Aria selections whenever any collector option is enabled * change: Use TEXT for message columns previously limited to VARCHAR(2048), including existing installations +* dev: Size the severity-legend chips to the longest label and lay them out as a CSS grid so every chip stays equal width as the legend wraps (matching the thold/monitor/servcheck/mactrack legends) * ci: Drop Ruby from the CodeQL language matrix; the plugin ships no Ruby source, so the Ruby database build failed with "no source code seen" * dev: Move the shared function and database libraries to includes/ and point the entry-point includes, coverage source, and tests at the new path * feature: Restyle the System Logs and Alert Logs severity legends as rounded, evenly spaced, solid-colour chips that line up with the Thold status legends, with theme-appropriate backgrounds loaded from a per-theme css/.css file (falling back to a theme-neutral css/legend.css) diff --git a/css/classic.css b/css/classic.css index b47d85d8..42c80443 100644 --- a/css/classic.css +++ b/css/classic.css @@ -24,15 +24,13 @@ /* Syslog status-legend palette for the classic (light surface) theme. */ .syslogLegend { - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(var(--syslog-chip-min, 8ch), 1fr)); gap: 4px; width: 100%; } .syslogLegend .syslogLegendItem { - flex: 1 1 0; - min-width: var(--syslog-chip-min, max-content); text-align: center; white-space: nowrap; padding: 4px 6px; diff --git a/css/dark.css b/css/dark.css index 28788de1..d43b99f1 100644 --- a/css/dark.css +++ b/css/dark.css @@ -24,15 +24,13 @@ /* Syslog status-legend palette for the dark (dark surface) theme. */ .syslogLegend { - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(var(--syslog-chip-min, 8ch), 1fr)); gap: 4px; width: 100%; } .syslogLegend .syslogLegendItem { - flex: 1 1 0; - min-width: var(--syslog-chip-min, max-content); text-align: center; white-space: nowrap; padding: 4px 6px; diff --git a/css/deepness.css b/css/deepness.css index 28788de1..d43b99f1 100644 --- a/css/deepness.css +++ b/css/deepness.css @@ -24,15 +24,13 @@ /* Syslog status-legend palette for the dark (dark surface) theme. */ .syslogLegend { - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(var(--syslog-chip-min, 8ch), 1fr)); gap: 4px; width: 100%; } .syslogLegend .syslogLegendItem { - flex: 1 1 0; - min-width: var(--syslog-chip-min, max-content); text-align: center; white-space: nowrap; padding: 4px 6px; diff --git a/css/legend.css b/css/legend.css index f313d9c6..787bdc29 100644 --- a/css/legend.css +++ b/css/legend.css @@ -24,15 +24,13 @@ /* Theme-neutral Syslog status-legend palette; the fallback loaded by syslog_include_js() when the active theme ships no dedicated css/.css file. */ .syslogLegend { - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(var(--syslog-chip-min, 8ch), 1fr)); gap: 4px; width: 100%; } .syslogLegend .syslogLegendItem { - flex: 1 1 0; - min-width: var(--syslog-chip-min, max-content); text-align: center; white-space: nowrap; padding: 4px 6px; diff --git a/css/midwinter.css b/css/midwinter.css index 78fe9898..c06840dc 100644 --- a/css/midwinter.css +++ b/css/midwinter.css @@ -24,15 +24,13 @@ /* Syslog status-legend palette for the midwinter (dark surface) theme. */ .syslogLegend { - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(var(--syslog-chip-min, 8ch), 1fr)); gap: 4px; width: 100%; } .syslogLegend .syslogLegendItem { - flex: 1 1 0; - min-width: var(--syslog-chip-min, max-content); text-align: center; white-space: nowrap; padding: 4px 6px; diff --git a/css/modern.css b/css/modern.css index c73080ed..31441cde 100644 --- a/css/modern.css +++ b/css/modern.css @@ -24,15 +24,13 @@ /* Syslog status-legend palette for the modern (light surface) theme. */ .syslogLegend { - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(var(--syslog-chip-min, 8ch), 1fr)); gap: 4px; width: 100%; } .syslogLegend .syslogLegendItem { - flex: 1 1 0; - min-width: var(--syslog-chip-min, max-content); text-align: center; white-space: nowrap; padding: 4px 6px; diff --git a/css/paper-plane.css b/css/paper-plane.css index 3c6ecfd2..7fcb65ae 100644 --- a/css/paper-plane.css +++ b/css/paper-plane.css @@ -24,15 +24,13 @@ /* Syslog status-legend palette for the paper-plane (dark surface) theme. */ .syslogLegend { - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(var(--syslog-chip-min, 8ch), 1fr)); gap: 4px; width: 100%; } .syslogLegend .syslogLegendItem { - flex: 1 1 0; - min-width: var(--syslog-chip-min, max-content); text-align: center; white-space: nowrap; padding: 4px 6px; diff --git a/css/paw.css b/css/paw.css index 733b69ab..12bd0c4a 100644 --- a/css/paw.css +++ b/css/paw.css @@ -24,15 +24,13 @@ /* Syslog status-legend palette for the paw (light surface) theme. */ .syslogLegend { - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(var(--syslog-chip-min, 8ch), 1fr)); gap: 4px; width: 100%; } .syslogLegend .syslogLegendItem { - flex: 1 1 0; - min-width: var(--syslog-chip-min, max-content); text-align: center; white-space: nowrap; padding: 4px 6px; diff --git a/css/sunrise.css b/css/sunrise.css index 10dcc8ae..670a93e0 100644 --- a/css/sunrise.css +++ b/css/sunrise.css @@ -24,15 +24,13 @@ /* Syslog status-legend palette for the sunrise (dark surface) theme. */ .syslogLegend { - display: flex; - flex-wrap: wrap; + display: grid; + grid-template-columns: repeat(auto-fit, minmax(var(--syslog-chip-min, 8ch), 1fr)); gap: 4px; width: 100%; } .syslogLegend .syslogLegendItem { - flex: 1 1 0; - min-width: var(--syslog-chip-min, max-content); text-align: center; white-space: nowrap; padding: 4px 6px; diff --git a/includes/functions.php b/includes/functions.php index 3c8c8c5b..f2f0cfdf 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -759,7 +759,6 @@ function syslog_syslog_legend(): void { ]; $chip_min = 0; - foreach ($items as $label) { $chip_min = max($chip_min, mb_strlen($label)); } @@ -768,7 +767,7 @@ function syslog_syslog_legend(): void { print '
'; foreach ($items as $class => $label) { - print '
' . $label . '
'; + print '
' . html_escape($label) . '
'; } print '
'; @@ -795,7 +794,6 @@ function syslog_log_legend(): void { ]; $chip_min = 0; - foreach ($items as $label) { $chip_min = max($chip_min, mb_strlen($label)); } @@ -804,7 +802,7 @@ function syslog_log_legend(): void { print '
'; foreach ($items as $class => $label) { - print '
' . $label . '
'; + print '
' . html_escape($label) . '
'; } print '
'; diff --git a/tests/Unit/SyslogLegendTest.php b/tests/Unit/SyslogLegendTest.php index a1485e62..c6afa5fb 100644 --- a/tests/Unit/SyslogLegendTest.php +++ b/tests/Unit/SyslogLegendTest.php @@ -41,12 +41,20 @@ $output = ob_get_clean(); expect($output)->toContain(''); - expect($output)->toContain('
'); + expect(substr_count($output, 'syslogLegendItem'))->toBe(8); + + foreach ($items as $class => $label) { expect($output)->toContain('
' . $label . '
'); } }); @@ -58,14 +66,40 @@ syslog_log_legend(); $output = ob_get_clean(); - expect($output)->toContain('
'); expect(substr_count($output, 'syslogLegendItem'))->toBe(3); - foreach (['logAlert' => 'Alert', 'logWarning' => 'Warning', 'logInfo' => 'Informational'] as $class => $label) { + foreach ($items as $class => $label) { expect($output)->toContain('
' . $label . '
'); } }); +it('sizes the chips from the translated labels, not the English source', function () { + syslog_load_plugin_source('includes/functions.php'); + + $long = 'A very long translated error label'; + + // 'Error' is short in English; its translation is the longest label, so the + // chip minimum must follow the translated (emitted) output, not the source. + test_override('__', function ($text) use ($long) { + return $text === 'Error' ? $long : $text; + }); + + ob_start(); + syslog_syslog_legend(); + $output = ob_get_clean(); + + expect($output)->toContain('--syslog-chip-min: calc(' . mb_strlen($long) . 'ch + 1.5rem)'); + expect($output)->toContain('
' . $long . '
'); +}); + it('links the theme legend stylesheet when the theme ships one', function () { syslog_load_plugin_source('includes/functions.php');