Skip to content

Commit 8e0d558

Browse files
committed
✨ Update Storage Efficiency, Memory Velocity, and Pattern Discovery cards with new designs
- Replace Storage Efficiency progress bar with sparkline showing 7.2 TB space saved - Update Memory Velocity to show 1,847 memories/hour with sparkline visualization - Change Pattern Discovery Rate to 73.2% accuracy with time-series tracking - Add comprehensive sparkline rendering for all new metrics - Implement real-time data updates for storage, velocity, and pattern sparklines - Match design specifications from user screenshots with proper trend indicators
1 parent e82910c commit 8e0d558

File tree

1 file changed

+287
-22
lines changed

1 file changed

+287
-22
lines changed

static/dashboard.html

Lines changed: 287 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1594,10 +1594,14 @@ <h3>P95 Latency</h3>
15941594
<div class="metric-card">
15951595
<div class="icon"><i class="fas fa-database"></i></div>
15961596
<h3>Storage Efficiency</h3>
1597-
<div class="metric-value success" id="storageEfficiency">24%</div>
1598-
<div class="metric-target">Post-consolidation ratio</div>
1599-
<div class="progress-bar">
1600-
<div class="progress-fill" style="width: 24%"></div>
1597+
<div class="metric-value success" id="storageEfficiency">7.2 TB</div>
1598+
<div class="metric-target">Space saved by compression</div>
1599+
<div class="sparkline-container">
1600+
<canvas id="storageSparkline" class="sparkline-chart"></canvas>
1601+
<div class="sparkline-info">
1602+
<span class="sparkline-trend" id="storageTrend">↑ 0.3 TB</span>
1603+
<span class="sparkline-period">Last 7d</span>
1604+
</div>
16011605
</div>
16021606
<div class="status-indicator success">
16031607
<i class="fas fa-compress-arrows-alt"></i> Optimized
@@ -1659,10 +1663,14 @@ <h3>API Performance</h3>
16591663
<div class="metric-card">
16601664
<div class="icon"><i class="fas fa-rocket"></i></div>
16611665
<h3>Memory Velocity</h3>
1662-
<div class="metric-value success" id="memoryVelocity">2.8GB/s</div>
1663-
<div class="metric-target">Target: >2.0GB/s</div>
1664-
<div class="progress-bar">
1665-
<div class="progress-fill" style="width: 140%"></div>
1666+
<div class="metric-value success" id="memoryVelocity">1,847</div>
1667+
<div class="metric-target">Memories processed/hour</div>
1668+
<div class="sparkline-container">
1669+
<canvas id="velocitySparkline" class="sparkline-chart"></canvas>
1670+
<div class="sparkline-info">
1671+
<span class="sparkline-trend" id="velocityTrend">↑ 127</span>
1672+
<span class="sparkline-period">Last 24h</span>
1673+
</div>
16661674
</div>
16671675
<div class="status-indicator success">
16681676
<i class="fas fa-check-circle"></i> High Throughput
@@ -1672,10 +1680,14 @@ <h3>Memory Velocity</h3>
16721680
<div class="metric-card">
16731681
<div class="icon"><i class="fas fa-search-plus"></i></div>
16741682
<h3>Pattern Discovery Rate</h3>
1675-
<div class="metric-value success" id="patternDiscoveryRateCard">4.2/hr</div>
1676-
<div class="metric-target">Target: >3.0/hr</div>
1677-
<div class="progress-bar">
1678-
<div class="progress-fill" style="width: 140%"></div>
1683+
<div class="metric-value success" id="patternDiscoveryRateCard">73.2%</div>
1684+
<div class="metric-target">Pattern recognition accuracy</div>
1685+
<div class="sparkline-container">
1686+
<canvas id="patternSparkline" class="sparkline-chart"></canvas>
1687+
<div class="sparkline-info">
1688+
<span class="sparkline-trend" id="patternTrend">↑ 2.1%</span>
1689+
<span class="sparkline-period">Last 24h</span>
1690+
</div>
16791691
</div>
16801692
<div class="status-indicator success">
16811693
<i class="fas fa-check-circle"></i> Above Target
@@ -2462,15 +2474,46 @@ <h4>🚀 Production Features:</h4>
24622474
let p95LatencyData = [];
24632475
const MAX_SPARKLINE_POINTS = 48; // 24 hours worth of data (30min intervals)
24642476

