From a5ea0b242eb993f00eb408dbf14157fe873d3883 Mon Sep 17 00:00:00 2001 From: Isaac Connor Date: Fri, 22 May 2026 08:59:46 -0400 Subject: [PATCH] fix: keep console summary row aligned when toggling event columns The footer matched cells positionally with `eventCells[index]`, but bootstrap-table omits hidden columns from the rebuilt tfoot, so hiding e.g. Hour shifted every later period's total into the wrong cell. Tag each event header with a unique colEvents class and target the footer cell by that class instead of by index. Bootstrap-table also rebuilds the tfoot on column-switch, which wiped our injected totals until the next ajax refresh. Cache the last footer payload and re-apply it on column-switch / column-switch-all. Co-Authored-By: Claude Opus 4.7 --- web/skins/classic/views/console.php | 2 +- web/skins/classic/views/js/console.js | 54 +++++++++++++++------------ 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/web/skins/classic/views/console.php b/web/skins/classic/views/console.php index 57e49ad53..8ac013361 100644 --- a/web/skins/classic/views/console.php +++ b/web/skins/classic/views/console.php @@ -294,7 +294,7 @@ echo $navbar ?> ); parseFilter($filter); $eventsLink = canView('Events') ? '?view='.ZM_WEB_EVENTS_VIEW.'&page=1'.$filter['querystring'] : ''; - echo '' .htmlspecialchars($eventCounts[$i]['title']) .''.PHP_EOL; diff --git a/web/skins/classic/views/js/console.js b/web/skins/classic/views/js/console.js index 8f21cc31f..2eb0f06bd 100644 --- a/web/skins/classic/views/js/console.js +++ b/web/skins/classic/views/js/console.js @@ -2,9 +2,11 @@ const table = $j('#consoleTable'); var ajax = null; var monitors = {}; // Store monitors by ID for function modal +var lastFooter = null; // Cached footer payload for re-applying after column toggles // Update footer with dynamic totals function updateFooter(footer) { + lastFooter = footer; // Target the footer within the bootstrap-table wrapper // Bootstrap-table may transform td to th and wrap content in divs var footerRow = $j('#consoleTable').closest('.bootstrap-table').find('tfoot tr'); @@ -32,35 +34,33 @@ function updateFooter(footer) { // Update bandwidth/FPS (in Function column) updateCell('td.colFunction, th.colFunction', footer.bandwidth_fps); - // Update event totals + // Update event totals. Target each period by its unique colEvents + // class rather than by positional index: bootstrap-table drops hidden columns + // from the tfoot DOM entirely, so an index-based lookup would shift every + // period after the hidden one into the wrong cell. var eventPeriods = ['Total', 'Hour', 'Day', 'Week', 'Month', 'Archived']; - var eventCells = footerRow.find('td.colEvents, th.colEvents'); - eventPeriods.forEach(function(period, index) { - if (eventCells.length > index) { - var cell = $j(eventCells[index]); - // Only update the th-inner div if it exists - var innerDiv = cell.find('.th-inner'); - var target = innerDiv.length ? innerDiv : cell; + eventPeriods.forEach(function(period) { + var sel = 'td.col' + period + 'Events, th.col' + period + 'Events'; + var cell = footerRow.find(sel); + if (!cell.length) return; - var contentHtml = footer[period + 'Events'] + '
' + - footer[period + 'EventDiskSpace'] + '
'; + var innerDiv = cell.find('.th-inner'); + var target = innerDiv.length ? innerDiv : cell; - // Create or update link with filter querystring - if (canView.Events && footer[period + 'FilterQuery']) { - var link = target.find('a'); - if (link.length) { - // Update existing link href and content - link.attr('href', '?view=' + ZM_WEB_EVENTS_VIEW + footer[period + 'FilterQuery']); - link.html(contentHtml); - } else { - // Create new link - target.html('' + - contentHtml + ''); - } + var contentHtml = footer[period + 'Events'] + '
' + + footer[period + 'EventDiskSpace'] + '
'; + + if (canView.Events && footer[period + 'FilterQuery']) { + var link = target.find('a'); + if (link.length) { + link.attr('href', '?view=' + ZM_WEB_EVENTS_VIEW + footer[period + 'FilterQuery']); + link.html(contentHtml); } else { - // No permission or no filter query, just show text - target.html(contentHtml); + target.html('' + + contentHtml + ''); } + } else { + target.html(contentHtml); } }); @@ -566,6 +566,12 @@ function initPage() { $j('.functionLnk').click(manageFunctionModal); }); + // Re-apply cached footer totals when columns are toggled, because + // bootstrap-table rebuilds tfoot on column-switch and clears our content. + table.on('column-switch.bs.table column-switch-all.bs.table', function() { + if (lastFooter) updateFooter(lastFooter); + }); + // Makes table sortable - disabled by default, enabled by Sort button // Note: This may need adjustment for bootstrap-table compatibility $j('#consoleTableBody').sortable({