Upload via GUI (340 Dateien)

This commit is contained in:
2026-10-26 21:19:21 +00:00
parent d6df75ad64
commit 12699f0918
5 changed files with 117 additions and 24 deletions
+45 -3
View File
@@ -24,6 +24,8 @@ foreach ($components as &$component) {
}
unset($component);
$incidents = status_incidents($pdo, 14);
$maintenanceWindows = status_maintenance_windows($pdo);
$activeMaintenance = status_active_maintenance_map($pdo);
$open = array_values(array_filter($incidents, fn($i) => $i['status'] !== 'resolved'));
$past = array_values(array_filter($incidents, fn($i) => $i['status'] === 'resolved'));
$incStates = status_incident_states();
@@ -33,10 +35,12 @@ if (($_GET['live'] ?? '') === '1') {
header('Cache-Control: no-store, no-cache, must-revalidate, max-age=0');
$liveComponents = [];
foreach ($components as $component) {
$componentState = $states[$component['status']] ?? $states['operational'];
$componentStatus = (string) $component['status'];
if (($componentStatus === 'operational') && (isset($activeMaintenance[0]) || isset($activeMaintenance[(int) $component['id']]))) $componentStatus = 'maintenance';
$componentState = $states[$componentStatus] ?? $states['operational'];
$liveComponents[] = [
'id' => (int) $component['id'],
'status' => (string) $component['status'],
'status' => $componentStatus,
'statusLabel' => (string) $componentState[0],
'color' => (string) $componentState[1],
'uptime' => $component['timeline']['uptime'],
@@ -64,11 +68,21 @@ if (($_GET['live'] ?? '') === '1') {
], $incident['updates']),
];
}
$liveMaintenance = [];
foreach ($maintenanceWindows as $window) {
$liveMaintenance[] = [
'title' => (string) $window['title'], 'body' => (string) ($window['body'] ?? ''),
'componentName' => (string) ($window['component_name'] ?? ''),
'startsAt' => format_dt((string) $window['starts_at']), 'endsAt' => format_dt((string) $window['ends_at']),
'active' => strtotime((string) $window['starts_at']) <= time() && strtotime((string) $window['ends_at']) >= time(),
];
}
echo json_encode([
'updatedAt' => date('d.m.Y H:i:s'),
'overall' => $overall,
'components' => $liveComponents,
'incidents' => $liveIncidents,
'maintenanceWindows' => $liveMaintenance,
], JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_AMP | JSON_HEX_QUOT);
exit;
}
@@ -83,6 +97,17 @@ require __DIR__ . '/includes/header_customer.php';
<div id="status-live-updated-at" class="muted" style="font-size:.82rem;margin-top:2px">Stand: <?= e(date("d.m.Y H:i:s")) ?> Uhr &middot; Live-Aktualisierung aktiv</div>
</div>
<div id="status-live-maintenance">
<?php foreach ($maintenanceWindows as $window): $isActiveWindow = strtotime((string) $window['starts_at']) <= time() && strtotime((string) $window['ends_at']) >= time(); ?>
<div class="card" style="padding:14px 18px;margin:0 0 12px;border-left:6px solid #2563eb">
<strong><?= $isActiveWindow ? 'Laufende Wartung' : 'Geplante Wartung' ?>: <?= e($window['title']) ?></strong>
<div class="muted" style="font-size:.85rem;margin-top:4px"><?= $isActiveWindow ? 'Läuft seit ' : 'Geplant von ' ?><?= e(format_dt((string) $window['starts_at'])) ?> bis <?= e(format_dt((string) $window['ends_at'])) ?></div>
<?php if (!empty($window['component_name'])): ?><div class="muted" style="font-size:.82rem">Betrifft: <?= e($window['component_name']) ?></div><?php else: ?><div class="muted" style="font-size:.82rem">Betrifft: gesamte Plattform</div><?php endif; ?>
<?php if (trim((string) ($window['body'] ?? '')) !== ''): ?><div style="margin-top:6px;white-space:pre-line"><?= e((string) $window['body']) ?></div><?php endif; ?>
</div>
<?php endforeach; ?>
</div>
<div id="status-live-incidents">
<?php foreach ($open as $i): ?>
<div class="card" style="padding:16px 20px;margin-bottom:14px;border-left:6px solid #dc2626">
@@ -104,7 +129,7 @@ require __DIR__ . '/includes/header_customer.php';
<?php foreach ($groups as $category => $group): ?>
<h2 style="font-size:1.05rem;margin:22px 0 8px"><?= e($category) ?></h2>
<section class="card" style="padding:0 20px;margin:0 0 16px">
<?php foreach ($group as $groupIndex => $c): $st = $states[$c['status']] ?? $states['operational']; ?>
<?php foreach ($group as $groupIndex => $c): $componentStatus = (string) $c['status']; if ($componentStatus === 'operational' && (isset($activeMaintenance[0]) || isset($activeMaintenance[(int) $c['id']]))) $componentStatus = 'maintenance'; $st = $states[$componentStatus] ?? $states['operational']; ?>
<div data-status-component="<?= (int) $c['id'] ?>" style="padding:13px 0;<?= $groupIndex < count($group) - 1 ? 'border-bottom:1px solid var(--border,#e3e9ee)' : '' ?>">
<div style="display:flex;justify-content:space-between;align-items:center;gap:12px">
<div><strong><?= e($c['name']) ?></strong><?php if (!empty($c['description'])): ?><div class="muted" style="font-size:.82rem"><?= e($c['description']) ?></div><?php endif; ?></div>
@@ -150,6 +175,7 @@ require __DIR__ . '/includes/header_customer.php';
const overallLabel = document.getElementById('status-live-overall-label');
const updatedAt = document.getElementById('status-live-updated-at');
const incidentList = document.getElementById('status-live-incidents');
const maintenanceList = document.getElementById('status-live-maintenance');
let polling = false;
function addText(parent, tag, text, className, style) {
@@ -183,6 +209,21 @@ require __DIR__ . '/includes/header_customer.php';
}
}
function renderMaintenance(windows) {
if (!maintenanceList) return;
maintenanceList.replaceChildren();
for (const window of windows || []) {
const card = document.createElement('div');
card.className = 'card';
card.style.cssText = 'padding:14px 18px;margin:0 0 12px;border-left:6px solid #2563eb';
addText(card, 'strong', (window.active ? 'Laufende Wartung: ' : 'Geplante Wartung: ') + window.title);
addText(card, 'div', (window.active ? 'Endet ' : 'Geplant von ') + window.startsAt + ' bis ' + window.endsAt, 'muted', 'font-size:.85rem;margin-top:4px');
addText(card, 'div', 'Betrifft: ' + (window.componentName || 'gesamte Plattform'), 'muted', 'font-size:.82rem');
if (window.body) addText(card, 'div', window.body, '', 'margin-top:6px;white-space:pre-line');
maintenanceList.appendChild(card);
}
}
async function refreshStatus() {
if (polling || document.visibilityState === 'hidden') return;
polling = true;
@@ -219,6 +260,7 @@ require __DIR__ . '/includes/header_customer.php';
if (uptime) uptime.textContent = component.uptime === null ? 'Noch keine Pr\u00fcfungen' : Number(component.uptime).toLocaleString('de-DE', {minimumFractionDigits: 2, maximumFractionDigits: 2}) + ' %';
}
renderIncidents(data.incidents);
renderMaintenance(data.maintenanceWindows);
} catch (_) {
// Bei einem voruebergehenden Netzfehler bleibt die zuletzt geladene Anzeige sichtbar.
} finally {