Sidebar with no hamburger menu

This commit is contained in:
2026-01-07 17:47:11 -05:00
parent 0f25c49d5c
commit cf2d596219
3 changed files with 534 additions and 808 deletions

View File

@@ -90,7 +90,6 @@ h1 {
.user-header {
background: var(--bg-secondary);
padding: 0.5rem 1rem;
margin-left: 50px; /* Space for hamburger menu */
color: var(--terminal-green);
display: flex;
justify-content: space-between;
@@ -1163,223 +1162,307 @@ input[type="checkbox"]:checked {
cursor: pointer;
}
/* ===== HAMBURGER MENU STYLES - TERMINAL EDITION ===== */
.hamburger-menu {
position: absolute;
top: 20px;
left: 20px;
z-index: 100;
}
.hamburger-icon {
cursor: pointer;
font-size: 24px;
/* ===== COLLAPSIBLE ASCII BANNER ===== */
.ascii-banner-wrapper {
max-width: 1600px;
margin: 0 auto 1rem auto;
border: 2px solid var(--terminal-green);
background: var(--bg-secondary);
padding: 12px;
border: 2px solid var(--terminal-green);
border-radius: 0;
box-shadow: none;
font-family: var(--font-mono);
color: var(--terminal-green);
}
.hamburger-icon::before {
content: '[';
margin-right: 4px;
.ascii-banner-wrapper.collapsed .banner-content {
display: none;
}
.hamburger-icon::after {
content: ']';
margin-left: 4px;
}
.hamburger-content {
position: fixed;
top: 0;
left: -300px;
width: 250px;
height: 100%;
background: var(--bg-primary);
border-right: 3px double var(--terminal-green);
transition: left 0.3s ease;
padding: 20px;
overflow-y: auto;
z-index: 99;
font-family: var(--font-mono);
box-shadow: 0 0 30px rgba(0, 255, 65, 0.3);
}
/* ASCII decoration at top */
.hamburger-content::before {
content: '╔═══════════════════╗\A║ MENU SYSTEM ║\A╚═══════════════════╝';
white-space: pre;
display: block;
color: var(--terminal-green);
font-family: var(--font-mono);
font-size: 0.8rem;
margin-bottom: 20px;
line-height: 1.2;
}
.hamburger-content.open {
left: 0;
}
.hamburger-content h3 {
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
font-family: var(--font-mono);
text-transform: uppercase;
margin-top: 20px;
margin-bottom: 10px;
}
.hamburger-content h3::before {
content: '> ';
color: var(--terminal-green);
}
.close-hamburger {
position: absolute;
top: 10px;
right: 10px;
cursor: pointer;
font-size: 24px;
background: transparent;
padding: 10px;
border: 2px solid var(--terminal-green);
border-radius: 0;
box-shadow: none;
color: var(--terminal-green);
font-family: var(--font-mono);
}
.close-hamburger::before {
content: '[';
}
.close-hamburger::after {
content: ']';
}
.close-hamburger:hover {
color: var(--priority-1);
border-color: var(--priority-1);
text-shadow: var(--glow-red);
}
/* Hamburger menu inline editing styles - TERMINAL */
.ticket-info-editable {
padding: 10px 0;
}
.editable-field, .info-field {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
position: relative;
padding: 10px;
border: 1px solid var(--terminal-green);
background: rgba(0, 255, 65, 0.03);
}
.editable-field label, .info-field label {
flex: 0 0 auto;
margin-right: 10px;
color: var(--terminal-green);
font-family: var(--font-mono);
}
.editable-value {
flex: 1;
text-align: right;
min-height: 20px;
display: inline-block;
cursor: pointer;
padding: 4px 8px;
border-radius: 0;
transition: all 0.2s;
color: var(--terminal-amber);
}
.editable-value::before {
content: '[ ';
color: var(--terminal-green);
}
.editable-value::after {
content: ' ]';
color: var(--terminal-green);
}
.editable-value:hover {
background-color: rgba(0, 255, 65, 0.1) !important;
text-shadow: var(--glow-amber);
}
.edit-dropdown {
position: absolute;
top: 100%;
right: 0;
background: var(--bg-primary);
border: 2px solid var(--terminal-green);
border-radius: 0;
padding: 8px;
box-shadow: 0 0 20px rgba(0, 255, 65, 0.3);
z-index: 1000;
min-width: 150px;
}
.field-select {
.banner-toggle {
width: 100%;
padding: 4px 8px;
background: var(--bg-secondary);
border: none;
color: var(--terminal-amber);
padding: 0.5rem 1rem;
cursor: pointer;
font-family: var(--font-mono);
text-align: left;
font-size: 0.9rem;
text-shadow: var(--glow-amber);
transition: all 0.2s ease;
}
.banner-toggle:hover {
background: var(--hover-bg);
box-shadow: inset 0 0 20px rgba(255, 176, 0, 0.2);
}
.toggle-icon {
display: inline-block;
width: 1rem;
text-align: center;
color: var(--terminal-green);
transition: transform 0.3s ease;
}
.banner-content {
padding: 1rem;
text-align: center;
}
/* ===== CONDENSED TOOLBAR ===== */
.dashboard-toolbar {
display: flex;
flex-wrap: wrap;
gap: 1rem;
align-items: center;
justify-content: space-between;
padding: 1rem;
background: var(--bg-secondary);
border: 2px solid var(--terminal-green);
margin-bottom: 1rem;
box-shadow: var(--glow-green);
}
.toolbar-left {
display: flex;
align-items: center;
gap: 1rem;
flex: 1;
min-width: 300px;
}
.dashboard-title {
font-family: var(--font-mono);
color: var(--terminal-green);
text-shadow: var(--glow-green);
font-size: 1.5rem;
margin: 0;
white-space: nowrap;
}
.toolbar-search {
display: flex;
gap: 0.5rem;
flex: 1;
}
.toolbar-center {
display: flex;
align-items: center;
gap: 1rem;
}
.toolbar-right {
display: flex;
align-items: center;
}
.ticket-count {
font-family: var(--font-mono);
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
font-size: 0.9rem;
white-space: nowrap;
}
.clear-search-btn {
background: var(--bg-primary);
color: var(--priority-1);
border: 2px solid var(--priority-1);
padding: 0.5rem 0.75rem;
font-family: var(--font-mono);
text-decoration: none;
cursor: pointer;
transition: all 0.2s ease;
}
.clear-search-btn:hover {
background: var(--priority-1);
color: var(--bg-primary);
box-shadow: var(--glow-red);
}
.search-results-info {
background: var(--bg-secondary);
border: 2px solid var(--terminal-amber);
padding: 0.75rem 1rem;
margin-bottom: 1rem;
font-family: var(--font-mono);
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
}
/* Inline Bulk Actions */
.bulk-actions-inline {
padding: 0.75rem 1rem;
background: var(--bg-primary);
border: 2px solid var(--terminal-amber);
border-radius: 0;
margin-bottom: 8px;
margin-bottom: 1rem;
display: flex;
gap: 1rem;
align-items: center;
font-family: var(--font-mono);
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
box-shadow: inset 0 0 20px rgba(255, 176, 0, 0.2);
}
.bulk-actions-inline .btn {
padding: 0.4rem 0.8rem;
font-size: 0.85rem;
}
/* Mobile: Stack toolbar items */
@media (max-width: 1024px) {
.dashboard-toolbar {
flex-direction: column;
align-items: stretch;
}
.toolbar-left,
.toolbar-center,
.toolbar-right {
width: 100%;
justify-content: space-between;
}
.toolbar-search {
min-width: 100%;
}
.dashboard-title {
font-size: 1.2rem;
}
}
@media (max-width: 768px) {
.toolbar-left {
flex-direction: column;
align-items: stretch;
}
.dashboard-title {
text-align: center;
}
}
/* ===== DASHBOARD SIDEBAR LAYOUT ===== */
.dashboard-layout {
display: flex;
gap: 1.5rem;
max-width: 1600px;
margin: 0 auto;
padding: 0 1rem;
}
.dashboard-sidebar {
width: 250px;
flex-shrink: 0;
position: sticky;
top: 1rem;
max-height: calc(100vh - 2rem);
overflow-y: auto;
}
.dashboard-sidebar .ascii-frame-inner {
background: var(--bg-secondary);
padding: 1rem;
border: 2px solid var(--terminal-green);
box-shadow: var(--glow-green);
}
.dashboard-sidebar .ascii-subsection-header {
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
font-family: var(--font-mono);
font-size: 1.1rem;
text-transform: uppercase;
margin-bottom: 1rem;
padding-bottom: 0.5rem;
border-bottom: 2px solid var(--terminal-green);
}
.filter-group {
margin-bottom: 1.5rem;
}
.filter-group h4 {
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
margin: 0 0 0.5rem 0;
font-size: 0.9rem;
text-transform: uppercase;
font-family: var(--font-mono);
}
.filter-group label {
display: block;
margin: 0.4rem 0;
color: var(--terminal-green);
cursor: pointer;
font-size: 0.85rem;
font-family: var(--font-mono);
transition: all 0.2s ease;
}
.filter-group label:hover {
color: var(--terminal-amber);
text-shadow: var(--glow-amber);
padding-left: 4px;
}
.filter-group input[type="checkbox"] {
margin-right: 0.5rem;
cursor: pointer;
accent-color: var(--terminal-green);
}
.dashboard-sidebar .btn {
width: 100%;
margin-top: 0.5rem;
padding: 0.5rem;
background: var(--bg-primary);
color: var(--terminal-green);
border: 2px solid var(--terminal-green);
font-family: var(--font-mono);
color: var(--text-primary);
}
.edit-actions {
display: flex;
gap: 4px;
justify-content: flex-end;
}
.save-btn, .cancel-btn {
padding: 4px 8px;
border: none;
border-radius: 0;
cursor: pointer;
font-size: 12px;
min-width: 24px;
transition: all 0.2s ease;
}
.save-btn {
background: #28a745;
color: white;
.dashboard-sidebar .btn:hover {
background: var(--terminal-green);
color: var(--bg-primary);
box-shadow: var(--glow-green);
}
.save-btn:hover {
background: #218838;
.dashboard-sidebar .btn-secondary {
background: transparent;
color: var(--terminal-amber);
border-color: var(--terminal-amber);
}
.cancel-btn {
background: #dc3545;
color: white;
.dashboard-sidebar .btn-secondary:hover {
background: var(--terminal-amber);
color: var(--bg-primary);
box-shadow: var(--glow-amber);
}
.cancel-btn:hover {
background: #c82333;
}
.info-field span {
.dashboard-main {
flex: 1;
text-align: right;
color: var(--text-secondary);
min-width: 0;
}
/* Mobile: Stack sidebar above content */
@media (max-width: 768px) {
.dashboard-layout {
flex-direction: column;
padding: 0 0.5rem;
}
.dashboard-sidebar {
width: 100%;
position: static;
max-height: none;
margin-bottom: 1rem;
}
}
/* ===== UTILITY STYLES ===== */

View File

@@ -17,23 +17,7 @@ document.addEventListener('DOMContentLoaded', function() {
// Dashboard-specific initialization
initStatusFilter();
initTableSorting();
console.log('Creating hamburger menu for dashboard...');
try {
createHamburgerMenu();
console.log('Hamburger menu created successfully');
} catch (error) {
console.error('Error creating hamburger menu:', error);
}
} else if (isTicketPage) {
// Ticket page initialization
console.log('Creating hamburger menu for ticket page...');
try {
createHamburgerMenu();
console.log('Hamburger menu created successfully');
} catch (error) {
console.error('Error creating hamburger menu:', error);
}
initSidebarFilters();
}
// Initialize for all pages
@@ -55,6 +39,72 @@ function initTableSorting() {
});
}
function initSidebarFilters() {
const applyFiltersBtn = document.getElementById('apply-filters-btn');
const clearFiltersBtn = document.getElementById('clear-filters-btn');
if (applyFiltersBtn) {
applyFiltersBtn.addEventListener('click', () => {
const params = new URLSearchParams(window.location.search);
// Collect selected statuses
const selectedStatuses = Array.from(
document.querySelectorAll('.filter-group input[name="status"]:checked')
).map(cb => cb.value);
// Collect selected categories
const selectedCategories = Array.from(
document.querySelectorAll('.filter-group input[name="category"]:checked')
).map(cb => cb.value);
// Collect selected types
const selectedTypes = Array.from(
document.querySelectorAll('.filter-group input[name="type"]:checked')
).map(cb => cb.value);
// Update URL parameters
if (selectedStatuses.length > 0) {
params.set('status', selectedStatuses.join(','));
} else {
params.delete('status');
}
if (selectedCategories.length > 0) {
params.set('category', selectedCategories.join(','));
} else {
params.delete('category');
}
if (selectedTypes.length > 0) {
params.set('type', selectedTypes.join(','));
} else {
params.delete('type');
}
// Reset to page 1 when filters change
params.set('page', '1');
// Reload with new parameters
window.location.search = params.toString();
});
}
if (clearFiltersBtn) {
clearFiltersBtn.addEventListener('click', () => {
const params = new URLSearchParams(window.location.search);
// Remove filter parameters
params.delete('status');
params.delete('category');
params.delete('type');
params.set('page', '1');
// Reload with cleared filters
window.location.search = params.toString();
});
}
}
function initSettingsModal() {
const settingsIcon = document.querySelector('.settings-icon');
if (settingsIcon) {
@@ -354,452 +404,6 @@ function quickSave() {
});
}
function createHamburgerMenu() {
console.log('createHamburgerMenu called');
// Remove any existing hamburger menu first
const existingMenu = document.querySelector('.hamburger-menu');
if (existingMenu) {
console.log('Removing existing menu');
existingMenu.remove();
}
const hamburgerMenu = document.createElement('div');
hamburgerMenu.className = 'hamburger-menu';
// Better detection for ticket pages
const isTicketPage = window.location.pathname.includes('/ticket/') ||
window.location.href.includes('ticket.php') ||
document.querySelector('.ticket-details') !== null;
console.log('Is ticket page:', isTicketPage);
console.log('Has ticketData:', !!window.ticketData);
console.log('TicketData contents:', window.ticketData);
if (isTicketPage) {
// Wait for ticketData if it's not loaded yet
if (!window.ticketData) {
console.log('Waiting for ticket data...');
setTimeout(() => {
if (window.ticketData) {
console.log('Ticket data now available, recreating menu');
createHamburgerMenu();
}
}, 100);
return;
}
console.log('Creating ticket hamburger menu with data:', window.ticketData);
// Ticket page hamburger menu with inline editing
hamburgerMenu.innerHTML = `
<div class="hamburger-icon">☰</div>
<div class="hamburger-content">
<div class="close-hamburger">☰</div>
<div class="ascii-subsection-header">Ticket Actions</div>
<div class="ascii-frame-inner">
<div class="ticket-info-editable">
<div class="editable-field" data-field="priority">
<label><strong>Priority:</strong></label>
<span class="editable-value" data-current="${window.ticketData.priority}">P${window.ticketData.priority}</span>
<div class="edit-dropdown" style="display: none;">
<select class="field-select">
<option value="1" ${String(window.ticketData.priority) === '1' ? 'selected' : ''}>P1 - Critical</option>
<option value="2" ${String(window.ticketData.priority) === '2' ? 'selected' : ''}>P2 - High</option>
<option value="3" ${String(window.ticketData.priority) === '3' ? 'selected' : ''}>P3 - Medium</option>
<option value="4" ${String(window.ticketData.priority) === '4' ? 'selected' : ''}>P4 - Low</option>
<option value="5" ${String(window.ticketData.priority) === '5' ? 'selected' : ''}>P5 - Lowest</option>
</select>
<div class="edit-actions">
<button class="save-btn">✓</button>
<button class="cancel-btn">✗</button>
</div>
</div>
</div>
<div class="editable-field" data-field="category">
<label><strong>Category:</strong></label>
<span class="editable-value" data-current="${window.ticketData.category}">${window.ticketData.category}</span>
<div class="edit-dropdown" style="display: none;">
<select class="field-select">
<option value="Hardware" ${window.ticketData.category === 'Hardware' ? 'selected' : ''}>Hardware</option>
<option value="Software" ${window.ticketData.category === 'Software' ? 'selected' : ''}>Software</option>
</select>
<div class="edit-actions">
<button class="save-btn">✓</button>
<button class="cancel-btn">✗</button>
</div>
</div>
</div>
<div class="editable-field" data-field="type">
<label><strong>Type:</strong></label>
<span class="editable-value" data-current="${window.ticketData.type}">${window.ticketData.type}</span>
<div class="edit-dropdown" style="display: none;">
<select class="field-select">
<option value="Install" ${window.ticketData.type === 'Install' ? 'selected' : ''}>Install</option>
<option value="Maintenance" ${window.ticketData.type === 'Maintenance' ? 'selected' : ''}>Maintenance</option>
<option value="Problem" ${window.ticketData.type === 'Problem' ? 'selected' : ''}>Problem</option>
<option value="Request" ${window.ticketData.type === 'Request' ? 'selected' : ''}>Request</option>
<option value="Task" ${window.ticketData.type === 'Task' ? 'selected' : ''}>Task</option>
<option value="Upgrade" ${window.ticketData.type === 'Upgrade' ? 'selected' : ''}>Upgrade</option>
</select>
<div class="edit-actions">
<button class="save-btn">✓</button>
<button class="cancel-btn">✗</button>
</div>
</div>
</div>
</div>
</div>
</div>
`;
console.log('Ticket hamburger menu HTML created');
// Add inline editing functionality
setupInlineEditing(hamburgerMenu);
} else {
console.log('Creating dashboard hamburger menu');
// Dashboard hamburger menu (your existing code)
hamburgerMenu.innerHTML = `
<div class="hamburger-icon">☰</div>
<div class="hamburger-content">
<div class="close-hamburger">☰</div>
<div class="ascii-subsection-header">Filters</div>
<div class="ascii-frame-inner">
<div class="dashboard-filters">
<div class="filter-section">
<h4>Categories</h4>
<div id="category-filters"></div>
</div>
<div class="filter-section">
<h4>Types</h4>
<div id="type-filters"></div>
</div>
<div class="filter-actions">
<button id="apply-filters">Apply Filters</button>
<button id="clear-filters">Clear Filters</button>
</div>
</div>
</div>
</div>
`;
// Get current URL parameters
const urlParams = new URLSearchParams(window.location.search);
const currentCategories = urlParams.get('category') ? urlParams.get('category').split(',') : [];
const currentTypes = urlParams.get('type') ? urlParams.get('type').split(',') : [];
// Get containers
const categoriesContainer = hamburgerMenu.querySelector('#category-filters');
const typesContainer = hamburgerMenu.querySelector('#type-filters');
// Get data from body attributes
const categories = JSON.parse(document.body.dataset.categories || '[]');
const types = JSON.parse(document.body.dataset.types || '[]');
// Create checkboxes for categories
categories.forEach(category => {
const label = document.createElement('label');
label.style.display = 'block';
label.style.marginBottom = '5px';
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.value = category;
checkbox.name = 'category';
const isChecked = currentCategories.includes(category);
label.appendChild(checkbox);
label.appendChild(document.createTextNode(' ' + category));
categoriesContainer.appendChild(label);
checkbox.checked = isChecked;
});
// Create checkboxes for types
types.forEach(type => {
const label = document.createElement('label');
label.style.display = 'block';
label.style.marginBottom = '5px';
const checkbox = document.createElement('input');
checkbox.type = 'checkbox';
checkbox.value = type;
checkbox.name = 'type';
const isChecked = currentTypes.includes(type);
label.appendChild(checkbox);
label.appendChild(document.createTextNode(' ' + type));
typesContainer.appendChild(label);
checkbox.checked = isChecked;
});
// Apply filters event
const applyFiltersBtn = hamburgerMenu.querySelector('#apply-filters');
applyFiltersBtn.addEventListener('click', () => {
const selectedCategories = Array.from(
categoriesContainer.querySelectorAll('input:checked')
).map(cb => cb.value);
const selectedTypes = Array.from(
typesContainer.querySelectorAll('input:checked')
).map(cb => cb.value);
const params = new URLSearchParams(window.location.search);
if (selectedCategories.length > 0) {
params.set('category', selectedCategories.join(','));
} else {
params.delete('category');
}
if (selectedTypes.length > 0) {
params.set('type', selectedTypes.join(','));
} else {
params.delete('type');
}
params.set('page', '1');
window.location.search = params.toString();
});
// Clear filters event
const clearFiltersBtn = hamburgerMenu.querySelector('#clear-filters');
clearFiltersBtn.addEventListener('click', () => {
const params = new URLSearchParams(window.location.search);
params.delete('category');
params.delete('type');
params.set('page', '1');
window.location.search = params.toString();
});
}
console.log('Adding hamburger menu to body');
// Add to body
document.body.appendChild(hamburgerMenu);
console.log('Hamburger menu added, setting up event listeners');
// Toggle hamburger menu
const hamburgerIcon = hamburgerMenu.querySelector('.hamburger-icon');
const hamburgerContent = hamburgerMenu.querySelector('.hamburger-content');
if (hamburgerIcon && hamburgerContent) {
hamburgerIcon.addEventListener('click', () => {
console.log('Hamburger icon clicked');
hamburgerContent.classList.toggle('open');
document.body.classList.toggle('menu-open');
});
// Close hamburger menu
const closeButton = hamburgerMenu.querySelector('.close-hamburger');
if (closeButton) {
closeButton.addEventListener('click', () => {
console.log('Close button clicked');
hamburgerContent.classList.remove('open');
document.body.classList.remove('menu-open');
});
}
console.log('Hamburger menu created successfully');
} else {
console.error('Failed to find hamburger icon or content');
}
}
function setupInlineEditing(hamburgerMenu) {
const editableFields = hamburgerMenu.querySelectorAll('.editable-field');
editableFields.forEach(field => {
const valueSpan = field.querySelector('.editable-value');
const dropdown = field.querySelector('.edit-dropdown');
const select = field.querySelector('.field-select');
const saveBtn = field.querySelector('.save-btn');
const cancelBtn = field.querySelector('.cancel-btn');
const fieldName = field.dataset.field;
// Make value span clickable
valueSpan.style.cursor = 'pointer';
valueSpan.style.padding = '4px 8px';
valueSpan.style.borderRadius = '4px';
valueSpan.style.transition = 'background-color 0.2s';
// Hover effect
valueSpan.addEventListener('mouseenter', () => {
valueSpan.style.backgroundColor = 'var(--hover-bg, #f0f0f0)';
});
valueSpan.addEventListener('mouseleave', () => {
if (dropdown.style.display === 'none') {
valueSpan.style.backgroundColor = 'transparent';
}
});
// Click to edit
valueSpan.addEventListener('click', () => {
dropdown.style.display = 'block';
valueSpan.style.backgroundColor = 'var(--hover-bg, #f0f0f0)';
select.focus();
});
// Save changes
saveBtn.addEventListener('click', () => {
const newValue = select.value;
const oldValue = valueSpan.dataset.current;
if (newValue !== oldValue) {
saveFieldChange(fieldName, newValue, valueSpan, dropdown);
} else {
cancelEdit(valueSpan, dropdown);
}
});
// Cancel changes
cancelBtn.addEventListener('click', () => {
select.value = valueSpan.dataset.current;
cancelEdit(valueSpan, dropdown);
});
// Cancel on escape key
select.addEventListener('keydown', (e) => {
if (e.key === 'Escape') {
select.value = valueSpan.dataset.current;
cancelEdit(valueSpan, dropdown);
} else if (e.key === 'Enter') {
saveBtn.click();
}
});
// Cancel when clicking outside
document.addEventListener('click', (e) => {
if (!field.contains(e.target) && dropdown.style.display === 'block') {
select.value = valueSpan.dataset.current;
cancelEdit(valueSpan, dropdown);
}
});
});
}
function saveFieldChange(fieldName, newValue, valueSpan, dropdown) {
if (!window.ticketData) {
console.error('No ticket data available');
return;
}
const data = {
ticket_id: parseInt(window.ticketData.id),
[fieldName]: fieldName === 'priority' ? parseInt(newValue) : newValue
};
console.log('Saving field change:', data);
// Show loading state
valueSpan.style.opacity = '0.6';
fetch('/api/update_ticket.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(data)
})
.then(response => {
return response.text().then(text => {
try {
return JSON.parse(text);
} catch (e) {
throw new Error('Invalid JSON response: ' + text);
}
});
})
.then(result => {
console.log('Update result:', result);
if (result.success) {
// Update the hamburger menu display
if (fieldName === 'priority') {
valueSpan.textContent = 'P' + newValue;
} else {
valueSpan.textContent = newValue;
}
valueSpan.dataset.current = newValue;
// Update window.ticketData
window.ticketData[fieldName] = fieldName === 'priority' ? parseInt(newValue) : newValue;
// Update main page elements
if (fieldName === 'status') {
const statusDisplay = document.getElementById('statusDisplay');
if (statusDisplay) {
// Remove all existing status classes
statusDisplay.className = statusDisplay.className.replace(/status-\S+/g, '').trim();
// Create the correct CSS class name to match your CSS
// "Open" -> "status-Open"
// "In Progress" -> "status-In-Progress"
// "Closed" -> "status-Closed"
const cssClass = newValue.replace(/\s+/g, '-'); // "In Progress" -> "In-Progress"
const fullClassName = `status-${cssClass}`;
statusDisplay.className = fullClassName;
statusDisplay.textContent = newValue;
console.log('Updated status display class to:', fullClassName);
console.log('Status display element:', statusDisplay);
}
}
if (fieldName === 'priority') {
const priorityDisplay = document.querySelector('.priority-indicator');
if (priorityDisplay) {
// Remove all priority classes first
priorityDisplay.className = priorityDisplay.className.replace(/priority-\d+/g, '');
priorityDisplay.className = `priority-indicator priority-${newValue}`;
priorityDisplay.textContent = 'P' + newValue;
}
// Update the ticket container's data-priority attribute for styling
const ticketContainer = document.querySelector('.ticket-container');
if (ticketContainer) {
ticketContainer.setAttribute('data-priority', newValue);
}
}
console.log('Field updated successfully');
cancelEdit(valueSpan, dropdown);
} else {
console.error('Error updating field:', result.error || 'Unknown error');
alert('Error updating ' + fieldName + ': ' + (result.error || 'Unknown error'));
cancelEdit(valueSpan, dropdown);
}
})
.catch(error => {
console.error('Error updating field:', error);
alert('Error updating ' + fieldName + ': ' + error.message);
cancelEdit(valueSpan, dropdown);
})
.finally(() => {
valueSpan.style.opacity = '1';
});
}
function cancelEdit(valueSpan, dropdown) {
dropdown.style.display = 'none';
valueSpan.style.backgroundColor = 'transparent';
}
// Ticket page functions (if needed)
function saveTicket() {
@@ -921,14 +525,16 @@ function toggleSelectAll() {
function updateSelectionCount() {
const checkboxes = document.querySelectorAll('.ticket-checkbox:checked');
const count = checkboxes.length;
const toolbar = document.querySelector('.bulk-actions-toolbar');
const toolbar = document.querySelector('.bulk-actions-inline');
const countDisplay = document.getElementById('selected-count');
if (count > 0) {
toolbar.style.display = 'flex';
countDisplay.textContent = count;
} else {
toolbar.style.display = 'none';
if (toolbar && countDisplay) {
if (count > 0) {
toolbar.style.display = 'flex';
countDisplay.textContent = count;
} else {
toolbar.style.display = 'none';
}
}
}