diff --git a/package.json b/package.json index aa5e660..7241126 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "dependencies": { "@design.estate/dees-domtools": "^2.1.1", "@design.estate/dees-element": "^2.0.42", - "@design.estate/dees-wcctools": "^1.0.92", + "@design.estate/dees-wcctools": "^1.0.95", "@fortawesome/fontawesome-svg-core": "^6.7.2", "@fortawesome/free-brands-svg-icons": "^6.7.2", "@fortawesome/free-regular-svg-icons": "^6.7.2", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 9a20650..f12f858 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -15,8 +15,8 @@ importers: specifier: ^2.0.42 version: 2.0.42 '@design.estate/dees-wcctools': - specifier: ^1.0.92 - version: 1.0.92 + specifier: ^1.0.95 + version: 1.0.95 '@fortawesome/fontawesome-svg-core': specifier: ^6.7.2 version: 6.7.2 @@ -305,8 +305,8 @@ packages: '@design.estate/dees-element@2.0.42': resolution: {integrity: sha512-1PzHP6q/PtSiu4P0nCxjSeHtRHn62zoSouMy8JFW2h29FT/CSDVaTUAUqYqnvwE/U98aLNivWTmerZitDF7kBQ==} - '@design.estate/dees-wcctools@1.0.92': - resolution: {integrity: sha512-E4Hnxvvzy2ivJzPHzWL2dmJtBtAD+stnEG7uQ0usQM6NVnarIGPI9PflGSspM75nnA/HKi+lpsqRgp1DtbPqTQ==} + '@design.estate/dees-wcctools@1.0.95': + resolution: {integrity: sha512-mXClal8YdvA74ILdAWe64ocydvwhVfQAOGaykrKGkR1qb8TA1Qn4H7QG9HUsg3jEVZApY0wYbhILuTvpvbkgGA==} '@esbuild/aix-ppc64@0.24.2': resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==} @@ -5176,7 +5176,7 @@ snapshots: - supports-color - vue - '@design.estate/dees-wcctools@1.0.92': + '@design.estate/dees-wcctools@1.0.95': dependencies: '@design.estate/dees-domtools': 2.3.2 '@design.estate/dees-element': 2.0.42 diff --git a/ts_web/elements/dees-chart-area.demo.ts b/ts_web/elements/dees-chart-area.demo.ts index 35a4c49..5b4176f 100644 --- a/ts_web/elements/dees-chart-area.demo.ts +++ b/ts_web/elements/dees-chart-area.demo.ts @@ -1,21 +1,9 @@ import { html, css } from '@design.estate/dees-element'; import type { DeesChartArea } from './dees-chart-area.js'; -import '@design.estate/dees-wcctools'; export const demoFunc = () => { - let chartElement: DeesChartArea; - let intervalId: 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()}`, - }; - - // Different datasets to showcase - const datasets = { + // Initial dataset values + const initialDatasets = { system: { label: 'System Usage (%)', series: [ @@ -43,186 +31,266 @@ export const demoFunc = () => { }, ], }, - network: { - label: 'Network Traffic (Mbps)', - series: [ - { - name: 'Download', - data: [ - { x: new Date(Date.now() - 300000).toISOString(), y: 120 }, - { x: new Date(Date.now() - 240000).toISOString(), y: 150 }, - { x: new Date(Date.now() - 180000).toISOString(), y: 180 }, - { x: new Date(Date.now() - 120000).toISOString(), y: 165 }, - { x: new Date(Date.now() - 60000).toISOString(), y: 190 }, - { x: new Date().toISOString(), y: 175 }, + }; + + const initialFormatters = { + system: (val: number) => `${val}%`, + }; + + return html` + { + // Get the chart element + const chartElement = elementArg.querySelector('dees-chart-area') as DeesChartArea; + let intervalId: 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()}`, + }; + + // Different datasets to showcase + const datasets = { + 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 }, + ], + }, ], }, - { - name: 'Upload', - 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: 35 }, - { x: new Date(Date.now() - 120000).toISOString(), y: 28 }, - { x: new Date(Date.now() - 60000).toISOString(), y: 32 }, - { x: new Date().toISOString(), y: 40 }, + network: { + label: 'Network Traffic (Mbps)', + series: [ + { + name: 'Download', + data: [ + { x: new Date(Date.now() - 300000).toISOString(), y: 120 }, + { x: new Date(Date.now() - 240000).toISOString(), y: 150 }, + { x: new Date(Date.now() - 180000).toISOString(), y: 180 }, + { x: new Date(Date.now() - 120000).toISOString(), y: 165 }, + { x: new Date(Date.now() - 60000).toISOString(), y: 190 }, + { x: new Date().toISOString(), y: 175 }, + ], + }, + { + name: 'Upload', + 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: 35 }, + { x: new Date(Date.now() - 120000).toISOString(), y: 28 }, + { x: new Date(Date.now() - 60000).toISOString(), y: 32 }, + { x: new Date().toISOString(), y: 40 }, + ], + }, ], }, - ], - }, - 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 }, + 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 }, + ], + }, ], }, - { - 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 random value within range - const getRandomValue = (min: number, max: number) => { - return Math.floor(Math.random() * (max - min + 1)) + min; - }; + // Generate random value within range + const getRandomValue = (min: number, max: number) => { + return Math.floor(Math.random() * (max - min + 1)) + min; + }; - // Get chart element - const getChartElement = () => { - return chartElement; - }; + // Add real-time data + const addRealtimeData = () => { + if (!chartElement) return; + + const newTimestamp = new Date().toISOString(); + + // Generate new data points based on dataset type + let newData: any[][] = []; + + if (currentDataset === 'system') { + newData = [ + [{ x: newTimestamp, y: getRandomValue(25, 45) }], // CPU + [{ x: newTimestamp, y: getRandomValue(45, 65) }], // Memory + ]; + } else if (currentDataset === 'network') { + newData = [ + [{ x: newTimestamp, y: getRandomValue(100, 250) }], // Download + [{ x: newTimestamp, y: getRandomValue(20, 50) }], // Upload + ]; + } + + // Keep only last 20 data points and update without animation + const currentSeries = chartElement.series.map((series, index) => ({ + ...series, + data: [...series.data.slice(-19), ...(newData[index] || [])], + })); + + // Update without animation for smoother real-time updates + chartElement.updateSeries(currentSeries, false); + }; - // Add real-time data - const addRealtimeData = () => { - const chart = getChartElement(); - if (!chart) return; - const newTimestamp = new Date().toISOString(); - - // Generate new data points based on dataset type - let newData: any[][] = []; - - if (currentDataset === 'system') { - newData = [ - [{ x: newTimestamp, y: getRandomValue(25, 45) }], // CPU - [{ x: newTimestamp, y: getRandomValue(45, 65) }], // Memory - ]; - } else if (currentDataset === 'network') { - newData = [ - [{ x: newTimestamp, y: getRandomValue(100, 250) }], // Download - [{ x: newTimestamp, y: getRandomValue(20, 50) }], // Upload - ]; - } - - // Keep only last 20 data points and update without animation - const currentSeries = chart.series.map((series, index) => ({ - ...series, - data: [...series.data.slice(-19), ...(newData[index] || [])], - })); - - // Update without animation for smoother real-time updates - chart.updateSeries(currentSeries, false); - }; - - // Switch dataset - const switchDataset = (name: string) => { - currentDataset = name; - - const updateChart = () => { - const chart = getChartElement(); - if (chart) { + // Switch dataset + const switchDataset = (name: string) => { + currentDataset = name; const dataset = datasets[name]; - chart.label = dataset.label; - chart.series = dataset.series; - chart.yAxisFormatter = formatters[name]; - } - }; - - updateChart(); - }; + chartElement.label = dataset.label; + chartElement.series = dataset.series; + chartElement.yAxisFormatter = formatters[name]; + }; - // Start/stop real-time updates - const startRealtime = () => { - if (!intervalId && (currentDataset === 'system' || currentDataset === 'network')) { - const chart = getChartElement(); - if (chart) { - // Disable animations for real-time mode - chart.updateOptions({ - chart: { - animations: { - enabled: false - } - } - }, false, false); - } - - intervalId = window.setInterval(() => addRealtimeData(), 2000); - } - }; - - const stopRealtime = () => { - if (intervalId) { - window.clearInterval(intervalId); - intervalId = null; - - const chart = getChartElement(); - if (chart) { - // Re-enable animations when stopping real-time - chart.updateOptions({ - chart: { - animations: { - enabled: true, - speed: 400, - animateGradually: { - enabled: true, - delay: 150 + // Start/stop real-time updates + const startRealtime = () => { + if (!intervalId && (currentDataset === 'system' || currentDataset === 'network')) { + // Disable animations for real-time mode + chartElement.updateOptions({ + chart: { + animations: { + enabled: false } } + }, false, false); + + intervalId = window.setInterval(() => addRealtimeData(), 2000); + } + }; + + const stopRealtime = () => { + if (intervalId) { + window.clearInterval(intervalId); + intervalId = null; + + // Re-enable animations when stopping real-time + chartElement.updateOptions({ + chart: { + animations: { + enabled: true, + speed: 400, + animateGradually: { + enabled: true, + delay: 150 + } + } + } + }, false, true); + } + }; + + // Randomize current data + const randomizeData = () => { + const currentSeries = chartElement.series.map(series => ({ + ...series, + data: series.data.map((point: any) => ({ + ...point, + y: typeof point.y === 'number' + ? Math.round(point.y * (0.8 + Math.random() * 0.4)) // +/- 20% variation + : point.y, + })), + })); + + // Update with animation for single updates + chartElement.updateSeries(currentSeries, true); + }; + + // 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 === 'Randomize Values') { + button.addEventListener('click', () => randomizeData()); + } else if (text === 'Add Point') { + button.addEventListener('click', () => addRealtimeData()); + } + }); + + // 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'; } - }, false, true); - } - } - }; - - // Randomize current data - const randomizeData = () => { - const chart = getChartElement(); - if (!chart) return; - - const currentSeries = chart.series.map(series => ({ - ...series, - data: series.data.map((point: any) => ({ - ...point, - y: typeof point.y === 'number' - ? Math.round(point.y * (0.8 + Math.random() * 0.4)) // +/- 20% variation - : point.y, - })), - })); - - // Update with animation for single updates - chart.updateSeries(currentSeries, true); - }; - - return html` - { - // Store the chart element reference - chartElement = element.querySelector('dees-chart-area') as DeesChartArea; + }); + }; + + // 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')); + } + }); }}>
- generateRandomLog()}>Add Single Log - startSimulation()}>Start Simulation - stopSimulation()}>Stop Simulation + Add Single Log + Start Simulation + Stop Simulation
Simulating realistic server logs with various levels and sources
-
+
`; -}; +}; \ No newline at end of file