Files
deskhub/DeskHub-Webseite/staff/status_page.php
T
2026-10-24 20:14:41 +00:00

111 lines
9.1 KiB
PHP
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.
<?php
require_once __DIR__ . '/../includes/bootstrap.php';
$admin = require_admin();
$pdo = get_db();
$errors = [];
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
verify_csrf();
$action = $_POST['action'] ?? '';
if ($action === 'settings') {
set_setting('status_page_enabled', !empty($_POST['enabled']) ? '1' : '0');
$title = trim(mb_substr((string) ($_POST['title'] ?? ''), 0, 80));
set_setting('status_page_title', $title !== '' ? $title : 'Systemstatus');
audit_log($admin['id'], 'Statusseite: Einstellungen geändert');
flash('success', 'Einstellungen gespeichert.');
} elseif ($action === 'component_save') {
$id = (int) ($_POST['id'] ?? 0) ?: null;
$r = status_save_component($pdo, $id, (string) ($_POST['name'] ?? ''), (string) ($_POST['description'] ?? ''), (int) ($_POST['sort_order'] ?? 0));
if ($r === null) $errors[] = 'Bitte einen Namen angeben.'; else flash('success', 'Dienst gespeichert.');
} elseif ($action === 'component_state') {
status_set_component($pdo, (int) ($_POST['id'] ?? 0), (string) ($_POST['status'] ?? ''));
flash('success', 'Zustand geändert.');
} elseif ($action === 'component_delete') {
status_delete_component($pdo, (int) ($_POST['id'] ?? 0));
flash('success', 'Dienst entfernt.');
} elseif ($action === 'incident_create') {
$cid = (int) ($_POST['component_id'] ?? 0) ?: null;
$r = status_create_incident($pdo, (string) ($_POST['title'] ?? ''), (string) ($_POST['body'] ?? ''), (string) ($_POST['status'] ?? 'investigating'), $cid, ($_POST['component_state'] ?? '') !== '' ? (string) $_POST['component_state'] : null, (int) $admin['id']);
if (!$r['ok']) $errors[] = $r['error']; else { audit_log($admin['id'], 'Statusseite: Meldung veröffentlicht'); flash('success', 'Meldung veröffentlicht.'); }
} elseif ($action === 'incident_update') {
$r = status_update_incident($pdo, (int) ($_POST['id'] ?? 0), (string) ($_POST['status'] ?? ''), (string) ($_POST['body'] ?? ''), (int) $admin['id'], true);
if (!$r['ok']) $errors[] = $r['error']; else flash('success', 'Update veröffentlicht.');
} elseif ($action === 'incident_delete') {
status_delete_incident($pdo, (int) ($_POST['id'] ?? 0));
flash('success', 'Meldung gelöscht.');
}
if (!$errors) redirect('/staff/status_page.php');
}
$components = status_components($pdo);
$incidents = status_incidents($pdo, 60);
$states = status_component_states();
$incStates = status_incident_states();
$pageTitle = 'Statusseite';
$activePage = 'status_page';
require __DIR__ . '/_header.php';
?>
<h1>Statusseite</h1>
<?php foreach ($errors as $err): ?><div class="flash error"><?= e($err) ?></div><?php endforeach; ?>
<p class="muted" style="max-width:820px">Eine öffentliche Seite, auf der Ihre Kunden sehen, ob alles läuft, und über Störungen und Wartungen informiert werden.
<?php if (status_page_enabled()): ?>Adresse: <a href="/status.php" target="_blank"><?= e(base_url()) ?>/status.php</a><?php endif; ?></p>
<form method="post" class="card" style="max-width:820px;margin-bottom:16px">
<?= csrf_field() ?><input type="hidden" name="action" value="settings">
<h3>Einstellungen</h3>
<label style="display:flex;align-items:center;gap:8px;font-weight:400"><input type="checkbox" name="enabled" value="1" style="width:auto" <?= status_page_enabled() ? 'checked' : '' ?>> Statusseite für Kunden anzeigen (Link „Status“ im Kundenbereich)</label>
<label for="title" style="margin-top:8px">Überschrift</label>
<input type="text" id="title" name="title" maxlength="80" value="<?= e((string) get_setting('status_page_title', 'Systemstatus')) ?>" style="max-width:340px">
<div class="btn-row"><button type="submit" class="btn">Speichern</button></div>
</form>
<div class="card" style="max-width:820px;margin-bottom:16px">
<h3>Dienste</h3>
<?php if (!$components): ?><p class="muted">Noch keine Dienste. Legen Sie unten zum Beispiel „Webseite“, „E-Mail“ oder „Telefon“ an.</p><?php endif; ?>
<?php foreach ($components as $c): $st = $states[$c['status']] ?? $states['operational']; ?>
<div style="display:flex;gap:10px;flex-wrap:wrap;align-items:center;padding:8px 0;border-top:1px solid var(--border,#e3e9ee)">
<div style="flex:1;min-width:180px"><strong><?= e($c['name']) ?></strong><?php if ($c['description']): ?><div class="muted" style="font-size:.8rem"><?= e($c['description']) ?></div><?php endif; ?></div>
<form method="post" style="display:flex;gap:6px;align-items:center"><?= csrf_field() ?><input type="hidden" name="action" value="component_state"><input type="hidden" name="id" value="<?= (int) $c['id'] ?>">
<select name="status" onchange="this.form.submit()" style="color:<?= e($st[1]) ?>;font-weight:600"><?php foreach ($states as $k => $s): ?><option value="<?= e($k) ?>" <?= $c['status'] === $k ? 'selected' : '' ?>><?= e($s[0]) ?></option><?php endforeach; ?></select></form>
<form method="post" onsubmit="return confirm('Dienst entfernen?')"><?= csrf_field() ?><input type="hidden" name="action" value="component_delete"><input type="hidden" name="id" value="<?= (int) $c['id'] ?>"><button class="btn secondary" type="submit" style="padding:2px 10px;font-size:.78rem">Entfernen</button></form>
</div>
<?php endforeach; ?>
<form method="post" style="display:flex;gap:8px;flex-wrap:wrap;margin-top:12px;border-top:1px solid var(--border,#e3e9ee);padding-top:12px"><?= csrf_field() ?><input type="hidden" name="action" value="component_save">
<input type="text" name="name" placeholder="Neuer Dienst, z. B. Webseite" maxlength="120" required style="flex:1;min-width:180px">
<input type="text" name="description" placeholder="Beschreibung (optional)" maxlength="255" style="flex:1;min-width:180px">
<input type="number" name="sort_order" value="<?= count($components) * 10 + 10 ?>" title="Reihenfolge" style="width:80px">
<button class="btn" type="submit">Hinzufügen</button></form>
</div>
<form method="post" class="card" style="max-width:820px;margin-bottom:16px"><?= csrf_field() ?><input type="hidden" name="action" value="incident_create">
<h3>Neue Meldung (Störung oder Wartung)</h3>
<label for="inc_title">Titel</label><input type="text" id="inc_title" name="title" maxlength="200" required placeholder="z. B. E-Mail-Versand verzögert">
<label for="inc_body" style="margin-top:8px">Beschreibung</label><textarea id="inc_body" name="body" rows="3" maxlength="4000"></textarea>
<div style="display:flex;gap:12px;flex-wrap:wrap;margin-top:8px">
<div><label>Stufe</label><select name="status"><?php foreach ($incStates as $k => $l): ?><option value="<?= e($k) ?>"><?= e($l) ?></option><?php endforeach; ?></select></div>
<div><label>Betrifft</label><select name="component_id"><option value="">– kein bestimmter Dienst –</option><?php foreach ($components as $c): ?><option value="<?= (int) $c['id'] ?>"><?= e($c['name']) ?></option><?php endforeach; ?></select></div>
<div><label>Dienst setzen auf</label><select name="component_state"><option value="">– nicht ändern –</option><?php foreach ($states as $k => $s): ?><option value="<?= e($k) ?>"><?= e($s[0]) ?></option><?php endforeach; ?></select></div>
</div>
<div class="btn-row"><button type="submit" class="btn">Veröffentlichen</button></div>
</form>
<div class="card" style="max-width:820px">
<h3>Meldungen</h3>
<?php if (!$incidents): ?><p class="muted">Keine Meldungen in den letzten 60 Tagen.</p><?php endif; ?>
<?php foreach ($incidents as $i): ?>
<div style="padding:10px 0;border-top:1px solid var(--border,#e3e9ee)">
<strong><?= e($i['title']) ?></strong>
<span class="muted" style="font-size:.8rem">· <?= e(format_dt((string) $i['created_at'])) ?><?= $i['component_name'] ? ' · ' . e($i['component_name']) : '' ?> · <?= e($incStates[$i['status']] ?? $i['status']) ?></span>
<?php foreach ($i['updates'] as $u): ?><div style="font-size:.86rem;margin-top:3px"><span class="muted"><?= e($incStates[$u['status']] ?? $u['status']) ?>:</span> <?= nl2br(e((string) $u['body'])) ?></div><?php endforeach; ?>
<?php if ($i['status'] !== 'resolved'): ?>
<form method="post" style="display:flex;gap:6px;flex-wrap:wrap;margin-top:6px"><?= csrf_field() ?><input type="hidden" name="action" value="incident_update"><input type="hidden" name="id" value="<?= (int) $i['id'] ?>">
<select name="status"><?php foreach ($incStates as $k => $l): ?><option value="<?= e($k) ?>" <?= $k === $i['status'] ? 'selected' : '' ?>><?= e($l) ?></option><?php endforeach; ?></select>
<input type="text" name="body" placeholder="Update für die Kunden" maxlength="4000" style="flex:1;min-width:200px">
<button class="btn secondary" type="submit">Update senden</button></form>
<?php endif; ?>
<form method="post" onsubmit="return confirm('Meldung löschen?')" style="margin-top:4px"><?= csrf_field() ?><input type="hidden" name="action" value="incident_delete"><input type="hidden" name="id" value="<?= (int) $i['id'] ?>"><button class="btn secondary" type="submit" style="padding:2px 10px;font-size:.76rem">Löschen</button></form>
</div>
<?php endforeach; ?>
</div>
<?php require __DIR__ . '/_footer.php'; ?>