2477+
// Storage Efficiency Sparkline Data
2478+
let storageData = [];
2479+
2480+
// Memory Velocity Sparkline Data
2481+
let velocityData = [];
2482+
2483+
// Pattern Discovery Sparkline Data
2484+
let patternData = [];
2485+
24652486
// Initialize with sample data
24662487
function initializeSparklineData() {
24672488
p95LatencyData = [];
2489+
storageData = [];
2490+
velocityData = [];
2491+
patternData = [];
2492+
24682493
for (let i = 0; i < MAX_SPARKLINE_POINTS; i++) {
2469-
// Generate realistic latency data with some variation
2494+
// P95 Latency data
24702495
const baseLatency = 38;
2471-
const variation = (Math.random() - 0.5) * 10; // ±5ms variation
2472-
const value = Math.max(25, Math.min(50, baseLatency + variation));
2473-
p95LatencyData.push(value);
2496+
const latencyVariation = (Math.random() - 0.5) * 10; // ±5ms variation
2497+
const latencyValue = Math.max(25, Math.min(50, baseLatency + latencyVariation));
2498+
p95LatencyData.push(latencyValue);
2499+
2500+
// Storage Efficiency data (in TB)
2501+
const baseStorage = 7.2;
2502+
const storageVariation = (Math.random() - 0.5) * 0.8; // ±0.4TB variation
2503+
const storageValue = Math.max(6.0, Math.min(8.5, baseStorage + storageVariation));
2504+
storageData.push(storageValue);
2505+
2506+
// Memory Velocity data (memories/hour)
2507+
const baseVelocity = 1847;
2508+
const velocityVariation = (Math.random() - 0.5) * 300; // ±150 variation
2509+
const velocityValue = Math.max(1400, Math.min(2200, baseVelocity + velocityVariation));
2510+
velocityData.push(velocityValue);
2511+
2512+
// Pattern Discovery data (accuracy %)
2513+
const basePattern = 73.2;
2514+
const patternVariation = (Math.random() - 0.5) * 8; // ±4% variation
2515+
const patternValue = Math.max(65, Math.min(85, basePattern + patternVariation));
2516+
patternData.push(patternValue);
24742517
}
24752518
}
24762519

@@ -2482,6 +2525,30 @@ <h4>🚀 Production Features:</h4>
24822525
drawSparkline();
24832526
}
24842527

2528+
function updateStorageSparkline(newValue) {
2529+
if (storageData.length >= MAX_SPARKLINE_POINTS) {
2530+
storageData.shift();
2531+
}
2532+
storageData.push(newValue);
2533+
drawStorageSparkline();
2534+
}
2535+
2536+
function updateVelocitySparkline(newValue) {
2537+
if (velocityData.length >= MAX_SPARKLINE_POINTS) {
2538+
velocityData.shift();
2539+
}
2540+
velocityData.push(newValue);
2541+
drawVelocitySparkline();
2542+
}
2543+
2544+
function updatePatternSparkline(newValue) {
2545+
if (patternData.length >= MAX_SPARKLINE_POINTS) {
2546+
patternData.shift();
2547+
}
2548+
patternData.push(newValue);
2549+
drawPatternSparkline();
2550+
}
2551+
24852552
function drawSparkline() {
24862553
const canvas = document.getElementById('p95Sparkline');
24872554
if (!canvas) return;
@@ -2562,6 +2629,195 @@ <h4>🚀 Production Features:</h4>
25622629
}
25632630
}
25642631

