import { html } from '@design.estate/dees-element'; import type { IIncidentDetails, IIncidentUpdate } from '../interfaces/index.js'; export const demoFunc = () => html`
Different Incident Types and Severities
{ const incidents = wrapperElement.querySelector('upl-statuspage-incidents') as any; // Generate different types of incidents const incidentScenarios = { critical: { name: 'Critical Outage', incidents: [ { id: 'crit-001', title: 'Complete Platform Outage', status: 'investigating' as const, severity: 'critical' as const, affectedServices: ['api-gateway', 'web-server', 'database', 'cdn'], startTime: Date.now() - 15 * 60 * 1000, impact: 'All services are currently unavailable. We are working on immediate resolution.', updates: [ { id: 'upd-c1', timestamp: Date.now() - 15 * 60 * 1000, status: 'investigating' as const, message: 'Multiple alerts triggered. All hands on deck.', author: 'Incident Commander' }, { id: 'upd-c2', timestamp: Date.now() - 10 * 60 * 1000, status: 'investigating' as const, message: 'Root cause appears to be datacenter power failure.', author: 'Infrastructure Team' } ] } ] }, major: { name: 'Major Issues', incidents: [ { id: 'maj-001', title: 'Database Performance Degradation', status: 'identified' as const, severity: 'major' as const, affectedServices: ['database', 'api-gateway'], startTime: Date.now() - 45 * 60 * 1000, impact: 'Significant slowdown in database queries affecting 60% of API requests.', updates: [ { id: 'upd-m1', timestamp: Date.now() - 45 * 60 * 1000, status: 'investigating' as const, message: 'Investigating database performance issues.', author: 'Database Team' }, { id: 'upd-m2', timestamp: Date.now() - 30 * 60 * 1000, status: 'identified' as const, message: 'Identified runaway queries causing resource exhaustion.', author: 'Database Team' } ] }, { id: 'maj-002', title: 'CDN Routing Issues', status: 'monitoring' as const, severity: 'major' as const, affectedServices: ['cdn'], startTime: Date.now() - 2 * 60 * 60 * 1000, impact: 'Assets loading slowly for users in EU region.', updates: [ { id: 'upd-m3', timestamp: Date.now() - 2 * 60 * 60 * 1000, status: 'investigating' as const, message: 'Reports of slow asset loading from EU users.', author: 'CDN Team' }, { id: 'upd-m4', timestamp: Date.now() - 90 * 60 * 1000, status: 'identified' as const, message: 'CDN provider experiencing issues with EU PoPs.', author: 'CDN Team' }, { id: 'upd-m5', timestamp: Date.now() - 30 * 60 * 1000, status: 'monitoring' as const, message: 'Rerouted traffic to alternate PoPs. Monitoring performance.', author: 'CDN Team' } ] } ] }, minor: { name: 'Minor Incidents', incidents: [ { id: 'min-001', title: 'Delayed Webhook Deliveries', status: 'monitoring' as const, severity: 'minor' as const, affectedServices: ['webhook-service'], startTime: Date.now() - 3 * 60 * 60 * 1000, impact: 'Webhooks experiencing 2-5 minute delays.', updates: [ { id: 'upd-n1', timestamp: Date.now() - 3 * 60 * 60 * 1000, status: 'investigating' as const, message: 'Investigating webhook delivery delays.', author: 'API Team' }, { id: 'upd-n2', timestamp: Date.now() - 2 * 60 * 60 * 1000, status: 'monitoring' as const, message: 'Queue processing optimized. Delays reducing.', author: 'API Team' } ] }, { id: 'min-002', title: 'Search Indexing Lag', status: 'identified' as const, severity: 'minor' as const, affectedServices: ['search-service'], startTime: Date.now() - 4 * 60 * 60 * 1000, impact: 'New content taking up to 30 minutes to appear in search results.', updates: [ { id: 'upd-n3', timestamp: Date.now() - 4 * 60 * 60 * 1000, status: 'identified' as const, message: 'Search indexing pipeline experiencing backlog.', author: 'Search Team' } ] } ] }, maintenance: { name: 'Maintenance', incidents: [ { id: 'maint-001', title: 'Scheduled Database Maintenance', status: 'identified' as const, severity: 'maintenance' as const, affectedServices: ['database'], startTime: Date.now() + 24 * 60 * 60 * 1000, endTime: Date.now() + 26 * 60 * 60 * 1000, impact: 'Database will be in read-only mode during maintenance window.', updates: [ { id: 'upd-mt1', timestamp: Date.now(), status: 'identified' as const, message: 'Scheduled maintenance for database version upgrade.', author: 'Database Team' } ] }, { id: 'maint-002', title: 'Network Equipment Upgrade', status: 'identified' as const, severity: 'maintenance' as const, affectedServices: ['cdn', 'api-gateway'], startTime: Date.now() + 48 * 60 * 60 * 1000, endTime: Date.now() + 49 * 60 * 60 * 1000, impact: 'Brief connectivity interruptions expected during upgrade window.', updates: [ { id: 'upd-mt2', timestamp: Date.now() - 2 * 60 * 60 * 1000, status: 'identified' as const, message: 'Core network switches scheduled for firmware upgrade.', author: 'Network Team' } ] } ] } }; // Initial setup let currentScenario = 'major'; incidents.currentIncidents = incidentScenarios[currentScenario].incidents; incidents.pastIncidents = []; // Create controls const controls = document.createElement('div'); controls.className = 'demo-controls'; Object.entries(incidentScenarios).forEach(([key, scenario]) => { const button = document.createElement('button'); button.className = 'demo-button' + (key === currentScenario ? ' active' : ''); button.textContent = scenario.name; button.onclick = () => { controls.querySelectorAll('.demo-button').forEach(btn => btn.classList.remove('active')); button.classList.add('active'); currentScenario = key; incidents.loading = true; setTimeout(() => { incidents.currentIncidents = scenario.incidents; incidents.loading = false; updateStats(); }, 500); }; controls.appendChild(button); }); wrapperElement.appendChild(controls); // Add statistics const statsDiv = document.createElement('div'); statsDiv.className = 'incident-stats'; wrapperElement.appendChild(statsDiv); const updateStats = () => { const current = incidents.currentIncidents || []; const critical = current.filter(i => i.severity === 'critical').length; const major = current.filter(i => i.severity === 'major').length; const minor = current.filter(i => i.severity === 'minor').length; const maintenance = current.filter(i => i.severity === 'maintenance').length; statsDiv.innerHTML = `
${critical}
Critical
${major}
Major
${minor}
Minor
${maintenance}
Maintenance
`; }; updateStats(); // Handle incident clicks incidents.addEventListener('incidentClick', (event: CustomEvent) => { alert(`Incident Details:\n\nTitle: ${event.detail.incident.title}\nSeverity: ${event.detail.incident.severity}\nStatus: ${event.detail.incident.status}\nImpact: ${event.detail.incident.impact}`); }); }} >
Real-time Incident Progression
{ const incidents = wrapperElement.querySelector('upl-statuspage-incidents') as any; // Create a progressing incident const progressingIncident: IIncidentDetails = { id: 'prog-001', title: 'Live Incident: Payment Processing Delays', status: 'investigating', severity: 'major', affectedServices: ['payment-gateway', 'api-gateway'], startTime: Date.now(), impact: 'Payment processing experiencing intermittent failures.', updates: [ { id: 'upd-p1', timestamp: Date.now(), status: 'investigating', message: 'We are investigating reports of payment processing failures.', author: 'Payment Team' } ] }; incidents.currentIncidents = [progressingIncident]; incidents.pastIncidents = []; // Progression timeline const progressionSteps = [ { delay: 10000, update: { status: 'investigating' as const, message: 'Initial investigation shows 30% of payment attempts failing.', author: 'Payment Team' } }, { delay: 20000, update: { status: 'identified' as const, message: 'Root cause identified: Third-party payment processor API rate limiting.', author: 'Engineering Team' }, incidentUpdate: { status: 'identified' as const } }, { delay: 30000, update: { status: 'monitoring' as const, message: 'Implemented retry logic and request throttling. Success rate improving.', author: 'Engineering Team' }, incidentUpdate: { status: 'monitoring' as const } }, { delay: 40000, update: { status: 'monitoring' as const, message: 'Payment success rate now at 95%. Continuing to monitor.', author: 'Payment Team' } }, { delay: 50000, update: { status: 'resolved' as const, message: 'All systems back to normal. Payment processing fully restored.', author: 'Payment Team' }, incidentUpdate: { status: 'resolved' as const, endTime: Date.now() + 50000, resolution: 'Implemented rate limiting and retry logic to prevent future occurrences.' } } ]; // Progress through steps progressionSteps.forEach((step, index) => { setTimeout(() => { const newUpdate: IIncidentUpdate = { id: `upd-p${index + 2}`, timestamp: Date.now(), ...step.update }; progressingIncident.updates.push(newUpdate); if (step.incidentUpdate) { Object.assign(progressingIncident, step.incidentUpdate); } if (progressingIncident.status === 'resolved') { // Move to past incidents incidents.pastIncidents = [progressingIncident, ...incidents.pastIncidents]; incidents.currentIncidents = []; } incidents.requestUpdate(); logUpdate(`[${step.update.status.toUpperCase()}] ${step.update.message}`); }, step.delay); }); // Create controls const controls = document.createElement('div'); controls.className = 'demo-controls'; controls.innerHTML = ` `; wrapperElement.appendChild(controls); controls.querySelector('#addUpdate')?.addEventListener('click', () => { if (progressingIncident.status !== 'resolved') { const message = prompt('Enter update message:'); if (message) { progressingIncident.updates.push({ id: `upd-custom-${Date.now()}`, timestamp: Date.now(), status: progressingIncident.status, message, author: 'Manual Update' }); incidents.requestUpdate(); logUpdate(`[MANUAL] ${message}`); } } }); controls.querySelector('#escalate')?.addEventListener('click', () => { if (progressingIncident.status !== 'resolved') { progressingIncident.severity = 'critical'; progressingIncident.updates.push({ id: `upd-esc-${Date.now()}`, timestamp: Date.now(), status: progressingIncident.status, message: 'Incident escalated to CRITICAL severity.', author: 'Incident Commander' }); incidents.requestUpdate(); logUpdate('[ESCALATED] Incident severity raised to CRITICAL'); } }); controls.querySelector('#resolve')?.addEventListener('click', () => { if (progressingIncident.status !== 'resolved') { progressingIncident.status = 'resolved'; progressingIncident.endTime = Date.now(); progressingIncident.resolution = 'Manually resolved.'; progressingIncident.updates.push({ id: `upd-res-${Date.now()}`, timestamp: Date.now(), status: 'resolved', message: 'Incident manually resolved.', author: 'Manual Resolution' }); incidents.pastIncidents = [progressingIncident, ...incidents.pastIncidents]; incidents.currentIncidents = []; incidents.requestUpdate(); logUpdate('[RESOLVED] Incident manually resolved'); } }); // Add update log const logDiv = document.createElement('div'); logDiv.className = 'incident-log'; logDiv.innerHTML = 'Incident Timeline:
'; wrapperElement.appendChild(logDiv); const logUpdate = (message: string) => { const time = new Date().toLocaleTimeString(); logDiv.innerHTML += `[${time}] ${message}
`; logDiv.scrollTop = logDiv.scrollHeight; }; logUpdate('[CREATED] New incident: Payment Processing Delays'); }} >
Historical Incident Patterns
{ const incidents = wrapperElement.querySelector('upl-statuspage-incidents') as any; // Generate historical patterns const generateHistoricalIncidents = (pattern: 'frequent' | 'seasonal' | 'improving' | 'stable'): IIncidentDetails[] => { const incidents: IIncidentDetails[] = []; const now = Date.now(); switch (pattern) { case 'frequent': // Many incidents in recent history for (let i = 0; i < 20; i++) { const daysAgo = Math.floor(Math.random() * 30); const duration = Math.floor(Math.random() * 4 + 1) * 60 * 60 * 1000; const startTime = now - daysAgo * 24 * 60 * 60 * 1000; incidents.push({ id: `freq-${i}`, title: `Service Disruption #${20 - i}`, status: 'resolved', severity: Math.random() < 0.3 ? 'major' : 'minor', affectedServices: ['api-gateway', 'database'].slice(0, Math.floor(Math.random() * 2) + 1), startTime, endTime: startTime + duration, impact: 'Service degradation affecting subset of users.', rootCause: 'Various infrastructure issues.', resolution: 'Applied temporary fixes.', updates: [ { id: `upd-${i}-1`, timestamp: startTime, status: 'investigating', message: 'Investigating service issues.', author: 'Ops Team' }, { id: `upd-${i}-2`, timestamp: startTime + duration, status: 'resolved', message: 'Issue resolved.', author: 'Ops Team' } ] }); } break; case 'seasonal': // Incidents clustered around specific times const peakDays = [7, 14, 21, 28]; // Weekly pattern peakDays.forEach((day, index) => { for (let j = 0; j < 3; j++) { const startTime = now - day * 24 * 60 * 60 * 1000 + (j - 1) * 60 * 60 * 1000; incidents.push({ id: `seas-${index}-${j}`, title: `Peak Traffic Overload`, status: 'resolved', severity: 'minor', affectedServices: ['api-gateway'], startTime, endTime: startTime + 30 * 60 * 1000, impact: 'Slow response times during peak hours.', rootCause: 'Insufficient capacity for peak traffic.', resolution: 'Auto-scaling adjusted.', updates: [ { id: `upd-s-${index}-${j}`, timestamp: startTime, status: 'resolved', message: 'Peak traffic handled by auto-scaling.', author: 'Auto-remediation' } ] }); } }); break; case 'improving': // Fewer incidents over time for (let i = 0; i < 15; i++) { const daysAgo = 30 - i * 2; if (Math.random() < (15 - i) / 15) { const startTime = now - daysAgo * 24 * 60 * 60 * 1000; incidents.push({ id: `imp-${i}`, title: `System Issue #${i + 1}`, status: 'resolved', severity: i < 5 ? 'major' : 'minor', affectedServices: ['database'], startTime, endTime: startTime + 2 * 60 * 60 * 1000, impact: 'Database performance issues.', rootCause: 'Legacy infrastructure limitations.', resolution: 'Infrastructure improvements implemented.', updates: [ { id: `upd-imp-${i}`, timestamp: startTime, status: 'resolved', message: 'Resolved with infrastructure improvements.', author: 'Infrastructure Team' } ] }); } } break; case 'stable': // Very few incidents, all minor for (let i = 0; i < 3; i++) { const daysAgo = Math.floor(Math.random() * 30); const startTime = now - daysAgo * 24 * 60 * 60 * 1000; incidents.push({ id: `stab-${i}`, title: ['Routine Maintenance', 'Minor Configuration Update', 'Planned Restart'][i], status: 'resolved', severity: 'maintenance', affectedServices: ['web-server'], startTime, endTime: startTime + 15 * 60 * 1000, impact: 'No user impact.', resolution: 'Completed as planned.', updates: [ { id: `upd-stab-${i}`, timestamp: startTime, status: 'resolved', message: 'Maintenance completed successfully.', author: 'Maintenance Team' } ] }); } break; } return incidents.sort((a, b) => b.startTime - a.startTime); }; // Initial setup let currentPattern: 'frequent' | 'seasonal' | 'improving' | 'stable' = 'frequent'; incidents.currentIncidents = []; incidents.pastIncidents = generateHistoricalIncidents(currentPattern); // Create pattern controls const controls = document.createElement('div'); controls.className = 'demo-controls'; const patterns = [ { key: 'frequent', label: 'Frequent Incidents' }, { key: 'seasonal', label: 'Seasonal Pattern' }, { key: 'improving', label: 'Improving Trend' }, { key: 'stable', label: 'Stable System' } ]; patterns.forEach((pattern) => { const button = document.createElement('button'); button.className = 'demo-button' + (pattern.key === currentPattern ? ' active' : ''); button.textContent = pattern.label; button.onclick = () => { controls.querySelectorAll('.demo-button').forEach(btn => btn.classList.remove('active')); button.classList.add('active'); currentPattern = pattern.key as any; incidents.loading = true; setTimeout(() => { incidents.pastIncidents = generateHistoricalIncidents(currentPattern as any); incidents.loading = false; }, 500); }; controls.appendChild(button); }); wrapperElement.appendChild(controls); // Add info about the pattern const info = document.createElement('div'); info.className = 'demo-info'; info.innerHTML = ` Pattern Description:
Frequent: Many incidents indicating stability issues
Seasonal: Incidents following a predictable pattern
Improving: Decreasing incident frequency over time
Stable: Minimal incidents, mostly maintenance `; wrapperElement.appendChild(info); }} >
Edge Cases and Special Scenarios
{ const incidents = wrapperElement.querySelector('upl-statuspage-incidents') as any; const edgeCases = { none: { name: 'No Incidents', current: [], past: [] }, manyActive: { name: 'Many Active', current: Array.from({ length: 8 }, (_, i) => ({ id: `many-${i}`, title: `Concurrent Issue #${i + 1}`, status: ['investigating', 'identified', 'monitoring'][i % 3] as any, severity: ['critical', 'major', 'minor'][i % 3] as any, affectedServices: [`service-${i}`], startTime: Date.now() - (i + 1) * 30 * 60 * 1000, impact: `Impact on service ${i + 1}`, updates: [{ id: `upd-many-${i}`, timestamp: Date.now() - (i + 1) * 30 * 60 * 1000, status: 'investigating' as const, message: 'Investigating issue.', author: 'Team' }] })), past: [] }, longRunning: { name: 'Long Running', current: [{ id: 'long-001', title: 'Persistent Infrastructure Issue', status: 'monitoring' as const, severity: 'major' as const, affectedServices: ['database', 'api-gateway'], startTime: Date.now() - 7 * 24 * 60 * 60 * 1000, // 7 days ago impact: 'Intermittent issues affecting 5-10% of requests.', updates: Array.from({ length: 50 }, (_, i) => ({ id: `upd-long-${i}`, timestamp: Date.now() - 7 * 24 * 60 * 60 * 1000 + i * 3 * 60 * 60 * 1000, status: 'monitoring' as const, message: `Update #${i + 1}: Continuing to monitor. Partial mitigation in place.`, author: 'Ops Team' })) }], past: [] }, complexUpdates: { name: 'Complex Updates', current: [{ id: 'complex-001', title: 'Multi-phase Incident Resolution', status: 'monitoring' as const, severity: 'critical' as const, affectedServices: ['api-gateway', 'database', 'cdn', 'email-service'], startTime: Date.now() - 4 * 60 * 60 * 1000, impact: 'Multiple services experiencing cascading failures.', updates: [ { id: 'upd-c1', timestamp: Date.now() - 4 * 60 * 60 * 1000, status: 'investigating' as const, message: '🚨 CRITICAL: Multiple service alerts triggered simultaneously.', author: 'Monitoring System' }, { id: 'upd-c2', timestamp: Date.now() - 3.5 * 60 * 60 * 1000, status: 'investigating' as const, message: 'All hands on deck. Incident commander taking charge.\n\n- API Gateway: DOWN\n- Database: DEGRADED\n- CDN: PARTIAL OUTAGE\n- Email: DELAYED', author: 'Incident Commander' }, { id: 'upd-c3', timestamp: Date.now() - 3 * 60 * 60 * 1000, status: 'identified' as const, message: 'Root cause identified: Cascading failure triggered by database connection pool exhaustion.\n\nAction items:\n1. Restart connection pools\n2. Implement circuit breakers\n3. Scale up database replicas', author: 'Engineering Lead' }, { id: 'upd-c4', timestamp: Date.now() - 2 * 60 * 60 * 1000, status: 'monitoring' as const, message: 'Partial recovery achieved:\n✅ API Gateway: RESTORED\n⚠️ Database: RECOVERING\n✅ CDN: OPERATIONAL\n⚠️ Email: CATCHING UP\n\nContinuing remediation efforts.', author: 'Ops Team' } ] }], past: [] } }; // Initial setup let currentCase = 'none'; incidents.currentIncidents = edgeCases[currentCase].current; incidents.pastIncidents = edgeCases[currentCase].past; // Create controls const controls = document.createElement('div'); controls.className = 'demo-controls'; Object.entries(edgeCases).forEach(([key, scenario]) => { const button = document.createElement('button'); button.className = 'demo-button' + (key === currentCase ? ' active' : ''); button.textContent = scenario.name; button.onclick = () => { controls.querySelectorAll('.demo-button').forEach(btn => btn.classList.remove('active')); button.classList.add('active'); currentCase = key; incidents.loading = true; setTimeout(() => { incidents.currentIncidents = scenario.current; incidents.pastIncidents = scenario.past; incidents.loading = false; }, 300); }; controls.appendChild(button); }); wrapperElement.appendChild(controls); }} >
Loading States and Filtering
{ const incidents = wrapperElement.querySelector('upl-statuspage-incidents') as any; // Start with loading incidents.loading = true; // Generate mixed incidents for filtering const allIncidents: IIncidentDetails[] = [ { id: 'filter-1', title: 'Critical Database Failure', status: 'resolved', severity: 'critical', affectedServices: ['database'], startTime: Date.now() - 2 * 24 * 60 * 60 * 1000, endTime: Date.now() - 2 * 24 * 60 * 60 * 1000 + 4 * 60 * 60 * 1000, impact: 'Complete database unavailability.', resolution: 'Failed over to secondary cluster.', updates: [{ id: 'u1', timestamp: Date.now() - 2 * 24 * 60 * 60 * 1000, status: 'resolved', message: 'Database restored.', author: 'DBA Team' }] }, { id: 'filter-2', title: 'API Rate Limiting Issues', status: 'resolved', severity: 'major', affectedServices: ['api-gateway'], startTime: Date.now() - 5 * 24 * 60 * 60 * 1000, endTime: Date.now() - 5 * 24 * 60 * 60 * 1000 + 2 * 60 * 60 * 1000, impact: 'API requests throttled for some users.', resolution: 'Rate limits adjusted.', updates: [{ id: 'u2', timestamp: Date.now() - 5 * 24 * 60 * 60 * 1000, status: 'resolved', message: 'Rate limiting resolved.', author: 'API Team' }] }, { id: 'filter-3', title: 'Email Delays', status: 'resolved', severity: 'minor', affectedServices: ['email-service'], startTime: Date.now() - 10 * 24 * 60 * 60 * 1000, endTime: Date.now() - 10 * 24 * 60 * 60 * 1000 + 30 * 60 * 1000, impact: 'Emails delayed by 5-10 minutes.', resolution: 'Queue cleared.', updates: [{ id: 'u3', timestamp: Date.now() - 10 * 24 * 60 * 60 * 1000, status: 'resolved', message: 'Email queue cleared.', author: 'Email Team' }] }, { id: 'filter-4', title: 'Scheduled Maintenance', status: 'resolved', severity: 'maintenance', affectedServices: ['web-server'], startTime: Date.now() - 15 * 24 * 60 * 60 * 1000, endTime: Date.now() - 15 * 24 * 60 * 60 * 1000 + 60 * 60 * 1000, impact: 'Brief downtime during upgrade.', resolution: 'Upgrade completed.', updates: [{ id: 'u4', timestamp: Date.now() - 15 * 24 * 60 * 60 * 1000, status: 'resolved', message: 'Maintenance completed.', author: 'Ops Team' }] } ]; const controls = document.createElement('div'); controls.className = 'demo-controls'; controls.innerHTML = ` `; wrapperElement.appendChild(controls); controls.querySelector('#toggleLoading')?.addEventListener('click', () => { incidents.loading = !incidents.loading; }); controls.querySelector('#loadSuccess')?.addEventListener('click', () => { incidents.loading = true; setTimeout(() => { incidents.currentIncidents = [ { id: 'current-1', title: 'Ongoing Investigation', status: 'investigating', severity: 'minor', affectedServices: ['api-gateway'], startTime: Date.now() - 30 * 60 * 1000, impact: 'Elevated error rates on API endpoints.', updates: [{ id: 'u-current', timestamp: Date.now() - 30 * 60 * 1000, status: 'investigating', message: 'Investigating elevated error rates.', author: 'API Team' }] } ]; incidents.pastIncidents = allIncidents; incidents.loading = false; }, 1000); }); controls.querySelector('#loadError')?.addEventListener('click', () => { incidents.loading = true; setTimeout(() => { incidents.loading = false; incidents.currentIncidents = []; incidents.pastIncidents = []; incidents.errorMessage = 'Failed to load incident data'; }, 1500); }); controls.querySelector('#filterCritical')?.addEventListener('click', () => { incidents.pastIncidents = allIncidents.filter(i => i.severity === 'critical'); }); controls.querySelector('#showAll')?.addEventListener('click', () => { incidents.pastIncidents = allIncidents; }); // Initial load after delay setTimeout(() => { incidents.currentIncidents = []; incidents.pastIncidents = allIncidents; incidents.loading = false; }, 2000); }} >
`;