diff --git a/public/assets/js/dropzoneFunctions.js b/public/assets/js/dropzoneFunctions.js index f1a8ddf6..7eae662f 100644 --- a/public/assets/js/dropzoneFunctions.js +++ b/public/assets/js/dropzoneFunctions.js @@ -1,6 +1,3 @@ -function triggerFileChooser(fileInputId, event) { - document.getElementById(fileInputId).click(); -} function drop_handler(event) { event.preventDefault(); diff --git a/public/assets/js/publishFileFunctions.js b/public/assets/js/publishFileFunctions.js index 3576a361..53b60a7b 100644 --- a/public/assets/js/publishFileFunctions.js +++ b/public/assets/js/publishFileFunctions.js @@ -1,132 +1,248 @@ /* publish functions */ +let stagedFiles = null; + +const previewReader = new FileReader(); + +function triggerFileChooser(fileInputId) { + document.getElementById(fileInputId).click(); +} + +function setImagePreview (selectedFile) { + const assetPreview = document.getElementById('asset-preview-target'); + const thumbnailInput = document.getElementById('claim-thumbnail-input'); + const thumbnailInputTool = document.getElementById('publish-thumbnail'); + if (selectedFile.type !== 'video/mp4') { + if (selectedFile.type === 'image/gif') { + assetPreview.innerHTML = `

loading preview...

` + } + previewReader.readAsDataURL(selectedFile); + previewReader.onloadend = function () { + assetPreview.innerHTML = 'image preview'; + }; + // clear & hide the thumbnail selection input + thumbnailInput.value = ''; + thumbnailInputTool.hidden = true; + } else { + assetPreview.innerHTML = ``; + // clear & show the thumbnail selection input + thumbnailInput.value = ''; + thumbnailInputTool.hidden = false; + } +} + +function hidePrimaryDropzone () { + const primaryDropzone = document.getElementById('primary-dropzone'); + const publishForm = document.getElementById('publish-form'); + primaryDropzone.setAttribute('class', 'hidden'); + publishForm.setAttribute('class', 'row') +} + +function updateClaimNameInputWithFileName (selectedFile) { + const nameInput = document.getElementById('claim-name-input'); + if (nameInput.value === "") { + var filename = selectedFile.name.substring(0, selectedFile.name.indexOf('.')) + nameInput.value = cleanseClaimName(filename); + checkClaimName(nameInput.value); + } +} + +function previewAndStageFile(selectedFile){ + const fileSelectionInputError = document.getElementById('input-error-file-selection'); + // When a file is selected for publish, validate that file and + // stage it so it will be ready when the publish button is clicked + try { + validateFile(selectedFile); // validate the file's name, type, and size + } catch (error) { + showError(fileSelectionInputError, error.message); + return; + } + // set image preview, if an image was provided + setImagePreview(selectedFile); + // hide the primary drop zone + hidePrimaryDropzone(); + // set the name input value to the image name if none is set yet + updateClaimNameInputWithFileName(selectedFile); + // store the selected file for upload + stagedFiles = [selectedFile]; +} + function cancelPublish () { window.location.href = '/'; } -// When a file is selected for publish, validate that file and -// stage it so it will be ready when the publish button is clicked. -function previewAndStageFile(selectedFile){ - const publishForm = document.getElementById('publish-form'); - const assetPreview = document.getElementById('asset-preview-target'); - const primaryDropzone = document.getElementById('primary-dropzone'); - const previewReader = new FileReader(); - const nameInput = document.getElementById('claim-name-input'); - const fileSelectionInputError = document.getElementById('input-error-file-selection'); - const thumbnailSelectionTool = document.getElementById('publish-thumbnail'); - const thumbnailSelectionInput = document.getElementById('claim-thumbnail-input'); - // validate the file's name, type, and size - try { - validateFile(selectedFile); - } catch (error) { - showError(fileSelectionInputError, error.message); - return; - } - // set the image preview, if an image was provided - if (selectedFile.type !== 'video/mp4') { - if (selectedFile.type === 'image/gif') { - assetPreview.innerHTML = `

loading preview...

` - } - previewReader.readAsDataURL(selectedFile); - previewReader.onloadend = function () { - assetPreview.innerHTML = 'image preview'; - }; - // clear & hide the thumbnail selection input - thumbnailSelectionInput.value = ''; - thumbnailSelectionTool.hidden = true; - } else { - assetPreview.innerHTML = ``; - // clear & show the thumbnail selection input - thumbnailSelectionInput.value = ''; - thumbnailSelectionTool.hidden = false; - } - // hide the drop zone - primaryDropzone.setAttribute('class', 'hidden'); - publishForm.setAttribute('class', 'row') - // set the name input value to the image name if none is set yet - if (nameInput.value === "") { - var filename = selectedFile.name.substring(0, selectedFile.name.indexOf('.')) - nameInput.value = cleanseClaimName(filename); - checkClaimName(nameInput.value); - } - // store the selected file for upload - stagedFiles = [selectedFile]; +var publishFileFunctions = { + returnNullOrChannel: function () { + const channelInput = document.getElementById('channel-name-select'); + const radios = document.getElementsByName('anonymous-or-channel'); + let anonymousOrInChannel; + // replace channelName with 'anonymous' if appropriate + for (let i = 0; i < radios.length; i++) { + if (radios[i].checked) { + anonymousOrInChannel = radios[i].value; // do whatever you want with the checked radio + break; // only one radio can be logically checked, don't check the rest + } + } + if (anonymousOrInChannel === 'anonymous') { + return null; + }; + return channelInput.value.trim(); + }, + createMetadata: function() { + const nameInput = document.getElementById('claim-name-input'); + const titleInput = document.getElementById('publish-title'); + const descriptionInput = document.getElementById('publish-description'); + const licenseInput = document.getElementById('publish-license'); + const nsfwInput = document.getElementById('publish-nsfw'); + const thumbnailInput = document.getElementById('claim-thumbnail-input'); + + return { + name: nameInput.value.trim(), + channel: this.returnNullOrChannel(), + title: titleInput.value.trim(), + description: descriptionInput.value.trim(), + license: licenseInput.value.trim(), + nsfw: nsfwInput.checked, + type: stagedFiles[0].type, + thumbnail: thumbnailInput.value.trim() + } + }, + appendDataToFormData: function (file, metadata) { + console.log(metadata); + var fd = new FormData(); + fd.append('file', file) + for (var key in metadata) { + if (metadata.hasOwnProperty(key)) { + console.log(key, metadata[key]); + fd.append(key, metadata[key]); + } + } + return fd; + }, + publishFile: function (file, metadata) { + var uri = "/api/publish"; + var xhr = new XMLHttpRequest(); + var fd = this.appendDataToFormData(file, metadata); + console.log('fd2:', fd); + xhr.upload.addEventListener("loadstart", function(e) { + uploadStarted(); + }) + xhr.upload.addEventListener("progress", function(e) { + if (e.lengthComputable) { + var percentage = Math.round((e.loaded * 100) / e.total); + console.log('progress:', percentage); + uploadProgress(percentage); + } + }, false); + xhr.upload.addEventListener("load", function(e){ + console.log('loaded 100%'); + filePublishUpdate("Your file has been loaded, and is now being published to the blockchain. Sit tight...") + }, false); + xhr.open("POST", uri, true); + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + if (xhr.status == 200) { + alert(xhr.responseText); // handle response. + filePublishComplete(xhr.responseText); + } else { + filePublishFailure(xhr.responseText); + } + } else { + console.log('xhr.readyState', xhr.readyState, 'xhr.status', xhr.status); + } + }; + // Initiate a multipart/form-data upload + xhr.send(fd); + }, + // Validate the publish submission and then trigger upload + publishStagedFile: function (event) { + event.preventDefault(); // prevent default so this script can handle submission + const metadata = this.createMetadata(); + const that = this; // note: necessary ? + const fileSelectionInputError = document.getElementById('input-error-file-selection'); + const claimNameError = document.getElementById('input-error-claim-name'); + const channelSelectError = document.getElementById('input-error-channel-select'); + const publishSubmitError = document.getElementById('input-error-publish-submit'); + // validate, submit, and handle response + validateFilePublishSubmission(stagedFiles, metadata) + .then( function() { + that.publishFile(stagedFiles[0], metadata); + }) + .catch(error => { + if (error.name === 'FileError') { + showError(fileSelectionInputError, error.message); + } else if (error.name === 'NameError') { + showError(claimNameError, error.message); + } else if (error.name === 'ChannelNameError'){ + console.log(error); + showError(channelSelectError, error.message); + } else { + showError(publishSubmitError, error.message); + } + return; + }) + }, } -// Validate the publish submission and then trigger upload -function publishStagedFile(event) { - // prevent default so this script can handle submission - event.preventDefault(); - // declare variables - const claimName = document.getElementById('claim-name-input').value; - let channelName = document.getElementById('channel-name-select').value; - const fileSelectionInputError = document.getElementById('input-error-file-selection'); - const claimNameError = document.getElementById('input-error-claim-name'); - const channelSelectError = document.getElementById('input-error-channel-select'); - const publishSubmitError = document.getElementById('input-error-publish-submit'); - let anonymousOrInChannel; - // replace channelName with 'anonymous' if appropriate - const radios = document.getElementsByName('anonymous-or-channel'); - for (let i = 0; i < radios.length; i++) { - if (radios[i].checked) { - // do whatever you want with the checked radio - anonymousOrInChannel = radios[i].value; - // only one radio can be logically checked, don't check the rest - break; - } - } - if (anonymousOrInChannel === 'anonymous') { - channelName = null; - }; - // validate, submit, and handle response - validateFilePublishSubmission(stagedFiles, claimName, channelName) - .then(() => { - publishFile(stagedFiles[0], claimName); - }) - .catch(error => { - if (error.name === 'FileError') { - showError(fileSelectionInputError, error.message); - } else if (error.name === 'NameError') { - showError(claimNameError, error.message); - } else if (error.name === 'ChannelNameError'){ - console.log(error); - showError(channelSelectError, error.message); - } else { - showError(publishSubmitError, error.message); - } - return; - }) +function uploadStarted (){ + console.log('starting upload'); + // hide the publish tool + hidePublishTools(); + // show the progress status and animation + showPublishStatus(); + showPublishProgressBar(); +}; +function uploadProgress (percentage){ + updatePublishStatus('

File is loading to server

') + updateUploadPercent(`

${percentage}%

`) +}; +function filePublishUpdate (msg) { + updatePublishStatus(`

${msg}

`); + updateUploadPercent(`

Curious what magic is happening here? Learn more.

`); +}; +function filePublishFailure (msg){ + updatePublishStatus('

--(✖╭╮✖)→

' + JSON.stringify(msg) + '

For help, post the above error text in the #speech channel on the lbry discord'); + hidePublishProgressBar(); + hideUploadPercent(); +}; +function filePublishComplete (msg) { + console.log('filePublishComplete message:', msg); + const showUrl = msg.result.claim_id + "/" + msg.name; + // update status + updatePublishStatus('

Your publish is complete! You are being redirected to it now.

'); + updateUploadPercent('

If you do not get redirected, click here.

') + // redirect the user + window.location.href = showUrl; }; -var publishFile = function (file, name) { - var uri = "/api/publish"; - var xhr = new XMLHttpRequest(); - var fd = new FormData(); - - console.log('publish file, file:', file); - console.log('publish file, name:', name); - fd.append('file', file); - fd.append('name', name); - - xhr.upload.addEventListener("progress", function(e) { - if (e.lengthComputable) { - var percentage = Math.round((e.loaded * 100) / e.total); - console.log('progress:', percentage); - } - }, false); - - xhr.upload.addEventListener("load", function(e){ - console.log('loaded 100%'); - }, false); - - xhr.open("POST", uri, true); - xhr.onreadystatechange = function() { - if (xhr.readyState == 4 && xhr.status == 200) { - alert(xhr.responseText); // handle response. - } else { - console.log('xhr.readyState', xhr.readyState, 'xhr.status', xhr.status); - } - }; - // Initiate a multipart/form-data upload - xhr.send(fd); +function hidePublishTools() { + const publishFormWrapper = document.getElementById('publish-form'); + publishFormWrapper.setAttribute('class', 'hidden'); } +// publish status functions +function showPublishStatus() { + const publishStatus = document.getElementById('publish-status'); + publishStatus.setAttribute('class', 'row row--tall flex-container--column flex-container--center-center'); +} +function updatePublishStatus(msg){ + const publishUpdate = document.getElementById('publish-update'); + publishUpdate.innerHTML = msg; +} +// progress bar functions +function showPublishProgressBar(){ + const publishProgressBar = document.getElementById('publish-progress-bar'); + createProgressBar(publishProgressBar, 12); +} +function hidePublishProgressBar(){ + const publishProgressBar = document.getElementById('publish-progress-bar'); + publishProgressBar.hidden = true; +} +// upload percent functions +function updateUploadPercent(msg){ + const uploadPercent = document.getElementById('upload-percent'); + uploadPercent.innerHTML = msg; +} +function hideUploadPercent(){ + const uploadPercent = document.getElementById('upload-percent'); + uploadPercent.hidden = true; +} \ No newline at end of file diff --git a/public/assets/js/validationFunctions.js b/public/assets/js/validationFunctions.js index e8204776..0f3e6f06 100644 --- a/public/assets/js/validationFunctions.js +++ b/public/assets/js/validationFunctions.js @@ -38,6 +38,7 @@ function validateFile(file) { // validation function that checks to make sure the claim name is valid function validateClaimName (name) { + console.log('claim name:', name); // ensure a name was entered if (name.length < 1) { throw new NameError("You must enter a name for your url"); @@ -140,7 +141,9 @@ function checkChannelName(name){ } // validation function which checks all aspects of the publish submission -function validateFilePublishSubmission(stagedFiles, claimName, channelName){ +function validateFilePublishSubmission(stagedFiles, metadata){ + const channelName = metadata.channelName; + const claimName = metadata.name; return new Promise(function (resolve, reject) { // 1. make sure 1 file was staged if (!stagedFiles) { diff --git a/views/index.handlebars b/views/index.handlebars index 6fa807a5..4b80e119 100644 --- a/views/index.handlebars +++ b/views/index.handlebars @@ -53,95 +53,4 @@ diff --git a/views/partials/publishForm-Submit.handlebars b/views/partials/publishForm-Submit.handlebars index 486e8841..494eebcb 100644 --- a/views/partials/publishForm-Submit.handlebars +++ b/views/partials/publishForm-Submit.handlebars @@ -1,6 +1,6 @@
- +