= e($c['name']) ?>= e($c['description']) ?>
@@ -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 {
diff --git a/DeskHub-Webseite/ticket_view.php b/DeskHub-Webseite/ticket_view.php
index 8da56818..61c88579 100644
--- a/DeskHub-Webseite/ticket_view.php
+++ b/DeskHub-Webseite/ticket_view.php
@@ -89,10 +89,11 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !in_array($ticket['status'], ['clos
}
// Ein Kunden-Reply auf ein beantwortetes Ticket setzt den Status zurück auf "Offen"
- $wasReopened = in_array($ticket['status'], ['answered', 'resolved']);
+ $wasReopened = in_array($ticket['status'], ['answered', 'resolved', 'pending']);
$newStatus = $wasReopened ? 'open' : $ticket['status'];
$stmt = $pdo->prepare('UPDATE tickets SET status = ?, updated_at = ? WHERE id = ?');
$stmt->execute([$newStatus, $now, $ticket['id']]);
+ ticket_sla_status_transition($pdo, (int) $ticket['id'], (string) $ticket['status'], $newStatus);
log_activity($pdo, $ticket['id'], null, 'Kunde hat geantwortet');
if ($wasReopened) {
diff --git a/DeskHub-Webseite/tools/demo-video/record.js b/DeskHub-Webseite/tools/demo-video/record.js
index 0a607d6f..69337290 100644
--- a/DeskHub-Webseite/tools/demo-video/record.js
+++ b/DeskHub-Webseite/tools/demo-video/record.js
@@ -228,6 +228,32 @@ app.whenReady().then(async () => {
await sleep(1400);
await hide();
+ // ── 3b. Weitere Funktionen der Weboberfläche ──
+ chapter('features');
+ const tour = async (url, title, sub, { y = 0, dwell = 2600 } = {}) => {
+ await go(url); await caption(title, sub); await sleep(1100);
+ if (y) { await scroll('page', y, 1700); await sleep(900); await scroll('page', 0, 1000); } else await sleep(dwell);
+ await hide();
+ };
+ await tour('/staff/tickets.php', 'Alle Tickets', 'Suchen, filtern, sortieren und Sammelaktionen', { dwell: 3200 });
+ await tour('/staff/reports.php', 'Berichte', 'Auslastung, Antwortzeiten und Zufriedenheit', { y: 520 });
+ await tour('/staff/sla_plans.php', 'SLA-Pläne', 'Reaktions- und Lösungszeiten je Priorität', { dwell: 3000 });
+ await tour('/staff/escalation_rules.php', 'Eskalation und Regeln', 'Überfällige Tickets automatisch weitergeben', { dwell: 3000 });
+ await tour('/staff/canned_responses.php', 'Textbausteine', 'Fertige Antworten für wiederkehrende Fragen', { dwell: 3000 });
+ await tour('/staff/kb_manage.php', 'Wissensdatenbank', 'Artikel für Kunden und den Assistenten', { dwell: 3000 });
+ await tour('/staff/customers.php', 'Kunden und Organisationen', 'Alle Tickets eines Kunden auf einen Blick', { dwell: 3000 });
+ await tour('/staff/tasks.php', 'Aufgaben', 'Eigene To-dos neben den Tickets', { dwell: 2800 });
+ await tour('/staff/time_entries.php', 'Zeiterfassung', 'Aufwand pro Ticket und Kunde', { dwell: 2800 });
+ await tour('/staff/status_page.php', 'Status-Seite', 'Störungen öffentlich melden', { dwell: 3000 });
+ await tour('/staff/departments.php', 'Abteilungen, Teams und Rollen', 'Rechte genau festlegen', { dwell: 2800 });
+ await tour('/staff/api_keys.php', 'Schnittstelle und Webhooks', 'DeskHub mit anderen Systemen verbinden', { dwell: 2800 });
+ await tour('/staff/audit_log.php', 'Protokoll', 'Wer hat wann was geändert', { dwell: 2800 });
+ await tour('/staff/security_check.php', 'Sicherheitsprüfung', 'Zeigt Schwachstellen der Installation', { dwell: 3000 });
+ await tour('/staff/backup.php', 'Datensicherung', 'Backups per Klick, auch auf ein NAS', { dwell: 3200 });
+ await tour('/staff/plugins.php', 'Plugins', 'Erweiterungen ohne Eingriff am Server', { dwell: 3000 });
+ await tour('/staff/apps.php', 'Apps und Minecraft-Plugin', 'Windows, Android und Minecraft zum Herunterladen', { dwell: 3200 });
+ await tour('/staff/settings.php', 'Einstellungen', 'Name, Farben, E-Mail, Sicherheit und mehr', { y: 500 });
+
// ── 4. Windows-Programm ──
chapter('windows');
await go('', { file: MOCK });
@@ -252,6 +278,10 @@ app.whenReady().then(async () => {
evt('whoosh');
await win.loadURL(card('
Android-App
- Neues, helles Design mit schwebender Navigation
- Wiedervorlage, Beobachten, „Dazu passend“
- Digitalen Assistenten komplett verwalten
- Widget in drei Größen, hell und dunkel
'));
await sleep(3700);
+ chapter('extras');
+ evt('whoosh');
+ await win.loadURL(card('
Und noch mehr
- Chrome-Erweiterung: Zähler, Suche, Ticket anlegen
- Minecraft-Plugin für Paper, Spigot und BungeeCord
- Windows-Programm auch für Linux und Mac
- Plugins und Sprachpakete, zum Beispiel Englisch
- Updates der Apps direkt aus DeskHub
'));
+ await sleep(3700);
chapter('outro');
evt('whoosh');
await win.loadURL(card('
DeskHub
Kundenportal · Weboberfläche · Windows · Android
Mehr in der README
'));