feat: introduce overlay dialog component

This commit is contained in:
2025-10-16 22:00:19 +02:00
parent 478d23b805
commit 79a28bae22
7 changed files with 584 additions and 25 deletions

View File

@@ -6,6 +6,9 @@ class FirmwareUploadComponent extends Component {
logger.debug('FirmwareUploadComponent: Constructor called');
logger.debug('FirmwareUploadComponent: Container:', container);
logger.debug('FirmwareUploadComponent: Container ID:', container?.id);
// Initialize overlay dialog
this.overlayDialog = null;
}
setupEventListeners() {
@@ -37,6 +40,9 @@ class FirmwareUploadComponent extends Component {
logger.debug('FirmwareUploadComponent: Mounting...');
// Initialize overlay dialog
this.initializeOverlayDialog();
// Initialize UI state
this.updateFileInfo();
this.updateDeployButton();
@@ -49,6 +55,32 @@ class FirmwareUploadComponent extends Component {
this.updateDeployButton();
}
initializeOverlayDialog() {
// Create overlay container if it doesn't exist
let overlayContainer = document.getElementById('firmware-upload-overlay-dialog');
if (!overlayContainer) {
overlayContainer = document.createElement('div');
overlayContainer.id = 'firmware-upload-overlay-dialog';
overlayContainer.className = 'overlay-dialog';
document.body.appendChild(overlayContainer);
}
// Create and initialize the overlay dialog component
if (!this.overlayDialog) {
const overlayVM = new ViewModel();
this.overlayDialog = new OverlayDialogComponent(overlayContainer, overlayVM, this.eventBus);
this.overlayDialog.mount();
}
}
showConfirmationDialog(options) {
if (!this.overlayDialog) {
this.initializeOverlayDialog();
}
this.overlayDialog.show(options);
}
handleFileSelect(event) {
const file = event.target.files[0];
this.viewModel.setSelectedFile(file);
@@ -59,28 +91,54 @@ class FirmwareUploadComponent extends Component {
const targetNodes = this.viewModel.get('targetNodes');
if (!file) {
alert('Please select a firmware file first.');
this.showConfirmationDialog({
title: 'No File Selected',
message: 'Please select a firmware file first.',
confirmText: 'OK',
cancelText: null,
onConfirm: () => {},
onCancel: null
});
return;
}
if (!targetNodes || targetNodes.length === 0) {
alert('No target nodes available for firmware update.');
this.showConfirmationDialog({
title: 'No Target Nodes',
message: 'No target nodes available for firmware update.',
confirmText: 'OK',
cancelText: null,
onConfirm: () => {},
onCancel: null
});
return;
}
// Show confirmation dialog for deployment
this.showDeploymentConfirmation(file, targetNodes);
}
showDeploymentConfirmation(file, targetNodes) {
const title = 'Deploy Firmware';
const message = `Upload firmware "${file.name}" to ${targetNodes.length} node(s)?<br><br>Target nodes:<br>${targetNodes.map(n => `${n.hostname || n.ip} (${n.ip})`).join('<br>')}<br><br>This will update the firmware on all selected nodes.`;
this.showConfirmationDialog({
title: title,
message: message,
confirmText: 'Deploy',
cancelText: 'Cancel',
onConfirm: () => this.performDeployment(file, targetNodes),
onCancel: () => {}
});
}
async performDeployment(file, targetNodes) {
try {
this.viewModel.startUpload();
// Show progress overlay to block UI interactions
this.showProgressOverlay();
const confirmed = confirm(`Upload firmware to ${targetNodes.length} node(s)?\n\nTarget nodes:\n${targetNodes.map(n => `${n.hostname || n.ip} (${n.ip})`).join('\n')}\n\nThis will update the firmware on all selected nodes.`);
if (!confirmed) {
this.viewModel.completeUpload();
this.hideProgressOverlay();
return;
}
// Show upload progress area
this.showUploadProgress(file, targetNodes);
@@ -95,7 +153,14 @@ class FirmwareUploadComponent extends Component {
} catch (error) {
logger.error('Firmware deployment failed:', error);
alert(`Deployment failed: ${error.message}`);
this.showConfirmationDialog({
title: 'Deployment Failed',
message: `Deployment failed: ${error.message}`,
confirmText: 'OK',
cancelText: null,
onConfirm: () => {},
onCancel: null
});
} finally {
this.viewModel.completeUpload();
this.hideProgressOverlay();