Fix CSP-blocked chart scripts, undefined CSS classes, and double-firing click handlers

- Add nonce to charts and ticket-preview drawer inline <script> blocks in
  DashboardView.php (both were CSP-blocked — charts never rendered)
- Add .lt-modal-xs (280px) to base.css — used by quickStatus/quickAssign
  modals but was undefined, causing them to use full modal width
- Fix showConfirmModal in utils.js: class="text-center" → "lt-text-center"
  (undefined class); escape newlines as <br> so multi-line messages render
- Remove duplicate click-handler cases from DashboardView.php inline script
  that were already handled by dashboard.js, preventing double-firing
  (export-tickets, open-settings, remove-filter, etc. were all called twice)
- Fix manual-refresh action to use lt.autoRefresh.now() instead of bare
  window.location.reload() so modal/focus guards are respected

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-04-04 23:00:35 -04:00
parent d588590989
commit 914c33ecf3
4 changed files with 14 additions and 20 deletions
+6 -14
View File
@@ -205,7 +205,7 @@ include __DIR__ . '/layout_header.php';
</div>
</div>
</div>
<script>
<script nonce="<?= $nonce ?>">
// ── Dashboard charts (Chart.js, loaded from CDN) ─────────────────
(function() {
function waitForChart(cb, tries) {
@@ -1124,27 +1124,19 @@ document.querySelectorAll('.lt-stat-card').forEach(function (card) {
});
});
// Event delegation for click actions — only handles cases NOT covered by dashboard.js
// bulk-*, navigate, view-ticket, quick-*, set-view-mode, clear-selection, toggle-*
// are all handled by dashboard.js to avoid double-firing (duplicate handlers = duplicate users in selects).
// Event delegation handles ONLY cases NOT covered by dashboard.js
// (bulk-*, navigate, view-ticket, quick-*, set-view-mode, clear-selection, toggle-select-all,
// toggle-row-checkbox, remove-filter, clear-all-filters, open/close/save-settings,
// open/toggle-export-menu, export-tickets, open-advanced-search are in dashboard.js)
document.addEventListener('click', function (e) {
var target = e.target.closest('[data-action]');
if (!target) return;
switch (target.getAttribute('data-action')) {
case 'open-settings': openSettingsModal(); break;
case 'close-settings': closeSettingsModal(); break;
case 'save-settings': saveSettings(); break;
case 'manual-refresh': if (lt.autoRefresh) lt.autoRefresh.now(); break;
case 'toggle-sidebar': if (typeof toggleSidebar==='function') toggleSidebar(); break;
case 'open-advanced-search': openAdvancedSearch(); break;
case 'close-advanced-search': closeAdvancedSearch(); break;
case 'reset-advanced-search': resetAdvancedSearch(); break;
case 'toggle-export-menu': e.stopPropagation(); toggleExportMenu(e); break;
case 'export-tickets': e.preventDefault(); exportSelectedTickets(target.getAttribute('data-format')); break;
case 'save-filter': saveCurrentFilter(); break;
case 'delete-filter': deleteSavedFilter(); break;
case 'remove-filter': removeFilter(target.getAttribute('data-filter-type'), target.getAttribute('data-filter-value')); break;
case 'clear-all-filters': window.location.href = '/'; break;
}
});
@@ -1206,7 +1198,7 @@ if (advForm) advForm.addEventListener('submit', performAdvancedSearch);
</aside>
<div class="lt-drawer-right-overlay" id="ticketPreviewDrawerOverlay"></div>
<script>
<script nonce="<?= $nonce ?>">
// ── Ticket Preview Drawer ──────────────────────────────────────────
(function() {
var drawer = document.getElementById('ticketPreviewDrawer');