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 = '
'; + html += '
'; + html += ''; + html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>'; + html += '
'; + html += ''; + html += '
'; + html += '
'; + html += ' '; + html += truncateLongString(asset.name, + <%= Constants::FILENAME_TRUNCATION_LENGTH %>); + html += _validateFilesSize(asset); + 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 = '
'; + html += '
'; + html += ''; + html += '<%= I18n.t 'assets.drag_n_drop.file_label' %>'; + html += '
'; + html += ''; + html += '
'; + html += '
'; + html += ''; + html += ''; + html += '
'; + html += truncateLongString(asset.name, + <%= Constants::FILENAME_TRUNCATION_LENGTH %>); + html += _validateFilesSize(asset); + 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-result-attachment-new').remove(); + _validateTotalSize(); + }); + } + + function processResult(button) { + if(isValid && _filerAndCheckFiles()) { + animateSpinner(); + $.ajax({ + url: $(button).attr('data-href'), + method: 'POST', + data: _appendFilesToForm(), + contentType: false, + processData: false, + success: function(data) { + animateSpinner(null, false); + $('#new-result-assets-select').parent().remove(); + $(data.html).prependTo('#results').promise().done(function() { + $.each($('[data-container="new-reports"]').find('.result'), + function() { + initFormSubmitLinks($(this)); + ResutlAssets.applyEditResultAssetCallback(); + Results.applyCollapseLinkCallBack(); + Results.toggleResultEditButtons(true); + initPreviewModal(); + Comments.initialize(); + ResutlAssets.initNewResultAsset(); + Results.expandResult($(this)); + }); + + }); + $('#results-toolbar').show(); + }, + error: function() { + animateSpinner(); + location.reload(); + } + }) + } + } + + function destroyAll() { + _dragNdropAssetsOff(); + droppedFiles = []; + isValid = true; + totalSize = 0; + } + + function _dragNdropAssetsOff() { + $('body').off('drag dragstart dragend dragover dragenter dragleave drop'); + $('.is-dragover').hide(); + } + + return Object.freeze({ + init: init, + listItems: listItems, + destroyAll: destroyAll, + filesStatus: filesStatus, + validateTextSize: validateTextSize, + processResult: processResult + }); + })(); + + global.dragNdropAssetsInit = function(location) { + var in_window = true; + + $('body').on('drag dragstart dragend dragover dragenter dragleave drop', + function(e) { + e.preventDefault(); + e.stopPropagation(); + }).on('dragover', function() { + in_window = true; + $('.is-dragover').show(); + }).on('dragleave', function() { + in_window = false; + setTimeout(function() { + if(!in_window) { + $('.is-dragover').hide(); + } + }, 5000); + + }).on('drop', function(e) { + $('.is-dragover').hide(); + var files = e.originalEvent.dataTransfer.files; + if(location === 'steps') { + DragNDropSteps.init(files); + } else { + DragNDropResults.init(files); + } + }); + } + +})(window); diff --git a/app/assets/stylesheets/constants.scss b/app/assets/stylesheets/constants.scss index c9cae6fef..b12a24d64 100644 --- a/app/assets/stylesheets/constants.scss +++ b/app/assets/stylesheets/constants.scss @@ -44,6 +44,9 @@ $color-milano-red: #a70b05; // Colors for specific intents $color-visited-link: #23527c; +// Overlay shade for drag'n dropdown +$color-drag-overlay: rgba(0, 0, 0, .4); + //============================================================================== // Other //============================================================================== diff --git a/app/assets/stylesheets/themes/scinote.scss b/app/assets/stylesheets/themes/scinote.scss index 7429fa6ff..a2825f52f 100644 --- a/app/assets/stylesheets/themes/scinote.scss +++ b/app/assets/stylesheets/themes/scinote.scss @@ -1265,6 +1265,45 @@ ul.content-module-activities { } } +.new-asset-box { + border: 1px solid $color-silver; + border-radius: 2px; + font-size: 2rem; + margin-bottom: 20px; + margin-top: 20px; + padding-bottom: 30px; + padding-top: 30px; +} + +.dnd-error { + color: $color-milano-red; +} + +.is-dragover { + background: $color-drag-overlay; + bottom: 0; + display: none; + height: 100%; + left: 0; + min-height: 100%; + pointer-events: none; + position: fixed; + right: 0; + top: 0; + width: 100%; + z-index: 999999; + + span { + color: $color-white; + display: block; + font-size: 4em; + font-weight: bold; + padding-top: 25%; + pointer-events: none; + text-align: center; + } +} + .step, .result { .panel { diff --git a/app/controllers/result_assets_controller.rb b/app/controllers/result_assets_controller.rb index 7bae4741b..faeb069e2 100644 --- a/app/controllers/result_assets_controller.rb +++ b/app/controllers/result_assets_controller.rb @@ -26,53 +26,27 @@ class ResultAssetsController < ApplicationController end def create - @asset = Asset.new(result_params[:asset_attributes]) - @asset.created_by = current_user - @asset.last_modified_by = current_user - @asset.team = current_team - @result = Result.new( - user: current_user, - my_module: @my_module, - name: result_params[:name], - asset: @asset - ) - @result.last_modified_by = current_user - + obj = create_multiple_results respond_to do |format| - if (@result.save and @asset.save) then - # Post process file here - @asset.post_process_file(@my_module.experiment.project.team) - - # Generate activity - Activity.create( - type_of: :add_result, - user: current_user, - project: @my_module.experiment.project, - experiment: @my_module.experiment, - my_module: @my_module, - message: t( - "activities.add_asset_result", - user: current_user.full_name, - result: @result.name, - ) - ) - + if obj.fetch(:status) format.html do - flash[:success] = t( - "result_assets.create.success_flash", - module: @my_module.name) + flash[:success] = t('result_assets.create.success_flash', + module: @my_module.name) redirect_to results_my_module_path(@my_module) end format.json do render json: { - status: 'ok', html: render_to_string( - partial: 'my_modules/result.html.erb', locals: { result: @result } + partial: 'my_modules/results.html.erb', + locals: { results: obj.fetch(:results) } ) }, status: :ok end else - format.json { render json: @result.errors, status: :bad_request } + flash[:error] = t('result_assets.error_flash') + format.json do + render json: {}, status: :bad_request + end end end end @@ -249,4 +223,40 @@ class ResultAssetsController < ApplicationController ] ) end + + def create_multiple_results + success = true + results = [] + params[:results_files].each_with_index do |file, index| + asset = Asset.new(file: file.second, + created_by: current_user, + last_modified_by: current_user, + team: current_team) + result = Result.new(user: current_user, + my_module: @my_module, + name: params[:results_names][index.to_s], + asset: asset, + last_modified_by: current_user) + if result.save && asset.save + results << result + # Post process file here + asset.post_process_file(@my_module.experiment.project.team) + + # Generate activity + Activity.create( + type_of: :add_result, + user: current_user, + project: @my_module.experiment.project, + experiment: @my_module.experiment, + my_module: @my_module, + message: t('activities.add_asset_result', + user: current_user.full_name, + result: result.name) + ) + else + success = false + end + end + { status: success, results: results } + end end diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb index a9cbf6409..20ee1b81b 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -44,7 +44,6 @@ class StepsController < ApplicationController table.created_by = current_user table.team = current_team end - # Update default checked state @step.checklists.each do |checklist| checklist.checklist_items.each do |checklist_item| diff --git a/app/views/my_modules/_results.html.erb b/app/views/my_modules/_results.html.erb new file mode 100644 index 000000000..83af69b62 --- /dev/null +++ b/app/views/my_modules/_results.html.erb @@ -0,0 +1,5 @@ +
+ <% results.reverse_each do |result| %> + <%= render partial: 'my_modules/result.html.erb', locals: { result: result } %> + <% end %> +
diff --git a/app/views/my_modules/protocols.html.erb b/app/views/my_modules/protocols.html.erb index d90814371..1645e5c8a 100644 --- a/app/views/my_modules/protocols.html.erb +++ b/app/views/my_modules/protocols.html.erb @@ -1,4 +1,6 @@ <% provide(:head_title, t("my_modules.protocols.head_title", project: h(@project.name), module: h(@my_module.name)).html_safe) %> + +<%= render partial: 'shared/drag_n_drop_overlay' %> <%= render partial: "shared/sidebar" %> <%= render partial: "shared/secondary_navigation" %> diff --git a/app/views/my_modules/results.html.erb b/app/views/my_modules/results.html.erb index f03a6b250..363764273 100644 --- a/app/views/my_modules/results.html.erb +++ b/app/views/my_modules/results.html.erb @@ -1,6 +1,7 @@ <% provide(:head_title, t("my_modules.results.head_title", project: h(@project.name), module: h(@my_module.name)).html_safe) %> <%= render partial: "shared/sidebar" %> <%= render partial: "shared/secondary_navigation" %> +<%= render partial: 'shared/drag_n_drop_overlay' %>
diff --git a/app/views/protocols/edit.html.erb b/app/views/protocols/edit.html.erb index 4a599f79f..ba3508844 100644 --- a/app/views/protocols/edit.html.erb +++ b/app/views/protocols/edit.html.erb @@ -1,5 +1,6 @@ <% provide(:head_title, t("protocols.edit.head_title")) %> +<%= render partial: 'shared/drag_n_drop_overlay' %> <%= render partial: "protocols/breadcrumbs.html.erb", locals: { teams: @teams, current_team: @protocol.team, diff --git a/app/views/result_assets/_new.html.erb b/app/views/result_assets/_new.html.erb index d4fa8e0bf..fe28d123d 100644 --- a/app/views/result_assets/_new.html.erb +++ b/app/views/result_assets/_new.html.erb @@ -1,14 +1,22 @@
- <%= bootstrap_form_for(@result, url: my_module_result_assets_path(format: :json), remote: true, multipart: true, data: { type: :json }) do |f| %> - <%= f.text_field :name, style: "margin-top: 10px;" %>
- <%= f.fields_for :asset do |ff| %> - <%= ff.file_field :file %> - <% end %> - <%= f.submit t("result_assets.new.create"), - class: 'btn btn-primary save-result', - onclick: "Results.processResult(event, Results.ResultTypeEnum.FILE, false);" %> - + - <% end %> + <%# end %>
diff --git a/app/views/shared/_drag_n_drop_overlay.html.erb b/app/views/shared/_drag_n_drop_overlay.html.erb new file mode 100644 index 000000000..4b3179911 --- /dev/null +++ b/app/views/shared/_drag_n_drop_overlay.html.erb @@ -0,0 +1,3 @@ +
+ <%=t 'assets.drag_n_drop.drop_label' %> +
diff --git a/app/views/steps/_empty_step.html.erb b/app/views/steps/_empty_step.html.erb index 9e93a0f9a..1882f419b 100644 --- a/app/views/steps/_empty_step.html.erb +++ b/app/views/steps/_empty_step.html.erb @@ -10,7 +10,9 @@ <%= t("protocols.steps.new.tab_checklists") %> -
+
+ <%=t 'assets.drag_n_drop.label_html' %> +
<%= f.nested_fields_for :assets do |ff| %> <%= render "form_assets.html.erb", ff: ff, step: step %> <% end %> - <%= f.add_nested_fields_link :assets do %> - - <%= t("protocols.steps.new.add_asset") %> - <% end %>
<%= f.nested_fields_for :tables do |ff| %> diff --git a/app/views/steps/_new.html.erb b/app/views/steps/_new.html.erb index c6803582e..883f92c9c 100644 --- a/app/views/steps/_new.html.erb +++ b/app/views/steps/_new.html.erb @@ -1,5 +1,5 @@
- <%= bootstrap_form_for(@step, url: protocol_steps_path(@protocol, format: :json), remote: true, authenticity_token: true, multipart: true, data: { role: "new-step-form", type: :json }) do |f| %> + <%= bootstrap_form_for(@step, url: protocol_steps_path(@protocol, format: :json), authenticity_token: true, multipart: true, data: { role: "new-step-form", type: :json }) do |f| %>

<%= t("protocols.steps.new.add_step_title") %>


<%= render partial: "empty_step.html.erb", locals: {step: @step, f: f} %> diff --git a/config/locales/en.yml b/config/locales/en.yml index d94fa4427..5d6f3e239 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -813,6 +813,7 @@ en: success_flash: "File result successfully deleted." wopi_open_file: "Open in %{app}" wopi_edit_file: "Edit in %{app}" + error_flash: 'Something went wrong! Please try again later.' result_tables: new: @@ -1566,7 +1567,11 @@ en: head_title: edit: "sciNote | %{file_name} | Edit" view: "sciNote | %{file_name} | View" - + drag_n_drop: + label_html: 'Drag & drop files here or ' + browse_label: 'Browse to add' + drop_label: 'Drop to add to Step' + file_label: 'File' atwho: no_results: "No results found" users: