Files
deskhub/desktop/test/mock.html
T
2026-10-23 17:22:55 +00:00

57 lines
9.7 KiB
HTML
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.
<!doctype html>
<html lang="de"><head><meta charset="utf-8"><title>DeskHub Mock</title>
<link rel="stylesheet" href="../src/styles.css"></head>
<body><div id="app"></div><div id="toast" class="toast hidden"></div>
<script>
// Test-Attrappe für die Electron-Brücke (window.deskhub) – nur für lokale UI-Tests ohne Server
const staff = { id: 1, name: 'Max Muster', email: 'max@example.de', role: 'agent', permissions: { view_reports: true, reply_ticket: true, close_ticket: true, post_note: true, assign_ticket: true, create_ticket: true, manage_teams: true, manage_roles: true, manage_business_hours: true } };
const prio = [{ id: 1, name: 'Hoch', color: '#ef4444' }, { id: 2, name: 'Normal', color: '#3b82f6' }];
const statuses = [{ value: 'open', label: 'Offen', color: '#3b82f6' }, { value: 'answered', label: 'Beantwortet', color: '#22c55e' }, { value: 'closed', label: 'Geschlossen', color: '#64748b' }, { value: 'resolved', label: 'Gelöst', color: '#16a34a' }];
const tk = (n, s, st, over) => ({ id: n, number: 'T-' + (1000 + n), subject: s, requesterName: 'Kunde ' + n, requesterEmail: `k${n}@mail.de`, status: st, priority: prio[n % 2], department: { id: 1, name: 'Technik' }, assignedStaff: n % 3 ? { id: 1, name: 'Max Muster' } : null, isOverdue: !!over, dueLabel: over ? 'vor 2 Std (überfällig)' : 'in 5 Std', isSpam: false, createdAt: '2026-10-12 08:00:00', updatedAt: '2026-10-12 09:1' + n + ':00' });
const tickets = [tk(1, 'Drucker druckt nicht', 'open', true), tk(2, 'Passwort zurücksetzen', 'answered'), tk(3, 'Rechnung fehlt', 'open'), tk(4, 'VPN Verbindung bricht ab', 'open', true)];
const routes = {
'me.php': () => ({ staff }), 'metadata.php': () => ({ staff, departments: [{ id: 1, name: 'Technik' }], priorities: prio, agents: [{ id: 1, name: 'Max Muster' }, { id: 2, name: 'Eva Beispiel' }], statuses, tags: [], liveChatEnabled: true }),
'activity.php': () => ({ newReplies: 0, newUnassigned: 0, serverTime: '2026-10-12 10:00:00', health: window.__health || [] }),
'dashboard.php': () => ({ myOpen: 3, overdue: 2, unassigned: 1, unanswered: 4, resolvedToday: 5, slaPercent: 92.4, recent: tickets, departments: [{ name: 'Technik', open: 8, overdue: 2 }, { name: 'Vertrieb', open: 3, overdue: 0 }] }),
'web_pages.php': () => ({ pages: [{ key: 'settings', label: 'Einstellungen', path: '/staff/settings.php', group: 'Verwaltung' }, { key: 'backup', label: 'Backup', path: '/staff/backup.php', group: 'System' }] }),
'assistant.php': (req) => {
if (req.method === 'POST') { (window.__assistantPosts = window.__assistantPosts || []).push(req.body); return req.body.action === 'test' ? { found: true, result: { source: 'custom', title: 'Versand', text: 'Zwei bis drei Werktage.', others: [] } } : req.body.action === 'save_synonyms' ? { ok: true, groups: 2 } : { ok: true, item: { id: 9 } }; }
const sec = (req.query || {}).section;
if (sec === 'answers') return { items: [{ id: 1, title: 'Wie lange dauert der Versand?', keywords: 'Lieferzeit', answer: 'Zwei bis drei Werktage.', isActive: true, hits: 3, updatedAt: '2026-10-20 10:00:00' }] };
if (sec === 'log') return { filters: { custom: 'Meine Antwort gefunden', kb: 'Wissensdatenbank', none: 'Keine Antwort', helpful: 'Hat geholfen' }, stats: { custom: 4, kb: 2, none: 1, helpful: 3 }, top: [{ question: 'Wie kündige ich?', n: 2, last: '2026-10-22 09:00:00' }], total: 1, pages: 1, page: 1, items: [{ id: 1, question: 'Wie kündige ich?', result: 'none', matchedTitle: null, ticketNumber: null, helpful: null, createdAt: '2026-10-22 09:00:00' }] };
return { dbReady: true, settings: { enabled: true, mode: 'offline_only', name: '', greeting: '', noAnswer: '', departmentId: 0, priorityId: 0, logDays: 90, synonyms: 'Zugang, Einladung, beitreten' }, defaults: { name: 'Digitaler Assistent', greeting: 'Hallo!', noAnswer: 'Keine Antwort.' }, state: { activeNow: true, liveChatEnabled: false, kbEnabled: true, helpdeskOffline: false }, departments: [{ id: 1, name: 'Technik' }], priorities: [{ id: 1, name: 'Normal' }] };
},
'tickets.php': () => ({ items: tickets, page: 1, perPage: 30, total: 4, hasMore: false }),
'ticket.php': () => ({ ticket: { ...tickets[0], source: 'web', firstResponseDueAt: null, resolutionDueAt: '2026-10-12 12:00:00', similar: { articles: [{ title: 'Drucker einrichten', url: '/kb_article.php?slug=drucker' }], tickets: [{ number: 'T-77', subject: 'Alter Druckerfall' }] }, lockedByOtherName: null, lockedBy: window.__lockedBy || null, canUnlock: !!window.__lockedBy, customFields: [{ label: 'Titel der Geschichte', type: 'text', value: 'Der kleine Bär' }, { label: 'Nutzerbedingungen', type: 'checkbox', value: 'Ja' }], replySignatures: { default: 'own', own: { available: true, text: 'Viele Grüße\nMax persönlich', html: '<p>Viele Grüße</p><div>Max persönlich</div>', hasImage: false }, department: { available: true, name: 'Technik', text: 'Technik-Team Support', html: '<p>Technik-Team Support</p><img src="https://example.org/logo.png" width="120" onerror="alert(1)" style="width:999px"><a href="javascript:alert(1)">Link</a><scr' + 'ipt>alert(2)</scr' + 'ipt>', hasImage: true } }, threads: [
{ id: 1, authorType: 'user', authorName: 'Kunde 1', message: 'Mein Drucker druckt nichts mehr.\nBitte helft.', isInternalNote: false, createdAt: '2026-10-12 08:00:00', attachments: [{ id: 1, name: 'foto.png', size: 20480 }], comments: [] },
{ id: 2, authorType: 'staff', authorName: 'Max Muster', message: 'Wir schauen uns das an.', isInternalNote: false, createdAt: '2026-10-12 08:30:00', attachments: [], comments: [] },
{ id: 3, authorType: 'staff', authorName: 'Max Muster', message: 'Treiber prüfen', isInternalNote: true, createdAt: '2026-10-12 08:35:00', attachments: [], comments: [] }] } }),
'ticket_unlock.php': () => { window.__lockedBy = null; return { ok: true, unlocked: true }; },
'departments.php': () => ({ staffOptions: [{ id: 1, name: 'Max Muster' }, { id: 2, name: 'Eva Beispiel' }], emailOptions: [], slaPlans: [], items: [{ id: 1, name: 'Technik', email: 'technik@example.de', isDefault: true, signature: '', isActive: true, slaPlanId: null, managerId: 1, managerName: 'Max Muster', autoAssignMode: 'staff', autoAssignStaffId: 2, notes: '', members: [{ id: 1, name: 'Max Muster', isPrimary: true }] }] }),
'queues.php': () => ({ items: [{ id: 1, name: 'Meine überfälligen', isShared: false, mine: true, ownerName: 'Max Muster', filters: { status: 'open,pending', assigned: 'me', sla: 'overdue' } }, { id: 2, name: 'Team-Überblick', isShared: true, mine: false, ownerName: 'Eva Beispiel', filters: { status: 'open,pending,answered' } }] }),
'report_builder.php': () => ({ config: { dimension: 'department', metrics: ['total', 'open', 'resolved', 'sla_resolve'], from: '2026-09-15', to: '2026-10-15', sort: 'label', desc: false, filters: {} },
columns: [{ key: 'label', label: 'Abteilung', unit: '' }, { key: 'total', label: 'Tickets gesamt', unit: '' }, { key: 'open', label: 'Offen', unit: '' }, { key: 'resolved', label: 'Gelöst/Geschlossen', unit: '' }, { key: 'sla_resolve', label: 'SLA Lösung', unit: '%' }],
rows: [{ label: 'Technik', total: 42, open: 8, resolved: 34, sla_resolve: 91.2 }, { label: 'Vertrieb', total: 17, open: 3, resolved: 14, sla_resolve: 97.5 }], totals: { total: 59, open: 11, resolved: 48, sla_resolve: 94.4 },
dimensions: [{ key: 'department', label: 'Abteilung' }, { key: 'month', label: 'Monat' }, { key: 'agent', label: 'Mitarbeiter' }],
metrics: [{ key: 'total', label: 'Tickets gesamt', unit: '' }, { key: 'open', label: 'Offen', unit: '' }, { key: 'resolved', label: 'Gelöst/Geschlossen', unit: '' }, { key: 'sla_resolve', label: 'SLA Lösung', unit: '%' }],
saved: [{ id: 1, name: 'Monatsbericht Support', isShared: true, mine: true, ownerName: 'Max Muster' }] }),
'canned_responses.php': () => ({ items: [{ id: 1, title: 'Gruß', body: 'Hallo,<br>danke für Ihre Nachricht.', departmentId: null }, { id: 2, title: 'Nur Technik', body: 'Technik-Text', departmentId: 1 }, { id: 3, title: 'Nur Vertrieb', body: 'Vertrieb-Text', departmentId: 2 }] }),
'customer.php': () => ({ customer: { name: 'Kunde 1', email: 'k1@mail.de' }, tickets }),
'teams.php': () => ({ staffOptions: [{ id: 1, name: 'Max Muster' }, { id: 2, name: 'Eva Beispiel' }], items: [{ id: 1, name: 'Support', leadId: 1, leadName: 'Max Muster', notes: '', isActive: true, memberCount: 2, memberIds: [1, 2] }] }),
'roles.php': () => ({ permissionKeys: ['reply_ticket', 'close_ticket', 'manage_teams'], defaultAgentPermissions: { reply_ticket: true }, items: [{ id: 1, name: 'Teamleitung', permissions: { reply_ticket: true }, staffCount: 2 }] }),
'business_hours.php': () => ({ enabled: true, hours: [1, 2, 3, 4, 5, 6, 0].map((w) => ({ weekday: w, isOpen: w > 0 && w < 6, openTime: '09:00', closeTime: '17:00' })), holidays: [{ id: 1, date: '2026-12-25', name: 'Weihnachten' }] }),
};
window.__calls = [];
window.deskhub = {
session: async () => ({ serverUrl: 'https://demo.example.de', staff }),
settings: async () => ({ theme: window.__theme || 'dark', autostart: false, closeToTray: true, notifications: true, pollSeconds: 60, version: '1.1.0', packaged: false }),
setSettings: async (p) => { if (p.theme) window.__theme = p.theme; return window.deskhub.settings(); },
login: async () => ({ staff }), logout: async () => true, notify: async () => {}, badge: async () => {},
openWeb: async (path) => { window.__web = path; return { data: true }; },
api: async (req) => { window.__calls.push(req.path); if (req.body) (window.__bodies = window.__bodies || {})[req.path] = req.body; window.__bodies = window.__bodies || {}; const f = routes[req.path]; return f ? { data: f(req) } : { error: { message: 'Mock: ' + req.path + ' nicht vorhanden' } }; },
onSessionExpired() {}, onNavigate() {},
};
</script>
<script src="../src/app.js"></script><script src="../src/admin-extra.js"></script>
</body></html>