diff --git a/app/assets/javascripts/my_modules/results.js.erb b/app/assets/javascripts/my_modules/results.js.erb index ad3608600..079815e61 100644 --- a/app/assets/javascripts/my_modules/results.js.erb +++ b/app/assets/javascripts/my_modules/results.js.erb @@ -157,23 +157,6 @@ $form.clearFormErrors(); switch(resultTypeEnum) { - case ResultTypeEnum.FILE: - var $nameInput = $form.find('#result_name'); - var nameValid = textValidator(ev, $nameInput, 0, - <%= Constants::NAME_MAX_LENGTH %>); - var $fileInput = $form.find('#result_asset_attributes_file'); - var filesValid = true; - if ($fileInput.val()) { - filesValid = filesValidator(ev, $fileInput, FileTypeEnum.FILE, - editMode); - } - - if(nameValid && filesValid) { - // Local file uploading - animateSpinner(); - - } - break; case ResultTypeEnum.TABLE: var $nameInput = $form.find('#result_name'); var nameValid = textValidator(ev, $nameInput, 0, diff --git a/app/assets/javascripts/protocols/steps.js.erb b/app/assets/javascripts/protocols/steps.js.erb index 25ad4cbf6..3458fecb2 100644 --- a/app/assets/javascripts/protocols/steps.js.erb +++ b/app/assets/javascripts/protocols/steps.js.erb @@ -214,23 +214,6 @@ $(e.target).find("input[type='file']").val(""); } }); - - // Add hidden fields for tables - $form.submit(function(){ - $(this).find("[data-role='editable-table']").each(function() { - var hot = $(this).find(".hot").handsontable('getInstance'); - var contents = $(this).find('.hot-contents'); - var data = JSON.stringify({data: hot.getData()}); - contents.attr("value", data); - }); - - setTimeout(function() { - initStepsComments(); - animateSpinner(null, false); - SmartAnnotation.preventPropagation('.atwho-user-popover'); - }, 1000); - return true; - }); } // Init ajax success/error for edit form @@ -279,49 +262,6 @@ }); } - function formNewAjax($form) { - $form - .on("ajax:beforeSend", function () { - $(".nested_step_checklists ul").each(function () { - reorderCheckboxData(this); - }); - }) - .on("ajax:success", function(e, data) { - $(this).after(data.html); - var $new_step = $(this).next(); - $(this).remove(); - - initCallBacks(); - initHandsOnTable($new_step); - expandStep($new_step); - toggleButtons(true); - SmartAnnotation.preventPropagation('.atwho-user-popover'); - - //Rerender tables - $new_step.find("div.step-result-hot-table").each(function() { - $(this).handsontable("render"); - }); - animateSpinner(null, false); - setupAssetsLoading(); - }) - .on("ajax:error", function(e, xhr, status, error) { - $(this).after(xhr.responseJSON.html); - var $form = $(this).next(); - $(this).remove(); - - $errInput = $form.find(".form-group.has-error").first().find("input"); - renderFormError(e, $errInput); - - formCallback($form); - formNewAjax($form); - applyCancelOnNew(); - animateSpinner(null, false); - - TinyMCE.destroyAll(); - SmartAnnotation.preventPropagation('.atwho-user-popover'); - }); - } - function toggleButtons(show) { if (show) { $("[data-action='new-step']").show(); @@ -562,7 +502,6 @@ scrollTop: $(document).height() - $(window).height() }); formCallback($form); - formNewAjax($form); applyCancelOnNew(); toggleButtons(false); initializeCheckboxSorting(); @@ -588,13 +527,13 @@ // experience is improved global.processStep = function processStep(ev, editMode) { ev.stopPropagation(); + ev.preventDefault(); + ev.stopImmediatePropagation(); var $form = $(ev.target.form); $form.clearFormErrors(); $form.removeBlankFileForms(); - var $fileInputs = $form.find("input[type=file]"); - var filesValid = filesValidator(ev, $fileInputs, FileTypeEnum.FILE); var $checklists = $form.find(".nested_step_checklists"); var checklistsValid = checklistsValidator(ev, $checklists, editMode); var $nameInput = $form.find("#step_name"); @@ -604,8 +543,73 @@ var descriptionValid = textValidator(ev, $descrTextarea, 0, <%= Constants::TEXT_MAX_LENGTH %>); - if (filesValid && checklistsValid && nameValid && descriptionValid) { - // Local file uploading + if (DragNDropSteps.filesStatus() && + checklistsValid && + nameValid && + descriptionValid) { + + $form.find("[data-role='editable-table']").each(function() { + var hot = $(this).find(".hot").handsontable('getInstance'); + var contents = $(this).find('.hot-contents'); + var data = JSON.stringify({data: hot.getData()}); + contents.attr("value", data); + }); + + setTimeout(function() { + initStepsComments(); + SmartAnnotation.preventPropagation('.atwho-user-popover'); + }, 1000); + + animateSpinner(null, true); + var data = DragNDropSteps.appendFilesToForm(ev); + data.append('step[description]', TinyMCE.getContent()); + $.ajax({ + url: $form.attr('action'), + method: 'POST', + data: data, + contentType: false, + processData: false, + beforeSend: function() { + $(".nested_step_checklists ul").each(function () { + reorderCheckboxData(this); + }); + }, + success: function(data) { + $($form.closest('.well')).after(data.html); + var $new_step = $($form.closest('.well')).next(); + $($form.closest('.well')).remove(); + + initCallBacks(); + initHandsOnTable($new_step); + expandStep($new_step); + toggleButtons(true); + SmartAnnotation.preventPropagation('.atwho-user-popover'); + + //Rerender tables + $new_step.find("div.step-result-hot-table").each(function() { + $(this).handsontable("render"); + }); + animateSpinner(null, false); + setupAssetsLoading(); + }, + error: function(e) { + $form.after(xhr.responseJSON.html); + var $new_form = $form.next(); + $form.remove(); + + $errInput = $new_form.find(".form-group.has-error") + .first() + .find("input"); + renderFormError(e, $errInput); + + formCallback($form); + applyCancelOnNew(); + animateSpinner(null, false); + + TinyMCE.destroyAll(); + SmartAnnotation.preventPropagation('.atwho-user-popover'); + } + }); newStepHandler(); } } diff --git a/app/assets/javascripts/results/result_assets.js b/app/assets/javascripts/results/result_assets.js index 47a23013e..ebf838234 100644 --- a/app/assets/javascripts/results/result_assets.js +++ b/app/assets/javascripts/results/result_assets.js @@ -1,7 +1,7 @@ (function(global) { 'use strict'; - var ResutlAssets = (function() { + global.ResutlAssets = (function() { // New result asset behaviour function initNewResultAsset() { $('#new-result-asset').on('click', function(event) { @@ -23,7 +23,7 @@ _formAjaxResultAsset($form); Results.initCancelFormButton($form, initNewResultAsset); Results.toggleResultEditButtons(false); - $('#result_name').focus(); + dragNdropAssetsInit('results'); }, error: function(xhr, status, e) { $(this).renderFormErrors('result', xhr.responseJSON, true, e); diff --git a/app/assets/javascripts/sitewide/drag_n_drop.js.erb b/app/assets/javascripts/sitewide/drag_n_drop.js.erb new file mode 100644 index 000000000..f53fa1adf --- /dev/null +++ b/app/assets/javascripts/sitewide/drag_n_drop.js.erb @@ -0,0 +1,346 @@ +(function(global) { + 'use strict'; + + // Module to handle file uploading in Steps + global.DragNDropSteps = (function() { + var droppedFiles = []; + var filesValid = true; + var totalSize = 0; + + function init(files) { + for(var i = 0; i < files.length; i++) { + droppedFiles.push(files[i]); + } + listItems(); + } + + // return the status of files if they are ready to submit + function filesStatus() { + return filesValid; + } + + // loops through a list of files and display each file in a separate panel + function listItems() { + droppedFiles = droppedFiles.filter(Boolean); + $('.panel-step-attachment-new').remove(); + _dragNdropAssetsOff(); + for(var i = 0; i < droppedFiles.length; i++) { + $('#new-step-assets') + .append(_uploadedAseetPreview(droppedFiles[i], i)) + .promise() + .done(function() { + _removeItemHandler(i); + }); + } + _validateTotalSize(); + dragNdropAssetsInit('steps'); + } + + // append the files to the form before submit + function appendFilesToForm(ev) { + var regex = /step\[assets_attributes\]\[[0-9]*\]\[id\]/; + var prevEls = $('input').filter(function() { + return this.name.match(regex); + }); + droppedFiles = droppedFiles.filter(Boolean); + var fd = new FormData($(ev.target).closest('form').get(0)); + for(var i = 0; i < droppedFiles.length; i++) { + var index = i + prevEls.length; + var name = 'step[assets_attributes][' + index + '][file]'; + fd.append(name, droppedFiles[i]); + } + droppedFiles = []; + filesValid = true; + totalSize = 0; + _dragNdropAssetsOff(); + return fd; + } + + function _validateFilesSize(file) { + var maxSize = file.size/1048576; + if(maxSize > <%= Constants::FILE_MAX_SIZE_MB %> && filesValid) { + return "
<%= I18n.t 'general.file.size_exceeded', file_size: Constants::FILE_MAX_SIZE_MB %>
"; + } + totalSize += parseInt(maxSize); + return ''; + } + + function _validateTotalSize() { + if(totalSize > <%= Constants::FILE_MAX_SIZE_MB %>) { + filesValid = false; + $.each($('.panel-step-attachment-new'), function() { + $(this) + .find('.panel-body') + .append("<%= I18n.t('general.file.total_size', size: Constants::FILE_MAX_SIZE_MB) %>
"); + }); + } else { + $('.dnd-error').remove(); + filesValid = true; + } + } + + function _uploadedAseetPreview(asset, i) { + var html = ' '; + return html; + } + + function _removeItemHandler(id) { + $('[data-item-id="' + id +'"]').off('click').on('click', function(e) { + e.preventDefault(); + e.stopImmediatePropagation(); + e.stopPropagation(); + var $el = $(this); + var index = $el.data('item-id'); + totalSize -= parseInt(droppedFiles[index]/1048576); + droppedFiles[index] = null; + $el.closest('.panel-step-attachment-new').remove(); + _validateTotalSize(); + }); + } + + function _dragNdropAssetsOff() { + $('body').off('drag dragstart dragend dragover dragenter dragleave drop'); + $('.is-dragover').hide(); + } + + return Object.freeze({ + init: init, + appendFilesToForm: appendFilesToForm, + listItems: listItems, + filesStatus: filesStatus + }); + })(); + + // Module to handle file uploading in Results + global.DragNDropResults = (function() { + var droppedFiles = []; + var isValid = true; + var totalSize = 0; + + function init(files) { + var filesPresent = droppedFiles.length; + for(var i = 0; i < files.length; i++) { + droppedFiles.push(files[i]); + } + listItems(filesPresent); + } + + // return the status of files if they are ready to submit + function filesStatus() { + return isValid; + } + + // loops through a list of files and display each file in a separate panel + function listItems(index) { + _dragNdropAssetsOff(); + for(var i = index; i < droppedFiles.length; i++) { + $('#new-result-assets-select') + .after(_uploadedAseetPreview(droppedFiles[i], i)) + .promise() + .done(function() { + _removeItemHandler(i); + }); + } + _validateTotalSize(); + dragNdropAssetsInit('results'); + } + + // appent the files to the form before submit + function _appendFilesToForm() { + var regex = /result\[assets_attributes\]\[[0-9]*\]\[id\]/; + var prevEls = $('input').filter(function() { + return this.name.match(regex); + }); + + var fd = new FormData(); + var result_names = []; + $.each($('input[rel="results[name]"'), function() { + result_names.push($(this).val()); + }); + result_names.reverse(); + for(var i = 0; i < droppedFiles.length; i++) { + var index = i + prevEls.length; + var file_name = 'results_files[' + index + ']'; + fd.append(file_name, droppedFiles[i]); + fd.append('results_names[' + i + ']', result_names[i]); + } + destroyAll(); + return fd; + } + + function _filerAndCheckFiles() { + droppedFiles = droppedFiles.filter(Boolean); + return (droppedFiles.length > 0); + } + + function _validateFilesSize(file) { + var maxSize = file.size/1048576; + if(maxSize > <%= Constants::FILE_MAX_SIZE_MB %> && isValid) { + return "<%= I18n.t 'general.file.size_exceeded', file_size: Constants::FILE_MAX_SIZE_MB %>
"; + } + totalSize += parseInt(maxSize); + return ''; + } + + function _validateTotalSize() { + if(totalSize > <%= Constants::FILE_MAX_SIZE_MB %>) { + isValid = false; + $.each($('.panel-result-attachment-new'), function() { + $(this) + .find('.panel-body') + .append("<%= I18n.t('general.file.total_size', size: Constants::FILE_MAX_SIZE_MB) %>
"); + }); + } else { + $('.dnd-error').remove(); + isValid = true; + } + } + + function validateTextSize(input) { + if(input.value.length > <%= Constants::NAME_MAX_LENGTH %>) { + $(input).parent().find('.dnd-error').remove(); + $(input).after("<%= I18n.t('general.text.length_too_long', max_length: Constants::NAME_MAX_LENGTH) %>
"); + isValid = false; + } else { + $(input).parent().find('.dnd-error').remove(); + isValid = true; + } + } + + function _uploadedAseetPreview(asset, i) { + var html = '