diff --git a/src/css/dvwebloader.css b/src/css/dvwebloader.css index 944e8b4..f61dd34 100644 --- a/src/css/dvwebloader.css +++ b/src/css/dvwebloader.css @@ -104,3 +104,52 @@ h1 { border-width: 2px; border-style: solid; } + +#refreshDataset { + float:right; +} +.button { + font-size:16px; +} + +.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); } +} + +.button-flex-container { + display: flex; + justify-content: space-between; + margin: 10px 0; + min-height: 40px; +} + +.button-left { + display: flex; + align-items: center; +} + +.button-right { + display: flex; + align-items: center; + gap: 10px; /* Space between buttons */ +} \ No newline at end of file diff --git a/src/dvwebloader.html b/src/dvwebloader.html index fc39f9f..536bff3 100644 --- a/src/dvwebloader.html +++ b/src/dvwebloader.html @@ -21,7 +21,13 @@

Folder Upload


- +
+
+ +
+
+
+
diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js index 7687d16..d30c59a 100644 --- a/src/js/fileupload2.js +++ b/src/js/fileupload2.js @@ -1,11 +1,13 @@ import getLocalizedString from './lang.js'; let startUploadsHasBeenCalled = false; +var isRetrievingDatasetInfo = false; var fileList = []; var rawFileMap = {}; var toRegisterFileList = []; var observer2 = null; var numDone = 0; +var numDoneCounter = 0; var delay = 100; //milliseconds var draftExists = false; var UploadState = { @@ -34,18 +36,27 @@ var getUpId = (function() { }; })(); //How many files are completely done -var finishFile = (function() { - var counter = 0; - return function() { - counter += 1; - return counter; - }; -})(); +function finishFile() { + numDoneCounter += 1; + return numDoneCounter; +} + +/** + * Resets the upload state variables and counters + */ +function resetUploadState() { + toRegisterFileList = []; + fileList = []; + curFile = 0; + numDoneCounter = 0; + numDone = 0; + filesInProgress = 0; +} var siteUrl; var datasetPid; var apiKey; -var existingFiles; -var convertedFileNameMap; +var existingFiles = {}; +var convertedFileNameMap = {}; var queryParams; var dvLocale; @@ -61,6 +72,7 @@ $(document).ready(function() { dvLocale = queryParams.get("dvLocale"); console.log('locale: ' + dvLocale); directUploadEnabled = true; + isRetrievingDatasetInfo = true; initTranslation(); addMessage('info', 'msgGettingDatasetInfo'); fetch(siteUrl + "/api/files/fixityAlgorithm") @@ -73,10 +85,14 @@ $(document).ready(function() { } }).then(checksumAlgJson => { checksumAlgName = "MD5"; - if (checksumAlgJson != null) { + if (checksumAlgJson != null && checksumAlgJson.data) { checksumAlgName = checksumAlgJson.data.message; } }) + .catch(error => { + console.log("Error fetching fixity algorithm, using MD5: " + error); + checksumAlgName = "MD5"; + }) .then(() => { var head = document.getElementsByTagName('head')[0]; var js = document.createElement("script"); @@ -113,22 +129,13 @@ $(document).ready(function() { var files = e.target.files; // FileList for (let i = 0; i < files.length; ++i) { let f = files[i]; - console.log('before ' + f.webkitRelativePath); + //console.log('before ' + f.webkitRelativePath); queueFileForDirectUpload(f); 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 +164,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()); @@ -230,7 +255,7 @@ function initSpanTxt(htmlId, key) { function formatMessage(key, keyArgs) { let msg = getLocalizedString(dvLocale, key); - + if(keyArgs && Array.isArray(keyArgs)) { for (var i = 0; i < keyArgs.length; i++) { msg = msg.replaceAll('{'+i+'}', keyArgs[i]); @@ -277,7 +302,17 @@ async function populatePageMetadata(data) { $('#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) { + isRetrievingDatasetInfo = true; + $('#files').prop('disabled', true); + if ($('#upload').length > 0) { + $('#upload').addClass('disabled').prop('disabled', true); + } + addMessage('info', 'msgGettingDatasetInfo'); try { // First, check for dataset locks const locksResponse = await $.ajax({ @@ -297,6 +332,8 @@ async function retrieveDatasetInfo() { if (locksResponse.data && locksResponse.data.length > 0 && !isLockedInReview) { addMessage('error', 'msgDatasetLocked'); disableUploadFunctionality(); + addRefreshButton(); + isRetrievingDatasetInfo = false; return; } @@ -313,6 +350,8 @@ async function retrieveDatasetInfo() { if (!permissionsResponse.data || !permissionsResponse.data.canPublishDataset) { addMessage('error', 'msgDatasetLockedInReview'); disableUploadFunctionality(); + addRefreshButton(); + isRetrievingDatasetInfo = false; return; } } @@ -329,8 +368,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 = {}; @@ -348,7 +388,7 @@ async function retrieveDatasetInfo() { if ('directoryLabel' in entry) { filepath = entry.directoryLabel + '/' + filepath; } - console.log("Storing: " + filepath); + //console.log("Storing: " + filepath); existingFiles[filepath] = df.checksum; if (convertedFile) { convertedFileNameMap[removeExtension(filepath)] = filepath; @@ -356,13 +396,155 @@ async function retrieveDatasetInfo() { } } $('#files').prop('disabled', false); - addMessage('info', 'msgReadyToStart'); + isRetrievingDatasetInfo = false; + if(isInitialLoad || $('#filelist>.ui-fileupload-files').length === 0) { + addMessage('info', 'msgReadyToStart'); + // Add the refresh button after initial load + addRefreshButton(); + } + + // Refresh listed files in case any were selected before this call finished + if ($('#filelist>.ui-fileupload-files .ui-fileupload-row').length > 0) { + refreshListedFileStates(); + } } catch (error) { + isRetrievingDatasetInfo = false; + $('#files').prop('disabled', false); console.log('Error:', error); addMessage('error', 'msgErrorRetrievingDataset'); + } +} + +/** + * Adds a refresh button to the UI + */ +function addRefreshButton() { + if ($('#refreshDataset').length === 0) { + $('#button-container .button-right').append( + $('