From be4232c359cac5658d896f8171ebef82634682b3 Mon Sep 17 00:00:00 2001 From: Holger Ehrmann Date: Fri, 3 Apr 2026 10:57:01 +0200 Subject: [PATCH 01/17] Added upload notification modal --- js/upload.js | 68 ++++++++++++++++++++++++++++++++++++++++++++++++---- lang/de.json | 5 +++- lang/en.json | 5 +++- lang/fr.json | 5 +++- modals.html | 20 ++++++++++++++++ 5 files changed, 96 insertions(+), 7 deletions(-) diff --git a/js/upload.js b/js/upload.js index f79cb8fa0..49a39bb9e 100644 --- a/js/upload.js +++ b/js/upload.js @@ -44,6 +44,13 @@ $(document).ready(function () { showUploadStatus('Please upload an XML file.', 'danger'); } }); + + // Reset modal state when closed + $('#modal-uploadxml').on('hidden.bs.modal', function () { + $('#input-uploadxml-file').val(''); + setUploadLoadingState(false); + $('#xml-upload-status').addClass('d-none'); + }); }); /** @@ -51,6 +58,8 @@ $(document).ready(function () { * @param {File} file - The uploaded XML file */ function handleXmlFile(file) { + setUploadLoadingState(true); + const reader = new FileReader(); reader.onload = async function (event) { @@ -65,17 +74,20 @@ function handleXmlFile(file) { // Load XML data into form await loadXmlToForm(xmlDoc); - // Close modal and show success message + // Close modal and show success toast + setUploadLoadingState(false); $('#modal-uploadxml').modal('hide'); - showUploadStatus('XML file successfully loaded', 'success'); + showUploadToast(file.name, 'success'); } catch (error) { console.error('Error:', error); + setUploadLoadingState(false); showUploadStatus('Error processing XML file: ' + error.message, 'danger'); } }; reader.onerror = function () { + setUploadLoadingState(false); showUploadStatus('Error reading file', 'danger'); }; @@ -83,7 +95,55 @@ function handleXmlFile(file) { } /** - * Shows upload status message + * Toggles loading state in the upload modal + * @param {boolean} loading - Whether the loading state should be active + */ +function setUploadLoadingState(loading) { + const fileInput = $('#input-uploadxml-file'); + const dropZone = $('#panel-uploadxml-dropfile'); + const spinner = $('#upload-spinner-overlay'); + + if (loading) { + fileInput.prop('disabled', true); + dropZone.addClass('pe-none opacity-50'); + spinner.removeClass('d-none'); + } else { + fileInput.prop('disabled', false); + dropZone.removeClass('pe-none opacity-50'); + spinner.addClass('d-none'); + } +} + +/** + * Shows a Bootstrap toast notification after upload + * @param {string} fileName - The name of the uploaded file + * @param {string} type - 'success' or 'danger' + */ +function showUploadToast(fileName, type) { + const toastEl = document.getElementById('toast-upload-feedback'); + if (!toastEl) return; + + const messageEl = document.getElementById('toast-upload-feedback-message'); + const iconEl = document.getElementById('toast-upload-feedback-icon'); + + toastEl.classList.remove('text-bg-success', 'text-bg-danger'); + + if (type === 'success') { + toastEl.classList.add('text-bg-success'); + iconEl.className = 'bi bi-check-circle-fill me-2'; + messageEl.textContent = fileName + ' successfully loaded'; + } else { + toastEl.classList.add('text-bg-danger'); + iconEl.className = 'bi bi-exclamation-triangle-fill me-2'; + messageEl.textContent = 'Error loading ' + fileName; + } + + var toast = new bootstrap.Toast(toastEl, { delay: 5000 }); + toast.show(); +} + +/** + * Shows upload status message inside the modal * @param {string} message - The message to display * @param {string} type - Bootstrap alert type (success, danger, etc.) */ @@ -102,5 +162,5 @@ function showUploadStatus(message, type) { // Export for testing if (typeof module !== 'undefined' && module.exports) { - module.exports = { handleXmlFile, showUploadStatus }; + module.exports = { handleXmlFile, showUploadStatus, setUploadLoadingState, showUploadToast }; } \ No newline at end of file diff --git a/lang/de.json b/lang/de.json index b4ce69c47..605e41b17 100644 --- a/lang/de.json +++ b/lang/de.json @@ -302,7 +302,10 @@ }, "upload": { "title": "XML-Datei auswählen:", - "dropZoneInfo": "XML-Datei hier ablegen" + "dropZoneInfo": "XML-Datei hier ablegen", + "loading": "Datei wird verarbeitet...", + "successToast": "erfolgreich geladen", + "errorToast": "Fehler beim Laden der Datei" }, "changelog": { "title": "Änderungsprotokoll", diff --git a/lang/en.json b/lang/en.json index 6fc03a84e..3c16439a0 100644 --- a/lang/en.json +++ b/lang/en.json @@ -301,7 +301,10 @@ }, "upload": { "title": "Select XML file:", - "dropZoneInfo": "Drop XML file here" + "dropZoneInfo": "Drop XML file here", + "loading": "Processing file...", + "successToast": "successfully loaded", + "errorToast": "Error loading file" }, "changelog": { "title": "Changelog", diff --git a/lang/fr.json b/lang/fr.json index d3be9b150..0a32cc009 100644 --- a/lang/fr.json +++ b/lang/fr.json @@ -299,7 +299,10 @@ }, "upload": { "title": "Sélectionner un fichier XML :", - "dropZoneInfo": "Déposer le fichier XML ici" + "dropZoneInfo": "Déposer le fichier XML ici", + "loading": "Traitement du fichier...", + "successToast": "chargé avec succès", + "errorToast": "Erreur lors du chargement du fichier" }, "changelog": { "title": "Journal des modifications", diff --git a/modals.html b/modals.html index 4271f1e9b..9242f9c64 100644 --- a/modals.html +++ b/modals.html @@ -17,6 +17,12 @@

Drop XML file here

+
+
+ Loading... +
+

Processing file...

+
@@ -384,4 +390,18 @@