From af00d1fe61da45b3326a3c1393e7c4e9d7ed4d3b Mon Sep 17 00:00:00 2001 From: Joshua Boniface Date: Fri, 28 Feb 2025 23:02:07 -0500 Subject: [PATCH] Add VM list to nodes page and remove whitespace --- pvc-vue/src/views/Nodes.vue | 257 +++++++++++++++++++++++++++++------- 1 file changed, 207 insertions(+), 50 deletions(-) diff --git a/pvc-vue/src/views/Nodes.vue b/pvc-vue/src/views/Nodes.vue index c831f5a..c5b1e85 100644 --- a/pvc-vue/src/views/Nodes.vue +++ b/pvc-vue/src/views/Nodes.vue @@ -46,42 +46,42 @@
- - - - - -
@@ -169,21 +169,21 @@
- - -
@@ -215,33 +215,33 @@
- - - - -
@@ -252,6 +252,60 @@ + + +
+ +
+
+
+
Running VMs
+
+
+
+ +
+
+ +
+
+
+
+
+
+ Running VMs +
+
+
+
+

No VMs running on this node

+
+
+
+ {{ vm }} +
+
+
+
+
+
+
+ +
+
+
@@ -314,7 +368,8 @@ const sections = ref({ info: true, graphs: true, cpu: true, - resources: true + resources: true, + vms: true }); // Toggle section visibility @@ -493,7 +548,7 @@ const nodeAllocatedMemoryChartData = computed(() => { // Determine color for daemon state const getDaemonStateColor = (state) => { if (!state) return ''; - + if (state === 'run') return 'green'; if (['init', 'shutdown'].includes(state)) return 'yellow'; if (['stop', 'dead', 'fenced'].includes(state)) return 'red'; @@ -503,7 +558,7 @@ const getDaemonStateColor = (state) => { // Determine color for coordinator state const getCoordinatorStateColor = (state) => { if (!state) return ''; - + if (state === 'primary') return 'green'; if (state === 'secondary') return 'blue'; if (state === 'hypervisor') return 'gray'; @@ -513,12 +568,35 @@ const getCoordinatorStateColor = (state) => { // Determine color for domain state const getDomainStateColor = (state) => { if (!state) return ''; - + if (state === 'ready') return 'green'; if (['flushing', 'flushed', 'unflushing'].includes(state)) return 'blue'; return 'gray'; }; +// Handle VM click (placeholder until VMs page is implemented) +const handleVmClick = (vmName) => { + console.log(`VM clicked: ${vmName}`); + // You can show a toast notification or modal here + alert(`The VMs page is not yet implemented. You clicked on VM: ${vmName}`); +}; + +// Calculate the minimum width for VM items based on the longest VM name +const calculateVmItemMinWidth = computed(() => { + if (!selectedNodeData.value || !selectedNodeData.value.running_domains || !selectedNodeData.value.running_domains.length) { + return 100; // Default minimum width + } + + // Find the longest VM name + const longestVmName = selectedNodeData.value.running_domains.reduce((longest, current) => { + return current.length > longest.length ? current : longest; + }, ''); + + // Calculate width based on character count (approx 8px per character plus padding) + const minWidth = Math.max(100, longestVmName.length * 8 + 32); + return minWidth; +}); + // Initialize the component onMounted(() => { // Select the first node by default if available @@ -720,7 +798,7 @@ onUnmounted(() => { .metrics-row { grid-template-columns: repeat(4, 1fr); } - + .info-row { grid-template-columns: repeat(3, 1fr); } @@ -742,7 +820,7 @@ onUnmounted(() => { .metrics-row { grid-template-columns: repeat(2, 1fr); } - + .info-row { grid-template-columns: repeat(2, 1fr); } @@ -761,9 +839,9 @@ onUnmounted(() => { } @media (max-width: 800px) { - .metrics-row, + .metrics-row, .info-row, - .graphs-row, + .graphs-row, .resources-row-cpu, .resources-row-memory { grid-template-columns: 1fr; @@ -922,4 +1000,83 @@ onUnmounted(() => { background: white; border: none; } + +/* Running VMs section styles */ +.vms-container { + width: 100%; +} + +.vms-card { + background: white; + border: 1px solid rgba(0,0,0,0.125); + border-radius: 0.25rem; + height: 100%; + display: flex; + flex-direction: column; + width: 100%; + overflow: hidden; +} + +.vms-card .card-header { + background-color: rgba(0, 0, 0, 0.03); + padding: 0.5rem; + border-bottom: 1px solid rgba(0, 0, 0, 0.125); + height: 38px; + display: flex; + justify-content: space-between; + align-items: center; +} + +.vms-card .card-body { + flex: 1; + padding: 0.5rem; + display: flex; + flex-direction: column; + position: relative; + width: 100%; + overflow: visible; +} + +.vm-count { + font-size: 0.8rem; + color: #6c757d; + font-weight: normal; + margin-left: 0.5rem; +} + +.no-vms { + display: flex; + justify-content: center; + align-items: center; + height: 100px; + color: #6c757d; + font-style: italic; +} + +.vm-list { + display: grid; + gap: 0.5rem; + width: 100%; +} + +.vm-item { + padding: 0.5rem; + background-color: rgba(0, 0, 0, 0.015); + border: 1px solid rgba(0, 0, 0, 0.05); + border-radius: 0.25rem; + cursor: pointer; + text-align: center; + font-weight: 500; + color: #333; + transition: all 0.2s; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + position: relative; +} + +.vm-item:hover { + background-color: rgba(0, 0, 0, 0.04); + border-color: rgba(0, 0, 0, 0.1); +} \ No newline at end of file