Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 86 additions & 4 deletions js/upload.js
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,23 @@ $(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');
$('#panel-uploadxml-dropfile').removeClass('border-primary');
});
});

/**
* Handles the uploaded XML file
* @param {File} file - The uploaded XML file
*/
function handleXmlFile(file) {
setUploadLoadingState(true);

const reader = new FileReader();

reader.onload = async function (event) {
Expand All @@ -65,25 +75,97 @@ 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');
};

reader.readAsText(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');
$('#xml-upload-status').addClass('d-none').text('');
} 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) {
var fallbackMsg = type === 'success'
? fileName + ' successfully loaded'
: 'Error loading ' + fileName;
showUploadStatus(fallbackMsg, type === 'success' ? 'success' : 'danger');
return;
}

if (!window.bootstrap || !window.bootstrap.Toast) {
var fallbackMsg = type === 'success'
? fileName + ' successfully loaded'
: 'Error loading ' + fileName;
showUploadStatus(fallbackMsg, type === 'success' ? 'success' : 'danger');
return;
}

var translate = (window.elmo && typeof window.elmo.translate === 'function')
? window.elmo.translate
: null;

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';
var successText = translate ? translate('modals.upload.successToast') : null;
messageEl.textContent = fileName + ' ' + (successText || 'successfully loaded');
} else {
toastEl.classList.add('text-bg-danger');
iconEl.className = 'bi bi-exclamation-triangle-fill me-2';
var errorText = translate ? translate('modals.upload.errorToast') : null;
messageEl.textContent = (errorText || 'Error loading file') + ': ' + 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.)
*/
Expand All @@ -102,5 +184,5 @@ function showUploadStatus(message, type) {

// Export for testing
if (typeof module !== 'undefined' && module.exports) {
module.exports = { handleXmlFile, showUploadStatus };
module.exports = { handleXmlFile, showUploadStatus, setUploadLoadingState, showUploadToast };
}
5 changes: 4 additions & 1 deletion lang/de.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 4 additions & 1 deletion lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
5 changes: 4 additions & 1 deletion lang/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
20 changes: 20 additions & 0 deletions modals.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,12 @@ <h5 class="modal-title" id="modal-uploadxml-label">XML hochladen</h5>
<div class="drop-zone mb-3 p-5 border rounded text-center" id="panel-uploadxml-dropfile">
<p class="mb-0" data-translate="modals.upload.dropZoneInfo">Drop XML file here</p>
</div>
<div id="upload-spinner-overlay" class="d-none text-center py-4">
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden" data-translate="modals.upload.loading">Processing file...</span>
</div>
<p class="mt-2 text-muted" aria-hidden="true" data-translate="modals.upload.loading">Processing file...</p>
</div>
<div class="alert alert-info d-none" id="xml-upload-status"></div>
</div>
</div>
Expand Down Expand Up @@ -384,4 +390,18 @@ <h2 class="modal-title fs-5" id="label-feedbackmodal" data-translate="modals.fee
</div>
</div>
</div>
</div>
<!-- Upload Feedback Toast -->
<div class="toast-container position-fixed top-0 end-0 p-3" style="z-index: 1090;" id="toast-upload-container">
<div id="toast-upload-feedback" class="toast align-items-center border-0" role="alert"
aria-live="assertive" aria-atomic="true">
<div class="d-flex">
<div class="toast-body" id="toast-upload-feedback-body">
<i id="toast-upload-feedback-icon" class="bi me-2"></i>
<span id="toast-upload-feedback-message"></span>
</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto"
data-bs-dismiss="toast" aria-label="Close"></button>
</div>
</div>
</div>
Loading
Loading