2632+
// Storage Efficiency Sparkline
2633+
function drawStorageSparkline() {
2634+
const canvas = document.getElementById('storageSparkline');
2635+
if (!canvas) return;
2636+
2637+
const ctx = canvas.getContext('2d');
2638+
const rect = canvas.getBoundingClientRect();
2639+
canvas.width = rect.width * window.devicePixelRatio;
2640+
canvas.height = rect.height * window.devicePixelRatio;
2641+
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
2642+
2643+
const width = rect.width;
2644+
const height = rect.height;
2645+
2646+
ctx.clearRect(0, 0, width, height);
2647+
2648+
if (storageData.length < 2) return;
2649+
2650+
const min = Math.min(...storageData);
2651+
const max = Math.max(...storageData);
2652+
const range = max - min || 1;
2653+
2654+
ctx.beginPath();
2655+
ctx.strokeStyle = '#b8bb26'; // Gruvbox green
2656+
ctx.lineWidth = 2;
2657+
2658+
const stepX = width / (storageData.length - 1);
2659+
2660+
storageData.forEach((value, index) => {
2661+
const x = index * stepX;
2662+
const y = height - ((value - min) / range) * height;
2663+
2664+
if (index === 0) {
2665+
ctx.moveTo(x, y);
2666+
} else {
2667+
ctx.lineTo(x, y);
2668+
}
2669+
});
2670+
2671+
ctx.stroke();
2672+
updateStorageTrend();
2673+
}
2674+
2675+
function updateStorageTrend() {
2676+
const trendElement = document.getElementById('storageTrend');
2677+
if (!trendElement || storageData.length < 2) return;
2678+
2679+
const current = storageData[storageData.length - 1];
2680+
const previous = storageData[storageData.length - 2];
2681+
const change = current - previous;
2682+
2683+
if (Math.abs(change) < 0.05) {
2684+
trendElement.textContent = '→ Stable';
2685+
trendElement.className = 'sparkline-trend';
2686+
} else if (change > 0) {
2687+
trendElement.textContent = `↗ +${change.toFixed(1)} TB`;
2688+
trendElement.className = 'sparkline-trend up';
2689+
} else {
2690+
trendElement.textContent = `↘ ${change.toFixed(1)} TB`;
2691+
trendElement.className = 'sparkline-trend down';
2692+
}
2693+
}
2694+
2695+
// Memory Velocity Sparkline
2696+
function drawVelocitySparkline() {
2697+
const canvas = document.getElementById('velocitySparkline');
2698+
if (!canvas) return;
2699+
2700+
const ctx = canvas.getContext('2d');
2701+
const rect = canvas.getBoundingClientRect();
2702+
canvas.width = rect.width * window.devicePixelRatio;
2703+
canvas.height = rect.height * window.devicePixelRatio;
2704+
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
2705+
2706+
const width = rect.width;
2707+
const height = rect.height;
2708+
2709+
ctx.clearRect(0, 0, width, height);
2710+
2711+
if (velocityData.length < 2) return;
2712+
2713+
const min = Math.min(...velocityData);
2714+
const max = Math.max(...velocityData);
2715+
const range = max - min || 1;
2716+
2717+
ctx.beginPath();
2718+
ctx.strokeStyle = '#b8bb26'; // Gruvbox green
2719+
ctx.lineWidth = 2;
2720+
2721+
const stepX = width / (velocityData.length - 1);
2722+
2723+
velocityData.forEach((value, index) => {
2724+
const x = index * stepX;
2725+
const y = height - ((value - min) / range) * height;
2726+
2727+
if (index === 0) {
2728+
ctx.moveTo(x, y);
2729+
} else {
2730+
ctx.lineTo(x, y);
2731+
}
2732+
});
2733+
2734+
ctx.stroke();
2735+
updateVelocityTrend();
2736+
}
2737+
2738+
function updateVelocityTrend() {
2739+
const trendElement = document.getElementById('velocityTrend');
2740+
if (!trendElement || velocityData.length < 2) return;
2741+
2742+
const current = velocityData[velocityData.length - 1];
2743+
const previous = velocityData[velocityData.length - 2];
2744+
const change = current - previous;
2745+
2746+
if (Math.abs(change) < 5) {
2747+
trendElement.textContent = '→ Stable';
2748+
trendElement.className = 'sparkline-trend';
2749+
} else if (change > 0) {
2750+
trendElement.textContent = `↗ +${Math.round(change)}`;
2751+
trendElement.className = 'sparkline-trend up';
2752+
} else {
2753+
trendElement.textContent = `↘ ${Math.round(change)}`;
2754+
trendElement.className = 'sparkline-trend down';
2755+
}
2756+
}
2757+
2758+
// Pattern Discovery Sparkline
2759+
function drawPatternSparkline() {
2760+
const canvas = document.getElementById('patternSparkline');
2761+
if (!canvas) return;
2762+
2763+
const ctx = canvas.getContext('2d');
2764+
const rect = canvas.getBoundingClientRect();
2765+
canvas.width = rect.width * window.devicePixelRatio;
2766+
canvas.height = rect.height * window.devicePixelRatio;
2767+
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
2768+
2769+
const width = rect.width;
2770+
const height = rect.height;
2771+
2772+
ctx.clearRect(0, 0, width, height);
2773+
2774+
if (patternData.length < 2) return;
2775+
2776+
const min = Math.min(...patternData);
2777+
const max = Math.max(...patternData);
2778+
const range = max - min || 1;
2779+
2780+
ctx.beginPath();
2781+
ctx.strokeStyle = '#b8bb26'; // Gruvbox green
2782+
ctx.lineWidth = 2;
2783+
2784+
const stepX = width / (patternData.length - 1);
2785+
2786+
patternData.forEach((value, index) => {
2787+
const x = index * stepX;
2788+
const y = height - ((value - min) / range) * height;
2789+
2790+
if (index === 0) {
2791+
ctx.moveTo(x, y);
2792+
} else {
2793+
ctx.lineTo(x, y);
2794+
}
2795+
});
2796+
2797+
ctx.stroke();
2798+
updatePatternTrend();
2799+
}
2800+
2801+
function updatePatternTrend() {
2802+
const trendElement = document.getElementById('patternTrend');
2803+
if (!trendElement || patternData.length < 2) return;
2804+
2805+
const current = patternData[patternData.length - 1];
2806+
const previous = patternData[patternData.length - 2];
2807+
const change = current - previous;
2808+
2809+
if (Math.abs(change) < 0.1) {
2810+
trendElement.textContent = '→ Stable';
2811+
trendElement.className = 'sparkline-trend';
2812+
} else if (change > 0) {
2813+
trendElement.textContent = `↗ +${change.toFixed(1)}%`;
2814+
trendElement.className = 'sparkline-trend up';
2815+
} else {
2816+
trendElement.textContent = `↘ ${change.toFixed(1)}%`;
2817+
trendElement.className = 'sparkline-trend down';
2818+
}
2819+
}
2820+
25652821
// Close modal when clicking outside
25662822
window.onclick = function(event) {
25672823
const modals = document.querySelectorAll('.branch-modal');
@@ -2599,6 +2855,9 @@ <h4>🚀 Production Features:</h4>
25992855
// Initial sparkline draw
26002856
setTimeout(() => {
26012857
drawSparkline();
2858+
drawStorageSparkline();
2859+
drawVelocitySparkline();
2860+
drawPatternSparkline();
26022861
}, 100);
26032862
});
26042863

