129 lines
4.3 KiB
JavaScript
129 lines
4.3 KiB
JavaScript
import { apiGet, apiPost, isAuthRedirectError } from '../api.js';
|
|
import { guard } from '../core/auth-guard.js';
|
|
import {
|
|
ticketStatusLabel,
|
|
ticketPriorityLabel,
|
|
statusBadgeClass,
|
|
priorityBadgeClass,
|
|
} from '../core/constants.js';
|
|
import { esc, extrasName } from '../core/utils.js';
|
|
|
|
const loadingEl = document.getElementById('page-loading');
|
|
const mainEl = document.getElementById('page-main');
|
|
const errEl = document.getElementById('page-error');
|
|
|
|
function showError(msg) {
|
|
loadingEl.hidden = true;
|
|
mainEl.hidden = true;
|
|
errEl.hidden = false;
|
|
errEl.textContent = msg;
|
|
}
|
|
|
|
function ticketListQuery() {
|
|
const q = new URLSearchParams(location.search);
|
|
const p = new URLSearchParams();
|
|
if (q.get('status')) p.set('status', q.get('status'));
|
|
if (q.get('priority')) p.set('priority', q.get('priority'));
|
|
if (q.get('machineId')) p.set('machineId', q.get('machineId'));
|
|
const s = p.toString();
|
|
return s ? `?${s}` : '';
|
|
}
|
|
|
|
function fillMachineSelects(allMachines, selectedMid) {
|
|
const selNm = document.getElementById('sel-nm');
|
|
const selFm = document.getElementById('sel-fm');
|
|
const opts = allMachines
|
|
.map(
|
|
(m) =>
|
|
`<option value="${esc(m.id)}">${esc(m.seriennummer)}${extrasName(m) ? ` · ${esc(extrasName(m))}` : ''}</option>`,
|
|
)
|
|
.join('');
|
|
selNm.innerHTML = `<option value="">— wählen —</option>${opts}`;
|
|
selFm.innerHTML = `<option value="">Alle</option>${opts}`;
|
|
if (selectedMid) {
|
|
selNm.value = selectedMid;
|
|
selFm.value = selectedMid;
|
|
}
|
|
}
|
|
|
|
function renderTicketRows(tickets) {
|
|
const tbody = document.getElementById('tickets-table-body');
|
|
tbody.innerHTML = tickets
|
|
.map(
|
|
(t) => `
|
|
<tr${t.isOverdue ? ' class="ticket-row-overdue"' : ''}>
|
|
<td><a href="/ticket.html?id=${esc(t.id)}">${esc(t.title)}</a></td>
|
|
<td><span class="badge ${statusBadgeClass[t.status] || ''}">${esc(ticketStatusLabel[t.status])}</span></td>
|
|
<td><span class="badge ${priorityBadgeClass[t.priority] || ''}">${esc(ticketPriorityLabel[t.priority])}</span></td>
|
|
<td class="muted">${t.machine ? esc(t.machine.seriennummer) : ''}${t.machine ? (extrasName(t.machine) ? ` · ${esc(extrasName(t.machine))}` : '') : ''}</td>
|
|
</tr>`,
|
|
)
|
|
.join('');
|
|
}
|
|
|
|
async function run(canEdit) {
|
|
const qs = ticketListQuery();
|
|
const urlParams = new URLSearchParams(location.search);
|
|
|
|
const newCard = document.getElementById('tickets-new-card');
|
|
if (newCard) newCard.hidden = !canEdit;
|
|
|
|
const [tickets, allMachines] = await Promise.all([
|
|
apiGet(`/tickets${qs}`),
|
|
apiGet('/machines'),
|
|
]);
|
|
|
|
const mid = urlParams.get('machineId') || '';
|
|
fillMachineSelects(allMachines, mid);
|
|
|
|
const filterStatus = urlParams.get('status') || '';
|
|
const filterPriority = urlParams.get('priority') || '';
|
|
const formFilter = document.getElementById('form-filter');
|
|
formFilter.elements.status.value = filterStatus;
|
|
formFilter.elements.priority.value = filterPriority;
|
|
|
|
renderTicketRows(tickets);
|
|
|
|
if (canEdit) {
|
|
document.getElementById('form-new-ticket').onsubmit = async (e) => {
|
|
e.preventDefault();
|
|
const fd = new FormData(e.target);
|
|
await apiPost('/tickets', {
|
|
machineId: fd.get('machineId'),
|
|
title: fd.get('title'),
|
|
description: fd.get('description'),
|
|
});
|
|
e.target.reset();
|
|
fillMachineSelects(allMachines, mid);
|
|
location.reload();
|
|
};
|
|
}
|
|
|
|
document.getElementById('form-filter').onsubmit = (e) => {
|
|
e.preventDefault();
|
|
const fd = new FormData(e.target);
|
|
const p = new URLSearchParams();
|
|
if (fd.get('status')) p.set('status', fd.get('status'));
|
|
if (fd.get('priority')) p.set('priority', fd.get('priority'));
|
|
if (fd.get('machineId')) p.set('machineId', fd.get('machineId'));
|
|
const q = p.toString();
|
|
location.href = `/tickets.html${q ? `?${q}` : ''}`;
|
|
};
|
|
}
|
|
|
|
async function init() {
|
|
const st = await guard({ activeNav: 'tickets' });
|
|
if (!st) return;
|
|
const canEdit = st.user?.canEditCrm === true;
|
|
loadingEl.hidden = true;
|
|
mainEl.hidden = false;
|
|
try {
|
|
await run(canEdit);
|
|
} catch (e) {
|
|
if (isAuthRedirectError(e)) return;
|
|
showError(e.message || 'Fehler');
|
|
}
|
|
}
|
|
|
|
init();
|