diff --git a/public/js/app.js b/public/js/app.js index ef98728..ae65be6 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -66,6 +66,7 @@ const App = { quick_edit_save: { ctrl: true, alt: false, shift: false, key: 'Enter', enabled: true }, pdf_save_edited: { ctrl: true, alt: false, shift: false, key: 'Enter', enabled: true }, ricerca_spudorata_open: { ctrl: true, alt: false, shift: true, key: 'f', enabled: true }, + ticket_list_open: { ctrl: true, alt: false, shift: true, key: 'Backspace', enabled: true }, }; return defaults[id] || { ctrl: true, alt: false, shift: false, key: 'Enter', enabled: true }; }, @@ -295,6 +296,11 @@ const App = { searchInput.select(); } } + } else if (this.isShortcutTriggered(e, 'ticket_list_open')) { + if (window.location.hash !== '#/tickets' && window.location.hash !== '') { + e.preventDefault(); + window.location.hash = '#/tickets'; + } } }); diff --git a/public/js/views/shortcuts.js b/public/js/views/shortcuts.js index 6374c10..c5983b2 100644 --- a/public/js/views/shortcuts.js +++ b/public/js/views/shortcuts.js @@ -72,6 +72,13 @@ const ShortcutsView = { context: 'Globale', defaultCombo: { ctrl: true, alt: false, shift: true, key: 'f', enabled: true } }, + { + id: 'ticket_list_open', + name: 'Torna a Elenco Ticket', + description: 'Naviga direttamente alla pagina principale dell\'elenco ticket', + context: 'Globale', + defaultCombo: { ctrl: true, alt: false, shift: true, key: 'Backspace', enabled: true } + }, { id: 'create_ticket_submit', name: 'Invia Nuovo Ticket', diff --git a/public/js/views/ticketDetail.js b/public/js/views/ticketDetail.js index 23ff7a8..6da781d 100644 --- a/public/js/views/ticketDetail.js +++ b/public/js/views/ticketDetail.js @@ -3577,7 +3577,12 @@ const TicketDetailView = { queueSearchInput.addEventListener('input', () => { clearTimeout(queueDebounce); const q = queueSearchInput.value.trim(); - if (queueIdInput) queueIdInput.value = ''; + const origQueueName = (this.originalValues['queue_name'] || '').trim(); + if (q !== origQueueName) { + if (queueIdInput) queueIdInput.value = ''; + } else { + if (queueIdInput) queueIdInput.value = String(this.originalValues['queue_id'] || ''); + } checkChanges(); queueDebounce = setTimeout(async () => { @@ -3699,8 +3704,13 @@ const TicketDetailView = { saveBtn.addEventListener('click', async () => { const queueSearch = queueSearchInput ? queueSearchInput.value.trim() : ''; if (queueSearchInput && !queueIdInput.value) { - Toast.warning('Seleziona una coda valida dall\'elenco.'); - return; + const origName = (this.originalValues['queue_name'] || '').trim(); + if (queueSearch === origName && this.originalValues['queue_id']) { + queueIdInput.value = String(this.originalValues['queue_id']); + } else { + Toast.warning('Seleziona una coda valida dall\'elenco.'); + return; + } } const customerSearch = customerSearchInput ? customerSearchInput.value.trim() : ''; diff --git a/routes/tickets.js b/routes/tickets.js index d9dbc50..bd3dcd6 100644 --- a/routes/tickets.js +++ b/routes/tickets.js @@ -916,8 +916,8 @@ router.patch('/:id', async (req, res) => { if (updates.type_id !== undefined) ticketFields.TypeID = updates.type_id; if (updates.title !== undefined) ticketFields.Title = updates.title; if (updates.ticket_lock_id !== undefined) ticketFields.LockID = updates.ticket_lock_id; - if (updates.customer_id !== undefined) ticketFields.CustomerID = updates.customer_id; - if (updates.customer_user_id !== undefined) ticketFields.CustomerUser = updates.customer_user_id; + if (updates.customer_id !== undefined && updates.customer_id !== null && updates.customer_id !== '') ticketFields.CustomerID = updates.customer_id; + if (updates.customer_user_id !== undefined && updates.customer_user_id !== null && updates.customer_user_id !== '') ticketFields.CustomerUser = updates.customer_user_id; // If ticketFields is empty but we have a note or timeUnit to log, supply a dummy field (StateID) so Ticket is not empty if (Object.keys(ticketFields).length === 0 && (hasNote || (!isNaN(timeUnit) && timeUnit > 0))) { @@ -986,6 +986,7 @@ router.patch('/:id', async (req, res) => { const client = await pool.connect(); try { await client.query('BEGIN'); + const localNow = getLocalTimestamp(); // If state is changing, check if the target state is a closed state type to auto-unlock if (updates.ticket_state_id && updates.ticket_state_id !== current.ticket_state_id) {