fix(dees-catalog): update @design.estate/dees-wcctools dependency to version 1.0.95 for compatibility
feat(dees-chart-area): refactor demo function for improved dataset handling and real-time updates feat(dees-chart-log): enhance demo function with simulation controls for server log generation
This commit is contained in:
@ -17,7 +17,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@design.estate/dees-domtools": "^2.1.1",
|
"@design.estate/dees-domtools": "^2.1.1",
|
||||||
"@design.estate/dees-element": "^2.0.42",
|
"@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/fontawesome-svg-core": "^6.7.2",
|
||||||
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
"@fortawesome/free-brands-svg-icons": "^6.7.2",
|
||||||
"@fortawesome/free-regular-svg-icons": "^6.7.2",
|
"@fortawesome/free-regular-svg-icons": "^6.7.2",
|
||||||
|
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@ -15,8 +15,8 @@ importers:
|
|||||||
specifier: ^2.0.42
|
specifier: ^2.0.42
|
||||||
version: 2.0.42
|
version: 2.0.42
|
||||||
'@design.estate/dees-wcctools':
|
'@design.estate/dees-wcctools':
|
||||||
specifier: ^1.0.92
|
specifier: ^1.0.95
|
||||||
version: 1.0.92
|
version: 1.0.95
|
||||||
'@fortawesome/fontawesome-svg-core':
|
'@fortawesome/fontawesome-svg-core':
|
||||||
specifier: ^6.7.2
|
specifier: ^6.7.2
|
||||||
version: 6.7.2
|
version: 6.7.2
|
||||||
@ -305,8 +305,8 @@ packages:
|
|||||||
'@design.estate/dees-element@2.0.42':
|
'@design.estate/dees-element@2.0.42':
|
||||||
resolution: {integrity: sha512-1PzHP6q/PtSiu4P0nCxjSeHtRHn62zoSouMy8JFW2h29FT/CSDVaTUAUqYqnvwE/U98aLNivWTmerZitDF7kBQ==}
|
resolution: {integrity: sha512-1PzHP6q/PtSiu4P0nCxjSeHtRHn62zoSouMy8JFW2h29FT/CSDVaTUAUqYqnvwE/U98aLNivWTmerZitDF7kBQ==}
|
||||||
|
|
||||||
'@design.estate/dees-wcctools@1.0.92':
|
'@design.estate/dees-wcctools@1.0.95':
|
||||||
resolution: {integrity: sha512-E4Hnxvvzy2ivJzPHzWL2dmJtBtAD+stnEG7uQ0usQM6NVnarIGPI9PflGSspM75nnA/HKi+lpsqRgp1DtbPqTQ==}
|
resolution: {integrity: sha512-mXClal8YdvA74ILdAWe64ocydvwhVfQAOGaykrKGkR1qb8TA1Qn4H7QG9HUsg3jEVZApY0wYbhILuTvpvbkgGA==}
|
||||||
|
|
||||||
'@esbuild/aix-ppc64@0.24.2':
|
'@esbuild/aix-ppc64@0.24.2':
|
||||||
resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==}
|
resolution: {integrity: sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==}
|
||||||
@ -5176,7 +5176,7 @@ snapshots:
|
|||||||
- supports-color
|
- supports-color
|
||||||
- vue
|
- vue
|
||||||
|
|
||||||
'@design.estate/dees-wcctools@1.0.92':
|
'@design.estate/dees-wcctools@1.0.95':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@design.estate/dees-domtools': 2.3.2
|
'@design.estate/dees-domtools': 2.3.2
|
||||||
'@design.estate/dees-element': 2.0.42
|
'@design.estate/dees-element': 2.0.42
|
||||||
|
@ -1,21 +1,9 @@
|
|||||||
import { html, css } from '@design.estate/dees-element';
|
import { html, css } from '@design.estate/dees-element';
|
||||||
import type { DeesChartArea } from './dees-chart-area.js';
|
import type { DeesChartArea } from './dees-chart-area.js';
|
||||||
import '@design.estate/dees-wcctools';
|
|
||||||
|
|
||||||
export const demoFunc = () => {
|
export const demoFunc = () => {
|
||||||
let chartElement: DeesChartArea;
|
// Initial dataset values
|
||||||
let intervalId: number;
|
const initialDatasets = {
|
||||||
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: {
|
system: {
|
||||||
label: 'System Usage (%)',
|
label: 'System Usage (%)',
|
||||||
series: [
|
series: [
|
||||||
@ -43,186 +31,266 @@ export const demoFunc = () => {
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
network: {
|
};
|
||||||
label: 'Network Traffic (Mbps)',
|
|
||||||
series: [
|
const initialFormatters = {
|
||||||
{
|
system: (val: number) => `${val}%`,
|
||||||
name: 'Download',
|
};
|
||||||
data: [
|
|
||||||
{ x: new Date(Date.now() - 300000).toISOString(), y: 120 },
|
return html`
|
||||||
{ x: new Date(Date.now() - 240000).toISOString(), y: 150 },
|
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
|
||||||
{ x: new Date(Date.now() - 180000).toISOString(), y: 180 },
|
// Get the chart element
|
||||||
{ x: new Date(Date.now() - 120000).toISOString(), y: 165 },
|
const chartElement = elementArg.querySelector('dees-chart-area') as DeesChartArea;
|
||||||
{ x: new Date(Date.now() - 60000).toISOString(), y: 190 },
|
let intervalId: number;
|
||||||
{ x: new Date().toISOString(), y: 175 },
|
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 },
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
network: {
|
||||||
name: 'Upload',
|
label: 'Network Traffic (Mbps)',
|
||||||
data: [
|
series: [
|
||||||
{ x: new Date(Date.now() - 300000).toISOString(), y: 25 },
|
{
|
||||||
{ x: new Date(Date.now() - 240000).toISOString(), y: 30 },
|
name: 'Download',
|
||||||
{ x: new Date(Date.now() - 180000).toISOString(), y: 35 },
|
data: [
|
||||||
{ x: new Date(Date.now() - 120000).toISOString(), y: 28 },
|
{ x: new Date(Date.now() - 300000).toISOString(), y: 120 },
|
||||||
{ x: new Date(Date.now() - 60000).toISOString(), y: 32 },
|
{ x: new Date(Date.now() - 240000).toISOString(), y: 150 },
|
||||||
{ x: new Date().toISOString(), y: 40 },
|
{ 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',
|
||||||
sales: {
|
series: [
|
||||||
label: 'Sales Analytics',
|
{
|
||||||
series: [
|
name: 'Revenue',
|
||||||
{
|
data: [
|
||||||
name: 'Revenue',
|
{ x: '2025-01-01', y: 45000 },
|
||||||
data: [
|
{ x: '2025-01-02', y: 52000 },
|
||||||
{ x: '2025-01-01', y: 45000 },
|
{ x: '2025-01-03', y: 48000 },
|
||||||
{ x: '2025-01-02', y: 52000 },
|
{ x: '2025-01-04', y: 61000 },
|
||||||
{ x: '2025-01-03', y: 48000 },
|
{ x: '2025-01-05', y: 58000 },
|
||||||
{ x: '2025-01-04', y: 61000 },
|
{ x: '2025-01-06', y: 65000 },
|
||||||
{ 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
|
// Generate random value within range
|
||||||
const getRandomValue = (min: number, max: number) => {
|
const getRandomValue = (min: number, max: number) => {
|
||||||
return Math.floor(Math.random() * (max - min + 1)) + min;
|
return Math.floor(Math.random() * (max - min + 1)) + min;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Get chart element
|
// Add real-time data
|
||||||
const getChartElement = () => {
|
const addRealtimeData = () => {
|
||||||
return chartElement;
|
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
|
// Switch dataset
|
||||||
const addRealtimeData = () => {
|
const switchDataset = (name: string) => {
|
||||||
const chart = getChartElement();
|
currentDataset = name;
|
||||||
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) {
|
|
||||||
const dataset = datasets[name];
|
const dataset = datasets[name];
|
||||||
chart.label = dataset.label;
|
chartElement.label = dataset.label;
|
||||||
chart.series = dataset.series;
|
chartElement.series = dataset.series;
|
||||||
chart.yAxisFormatter = formatters[name];
|
chartElement.yAxisFormatter = formatters[name];
|
||||||
}
|
};
|
||||||
};
|
|
||||||
|
|
||||||
updateChart();
|
|
||||||
};
|
|
||||||
|
|
||||||
// Start/stop real-time updates
|
// Start/stop real-time updates
|
||||||
const startRealtime = () => {
|
const startRealtime = () => {
|
||||||
if (!intervalId && (currentDataset === 'system' || currentDataset === 'network')) {
|
if (!intervalId && (currentDataset === 'system' || currentDataset === 'network')) {
|
||||||
const chart = getChartElement();
|
// Disable animations for real-time mode
|
||||||
if (chart) {
|
chartElement.updateOptions({
|
||||||
// Disable animations for real-time mode
|
chart: {
|
||||||
chart.updateOptions({
|
animations: {
|
||||||
chart: {
|
enabled: false
|
||||||
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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}, 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);
|
});
|
||||||
}
|
};
|
||||||
}
|
|
||||||
};
|
// Update button states when dataset changes
|
||||||
|
const originalSwitchDataset = switchDataset;
|
||||||
// Randomize current data
|
const switchDatasetWithButtonUpdate = (name: string) => {
|
||||||
const randomizeData = () => {
|
originalSwitchDataset(name);
|
||||||
const chart = getChartElement();
|
updateButtonStates();
|
||||||
if (!chart) return;
|
};
|
||||||
|
|
||||||
const currentSeries = chart.series.map(series => ({
|
// Replace switchDataset with the one that updates buttons
|
||||||
...series,
|
buttons.forEach(button => {
|
||||||
data: series.data.map((point: any) => ({
|
const text = button.textContent?.trim();
|
||||||
...point,
|
if (text === 'System Usage') {
|
||||||
y: typeof point.y === 'number'
|
button.removeEventListener('click', () => switchDataset('system'));
|
||||||
? Math.round(point.y * (0.8 + Math.random() * 0.4)) // +/- 20% variation
|
button.addEventListener('click', () => switchDatasetWithButtonUpdate('system'));
|
||||||
: point.y,
|
} else if (text === 'Network Traffic') {
|
||||||
})),
|
button.removeEventListener('click', () => switchDataset('network'));
|
||||||
}));
|
button.addEventListener('click', () => switchDatasetWithButtonUpdate('network'));
|
||||||
|
} else if (text === 'Sales Data') {
|
||||||
// Update with animation for single updates
|
button.removeEventListener('click', () => switchDataset('sales'));
|
||||||
chart.updateSeries(currentSeries, true);
|
button.addEventListener('click', () => switchDatasetWithButtonUpdate('sales'));
|
||||||
};
|
}
|
||||||
|
});
|
||||||
return html`
|
|
||||||
<dees-demowrapper .runAfterRender=${async (element: HTMLElement) => {
|
|
||||||
// Store the chart element reference
|
|
||||||
chartElement = element.querySelector('dees-chart-area') as DeesChartArea;
|
|
||||||
}}>
|
}}>
|
||||||
<style>
|
<style>
|
||||||
${css`
|
${css`
|
||||||
@ -262,36 +330,27 @@ export const demoFunc = () => {
|
|||||||
<div class="demoBox">
|
<div class="demoBox">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<dees-button-group label="Dataset:">
|
<dees-button-group label="Dataset:">
|
||||||
<dees-button
|
<dees-button type="highlighted">System Usage</dees-button>
|
||||||
@clicked=${() => switchDataset('system')}
|
<dees-button>Network Traffic</dees-button>
|
||||||
type=${currentDataset === 'system' ? 'highlighted' : 'normal'}
|
<dees-button>Sales Data</dees-button>
|
||||||
>System Usage</dees-button>
|
|
||||||
<dees-button
|
|
||||||
@clicked=${() => switchDataset('network')}
|
|
||||||
type=${currentDataset === 'network' ? 'highlighted' : 'normal'}
|
|
||||||
>Network Traffic</dees-button>
|
|
||||||
<dees-button
|
|
||||||
@clicked=${() => switchDataset('sales')}
|
|
||||||
type=${currentDataset === 'sales' ? 'highlighted' : 'normal'}
|
|
||||||
>Sales Data</dees-button>
|
|
||||||
</dees-button-group>
|
</dees-button-group>
|
||||||
|
|
||||||
<dees-button-group label="Real-time:">
|
<dees-button-group label="Real-time:">
|
||||||
<dees-button @clicked=${() => startRealtime()}>Start Live</dees-button>
|
<dees-button>Start Live</dees-button>
|
||||||
<dees-button @clicked=${() => stopRealtime()}>Stop Live</dees-button>
|
<dees-button>Stop Live</dees-button>
|
||||||
</dees-button-group>
|
</dees-button-group>
|
||||||
|
|
||||||
<dees-button-group label="Actions:">
|
<dees-button-group label="Actions:">
|
||||||
<dees-button @clicked=${() => randomizeData()}>Randomize Values</dees-button>
|
<dees-button>Randomize Values</dees-button>
|
||||||
<dees-button @clicked=${() => addRealtimeData()}>Add Point</dees-button>
|
<dees-button>Add Point</dees-button>
|
||||||
</dees-button-group>
|
</dees-button-group>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="chart-container">
|
<div class="chart-container">
|
||||||
<dees-chart-area
|
<dees-chart-area
|
||||||
.label=${datasets[currentDataset].label}
|
.label=${initialDatasets.system.label}
|
||||||
.series=${datasets[currentDataset].series}
|
.series=${initialDatasets.system.series}
|
||||||
.yAxisFormatter=${formatters[currentDataset]}
|
.yAxisFormatter=${initialFormatters.system}
|
||||||
></dees-chart-area>
|
></dees-chart-area>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -300,7 +359,7 @@ export const demoFunc = () => {
|
|||||||
Chart updates every 2 seconds when live mode is active •
|
Chart updates every 2 seconds when live mode is active •
|
||||||
Try switching datasets and randomizing values
|
Try switching datasets and randomizing values
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</dees-demowrapper>
|
</dees-demowrapper>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
@ -1,129 +1,134 @@
|
|||||||
import { html } from '@design.estate/dees-element';
|
import { html } from '@design.estate/dees-element';
|
||||||
import type { DeesChartLog } from './dees-chart-log.js';
|
import type { DeesChartLog } from './dees-chart-log.js';
|
||||||
import '@design.estate/dees-wcctools';
|
|
||||||
|
|
||||||
export const demoFunc = () => {
|
export const demoFunc = () => {
|
||||||
let intervalId: number;
|
|
||||||
let logElement: DeesChartLog;
|
|
||||||
|
|
||||||
const serverSources = ['Server', 'Database', 'API', 'Auth', 'Cache', 'Queue', 'WebSocket', 'Scheduler'];
|
|
||||||
|
|
||||||
const logTemplates = {
|
|
||||||
debug: [
|
|
||||||
'Loading module: {{module}}',
|
|
||||||
'Cache hit for key: {{key}}',
|
|
||||||
'SQL query executed in {{time}}ms',
|
|
||||||
'Request headers: {{headers}}',
|
|
||||||
'Environment variable loaded: {{var}}',
|
|
||||||
],
|
|
||||||
info: [
|
|
||||||
'Request received: {{method}} {{path}}',
|
|
||||||
'User {{userId}} authenticated successfully',
|
|
||||||
'Processing job {{jobId}} from queue',
|
|
||||||
'Scheduled task "{{task}}" started',
|
|
||||||
'WebSocket connection established from {{ip}}',
|
|
||||||
],
|
|
||||||
warn: [
|
|
||||||
'Slow query detected: {{query}} ({{time}}ms)',
|
|
||||||
'Memory usage at {{percent}}%',
|
|
||||||
'Rate limit approaching for IP {{ip}}',
|
|
||||||
'Deprecated API endpoint called: {{endpoint}}',
|
|
||||||
'Certificate expires in {{days}} days',
|
|
||||||
],
|
|
||||||
error: [
|
|
||||||
'Database connection lost: {{error}}',
|
|
||||||
'Failed to process request: {{error}}',
|
|
||||||
'Authentication failed for user {{user}}',
|
|
||||||
'File not found: {{path}}',
|
|
||||||
'Service unavailable: {{service}}',
|
|
||||||
],
|
|
||||||
success: [
|
|
||||||
'Server started successfully on port {{port}}',
|
|
||||||
'Database migration completed',
|
|
||||||
'Backup completed: {{size}} MB',
|
|
||||||
'SSL certificate renewed',
|
|
||||||
'Health check passed: all systems operational',
|
|
||||||
],
|
|
||||||
};
|
|
||||||
|
|
||||||
const generateRandomLog = () => {
|
|
||||||
if (!logElement) {
|
|
||||||
console.warn('Log element not ready yet');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const levels: Array<'debug' | 'info' | 'warn' | 'error' | 'success'> = ['debug', 'info', 'warn', 'error', 'success'];
|
|
||||||
const weights = [0.2, 0.5, 0.15, 0.1, 0.05]; // Weighted probability
|
|
||||||
|
|
||||||
const random = Math.random();
|
|
||||||
let cumulative = 0;
|
|
||||||
let level: typeof levels[0] = 'info';
|
|
||||||
|
|
||||||
for (let i = 0; i < weights.length; i++) {
|
|
||||||
cumulative += weights[i];
|
|
||||||
if (random < cumulative) {
|
|
||||||
level = levels[i];
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const source = serverSources[Math.floor(Math.random() * serverSources.length)];
|
|
||||||
const templates = logTemplates[level];
|
|
||||||
const template = templates[Math.floor(Math.random() * templates.length)];
|
|
||||||
|
|
||||||
// Replace placeholders with random values
|
|
||||||
const message = template
|
|
||||||
.replace('{{module}}', ['express', 'mongoose', 'redis', 'socket.io'][Math.floor(Math.random() * 4)])
|
|
||||||
.replace('{{key}}', 'user:' + Math.floor(Math.random() * 1000))
|
|
||||||
.replace('{{time}}', String(Math.floor(Math.random() * 500) + 50))
|
|
||||||
.replace('{{headers}}', 'Content-Type: application/json, Authorization: Bearer ...')
|
|
||||||
.replace('{{var}}', ['NODE_ENV', 'DATABASE_URL', 'API_KEY', 'PORT'][Math.floor(Math.random() * 4)])
|
|
||||||
.replace('{{method}}', ['GET', 'POST', 'PUT', 'DELETE'][Math.floor(Math.random() * 4)])
|
|
||||||
.replace('{{path}}', ['/api/users', '/api/auth/login', '/api/products', '/health'][Math.floor(Math.random() * 4)])
|
|
||||||
.replace('{{userId}}', String(Math.floor(Math.random() * 10000)))
|
|
||||||
.replace('{{jobId}}', 'job_' + Math.random().toString(36).substring(2, 11))
|
|
||||||
.replace('{{task}}', ['cleanup', 'backup', 'report-generation', 'cache-refresh'][Math.floor(Math.random() * 4)])
|
|
||||||
.replace('{{ip}}', `192.168.1.${Math.floor(Math.random() * 255)}`)
|
|
||||||
.replace('{{query}}', 'SELECT * FROM users WHERE ...')
|
|
||||||
.replace('{{percent}}', String(Math.floor(Math.random() * 30) + 70))
|
|
||||||
.replace('{{endpoint}}', '/api/v1/legacy')
|
|
||||||
.replace('{{days}}', String(Math.floor(Math.random() * 30) + 1))
|
|
||||||
.replace('{{error}}', ['ECONNREFUSED', 'ETIMEDOUT', 'ENOTFOUND'][Math.floor(Math.random() * 3)])
|
|
||||||
.replace('{{user}}', 'user_' + Math.floor(Math.random() * 1000))
|
|
||||||
.replace('{{service}}', ['Redis', 'MongoDB', 'ElasticSearch'][Math.floor(Math.random() * 3)])
|
|
||||||
.replace('{{port}}', String(3000 + Math.floor(Math.random() * 10)))
|
|
||||||
.replace('{{size}}', String(Math.floor(Math.random() * 500) + 100));
|
|
||||||
|
|
||||||
logElement.addLog(level, message, source);
|
|
||||||
};
|
|
||||||
|
|
||||||
const startSimulation = () => {
|
|
||||||
if (!intervalId) {
|
|
||||||
// Generate logs at random intervals between 500ms and 2500ms
|
|
||||||
const scheduleNext = () => {
|
|
||||||
generateRandomLog();
|
|
||||||
const nextDelay = Math.random() * 2000 + 500;
|
|
||||||
intervalId = window.setTimeout(() => {
|
|
||||||
if (intervalId) {
|
|
||||||
scheduleNext();
|
|
||||||
}
|
|
||||||
}, nextDelay);
|
|
||||||
};
|
|
||||||
scheduleNext();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const stopSimulation = () => {
|
|
||||||
if (intervalId) {
|
|
||||||
window.clearTimeout(intervalId);
|
|
||||||
intervalId = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
return html`
|
return html`
|
||||||
<dees-demowrapper .runAfterRender=${async (element: HTMLElement) => {
|
<dees-demowrapper .runAfterRender=${async (elementArg: HTMLElement) => {
|
||||||
// Store the log element reference
|
// Get the log element
|
||||||
logElement = element.querySelector('dees-chart-log') as DeesChartLog;
|
const logElement = elementArg.querySelector('dees-chart-log') as DeesChartLog;
|
||||||
|
let intervalId: number;
|
||||||
|
|
||||||
|
const serverSources = ['Server', 'Database', 'API', 'Auth', 'Cache', 'Queue', 'WebSocket', 'Scheduler'];
|
||||||
|
|
||||||
|
const logTemplates = {
|
||||||
|
debug: [
|
||||||
|
'Loading module: {{module}}',
|
||||||
|
'Cache hit for key: {{key}}',
|
||||||
|
'SQL query executed in {{time}}ms',
|
||||||
|
'Request headers: {{headers}}',
|
||||||
|
'Environment variable loaded: {{var}}',
|
||||||
|
],
|
||||||
|
info: [
|
||||||
|
'Request received: {{method}} {{path}}',
|
||||||
|
'User {{userId}} authenticated successfully',
|
||||||
|
'Processing job {{jobId}} from queue',
|
||||||
|
'Scheduled task "{{task}}" started',
|
||||||
|
'WebSocket connection established from {{ip}}',
|
||||||
|
],
|
||||||
|
warn: [
|
||||||
|
'Slow query detected: {{query}} ({{time}}ms)',
|
||||||
|
'Memory usage at {{percent}}%',
|
||||||
|
'Rate limit approaching for IP {{ip}}',
|
||||||
|
'Deprecated API endpoint called: {{endpoint}}',
|
||||||
|
'Certificate expires in {{days}} days',
|
||||||
|
],
|
||||||
|
error: [
|
||||||
|
'Database connection lost: {{error}}',
|
||||||
|
'Failed to process request: {{error}}',
|
||||||
|
'Authentication failed for user {{user}}',
|
||||||
|
'File not found: {{path}}',
|
||||||
|
'Service unavailable: {{service}}',
|
||||||
|
],
|
||||||
|
success: [
|
||||||
|
'Server started successfully on port {{port}}',
|
||||||
|
'Database migration completed',
|
||||||
|
'Backup completed: {{size}} MB',
|
||||||
|
'SSL certificate renewed',
|
||||||
|
'Health check passed: all systems operational',
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const generateRandomLog = () => {
|
||||||
|
const levels: Array<'debug' | 'info' | 'warn' | 'error' | 'success'> = ['debug', 'info', 'warn', 'error', 'success'];
|
||||||
|
const weights = [0.2, 0.5, 0.15, 0.1, 0.05]; // Weighted probability
|
||||||
|
|
||||||
|
const random = Math.random();
|
||||||
|
let cumulative = 0;
|
||||||
|
let level: typeof levels[0] = 'info';
|
||||||
|
|
||||||
|
for (let i = 0; i < weights.length; i++) {
|
||||||
|
cumulative += weights[i];
|
||||||
|
if (random < cumulative) {
|
||||||
|
level = levels[i];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const source = serverSources[Math.floor(Math.random() * serverSources.length)];
|
||||||
|
const templates = logTemplates[level];
|
||||||
|
const template = templates[Math.floor(Math.random() * templates.length)];
|
||||||
|
|
||||||
|
// Replace placeholders with random values
|
||||||
|
const message = template
|
||||||
|
.replace('{{module}}', ['express', 'mongoose', 'redis', 'socket.io'][Math.floor(Math.random() * 4)])
|
||||||
|
.replace('{{key}}', 'user:' + Math.floor(Math.random() * 1000))
|
||||||
|
.replace('{{time}}', String(Math.floor(Math.random() * 500) + 50))
|
||||||
|
.replace('{{headers}}', 'Content-Type: application/json, Authorization: Bearer ...')
|
||||||
|
.replace('{{var}}', ['NODE_ENV', 'DATABASE_URL', 'API_KEY', 'PORT'][Math.floor(Math.random() * 4)])
|
||||||
|
.replace('{{method}}', ['GET', 'POST', 'PUT', 'DELETE'][Math.floor(Math.random() * 4)])
|
||||||
|
.replace('{{path}}', ['/api/users', '/api/auth/login', '/api/products', '/health'][Math.floor(Math.random() * 4)])
|
||||||
|
.replace('{{userId}}', String(Math.floor(Math.random() * 10000)))
|
||||||
|
.replace('{{jobId}}', 'job_' + Math.random().toString(36).substring(2, 11))
|
||||||
|
.replace('{{task}}', ['cleanup', 'backup', 'report-generation', 'cache-refresh'][Math.floor(Math.random() * 4)])
|
||||||
|
.replace('{{ip}}', `192.168.1.${Math.floor(Math.random() * 255)}`)
|
||||||
|
.replace('{{query}}', 'SELECT * FROM users WHERE ...')
|
||||||
|
.replace('{{percent}}', String(Math.floor(Math.random() * 30) + 70))
|
||||||
|
.replace('{{endpoint}}', '/api/v1/legacy')
|
||||||
|
.replace('{{days}}', String(Math.floor(Math.random() * 30) + 1))
|
||||||
|
.replace('{{error}}', ['ECONNREFUSED', 'ETIMEDOUT', 'ENOTFOUND'][Math.floor(Math.random() * 3)])
|
||||||
|
.replace('{{user}}', 'user_' + Math.floor(Math.random() * 1000))
|
||||||
|
.replace('{{service}}', ['Redis', 'MongoDB', 'ElasticSearch'][Math.floor(Math.random() * 3)])
|
||||||
|
.replace('{{port}}', String(3000 + Math.floor(Math.random() * 10)))
|
||||||
|
.replace('{{size}}', String(Math.floor(Math.random() * 500) + 100));
|
||||||
|
|
||||||
|
logElement.addLog(level, message, source);
|
||||||
|
};
|
||||||
|
|
||||||
|
const startSimulation = () => {
|
||||||
|
if (!intervalId) {
|
||||||
|
// Generate logs at random intervals between 500ms and 2500ms
|
||||||
|
const scheduleNext = () => {
|
||||||
|
generateRandomLog();
|
||||||
|
const nextDelay = Math.random() * 2000 + 500;
|
||||||
|
intervalId = window.setTimeout(() => {
|
||||||
|
if (intervalId) {
|
||||||
|
scheduleNext();
|
||||||
|
}
|
||||||
|
}, nextDelay);
|
||||||
|
};
|
||||||
|
scheduleNext();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const stopSimulation = () => {
|
||||||
|
if (intervalId) {
|
||||||
|
window.clearTimeout(intervalId);
|
||||||
|
intervalId = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Wire up button click handlers
|
||||||
|
const buttons = elementArg.querySelectorAll('dees-button');
|
||||||
|
buttons.forEach(button => {
|
||||||
|
const text = button.textContent?.trim();
|
||||||
|
if (text === 'Add Single Log') {
|
||||||
|
button.addEventListener('click', () => generateRandomLog());
|
||||||
|
} else if (text === 'Start Simulation') {
|
||||||
|
button.addEventListener('click', () => startSimulation());
|
||||||
|
} else if (text === 'Stop Simulation') {
|
||||||
|
button.addEventListener('click', () => stopSimulation());
|
||||||
|
}
|
||||||
|
});
|
||||||
}}>
|
}}>
|
||||||
<style>
|
<style>
|
||||||
.demoBox {
|
.demoBox {
|
||||||
@ -150,15 +155,15 @@ export const demoFunc = () => {
|
|||||||
</style>
|
</style>
|
||||||
<div class="demoBox">
|
<div class="demoBox">
|
||||||
<div class="controls">
|
<div class="controls">
|
||||||
<dees-button @clicked=${() => generateRandomLog()}>Add Single Log</dees-button>
|
<dees-button>Add Single Log</dees-button>
|
||||||
<dees-button @clicked=${() => startSimulation()}>Start Simulation</dees-button>
|
<dees-button>Start Simulation</dees-button>
|
||||||
<dees-button @clicked=${() => stopSimulation()}>Stop Simulation</dees-button>
|
<dees-button>Stop Simulation</dees-button>
|
||||||
</div>
|
</div>
|
||||||
<div class="info">Simulating realistic server logs with various levels and sources</div>
|
<div class="info">Simulating realistic server logs with various levels and sources</div>
|
||||||
<dees-chart-log
|
<dees-chart-log
|
||||||
.label=${'Production Server Logs'}
|
.label=${'Production Server Logs'}
|
||||||
></dees-chart-log>
|
></dees-chart-log>
|
||||||
</div>
|
</div>
|
||||||
</dees-demowrapper>
|
</dees-demowrapper>
|
||||||
`;
|
`;
|
||||||
};
|
};
|
Reference in New Issue
Block a user