Files
deskhub/chrome-erweiterung/views/home.js
T
2026-11-04 07:55:00 +00:00

56 lines
3.6 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Start: Begrüßung, eigener Status, Kennzahlen, als Nächstes fällige Tickets.
import { h, clear, icon, toast, errText } from '../lib/dom.js';
import { apiCall, AVAILABILITY, openWeb, compareVersions } from '../lib/core.js';
import { spinner, ticketList, showError, segmented } from '../lib/ui.js';
export async function renderHome(host, ctx) {
host.append(spinner());
try {
const [dash, avail] = await Promise.all([
apiCall('dashboard.php').then((r) => r.data),
apiCall('availability.php').then((r) => r.data).catch(() => null),
]);
clear(host);
const first = (ctx.session.staff?.name || '').split(' ')[0];
const stack = h('div', { class: 'stack' });
stack.append(h('div', {}, h('div', { class: 'muted' }, new Date().toLocaleDateString('de-DE', { weekday: 'long', day: 'numeric', month: 'long' })), h('div', { class: 'hello' }, `Hallo ${first || ''}`.trim())));
// Neue Version der Erweiterung: Hinweis mit Weg zum Download (die Seite „Apps“ der Weboberfläche)
try {
const { update } = await chrome.storage.local.get('update');
if (update && compareVersions(update.version, chrome.runtime.getManifest().version) > 0) {
stack.append(h('div', { class: 'card' }, h('h2', {}, `Update verfügbar: ${update.version}`),
h('div', { class: 'muted' }, 'Eine neuere Version der Erweiterung liegt bereit. Auf der Seite „Apps“ laden, entpacken und unter chrome://extensions neu laden.'),
update.notes ? h('div', { class: 'muted', style: { marginTop: '6px', whiteSpace: 'pre-wrap' } }, update.notes) : null,
h('div', { style: { marginTop: '8px' } }, h('button', { class: 'btn', onclick: () => openWeb('/staff/apps.php').catch((e) => toast(errText(e), 'err')) }, 'Download-Seite öffnen'))));
}
} catch { /* ohne Hinweis weiter */ }
if (avail) {
let current = avail.myStatus;
const holder = h('div');
const draw = () => holder.replaceChildren(segmented(Object.entries(AVAILABILITY), current, async (v) => {
const old = current; current = v; draw();
try { await apiCall('availability.php', { method: 'POST', body: { status: v, note: avail.myNote || '' } }); ctx.setStatusDot(v); toast(`Status: ${AVAILABILITY[v]}`); }
catch (e) { current = old; draw(); toast(errText(e), 'err'); }
}));
draw();
ctx.setStatusDot(current);
stack.append(h('div', { class: 'card' }, h('h2', {}, 'Mein Status'), holder));
}
const stat = (value, label, cls, filter) => h('button', { class: `stat ${cls || ''}`, onclick: () => ctx.go('tickets', { filter }) }, h('div', { class: 'v' }, value), h('div', { class: 'k' }, label));
stack.append(h('div', { class: 'stats' },
stat(dash.myOpen ?? 0, 'Meine offenen', '', 'mine'),
stat(dash.overdue ?? 0, 'Überfällig', dash.overdue ? 'warn' : '', 'overdue'),
stat(dash.unassigned ?? 0, 'Nicht zugewiesen', '', 'unassigned'),
stat(dash.unanswered ?? 0, 'Unbeantwortet', '', 'open_status')),
h('div', { class: 'stats' },
h('div', { class: 'stat good' }, h('div', { class: 'v' }, dash.resolvedToday ?? 0), h('div', { class: 'k' }, 'Heute gelöst')),
h('div', { class: 'stat' }, h('div', { class: 'v' }, dash.slaPercent == null ? '–' : `${Math.round(dash.slaPercent)} %`), h('div', { class: 'k' }, 'SLA eingehalten (30 Tage)'))));
stack.append(h('h2', { class: 'sec', style: { margin: '6px 0 0' } }, 'Als Nächstes fällig'), ticketList(dash.recent || [], (t) => ctx.go('ticket', { number: t.number }), 'Alles erledigt. Nichts offen.'));
host.append(stack);
} catch (e) { showError(ctx, host, e); }
}