From 15e12350e9975b7053f5250ab8e44f9327b2ffbc Mon Sep 17 00:00:00 2001 From: qqmyers Date: Tue, 28 Feb 2023 17:35:31 -0500 Subject: [PATCH 01/10] a11y changes and site logo add
, single

, lang='en' (placeholder until i18n), DOCTYPE to stop chrome 'quirk mode' warning in console With these Axe gives no issues, at least prior to loading files. i18n should be able to follow the previewers model using i18n.js, etc. Note the locale param is dvLocale. Also need a blank placeholder logo for when a site doesn't have one. Possibly could use site name in title as well? --- src/css/dvwebloader.css | 14 ++++++++++- src/dvwebloader.html | 47 +++++++++++++++++++++--------------- src/js/fileupload2.js | 53 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 93 insertions(+), 21 deletions(-) diff --git a/src/css/dvwebloader.css b/src/css/dvwebloader.css index 9a13d78..a413c03 100644 --- a/src/css/dvwebloader.css +++ b/src/css/dvwebloader.css @@ -54,4 +54,16 @@ label { } #help { float:right; -} \ No newline at end of file +} +#logo { + display: inline-block; + margin: 10px 10px 10px 40px; + width: 240px; + min-height: 120px; + vertical-align: middle; +} +h1 { + text-align: center; + width: 58%; + display:inline-block; +} diff --git a/src/dvwebloader.html b/src/dvwebloader.html index fa2cee3..47eb4f5 100644 --- a/src/dvwebloader.html +++ b/src/dvwebloader.html @@ -1,4 +1,5 @@ - + + Dataverse WebLoader @@ -8,25 +9,33 @@ - -
-
-
-
-
DVWebloader v0.2, development sponsored by UiT/DataverseNO
- + input.onchange = function (e) { + var files = e.target.files; // FileList + for (let i = 0; i < files.length; ++i) { + let f = files[i]; + queueFileForDirectUpload(f); + console.debug(files[i].webkitRelativePath); + // output.innerText = output.innerText + files[i].webkitRelativePath+"\n"; + } + }; + +

diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js index 63cb9ee..049a479 100644 --- a/src/js/fileupload2.js +++ b/src/js/fileupload2.js @@ -47,6 +47,7 @@ $(document).ready(function () { queryParams = new URLSearchParams(window.location.search.substring(1)); siteUrl = queryParams.get("siteUrl"); console.log(siteUrl); + addIconAndLogo(siteUrl); datasetPid = queryParams.get("datasetPid"); console.log('PID: ' + datasetPid); apiKey = queryParams.get("key"); @@ -77,6 +78,56 @@ $(document).ready(function () { $('label.button').hide(); }; }); + +function addIconAndLogo(siteUrl) { + // Add favicon from source Dataverse + $('head') + .append( + $('') + .attr('sizes', '180x180') + .attr('rel', 'apple-touch-icon') + .attr( + 'href', + queryParams.get("siteUrl") + + '/javax.faces.resource/images/fav/apple-touch-icon.png.xhtml')) + .append( + $('') + .attr('type', 'image/png') + .attr('sizes', '16x16') + .attr('rel', 'icon') + .attr( + 'href', + queryParams.get("siteUrl") + + '/javax.faces.resource/images/fav/favicon-16x16.png.xhtml')) + .append( + $('') + .attr('type', 'image/png') + .attr('sizes', '32x32') + .attr('rel', 'icon') + .attr( + 'href', + queryParams.get("siteUrl") + + '/javax.faces.resource/images/fav/favicon-32x32.png.xhtml')) + + .append( + $('') + .attr('color', '#da532c') + .attr('rel', 'mask-icon') + .attr( + 'href', + queryParams.get("siteUrl") + + '/javax.faces.resource/images/fav/safari-pinned-tab.svg.xhtml')) + .append( + $('') + .attr('content', '#da532c') + .attr('name', 'msapplication-TileColor')) + .append( + $('') + .attr('content', '#ffffff') + .attr('name', 'theme-color')); + $('#logo').attr('src', queryParams.get("siteUrl") + '/logos/preview_logo.png'); + +} function addMessage(type, text) { $('#messages').html('').append($('
').addClass(type).text(text)); } @@ -106,7 +157,7 @@ async function populatePageMetadata(data) { } } } - let mdDiv = $('
').append($('

').text("Uploading to ").append($('').prop("href", datasetUrl).prop('target', '_blank').text(title))); + let mdDiv = $('
').append($('

').text("Uploading to ").append($('').prop("href", datasetUrl).prop('target', '_blank').text(title))); $('#top').prepend(mdDiv); } From dc36916b7c128c0404099b52d51b34fa7d9f6415 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Tue, 28 Mar 2023 10:07:48 -0400 Subject: [PATCH 02/10] fix wiki link --- src/dvwebloader.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/dvwebloader.html b/src/dvwebloader.html index 47eb4f5..8263de8 100644 --- a/src/dvwebloader.html +++ b/src/dvwebloader.html @@ -13,7 +13,7 @@
From 4d14e3f639e1dde06f646e26df2e261078d03c24 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Tue, 7 Mar 2023 17:03:05 -0500 Subject: [PATCH 03/10] fix typo, reformat --- src/dvwebloader.html | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/dvwebloader.html b/src/dvwebloader.html index 8263de8..3a4fd2a 100644 --- a/src/dvwebloader.html +++ b/src/dvwebloader.html @@ -11,27 +11,31 @@
- +

Folder Upload


-
+
+
-
DVWebloader v0.2, development sponsored by UiT/DataverseNO
+
+ DVWebloader v0.2, development sponsored by UiT/DataverseNO +
From 1c0c13c46a0807b2dd91aad9c95ae1652b220ed4 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Wed, 8 Mar 2023 09:08:13 -0500 Subject: [PATCH 04/10] support other checksum algorithms for v5.14+ --- src/js/fileupload2.js | 72 +++++++++++++++++++++++++++++++------------ 1 file changed, 52 insertions(+), 20 deletions(-) diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js index 049a479..badc870 100644 --- a/src/js/fileupload2.js +++ b/src/js/fileupload2.js @@ -16,6 +16,9 @@ var UploadState = { //true indicates direct upload is being used, but cancel may set it back to false at which point direct upload functions should not do further work var directUploadEnabled = false; var directUploadReport = true; + +var checksumAlgName; + //How many files have started being processed but aren't yet being uploaded var filesInProgress = 0; //The # of the current file being processed (total number of files for which upload has at least started) @@ -54,7 +57,23 @@ $(document).ready(function () { console.log(apiKey); directUploadEnabled = true; addMessage('info', 'Getting Dataset Information...'); + fetch("api/files/fixityAlgorithm") + .then((response) => { + if (!response.ok) { + console.log("Did not get fixityAlgorithm from Dataverse, using MD5"); + return null; + } else { + return response.json(); + } + }).then(checksumAlgJson => { + checksumAlgName = "MD5"; + if (checksumAlgJson != null) { + checksumAlgName = checksumAlgJson.data.message; + } + }) + .then(() => { retrieveDatasetInfo(); + }); var input = document.getElementById('files'); input.onchange = function (e) { var files = e.target.files; // FileList @@ -397,7 +416,6 @@ var fileUpload = class fileUploadClass { }, xhr: function () { var myXhr = $.ajaxSettings.xhr(); -//var myXhr = new window.XMLHttpRequest(); if (myXhr.upload) { myXhr.upload.addEventListener('progress', function (e) { if (e.lengthComputable) { @@ -526,17 +544,17 @@ var fileUpload = class fileUploadClass { this.state = UploadState.UPLOADED; console.log('S3 Upload complete for ' + this.file.name + ' : ' + this.storageId); if (directUploadReport) { - this.hashAlg = 'MD5'; - getMD5(this.file, prog => { + + getChecksum(this.file, prog => { var current = 1 + prog; $('[upid="' + this.id + '"] progress').attr({ value: current, max: 2 }); - }).then(md5 => { - console.log('md5 done'); - this.hashVal = md5; - this.handleDirectUpload(md5); + }).then(checksum => { + console.log('checksum done'); + this.hashVal = checksum; + this.handleDirectUpload(); }, err => console.error(err)); } else { console.log("Abandoned: " + this.storageId); @@ -583,20 +601,14 @@ var fileUpload = class fileUploadClass { }); } - async handleDirectUpload(md5) { + async handleDirectUpload() { this.state = UploadState.HASHED; //Wait for each call to finish and update the DOM - console.log('handling'); while (inDataverseCall === true) { await sleep(delay); } - console.log('handling2'); toRegisterFileList.push(this); directUploadFinished(); - //inDataverseCall = true; - //storageId is not the location - has a : separator and no path elements from dataset - //(String uploadComponentId, String fullStorageIdentifier, String fileName, String contentType, String checksumType, String checksumValue) - //handleExternalUpload([{ name: 'uploadComponentId', value: 'datasetForm:fileUpload' }, { name: 'fullStorageIdentifier', value: this.storageId },{ name: 'fileName', value: this.file.name }, { name: 'contentType', value: this.file.type }, { name: 'checksumType', value: 'MD5' }, { name: 'checksumValue', value: md5 }]); } } ; @@ -711,6 +723,9 @@ function removeErrors() { } var observer = null; + +// uploadStarted and uploadFinished are not related to direct upload. +// They deal with clearing old errors and watching for new ones and then signaling when all uploads are done function uploadStarted() { // If this is not the first upload, remove error messages since // the upload of any files that failed will be tried again. @@ -782,7 +797,7 @@ async function directUploadFinished() { entry.directoryLabel = path; } entry.checksum = {}; - entry.checksum['@type'] = fup.hashAlg; + entry.checksum['@type'] = checksumAlgName; entry.checksum['@value'] = fup.hashVal; entry.mimeType = fup.file.type; if (entry.mimeType === '') { @@ -942,12 +957,29 @@ function readChunked(file, chunkCallback, endCallback) { } readNext(); } +function getChecksum(blob, cbProgress) { + return new Promise((resolve, reject) => { -function getMD5(blob, cbProgress) { - return new Promise((resolve, reject) => { - var md5 = CryptoJS.algo.MD5.create(); + var checksumAlg; + switch (checksumAlgName) { + case 'MD5': + checksumAlg = CryptoJS.algo.MD5.create(); + break; + case 'SHA-1': + checksumAlg = CryptoJS.algo.SHA1.create(); + break; + case 'SHA-256': + checksumAlg = CryptoJS.algo.SHA256.create(); + break; + case 'SHA-512': + checksumAlg = CryptoJS.algo.SHA512.create(); + break; + default: + console.log('$(checksumAlgName) is not supported, using MD5 as the checksumAlg checksum Algorithm'); + checksumAlg = CryptoJS.algo.MD5.create(); + } readChunked(blob, (chunk, offs, total) => { - md5.update(CryptoJS.enc.Latin1.parse(chunk)); + checksumAlg.update(CryptoJS.enc.Latin1.parse(chunk)); if (cbProgress) { cbProgress(offs / total); } @@ -956,7 +988,7 @@ function getMD5(blob, cbProgress) { reject(err); } else { // TODO: Handle errors - var hash = md5.finalize(); + var hash = checksumAlg.finalize(); var hashHex = hash.toString(CryptoJS.enc.Hex); resolve(hashHex); } From 50b17bdd059c1dc07eee9be8c530929b56dc1a78 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Wed, 8 Mar 2023 09:58:19 -0500 Subject: [PATCH 05/10] fix fixityalg url, dynamically load 4.0.0 crypto scripts, reformat --- src/dvwebloader.html | 4 +- src/js/fileupload2.js | 325 +++++++++++++++++++++++------------------- 2 files changed, 178 insertions(+), 151 deletions(-) diff --git a/src/dvwebloader.html b/src/dvwebloader.html index 3a4fd2a..4ceffec 100644 --- a/src/dvwebloader.html +++ b/src/dvwebloader.html @@ -13,7 +13,9 @@

Folder Upload

- +

diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js index badc870..4f3230a 100644 --- a/src/js/fileupload2.js +++ b/src/js/fileupload2.js @@ -24,17 +24,17 @@ var filesInProgress = 0; //The # of the current file being processed (total number of files for which upload has at least started) var curFile = 0; //The number of upload ids that have been assigned in the files table -var getUpId = (function () { +var getUpId = (function() { var counter = -1; - return function () { + return function() { counter += 1; return counter; }; })(); //How many files are completely done -var finishFile = (function () { +var finishFile = (function() { var counter = 0; - return function () { + return function() { counter += 1; return counter; }; @@ -46,7 +46,7 @@ var existingFiles; var convertedFileNameMap; var queryParams; -$(document).ready(function () { +$(document).ready(function() { queryParams = new URLSearchParams(window.location.search.substring(1)); siteUrl = queryParams.get("siteUrl"); console.log(siteUrl); @@ -57,25 +57,50 @@ $(document).ready(function () { console.log(apiKey); directUploadEnabled = true; addMessage('info', 'Getting Dataset Information...'); - fetch("api/files/fixityAlgorithm") - .then((response) => { - if (!response.ok) { - console.log("Did not get fixityAlgorithm from Dataverse, using MD5"); - return null; - } else { - return response.json(); - } - }).then(checksumAlgJson => { - checksumAlgName = "MD5"; - if (checksumAlgJson != null) { - checksumAlgName = checksumAlgJson.data.message; - } - }) - .then(() => { - retrieveDatasetInfo(); - }); + fetch(siteUrl + "/api/files/fixityAlgorithm") + .then((response) => { + if (!response.ok) { + console.log("Did not get fixityAlgorithm from Dataverse, using MD5"); + return null; + } else { + return response.json(); + } + }).then(checksumAlgJson => { + checksumAlgName = "MD5"; + if (checksumAlgJson != null) { + checksumAlgName = checksumAlgJson.data.message; + } + }) + .then(() => { + var head = document.getElementsByTagName('head')[0]; + var js = document.createElement("script"); + js.type = "text/javascript"; + + switch (checksumAlgName) { + case 'MD5': + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/md5.js"; + break; + case 'SHA-1': + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/sha1.js"; + break; + case 'SHA-256': + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/sha256.js"; + break; + case 'SHA-512': + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/x64-core.js"; + head.appendChild(js); + js = document.createElement("script"); + js.type = "text/javascript"; + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/sha512.js"; + break; + default: + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/md5.js"; + } + head.appendChild(js); + retrieveDatasetInfo(); + }); var input = document.getElementById('files'); - input.onchange = function (e) { + input.onchange = function(e) { var files = e.target.files; // FileList for (let i = 0; i < files.length; ++i) { let f = files[i]; @@ -91,9 +116,9 @@ $(document).ready(function () { if (totalFiles === numExists) { addMessage('info', 'All files already exist in dataset. There\'s nothing to upload.'); } else - if (numExists !== 0 && totalFiles > numExists) { - addMessage('info', 'Some files already exist in dataset. Only checked files will be uploaded.'); - } + if (numExists !== 0 && totalFiles > numExists) { + addMessage('info', 'Some files already exist in dataset. Only checked files will be uploaded.'); + } $('label.button').hide(); }; }); @@ -101,50 +126,50 @@ $(document).ready(function () { function addIconAndLogo(siteUrl) { // Add favicon from source Dataverse $('head') - .append( - $('') - .attr('sizes', '180x180') - .attr('rel', 'apple-touch-icon') - .attr( - 'href', - queryParams.get("siteUrl") + - '/javax.faces.resource/images/fav/apple-touch-icon.png.xhtml')) - .append( - $('') - .attr('type', 'image/png') - .attr('sizes', '16x16') - .attr('rel', 'icon') - .attr( - 'href', - queryParams.get("siteUrl") + - '/javax.faces.resource/images/fav/favicon-16x16.png.xhtml')) - .append( - $('') - .attr('type', 'image/png') - .attr('sizes', '32x32') - .attr('rel', 'icon') - .attr( - 'href', - queryParams.get("siteUrl") + - '/javax.faces.resource/images/fav/favicon-32x32.png.xhtml')) - - .append( - $('') - .attr('color', '#da532c') - .attr('rel', 'mask-icon') - .attr( - 'href', - queryParams.get("siteUrl") + - '/javax.faces.resource/images/fav/safari-pinned-tab.svg.xhtml')) - .append( - $('') - .attr('content', '#da532c') - .attr('name', 'msapplication-TileColor')) - .append( - $('') - .attr('content', '#ffffff') - .attr('name', 'theme-color')); - $('#logo').attr('src', queryParams.get("siteUrl") + '/logos/preview_logo.png'); + .append( + $('') + .attr('sizes', '180x180') + .attr('rel', 'apple-touch-icon') + .attr( + 'href', + siteUrl + + '/javax.faces.resource/images/fav/apple-touch-icon.png.xhtml')) + .append( + $('') + .attr('type', 'image/png') + .attr('sizes', '16x16') + .attr('rel', 'icon') + .attr( + 'href', + siteUrl + + '/javax.faces.resource/images/fav/favicon-16x16.png.xhtml')) + .append( + $('') + .attr('type', 'image/png') + .attr('sizes', '32x32') + .attr('rel', 'icon') + .attr( + 'href', + siteUrl + + '/javax.faces.resource/images/fav/favicon-32x32.png.xhtml')) + + .append( + $('') + .attr('color', '#da532c') + .attr('rel', 'mask-icon') + .attr( + 'href', + siteUrl + + '/javax.faces.resource/images/fav/safari-pinned-tab.svg.xhtml')) + .append( + $('') + .attr('content', '#da532c') + .attr('name', 'msapplication-TileColor')) + .append( + $('') + .attr('content', '#ffffff') + .attr('name', 'theme-color')); + $('#logo').attr('src', siteUrl + '/logos/preview_logo.png'); } function addMessage(type, text) { @@ -172,7 +197,7 @@ async function populatePageMetadata(data) { authors = authors + "; "; } authors = authors - + authorFields[author].authorName.value; + + authorFields[author].authorName.value; } } } @@ -183,13 +208,13 @@ async function populatePageMetadata(data) { async function retrieveDatasetInfo() { $.ajax({ url: siteUrl + '/api/datasets/:persistentId/versions/:latest?persistentId=' + datasetPid, - headers: {"X-Dataverse-key": apiKey}, + headers: { "X-Dataverse-key": apiKey }, type: 'GET', context: this, cache: false, dataType: "json", processData: false, - success: function (body, statusText, jqXHR) { + success: function(body, statusText, jqXHR) { console.log(body); let data = body.data; console.log(data); @@ -202,9 +227,9 @@ async function retrieveDatasetInfo() { let df = entry.dataFile; let convertedFile = false; if (("originalFileFormat" in df) - && (!df.contentType.equals(df.originalFileFormat))) { + && (!df.contentType.equals(df.originalFileFormat))) { console.log("The file named " + df.getString("filename") - + " on the server was created by Dataverse's ingest process from an original uploaded file"); + + " on the server was created by Dataverse's ingest process from an original uploaded file"); convertedFile = true; } let filepath = df.filename; @@ -221,7 +246,7 @@ async function retrieveDatasetInfo() { $('#files').prop('disabled', false); addMessage('info', 'Ready. Click Select a Directory. Review the selected files. Start Uploads. (Note - selection dialog will not show files, but they will be shown afterwards on the page.) '); }, - error: function (jqXHR, textStatus, errorThrown) { + error: function(jqXHR, textStatus, errorThrown) { console.log('Failure: ' + jqXHR.status); console.log('Failure: ' + errorThrown); } @@ -238,33 +263,33 @@ function setupDirectUpload(enabled) { //Catch files entered via upload dialog box. Since this 'select' widget is replaced by PF, we need to add a listener again when it is replaced var fileInput = document.getElementById('datasetForm:fileUpload_input'); if (fileInput !== null) { - fileInput.addEventListener('change', function (event) { + fileInput.addEventListener('change', function(event) { fileList = []; for (var i = 0; i < fileInput.files.length; i++) { queueFileForDirectUpload(fileInput.files[i]); } - }, {once: false}); + }, { once: false }); } -//Add support for drag and drop. Since the fileUploadForm is not replaced by PF, catching changes with a mutationobserver isn't needed + //Add support for drag and drop. Since the fileUploadForm is not replaced by PF, catching changes with a mutationobserver isn't needed var fileDropWidget = document.getElementById('datasetForm:fileUpload'); - fileDropWidget.addEventListener('drop', function (event) { + fileDropWidget.addEventListener('drop', function(event) { fileList = []; for (var i = 0; i < event.dataTransfer.files.length; i++) { queueFileForDirectUpload(event.dataTransfer.files[i]); } - }, {once: false}); - var config = {childList: true}; - var callback = function (mutations) { - mutations.forEach(function (mutation) { + }, { once: false }); + var config = { childList: true }; + var callback = function(mutations) { + mutations.forEach(function(mutation) { for (i = 0; i < mutation.addedNodes.length; i++) { //Add a listener on any replacement file 'select' widget if (mutation.addedNodes[i].id === 'datasetForm:fileUpload_input') { fileInput = mutation.addedNodes[i]; - mutation.addedNodes[i].addEventListener('change', function (event) { + mutation.addedNodes[i].addEventListener('change', function(event) { for (var j = 0; j < mutation.addedNodes[i].files.length; j++) { queueFileForDirectUpload(mutation.addedNodes[i].files[j]); } - }, {once: false}); + }, { once: false }); } } }); @@ -282,7 +307,7 @@ function sleep(ms) { } async function cancelDatasetCreate() { -//Page is going away - don't upload any more files, finish reporting current uploads, and then call cancelCreateCommand to clean up temp files + //Page is going away - don't upload any more files, finish reporting current uploads, and then call cancelCreateCommand to clean up temp files if (directUploadEnabled) { fileList = []; directUploadEnabled = false; @@ -300,7 +325,7 @@ async function cancelDatasetCreate() { async function cancelDatasetEdit() { -//Don't upload any more files and don't send any more file entries to Dataverse, report any direct upload files that didn't get handled + //Don't upload any more files and don't send any more file entries to Dataverse, report any direct upload files that didn't get handled if (directUploadEnabled) { fileList = []; directUploadEnabled = false; @@ -338,13 +363,13 @@ var fileUpload = class fileUploadClass { async requestDirectUploadUrls() { $.ajax({ url: siteUrl + '/api/datasets/:persistentId/uploadurls?persistentId=' + datasetPid + '&size=' + this.file.size, - headers: {"X-Dataverse-key": apiKey}, + headers: { "X-Dataverse-key": apiKey }, type: 'GET', context: this, cache: false, dataType: "json", processData: false, - success: function (body, statusText, jqXHR) { + success: function(body, statusText, jqXHR) { console.log(body); let data = body.data; console.log(data); @@ -355,7 +380,7 @@ var fileUpload = class fileUploadClass { this.doUpload(); console.log(JSON.stringify(data)); }, - error: function (jqXHR, textStatus, errorThrown) { + error: function(jqXHR, textStatus, errorThrown) { console.log('Failure: ' + jqXHR.status); console.log('Failure: ' + errorThrown); uploadFailure(jqXHR, this.file); @@ -389,7 +414,7 @@ var fileUpload = class fileUploadClass { const progBar = fileNode.find('.ui-fileupload-progress'); const cancelButton = fileNode.find('.ui-fileupload-cancel'); var cancelled = false; - cancelButton.click(function () { + cancelButton.click(function() { cancelled = true; }); progBar.html(''); @@ -397,27 +422,27 @@ var fileUpload = class fileUploadClass { if (this.urls.hasOwnProperty("url")) { $.ajax({ url: this.urls.url, - headers: {"x-amz-tagging": "dv-state=temp"}, + headers: { "x-amz-tagging": "dv-state=temp" }, type: 'PUT', data: this.file, context: this, cache: false, processData: false, - success: function () { + success: function() { //ToDo - cancelling abandons the file. It is marked as temp so can be cleaned up later, but would be good to remove now (requires either sending a presigned delete URL or adding a callback to delete only a temp file if (!cancelled) { this.reportUpload(); } }, - error: function (jqXHR, textStatus, errorThrown) { + error: function(jqXHR, textStatus, errorThrown) { console.log('Failure: ' + jqXHR.status); console.log('Failure: ' + errorThrown); uploadFailure(jqXHR, thisFile); }, - xhr: function () { + xhr: function() { var myXhr = $.ajaxSettings.xhr(); if (myXhr.upload) { - myXhr.upload.addEventListener('progress', function (e) { + myXhr.upload.addEventListener('progress', function(e) { if (e.lengthComputable) { var doublelength = 2 * e.total; progBar.children('progress').attr({ @@ -468,7 +493,7 @@ var fileUpload = class fileUploadClass { context: this, cache: false, processData: false, - success: function (data, status, response) { + success: function(data, status, response) { console.log('Successful upload of part ' + key + ' of ' + Object.keys(this.urls.urls).length); //The header has quotes around the eTag this.etags[key] = response.getResponseHeader('ETag').replace(/["]+/g, ''); @@ -477,7 +502,7 @@ var fileUpload = class fileUploadClass { this.multipartComplete(); } }, - error: function (jqXHR, textStatus, errorThrown) { + error: function(jqXHR, textStatus, errorThrown) { console.log('Failure: ' + jqXHR.status); console.log('Failure: ' + errorThrown); console.log(thisFile + ' : part' + key); @@ -487,10 +512,10 @@ var fileUpload = class fileUploadClass { this.multipartComplete(); } }, - xhr: function () { + xhr: function() { var myXhr = $.ajaxSettings.xhr(); if (myXhr.upload) { - myXhr.upload.addEventListener('progress', function (e) { + myXhr.upload.addEventListener('progress', function(e) { if (e.lengthComputable) { loaded[thisFile][key - 1] = e.loaded; var total = 0; @@ -563,15 +588,15 @@ var fileUpload = class fileUploadClass { async cancelMPUpload() { $.ajax({ url: siteUrl + this.urls.abort, - headers: {"X-Dataverse-key": apiKey}, + headers: { "X-Dataverse-key": apiKey }, type: 'DELETE', context: this, cache: false, processData: false, - success: function () { + success: function() { console.log('Successfully cancelled upload of ' + this.file.name); }, - error: function (jqXHR, textStatus, errorThrown) { + error: function(jqXHR, textStatus, errorThrown) { console.log('Failure: ' + jqXHR.status); console.log('Failure: ' + errorThrown); } @@ -585,16 +610,16 @@ var fileUpload = class fileUploadClass { $.ajax({ url: siteUrl + this.urls.complete, type: 'PUT', - headers: {"X-Dataverse-key": apiKey}, + headers: { "X-Dataverse-key": apiKey }, context: this, data: JSON.stringify(eTagsObject), cache: false, processData: false, - success: function () { + success: function() { console.log('Successfully completed upload of ' + this.file.name); this.reportUpload(); }, - error: function (jqXHR, textStatus, errorThrown) { + error: function(jqXHR, textStatus, errorThrown) { console.log('Failure: ' + jqXHR.status); console.log('Failure: ' + errorThrown); } @@ -611,17 +636,17 @@ var fileUpload = class fileUploadClass { directUploadFinished(); } } -; - function removeExtension(name) { - let extIndex = name.indexOf("."); - let sepIndex = name.indexOf('/'); - if (extIndex > sepIndex) { - return name.substring(0, extIndex); - } else { - return name; - } + ; +function removeExtension(name) { + let extIndex = name.indexOf("."); + let sepIndex = name.indexOf('/'); + if (extIndex > sepIndex) { + return name.substring(0, extIndex); + } else { + return name; + } - } +} function queueFileForDirectUpload(file) { if (fileList.length === 0) { //uploadWidgetDropRemoveMsg(); } @@ -651,9 +676,9 @@ function queueFileForDirectUpload(file) { row.addClass('file-exists'); } row.append($('').prop('type', 'checkbox').prop('id', 'file_' + fileBlock.children().length).prop('checked', send)) - .append($('
').addClass('ui-fileupload-filename').text(path)) - .append($('
').text(file.size)).append($('
').addClass('ui - fileupload - progress')) - .append($('
').addClass('ui - fileupload - cancel')); + .append($('
').addClass('ui-fileupload-filename').text(path)) + .append($('
').text(file.size)).append($('
').addClass('ui - fileupload - progress')) + .append($('
').addClass('ui - fileupload - cancel')); console.log('adding click handler for file_' + fileBlock.children().length); $('#file_' + fileBlock.children().length).click(toggleUpload); } @@ -677,7 +702,7 @@ function toggleUpload() { function startUploads() { $('#top button').remove(); let checked = $('#filelist>.ui-fileupload-files input:checked'); - checked.each(function () { + checked.each(function() { console.log('Name ' + $(this).siblings('.ui-fileupload-filename').text()); let file = rawFileMap[$(this).siblings('.ui-fileupload-filename').text()]; let fUpload = new fileUpload(file); @@ -739,10 +764,10 @@ function uploadStarted() { curId = curId + 1; } //Setup an observer to watch for additional rows being added - var config = {childList: true}; - var callback = function (mutations) { + var config = { childList: true }; + var callback = function(mutations) { //Add an id attribute to all new entries - mutations.forEach(function (mutation) { + mutations.forEach(function(mutation) { for (i = 0; i < mutation.addedNodes.length; i++) { mutation.addedNodes[i].setAttribute('upid', curId); curId = curId + 1; @@ -810,7 +835,7 @@ async function directUploadFinished() { fd.append('jsonData', JSON.stringify(body)); $.ajax({ url: siteUrl + '/api/datasets/:persistentId/addFiles?persistentId=' + datasetPid, - headers: {"X-Dataverse-key": apiKey}, + headers: { "X-Dataverse-key": apiKey }, type: 'POST', enctype: 'multipart/form-data', contentType: false, @@ -818,11 +843,11 @@ async function directUploadFinished() { cache: false, data: fd, processData: false, - success: function (body, statusText, jqXHR) { + success: function(body, statusText, jqXHR) { console.log("All files sent to " + siteUrl + '/dataset.xhtml?persistentId=doi:' + datasetPid + '&version=DRAFT'); addMessage('success', 'Upload complete, all files in dataset. Close this window and refresh your dataset page to see the uploaded files.'); }, - error: function (jqXHR, textStatus, errorThrown) { + error: function(jqXHR, textStatus, errorThrown) { console.log('Failure: ' + jqXHR.status); console.log('Failure: ' + errorThrown); //uploadFailure(jqXHR, thisFile); @@ -933,7 +958,7 @@ function readChunked(file, chunkCallback, endCallback) { var chunkSize = 64 * 1024 * 1024; // 64MB var offset = 0; var reader = new FileReader(); - reader.onload = function () { + reader.onload = function() { if (reader.error) { endCallback(reader.error || {}); return; @@ -948,7 +973,7 @@ function readChunked(file, chunkCallback, endCallback) { } readNext(); }; - reader.onerror = function (err) { + reader.onerror = function(err) { endCallback(err || {}); }; function readNext() { @@ -958,28 +983,28 @@ function readChunked(file, chunkCallback, endCallback) { readNext(); } function getChecksum(blob, cbProgress) { - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { - var checksumAlg; - switch (checksumAlgName) { - case 'MD5': - checksumAlg = CryptoJS.algo.MD5.create(); - break; - case 'SHA-1': - checksumAlg = CryptoJS.algo.SHA1.create(); - break; - case 'SHA-256': - checksumAlg = CryptoJS.algo.SHA256.create(); - break; - case 'SHA-512': - checksumAlg = CryptoJS.algo.SHA512.create(); - break; - default: - console.log('$(checksumAlgName) is not supported, using MD5 as the checksumAlg checksum Algorithm'); - checksumAlg = CryptoJS.algo.MD5.create(); - } + var checksumAlg; + switch (checksumAlgName) { + case 'MD5': + checksumAlg = CryptoJS.algo.MD5.create(); + break; + case 'SHA-1': + checksumAlg = CryptoJS.algo.SHA1.create(); + break; + case 'SHA-256': + checksumAlg = CryptoJS.algo.SHA256.create(); + break; + case 'SHA-512': + checksumAlg = CryptoJS.algo.SHA512.create(); + break; + default: + console.log('$(checksumAlgName) is not supported, using MD5 as the checksumAlg checksum Algorithm'); + checksumAlg = CryptoJS.algo.MD5.create(); + } readChunked(blob, (chunk, offs, total) => { - checksumAlg.update(CryptoJS.enc.Latin1.parse(chunk)); + checksumAlg.update(CryptoJS.enc.Latin1.parse(chunk)); if (cbProgress) { cbProgress(offs / total); } @@ -988,7 +1013,7 @@ function getChecksum(blob, cbProgress) { reject(err); } else { // TODO: Handle errors - var hash = checksumAlg.finalize(); + var hash = checksumAlg.finalize(); var hashHex = hash.toString(CryptoJS.enc.Hex); resolve(hashHex); } From d556a99c074466113309fb11b3ab08f09b9f4a5e Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Wed, 8 Mar 2023 10:33:53 -0500 Subject: [PATCH 06/10] use == where type may be different - line 726 requires it --- src/js/fileupload2.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js index 4f3230a..1c808b7 100644 --- a/src/js/fileupload2.js +++ b/src/js/fileupload2.js @@ -723,7 +723,7 @@ async function uploadFileDirectly(urls, storageId, filesize) { var upload = null; //As long as we have the right file size, we're OK for (i = 0; i < fileList.length; i++) { - if (fileList[i].file.size === filesize) { + if (fileList[i].file.size == filesize) { upload = fileList.splice(i, 1)[0]; break; } @@ -825,7 +825,7 @@ async function directUploadFinished() { entry.checksum['@type'] = checksumAlgName; entry.checksum['@value'] = fup.hashVal; entry.mimeType = fup.file.type; - if (entry.mimeType === '') { + if (entry.mimeType == '') { entry.mimeType = 'application/octet-stream'; } body.push(entry); From 8e41382a02af6267a44eee0631dae0999d24e1d1 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Wed, 8 Mar 2023 10:40:37 -0500 Subject: [PATCH 07/10] bug fixes --- src/js/fileupload2.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js index 1c808b7..a5d269e 100644 --- a/src/js/fileupload2.js +++ b/src/js/fileupload2.js @@ -78,23 +78,23 @@ $(document).ready(function() { switch (checksumAlgName) { case 'MD5': - js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/md5.js"; + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/md5.js"; break; case 'SHA-1': - js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/sha1.js"; + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/sha1.js"; break; case 'SHA-256': - js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/sha256.js"; + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/sha256.js"; break; case 'SHA-512': - js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/x64-core.js"; + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/x64-core.js"; head.appendChild(js); js = document.createElement("script"); js.type = "text/javascript"; - js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/sha512.js"; + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/sha512.js"; break; default: - js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/components/md5.js"; + js.src = "https://cdnjs.cloudflare.com/ajax/libs/crypto-js/4.0.0/md5.js"; } head.appendChild(js); retrieveDatasetInfo(); @@ -580,7 +580,7 @@ var fileUpload = class fileUploadClass { console.log('checksum done'); this.hashVal = checksum; this.handleDirectUpload(); - }, err => console.error(err)); + }).catch(err => console.error(err)); } else { console.log("Abandoned: " + this.storageId); } From 9cfe4bd8106204fb35dd14ca6d480ff4bdb58a3e Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Tue, 28 Mar 2023 10:17:32 -0400 Subject: [PATCH 08/10] fix merge issue --- src/dvwebloader.html | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/dvwebloader.html b/src/dvwebloader.html index 4ceffec..15297f6 100644 --- a/src/dvwebloader.html +++ b/src/dvwebloader.html @@ -4,8 +4,7 @@ Dataverse WebLoader - - + From e3e23c182eac3da54474e9de74baf3b44fe99c07 Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Tue, 28 Mar 2023 10:27:41 -0400 Subject: [PATCH 09/10] remove console logging of api key --- src/js/fileupload2.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js index a5d269e..3c83d8b 100644 --- a/src/js/fileupload2.js +++ b/src/js/fileupload2.js @@ -54,7 +54,6 @@ $(document).ready(function() { datasetPid = queryParams.get("datasetPid"); console.log('PID: ' + datasetPid); apiKey = queryParams.get("key"); - console.log(apiKey); directUploadEnabled = true; addMessage('info', 'Getting Dataset Information...'); fetch(siteUrl + "/api/files/fixityAlgorithm") From 2679f2c693afa1de0bde45b70b3a8086949214dc Mon Sep 17 00:00:00 2001 From: Jim Myers Date: Thu, 1 Jun 2023 14:12:17 -0400 Subject: [PATCH 10/10] fix equals instead of === in orig file format check --- src/js/fileupload2.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/js/fileupload2.js b/src/js/fileupload2.js index 3c83d8b..f972a7a 100644 --- a/src/js/fileupload2.js +++ b/src/js/fileupload2.js @@ -226,7 +226,7 @@ async function retrieveDatasetInfo() { let df = entry.dataFile; let convertedFile = false; if (("originalFileFormat" in df) - && (!df.contentType.equals(df.originalFileFormat))) { + && (!df.contentType === df.originalFileFormat)) { console.log("The file named " + df.getString("filename") + " on the server was created by Dataverse's ingest process from an original uploaded file"); convertedFile = true;