/** * Ticket Detail View * Shows full ticket info with quick-edit dropdowns, article timeline, and add-note form. */ const TicketDetailView = { ticketId: null, htmlMode: true, originalValues: {}, noteAttachments: [], saveDraft() { if (!this.ticketId) return; const body = this.noteQuill ? this.noteQuill.root.innerHTML.trim() : ''; const subject = document.getElementById('note-subject') ? document.getElementById('note-subject').value.trim() : ''; const time_unit = document.getElementById('note-time-units') ? document.getElementById('note-time-units').value.trim() : ''; const ticket_state_id = document.getElementById('note-ticket-state') ? document.getElementById('note-ticket-state').value : ''; if ((body !== '
Scegli se aprire il file con l'applicazione predefinita del tuo computer (Word, Excel, PowerPoint, ecc.) oppure scaricarne una copia locale.
Caricamento ticket...
consuntivazione
'; } else if (!noteBody && noteSubject) { noteBody = `${App.escapeHtml(noteSubject)}
`; } else if (noteBody && !noteSubject) { const tempDiv = document.createElement('div'); tempDiv.innerHTML = noteBody; const plainText = tempDiv.textContent || tempDiv.innerText || ''; noteSubject = plainText.trim().substring(0, 50) || 'consuntivazione'; } const resNote = await App.api(`/api/tickets/${this.ticketId}/articles`, { method: 'POST', body: JSON.stringify({ subject: noteSubject, body: noteBody, time_unit: timeUnitVal, attachments: this.noteAttachments.length > 0 ? this.noteAttachments : undefined }), }); this.noteAttachments = []; // Clear attachments after successful send if (noteCreateTimeVal && resNote.article_id) { try { const formattedDate = noteCreateTimeVal.replace('T', ' '); await App.api(`/api/tickets/articles/${resNote.article_id}/retrodata-article`, { method: 'POST', body: JSON.stringify({ create_time: formattedDate }) }); } catch (retErr) { console.warn('Note retrodate error:', retErr); } } } Toast.success('Modifiche e note salvate con successo!'); App.clearDraft(this.ticketId, 'note'); App.updateDailyTimer(); TicketListView.invalidateCache(); this.render(this.ticketId); } catch (err) { Toast.error('Errore durante il salvataggio: ' + err.message); saveBtn.disabled = false; } }); } // Note Attachments Upload Handlers const noteAttachBtn = document.getElementById('btn-note-add-attachments'); const noteFileInput = document.getElementById('note-attachments'); if (noteAttachBtn && noteFileInput) { noteAttachBtn.addEventListener('click', () => noteFileInput.click()); noteFileInput.addEventListener('change', (e) => { const files = Array.from(e.target.files); for (const file of files) { const reader = new FileReader(); reader.onload = () => { const base64Data = reader.result.split(',')[1]; this.noteAttachments.push({ filename: file.name, content: base64Data, content_type: file.type }); this.updateNoteAttachmentList(); }; reader.readAsDataURL(file); } noteFileInput.value = ''; // Reset input }); } // Email Compose Button const btnEmailCompose = document.getElementById('btn-open-email-compose'); if (btnEmailCompose) { btnEmailCompose.addEventListener('click', () => { if (window.EmailCompose) { const tId = parseInt(btnEmailCompose.dataset.ticketId, 10); const emailDraft = App.getDraft(tId, 'email'); if (emailDraft) { EmailCompose.open({ ...emailDraft.options, draft: emailDraft }); } else { EmailCompose.open({ ticketId: tId, ticketTn: btnEmailCompose.dataset.ticketTn, ticketTitle: btnEmailCompose.dataset.ticketTitle, customerEmail: btnEmailCompose.dataset.customerEmail, }); } } else { Toast.error('Modulo email non disponibile'); } }); } // Article Email Reply Buttons document.querySelectorAll('.btn-email-article').forEach(btn => { btn.addEventListener('click', () => { const articleId = parseInt(btn.dataset.articleId, 10); const article = articles.find(art => art.article_id == articleId); if (!article) return; if (window.EmailCompose) { const rawQuotedBody = article.html_body || article.a_body || ''; const hasHtml = article.has_html || (article.a_content_type || '').toLowerCase().includes('html') || rawQuotedBody.includes('') || rawQuotedBody.includes('/>'); let processedQuoted = rawQuotedBody; if (hasHtml) { const articleAttachments = (attachments || []).filter(att => att.article_id === article.article_id); articleAttachments.forEach(att => { if (att.content_id) { const cleanCid = att.content_id.replace(/[<>]/g, '').trim(); if (cleanCid) { const escapedCid = cleanCid.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); const regex = new RegExp(`cid:${escapedCid}>?`, 'gi'); processedQuoted = processedQuoted.replace(regex, `/api/tickets/attachments/${att.id}`); } } if (att.filename) { const escapedFilename = att.filename.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); const regexFilename = new RegExp(`cid:${escapedFilename}>?`, 'gi'); processedQuoted = processedQuoted.replace(regexFilename, `/api/tickets/attachments/${att.id}`); } }); } const quotedBody = hasHtml ? processedQuoted : App.escapeHtml(article.a_body || '').replace(/\n/g, 'Il ${App.formatDateTime(article.create_time)}, ${App.escapeHtml(article.a_from || 'Sistema')} ha scritto:
${quotedBody}