refactor(tabs): centralize tab wiring in base Component.setupTabs with onChange hook; persist and restore NodeDetails active tab; reuse base tabs in ClusterMembersComponent

This commit is contained in:
2025-08-31 11:06:39 +02:00
parent c0aef5b8d5
commit f18907d9e4
2 changed files with 20 additions and 42 deletions

View File

@@ -571,32 +571,14 @@ class ClusterMembersComponent extends Component {
}
setupTabs(container) {
const tabButtons = container.querySelectorAll('.tab-button');
const tabContents = container.querySelectorAll('.tab-content');
tabButtons.forEach(button => {
this.addEventListener(button, 'click', (e) => {
e.stopPropagation();
const targetTab = button.dataset.tab;
// Use base helper to set active tab
this.setActiveTab(targetTab, container);
// Store active tab state
super.setupTabs(container, {
onChange: (targetTab) => {
const memberCard = container.closest('.member-card');
if (memberCard) {
const memberIp = memberCard.dataset.memberIp;
this.viewModel.storeActiveTab(memberIp, targetTab);
}
});
});
// Also prevent event propagation on tab content areas
tabContents.forEach(content => {
this.addEventListener(content, 'click', (e) => {
e.stopPropagation();
});
}
});
}
@@ -884,6 +866,11 @@ class NodeDetailsComponent extends Component {
this.setHTML('', html);
this.setupTabs();
// 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) {
this.setActiveTab(restored);
}
this.setupFirmwareUpload();
}
@@ -1158,26 +1145,13 @@ class NodeDetailsComponent extends Component {
setupTabs() {
console.log('NodeDetailsComponent: Setting up tabs');
const tabButtons = this.findAllElements('.tab-button');
const tabContents = this.findAllElements('.tab-content');
tabButtons.forEach(button => {
this.addEventListener(button, 'click', (e) => {
e.stopPropagation();
const targetTab = button.dataset.tab;
console.log('NodeDetailsComponent: Tab clicked:', targetTab);
// Update tab UI locally, don't store in view model
this.setActiveTab(targetTab);
});
});
// Also prevent event propagation on tab content areas
tabContents.forEach(content => {
this.addEventListener(content, 'click', (e) => {
e.stopPropagation();
});
super.setupTabs(this.container, {
onChange: (tab) => {
// Persist active tab in the view model for restoration
if (this.viewModel && typeof this.viewModel.setActiveTab === 'function') {
this.viewModel.setActiveTab(tab);
}
}
});
}

View File

@@ -570,7 +570,8 @@ class Component {
}
// Tab helpers
setupTabs(container = this.container) {
setupTabs(container = this.container, options = {}) {
const { onChange } = options;
const tabButtons = container.querySelectorAll('.tab-button');
const tabContents = container.querySelectorAll('.tab-content');
tabButtons.forEach(button => {
@@ -578,6 +579,9 @@ class Component {
e.stopPropagation();
const targetTab = button.dataset.tab;
this.setActiveTab(targetTab, container);
if (typeof onChange === 'function') {
try { onChange(targetTab); } catch (_) {}
}
});
});
tabContents.forEach(content => {