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
+19
View File
@@ -180,6 +180,7 @@ include __DIR__ . '/layout_header.php';
<option value="internal">Internal — Specific groups only</option>
<option value="confidential">Confidential — Creator, assignee, and admins only</option>
</select>
<p id="visibilityHint" class="lt-form-hint">Everyone who is logged in can view this ticket.</p>
</div>
<div id="visibilityGroupsContainer" class="lt-form-group is-hidden" aria-live="polite">
@@ -296,21 +297,39 @@ include __DIR__ . '/layout_header.php';
}
// ── Visibility groups toggle ──────────────────────────────
var visibilityHints = {
'public': 'Everyone who is logged in can view this ticket.',
'internal': 'Only members of the selected groups (plus admins) can view this ticket.',
'confidential': 'Only you, the assignee, and admins can view this ticket.'
};
function toggleVisibilityGroups() {
var vis = document.getElementById('visibility').value;
var container = document.getElementById('visibilityGroupsContainer');
var hint = document.getElementById('visibilityHint');
if (vis === 'internal') {
container.classList.remove('is-hidden');
} else {
container.classList.add('is-hidden');
container.querySelectorAll('.visibility-group-checkbox').forEach(function (cb) { cb.checked = false; });
}
if (hint) hint.textContent = visibilityHints[vis] || '';
}
// ── Template loader ───────────────────────────────────────
function loadTemplate() {
var tplId = document.getElementById('templateSelect').value;
if (!tplId) return;
// Warn before overwriting content the user has already typed
var existingTitle = (document.getElementById('title').value || '').trim();
var existingDesc = (document.getElementById('description').value || '').trim();
if (existingTitle || existingDesc) {
if (!confirm('Applying this template will overwrite your current title and description. Continue?')) {
document.getElementById('templateSelect').value = '';
return;
}
}
lt.api.get('/api/get_template.php?template_id=' + encodeURIComponent(tplId))
.then(function (data) {
if (!data.success || !data.template) {