feat: introduce global config dialog

This commit is contained in:
2025-10-18 10:41:54 +02:00
parent 07be307035
commit f73dd4d0e9
6 changed files with 788 additions and 4 deletions

View File

@@ -53,6 +53,9 @@ class ClusterViewComponent extends Component {
// Set up deploy button event listener
this.setupDeployButton();
// Set up config button event listener
this.setupConfigButton();
// Initialize overlay dialog
this.initializeOverlayDialog();
@@ -112,6 +115,23 @@ class ClusterViewComponent extends Component {
}
}
setupConfigButton() {
logger.debug('ClusterViewComponent: Setting up config button...');
const configBtn = this.findElement('#config-wifi-btn');
logger.debug('ClusterViewComponent: Found config button:', !!configBtn, configBtn);
if (configBtn) {
logger.debug('ClusterViewComponent: Adding click event listener to config button');
this.addEventListener(configBtn, 'click', this.handleConfig.bind(this));
logger.debug('ClusterViewComponent: Event listener added successfully');
} else {
logger.error('ClusterViewComponent: Config button not found!');
logger.debug('ClusterViewComponent: Container HTML:', this.container.innerHTML);
logger.debug('ClusterViewComponent: All buttons in container:', this.container.querySelectorAll('button'));
}
}
initializeOverlayDialog() {
// Create overlay container if it doesn't exist
let overlayContainer = document.getElementById('cluster-overlay-dialog');
@@ -160,6 +180,28 @@ class ClusterViewComponent extends Component {
this.openFirmwareUploadDrawer(filteredMembers);
}
async handleConfig() {
logger.debug('ClusterViewComponent: Config button clicked, opening WiFi config drawer...');
// Get current filtered members from cluster members component
const filteredMembers = this.clusterMembersComponent ? this.clusterMembersComponent.getFilteredMembers() : [];
if (!filteredMembers || filteredMembers.length === 0) {
this.showConfirmationDialog({
title: 'No Nodes Available',
message: 'No nodes available for WiFi configuration. Please ensure cluster members are loaded and visible.',
confirmText: 'OK',
cancelText: null,
onConfirm: () => {},
onCancel: null
});
return;
}
// Open drawer with WiFi configuration interface
this.openWiFiConfigDrawer(filteredMembers);
}
openFirmwareUploadDrawer(targetNodes) {
logger.debug('ClusterViewComponent: Opening firmware upload drawer for', targetNodes.length, 'nodes');
@@ -255,6 +297,81 @@ class ClusterViewComponent extends Component {
}, true); // Hide terminal button for firmware upload
}
openWiFiConfigDrawer(targetNodes) {
logger.debug('ClusterViewComponent: Opening WiFi config drawer for', targetNodes.length, 'nodes');
// Get display name for drawer title
const nodeCount = targetNodes.length;
const displayName = `Configuration - ${nodeCount} node${nodeCount !== 1 ? 's' : ''}`;
// Open drawer with content callback (hide terminal button for WiFi config)
this.clusterMembersComponent.drawer.openDrawer(displayName, (contentContainer, setActiveComponent) => {
// Create WiFi config view model and component
const wifiConfigVM = new WiFiConfigViewModel();
wifiConfigVM.setTargetNodes(targetNodes);
// Create HTML for WiFi configuration interface
contentContainer.innerHTML = `
<div class="wifi-config-drawer">
<div class="tabs-container">
<div class="tabs-header">
<button class="tab-button active" data-tab="wifi">WiFi</button>
</div>
<div class="tab-content active" id="wifi-tab">
<div class="wifi-config-section">
<div class="wifi-form">
<div class="form-group">
<label for="wifi-ssid">SSID (Network Name)</label>
<input type="text" id="wifi-ssid" placeholder="Enter WiFi network name" required>
</div>
<div class="form-group">
<label for="wifi-password">Password</label>
<input type="password" id="wifi-password" placeholder="Enter WiFi password" required>
</div>
<div class="wifi-divider"></div>
<div class="affected-nodes-info">
<div class="nodes-count">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" width="16" height="16" style="margin-right:6px; vertical-align: -2px;">
<path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
<path d="M23 21v-2a4 4 0 0 0-3-3.87"/>
<path d="M16 3.13a4 4 0 0 1 0 7.75"/>
</svg>
Affected Nodes: <span id="affected-nodes-count">${targetNodes.length}</span>
</div>
</div>
<div class="wifi-actions">
<button class="config-btn" id="apply-wifi-config" disabled>
Apply
</button>
</div>
</div>
<div id="wifi-progress-container">
<!-- Progress will be shown here during configuration -->
</div>
</div>
</div>
</div>
</div>
`;
// Create and mount WiFi config component
const wifiConfigComponent = new WiFiConfigComponent(contentContainer, wifiConfigVM, this.eventBus);
setActiveComponent(wifiConfigComponent);
wifiConfigComponent.mount();
}, null, () => {
// Close callback - clear any config state
logger.debug('ClusterViewComponent: WiFi config drawer closed');
}, true); // Hide terminal button for WiFi config
}
async handleRefresh() {
logger.debug('ClusterViewComponent: Refresh button clicked, performing full refresh...');