From f388b2c395d3fae29295cb8fac45f1c97471496e Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Fri, 6 Jun 2025 12:05:21 -0400 Subject: [PATCH 1/4] add waiting for Dataverse indicator --- src/css/dvwebloader.css | 24 ++++++++++++++++++++++++ src/js/fileupload2.js | 13 +++++++++++-- src/js/lang.js | 2 ++ 3 files changed, 37 insertions(+), 2 deletions(-) diff --git a/src/css/dvwebloader.css b/src/css/dvwebloader.css index 944e8b4..afd62e6 100644 --- a/src/css/dvwebloader.css +++ b/src/css/dvwebloader.css @@ -104,3 +104,27 @@ h1 { border-width: 2px; border-style: solid; } + +.pending { + display: flex; + align-items: center; + padding: 10px; + background-color: #f8f9fa; + border-left: 4px solid #007bff; + margin: 10px 0; +} + +.spinner { + border: 3px solid rgba(0, 0, 0, 0.1); + border-radius: 50%; + border-top: 3px solid #007bff; + width: 20px; + height: 20px; + margin-right: 10px; + animation: spin 1s linear infinite; +} + +@keyframes spin { + 0% { transform: rotate(0deg); } + 100% { transform: rotate(360deg); } +} \ No newline at end of file diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js index 7687d16..481e9d5 100644 --- a/src/js/fileupload2.js +++ b/src/js/fileupload2.js @@ -1020,6 +1020,10 @@ async function directUploadFinished() { console.log(JSON.stringify(body)); let fd = new FormData(); fd.append('jsonData', JSON.stringify(body)); + + // Add a loading indicator before making the AJAX call + $('#messages').append($('
').attr('id', 'loading-indicator').addClass('pending') + .html('
' + formatMessage('msgRegisteringFiles'))); $.ajax({ url: siteUrl + '/api/datasets/:persistentId/addFiles?persistentId=' + datasetPid, headers: { "X-Dataverse-key": apiKey }, @@ -1031,6 +1035,9 @@ async function directUploadFinished() { data: fd, processData: false, success: function(body, statusText, jqXHR) { + // Remove the loading indicator + $('#loading-indicator').remove(); + var datasetUrl = siteUrl + '/dataset.xhtml?persistentId=' + datasetPid + '&version=DRAFT'; console.log("All files sent to " + datasetUrl); if(draftExists) { @@ -1040,10 +1047,12 @@ async function directUploadFinished() { } }, error: function(jqXHR, textStatus, errorThrown) { + // Remove the loading indicator + $('#loading-indicator').remove(); + console.log('Failure: ' + jqXHR.status); console.log('Failure: ' + errorThrown); - addMessage("failure", "msgUploadToDataverseFailed", "Status: " + jqXHR.status + ", Error: " + errorThrown); - //uploadFailure(jqXHR, thisFile); + addMessage("error", "msgUploadToDataverseFailed", "Status: " + jqXHR.status + ", Error: " + errorThrown); } }); //stop observer when we're done diff --git a/src/js/lang.js b/src/js/lang.js index 2d52694..274eb1a 100644 --- a/src/js/lang.js +++ b/src/js/lang.js @@ -14,6 +14,7 @@ const translations = { msgStartUpload: "Checked files will be uploaded.", msgNoFile: "No files to upload. Check some files, or refresh to start over.", msgUploadCompleteRegistering: "Uploads to S3 complete. Now registering all files with the dataset. This may take some time for large numbers of files.", + msgRegisteringFiles: "Waiting for response from Dataverse ...", msgUploadComplete: "Upload complete, all files in dataset. Close this window and refresh your dataset page to see the uploaded files.", msgUploadCompleteNewDraft: "Upload complete, all files in dataset. Close this window, refresh your dataset page, and navigate to the new DRAFT version to see the uploaded files, or click here to open the new draft version in this tab.", msgRequiredPathOrFileNameChange: "The highlighted path/file(s) below contain one or more disallowed characters (paths can only contain a-Z, 0-9, '_', '-', '.', '\', '/' and ' ', and filenames cannot contain any of '/;:|?*#' ). Disallowed characters will be replaced by an underscore ('_') if the file(s) are uploaded.", @@ -41,6 +42,7 @@ const translations = { msgStartUpload: "Les fichiers cochés seront envoyés.", msgNoFile: "Aucun fichier à envoyer. Cochez certains fichiers ou rafraîchissez la page pour recommencer.", msgUploadCompleteRegistering: "Envois vers S3 terminés. Enregistrement de tous les fichiers en cours dans le jeu de données. Cela peut prendre du temps pour un grand nombre de fichiers.", + msgRegisteringFiles: "En attente de réponse de Dataverse ...", msgUploadComplete: "Envoi terminé, tous les fichiers sont dans le jeu de données. Fermez cette fenêtre et rafraîchissez la page de votre jeu de données pour voir les fichiers envoyés.", msgUploadCompleteNewDraft: "Envoi terminé, tous les fichiers sont dans le jeu de données. Fermez cette fenêtre, rafraîchissez la page de votre jeu de données, et accédez à la nouvelle version DRAFT pour voir les fichiers envoyés, ou cliquez ici pour ouvrir la nouvelle version brouillon dans cet onglet.", msgRequiredPathOrFileNameChange: "Le(s) chemin(s) en surbrillance ci-dessous contiennent un ou plusieurs caractères non autorisés (les chemins ne peuvent contenir que a-Z, 0-9, '_', '-', '.', '\', '/' et ' ', et les noms de fichiers ne peuvent contenir aucun des éléments '/;:|?*#' ). Les caractères non autorisés seront remplacés par un trait de soulignement (« _ ») si le(s) fichier(s) sont téléchargés.", From bc253424c589f3753d7ed625eff50daaf2ab5e19 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Fri, 6 Jun 2025 16:58:03 -0400 Subject: [PATCH 2/4] add refresh button --- src/css/dvwebloader.css | 9 +- src/js/fileupload2.js | 194 +++++++++++++++++++++++++++++++--------- src/js/lang.js | 4 + 3 files changed, 163 insertions(+), 44 deletions(-) diff --git a/src/css/dvwebloader.css b/src/css/dvwebloader.css index afd62e6..4e04c3a 100644 --- a/src/css/dvwebloader.css +++ b/src/css/dvwebloader.css @@ -84,7 +84,7 @@ h1 { width: 58%; display:inline-block; } -.button:disabled { +.button.disabled { background: gray; border-color: gray!important; } @@ -105,6 +105,13 @@ h1 { border-style: solid; } +#refreshDataset { + float:right; +} +.button { + font-size:16px; +} + .pending { display: flex; align-items: center; diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js index 481e9d5..bd094d5 100644 --- a/src/js/fileupload2.js +++ b/src/js/fileupload2.js @@ -118,17 +118,8 @@ $(document).ready(function() { console.debug(files[i].webkitRelativePath); // output.innerText = output.innerText + files[i].webkitRelativePath+"\n"; } - let numExists = $('#filelist>.ui-fileupload-files .file-exists').length; let totalFiles = Object.keys(rawFileMap).length; - console.log('exists: ' + numExists); - console.log('rawFileMap len: ' + totalFiles); - if (totalFiles === numExists) { - addMessage('info', 'msgFilesAlreadyExist'); - } else if (numExists !== 0 && totalFiles > numExists) { - addMessage('info', 'msgUploadOnlyCheckedFiles'); - } else ( - addMessage('info', 'msgStartUpload') - ) + updateFileSelectionMessage(); $('label.button').hide(); // Add buttons for selecting/deselecting files $('
') @@ -157,6 +148,24 @@ $(document).ready(function() { }; }); +/** + * Updates the message displayed to the user based on file selection status + */ +function updateFileSelectionMessage() { + let numExists = $('#filelist>.ui-fileupload-files .file-exists').length; + let totalFiles = Object.keys(rawFileMap).length; + console.log('exists: ' + numExists); + console.log('rawFileMap len: ' + totalFiles); + + if (totalFiles === numExists) { + addMessage('info', 'msgFilesAlreadyExist'); + } else if (numExists !== 0 && totalFiles > numExists) { + addMessage('info', 'msgUploadOnlyCheckedFiles'); + } else { + addMessage('info', 'msgStartUpload'); + } +} + function updateMaxFiles() { let maxInput = $('#maxFilesInput'); let maxFiles = parseInt(maxInput.val()); @@ -254,7 +263,6 @@ function addContentWarning(key, ...keyArgs) { async function populatePageMetadata(data) { var mdFields = data.metadataBlocks.citation.fields; var title = ""; - var authors = ""; var datasetUrl = siteUrl + '/dataset.xhtml?persistentId=' + datasetPid; draftExists = data.latestVersionPublishingState && data.latestVersionPublishingState === "DRAFT"; @@ -262,22 +270,17 @@ async function populatePageMetadata(data) { if (mdFields[field].typeName === "title") { title = mdFields[field].value; } - if (mdFields[field].typeName === "author") { - var authorFields = mdFields[field].value; - for (var author in authorFields) { - if (authors.length > 0) { - authors = authors + "; "; - } - authors = authors - + authorFields[author].authorName.value; - } - } } let mdDiv = $('
').append($('

').text(getLocalizedString(dvLocale, 'uploadingTo')).append($('').prop("href", datasetUrl).prop('target', '_blank').text(title))); $('#top').prepend(mdDiv); } -async function retrieveDatasetInfo() { +/** + * Refreshes dataset information from Dataverse + * @param {boolean} isInitialLoad - Whether this is the initial load or a refresh + */ +async function retrieveDatasetInfo(isInitialLoad = true) { + addMessage('info', 'msgGettingDatasetInfo'); try { // First, check for dataset locks const locksResponse = await $.ajax({ @@ -297,6 +300,7 @@ async function retrieveDatasetInfo() { if (locksResponse.data && locksResponse.data.length > 0 && !isLockedInReview) { addMessage('error', 'msgDatasetLocked'); disableUploadFunctionality(); + addRefreshButton(); return; } @@ -313,6 +317,7 @@ async function retrieveDatasetInfo() { if (!permissionsResponse.data || !permissionsResponse.data.canPublishDataset) { addMessage('error', 'msgDatasetLockedInReview'); disableUploadFunctionality(); + addRefreshButton(); return; } } @@ -329,8 +334,9 @@ async function retrieveDatasetInfo() { console.log(datasetResponse); let data = datasetResponse.data; console.log(data); - - populatePageMetadata(data); + if(isInitialLoad) { + populatePageMetadata(data); + } if (data.files !== null) { existingFiles = {}; convertedFileNameMap = {}; @@ -356,12 +362,111 @@ async function retrieveDatasetInfo() { } } $('#files').prop('disabled', false); - addMessage('info', 'msgReadyToStart'); + if(isInitialLoad || $('#filelist>.ui-fileupload-files').length === 0) { + addMessage('info', 'msgReadyToStart'); + // Add the refresh button after initial load + addRefreshButton(); + } } catch (error) { console.log('Error:', error); addMessage('error', 'msgErrorRetrievingDataset'); + } +} + +/** + * Adds a refresh button to the UI + */ +function addRefreshButton() { + if ($('#refreshDataset').length === 0) { + $('