diff --git a/app/static/index.html b/app/static/index.html
index d52263e..e206bae 100644
--- a/app/static/index.html
+++ b/app/static/index.html
@@ -342,6 +342,114 @@
transform: translateY(-2px);
box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
}
+
+ /* Storage Cylinder Chart */
+ .storage-cylinder-card {
+ background: linear-gradient(135deg, #2B2B2B 0%, #1E1E1E 100%);
+ border: 1px solid #404040;
+ border-radius: 8px;
+ padding: 20px;
+ text-align: center;
+ transition: all 0.3s ease;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ min-height: 200px;
+ }
+
+ .storage-cylinder-card:hover {
+ transform: translateY(-2px);
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.3);
+ }
+
+ .storage-cylinder {
+ width: 80px;
+ height: 120px;
+ position: relative;
+ margin: 16px 0;
+ }
+
+ .cylinder-container {
+ width: 100%;
+ height: 100%;
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ }
+
+ .cylinder-outline {
+ width: 60px;
+ height: 100px;
+ border: 3px solid rgba(255, 255, 255, 0.3);
+ border-radius: 30px;
+ position: relative;
+ background: rgba(255, 255, 255, 0.05);
+ overflow: hidden;
+ }
+
+ .cylinder-fill {
+ position: absolute;
+ bottom: 0;
+ left: 0;
+ width: 100%;
+ background: linear-gradient(to top,
+ rgba(34, 197, 94, 0.8) 0%,
+ rgba(34, 197, 94, 0.6) 50%,
+ rgba(34, 197, 94, 0.4) 100%);
+ border-radius: 0 0 27px 27px;
+ transition: height 0.8s ease-in-out;
+ min-height: 2px;
+ }
+
+ .cylinder-top {
+ position: absolute;
+ top: -3px;
+ left: -3px;
+ width: 66px;
+ height: 20px;
+ border: 3px solid rgba(255, 255, 255, 0.3);
+ border-bottom: none;
+ border-radius: 33px 33px 0 0;
+ background: rgba(255, 255, 255, 0.05);
+ }
+
+ .cylinder-bottom {
+ position: absolute;
+ bottom: -3px;
+ left: -3px;
+ width: 66px;
+ height: 20px;
+ border: 3px solid rgba(255, 255, 255, 0.3);
+ border-top: none;
+ border-radius: 0 0 33px 33px;
+ background: rgba(255, 255, 255, 0.05);
+ }
+
+ .storage-cylinder-info {
+ margin-top: 12px;
+ text-align: center;
+ }
+
+ .storage-cylinder-label {
+ font-size: 14px;
+ color: var(--pf-global--Color--200);
+ margin-bottom: 4px;
+ }
+
+ .storage-cylinder-value {
+ font-size: 18px;
+ font-weight: 600;
+ color: var(--pf-global--Color--100);
+ margin-bottom: 2px;
+ }
+
+ .storage-cylinder-percentage {
+ font-size: 12px;
+ color: var(--pf-global--success-color--100);
+ font-weight: 500;
+ }
/* Chart Cards */
.chart-card {
@@ -1821,6 +1929,50 @@
+
+
+
+
+
+
+
+
+
Storage Usage
+
-
+
0%
+
+
+
+
+
+
+
+
-
+
Storage Warnings
+
+
+
+
+
+
-
+
Storage Classes
+
+
+
Resource Analytics
@@ -2727,6 +2879,86 @@
return 'Healthy';
}
+ // Dashboard Storage Functions
+ async function loadDashboardStorageData() {
+ try {
+ console.log('Loading dashboard storage data...');
+
+ // Load storage data from API
+ const response = await fetch('/api/v1/storage/analysis');
+ if (!response.ok) {
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
+ }
+
+ const data = await response.json();
+
+ // Update dashboard storage metrics
+ updateDashboardStorageMetrics(data);
+
+ console.log('Dashboard storage data loaded successfully');
+
+ } catch (error) {
+ console.error('Error loading dashboard storage data:', error);
+ // Don't show error for storage data, just log it
+ }
+ }
+
+ function updateDashboardStorageMetrics(data) {
+ try {
+ // Update storage metrics cards
+ document.getElementById('dashboard-total-pvcs').textContent = data.total_pvcs || '0';
+ document.getElementById('dashboard-storage-warnings').textContent = data.storage_warnings || '0';
+ document.getElementById('dashboard-storage-classes').textContent = data.storage_classes ? data.storage_classes.length : '0';
+
+ // Update storage cylinder
+ updateStorageCylinder(data);
+
+ } catch (error) {
+ console.error('Error updating dashboard storage metrics:', error);
+ }
+ }
+
+ function updateStorageCylinder(data) {
+ try {
+ const totalStorageUsed = data.total_storage_used || 0;
+ const storageUtilization = data.storage_utilization_percent || 0;
+
+ // Calculate cylinder fill percentage (use storage utilization or mock calculation)
+ const fillPercentage = Math.min(100, Math.max(0, storageUtilization));
+
+ // Update cylinder fill
+ const cylinderFill = document.getElementById('storage-cylinder-fill');
+ if (cylinderFill) {
+ cylinderFill.style.height = `${fillPercentage}%`;
+ }
+
+ // Update cylinder info
+ document.getElementById('storage-cylinder-used').textContent = formatBytes(totalStorageUsed);
+ document.getElementById('storage-cylinder-percentage').textContent = `${fillPercentage.toFixed(1)}%`;
+
+ // Change color based on utilization level
+ const cylinderPercentage = document.getElementById('storage-cylinder-percentage');
+ if (cylinderPercentage) {
+ if (fillPercentage >= 90) {
+ cylinderPercentage.style.color = 'var(--pf-global--danger-color--100)';
+ cylinderFill.style.background = 'linear-gradient(to top, rgba(220, 38, 38, 0.8) 0%, rgba(220, 38, 38, 0.6) 50%, rgba(220, 38, 38, 0.4) 100%)';
+ } else if (fillPercentage >= 75) {
+ cylinderPercentage.style.color = 'var(--pf-global--warning-color--100)';
+ cylinderFill.style.background = 'linear-gradient(to top, rgba(245, 158, 11, 0.8) 0%, rgba(245, 158, 11, 0.6) 50%, rgba(245, 158, 11, 0.4) 100%)';
+ } else if (fillPercentage >= 50) {
+ cylinderPercentage.style.color = 'var(--pf-global--info-color--100)';
+ cylinderFill.style.background = 'linear-gradient(to top, rgba(59, 130, 246, 0.8) 0%, rgba(59, 130, 246, 0.6) 50%, rgba(59, 130, 246, 0.4) 100%)';
+ } else {
+ cylinderPercentage.style.color = 'var(--pf-global--success-color--100)';
+ cylinderFill.style.background = 'linear-gradient(to top, rgba(34, 197, 94, 0.8) 0%, rgba(34, 197, 94, 0.6) 50%, rgba(34, 197, 94, 0.4) 100%)';
+ }
+ }
+
+ } catch (error) {
+ console.error('Error updating storage cylinder:', error);
+ }
+ }
+
// Initialize the application
document.addEventListener('DOMContentLoaded', function() {
initializeApp();
@@ -3088,6 +3320,9 @@
// Update metrics cards with results
updateMetricsCards(statusData.result);
+ // Load storage data for dashboard
+ await loadDashboardStorageData();
+
// Load dashboard charts
updateSmartProgress(100, 'Loading dashboard charts...');
await loadDashboardCharts();