UX and architecture fixes: bulk-delete, template guard, statuses config

Bug fixes:
- bulk-delete action called undefined bulkDelete() — wired to the
  existing showBulkDeleteModal() so the confirmation modal actually shows

UX:
- Template loader now checks for existing title/description and asks
  for confirmation before overwriting user-typed content
- Visibility select shows a dynamic hint paragraph that updates when
  the user changes the selection (public/internal/confidential)

Architecture:
- TICKET_STATUSES added to config as single source of truth; all
  hardcoded ['Open','Pending','In Progress','Closed'] arrays in
  DashboardView now read from config; bulk-status modal in dashboard.js
  reads window.TICKET_STATUSES (set from PHP) with array fallback
- ASSET_VERSION now auto-computed from max mtime of dashboard/ticket
  CSS+JS files so browsers always pick up changes on deploy; manual
  override still available via ASSET_VERSION in .env
- Removed 10 dead standalone stat methods from StatsModel (getOpenTicketCount,
  getClosedTicketCount, getTicketsByPriority, etc.) — all superseded by
  the consolidated fetchAllStats() queries, never called externally

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-29 21:09:29 -04:00
parent 277daf6f00
commit 2fdd42b45b
5 changed files with 44 additions and 135 deletions
+6 -4
View File
@@ -51,6 +51,7 @@ if (!empty($_GET['assigned_to'])) {
$activeFilters[] = ['type' => 'assigned_to', 'value' => $_GET['assigned_to'], 'label' => 'Assigned: ' . $label];
}
$_lt_statuses = $GLOBALS['config']['TICKET_STATUSES'];
$currentStatus = isset($_GET['status']) ? explode(',', $_GET['status']) : ['Open', 'Pending', 'In Progress'];
$currentCategories = isset($_GET['category']) ? explode(',', $_GET['category']) : [];
$currentTypes = isset($_GET['type']) ? explode(',', $_GET['type']) : [];
@@ -181,7 +182,7 @@ include __DIR__ . '/layout_header.php';
<!-- Status Filter -->
<fieldset class="lt-filter-group">
<legend class="lt-filter-label">Status</legend>
<?php foreach (['Open', 'Pending', 'In Progress', 'Closed'] as $s): ?>
<?php foreach ($GLOBALS['config']['TICKET_STATUSES'] as $s): ?>
<label class="lt-filter-option">
<input type="checkbox" class="lt-checkbox sidebar-filter"
name="status" value="<?= htmlspecialchars($s) ?>"
@@ -592,11 +593,11 @@ include __DIR__ . '/layout_header.php';
<div class="lt-kv-row">
<span class="lt-kv-label">Default status filters</span>
<span class="lt-kv-value lt-flex lt-flex-wrap lt-flex-gap-sm">
<?php foreach (['Open','Pending','In Progress','Closed'] as $sf): ?>
<?php foreach ($_lt_statuses as $sf): ?>
<label class="lt-filter-option">
<input type="checkbox" class="lt-checkbox" name="defaultFilters" value="<?= $sf ?>"
<input type="checkbox" class="lt-checkbox" name="defaultFilters" value="<?= htmlspecialchars($sf) ?>"
<?= in_array($sf, ['Open','Pending','In Progress']) ? 'checked' : '' ?>>
<?= $sf ?>
<?= htmlspecialchars($sf) ?>
</label>
<?php endforeach ?>
</span>
@@ -824,6 +825,7 @@ include __DIR__ . '/layout_header.php';
DASHBOARD INLINE SCRIPT
═══════════════════════════════════════════════════════════ -->
<script nonce="<?= $nonce ?>">
window.TICKET_STATUSES = <?= json_encode($GLOBALS['config']['TICKET_STATUSES']) ?>;
// Initialize keyboard and table navigation
if (window.lt) {
lt.keys.initDefaults();