import { apiGet, apiPost, apiPostForm, apiPut, isAuthRedirectError } from '../api.js'; import { guard } from '../core/auth-guard.js'; import { ticketStatusLabel, ticketPriorityLabel, eventTypeLabel, eventTypeBadgeClass, statusBadgeClass, priorityBadgeClass, } from '../core/constants.js'; import { esc, formatDateTime, extrasName } from '../core/utils.js'; import { bindAttachmentPreview } from '../core/attachment-preview.js'; import { eventInhaltHtml, syncEventFormFieldGroups, buildEventPostBody, loadTeamViewerConnectionsIntoSelect, sortEventsChronologicalWithAttachmentsLast, } from '../core/ticket-events.js'; const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i; const loadingEl = document.getElementById('page-loading'); const badIdEl = document.getElementById('ticket-bad-id'); const errEl = document.getElementById('page-error'); const mainEl = document.getElementById('page-main'); const panelView = document.getElementById('panel-ticket-view'); const panelEdit = document.getElementById('panel-ticket-edit'); function showError(msg) { loadingEl.hidden = true; badIdEl.hidden = true; mainEl.hidden = true; errEl.hidden = false; errEl.textContent = msg; } function fillTicketView(ticket) { document.getElementById('ticket-title').textContent = ticket.title; const stBadge = document.getElementById('t-status-badge'); stBadge.textContent = ticketStatusLabel[ticket.status]; stBadge.className = `badge ${statusBadgeClass[ticket.status] || ''}`; document.getElementById('t-priority-label').textContent = ticketPriorityLabel[ticket.priority]; const slaSel = document.getElementById('t-sla-days'); if (slaSel) { slaSel.value = ticket.slaDays != null && ticket.slaDays !== '' ? String(ticket.slaDays) : ''; } document.getElementById('t-description').textContent = ticket.description; const mrow = document.getElementById('t-machine-row'); if (ticket.machine) { mrow.hidden = false; const mn = extrasName(ticket.machine); const link = document.getElementById('t-machine-link'); link.href = `/machine.html?id=${encodeURIComponent(ticket.machine.id)}`; link.textContent = ticket.machine.seriennummer; document.getElementById('t-machine-suffix').textContent = mn ? ` · ${mn}` : ''; } else { mrow.hidden = true; } } function fillEditForm(ticket) { document.getElementById('tu-title').value = ticket.title; document.getElementById('tu-desc').value = ticket.description; document.getElementById('tu-status').value = ticket.status; document.getElementById('tu-priority').value = ticket.priority; } function renderEvents(events) { const tbody = document.getElementById('events-table-body'); if (events.length === 0) { tbody.innerHTML = '
Mindestens eine Datei auswählen.
', ); setTimeout(() => { document.querySelector('.tv-form-err')?.remove(); }, 4000); return; } const formData = new FormData(); formData.append( 'description', String(fd.get('description_attachment') ?? '').trim(), ); for (let i = 0; i < files.length; i += 1) { formData.append('files', files[i]); } await apiPostForm(`/tickets/${id}/events/attachments`, formData); e.target.reset(); syncEventFormFieldGroups(formEv); location.reload(); return; } let body = buildEventPostBody(id, fd); if (body.type === 'REMOTE') { const sel = document.getElementById('tv-conn-select'); const opt = sel?.selectedOptions?.[0]; if (opt?.value) { body.teamviewerId = opt.value; const sd = opt.getAttribute('data-start-date'); const ed = opt.getAttribute('data-end-date'); if (sd) body.teamviewerStartDate = sd; if (ed) body.teamviewerEndDate = ed; const n = opt.getAttribute('data-notes'); if (n && String(n).trim()) body.teamviewerNotes = String(n).trim(); const dn = opt.getAttribute('data-devicename') || ''; const u = String(fd.get('description_remote') ?? '').trim(); if (dn) { body.description = u ? `${u}\n\nTeamViewer-Gerät: ${dn}` : `TeamViewer-Gerät: ${dn}`; } else if (u) { body.description = u; } else { body.description = 'Remote-Session (TeamViewer)'; } } else { body.description = String(body.description ?? '').trim(); if (!body.description) { formEv.insertAdjacentHTML( 'afterbegin', 'Beschreibung oder Gerät auswählen.
', ); setTimeout(() => { document.querySelector('.tv-form-err')?.remove(); }, 4000); return; } } } await apiPost('/events', body); e.target.reset(); syncEventFormFieldGroups(formEv); location.reload(); }; document.getElementById('form-t2').onsubmit = async (e) => { e.preventDefault(); const fd = new FormData(e.target); await apiPost('/tickets', { machineId: currentTicket.machineId, title: fd.get('title'), description: fd.get('description'), }); e.target.reset(); location.reload(); }; } async function init() { const st = await guard({ activeNav: 'tickets' }); if (!st) return; const id = new URLSearchParams(location.search).get('id'); if (!id || !UUID.test(id)) { loadingEl.hidden = true; badIdEl.hidden = false; return; } loadingEl.hidden = true; mainEl.hidden = false; bindAttachmentPreview(document.body); try { await viewTicketDetail(id); } catch (e) { if (isAuthRedirectError(e)) return; showError(e.message || 'Fehler'); } } init();