diff --git a/pvc-vue/package-lock.json b/pvc-vue/package-lock.json index ed28ba3..eeac95e 100644 --- a/pvc-vue/package-lock.json +++ b/pvc-vue/package-lock.json @@ -10,7 +10,8 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.7.2", "bootstrap": "^5.3.3", - "chart.js": "^4.4.8", + "chart.js": "^4.4.1", + "chartjs-plugin-annotation": "^3.0.1", "pinia": "^3.0.1", "vue": "^3.5.13", "vue-chartjs": "^5.3.2" @@ -983,6 +984,14 @@ "pnpm": ">=8" } }, + "node_modules/chartjs-plugin-annotation": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/chartjs-plugin-annotation/-/chartjs-plugin-annotation-3.1.0.tgz", + "integrity": "sha512-EkAed6/ycXD/7n0ShrlT1T2Hm3acnbFhgkIEJLa0X+M6S16x0zwj1Fv4suv/2bwayCT3jGPdAtI9uLcAMToaQQ==", + "peerDependencies": { + "chart.js": ">=4.0.0" + } + }, "node_modules/copy-anything": { "version": "3.0.5", "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", diff --git a/pvc-vue/package.json b/pvc-vue/package.json index 30f123c..fb0ae64 100644 --- a/pvc-vue/package.json +++ b/pvc-vue/package.json @@ -11,10 +11,11 @@ "dependencies": { "@fortawesome/fontawesome-free": "^6.7.2", "bootstrap": "^5.3.3", - "chart.js": "^4.4.8", + "chart.js": "^4.4.1", "pinia": "^3.0.1", "vue": "^3.5.13", - "vue-chartjs": "^5.3.2" + "vue-chartjs": "^5.3.2", + "chartjs-plugin-annotation": "^3.0.1" }, "devDependencies": { "@vitejs/plugin-vue": "^5.2.1", diff --git a/pvc-vue/src/App.vue b/pvc-vue/src/App.vue index 416fdd2..8572526 100644 --- a/pvc-vue/src/App.vue +++ b/pvc-vue/src/App.vue @@ -25,7 +25,10 @@
- +
diff --git a/pvc-vue/src/components/ClusterOverview.vue b/pvc-vue/src/components/ClusterOverview.vue index 69993c5..7ce7047 100644 --- a/pvc-vue/src/components/ClusterOverview.vue +++ b/pvc-vue/src/components/ClusterOverview.vue @@ -8,7 +8,7 @@
Cluster Health
-
+

@@ -116,6 +116,7 @@ import { Legend, Filler } from 'chart.js'; +import annotationPlugin from 'chartjs-plugin-annotation'; // Register Chart.js components ChartJS.register( @@ -126,7 +127,8 @@ ChartJS.register( Title, Tooltip, Legend, - Filler + Filler, + annotationPlugin ); const props = defineProps({ @@ -134,6 +136,11 @@ const props = defineProps({ type: Object, required: true, default: () => ({}) + }, + metricsHistory: { + type: Object, + required: true, + default: () => ({ labels: [], data: [] }) } }); @@ -153,19 +160,10 @@ const healthChartData = computed(() => { const health = props.clusterData.cluster_health?.health || 0; const colors = getHealthColors(health); - // Create sample data if health_history is not available - const now = Date.now(); - const defaultData = Array.from({length: 20}, (_, i) => ({ - time: now - (19 - i) * 1000, - value: health - })); - - const dataPoints = props.clusterData.health_history || defaultData; - return { - labels: dataPoints.map(point => new Date(point.time).toLocaleTimeString()), + labels: props.metricsHistory.labels, datasets: [{ - data: dataPoints.map(point => point.value), + data: props.metricsHistory.data, fill: true, backgroundColor: colors.bg, borderColor: colors.border, @@ -180,25 +178,49 @@ const healthChartData = computed(() => { const healthChartOptions = { responsive: true, maintainAspectRatio: false, + clip: false, plugins: { legend: { display: false + }, + tooltip: { + callbacks: { + label: (context) => `${context.parsed.y}%` + } + }, + annotation: { + annotations: { + warning: { + type: 'line', + yMin: 90, + yMax: 90, + borderColor: 'rgba(255, 193, 7, 0.2)', + borderWidth: 1, + }, + danger: { + type: 'line', + yMin: 50, + yMax: 50, + borderColor: 'rgba(220, 53, 69, 0.2)', + borderWidth: 1, + } + } } }, scales: { x: { display: false, grid: { - display: false, - }, + display: false + } }, y: { display: false, grid: { - display: false, + display: false }, min: 0, - max: 100, + max: 100 } }, animation: false, @@ -225,18 +247,21 @@ const healthChartOptions = { height: 100%; } -.health-content { +.health-content-wrapper { display: flex; flex-direction: column; gap: 0.5rem; - min-height: 300px; - height: auto; + height: calc(100% - 2rem); /* Account for header */ width: 100%; + position: relative; } .health-graph { position: relative; - height: 200px; + flex-grow: 1; + min-height: 0; /* Allow shrinking */ + display: flex; + align-items: center; } .health-percentage { @@ -262,7 +287,11 @@ const healthChartOptions = { padding: 0.5rem; background: rgba(0, 0, 0, 0.02); border-radius: 0.25rem; - flex-grow: 1; + position: relative; + bottom: 0; + min-height: 2.5rem; + max-height: 30%; /* Reduce maximum height */ + overflow-y: auto; } .messages-grid { @@ -291,7 +320,11 @@ const healthChartOptions = { } .health-message:hover { - background: rgba(220, 53, 69, 0.15); + background: rgba(0, 0, 0, 0.05); +} + +.health-message.healthy:hover { + background: rgba(40, 167, 69, 0.15); } .health-message:hover::after {