feat: fresh tabs
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
class NodeDetailsComponent extends Component {
|
||||
constructor(container, viewModel, eventBus) {
|
||||
super(container, viewModel, eventBus);
|
||||
this.suppressLoadingUI = false;
|
||||
}
|
||||
|
||||
setupViewModelListeners() {
|
||||
@@ -31,6 +32,7 @@ class NodeDetailsComponent extends Component {
|
||||
// Handle loading state update
|
||||
handleLoadingUpdate(isLoading) {
|
||||
if (isLoading) {
|
||||
if (this.suppressLoadingUI) return;
|
||||
this.renderLoading('<div class="loading-details">Loading detailed information...</div>');
|
||||
}
|
||||
}
|
||||
@@ -103,6 +105,13 @@ class NodeDetailsComponent extends Component {
|
||||
<button class="tab-button ${activeTab === 'endpoints' ? 'active' : ''}" data-tab="endpoints">Endpoints</button>
|
||||
<button class="tab-button ${activeTab === 'tasks' ? 'active' : ''}" data-tab="tasks">Tasks</button>
|
||||
<button class="tab-button ${activeTab === 'firmware' ? 'active' : ''}" data-tab="firmware">Firmware</button>
|
||||
<button class="tab-refresh-btn" title="Refresh current tab" aria-label="Refresh">
|
||||
<svg class="refresh-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
|
||||
<path d="M1 4v6h6" />
|
||||
<path d="M23 20v-6h-6" />
|
||||
<path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15" />
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="tab-content ${activeTab === 'status' ? 'active' : ''}" id="status-tab">
|
||||
@@ -145,6 +154,7 @@ class NodeDetailsComponent extends Component {
|
||||
|
||||
this.setHTML('', html);
|
||||
this.setupTabs();
|
||||
this.setupTabRefreshButton();
|
||||
// Restore last active tab from view model if available
|
||||
const restored = this.viewModel && typeof this.viewModel.get === 'function' ? this.viewModel.get('activeTab') : null;
|
||||
if (restored) {
|
||||
@@ -153,6 +163,46 @@ class NodeDetailsComponent extends Component {
|
||||
this.setupFirmwareUpload();
|
||||
}
|
||||
|
||||
setupTabRefreshButton() {
|
||||
const btn = this.findElement('.tab-refresh-btn');
|
||||
if (!btn) return;
|
||||
this.addEventListener(btn, 'click', async (e) => {
|
||||
e.stopPropagation();
|
||||
const original = btn.innerHTML;
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = `
|
||||
<svg class="refresh-icon spinning" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16">
|
||||
<path d="M1 4v6h6" />
|
||||
<path d="M23 20v-6h-6" />
|
||||
<path d="M20.49 9A9 9 0 0 0 5.64 5.64L1 10m22 4l-4.64 4.36A9 9 0 0 1 3.51 15" />
|
||||
</svg>
|
||||
`;
|
||||
|
||||
try {
|
||||
const activeTab = (this.viewModel && typeof this.viewModel.get === 'function') ? (this.viewModel.get('activeTab') || 'status') : 'status';
|
||||
const nodeIp = (this.viewModel && typeof this.viewModel.get === 'function') ? this.viewModel.get('nodeIp') : null;
|
||||
this.suppressLoadingUI = true;
|
||||
|
||||
if (activeTab === 'endpoints' && typeof this.viewModel.loadEndpointsData === 'function') {
|
||||
await this.viewModel.loadEndpointsData();
|
||||
} else if (activeTab === 'tasks' && typeof this.viewModel.loadTasksData === 'function') {
|
||||
await this.viewModel.loadTasksData();
|
||||
} else {
|
||||
// status or firmware: refresh core node details
|
||||
if (nodeIp && typeof this.viewModel.loadNodeDetails === 'function') {
|
||||
await this.viewModel.loadNodeDetails(nodeIp);
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
logger.error('Tab refresh failed:', err);
|
||||
} finally {
|
||||
this.suppressLoadingUI = false;
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = original;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
renderEndpointsTab(endpoints) {
|
||||
if (!endpoints || !Array.isArray(endpoints.endpoints) || endpoints.endpoints.length === 0) {
|
||||
return `
|
||||
|
||||
Reference in New Issue
Block a user