diff --git a/assets/capabilities.png b/assets/capabilities.png index c37b858..7692eb1 100644 Binary files a/assets/capabilities.png and b/assets/capabilities.png differ diff --git a/public/components.js b/public/components.js index 61b8d00..821bc9a 100644 --- a/public/components.js +++ b/public/components.js @@ -872,7 +872,6 @@ class NodeDetailsComponent extends Component {
-

Available API Endpoints:

${nodeStatus.api ? nodeStatus.api.map(endpoint => `
${endpoint.method === 1 ? 'GET' : 'POST'} ${endpoint.uri}
` ).join('') : '
No API endpoints available
'} @@ -907,6 +906,16 @@ class NodeDetailsComponent extends Component { `; } + const total = capabilities.endpoints.length; + let selectedIndex = Number(this.getUIState('capSelectedIndex')); + if (Number.isNaN(selectedIndex) || selectedIndex < 0 || selectedIndex >= total) { + selectedIndex = 0; + } + + const selectorOptions = capabilities.endpoints.map((ep, idx) => { + return ``; + }).join(''); + const items = capabilities.endpoints.map((ep, idx) => { const formId = `cap-form-${idx}`; const resultId = `cap-result-${idx}`; @@ -922,7 +931,7 @@ class NodeDetailsComponent extends Component { `).join('')}
` : '
No parameters
'; return ` -
+
${ep.method} ${ep.uri} @@ -940,12 +949,27 @@ class NodeDetailsComponent extends Component { setTimeout(() => this.setupCapabilitiesEvents(), 0); return ` -

Node Capabilities

+
+ + +
${items}
`; } setupCapabilitiesEvents() { + const selector = this.findElement('#capability-select'); + if (selector) { + this.addEventListener(selector, 'change', (e) => { + const selected = Number(e.target.value); + const items = Array.from(this.findAllElements('.capability-item')); + items.forEach((el, idx) => { + el.style.display = (idx === selected) ? '' : 'none'; + }); + this.setUIState('capSelectedIndex', selected); + }); + } + const buttons = this.findAllElements('.cap-call-btn'); buttons.forEach(btn => { this.addEventListener(btn, 'click', async (e) => { @@ -1029,7 +1053,6 @@ class NodeDetailsComponent extends Component { `).join(''); return ` -

Active Tasks

${tasksHTML} `; } else { diff --git a/public/styles.css b/public/styles.css index ad07fee..6e163a9 100644 --- a/public/styles.css +++ b/public/styles.css @@ -470,7 +470,6 @@ p { .tab-content { display: none; - padding: 1rem 0; } .tab-content.active { @@ -1735,6 +1734,21 @@ p { gap: 0.75rem; } +/* Custom dropdown wrapper and arrow for capability selector */ +.capability-selector { + display: flex; + align-items: center; + gap: 0.5rem; +} + +#capability-select { + padding-right: 2rem; + background-image: url('data:image/svg+xml;utf8,'); + background-repeat: no-repeat; + background-position: right 0.6rem center; + background-size: 12px 12px; +} + .capability-item { background: rgba(0, 0, 0, 0.2); border: 1px solid rgba(255, 255, 255, 0.1);