feat: add labels to nodes in monitoring
This commit is contained in:
@@ -361,7 +361,7 @@ class MonitoringViewComponent extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
renderNodeCard(nodeData) {
|
renderNodeCard(nodeData) {
|
||||||
const { ip, hostname, resources, hasResources, error, resourceSource } = nodeData;
|
const { ip, hostname, resources, hasResources, error, resourceSource, labels } = nodeData;
|
||||||
|
|
||||||
|
|
||||||
if (!hasResources) {
|
if (!hasResources) {
|
||||||
@@ -374,8 +374,21 @@ class MonitoringViewComponent extends Component {
|
|||||||
<div class="node-status">
|
<div class="node-status">
|
||||||
<span class="status-badge error">❌ No Resources</span>
|
<span class="status-badge error">❌ No Resources</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
${labels && Object.keys(labels).length > 0 ? `
|
||||||
|
<div class="node-labels">
|
||||||
|
<div class="labels-container">
|
||||||
|
${Object.entries(labels).map(([key, value]) =>
|
||||||
|
`<span class="label-chip">${key}: ${value}</span>`
|
||||||
|
).join('')}
|
||||||
|
</div>
|
||||||
|
<div class="labels-divider"></div>
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
|
||||||
<div class="node-error">
|
<div class="node-error">
|
||||||
${error || 'Monitoring endpoint not available'}
|
<div class="error-label">⚠️ Error</div>
|
||||||
|
<div class="error-message">${error || 'Monitoring endpoint not available'}</div>
|
||||||
</div>
|
</div>
|
||||||
${nodeData.lastSeen ? `
|
${nodeData.lastSeen ? `
|
||||||
<div class="node-uptime">
|
<div class="node-uptime">
|
||||||
@@ -446,6 +459,17 @@ class MonitoringViewComponent extends Component {
|
|||||||
<span class="status-badge ${resourceSource === 'monitoring' ? 'success' : 'warning'}">${resourceSourceText}</span>
|
<span class="status-badge ${resourceSource === 'monitoring' ? 'success' : 'warning'}">${resourceSourceText}</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
${labels && Object.keys(labels).length > 0 ? `
|
||||||
|
<div class="node-labels">
|
||||||
|
<div class="labels-container">
|
||||||
|
${Object.entries(labels).map(([key, value]) =>
|
||||||
|
`<span class="label-chip">${key}: ${value}</span>`
|
||||||
|
).join('')}
|
||||||
|
</div>
|
||||||
|
<div class="labels-divider"></div>
|
||||||
|
</div>
|
||||||
|
` : ''}
|
||||||
|
|
||||||
${system.uptime_formatted ? `
|
${system.uptime_formatted ? `
|
||||||
<div class="node-uptime">
|
<div class="node-uptime">
|
||||||
<div class="uptime-label">⏱️ Uptime</div>
|
<div class="uptime-label">⏱️ Uptime</div>
|
||||||
@@ -469,7 +493,9 @@ class MonitoringViewComponent extends Component {
|
|||||||
<div class="node-resources">
|
<div class="node-resources">
|
||||||
<div class="resource-item">
|
<div class="resource-item">
|
||||||
<div class="resource-label">⚡ CPU</div>
|
<div class="resource-label">⚡ CPU</div>
|
||||||
<div class="resource-value">${Math.round(cpuUsed)}MHz / ${Math.round(cpuTotal)}MHz</div>
|
<div class="resource-value">
|
||||||
|
<span class="value-label">Used:</span> ${Math.round(cpuUsed)}MHz / <span class="value-label">Total:</span> ${Math.round(cpuTotal)}MHz
|
||||||
|
</div>
|
||||||
<div class="resource-utilization">
|
<div class="resource-utilization">
|
||||||
<div class="utilization-bar">
|
<div class="utilization-bar">
|
||||||
<div class="utilization-fill ${this.getUtilizationColorClass(cpuUtilization)}" style="width: ${cpuUtilization}%"></div>
|
<div class="utilization-fill ${this.getUtilizationColorClass(cpuUtilization)}" style="width: ${cpuUtilization}%"></div>
|
||||||
@@ -480,7 +506,9 @@ class MonitoringViewComponent extends Component {
|
|||||||
|
|
||||||
<div class="resource-item">
|
<div class="resource-item">
|
||||||
<div class="resource-label">🧠 Memory</div>
|
<div class="resource-label">🧠 Memory</div>
|
||||||
<div class="resource-value">${this.viewModel.formatResourceValue(memoryUsed, 'memory')} / ${this.viewModel.formatResourceValue(memoryTotal, 'memory')}</div>
|
<div class="resource-value">
|
||||||
|
<span class="value-label">Used:</span> ${this.viewModel.formatResourceValue(memoryUsed, 'memory')} / <span class="value-label">Total:</span> ${this.viewModel.formatResourceValue(memoryTotal, 'memory')}
|
||||||
|
</div>
|
||||||
<div class="resource-utilization">
|
<div class="resource-utilization">
|
||||||
<div class="utilization-bar">
|
<div class="utilization-bar">
|
||||||
<div class="utilization-fill ${this.getUtilizationColorClass(memoryUtilization)}" style="width: ${memoryUtilization}%"></div>
|
<div class="utilization-fill ${this.getUtilizationColorClass(memoryUtilization)}" style="width: ${memoryUtilization}%"></div>
|
||||||
@@ -491,7 +519,9 @@ class MonitoringViewComponent extends Component {
|
|||||||
|
|
||||||
<div class="resource-item">
|
<div class="resource-item">
|
||||||
<div class="resource-label">💾 Storage</div>
|
<div class="resource-label">💾 Storage</div>
|
||||||
<div class="resource-value">${this.viewModel.formatResourceValue(storageUsed, 'storage')} / ${this.viewModel.formatResourceValue(storageTotal, 'storage')}</div>
|
<div class="resource-value">
|
||||||
|
<span class="value-label">Used:</span> ${this.viewModel.formatResourceValue(storageUsed, 'storage')} / <span class="value-label">Total:</span> ${this.viewModel.formatResourceValue(storageTotal, 'storage')}
|
||||||
|
</div>
|
||||||
<div class="resource-utilization">
|
<div class="resource-utilization">
|
||||||
<div class="utilization-bar">
|
<div class="utilization-bar">
|
||||||
<div class="utilization-fill ${this.getUtilizationColorClass(storageUtilization)}" style="width: ${storageUtilization}%"></div>
|
<div class="utilization-fill ${this.getUtilizationColorClass(storageUtilization)}" style="width: ${storageUtilization}%"></div>
|
||||||
|
|||||||
@@ -4248,10 +4248,49 @@ html {
|
|||||||
font-family: 'Courier New', monospace;
|
font-family: 'Courier New', monospace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.ip-label {
|
||||||
|
color: var(--text-tertiary);
|
||||||
|
font-size: 0.75rem;
|
||||||
|
font-weight: 500;
|
||||||
|
opacity: 0.8;
|
||||||
|
margin-right: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
.node-status {
|
.node-status {
|
||||||
margin-bottom: 0.75rem;
|
margin-bottom: 0.75rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.node-labels {
|
||||||
|
margin-bottom: 0.75rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labels-container {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: 0.35rem;
|
||||||
|
margin-bottom: 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.labels-divider {
|
||||||
|
height: 1px;
|
||||||
|
background: var(--border-primary);
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
opacity: 0.3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.label-chip {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
font-size: 0.75rem;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
border-radius: 9999px;
|
||||||
|
background: rgba(30, 58, 138, 0.35);
|
||||||
|
border: 1px solid rgba(59, 130, 246, 0.4);
|
||||||
|
color: #dbeafe;
|
||||||
|
white-space: nowrap;
|
||||||
|
font-family: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
.node-uptime {
|
.node-uptime {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
@@ -4385,6 +4424,27 @@ html {
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.value-label {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 500;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-label {
|
||||||
|
color: var(--text-secondary);
|
||||||
|
font-size: 0.8rem;
|
||||||
|
font-weight: 500;
|
||||||
|
opacity: 0.8;
|
||||||
|
margin-bottom: 0.25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-message {
|
||||||
|
color: var(--text-primary);
|
||||||
|
font-size: 0.875rem;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
.resource-utilization {
|
.resource-utilization {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|||||||
Reference in New Issue
Block a user