Dashboard cleanup: chart empty-state message, dead click-handler (#101)
Two small findings from the same dashboard audit pass: 1. Charts rendered a bare empty frame with no message when the filtered dataset was empty (fresh install, or a non-admin's visibility-filtered ticket set happening to be zero). makeDonut/ makeBar now show a "No data for current filters" message in the chart's place instead of silently doing nothing. 2. Stat cards had two independent, redundant click-handler implementations. lt.statsFilter.init() (base.js, shared web_template code) read each card's data-filter-key/data-filter-val attributes and called window.lt_onStatFilter(key, val) on click — but that global is never defined anywhere in this app, so it only toggled a cosmetic .active class with no functional effect. The actual navigation logic is the separate handler at ~line 1282 that ignores those attributes entirely. Both fired on the same click with no visible symptom, but the markup looked load-bearing and wasn't — a trap for a future edit that touches one implementation assuming it's the only one. Removed the dead lt.statsFilter.init() call and the now-unused data-filter-key/data-filter-val attributes from this app's DashboardView.php (left the shared lt.statsFilter module in base.js itself untouched, since other LotusGuild apps consuming the same shared template file may define their own lt_onStatFilter). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MGDKHiU5RJdo3dqQUDow3X
This commit is contained in:
+16
-7
@@ -120,7 +120,6 @@ include __DIR__ . '/layout_header.php';
|
|||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="lt-stat-card stat-open" role="button" tabindex="0"
|
<div class="lt-stat-card stat-open" role="button" tabindex="0"
|
||||||
data-filter-key="status" data-filter-val="Open,Pending,In Progress"
|
|
||||||
title="Click to filter by active tickets" aria-label="Open tickets">
|
title="Click to filter by active tickets" aria-label="Open tickets">
|
||||||
<div class="lt-stat-icon">[ # ]</div>
|
<div class="lt-stat-icon">[ # ]</div>
|
||||||
<div class="lt-stat-info">
|
<div class="lt-stat-info">
|
||||||
@@ -133,7 +132,6 @@ include __DIR__ . '/layout_header.php';
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lt-stat-card stat-critical" role="button" tabindex="0"
|
<div class="lt-stat-card stat-critical" role="button" tabindex="0"
|
||||||
data-filter-key="priority" data-filter-val="1"
|
|
||||||
title="Click to filter critical (P1) tickets" aria-label="Critical P1 tickets">
|
title="Click to filter critical (P1) tickets" aria-label="Critical P1 tickets">
|
||||||
<div class="lt-stat-icon lt-text-danger">[ ! ]</div>
|
<div class="lt-stat-icon lt-text-danger">[ ! ]</div>
|
||||||
<div class="lt-stat-info">
|
<div class="lt-stat-info">
|
||||||
@@ -146,7 +144,6 @@ include __DIR__ . '/layout_header.php';
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lt-stat-card stat-unassigned" role="button" tabindex="0"
|
<div class="lt-stat-card stat-unassigned" role="button" tabindex="0"
|
||||||
data-filter-key="assigned_to" data-filter-val="unassigned"
|
|
||||||
title="Click to filter unassigned tickets" aria-label="Unassigned tickets">
|
title="Click to filter unassigned tickets" aria-label="Unassigned tickets">
|
||||||
<div class="lt-stat-icon lt-text-amber">[ @ ]</div>
|
<div class="lt-stat-icon lt-text-amber">[ @ ]</div>
|
||||||
<div class="lt-stat-info">
|
<div class="lt-stat-info">
|
||||||
@@ -171,7 +168,6 @@ include __DIR__ . '/layout_header.php';
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="lt-stat-card stat-resolved" role="button" tabindex="0"
|
<div class="lt-stat-card stat-resolved" role="button" tabindex="0"
|
||||||
data-filter-key="status" data-filter-val="Closed"
|
|
||||||
title="Click to filter closed tickets" aria-label="Closed tickets today">
|
title="Click to filter closed tickets" aria-label="Closed tickets today">
|
||||||
<div class="lt-stat-icon lt-text-muted">[ OK ]</div>
|
<div class="lt-stat-icon lt-text-muted">[ OK ]</div>
|
||||||
<div class="lt-stat-info">
|
<div class="lt-stat-info">
|
||||||
@@ -334,7 +330,8 @@ include __DIR__ . '/layout_header.php';
|
|||||||
|
|
||||||
function makeDonut(canvasId, data, colorMap) {
|
function makeDonut(canvasId, data, colorMap) {
|
||||||
var ctx = document.getElementById(canvasId);
|
var ctx = document.getElementById(canvasId);
|
||||||
if (!ctx || !data.length) return;
|
if (!ctx) return;
|
||||||
|
if (!data.length) { showChartEmptyState(ctx); return; }
|
||||||
ctx.title = 'Click a segment to filter the ticket list';
|
ctx.title = 'Click a segment to filter the ticket list';
|
||||||
return new Chart(ctx, {
|
return new Chart(ctx, {
|
||||||
type: 'doughnut',
|
type: 'doughnut',
|
||||||
@@ -365,9 +362,22 @@ include __DIR__ . '/layout_header.php';
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function showChartEmptyState(canvas) {
|
||||||
|
canvas.style.display = 'none';
|
||||||
|
var wrap = canvas.parentElement;
|
||||||
|
if (wrap && !wrap.querySelector('.lt-chart-empty')) {
|
||||||
|
var msg = document.createElement('div');
|
||||||
|
msg.className = 'lt-chart-empty';
|
||||||
|
msg.style.cssText = 'display:flex;align-items:center;justify-content:center;height:100%;color:var(--text-muted);font-size:0.75rem';
|
||||||
|
msg.textContent = 'No data for current filters';
|
||||||
|
wrap.appendChild(msg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function makeBar(canvasId, data) {
|
function makeBar(canvasId, data) {
|
||||||
var ctx = document.getElementById(canvasId);
|
var ctx = document.getElementById(canvasId);
|
||||||
if (!ctx || !data.length) return;
|
if (!ctx) return;
|
||||||
|
if (!data.length) { showChartEmptyState(ctx); return; }
|
||||||
ctx.title = 'Click a bar to filter the ticket list';
|
ctx.title = 'Click a bar to filter the ticket list';
|
||||||
return new Chart(ctx, {
|
return new Chart(ctx, {
|
||||||
type: 'bar',
|
type: 'bar',
|
||||||
@@ -1226,7 +1236,6 @@ window.TICKET_STATUSES = <?= json_encode($GLOBALS['config']['TICKET_STATUSES'])
|
|||||||
if (window.lt) {
|
if (window.lt) {
|
||||||
lt.keys.initDefaults();
|
lt.keys.initDefaults();
|
||||||
lt.tableNav.init('tickets-table');
|
lt.tableNav.init('tickets-table');
|
||||||
lt.statsFilter.init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Saved filter pills — load on page init
|
// Saved filter pills — load on page init
|
||||||
|
|||||||
Reference in New Issue
Block a user