@@ -3452,14 +3711,14 @@ <h4>🚀 Production Features:</h4>
34523711
function updateMetrics() {
34533712
// Simulate real system performance data updates
34543713
const elements = [
3455-
{ id: 'p95Latency', current: 38, min: 35, max: 48, suffix: 'ms' },
3456-
{ id: 'storageEfficiency', current: 24, min: 22, max: 26, suffix: '%' },
3714+
{ id: 'p95Latency', current: 38, min: 35, max: 48, suffix: 'ms', sparkline: 'p95' },
3715+
{ id: 'storageEfficiency', current: 7.2, min: 6.5, max: 8.0, suffix: ' TB', decimal: 1, sparkline: 'storage' },
34573716
{ id: 'predictionAccuracy', current: 89.2, min: 87.5, max: 91.0, suffix: '%', decimal: 1 },
34583717
{ id: 'relevancePrecision', current: 91.7, min: 90.0, max: 93.5, suffix: '%', decimal: 1 },
34593718
{ id: 'cacheHitRate', current: 94.3, min: 92.0, max: 96.0, suffix: '%', decimal: 1 },
34603719
{ id: 'apiPerformance', current: 99.1, min: 98.5, max: 99.8, suffix: '%', decimal: 1 },
3461-
{ id: 'memoryVelocity', current: 2.8, min: 2.5, max: 3.2, suffix: 'GB/s', decimal: 1 },
3462-
{ id: 'patternDiscoveryRateCard', current: 4.2, min: 3.8, max: 4.6, suffix: '/hr', decimal: 1 }
3720+
{ id: 'memoryVelocity', current: 1847, min: 1600, max: 2100, suffix: '', sparkline: 'velocity' },
3721+
{ id: 'patternDiscoveryRateCard', current: 73.2, min: 68.0, max: 78.0, suffix: '%', decimal: 1, sparkline: 'pattern' }
34633722
];
34643723

34653724
elements.forEach(el => {
@@ -3475,9 +3734,15 @@ <h4>🚀 Production Features:</h4>
34753734
element.textContent = Math.round(newValue) + el.suffix;
34763735
}
34773736

3478-
// Update sparkline for P95 latency
3479-
if (el.id === 'p95Latency') {
3737+
// Update sparklines for relevant metrics
3738+
if (el.sparkline === 'p95') {
34803739
updateSparklineData(newValue);
3740+
} else if (el.sparkline === 'storage') {
3741+
updateStorageSparkline(newValue);
3742+
} else if (el.sparkline === 'velocity') {
3743+
updateVelocitySparkline(newValue);
3744+
} else if (el.sparkline === 'pattern') {
3745+
updatePatternSparkline(newValue);
34813746
}
34823747
}
34833748
});

0 commit comments

Comments
 (0)