diff --git a/public/components.js b/public/components.js index 16b5896..7f077dd 100644 --- a/public/components.js +++ b/public/components.js @@ -452,6 +452,11 @@ class ClusterMembersComponent extends Component { Latency: ${member.latency ? member.latency + 'ms' : 'N/A'} + ${member.labels && Object.keys(member.labels).length ? ` +
+ ${Object.entries(member.labels).map(([key, value]) => `${key}: ${value}`).join('')} +
+ ` : ''}
diff --git a/public/deploy-button-test.html b/public/deploy-button-test.html index 74bcd4a..e45494a 100644 --- a/public/deploy-button-test.html +++ b/public/deploy-button-test.html @@ -147,7 +147,8 @@ ip: `192.168.1.${100 + nodeCount}`, hostname: `TestNode${nodeCount}`, status: 'active', - latency: Math.floor(Math.random() * 50) + 10 + latency: Math.floor(Math.random() * 50) + 10, + labels: nodeCount % 2 === 0 ? { app: 'demo', role: 'worker' } : { device: 'sensor', zone: `Z${nodeCount}` } }; testNodes.push(newNode); displayClusterMembers(); @@ -185,6 +186,7 @@ ${statusIcon} ${statusText}
Latency: ${node.latency}ms
+ ${node.labels ? `
${Object.entries(node.labels).map(([k,v]) => `${k}: ${v}`).join('')}
` : ''} `; }).join(''); diff --git a/public/styles.css b/public/styles.css index 3292a62..a6925fd 100644 --- a/public/styles.css +++ b/public/styles.css @@ -221,6 +221,26 @@ p { z-index: 1; } +/* Labels */ +.member-labels { + display: flex; + flex-wrap: wrap; + gap: 0.35rem; + margin-top: 0.5rem; +} + +.label-chip { + display: inline-flex; + align-items: center; + font-size: 0.75rem; + padding: 0.15rem 0.45rem; + border-radius: 9999px; + background: rgba(255, 255, 255, 0.08); + border: 1px solid rgba(255, 255, 255, 0.15); + color: rgba(255, 255, 255, 0.9); + white-space: nowrap; +} + .member-card::before { content: ''; position: absolute; @@ -2042,4 +2062,49 @@ p { /* Preserve focus ring on active tab */ .tab-button.active:focus-visible { box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.35); +} + +/* Responsive Capability Selector */ +@media (max-width: 768px) { + .capability-selector { + flex-wrap: wrap; + align-items: stretch; + } + #capability-select { + flex: 1 1 100%; + width: 100%; + max-width: 100%; + min-width: 0; + } +} + +@media (max-width: 480px) { + #capability-select { + padding-right: 1.75rem; + background-position: right 0.5rem center; + background-size: 10px 10px; + } +} + +/* Capability header mobile wrapping */ +@media (max-width: 768px) { + .capability-header { + flex-wrap: wrap; + } + .cap-uri { + flex: 1 1 100%; + min-width: 0; + } + .cap-call-btn { + flex: 1 1 100%; + width: 100%; + justify-content: center; + margin-top: 0.5rem; + } +} + +@media (max-width: 480px) { + .cap-call-btn { + padding: 0.35rem 0.75rem; + } } \ No newline at end of file diff --git a/public/test-deploy-button.html b/public/test-deploy-button.html index f3abb19..03129c6 100644 --- a/public/test-deploy-button.html +++ b/public/test-deploy-button.html @@ -169,7 +169,8 @@ ip: `192.168.1.${100 + nodeCount}`, hostname: `TestNode${nodeCount}`, status: 'active', - latency: Math.floor(Math.random() * 50) + 10 + latency: Math.floor(Math.random() * 50) + 10, + labels: nodeCount % 2 === 0 ? { app: 'demo', role: 'worker' } : { device: 'sensor', zone: `Z${nodeCount}` } }; testNodes.push(newNode); displayClusterMembers(); @@ -205,6 +206,7 @@ ${statusIcon} ${statusText}
Latency: ${node.latency}ms
+ ${node.labels ? `
${Object.entries(node.labels).map(([k,v]) => `${k}: ${v}`).join('')}
` : ''} `; }).join('');