import { html } from '@design.estate/dees-element'; import type { IStatusHistoryPoint } from '../interfaces/index.js'; export const demoFunc = () => html`
Different Time Ranges
{ const statusDetails = wrapperElement.querySelector('upl-statuspage-statusdetails') as any; // Generate data for different time ranges const generateDataForRange = (hours: number, pattern: 'stable' | 'degrading' | 'improving' | 'volatile' = 'stable'): IStatusHistoryPoint[] => { const now = Date.now(); const data: IStatusHistoryPoint[] = []; // For proper display, we need hourly data points that align with actual hours for (let i = hours - 1; i >= 0; i--) { // Create timestamp at the start of each hour const date = new Date(); date.setMinutes(0, 0, 0); date.setHours(date.getHours() - i); const timestamp = date.getTime(); let status: IStatusHistoryPoint['status'] = 'operational'; let responseTime = 50 + Math.random() * 50; let errorRate = 0; switch (pattern) { case 'degrading': // Getting worse over time const degradation = (hours - i) / hours; if (degradation > 0.7) { status = 'major_outage'; responseTime = 800 + Math.random() * 200; errorRate = 0.3 + Math.random() * 0.2; } else if (degradation > 0.5) { status = 'partial_outage'; responseTime = 500 + Math.random() * 200; errorRate = 0.1 + Math.random() * 0.1; } else if (degradation > 0.3) { status = 'degraded'; responseTime = 200 + Math.random() * 100; errorRate = 0.02 + Math.random() * 0.03; } break; case 'improving': // Getting better over time const improvement = i / hours; if (improvement < 0.3) { status = 'major_outage'; responseTime = 800 + Math.random() * 200; errorRate = 0.3 + Math.random() * 0.2; } else if (improvement < 0.5) { status = 'partial_outage'; responseTime = 500 + Math.random() * 200; errorRate = 0.1 + Math.random() * 0.1; } else if (improvement < 0.7) { status = 'degraded'; responseTime = 200 + Math.random() * 100; errorRate = 0.02 + Math.random() * 0.03; } break; case 'volatile': // Random ups and downs const rand = Math.random(); if (rand < 0.05) { status = 'major_outage'; responseTime = 800 + Math.random() * 200; errorRate = 0.3 + Math.random() * 0.2; } else if (rand < 0.1) { status = 'partial_outage'; responseTime = 500 + Math.random() * 200; errorRate = 0.1 + Math.random() * 0.1; } else if (rand < 0.2) { status = 'degraded'; responseTime = 200 + Math.random() * 100; errorRate = 0.02 + Math.random() * 0.03; } else if (rand < 0.25) { status = 'maintenance'; responseTime = 100 + Math.random() * 50; errorRate = 0; } break; default: // Stable with occasional hiccups if (Math.random() < 0.02) { status = 'degraded'; responseTime = 200 + Math.random() * 100; errorRate = 0.01 + Math.random() * 0.02; } } data.push({ timestamp, status, responseTime, errorRate }); } return data; }; // Initial setup statusDetails.serviceId = 'api-gateway'; statusDetails.serviceName = 'API Gateway'; statusDetails.historyData = generateDataForRange(24); // Create controls const controls = document.createElement('div'); controls.className = 'demo-controls'; const timeRanges = [ { hours: 24, label: '24 Hours' }, { hours: 168, label: '7 Days' }, { hours: 720, label: '30 Days' }, { hours: 2160, label: '90 Days' } ]; timeRanges.forEach((range, index) => { const button = document.createElement('button'); button.className = 'demo-button' + (index === 0 ? ' active' : ''); button.textContent = range.label; button.onclick = () => { // Update active button controls.querySelectorAll('.demo-button').forEach(btn => btn.classList.remove('active')); button.classList.add('active'); // Load new data with loading state statusDetails.loading = true; setTimeout(() => { statusDetails.historyData = generateDataForRange(range.hours, 'volatile'); statusDetails.loading = false; updateStats(); }, 500); }; controls.appendChild(button); }); wrapperElement.appendChild(controls); // Add statistics display const statsDiv = document.createElement('div'); statsDiv.className = 'stats-grid'; wrapperElement.appendChild(statsDiv); const updateStats = () => { const data = statusDetails.historyData || []; const operational = data.filter(d => d.status === 'operational').length; const avgResponseTime = data.reduce((sum, d) => sum + (d.responseTime || 0), 0) / data.length; const uptime = (operational / data.length) * 100; const incidents = data.filter(d => d.status !== 'operational' && d.status !== 'maintenance').length; statsDiv.innerHTML = `
${uptime.toFixed(2)}%
Uptime
${avgResponseTime.toFixed(0)}ms
Avg Response Time
${incidents}
Incidents
${data.length}
Data Points
`; }; updateStats(); // Handle bar clicks statusDetails.addEventListener('barClick', (event: CustomEvent) => { const { timestamp, status, responseTime, errorRate } = event.detail; const date = new Date(timestamp); alert(`Details for ${date.toLocaleString()}:\n\nStatus: ${status}\nResponse Time: ${responseTime.toFixed(0)}ms\nError Rate: ${(errorRate * 100).toFixed(2)}%`); }); }} >
Different Data Patterns
{ const statusDetails = wrapperElement.querySelector('upl-statuspage-statusdetails') as any; // Pattern generators const patterns = { stable: () => { const data: IStatusHistoryPoint[] = []; for (let i = 47; i >= 0; i--) { const date = new Date(); date.setMinutes(0, 0, 0); date.setHours(date.getHours() - i); data.push({ timestamp: date.getTime(), status: 'operational', responseTime: 40 + Math.random() * 20, errorRate: 0 }); } return data; }, degrading: () => { const now = Date.now(); const data: IStatusHistoryPoint[] = []; for (let i = 47; i >= 0; i--) { const degradation = (47 - i) / 47; let status: IStatusHistoryPoint['status'] = 'operational'; let responseTime = 50; let errorRate = 0; if (degradation > 0.8) { status = 'major_outage'; responseTime = 800 + Math.random() * 200; errorRate = 0.4; } else if (degradation > 0.6) { status = 'partial_outage'; responseTime = 500 + Math.random() * 100; errorRate = 0.2; } else if (degradation > 0.4) { status = 'degraded'; responseTime = 200 + Math.random() * 100; errorRate = 0.05; } else { responseTime = 50 + degradation * 100; } data.push({ timestamp: now - (i * 60 * 60 * 1000), status, responseTime, errorRate }); } return data; }, recovering: () => { const now = Date.now(); const data: IStatusHistoryPoint[] = []; for (let i = 47; i >= 0; i--) { const recovery = i / 47; let status: IStatusHistoryPoint['status'] = 'operational'; let responseTime = 50; let errorRate = 0; if (recovery < 0.2) { status = 'operational'; responseTime = 50 + Math.random() * 20; } else if (recovery < 0.4) { status = 'degraded'; responseTime = 150 + Math.random() * 50; errorRate = 0.02; } else if (recovery < 0.7) { status = 'partial_outage'; responseTime = 400 + Math.random() * 100; errorRate = 0.15; } else { status = 'major_outage'; responseTime = 800 + Math.random() * 200; errorRate = 0.35; } data.push({ timestamp: now - (i * 60 * 60 * 1000), status, responseTime, errorRate }); } return data; }, periodic: () => { const now = Date.now(); const data: IStatusHistoryPoint[] = []; for (let i = 47; i >= 0; i--) { // Issues every 12 hours const hourOfDay = i % 24; let status: IStatusHistoryPoint['status'] = 'operational'; let responseTime = 50 + Math.random() * 30; let errorRate = 0; if (hourOfDay >= 9 && hourOfDay <= 11) { // Morning peak status = 'degraded'; responseTime = 200 + Math.random() * 100; errorRate = 0.05; } else if (hourOfDay >= 18 && hourOfDay <= 20) { // Evening peak status = 'degraded'; responseTime = 250 + Math.random() * 150; errorRate = 0.08; } data.push({ timestamp: now - (i * 60 * 60 * 1000), status, responseTime, errorRate }); } return data; }, maintenance: () => { const now = Date.now(); const data: IStatusHistoryPoint[] = []; for (let i = 47; i >= 0; i--) { let status: IStatusHistoryPoint['status'] = 'operational'; let responseTime = 50 + Math.random() * 30; let errorRate = 0; // Maintenance window from hour 20-24 if (i >= 20 && i <= 24) { status = 'maintenance'; responseTime = 0; errorRate = 0; } data.push({ timestamp: now - (i * 60 * 60 * 1000), status, responseTime, errorRate }); } return data; } }; // Initial setup statusDetails.serviceId = 'web-server'; statusDetails.serviceName = 'Web Server'; statusDetails.historyData = patterns.stable(); // Create controls const controls = document.createElement('div'); controls.className = 'demo-controls'; Object.entries(patterns).forEach(([name, generator]) => { const button = document.createElement('button'); button.className = 'demo-button' + (name === 'stable' ? ' active' : ''); button.textContent = name.charAt(0).toUpperCase() + name.slice(1); button.onclick = () => { controls.querySelectorAll('.demo-button').forEach(btn => btn.classList.remove('active')); button.classList.add('active'); statusDetails.loading = true; setTimeout(() => { statusDetails.historyData = generator(); statusDetails.loading = false; updateInfo(name); }, 300); }; controls.appendChild(button); }); wrapperElement.appendChild(controls); // Add info display const info = document.createElement('div'); info.className = 'demo-info'; wrapperElement.appendChild(info); const updateInfo = (pattern: string) => { const descriptions = { stable: 'Service running smoothly with consistent performance', degrading: 'Service health deteriorating over time', recovering: 'Service recovering from a major outage', periodic: 'Regular performance issues during peak hours (9-11 AM and 6-8 PM)', maintenance: 'Scheduled maintenance window (hours 20-24)' }; info.innerHTML = `Pattern: ${descriptions[pattern as keyof typeof descriptions] || pattern}`; }; updateInfo('stable'); }} >
Real-time Updates with Manual Control
{ const statusDetails = wrapperElement.querySelector('upl-statuspage-statusdetails') as any; // Initialize with recent data const now = Date.now(); const initialData: IStatusHistoryPoint[] = []; for (let i = 23; i >= 0; i--) { initialData.push({ timestamp: now - (i * 60 * 60 * 1000), status: 'operational', responseTime: 50 + Math.random() * 30, errorRate: 0 }); } statusDetails.serviceId = 'real-time-api'; statusDetails.serviceName = 'Real-time API'; statusDetails.historyData = initialData; statusDetails.timeRange = '24h'; // Create controls const controls = document.createElement('div'); controls.className = 'demo-controls'; controls.innerHTML = ` `; wrapperElement.appendChild(controls); const addDataPoint = (status: IStatusHistoryPoint['status'], responseTime: number, errorRate: number = 0) => { const data = [...(statusDetails.historyData || [])]; if (data.length >= 24) { data.shift(); // Keep only 24 points } data.push({ timestamp: Date.now(), status, responseTime, errorRate }); statusDetails.historyData = data; }; controls.querySelector('#addHealthy')?.addEventListener('click', () => { addDataPoint('operational', 50 + Math.random() * 30); }); controls.querySelector('#addDegraded')?.addEventListener('click', () => { addDataPoint('degraded', 200 + Math.random() * 100, 0.05); }); controls.querySelector('#addOutage')?.addEventListener('click', () => { addDataPoint('major_outage', 800 + Math.random() * 200, 0.5); }); controls.querySelector('#simulateSpike')?.addEventListener('click', () => { // Add several degraded points for (let i = 0; i < 3; i++) { setTimeout(() => { addDataPoint('degraded', 300 + Math.random() * 200, 0.1 + Math.random() * 0.1); }, i * 1000); } }); controls.querySelector('#clearData')?.addEventListener('click', () => { statusDetails.historyData = []; }); // Auto-update every 5 seconds let autoUpdate = setInterval(() => { const rand = Math.random(); if (rand < 0.8) { addDataPoint('operational', 40 + Math.random() * 40); } else if (rand < 0.95) { addDataPoint('degraded', 150 + Math.random() * 100, 0.02); } else { addDataPoint('partial_outage', 400 + Math.random() * 200, 0.15); } }, 5000); // Add toggle for auto-updates const autoToggle = document.createElement('button'); autoToggle.className = 'demo-button active'; autoToggle.textContent = 'Auto-update: ON'; autoToggle.style.marginLeft = '10px'; autoToggle.onclick = () => { if (autoUpdate) { clearInterval(autoUpdate); autoUpdate = null; autoToggle.textContent = 'Auto-update: OFF'; autoToggle.classList.remove('active'); } else { autoUpdate = setInterval(() => { const rand = Math.random(); if (rand < 0.8) { addDataPoint('operational', 40 + Math.random() * 40); } else if (rand < 0.95) { addDataPoint('degraded', 150 + Math.random() * 100, 0.02); } else { addDataPoint('partial_outage', 400 + Math.random() * 200, 0.15); } }, 5000); autoToggle.textContent = 'Auto-update: ON'; autoToggle.classList.add('active'); } }; controls.appendChild(autoToggle); // Cleanup on unmount wrapperElement.addEventListener('remove', () => { if (autoUpdate) clearInterval(autoUpdate); }); }} >
Edge Cases and Special Scenarios
{ const statusDetails = wrapperElement.querySelector('upl-statuspage-statusdetails') as any; const scenarios = { noData: { name: 'No Data Available', data: [] }, singlePoint: { name: 'Single Data Point', data: [{ timestamp: Date.now(), status: 'operational' as const, responseTime: 75, errorRate: 0 }] }, allDown: { name: 'Complete Outage', data: Array.from({ length: 48 }, (_, i) => ({ timestamp: Date.now() - (i * 60 * 60 * 1000), status: 'major_outage' as const, responseTime: 0, errorRate: 1 })) }, highLatency: { name: 'High Latency Issues', data: Array.from({ length: 48 }, (_, i) => ({ timestamp: Date.now() - (i * 60 * 60 * 1000), status: 'operational' as const, responseTime: 2000 + Math.random() * 1000, errorRate: 0 })) }, mixedStatuses: { name: 'All Status Types', data: Array.from({ length: 50 }, (_, i) => { const statuses: IStatusHistoryPoint['status'][] = ['operational', 'degraded', 'partial_outage', 'major_outage', 'maintenance']; const status = statuses[i % statuses.length]; return { timestamp: Date.now() - (i * 60 * 60 * 1000), status, responseTime: status === 'operational' ? 50 : status === 'maintenance' ? 0 : 200 + Math.random() * 600, errorRate: status === 'operational' || status === 'maintenance' ? 0 : 0.1 + Math.random() * 0.4 }; }) } }; // Initial scenario let currentScenario = 'noData'; statusDetails.serviceId = 'edge-case-service'; statusDetails.serviceName = 'Edge Case Service'; statusDetails.historyData = scenarios[currentScenario].data; // Create scenario buttons const controls = document.createElement('div'); controls.className = 'demo-controls'; Object.entries(scenarios).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; statusDetails.loading = true; setTimeout(() => { statusDetails.historyData = scenario.data; statusDetails.loading = false; }, 300); }; controls.appendChild(button); }); wrapperElement.appendChild(controls); }} >
Loading and Error Handling
{ const statusDetails = wrapperElement.querySelector('upl-statuspage-statusdetails') as any; // Start with loading statusDetails.loading = true; statusDetails.serviceId = 'loading-demo'; statusDetails.serviceName = 'Loading Demo Service'; const controls = document.createElement('div'); controls.className = 'demo-controls'; controls.innerHTML = ` `; wrapperElement.appendChild(controls); controls.querySelector('#toggleLoading')?.addEventListener('click', () => { statusDetails.loading = !statusDetails.loading; }); controls.querySelector('#loadSuccess')?.addEventListener('click', () => { statusDetails.loading = true; setTimeout(() => { const now = Date.now(); statusDetails.historyData = Array.from({ length: 24 }, (_, i) => ({ timestamp: now - (i * 60 * 60 * 1000), status: Math.random() > 0.9 ? 'degraded' : 'operational', responseTime: 50 + Math.random() * 50, errorRate: 0 })); statusDetails.loading = false; }, 500); }); controls.querySelector('#loadError')?.addEventListener('click', () => { statusDetails.loading = true; setTimeout(() => { statusDetails.loading = false; statusDetails.historyData = []; statusDetails.errorMessage = 'Failed to load status data: Connection timeout'; }, 1500); }); controls.querySelector('#loadSlowly')?.addEventListener('click', () => { statusDetails.loading = true; setTimeout(() => { const now = Date.now(); statusDetails.historyData = Array.from({ length: 48 }, (_, i) => ({ timestamp: now - (i * 60 * 60 * 1000), status: 'operational', responseTime: 45 + Math.random() * 30, errorRate: 0 })); statusDetails.loading = false; }, 3000); }); }} >
`;