diff --git a/assets/css/ticket.css b/assets/css/ticket.css index 8855411..b069d52 100644 --- a/assets/css/ticket.css +++ b/assets/css/ticket.css @@ -85,11 +85,16 @@ body.edit-mode .editable-metadata { border: 1px solid rgba(0, 255, 65, 0.2); } .comment-reply { + /* depth-1 default; .thread-depth-N overrides for deeper nesting */ margin-left: 1.5rem; border-color: rgba(0, 255, 65, 0.12); } -.thread-depth-2 { margin-left: 3rem; } -.thread-depth-3 { margin-left: 4.5rem; } +/* Explicit depth overrides using combined selectors — higher specificity prevents + cascade order from determining winner when both classes are present */ +.comment.thread-depth-2, +.comment-reply.thread-depth-2 { margin-left: 3rem; } +.comment.thread-depth-3, +.comment-reply.thread-depth-3 { margin-left: 4.5rem; } .thread-line { position: absolute; diff --git a/assets/js/dashboard.js b/assets/js/dashboard.js index 2018137..f8976ed 100644 --- a/assets/js/dashboard.js +++ b/assets/js/dashboard.js @@ -99,18 +99,12 @@ document.addEventListener('DOMContentLoaded', function() { if (isDashboard) { // Dashboard-specific initialization - initStatusFilter(); - initTableSorting(); initSidebarFilters(); } // Initialize for all pages initSettingsModal(); - // Force dark mode only (terminal aesthetic - no theme switching) - document.documentElement.setAttribute('data-theme', 'dark'); - document.body.classList.add('dark-mode'); - // Event delegation for dynamically created modals document.addEventListener('click', function(e) { const target = e.target.closest('[data-action]'); @@ -451,233 +445,6 @@ function sortTable(table, column) { // Old settings modal functions removed - now using settings.js with new settings modal -function initStatusFilter() { - const filterContainer = document.createElement('div'); - filterContainer.className = 'status-filter-container'; - - const dropdown = document.createElement('div'); - dropdown.className = 'status-dropdown'; - - const dropdownHeader = document.createElement('div'); - dropdownHeader.className = 'dropdown-header'; - dropdownHeader.textContent = 'Status Filter'; - - const dropdownContent = document.createElement('div'); - dropdownContent.className = 'dropdown-content'; - - const statuses = ['Open', 'In Progress', 'Closed']; - statuses.forEach(status => { - const label = document.createElement('label'); - const checkbox = document.createElement('input'); - checkbox.type = 'checkbox'; - checkbox.value = status; - checkbox.id = `status-${status.toLowerCase().replace(/\s+/g, '-')}`; - - const urlParams = new URLSearchParams(window.location.search); - const currentStatuses = urlParams.get('status') ? urlParams.get('status').split(',') : []; - const showAll = urlParams.get('show_all'); - - // FIXED LOGIC: Determine checkbox state - if (showAll === '1') { - // If show_all=1 parameter exists, all should be checked - checkbox.checked = true; - } else if (currentStatuses.length === 0) { - // No status parameter - default: Open and In Progress checked, Closed unchecked - checkbox.checked = status !== 'Closed'; - } else { - // Status parameter exists - check if this status is in the list - checkbox.checked = currentStatuses.includes(status); - } - - label.appendChild(checkbox); - label.appendChild(document.createTextNode(' ' + status)); - dropdownContent.appendChild(label); - }); - - const saveButton = document.createElement('button'); - saveButton.className = 'btn save-filter'; - saveButton.textContent = 'Apply Filter'; - - saveButton.onclick = () => { - const checkedBoxes = dropdownContent.querySelectorAll('input:checked'); - const selectedStatuses = Array.from(checkedBoxes).map(cb => cb.value); - - const params = new URLSearchParams(window.location.search); - - if (selectedStatuses.length === 0) { - // No statuses selected - show default (Open + In Progress) - params.delete('status'); - params.delete('show_all'); - } else if (selectedStatuses.length === 3) { - // All statuses selected - show all tickets - params.delete('status'); - params.set('show_all', '1'); - } else { - // Some statuses selected - set the parameter - params.set('status', selectedStatuses.join(',')); - params.delete('show_all'); - } - - params.set('page', '1'); - window.location.search = params.toString(); - dropdown.classList.remove('active'); - }; - - dropdownHeader.onclick = () => { - dropdown.classList.toggle('active'); - }; - - dropdown.appendChild(dropdownHeader); - dropdown.appendChild(dropdownContent); - dropdownContent.appendChild(saveButton); - filterContainer.appendChild(dropdown); - - const tableActions = document.querySelector('.table-controls .table-actions'); - if (tableActions) { - tableActions.prepend(filterContainer); - } -} - -function quickSave() { - if (!window.ticketData) { - return; - } - - const statusSelect = document.getElementById('status-select'); - const prioritySelect = document.getElementById('priority-select'); - - if (!statusSelect || !prioritySelect) { - return; - } - - const data = { - ticket_id: parseInt(window.ticketData.id), - status: statusSelect.value, - priority: parseInt(prioritySelect.value) - }; - - lt.api.post('/api/update_ticket.php', data) - .then(result => { - if (result.success) { - // Update the hamburger menu display - const hamburgerStatus = document.getElementById('hamburger-status'); - const hamburgerPriority = document.getElementById('hamburger-priority'); - - if (hamburgerStatus) hamburgerStatus.textContent = statusSelect.value; - if (hamburgerPriority) hamburgerPriority.textContent = 'P' + prioritySelect.value; - - // Update window.ticketData - window.ticketData.status = statusSelect.value; - window.ticketData.priority = parseInt(prioritySelect.value); - - // Update main page elements if they exist - const statusDisplay = document.getElementById('statusDisplay'); - if (statusDisplay) { - statusDisplay.className = `status-${statusSelect.value}`; - statusDisplay.textContent = statusSelect.value; - } - - // Close hamburger menu after successful save - const hamburgerContent = document.querySelector('.hamburger-content'); - if (hamburgerContent) { - hamburgerContent.classList.remove('open'); - document.body.classList.remove('menu-open'); - } - - } else { - lt.toast.error('Error updating ticket: ' + (result.error || 'Unknown error'), 5000); - } - }) - .catch(error => { - lt.toast.error('Error updating ticket: ' + error.message, 5000); - }); -} - - -// Ticket page functions (if needed) -function saveTicket() { - const editables = document.querySelectorAll('.editable'); - const data = {}; - const ticketId = getTicketIdFromUrl(); - - editables.forEach(field => { - if (field.dataset.field) { - data[field.dataset.field] = field.value; - } - }); - - lt.api.post('/api/update_ticket.php', { ticket_id: ticketId, ...data }) - .then(data => { - if(data.success) { - const statusDisplay = document.getElementById('statusDisplay'); - if (statusDisplay) { - statusDisplay.className = `status-${data.status}`; - statusDisplay.textContent = data.status; - } - } else { - lt.toast.error('Error saving ticket: ' + (data.error || 'Unknown error')); - } - }) - .catch(error => { - lt.toast.error('Error saving ticket: ' + error.message); - }); -} -/** - * Load template data into the create ticket form - */ -function loadTemplate() { - const templateSelect = document.getElementById('templateSelect'); - if (!templateSelect) return; - const templateId = templateSelect.value; - - if (!templateId) { - // Clear form when "No Template" is selected - document.getElementById('title').value = ''; - document.getElementById('description').value = ''; - document.getElementById('priority').value = '4'; - document.getElementById('category').value = 'General'; - document.getElementById('type').value = 'Issue'; - const assignedToSelect = document.getElementById('assigned_to'); - if (assignedToSelect) { - assignedToSelect.value = ''; - } - return; - } - - // Fetch template data - lt.api.get(`/api/get_template.php?template_id=${templateId}`) - .then(data => { - if (data.success && data.template) { - const template = data.template; - - // Populate form fields with template data - if (template.title_template) { - document.getElementById('title').value = template.title_template; - } - - if (template.description_template) { - document.getElementById('description').value = template.description_template; - } - - if (template.category) { - document.getElementById('category').value = template.category; - } - - if (template.type) { - document.getElementById('type').value = template.type; - } - - if (template.default_priority) { - document.getElementById('priority').value = template.default_priority; - } - } else { - lt.toast.error('Failed to load template: ' + (data.error || 'Unknown error'), 4000); - } - }) - .catch(error => { - lt.toast.error('Error loading template: ' + error.message, 4000); - }); -} /** * Bulk Actions Functions (Admin only) @@ -1067,9 +834,9 @@ function showBulkDeleteModal() { [ ! ] DELETE ${ticketIds.length} TICKET(S) -
This action cannot be undone!
-You are about to permanently delete ${ticketIds.length} ticket(s).
All associated comments and history will be lost.
This action cannot be undone!
+You are about to permanently delete ${ticketIds.length} ticket(s).
All associated comments and history will be lost.
Ticket #${lt.escHtml(ticketId)}
-Current: ${lt.escHtml(currentStatus)}
+Ticket #${lt.escHtml(ticketId)}
+Current: ${lt.escHtml(currentStatus)}
Ticket #${lt.escHtml(ticketId)}
+Ticket #${lt.escHtml(ticketId)}