diff --git a/pvc-vue/src/App.vue b/pvc-vue/src/App.vue index b9e5c5a..961dc63 100644 --- a/pvc-vue/src/App.vue +++ b/pvc-vue/src/App.vue @@ -115,13 +115,20 @@ const updateMetricsHistory = (timestamp, status) => { memory: status.resources?.memory?.utilization || 0, health: status.cluster_health?.health || 0, storage: status.resources?.disk?.utilization || 0, - maintenance: status.maintenance === "true" ? true : false }; + // Create maintenance array if it doesn't exist + if (!metricsHistory.value.maintenance) { + metricsHistory.value.maintenance = { labels: [], data: [] }; + } + + // Track maintenance status as a boolean for each data point + const isInMaintenance = status.maintenance === "true"; + Object.keys(metrics).forEach(metric => { const labels = [...metricsHistory.value[metric].labels, timestamp]; const data = [...metricsHistory.value[metric].data, - typeof metrics[metric] === 'boolean' ? metrics[metric] : Math.round(metrics[metric]) + Math.round(metrics[metric]) ]; // Keep only last 180 points @@ -136,6 +143,21 @@ const updateMetricsHistory = (timestamp, status) => { }; }); + // Update maintenance history + const maintenanceLabels = [...metricsHistory.value.maintenance.labels, timestamp]; + const maintenanceData = [...metricsHistory.value.maintenance.data, isInMaintenance]; + + // Keep only last 180 points for maintenance too + if (maintenanceLabels.length > 180) { + maintenanceLabels.shift(); + maintenanceData.shift(); + } + + metricsHistory.value.maintenance = { + labels: maintenanceLabels, + data: maintenanceData + }; + // Track node-specific metrics if (!metricsHistory.value.nodes) { metricsHistory.value.nodes = {}; diff --git a/pvc-vue/src/components/charts/HealthChart.vue b/pvc-vue/src/components/charts/HealthChart.vue index dc1f860..5c15000 100644 --- a/pvc-vue/src/components/charts/HealthChart.vue +++ b/pvc-vue/src/components/charts/HealthChart.vue @@ -50,7 +50,11 @@ const props = defineProps({ }, chartData: { type: Object, - default: () => ({ labels: [], data: [] }) + default: () => ({ labels: [], data: [], maintenance: [] }) + }, + maintenance: { + type: Boolean, + default: false } }); @@ -66,7 +70,15 @@ const chartOptions = { }, tooltip: { callbacks: { - label: (context) => `${context.parsed.y}%` + label: (context) => { + const dataPoint = context.dataIndex; + const maintenanceData = props.chartData.maintenance || []; + const isInMaintenance = maintenanceData[dataPoint]; + + return isInMaintenance + ? `${context.parsed.y}% (Maintenance)` + : `${context.parsed.y}%`; + } } }, annotation: { @@ -117,9 +129,14 @@ const chartOptions = { } }; -// Helper function to get health color based on value -const getHealthColor = (value) => { - if (value > 90) { +// Helper function to get health color based on value and maintenance status +const getHealthColor = (value, isInMaintenance) => { + if (isInMaintenance) { + return { + border: 'rgba(13, 110, 253, 0.8)', // Blue for maintenance + background: 'rgba(13, 110, 253, 0.1)' + }; + } else if (value > 90) { return { border: 'rgba(40, 167, 69, 0.8)', // Green background: 'rgba(40, 167, 69, 0.1)' @@ -140,11 +157,13 @@ const getHealthColor = (value) => { const formattedChartData = computed(() => { const labels = props.chartData.labels || []; const data = props.chartData.data || []; + const maintenanceData = props.chartData.maintenance || []; // For single value or empty data if (data.length <= 1) { const value = data.length === 1 ? data[0] : props.value; - const color = getHealthColor(value); + const isInMaintenance = props.maintenance; + const color = getHealthColor(value, isInMaintenance); return { labels: labels.length ? labels : ['Health'], @@ -173,16 +192,24 @@ const formattedChartData = computed(() => { data, segment: { borderColor: ctx => { + const index = ctx.p1DataIndex; const value = ctx.p1.parsed.y; + const isInMaintenance = maintenanceData[index]; + + if (isInMaintenance) return 'rgba(13, 110, 253, 0.8)'; // Blue for maintenance if (value > 90) return 'rgba(40, 167, 69, 0.8)'; // Green if (value > 50) return 'rgba(255, 193, 7, 0.8)'; // Yellow - return 'rgba(220, 53, 69, 0.8)'; // Red + return 'rgba(220, 53, 69, 0.8)'; // Red }, backgroundColor: ctx => { + const index = ctx.p1DataIndex; const value = ctx.p1.parsed.y; + const isInMaintenance = maintenanceData[index]; + + if (isInMaintenance) return 'rgba(13, 110, 253, 0.1)'; // Blue for maintenance if (value > 90) return 'rgba(40, 167, 69, 0.1)'; // Green if (value > 50) return 'rgba(255, 193, 7, 0.1)'; // Yellow - return 'rgba(220, 53, 69, 0.1)'; // Red + return 'rgba(220, 53, 69, 0.1)'; // Red } }, fill: true, @@ -194,7 +221,8 @@ const formattedChartData = computed(() => { pointBorderColor: function(context) { const index = context.dataIndex; const value = context.dataset.data[index]; - return getHealthColor(value).border; + const isInMaintenance = maintenanceData[index]; + return getHealthColor(value, isInMaintenance).border; }, pointBorderWidth: 1.5 }]