import { html, css } from '@design.estate/dees-element'; import type { DeesChartArea } from './dees-chart-area.js'; import '@design.estate/dees-wcctools/demotools'; export const demoFunc = () => { // Initial dataset values const initialDatasets = { system: { label: 'System Usage (%)', series: [ { name: 'CPU', data: [ { x: new Date(Date.now() - 300000).toISOString(), y: 25 }, { x: new Date(Date.now() - 240000).toISOString(), y: 30 }, { x: new Date(Date.now() - 180000).toISOString(), y: 28 }, { x: new Date(Date.now() - 120000).toISOString(), y: 35 }, { x: new Date(Date.now() - 60000).toISOString(), y: 32 }, { x: new Date().toISOString(), y: 38 }, ], }, { name: 'Memory', data: [ { x: new Date(Date.now() - 300000).toISOString(), y: 45 }, { x: new Date(Date.now() - 240000).toISOString(), y: 48 }, { x: new Date(Date.now() - 180000).toISOString(), y: 46 }, { x: new Date(Date.now() - 120000).toISOString(), y: 52 }, { x: new Date(Date.now() - 60000).toISOString(), y: 50 }, { x: new Date().toISOString(), y: 55 }, ], }, ], }, }; const initialFormatters = { system: (val: number) => `${val}%`, }; return html` { // Get the chart elements const chartElement = elementArg.querySelector('#main-chart') as DeesChartArea; const connectionsChartElement = elementArg.querySelector('#connections-chart') as DeesChartArea; let intervalId: number; let connectionsIntervalId: number; let currentDataset = 'system'; // Y-axis formatters for different datasets const formatters = { system: (val: number) => `${val}%`, network: (val: number) => `${val} Mbps`, sales: (val: number) => `$${val.toLocaleString()}`, }; // Time window configuration (in milliseconds) const TIME_WINDOW = 2 * 60 * 1000; // 2 minutes const UPDATE_INTERVAL = 1000; // 1 second const DATA_POINT_INTERVAL = 5000; // Show data points every 5 seconds // Store previous values for smooth transitions let previousValues = { cpu: 30, memory: 50, download: 150, upload: 30, connections: 150 }; // Generate initial data points for time window const generateInitialData = (baseValue: number, variance: number, interval: number = DATA_POINT_INTERVAL) => { const data = []; const now = Date.now(); const pointCount = Math.floor(TIME_WINDOW / interval); for (let i = pointCount; i >= 0; i--) { const timestamp = new Date(now - (i * interval)).toISOString(); const value = baseValue + (Math.random() - 0.5) * variance; data.push({ x: timestamp, y: Math.round(value) }); } return data; }; // Different datasets to showcase const datasets = { system: { label: 'System Usage (%)', series: [ { name: 'CPU', data: generateInitialData(previousValues.cpu, 10), }, { name: 'Memory', data: generateInitialData(previousValues.memory, 8), }, ], }, network: { label: 'Network Traffic (Mbps)', series: [ { name: 'Download', data: generateInitialData(previousValues.download, 30), }, { name: 'Upload', data: generateInitialData(previousValues.upload, 10), }, ], }, sales: { label: 'Sales Analytics', series: [ { name: 'Revenue', data: [ { x: '2025-01-01', y: 45000 }, { x: '2025-01-02', y: 52000 }, { x: '2025-01-03', y: 48000 }, { x: '2025-01-04', y: 61000 }, { x: '2025-01-05', y: 58000 }, { x: '2025-01-06', y: 65000 }, ], }, { name: 'Profit', data: [ { x: '2025-01-01', y: 12000 }, { x: '2025-01-02', y: 14000 }, { x: '2025-01-03', y: 11000 }, { x: '2025-01-04', y: 18000 }, { x: '2025-01-05', y: 16000 }, { x: '2025-01-06', y: 20000 }, ], }, ], }, }; // Generate smooth value transitions const getNextValue = (current: number, min: number, max: number, maxChange: number = 5) => { // Add some randomness but keep it close to current value const change = (Math.random() - 0.5) * maxChange * 2; let newValue = current + change; // Apply some "pressure" to move towards center of range const center = (min + max) / 2; const pressure = (center - newValue) * 0.1; newValue += pressure; // Ensure within bounds newValue = Math.max(min, Math.min(max, newValue)); return Math.round(newValue); }; // Track time of last data point let lastDataPointTime = Date.now(); let connectionsLastUpdate = Date.now(); // Add real-time data const addRealtimeData = () => { if (!chartElement) return; const now = Date.now(); // Only add new data point every DATA_POINT_INTERVAL const shouldAddPoint = (now - lastDataPointTime) >= DATA_POINT_INTERVAL; if (shouldAddPoint) { lastDataPointTime = now; const newTimestamp = new Date(now).toISOString(); // Generate smooth transitions for new values if (currentDataset === 'system') { // Generate new values previousValues.cpu = getNextValue(previousValues.cpu, 20, 50, 3); previousValues.memory = getNextValue(previousValues.memory, 40, 70, 2); // Get current data and add new points const currentSeries = chartElement.chartSeries.map((series, index) => ({ name: series.name, data: [ ...(series.data as Array<{x: any; y: any}>), index === 0 ? { x: newTimestamp, y: previousValues.cpu } : { x: newTimestamp, y: previousValues.memory } ] })); chartElement.updateSeries(currentSeries, false); } else if (currentDataset === 'network') { // Generate new values previousValues.download = getNextValue(previousValues.download, 100, 200, 10); previousValues.upload = getNextValue(previousValues.upload, 20, 50, 5); // Get current data and add new points const currentSeries = chartElement.chartSeries.map((series, index) => ({ name: series.name, data: [ ...(series.data as Array<{x: any; y: any}>), index === 0 ? { x: newTimestamp, y: previousValues.download } : { x: newTimestamp, y: previousValues.upload } ] })); chartElement.updateSeries(currentSeries, false); } } }; // Update connections chart data const updateConnections = () => { if (!connectionsChartElement) return; const now = Date.now(); const newTimestamp = new Date(now).toISOString(); // Generate new connections value with discrete changes const change = Math.floor(Math.random() * 21) - 10; // -10 to +10 connections previousValues.connections = Math.max(50, Math.min(300, previousValues.connections + change)); // Get current data and add new point const currentSeries = connectionsChartElement.chartSeries; const newData = [{ name: currentSeries[0]?.name || 'Connections', data: [ ...(currentSeries[0]?.data as Array<{x: any; y: any}> || []), { x: newTimestamp, y: previousValues.connections } ] }]; connectionsChartElement.updateSeries(newData, false); }; // Switch dataset const switchDataset = (name: string) => { currentDataset = name; const dataset = datasets[name]; chartElement.label = dataset.label; chartElement.series = dataset.series; chartElement.yAxisFormatter = formatters[name]; // Set appropriate y-axis scaling if (name === 'system') { chartElement.yAxisScaling = 'percentage'; chartElement.yAxisMax = 100; } else if (name === 'network') { chartElement.yAxisScaling = 'dynamic'; } else { chartElement.yAxisScaling = 'dynamic'; } // Reset last data point time to get fresh data immediately lastDataPointTime = Date.now() - DATA_POINT_INTERVAL; }; // Start/stop real-time updates const startRealtime = () => { if (!intervalId && (currentDataset === 'system' || currentDataset === 'network')) { chartElement.realtimeMode = true; // Only add data every 5 seconds, chart auto-scrolls independently intervalId = window.setInterval(() => addRealtimeData(), DATA_POINT_INTERVAL); } // Start connections updates if (!connectionsIntervalId) { connectionsChartElement.realtimeMode = true; // Update connections every second connectionsIntervalId = window.setInterval(() => updateConnections(), UPDATE_INTERVAL); } }; const stopRealtime = () => { if (intervalId) { window.clearInterval(intervalId); intervalId = null; chartElement.realtimeMode = false; } // Stop connections updates if (connectionsIntervalId) { window.clearInterval(connectionsIntervalId); connectionsIntervalId = null; connectionsChartElement.realtimeMode = false; } }; // Randomize current data (spike/drop simulation) const randomizeData = () => { if (currentDataset === 'system') { // Simulate CPU/Memory spike previousValues.cpu = Math.random() > 0.5 ? 85 : 25; previousValues.memory = Math.random() > 0.5 ? 80 : 45; } else if (currentDataset === 'network') { // Simulate network traffic spike previousValues.download = Math.random() > 0.5 ? 250 : 100; previousValues.upload = Math.random() > 0.5 ? 80 : 20; } // Also spike connections previousValues.connections = Math.random() > 0.5 ? 280 : 80; // Force immediate update by resetting timers lastDataPointTime = 0; connectionsLastUpdate = 0; }; // Wire up button click handlers const buttons = elementArg.querySelectorAll('dees-button'); buttons.forEach(button => { const text = button.textContent?.trim(); if (text === 'System Usage') { button.addEventListener('click', () => switchDataset('system')); } else if (text === 'Network Traffic') { button.addEventListener('click', () => switchDataset('network')); } else if (text === 'Sales Data') { button.addEventListener('click', () => switchDataset('sales')); } else if (text === 'Start Live') { button.addEventListener('click', () => startRealtime()); } else if (text === 'Stop Live') { button.addEventListener('click', () => stopRealtime()); } else if (text === 'Spike Values') { button.addEventListener('click', () => randomizeData()); } }); // Update button states based on current dataset const updateButtonStates = () => { const buttons = elementArg.querySelectorAll('dees-button'); buttons.forEach(button => { const text = button.textContent?.trim(); if (text === 'System Usage') { button.type = currentDataset === 'system' ? 'highlighted' : 'normal'; } else if (text === 'Network Traffic') { button.type = currentDataset === 'network' ? 'highlighted' : 'normal'; } else if (text === 'Sales Data') { button.type = currentDataset === 'sales' ? 'highlighted' : 'normal'; } }); }; // Configure main chart with rolling window chartElement.rollingWindow = TIME_WINDOW; chartElement.realtimeMode = false; // Will be enabled when starting live updates chartElement.yAxisScaling = 'percentage'; // Initial system dataset uses percentage chartElement.yAxisMax = 100; chartElement.autoScrollInterval = 1000; // Auto-scroll every second // Set initial time window setTimeout(() => { chartElement.updateTimeWindow(); }, 100); // Update button states when dataset changes const originalSwitchDataset = switchDataset; const switchDatasetWithButtonUpdate = (name: string) => { originalSwitchDataset(name); updateButtonStates(); }; // Replace switchDataset with the one that updates buttons buttons.forEach(button => { const text = button.textContent?.trim(); if (text === 'System Usage') { button.removeEventListener('click', () => switchDataset('system')); button.addEventListener('click', () => switchDatasetWithButtonUpdate('system')); } else if (text === 'Network Traffic') { button.removeEventListener('click', () => switchDataset('network')); button.addEventListener('click', () => switchDatasetWithButtonUpdate('network')); } else if (text === 'Sales Data') { button.removeEventListener('click', () => switchDataset('sales')); button.addEventListener('click', () => switchDatasetWithButtonUpdate('sales')); } }); // Initialize connections chart with data if (connectionsChartElement) { const initialConnectionsData = generateInitialData(previousValues.connections, 30, UPDATE_INTERVAL); connectionsChartElement.series = [{ name: 'Connections', data: initialConnectionsData }]; // Configure connections chart connectionsChartElement.rollingWindow = TIME_WINDOW; connectionsChartElement.realtimeMode = false; // Will be enabled when starting live updates connectionsChartElement.yAxisScaling = 'fixed'; connectionsChartElement.yAxisMax = 350; connectionsChartElement.autoScrollInterval = 1000; // Auto-scroll every second // Set initial time window setTimeout(() => { connectionsChartElement.updateTimeWindow(); }, 100); } }}>
System Usage Network Traffic Sales Data Start Live Stop Live Spike Values
}]} .yAxisFormatter=${(val: number) => `${val}`} >
Real-time monitoring with 2-minute rolling window • Updates every second with smooth value transitions • Click 'Spike Values' to simulate load spikes
`; };