'use strict'; // Verwaltungsbereich „Statusseite“: öffentliche Seite für Kunden mit dem Zustand der Dienste und Störungsmeldungen. // Gleicher Funktionsumfang wie in der Android-App; die Texte der Seite selbst stehen unter /status.php. async function adminStatusPage(body) { const A = 'status.php'; const COLORS = { operational: '#157a45', maintenance: '#2563eb', degraded: '#b45309', outage: '#dc2626' }; let st = null; const act = async (payload, ok) => { const r = await run(() => post(A, payload), ok); if (r) { st = r.status; paint(); } return r; }; function paint() { const s = st; const comps = h('div', { class: 'panel' }, h('div', { class: 'sect first' }, 'Dienste'), s.components.length ? h('table', {}, ...s.components.map((c) => h('tr', {}, h('td', {}, h('b', {}, c.name), c.description ? h('div', { class: 'muted' }, c.description) : null), h('td', {}, h('select', { onchange: (e) => act({ action: 'set_component', id: c.id, status: e.target.value }, 'Zustand geändert') }, ...s.componentStates.map((o) => h('option', { value: o.key, selected: o.key === c.status }, o.label))))))) : h('div', { class: 'muted' }, 'Noch keine Dienste eingetragen.')); const title = h('input', { placeholder: 'z. B. E-Mail-Versand verzögert' }), text = h('textarea', { placeholder: 'Was ist passiert? Was tun wir dagegen?' }); const level = h('select', {}, ...s.incidentStates.map((o) => h('option', { value: o.key }, o.label))); const comp = h('select', {}, h('option', { value: '' }, '– kein bestimmter Dienst –'), ...s.components.map((c) => h('option', { value: c.id }, c.name))); const compState = h('select', {}, h('option', { value: '' }, '– nicht ändern –'), ...s.componentStates.map((o) => h('option', { value: o.key }, o.label))); const create = h('div', { class: 'panel' }, h('div', { class: 'sect first' }, 'Neue Meldung (Störung oder Wartung)'), h('label', {}, 'Titel'), title, h('label', {}, 'Beschreibung'), text, h('label', {}, 'Stufe'), level, h('label', {}, 'Betrifft'), comp, h('label', {}, 'Dienst setzen auf'), compState, h('div', { class: 'row top' }, h('button', { class: 'btn', onclick: () => act({ action: 'create_incident', title: title.value, body: text.value, status: level.value, componentId: comp.value ? +comp.value : null, componentState: compState.value || null }, 'Meldung veröffentlicht') }, 'Veröffentlichen'))); const incidents = h('div', { class: 'panel' }, h('div', { class: 'sect first' }, 'Meldungen (letzte 14 Tage)'), s.incidents.length ? null : h('div', { class: 'muted' }, 'Keine Meldungen.'), ...s.incidents.map((i) => { const upd = h('input', { placeholder: 'Update für die Kunden' }); const lv = h('select', {}, ...s.incidentStates.map((o) => h('option', { value: o.key, selected: o.key === i.status }, o.label))); return h('div', { class: 'incident' }, h('div', {}, h('b', {}, i.title), ' ', h('span', { class: 'chip' }, i.statusLabel), i.component ? h('span', { class: 'muted' }, ' · ' + i.component) : null, h('span', { class: 'muted' }, ' · ' + fmtDate(i.createdAt))), ...i.updates.map((u) => h('div', { class: 'muted' }, `${u.statusLabel}${u.body ? ': ' + u.body : ''}`)), h('div', { class: 'row top' }, i.status === 'resolved' ? null : [lv, upd, h('button', { class: 'btn sm', onclick: () => act({ action: 'update_incident', id: i.id, status: lv.value, body: upd.value }, 'Update veröffentlicht') }, 'Update senden')], h('button', { class: 'btn danger sm', onclick: () => confirm('Meldung löschen?') && act({ action: 'delete_incident', id: i.id }, 'Gelöscht') }, '✕'))); })); clear(view).append( h('div', { class: 'panel' }, h('div', { class: 'row' }, h('span', { class: 'pill', color: s.overall.color }, s.overall.label), h('label', { class: 'check grow' }, h('input', { type: 'checkbox', checked: s.enabled, onchange: (e) => act({ action: 'set_enabled', enabled: e.target.checked }, e.target.checked ? 'Statusseite eingeschaltet' : 'Statusseite ausgeschaltet') }), 'Statusseite für Kunden anzeigen')), s.enabled ? h('div', { class: 'muted' }, 'Adresse für Kunden: ' + s.url) : null), comps, create, incidents); } const view = h('div'); body.append(view); const r = await run(() => api(A)); if (!r) return; st = r.status; paint(); } ADMIN.push({ key: 'statuspage', label: 'Statusseite', admin: true, custom: adminStatusPage }); ADMIN_GROUPS.find((g) => g[0] === 'System')[1].push('statuspage'); ADMIN_DESC.statuspage = 'Dienste und Störungsmeldungen für Kunden';