diff --git a/pvc-vue/src/App.vue b/pvc-vue/src/App.vue index 9886628..3a3061f 100644 --- a/pvc-vue/src/App.vue +++ b/pvc-vue/src/App.vue @@ -57,7 +57,8 @@ const metricsHistory = ref({ cpu: { labels: [], data: [] }, memory: { labels: [], data: [] }, health: { labels: [], data: [] }, - storage: { labels: [], data: [] } + storage: { labels: [], data: [] }, + maintenance: { labels: [], data: [] } }); const showConnectionStatus = ref(false); @@ -83,17 +84,19 @@ const saveConfig = async (newConfig) => { }; const updateMetricsHistory = (timestamp, status) => { - // Create new arrays instead of mutating const metrics = { cpu: status.resources?.cpu?.utilization || 0, memory: status.resources?.memory?.utilization || 0, health: status.cluster_health?.health || 0, - storage: status.resources?.disk?.utilization || 0 + storage: status.resources?.disk?.utilization || 0, + maintenance: status.maintenance === "true" ? true : false }; Object.keys(metrics).forEach(metric => { const labels = [...metricsHistory.value[metric].labels, timestamp]; - const data = [...metricsHistory.value[metric].data, Math.round(metrics[metric])]; + const data = [...metricsHistory.value[metric].data, + typeof metrics[metric] === 'boolean' ? metrics[metric] : Math.round(metrics[metric]) + ]; // Keep only last 180 points if (labels.length > 180) { diff --git a/pvc-vue/src/components/ClusterOverview.vue b/pvc-vue/src/components/ClusterOverview.vue index 10b4c15..e26d74d 100644 --- a/pvc-vue/src/components/ClusterOverview.vue +++ b/pvc-vue/src/components/ClusterOverview.vue @@ -123,9 +123,9 @@
@@ -241,6 +237,37 @@ const props = defineProps({ } }); +const displayMessages = computed(() => { + const messages = []; + + // Add maintenance message if maintenance is "true" + if (props.clusterData.maintenance === "true") { + messages.push({ + id: "Cluster is in maintenance", + health_delta: null, + text: "Cluster is currently in maintenance mode", + maintenance: true + }); + } + + // Add other messages if they exist + if (props.clusterData.cluster_health?.messages?.length) { + messages.push(...props.clusterData.cluster_health.messages); + } + + // If no messages and not in maintenance, show "No issues" + if (messages.length === 0) { + messages.push({ + id: "No issues detected", + health_delta: null, + text: "System is healthy", + health_delta: 0 // This will trigger the delta-low class for green styling + }); + } + + return messages; +}); + const getHealthClass = (health) => { if (health > 90) return 'status-healthy'; if (health > 50) return 'status-warning'; @@ -248,12 +275,16 @@ const getHealthClass = (health) => { }; const getHealthColors = (health) => { + if (props.clusterData.maintenance === "true") { + return { bg: 'rgba(13, 110, 253, 0.1)', border: 'rgba(13, 110, 253, 0.2)' }; // Blue + } if (health > 90) return { bg: 'rgba(40, 167, 69, 0.1)', border: 'rgba(40, 167, 69, 0.2)' }; // Green if (health > 50) return { bg: 'rgba(255, 193, 7, 0.1)', border: 'rgba(255, 193, 7, 0.2)' }; // Yellow return { bg: 'rgba(220, 53, 69, 0.1)', border: 'rgba(220, 53, 69, 0.2)' }; // Red }; const getDeltaClass = (delta) => { + if (delta === null) return 'delta-info'; // For maintenance and healthy messages const value = Math.abs(delta); if (value <= 5) return 'delta-low'; if (value <= 10) return 'delta-medium'; @@ -268,12 +299,26 @@ const healthChartData = computed(() => { fill: true, segment: { borderColor: (ctx) => { + console.log('Context:', ctx); + console.log('Maintenance data:', props.metricsData.maintenance?.data); + console.log('Available indices:', ctx.p0?.parsed?.x, ctx.p1?.parsed?.x); + const maintenanceAtPoint = props.metricsData.maintenance?.data[ctx.p0.parsed.x]; + console.log('Point', ctx.p0.parsed.x, 'Maintenance:', maintenanceAtPoint); + if (maintenanceAtPoint === true) { + console.log('Using blue color for maintenance'); + return 'rgba(13, 110, 253, 0.2)'; + } const value = ctx.p1.parsed.y; + console.log('Using health-based color:', value); if (value > 90) return 'rgba(40, 167, 69, 0.2)'; // Green if (value > 50) return 'rgba(255, 193, 7, 0.2)'; // Yellow return 'rgba(220, 53, 69, 0.2)'; // Red }, backgroundColor: (ctx) => { + const maintenanceAtPoint = props.metricsData.maintenance?.data[ctx.p0.parsed.x]; + if (maintenanceAtPoint === true) { + return 'rgba(13, 110, 253, 0.1)'; + } const value = ctx.p1.parsed.y; if (value > 90) return 'rgba(40, 167, 69, 0.1)'; // Green if (value > 50) return 'rgba(255, 193, 7, 0.1)'; // Yellow @@ -286,6 +331,8 @@ const healthChartData = computed(() => { pointHoverRadius: 4, pointBackgroundColor: 'rgba(255, 255, 255, 0.8)', // Light background for all points pointBorderColor: (ctx) => { + const maintenanceAtPoint = props.metricsData.maintenance?.data[ctx.dataIndex]; + if (maintenanceAtPoint === true) return 'rgba(13, 110, 253, 0.5)'; // Blue for maintenance if (!ctx.raw) return 'rgba(0, 0, 0, 0.2)'; const value = ctx.raw; if (value > 90) return 'rgba(40, 167, 69, 0.5)'; // Green @@ -607,6 +654,11 @@ const chartOptions = { color: #721c24; /* Darker red */ } +.delta-info { + background: rgba(13, 110, 253, 0.1); + color: #0d6efd; +} + .metric-card { background: white; border: 1px solid rgba(0,0,0,0.125); @@ -676,4 +728,18 @@ const chartOptions = { grid-template-columns: repeat(2, 1fr); } } + +.status-maintenance { + color: #0d6efd; /* Bootstrap blue */ +} + +.health-message.healthy { + background: rgba(40, 167, 69, 0.1); + color: #28a745; +} + +.delta-info { + background: rgba(13, 110, 253, 0.1); + color: #0d6efd; +}