import { html } from '@design.estate/dees-element'; import type { IMonthlyUptime, IUptimeDay } from '../interfaces/index.js'; export const demoFunc = () => html`
Different Month Patterns
{ const statusMonth = wrapperElement.querySelector('upl-statuspage-statusmonth') as any; // Pattern generators const generateMonthPattern = (monthCount: number, pattern: 'perfect' | 'problematic' | 'improving' | 'degrading' | 'seasonal'): IMonthlyUptime[] => { const months: IMonthlyUptime[] = []; const now = new Date(); for (let monthOffset = monthCount - 1; monthOffset >= 0; monthOffset--) { const monthDate = new Date(now.getFullYear(), now.getMonth() - monthOffset, 1); const year = monthDate.getFullYear(); const month = monthDate.getMonth(); const monthKey = `${year}-${String(month + 1).padStart(2, '0')}`; const daysInMonth = new Date(year, month + 1, 0).getDate(); const days: IUptimeDay[] = []; let totalIncidents = 0; let totalUptimeMinutes = 0; for (let day = 1; day <= daysInMonth; day++) { let uptime = 100; let incidents = 0; let downtime = 0; let status: IUptimeDay['status'] = 'operational'; switch (pattern) { case 'perfect': // Near perfect uptime if (Math.random() < 0.02) { uptime = 99.9 + Math.random() * 0.099; status = 'degraded'; } break; case 'problematic': // Frequent issues const problemRand = Math.random(); if (problemRand < 0.1) { uptime = 70 + Math.random() * 20; incidents = 2 + Math.floor(Math.random() * 3); status = 'major_outage'; } else if (problemRand < 0.25) { uptime = 90 + Math.random() * 8; incidents = 1 + Math.floor(Math.random() * 2); status = 'partial_outage'; } else if (problemRand < 0.4) { uptime = 98 + Math.random() * 1.5; incidents = 1; status = 'degraded'; } break; case 'improving': // Getting better over time const improvementFactor = (monthCount - monthOffset) / monthCount; const improveRand = Math.random(); if (improveRand < 0.3 * (1 - improvementFactor)) { uptime = 85 + Math.random() * 10 + (improvementFactor * 10); incidents = Math.max(0, 3 - Math.floor(improvementFactor * 3)); status = improvementFactor > 0.7 ? 'degraded' : 'partial_outage'; } break; case 'degrading': // Getting worse over time const degradationFactor = monthOffset / monthCount; const degradeRand = Math.random(); if (degradeRand < 0.3 * (1 - degradationFactor)) { uptime = 85 + Math.random() * 10 + (degradationFactor * 10); incidents = Math.max(0, 3 - Math.floor(degradationFactor * 3)); status = degradationFactor > 0.7 ? 'degraded' : 'major_outage'; } break; case 'seasonal': // Worse during certain months (simulating high traffic periods) const monthNum = month; if (monthNum === 11 || monthNum === 0) { // December, January if (Math.random() < 0.3) { uptime = 92 + Math.random() * 6; incidents = 1 + Math.floor(Math.random() * 2); status = 'degraded'; } } else if (monthNum === 6 || monthNum === 7) { // July, August if (Math.random() < 0.2) { uptime = 94 + Math.random() * 5; incidents = 1; status = 'degraded'; } } break; } downtime = Math.floor((100 - uptime) * 14.4); totalIncidents += incidents; totalUptimeMinutes += uptime * 14.4; days.push({ date: `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`, uptime, incidents, totalDowntime: downtime, status }); } const overallUptime = totalUptimeMinutes / (daysInMonth * 1440) * 100; months.push({ month: monthKey, days, overallUptime, totalIncidents }); } return months; }; // Initial setup statusMonth.serviceId = 'production-api'; statusMonth.serviceName = 'Production API'; statusMonth.monthlyData = generateMonthPattern(6, 'perfect'); // Create pattern controls const controls = document.createElement('div'); controls.className = 'demo-controls'; const patterns = [ { key: 'perfect', label: 'Perfect Uptime' }, { key: 'problematic', label: 'Problematic' }, { key: 'improving', label: 'Improving Trend' }, { key: 'degrading', label: 'Degrading Trend' }, { key: 'seasonal', label: 'Seasonal Pattern' } ]; patterns.forEach((pattern, index) => { const button = document.createElement('button'); button.className = 'demo-button' + (index === 0 ? ' active' : ''); button.textContent = pattern.label; button.onclick = () => { controls.querySelectorAll('.demo-button').forEach(btn => btn.classList.remove('active')); button.classList.add('active'); statusMonth.loading = true; setTimeout(() => { statusMonth.monthlyData = generateMonthPattern(6, pattern.key as any); statusMonth.loading = false; updateStats(); }, 500); }; controls.appendChild(button); }); wrapperElement.appendChild(controls); // Add statistics display const statsDiv = document.createElement('div'); statsDiv.className = 'stats-display'; wrapperElement.appendChild(statsDiv); const updateStats = () => { const data = statusMonth.monthlyData || []; const avgUptime = data.reduce((sum, month) => sum + month.overallUptime, 0) / data.length; const totalIncidents = data.reduce((sum, month) => sum + month.totalIncidents, 0); const worstMonth = data.reduce((worst, month) => month.overallUptime < worst.overallUptime ? month : worst, data[0]); statsDiv.innerHTML = `
${avgUptime.toFixed(3)}%
Avg Uptime
${totalIncidents}
Total Incidents
${data.length}
Months
${worstMonth ? worstMonth.overallUptime.toFixed(2) : '100'}%
Worst Month
`; }; updateStats(); // Handle day clicks statusMonth.addEventListener('dayClick', (event: CustomEvent) => { const { date, uptime, incidents, status, totalDowntime } = event.detail; alert(`Day Details for ${date}:\n\nUptime: ${uptime.toFixed(3)}%\nIncidents: ${incidents}\nStatus: ${status}\nDowntime: ${totalDowntime} minutes`); }); }} >
Different Time Spans
{ const statusMonth = wrapperElement.querySelector('upl-statuspage-statusmonth') as any; // Generate data for different time spans const generateTimeSpanData = (months: number): IMonthlyUptime[] => { const data: IMonthlyUptime[] = []; const now = new Date(); for (let monthOffset = months - 1; monthOffset >= 0; monthOffset--) { const monthDate = new Date(now.getFullYear(), now.getMonth() - monthOffset, 1); const year = monthDate.getFullYear(); const month = monthDate.getMonth(); const monthKey = `${year}-${String(month + 1).padStart(2, '0')}`; const daysInMonth = new Date(year, month + 1, 0).getDate(); const days: IUptimeDay[] = []; let totalIncidents = 0; let totalUptimeMinutes = 0; for (let day = 1; day <= daysInMonth; day++) { // Create realistic patterns let uptime = 99.9 + Math.random() * 0.099; let incidents = 0; let status: IUptimeDay['status'] = 'operational'; if (Math.random() < 0.05) { uptime = 95 + Math.random() * 4.9; incidents = 1; status = 'degraded'; } else if (Math.random() < 0.01) { uptime = 85 + Math.random() * 10; incidents = 2; status = 'partial_outage'; } const downtime = Math.floor((100 - uptime) * 14.4); totalIncidents += incidents; totalUptimeMinutes += uptime * 14.4; days.push({ date: `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`, uptime, incidents, totalDowntime: downtime, status }); } const overallUptime = totalUptimeMinutes / (daysInMonth * 1440) * 100; data.push({ month: monthKey, days, overallUptime, totalIncidents }); } return data; }; // Initial setup statusMonth.serviceId = 'multi-region-lb'; statusMonth.serviceName = 'Multi-Region Load Balancer'; statusMonth.monthlyData = generateTimeSpanData(3); // Create time span controls const controls = document.createElement('div'); controls.className = 'demo-controls'; const timeSpans = [ { months: 3, label: 'Last 3 Months' }, { months: 6, label: 'Last 6 Months' }, { months: 12, label: 'Last 12 Months' }, { months: 24, label: 'Last 24 Months' } ]; timeSpans.forEach((span, index) => { const button = document.createElement('button'); button.className = 'demo-button' + (index === 0 ? ' active' : ''); button.textContent = span.label; button.onclick = () => { controls.querySelectorAll('.demo-button').forEach(btn => btn.classList.remove('active')); button.classList.add('active'); statusMonth.loading = true; setTimeout(() => { statusMonth.monthlyData = generateTimeSpanData(span.months); statusMonth.loading = false; }, 500); }; controls.appendChild(button); }); wrapperElement.appendChild(controls); // Add info display const info = document.createElement('div'); info.className = 'demo-info'; info.innerHTML = 'Click on different time spans to see historical uptime data. The component automatically adjusts the display based on the number of months.'; wrapperElement.appendChild(info); }} >
Current Month with Real-time Updates
{ const statusMonth = wrapperElement.querySelector('upl-statuspage-statusmonth') as any; // Generate current month data const generateCurrentMonthData = (): IMonthlyUptime[] => { const now = new Date(); const year = now.getFullYear(); const month = now.getMonth(); const today = now.getDate(); const monthKey = `${year}-${String(month + 1).padStart(2, '0')}`; const daysInMonth = new Date(year, month + 1, 0).getDate(); const days: IUptimeDay[] = []; let totalIncidents = 0; let totalUptimeMinutes = 0; // Generate data only up to today for (let day = 1; day <= today; day++) { let uptime = 99.9 + Math.random() * 0.099; let incidents = 0; let status: IUptimeDay['status'] = 'operational'; // Today might have ongoing issues if (day === today) { if (Math.random() < 0.3) { uptime = 95 + Math.random() * 4; incidents = 1; status = 'degraded'; } } else if (Math.random() < 0.05) { uptime = 97 + Math.random() * 2.9; incidents = 1; status = 'degraded'; } const downtime = Math.floor((100 - uptime) * 14.4); totalIncidents += incidents; totalUptimeMinutes += uptime * 14.4; days.push({ date: `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`, uptime, incidents, totalDowntime: downtime, status }); } // Fill remaining days with placeholder for (let day = today + 1; day <= daysInMonth; day++) { days.push({ date: `${year}-${String(month + 1).padStart(2, '0')}-${String(day).padStart(2, '0')}`, uptime: 0, incidents: 0, totalDowntime: 0, status: 'operational' }); } const overallUptime = today > 0 ? totalUptimeMinutes / (today * 1440) * 100 : 100; return [{ month: monthKey, days, overallUptime, totalIncidents }]; }; // Initial setup statusMonth.serviceId = 'realtime-monitor'; statusMonth.serviceName = 'Real-time Monitoring Service'; statusMonth.monthlyData = generateCurrentMonthData(); statusMonth.showCurrentDay = true; // Update today's status periodically const updateInterval = setInterval(() => { const data = statusMonth.monthlyData; if (data && data.length > 0) { const currentMonth = data[0]; const today = new Date().getDate() - 1; if (currentMonth.days[today]) { // Simulate status changes const rand = Math.random(); if (rand < 0.1) { currentMonth.days[today].uptime = 95 + Math.random() * 4.9; currentMonth.days[today].incidents = (currentMonth.days[today].incidents || 0) + 1; currentMonth.days[today].status = 'degraded'; currentMonth.days[today].totalDowntime = Math.floor((100 - currentMonth.days[today].uptime) * 14.4); // Recalculate overall uptime let totalUptime = 0; let validDays = 0; currentMonth.days.forEach((day, index) => { if (index <= today && day.uptime > 0) { totalUptime += day.uptime; validDays++; } }); currentMonth.overallUptime = validDays > 0 ? totalUptime / validDays : 100; currentMonth.totalIncidents = currentMonth.days.reduce((sum, day) => sum + (day.incidents || 0), 0); statusMonth.requestUpdate(); logUpdate('Status degraded - Uptime: ' + currentMonth.days[today].uptime.toFixed(2) + '%'); } else if (rand < 0.05 && currentMonth.days[today].status !== 'operational') { // Recover from issues currentMonth.days[today].uptime = 99.9 + Math.random() * 0.099; currentMonth.days[today].status = 'operational'; currentMonth.days[today].totalDowntime = Math.floor((100 - currentMonth.days[today].uptime) * 14.4); statusMonth.requestUpdate(); logUpdate('Service recovered to operational status'); } } } }, 3000); // Create controls const controls = document.createElement('div'); controls.className = 'demo-controls'; controls.innerHTML = '' + '' + ''; wrapperElement.appendChild(controls); controls.querySelector('#simulateOutage')?.addEventListener('click', () => { const data = statusMonth.monthlyData; if (data && data.length > 0) { const today = new Date().getDate() - 1; data[0].days[today].uptime = 85 + Math.random() * 10; data[0].days[today].incidents = (data[0].days[today].incidents || 0) + 1; data[0].days[today].status = 'major_outage'; data[0].days[today].totalDowntime = Math.floor((100 - data[0].days[today].uptime) * 14.4); statusMonth.requestUpdate(); logUpdate('Major outage simulated'); } }); controls.querySelector('#simulateRecovery')?.addEventListener('click', () => { const data = statusMonth.monthlyData; if (data && data.length > 0) { const today = new Date().getDate() - 1; data[0].days[today].uptime = 99.95; data[0].days[today].status = 'operational'; data[0].days[today].totalDowntime = Math.floor((100 - data[0].days[today].uptime) * 14.4); statusMonth.requestUpdate(); logUpdate('Service recovered'); } }); controls.querySelector('#refreshData')?.addEventListener('click', () => { statusMonth.monthlyData = generateCurrentMonthData(); logUpdate('Data refreshed'); }); // Add update log const logDiv = document.createElement('div'); logDiv.className = 'demo-info'; logDiv.style.maxHeight = '100px'; logDiv.style.overflowY = 'auto'; logDiv.innerHTML = 'Update Log:
'; wrapperElement.appendChild(logDiv); const logUpdate = (message: string) => { const time = new Date().toLocaleTimeString(); logDiv.innerHTML += '[' + time + '] ' + message + '
'; logDiv.scrollTop = logDiv.scrollHeight; }; // Cleanup wrapperElement.addEventListener('remove', () => { clearInterval(updateInterval); }); }} >
Edge Cases and Special Scenarios
{ const statusMonth = wrapperElement.querySelector('upl-statuspage-statusmonth') as any; const scenarios = { noData: { name: 'No Data', data: [] }, singleMonth: { name: 'Single Month', data: [{ month: '2024-01', days: Array.from({ length: 31 }, (_, i) => ({ date: `2024-01-${String(i + 1).padStart(2, '0')}`, uptime: 99.9 + Math.random() * 0.099, incidents: 0, totalDowntime: 0, status: 'operational' as const })), overallUptime: 99.95, totalIncidents: 0 }] }, allDown: { name: 'Complete Outage Month', data: [{ month: '2024-01', days: Array.from({ length: 31 }, (_, i) => ({ date: `2024-01-${String(i + 1).padStart(2, '0')}`, uptime: 0, incidents: 5, totalDowntime: 1440, status: 'major_outage' as const })), overallUptime: 0, totalIncidents: 155 }] }, maintenanceMonth: { name: 'Maintenance Heavy Month', data: [{ month: '2024-01', days: Array.from({ length: 31 }, (_, i) => { // Maintenance every weekend const dayOfWeek = new Date(2024, 0, i + 1).getDay(); if (dayOfWeek === 0 || dayOfWeek === 6) { return { date: `2024-01-${String(i + 1).padStart(2, '0')}`, uptime: 95, incidents: 0, totalDowntime: 72, status: 'maintenance' as const }; } return { date: `2024-01-${String(i + 1).padStart(2, '0')}`, uptime: 99.95, incidents: 0, totalDowntime: 0.7, status: 'operational' as const }; }), overallUptime: 98.2, totalIncidents: 0 }] }, mixedYear: { name: 'Full Year Mixed', data: Array.from({ length: 12 }, (_, monthIndex) => { const year = 2023; const month = monthIndex; const daysInMonth = new Date(year, month + 1, 0).getDate(); // Different pattern each quarter let monthPattern = 'operational'; if (monthIndex < 3) monthPattern = 'degraded'; else if (monthIndex < 6) monthPattern = 'improving'; else if (monthIndex < 9) monthPattern = 'stable'; else monthPattern = 'volatile'; const days = Array.from({ length: daysInMonth }, (_, dayIndex) => { let uptime = 99.9; let status: IUptimeDay['status'] = 'operational'; let incidents = 0; if (monthPattern === 'degraded' && Math.random() < 0.3) { uptime = 85 + Math.random() * 10; status = 'degraded'; incidents = 1; } else if (monthPattern === 'volatile' && Math.random() < 0.2) { uptime = 90 + Math.random() * 9; status = Math.random() < 0.5 ? 'partial_outage' : 'degraded'; incidents = Math.floor(Math.random() * 3) + 1; } return { date: `${year}-${String(month + 1).padStart(2, '0')}-${String(dayIndex + 1).padStart(2, '0')}`, uptime, incidents, totalDowntime: Math.floor((100 - uptime) * 14.4), status }; }); const totalIncidents = days.reduce((sum, day) => sum + day.incidents, 0); const overallUptime = days.reduce((sum, day) => sum + day.uptime, 0) / days.length; return { month: `${year}-${String(month + 1).padStart(2, '0')}`, days, overallUptime, totalIncidents }; }) } }; // Initial setup let currentScenario = 'singleMonth'; statusMonth.serviceId = 'edge-case-service'; statusMonth.serviceName = 'Edge Case Service'; statusMonth.monthlyData = scenarios[currentScenario].data; // Create scenario controls 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; statusMonth.loading = true; setTimeout(() => { statusMonth.monthlyData = scenario.data; statusMonth.loading = false; }, 300); }; controls.appendChild(button); }); wrapperElement.appendChild(controls); }} >
Loading and Navigation Features
{ const statusMonth = wrapperElement.querySelector('upl-statuspage-statusmonth') as any; // Start with loading statusMonth.loading = true; statusMonth.serviceId = 'navigation-demo'; statusMonth.serviceName = 'Navigation Demo Service'; const controls = document.createElement('div'); controls.className = 'demo-controls'; controls.innerHTML = '' + '' + '' + ''; wrapperElement.appendChild(controls); controls.querySelector('#toggleLoading')?.addEventListener('click', () => { statusMonth.loading = !statusMonth.loading; }); controls.querySelector('#loadSuccess')?.addEventListener('click', () => { statusMonth.loading = true; setTimeout(() => { const months = 6; const data: IMonthlyUptime[] = []; const now = new Date(); for (let i = months - 1; i >= 0; i--) { const monthDate = new Date(now.getFullYear(), now.getMonth() - i, 1); const year = monthDate.getFullYear(); const month = monthDate.getMonth(); const daysInMonth = new Date(year, month + 1, 0).getDate(); data.push({ month: `${year}-${String(month + 1).padStart(2, '0')}`, days: Array.from({ length: daysInMonth }, (_, d) => ({ date: `${year}-${String(month + 1).padStart(2, '0')}-${String(d + 1).padStart(2, '0')}`, uptime: 99 + Math.random(), incidents: Math.random() < 0.05 ? 1 : 0, totalDowntime: Math.random() < 0.05 ? Math.floor(Math.random() * 60) : 0, status: Math.random() < 0.05 ? 'degraded' : 'operational' })), overallUptime: 99.5 + Math.random() * 0.4, totalIncidents: Math.floor(Math.random() * 5) }); } statusMonth.monthlyData = data; statusMonth.loading = false; }, 1000); }); controls.querySelector('#loadError')?.addEventListener('click', () => { statusMonth.loading = true; setTimeout(() => { statusMonth.loading = false; statusMonth.monthlyData = []; statusMonth.errorMessage = 'Failed to load monthly uptime data'; }, 1500); }); controls.querySelector('#toggleTooltip')?.addEventListener('click', () => { statusMonth.showTooltip = !statusMonth.showTooltip; const btn = controls.querySelector('#toggleTooltip'); if (btn) btn.textContent = 'Toggle Tooltip (' + (statusMonth.showTooltip ? 'ON' : 'OFF') + ')'; }); // Month navigation const navDiv = document.createElement('div'); navDiv.className = 'month-nav'; navDiv.innerHTML = '' + 'Loading...' + ''; wrapperElement.appendChild(navDiv); let currentMonthIndex = 0; const updateNavigation = () => { const data = statusMonth.monthlyData || []; if (data.length > 0 && currentMonthIndex < data.length) { const month = data[currentMonthIndex]; const currentMonthEl = navDiv.querySelector('#currentMonth'); if (currentMonthEl) currentMonthEl.textContent = month.month; const prevBtn = navDiv.querySelector('#prevMonth') as HTMLButtonElement; const nextBtn = navDiv.querySelector('#nextMonth') as HTMLButtonElement; if (prevBtn) prevBtn.disabled = currentMonthIndex === 0; if (nextBtn) nextBtn.disabled = currentMonthIndex === data.length - 1; } }; navDiv.querySelector('#prevMonth')?.addEventListener('click', () => { if (currentMonthIndex > 0) { currentMonthIndex--; updateNavigation(); // Highlight the month somehow statusMonth.highlightMonth = statusMonth.monthlyData[currentMonthIndex].month; } }); navDiv.querySelector('#nextMonth')?.addEventListener('click', () => { if (currentMonthIndex < (statusMonth.monthlyData?.length || 0) - 1) { currentMonthIndex++; updateNavigation(); statusMonth.highlightMonth = statusMonth.monthlyData[currentMonthIndex].month; } }); // Initial load setTimeout(() => { const data = Array.from({ length: 3 }, (_, i) => ({ month: `2024-${String(i + 1).padStart(2, '0')}`, days: Array.from({ length: 31 }, (_, d) => ({ date: `2024-${String(i + 1).padStart(2, '0')}-${String(d + 1).padStart(2, '0')}`, uptime: 99.5 + Math.random() * 0.5, incidents: 0, totalDowntime: 0, status: 'operational' as const })), overallUptime: 99.7 + Math.random() * 0.3, totalIncidents: Math.floor(Math.random() * 3) })); statusMonth.monthlyData = data; statusMonth.loading = false; statusMonth.showTooltip = true; updateNavigation(); }, 1000); }} >
`;