feat: capability selection
This commit is contained in:
Binary file not shown.
|
Before Width: | Height: | Size: 314 KiB After Width: | Height: | Size: 212 KiB |
@@ -872,7 +872,6 @@ class NodeDetailsComponent extends Component {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="tab-content ${activeTab === 'endpoints' ? 'active' : ''}" id="endpoints-tab">
|
<div class="tab-content ${activeTab === 'endpoints' ? 'active' : ''}" id="endpoints-tab">
|
||||||
<h4>Available API Endpoints:</h4>
|
|
||||||
${nodeStatus.api ? nodeStatus.api.map(endpoint =>
|
${nodeStatus.api ? nodeStatus.api.map(endpoint =>
|
||||||
`<div class="endpoint-item">${endpoint.method === 1 ? 'GET' : 'POST'} ${endpoint.uri}</div>`
|
`<div class="endpoint-item">${endpoint.method === 1 ? 'GET' : 'POST'} ${endpoint.uri}</div>`
|
||||||
).join('') : '<div class="endpoint-item">No API endpoints available</div>'}
|
).join('') : '<div class="endpoint-item">No API endpoints available</div>'}
|
||||||
@@ -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 `<option value="${idx}" ${idx === selectedIndex ? 'selected' : ''}>${ep.method} ${ep.uri}</option>`;
|
||||||
|
}).join('');
|
||||||
|
|
||||||
const items = capabilities.endpoints.map((ep, idx) => {
|
const items = capabilities.endpoints.map((ep, idx) => {
|
||||||
const formId = `cap-form-${idx}`;
|
const formId = `cap-form-${idx}`;
|
||||||
const resultId = `cap-result-${idx}`;
|
const resultId = `cap-result-${idx}`;
|
||||||
@@ -922,7 +931,7 @@ class NodeDetailsComponent extends Component {
|
|||||||
`).join('')}</div>`
|
`).join('')}</div>`
|
||||||
: '<div class="capability-params none">No parameters</div>';
|
: '<div class="capability-params none">No parameters</div>';
|
||||||
return `
|
return `
|
||||||
<div class="capability-item" data-cap-index="${idx}">
|
<div class="capability-item" data-cap-index="${idx}" style="display:${idx === selectedIndex ? '' : 'none'};">
|
||||||
<div class="capability-header">
|
<div class="capability-header">
|
||||||
<span class="cap-method">${ep.method}</span>
|
<span class="cap-method">${ep.method}</span>
|
||||||
<span class="cap-uri">${ep.uri}</span>
|
<span class="cap-uri">${ep.uri}</span>
|
||||||
@@ -940,12 +949,27 @@ class NodeDetailsComponent extends Component {
|
|||||||
setTimeout(() => this.setupCapabilitiesEvents(), 0);
|
setTimeout(() => this.setupCapabilitiesEvents(), 0);
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<h4>Node Capabilities</h4>
|
<div class="capability-selector">
|
||||||
|
<label class="param-name" for="capability-select">Capability</label>
|
||||||
|
<select id="capability-select" class="param-input">${selectorOptions}</select>
|
||||||
|
</div>
|
||||||
<div class="capabilities-list">${items}</div>
|
<div class="capabilities-list">${items}</div>
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
|
|
||||||
setupCapabilitiesEvents() {
|
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');
|
const buttons = this.findAllElements('.cap-call-btn');
|
||||||
buttons.forEach(btn => {
|
buttons.forEach(btn => {
|
||||||
this.addEventListener(btn, 'click', async (e) => {
|
this.addEventListener(btn, 'click', async (e) => {
|
||||||
@@ -1029,7 +1053,6 @@ class NodeDetailsComponent extends Component {
|
|||||||
`).join('');
|
`).join('');
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<h4>Active Tasks</h4>
|
|
||||||
${tasksHTML}
|
${tasksHTML}
|
||||||
`;
|
`;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -470,7 +470,6 @@ p {
|
|||||||
|
|
||||||
.tab-content {
|
.tab-content {
|
||||||
display: none;
|
display: none;
|
||||||
padding: 1rem 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.tab-content.active {
|
.tab-content.active {
|
||||||
@@ -1735,6 +1734,21 @@ p {
|
|||||||
gap: 0.75rem;
|
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,<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="%23ecf0f1" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M6 9l6 6 6-6"/></svg>');
|
||||||
|
background-repeat: no-repeat;
|
||||||
|
background-position: right 0.6rem center;
|
||||||
|
background-size: 12px 12px;
|
||||||
|
}
|
||||||
|
|
||||||
.capability-item {
|
.capability-item {
|
||||||
background: rgba(0, 0, 0, 0.2);
|
background: rgba(0, 0, 0, 0.2);
|
||||||
border: 1px solid rgba(255, 255, 255, 0.1);
|
border: 1px solid rgba(255, 255, 255, 0.1);
|
||||||
|
|||||||
Reference in New Issue
Block a user