From 7242dfbf84f3d6deca673e6a57dcb1e3db5ad6b1 Mon Sep 17 00:00:00 2001 From: Alexander Moisseev Date: Tue, 11 Nov 2025 16:32:10 +0300 Subject: [PATCH] [Minor] Fix hover behavior for Status tab tables Tables with rowspan cells (Bayesian statistics and Fuzzy hashes) now have consistent hover highlighting across all rows in a group. --- interface/css/rspamd.css | 10 ++++++-- interface/js/app/stats.js | 51 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+), 2 deletions(-) diff --git a/interface/css/rspamd.css b/interface/css/rspamd.css index a43f1e5e1c..367b96066c 100644 --- a/interface/css/rspamd.css +++ b/interface/css/rspamd.css @@ -346,10 +346,10 @@ table#symbolsTable input[type="number"] { .symbol-special { background-color: var(--rspamd-symbol-special-bg); } -.symbol-negative:hover { +.parent:not(.status-table) .symbol-negative:hover { background-color: var(--rspamd-symbol-hover-bg); } -.symbol-positive:hover { +.parent:not(.status-table) .symbol-positive:hover { background-color: var(--rspamd-symbol-hover-bg); } .symbol-special:hover { @@ -428,6 +428,12 @@ table#symbolsTable input[type="number"] { border-radius: 0 0 0 calc(var(--bs-border-radius) + 1px); } +/* Hover effect for table cells in tables with rowspan groups */ +.status-table tbody td.table-hover-cell { + --bs-table-color-state: var(--bs-table-hover-color); + --bs-table-bg-state: var(--bs-table-hover-bg); +} + /* RRD summary */ #summary-row { padding-left: 80px; diff --git a/interface/js/app/stats.js b/interface/js/app/stats.js index e504aef799..e97b704af0 100644 --- a/interface/js/app/stats.js +++ b/interface/js/app/stats.js @@ -55,6 +55,51 @@ define(["jquery", "app/common", "d3pie", "d3"], return out; } + let rowspanHoverHandlersInitialized = false; + + function attachRowspanHoverHandlers(tableId) { + const $table = $(tableId); + + function findRowspanCell($row) { + const headerCount = $table.find("thead th").length; + if ($row.find("td").length >= headerCount) return null; + + // Assumes rowspan cells always appear in the first column + let result = null; + $row.prevAll().find("td:first-child[rowspan]").each((_, el) => { + const $cell = $(el); + const rowspan = parseInt($cell.attr("rowspan"), 10); + const distance = $row.prevAll().length - $cell.parent().prevAll().length; + if (distance < rowspan) { + result = $cell; + return false; // break + } + return true; + }); + return result; + } + + $table.on("mouseenter", "tbody td", (event) => { + const $cell = $(event.currentTarget); + const $row = $cell.parent(); + + if ($cell.attr("rowspan")) { + // Hovering over rowspan cell - highlight entire group + const rowspan = parseInt($cell.attr("rowspan"), 10); + $cell.addClass("table-hover-cell"); + $row.find("td").addClass("table-hover-cell"); + $row.nextAll().slice(0, rowspan - 1).find("td").addClass("table-hover-cell"); + } else { + // Hovering over regular cell - highlight current row + $row.find("td").addClass("table-hover-cell"); + + // Highlight rowspan cell if exists + const $rowspanCell = findRowspanCell($row); + if ($rowspanCell) $rowspanCell.addClass("table-hover-cell"); + } + }).on("mouseleave", "tbody td", () => $table.find("tbody td").removeClass("table-hover-cell")); + } + function displayStatWidgets(checked_server) { const servers = JSON.parse(sessionStorage.getItem("Credentials")); let data = {}; @@ -223,6 +268,12 @@ define(["jquery", "app/common", "d3pie", "d3"], addStatfiles(checked_server, data.statfiles); addFuzzyStorage(checked_server, data.fuzzy_hashes); } + + if (!rowspanHoverHandlersInitialized) { + attachRowspanHoverHandlers("#bayesTable"); + attachRowspanHoverHandlers("#fuzzyTable"); + rowspanHoverHandlersInitialized = true; + } } function getChart(graphs, checked_server) { -- 2.47.3