'use strict'; /** * tools/manual/capture_manual.js: nimmt die Bilder für das Handbuch auf (Demo-Installation mit erfundenen Daten, siehe seed_manual.php). * 1. php tools/demo-video/seed_demo.php && php tools/manual/seed_manual.php && php tools/manual/install_plugins.php * 2. DESKHUB_CATALOG_DEFAULTS=tests/fixtures/no-catalog.php php -S 127.0.0.1:8097 -t * 3. electron tools/manual/capture_manual.js */ const { app, BrowserWindow } = require('electron'); const fs = require('fs'); const path = require('path'); const BASE = 'http://127.0.0.1:8097'; const OUT = path.resolve(process.argv[2] || path.join(__dirname, 'shots')); const W = 1180; // schmaler als ein Bildschirm: Die Bilder werden auf A4 verkleinert und müssen lesbar bleiben const SIDEBAR = 240; // Breite der Seitenleiste; sie wird aus den Bildern der Seiten herausgeschnitten (eigenes Bild vom Menü) const H = 860; const MAXH = 2400; fs.mkdirSync(OUT, { recursive: true }); const sleep = (ms) => new Promise((r) => setTimeout(r, ms)); let win; const run = (js) => win.webContents.executeJavaScript(js, true); const report = { ok: [], fail: [] }; /** Seite laden und alles entfernen, was nur zur Demo-Installation gehört (SQLite-Hinweis, Zähler der Sitzung). */ async function load(url, wait = 700) { await win.loadURL(BASE + url); await sleep(wait); await run(`(() => { document.getElementById('session-timer-bar')?.remove(); document.querySelectorAll('div,p,section,aside').forEach((e) => { if (e.children.length < 8 && /SQLite-Modus aktiv/.test(e.textContent) && e.textContent.length < 400) e.remove(); }); })()`); } /** Bild der Seite speichern: höchstens MAXH hoch; mit full = false nur der sichtbare Teil. */ async function shot(name, { full = true, clip = null, keepSidebar = false } = {}) { let h = H; if (full) { h = await run('Math.max(document.documentElement.scrollHeight, document.body.scrollHeight)'); h = Math.min(Math.max(h, 500), MAXH); } win.setContentSize(W, h); await sleep(350); const hasSidebar = await run(`(() => { const s = document.getElementById('sidebar'); return !!s && s.getBoundingClientRect().width > 100; })()`); let img = await win.webContents.capturePage(); if (clip) img = img.crop(clip); else if (hasSidebar && !keepSidebar) img = img.crop({ x: SIDEBAR, y: 0, width: W - SIDEBAR, height: h }); fs.writeFileSync(path.join(OUT, name + '.png'), img.toPNG()); win.setContentSize(W, H); report.ok.push(name); } async function page(name, url, opts = {}) { try { await load(url, opts.wait); if (opts.prep) { await run(opts.prep); await sleep(opts.prepWait || 400); } await shot(name, opts); } catch (e) { report.fail.push(name + ': ' + e.message); } } async function login(email, pass, loginUrl) { await load(loginUrl, 600); await run(`(() => { const f = document.querySelector('form'); f.querySelector('[name=email]').value = ${JSON.stringify(email)}; f.querySelector('[name=password]').value = ${JSON.stringify(pass)}; f.submit(); })()`); await sleep(1500); } app.whenReady().then(async () => { win = new BrowserWindow({ width: W, height: H, show: true, useContentSize: true, webPreferences: { contextIsolation: true, backgroundThrottling: false } }); const tab = (id) => `document.querySelector('[data-tab="${id}"]')?.click()`; try { // ── Kundenportal ────────────────────────────────────────────────────────── await page('portal-start', '/home.php', { full: false }); await page('portal-neues-ticket', '/ticket_new.php'); await page('portal-status-pruefen', '/ticket_lookup.php', { full: false }); await page('portal-login', '/login.php', { full: false }); await page('portal-registrieren', '/register.php', { full: false }); await page('portal-passwort-vergessen', '/forgot_password.php', { full: false }); await page('portal-wissensdatenbank', '/kb.php'); await page('portal-artikel', '/kb_article.php?slug=versandzeiten'); await page('portal-seite-impressum', '/page.php?slug=impressum', { full: false }); await page('portal-statusseite', '/status.php'); await page('portal-assistent', '/home.php', { full: false, wait: 1000, prepWait: 1800, prep: `(() => { document.getElementById('as-bubble')?.click(); const i = document.getElementById('as-input'); if (i) { i.value = 'Wie lange dauert der Versand?'; document.getElementById('as-form').dispatchEvent(new Event('submit', { cancelable: true })); } })()` }); await login('erika.muster@kunde.example', 'Demo-Passwort-1234', '/login.php'); await page('portal-meine-tickets', '/dashboard.php'); await page('portal-ticket-ansicht', '/ticket_view.php?n=260107'); await page('portal-kunden-startseite', '/home.php', { full: false }); await load('/logout.php'); // ── Mitarbeiter-Anmeldung ───────────────────────────────────────────────── await page('staff-login', '/staff/login.php', { full: false }); await page('staff-passwort-vergessen', '/staff/forgot_password.php', { full: false }); await login('lena@demo.example', 'Demo-Passwort-1234', '/staff/login.php'); // Gesamtansicht mit Seitenleiste und die Seitenleiste allein (Adminportal aufgeklappt) await page('staff-gesamtansicht', '/staff/reports.php', { full: false, keepSidebar: true }); await page('staff-seitenleiste', '/staff/reports.php', { full: false, clip: { x: 0, y: 0, width: SIDEBAR, height: 2000 }, prep: `(() => { const b = document.getElementById('admin-block'); if (b) b.style.display = 'block'; document.getElementById('sidebar').style.height = 'auto'; document.getElementById('sidebar').style.overflow = 'visible'; })()` }); // ── Arbeitsalltag ───────────────────────────────────────────────────────── await page('uebersicht-ueberblick', '/staff/reports.php'); await page('uebersicht-verlauf', '/staff/reports.php?tab=activity'); await page('uebersicht-auswertung', '/staff/reports.php?tab=analysis'); await page('uebersicht-zufriedenheit', '/staff/reports.php?tab=csat'); await page('meine-woche', '/staff/my_week.php'); await page('tickets-liste', '/staff/tickets.php'); await page('tickets-suche', '/staff/tickets.php?q=Rechnung', { full: false }); await page('tickets-ansicht-speichern', '/staff/tickets.php?tab=open', { full: false }); await page('tickets-wiedervorlage', '/staff/tickets.php?tab=snoozed', { full: false }); await page('tickets-tastenkuerzel', '/staff/tickets.php', { full: false, prep: `document.dispatchEvent(new KeyboardEvent('keydown', { key: '?' }))` }); await page('ticket-neu', '/staff/ticket_create.php'); await page('ticket-ansicht', '/staff/ticket_view.php?n=260101'); await page('ticket-ansicht-details', '/staff/ticket_view.php?n=260101', { prep: tab('details') }); await page('ticket-ansicht-organisation', '/staff/ticket_view.php?n=260107', { prep: tab('manage') }); await page('ticket-ansicht-mehr', '/staff/ticket_view.php?n=260101', { prep: tab('more') }); await page('ticket-anhang', '/staff/ticket_view.php?n=260105'); await page('ticket-antwortformular', '/staff/ticket_view.php?n=260102', { full: false, prep: `(() => { document.getElementById('message-field')?.scrollIntoView({block:'start'}); window.scrollBy(0,-80); document.querySelectorAll('details').forEach((d) => { if (/Später senden/.test(d.textContent)) d.open = true; }); })()` }); await page('ticket-geplante-antwort', '/staff/ticket_view.php?n=260103'); await page('ticket-zeiterfassung', '/staff/ticket_view.php?n=260108', { prep: tab('manage') }); await page('ticket-tastenkuerzel', '/staff/ticket_view.php?n=260101', { full: false, prep: `document.dispatchEvent(new KeyboardEvent('keydown', { key: '?' }))` }); await page('ticket-drucken', '/staff/ticket_print.php?n=260101'); await page('aufgaben', '/staff/tasks.php'); await page('sperrliste', '/staff/banlist.php'); await page('verzeichnis', '/staff/agent_directory.php'); await page('erwaehnungen', '/staff/mentions.php'); await page('interner-chat', '/staff/chat.php?with=3', { wait: 1200 }); await page('live-chat', '/staff/live_chat.php'); await page('kunden-profil', '/staff/customer_profile.php?id=1'); await page('apps', '/staff/apps.php'); // ── Profil ──────────────────────────────────────────────────────────────── await page('profil-konto', '/staff/profile.php?tab=account'); await page('profil-einstellungen', '/staff/profile.php?tab=settings'); await page('profil-sicherheit', '/staff/profile.php?tab=security'); await page('profil-signatur', '/staff/profile.php?tab=signature'); await page('verfuegbarkeit', '/staff/availability.php'); // ── Berichte ────────────────────────────────────────────────────────────── await page('bericht-baukasten', '/staff/report_builder.php?dimension=department'); await page('bericht-zeitplan', '/staff/report_builder.php#versand', { prep: `document.getElementById('versand')?.setAttribute('open','')` }); // ── Adminportal ─────────────────────────────────────────────────────────── const admin = [ ['admin-abteilungen', '/staff/departments.php'], ['admin-abteilung-bearbeiten', '/staff/department_form.php?dept=1'], ['admin-prioritaeten', '/staff/priorities.php'], ['admin-sla-plaene', '/staff/sla_plans.php'], ['admin-hilfethemen', '/staff/help_topics.php'], ['admin-ticket-felder', '/staff/custom_fields.php'], ['admin-listen', '/staff/custom_lists.php'], ['admin-vorlagen', '/staff/canned_responses.php'], ['admin-seiten', '/staff/site_pages.php'], ['admin-sprachen', '/staff/languages.php'], ['admin-ticket-vorlagen', '/staff/ticket_templates.php'], ['admin-statusseite', '/staff/status_page.php'], ['admin-mail-warteschlange', '/staff/mail_queue.php'], ['admin-anmelde-waechter', '/staff/login_log.php'], ['admin-email-adressen', '/staff/email_addresses.php'], ['admin-postfaecher', '/staff/imap_accounts.php'], ['admin-email-vorlagen', '/staff/email_templates.php'], ['admin-wissensdatenbank', '/staff/kb_manage.php'], ['admin-assistent-einstellungen', '/staff/assistant.php?tab=settings'], ['admin-assistent-antworten', '/staff/assistant.php?tab=answers'], ['admin-assistent-log', '/staff/assistant.php?tab=log'], ['admin-plugins-installiert', '/staff/plugins.php?tab=installed'], ['admin-plugins-hinzufuegen', '/staff/plugins.php?tab=add'], ['admin-plugins-katalog', '/staff/plugins.php?tab=settings'], ['admin-api-schluessel', '/staff/api_keys.php'], ['admin-webhooks', '/staff/webhooks.php'], ['admin-kundenverzeichnis', '/staff/customers.php'], ['admin-organisationen', '/staff/organizations.php'], ['admin-mitarbeiter', '/staff/staff_manage.php'], ['admin-mitarbeiter-bearbeiten', '/staff/staff_manage.php?edit=2'], ['admin-mitarbeiter-zugriff', '/staff/staff_manage.php?edit=2&tab=access'], ['admin-teams', '/staff/teams.php'], ['admin-rollen', '/staff/roles.php'], ['admin-sicherheitspruefung', '/staff/security_check.php'], ['admin-protokoll', '/staff/audit_log.php'], ['admin-ticket-regeln', '/staff/ticket_rules.php'], ['admin-eskalationsregeln', '/staff/escalation_rules.php'], ['admin-wiederkehrende-tickets', '/staff/recurring_tickets.php'], ['admin-zeiterfassung', '/staff/time_entries.php'], ['admin-geschaeftszeiten', '/staff/business_hours.php'], ['admin-einstellungen-allgemein', '/staff/settings.php?tab=allgemein'], ['admin-einstellungen-design', '/staff/settings.php?tab=design'], ['admin-einstellungen-email', '/staff/settings.php?tab=email'], ['admin-einstellungen-benachrichtigungen', '/staff/settings.php?tab=benachrichtigungen'], ['admin-einstellungen-uploads', '/staff/settings.php?tab=uploads'], ['admin-einstellungen-footer', '/staff/settings.php?tab=footer'], ['admin-einstellungen-cron', '/staff/settings.php?tab=cron'], ['admin-einstellungen-datenschutz', '/staff/settings.php?tab=datenschutz'], ['admin-backup', '/staff/backup.php'], ['admin-system-update', '/staff/update.php'], ['admin-osticket-import', '/staff/import_osticket.php'], ['admin-probleme', '/staff/problems.php'], ]; for (const [name, url] of admin) await page(name, url); await page('admin-menue-aktionen', '/staff/staff_manage.php', { full: false, prep: `document.querySelector('.sm-menu summary')?.click()` }); // ── Plugin-Seiten ───────────────────────────────────────────────────────── const plugins = [['tagesbericht', 'einstellungen'], ['tagesbericht', 'persoenlich'], ['schichtuebergabe', 'schichtuebergabe'], ['rundmail', 'rundmail'], ['spamfilter', 'spamfilter'], ['virenscan', 'virenscan'], ['ueberwachung', 'ueberwachung'], ['datenschutz', 'datenschutz'], ['vertretung', 'vertretung'], ['community-bot', 'community-bot'], ['authentik', 'einstellungen'], ['authentik', 'konto'], ['nas-backup', 'einstellungen'], ['virustotal', 'virustotal'], ['deskhub-cache-manager', 'status'], ['code-issue-sync', 'manage'], ['cloudflare-protection', 'status']]; for (const [slug, pg] of plugins) await page(`plugin-${slug}-${pg}`, `/staff/plugin.php?p=${slug}&page=${pg}`); } catch (e) { report.fail.push('FATAL ' + e.stack); } fs.writeFileSync(path.join(OUT, '_bericht.json'), JSON.stringify(report, null, 1)); console.log(`Aufgenommen: ${report.ok.length}, Fehler: ${report.fail.length}`); report.fail.forEach((f) => console.log(' - ' + f)); app.quit(); });