mirror of
https://github.com/rcourtman/Pulse.git
synced 2026-09-22 11:13:26 +00:00
fix: improve node name display and configuration handling
- Add support for custom display names via PROXMOX_NODE_NAME configuration - Handle multi-node clusters properly by prefixing node names with endpoint name - Fix dashboard and nodes views to show configured display names - Fix non-sequential endpoint numbering issue in settings (node_2, node_8, node_14) - Improve endpoint configuration loading to handle any index number Fixes #100 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
+23
-2
@@ -275,9 +275,20 @@ async function fetchDataForPveEndpoint(endpointId, apiClientInstance, config) {
|
||||
const correspondingNodeInfo = nodes[index];
|
||||
if (!correspondingNodeInfo || !correspondingNodeInfo.node) return;
|
||||
|
||||
// Determine display name based on cluster configuration
|
||||
let nodeDisplayName = correspondingNodeInfo.node;
|
||||
if (endpointType === 'standalone' && config.name) {
|
||||
// For standalone nodes, use the configured name
|
||||
nodeDisplayName = config.name;
|
||||
} else if (endpointType === 'cluster' && nodes.length > 1 && config.name) {
|
||||
// For multi-node clusters, prefix with configured name
|
||||
nodeDisplayName = `${config.name} - ${correspondingNodeInfo.node}`;
|
||||
}
|
||||
|
||||
const finalNode = {
|
||||
cpu: null, mem: null, disk: null, maxdisk: null, uptime: 0, loadavg: null, storage: [],
|
||||
node: correspondingNodeInfo.node,
|
||||
displayName: nodeDisplayName,
|
||||
maxcpu: correspondingNodeInfo.maxcpu,
|
||||
maxmem: correspondingNodeInfo.maxmem,
|
||||
level: correspondingNodeInfo.level,
|
||||
@@ -292,8 +303,18 @@ async function fetchDataForPveEndpoint(endpointId, apiClientInstance, config) {
|
||||
if (result.status === 'fulfilled' && result.value) {
|
||||
const nodeData = result.value;
|
||||
// Use endpointId (the actual key) for constructing IDs and tagging
|
||||
endpointVms.push(...(nodeData.vms || []).map(vm => ({ ...vm, endpointId: endpointId, id: `${endpointId}-${vm.node}-${vm.vmid}` })));
|
||||
endpointContainers.push(...(nodeData.containers || []).map(ct => ({ ...ct, endpointId: endpointId, id: `${endpointId}-${ct.node}-${ct.vmid}` })));
|
||||
endpointVms.push(...(nodeData.vms || []).map(vm => ({
|
||||
...vm,
|
||||
endpointId: endpointId,
|
||||
id: `${endpointId}-${vm.node}-${vm.vmid}`,
|
||||
nodeDisplayName: nodeDisplayName // Use the calculated display name
|
||||
})));
|
||||
endpointContainers.push(...(nodeData.containers || []).map(ct => ({
|
||||
...ct,
|
||||
endpointId: endpointId,
|
||||
id: `${endpointId}-${ct.node}-${ct.vmid}`,
|
||||
nodeDisplayName: nodeDisplayName // Use the calculated display name
|
||||
})));
|
||||
|
||||
if (nodeData.nodeStatus && Object.keys(nodeData.nodeStatus).length > 0) {
|
||||
const statusData = nodeData.nodeStatus;
|
||||
|
||||
@@ -282,7 +282,7 @@ PulseApp.ui.dashboard = (() => {
|
||||
uniqueId: guestUniqueId,
|
||||
vmid: guest.vmid,
|
||||
name: guest.name || `${guest.type === 'qemu' ? GUEST_TYPE_VM : GUEST_TYPE_CT} ${guest.vmid}`,
|
||||
node: guest.node,
|
||||
node: guest.nodeDisplayName || guest.node, // Use display name if available
|
||||
type: guest.type === 'qemu' ? GUEST_TYPE_VM : GUEST_TYPE_CT,
|
||||
status: guest.status,
|
||||
cpu: avgCpu,
|
||||
|
||||
@@ -64,7 +64,7 @@ PulseApp.ui.nodes = (() => {
|
||||
<span class="capitalize">${statusText}</span>
|
||||
</span>
|
||||
</td>
|
||||
<td class="p-1 px-2 whitespace-nowrap overflow-hidden text-ellipsis max-w-0 text-gray-900 dark:text-gray-100" title="${node.node || 'N/A'}">${node.node || 'N/A'}</td>
|
||||
<td class="p-1 px-2 whitespace-nowrap overflow-hidden text-ellipsis max-w-0 text-gray-900 dark:text-gray-100" title="${node.displayName || node.node || 'N/A'}">${node.displayName || node.node || 'N/A'}</td>
|
||||
<td class="p-1 px-2 min-w-[200px]">${cpuBarHTML}</td>
|
||||
<td class="p-1 px-2 min-w-[200px]">${memoryBarHTML}</td>
|
||||
<td class="p-1 px-2 min-w-[200px]">${diskBarHTML}</td>
|
||||
@@ -99,7 +99,7 @@ PulseApp.ui.nodes = (() => {
|
||||
|
||||
card.innerHTML = `
|
||||
<div class="flex justify-between items-center">
|
||||
<h3 class="text-sm font-semibold text-gray-800 dark:text-gray-200 truncate" title="${node.node || 'N/A'}">${node.node || 'N/A'}</h3>
|
||||
<h3 class="text-sm font-semibold text-gray-800 dark:text-gray-200 truncate" title="${node.displayName || node.node || 'N/A'}">${node.displayName || node.node || 'N/A'}</h3>
|
||||
<div class="flex items-center">
|
||||
<span class="h-2.5 w-2.5 rounded-full ${statusColor} mr-1.5 flex-shrink-0"></span>
|
||||
<span class="text-xs capitalize text-gray-600 dark:text-gray-400">${statusText}</span>
|
||||
@@ -237,7 +237,7 @@ PulseApp.ui.nodes = (() => {
|
||||
<div class="flex items-center justify-between gap-2">
|
||||
<div class="flex items-center min-w-0">
|
||||
<span class="h-2 w-2 rounded-full ${statusDotColor} mr-1.5 flex-shrink-0"></span>
|
||||
<h3 class="font-semibold text-xs truncate">${node.node || 'Unknown'}</h3>
|
||||
<h3 class="font-semibold text-xs truncate">${node.displayName || node.node || 'Unknown'}</h3>
|
||||
</div>
|
||||
<div class="flex items-center gap-3 text-[10px] text-gray-600 dark:text-gray-400">
|
||||
<span class="flex items-center gap-1">
|
||||
|
||||
@@ -814,7 +814,24 @@ PulseApp.ui.settings = (() => {
|
||||
|
||||
// Count only actual endpoint divs (not the empty state)
|
||||
const existingEndpoints = container.querySelectorAll('.border:not(.border-dashed)');
|
||||
const index = existingEndpoints.length + 2; // Start from _2 for additional endpoints
|
||||
|
||||
// Find the next available index by checking existing endpoints
|
||||
let index = 2;
|
||||
const usedIndexes = new Set();
|
||||
existingEndpoints.forEach(endpoint => {
|
||||
const header = endpoint.querySelector('h4');
|
||||
if (header) {
|
||||
const match = header.textContent.match(/#(\d+)/);
|
||||
if (match) {
|
||||
usedIndexes.add(parseInt(match[1]));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Find the first unused index starting from 2
|
||||
while (usedIndexes.has(index)) {
|
||||
index++;
|
||||
}
|
||||
const endpointHtml = `
|
||||
<div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4 mb-4 relative">
|
||||
<button type="button" onclick="PulseApp.ui.settings.removeEndpoint(this)"
|
||||
@@ -876,7 +893,24 @@ PulseApp.ui.settings = (() => {
|
||||
|
||||
// Count only actual endpoint divs (not the empty state)
|
||||
const existingEndpoints = container.querySelectorAll('.border:not(.border-dashed)');
|
||||
const index = existingEndpoints.length + 2; // Start from _2 for additional endpoints
|
||||
|
||||
// Find the next available index by checking existing endpoints
|
||||
let index = 2;
|
||||
const usedIndexes = new Set();
|
||||
existingEndpoints.forEach(endpoint => {
|
||||
const header = endpoint.querySelector('h4');
|
||||
if (header) {
|
||||
const match = header.textContent.match(/#(\d+)/);
|
||||
if (match) {
|
||||
usedIndexes.add(parseInt(match[1]));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
// Find the first unused index starting from 2
|
||||
while (usedIndexes.has(index)) {
|
||||
index++;
|
||||
}
|
||||
const endpointHtml = `
|
||||
<div class="border border-gray-200 dark:border-gray-700 rounded-lg p-4 mb-4 relative">
|
||||
<button type="button" onclick="PulseApp.ui.settings.removeEndpoint(this)"
|
||||
@@ -942,7 +976,17 @@ PulseApp.ui.settings = (() => {
|
||||
if (!container) return;
|
||||
|
||||
// Load additional PVE endpoints from config
|
||||
for (let i = 2; i <= 10; i++) {
|
||||
// Find all PROXMOX_HOST_N keys in the config
|
||||
const pveHostKeys = Object.keys(config)
|
||||
.filter(key => key.match(/^PROXMOX_HOST_\d+$/))
|
||||
.map(key => {
|
||||
const match = key.match(/^PROXMOX_HOST_(\d+)$/);
|
||||
return match ? parseInt(match[1]) : null;
|
||||
})
|
||||
.filter(num => num !== null && num > 1) // Exclude primary endpoint (no suffix)
|
||||
.sort((a, b) => a - b);
|
||||
|
||||
for (const i of pveHostKeys) {
|
||||
if (config[`PROXMOX_HOST_${i}`]) {
|
||||
addPveEndpoint();
|
||||
// Populate the newly added endpoint with data
|
||||
@@ -968,7 +1012,17 @@ PulseApp.ui.settings = (() => {
|
||||
if (!container) return;
|
||||
|
||||
// Load additional PBS endpoints from config
|
||||
for (let i = 2; i <= 10; i++) {
|
||||
// Find all PBS_HOST_N keys in the config
|
||||
const pbsHostKeys = Object.keys(config)
|
||||
.filter(key => key.match(/^PBS_HOST_\d+$/))
|
||||
.map(key => {
|
||||
const match = key.match(/^PBS_HOST_(\d+)$/);
|
||||
return match ? parseInt(match[1]) : null;
|
||||
})
|
||||
.filter(num => num !== null && num > 1) // Exclude primary endpoint (no suffix)
|
||||
.sort((a, b) => a - b);
|
||||
|
||||
for (const i of pbsHostKeys) {
|
||||
if (config[`PBS_HOST_${i}`]) {
|
||||
addPbsEndpoint();
|
||||
// Populate the newly added endpoint with data
|
||||
|
||||
Reference in New Issue
Block a user