From cd6bae6e351b1eeb89762e66fe1f1012d762e1bb Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Tue, 9 May 2017 14:14:01 +0200 Subject: [PATCH 01/29] Added migration to remove updated_at from Activity [fixes SCI-1145] --- db/migrate/20170509113030_remove_updated_at_from_activity.rb | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 db/migrate/20170509113030_remove_updated_at_from_activity.rb diff --git a/db/migrate/20170509113030_remove_updated_at_from_activity.rb b/db/migrate/20170509113030_remove_updated_at_from_activity.rb new file mode 100644 index 000000000..b38a2fa20 --- /dev/null +++ b/db/migrate/20170509113030_remove_updated_at_from_activity.rb @@ -0,0 +1,5 @@ +class RemoveUpdatedAtFromActivity < ActiveRecord::Migration + def change + remove_column :activities, :updated_at, :datetime + end +end From a4032f5cc629ad92a652fd3627af1dc08660d20e Mon Sep 17 00:00:00 2001 From: zmagod Date: Wed, 10 May 2017 13:53:32 +0200 Subject: [PATCH 02/29] first run --- .../javascripts/my_modules/results.js.erb | 393 +++++++++--------- .../javascripts/results/result_assets.js | 154 +++---- .../javascripts/results/result_tables.js.erb | 4 +- .../javascripts/results/result_texts.js | 2 +- .../javascripts/sitewide/image_preview.js | 89 ++-- 5 files changed, 336 insertions(+), 306 deletions(-) diff --git a/app/assets/javascripts/my_modules/results.js.erb b/app/assets/javascripts/my_modules/results.js.erb index 7338c06de..9f0c1221c 100644 --- a/app/assets/javascripts/my_modules/results.js.erb +++ b/app/assets/javascripts/my_modules/results.js.erb @@ -1,199 +1,214 @@ //= require assets //= require comments -/** - * Initializes page - */ -function init() { - initHandsOnTables($(document)); - expandAllResults(); - initTutorial(); - applyCollapseLinkCallBack(); +(function(global) { + 'use strict'; - Comments.bindNewElement(); - Comments.initialize(); + global.Results = (function() { + var self = this; + var ResultTypeEnum = Object.freeze({ + FILE: 0, + TABLE: 1, + TEXT: 2, + COMMENT: 3 + }); - Comments.initCommentOptions("ul.content-comments"); - Comments.initEditComments("#results"); - Comments.initDeleteComments("#results"); + function init() { + self.initHandsOnTables($(document)); + _expandAllResults(); + _initTutorial(); + self.applyCollapseLinkCallBack(); - $(function () { - $("#results-collapse-btn").click(function () { - $('.result .panel-collapse').collapse('hide'); - $(document).find("span.collapse-result-icon").each(function() { - $(this).addClass("glyphicon-collapse-down"); - $(this).removeClass("glyphicon-collapse-up"); + Comments.bindNewElement(); + Comments.initialize(); + + Comments.initCommentOptions('ul.content-comments'); + Comments.initEditComments('#results'); + Comments.initDeleteComments('#results'); + + $(function () { + $('#results-collapse-btn').click(function () { + $('.result .panel-collapse').collapse('hide'); + $(document).find('span.collapse-result-icon').each(function() { + $(this).addClass('glyphicon-collapse-down'); + $(this).removeClass('glyphicon-collapse-up'); + }); + }); + + $('#results-expand-btn').click(_expandAllResults); }); + + // This checks if the ctarget param exist in the rendered url and opens the + // comment tab + if( getParam('ctarget') ){ + var target = '#'+ getParam('ctarget'); + $(target).find('a.comment-tab-link').click(); + } + } + + function initHandsOnTables(root) { + root.find('div.hot-table').each(function() { + var $container = $(this).find('.step-result-hot-table'); + var contents = $(this).find('.hot-contents'); + + $container.handsontable({ + width: '100%', + startRows: 5, + startCols: 5, + rowHeaders: true, + colHeaders: true, + fillHandle: false, + formulas: true, + cells: function (row, col, prop) { + var cellProperties = {}; + + if (col >= 0) + cellProperties.readOnly = true; + else + cellProperties.readOnly = false; + + return cellProperties; + } + }); + var hot = $container.handsontable('getInstance'); + var data = JSON.parse(contents.attr('value')); + hot.loadData(data.data); + }); + } + + function applyCollapseLinkCallBack() { + $('.result-panel-collapse-link') + .on('ajax:success', function() { + var collapseIcon = $(this).find('.collapse-result-icon'); + var collapsed = $(this).hasClass('collapsed'); + // Toggle collapse button + collapseIcon.toggleClass('glyphicon-collapse-up', !collapsed); + collapseIcon.toggleClass('glyphicon-collapse-down', collapsed); + }); + } + + // Toggle editing buttons + function toggleResultEditButtons(show) { + if (show) { + $('#results-toolbar').show(); + $('.edit-result-button').show(); + } else { + $('.edit-result-button').hide(); + $('#results-toolbar').hide(); + } + } + + // Expand all results + function _expandAllResults() { + $('.result .panel-collapse').collapse('show'); + $(document).find('span.collapse-result-icon').each(function() { + $(this).addClass('glyphicon-collapse-up'); + $(this).removeClass('glyphicon-collapse-down'); + }); + $(document).find('div.step-result-hot-table').each(function() { + _renderTable(this); + }); + } + + function expandResult(result) { + $('.panel-collapse', result).collapse('show'); + $(result).find('span.collapse-result-icon').each(function() { + $(this).addClass('glyphicon-collapse-up'); + $(this).removeClass('glyphicon-collapse-down'); + }); + _renderTable($(result).find('div.step-result-hot-table')); + animateSpinner(null, false); + setupAssetsLoading(); + } + + function _renderTable(table) { + $(table).handsontable('render'); + // Yet another dirty hack to solve HandsOnTable problems + if (parseInt($(table).css('height'), 10) < + parseInt($(table).css('max-height'), 10) - 30) { + $(table).find('.ht_master .wtHolder').css({ 'height': '100%', + 'width': '100%' }); + } + } + + /** + * Initializes tutorial + */ + function _initTutorial() { + var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10); + if (stepNum >= 15 && stepNum <= 16) { + var samplesTab = $('#module-samples-nav-tab'); + + var nextPage = samplesTab.find('a').attr('href'); + var steps = [{ + element: $('#results-toolbar')[0], + intro: I18n.t('tutorial.module_results_html') + }, {ResultTypeEnum + element: samplesTab[0], + intro: I18n.t('tutorial.module_results_click_samples_html'), + position: 'left' + }]; + initPageTutorialSteps(15, 16, nextPage, function() {}, function() {}, + steps); + } + } + + function processResult(ev, resultTypeEnum, editMode) { + var $form = $(ev.target.form); + $form.clearFormErrors(); + + switch(resultTypeEnum) { + case self.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 self.ResultTypeEnum.TABLE: + var $nameInput = $form.find('#result_name'); + var nameValid = textValidator(ev, $nameInput, 0, + <%= Constants::NAME_MAX_LENGTH %>); + break; + case self.ResultTypeEnum.TEXT: + var $nameInput = $form.find('#result_name'); + var nameValid = textValidator(ev, $nameInput, 0, + <%= Constants::NAME_MAX_LENGTH %>); + var $textInput = TinyMCE.getContent(); + textValidator(ev, $textInput, 1, <%= Constants::TEXT_MAX_LENGTH %>, false, true); + break; + case self.ResultTypeEnum.COMMENT: + var $commentInput = $form.find('#comment_message'); + var commentValid = textValidator(ev, $commentInput, 1, + <%= Constants::TEXT_MAX_LENGTH %>); + break; + } + } + + var publicAPI = Object.freeze({ + init: init, + initHandsOnTables: initHandsOnTables, + applyCollapseLinkCallBack: applyCollapseLinkCallBack, + toggleResultEditButtons: toggleResultEditButtons, + expandResult: expandResult, + processResult: processResult, + ResultTypeEnum: ResultTypeEnum }); - $("#results-expand-btn").click(expandAllResults); + return publicAPI; + })(); + + $(document).ready(function(){ + Results.init(); }); - - // This checks if the ctarget param exist in the rendered url and opens the - // comment tab - if( getParam('ctarget') ){ - var target = "#"+ getParam('ctarget'); - $(target).find('a.comment-tab-link').click(); - } -} - -function initHandsOnTables(root) { - root.find("div.hot-table").each(function() { - var $container = $(this).find(".step-result-hot-table"); - var contents = $(this).find('.hot-contents'); - - $container.handsontable({ - width: '100%', - startRows: 5, - startCols: 5, - rowHeaders: true, - colHeaders: true, - fillHandle: false, - formulas: true, - cells: function (row, col, prop) { - var cellProperties = {}; - - if (col >= 0) - cellProperties.readOnly = true; - else - cellProperties.readOnly = false; - - return cellProperties; - } - }); - var hot = $container.handsontable('getInstance'); - var data = JSON.parse(contents.attr("value")); - hot.loadData(data.data); - - }); -} - -function applyCollapseLinkCallBack() { - $(".result-panel-collapse-link") - .on("ajax:success", function() { - var collapseIcon = $(this).find(".collapse-result-icon"); - var collapsed = $(this).hasClass("collapsed"); - // Toggle collapse button - collapseIcon.toggleClass("glyphicon-collapse-up", !collapsed); - collapseIcon.toggleClass("glyphicon-collapse-down", collapsed); - }); -} - -// Toggle editing buttons -function toggleResultEditButtons(show) { - if (show) { - $("#results-toolbar").show(); - $(".edit-result-button").show(); - } else { - $(".edit-result-button").hide(); - $("#results-toolbar").hide(); - } -} - -// Expand all results -function expandAllResults() { - $('.result .panel-collapse').collapse('show'); - $(document).find("span.collapse-result-icon").each(function() { - $(this).addClass("glyphicon-collapse-up"); - $(this).removeClass("glyphicon-collapse-down"); - }); - $(document).find("div.step-result-hot-table").each(function() { - renderTable(this); - }); -} - -function expandResult(result) { - $('.panel-collapse', result).collapse('show'); - $(result).find("span.collapse-result-icon").each(function() { - $(this).addClass("glyphicon-collapse-up"); - $(this).removeClass("glyphicon-collapse-down"); - }); - renderTable($(result).find("div.step-result-hot-table")); - animateSpinner(null, false); - setupAssetsLoading(); -} - -function renderTable(table) { - $(table).handsontable("render"); - // Yet another dirty hack to solve HandsOnTable problems - if (parseInt($(table).css("height"), 10) < parseInt($(table).css("max-height"), 10) - 30) { - $(table).find(".ht_master .wtHolder").css({ 'height': '100%', - 'width': '100%' }); - } -} - -/** - * Initializes tutorial - */ -function initTutorial() { - var stepNum = parseInt(Cookies.get('current_tutorial_step'), 10); - if (stepNum >= 15 && stepNum <= 16) { - var samplesTab = $('#module-samples-nav-tab'); - - var nextPage = samplesTab.find('a').attr('href'); - var steps = [{ - element: $('#results-toolbar')[0], - intro: I18n.t('tutorial.module_results_html') - }, { - element: samplesTab[0], - intro: I18n.t('tutorial.module_results_click_samples_html'), - position: 'left' - }]; - initPageTutorialSteps(15, 16, nextPage, function() {}, function() {}, - steps); - } -} - -var ResultTypeEnum = Object.freeze({ - FILE: 0, - TABLE: 1, - TEXT: 2, - COMMENT: 3 -}); - -function processResult(ev, resultTypeEnum, editMode) { - - var $form = $(ev.target.form); - $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, - <%= Constants::NAME_MAX_LENGTH %>); - break; - case ResultTypeEnum.TEXT: - var $nameInput = $form.find("#result_name"); - var nameValid = textValidator(ev, $nameInput, 0, - <%= Constants::NAME_MAX_LENGTH %>); - var $textInput = TinyMCE.getContent(); - textValidator(ev, $textInput, 1, <%= Constants::TEXT_MAX_LENGTH %>, false, true); - break; - case ResultTypeEnum.COMMENT: - var $commentInput = $form.find("#comment_message"); - var commentValid = textValidator(ev, $commentInput, 1, - <%= Constants::TEXT_MAX_LENGTH %>); - break; - } -} - -$(document).ready(function(){ - init(); -}); +})(window); diff --git a/app/assets/javascripts/results/result_assets.js b/app/assets/javascripts/results/result_assets.js index 6fe3a6a18..0e729fc74 100644 --- a/app/assets/javascripts/results/result_assets.js +++ b/app/assets/javascripts/results/result_assets.js @@ -1,83 +1,93 @@ -// New result asset behaviour -$("#new-result-asset").on("ajax:success", function(e, data) { - var $form = $(data.html); - $("#results").prepend($form); +(function(global) { + 'use strict'; - formAjaxResultAsset($form); + var ResutlAssetHandler = (function() { + var self = this; + var publicAPI = Object.freeze({ + initNewResultAsset: function initNewResultAsset() { + // New result asset behaviour + $('#new-result-asset').on('ajax:success', function(e, data) { + var $form = $(data.html); + $('#results').prepend($form); + debugger; + self.formAjaxResultAsset($form); - // Cancel button - $form.find(".cancel-new").click(function () { - $form.remove(); - toggleResultEditButtons(true); - }); + // Cancel button + $form.find('.cancel-new').click(function () { + $form.remove(); + toggleResultEditButtons(true); + }); - toggleResultEditButtons(false); + toggleResultEditButtons(false); - $("#result_name").focus(); -}); + $('#result_name').focus(); + }); -$("#new-result-asset").on("ajax:error", function(e, xhr, status, error) { - animateSpinner(null, false); -}); + $('#new-result-asset') + .on('ajax:error', function(e, xhr, status, error) { + animateSpinner(null, false); + }); + }, + applyEditResultAssetCallback: function applyEditResultAssetCallback() { + $('.edit-result-asset').on('ajax:success', function(e, data) { + var $result = $(this).closest('.result'); + var $form = $(data.html); + var $prevResult = $result; + $result.after($form); + $result.remove(); -// Edit result asset button behaviour -function applyEditResultAssetCallback() { - $(".edit-result-asset").on("ajax:success", function(e, data) { - var $result = $(this).closest(".result"); - var $form = $(data.html); - var $prevResult = $result; - $result.after($form); - $result.remove(); + formAjaxResultAsset($form); - formAjaxResultAsset($form); + // Cancel button + $form.find('.cancel-edit').click(function () { + $form.after($prevResult); + $form.remove(); + applyEditResultAssetCallback(); + toggleResultEditButtons(true); + initPreviewModal(); + }); - // Cancel button - $form.find(".cancel-edit").click(function () { - $form.after($prevResult); - $form.remove(); - applyEditResultAssetCallback(); - toggleResultEditButtons(true); - initPreviewModal(); + toggleResultEditButtons(false); + + $('#result_name').focus(); + }); + + $('.edit-result-asset') + .on('ajax:error', function(e, xhr, status, error) { + animateSpinner(null, false); + }); + }, + formAjaxResultAsset: function formAjaxResultAsset($form) { + $form.on('ajax:success', function(e, data) { + $form.after(data.html); + var $newResult = $form.next(); + initFormSubmitLinks($newResult); + $(this).remove(); + applyEditResultAssetCallback(); + Results.applyCollapseLinkCallBack(); + + toggleResultEditButtons(true); + expandResult($newResult); + initPreviewModal(); + Comments.initialize(); + }).on('ajax:error', function(e, data) { + // This check is here only because of remotipart bug, which returns + // HTML instead of JSON, go figure + var errors = ''; + if (data.errors) + errors = data.errors; + else + errors = data.responseJSON.errors; + $form.renderFormErrors('result', errors, true, e); + animateSpinner(null, false); + }); + } }); - toggleResultEditButtons(false); + return publicAPI; + })(); - $("#result_name").focus(); - }); - - $(".edit-result-asset").on("ajax:error", function(e, xhr, status, error) { - animateSpinner(null, false); - }); -} - -// Apply ajax callback to form -function formAjaxResultAsset($form) { - $form - .on("ajax:success", function(e, data) { - $form.after(data.html); - var $newResult = $form.next(); - initFormSubmitLinks($newResult); - $(this).remove(); - applyEditResultAssetCallback(); - applyCollapseLinkCallBack(); - - toggleResultEditButtons(true); - expandResult($newResult); - initPreviewModal(); - Comments.initialize(); - }) - .on("ajax:error", function(e, data) { - // This check is here only because of remotipart bug, which returns - // HTML instead of JSON, go figure - var errors = ''; - if (data.errors) - errors = data.errors; - else - errors = data.responseJSON.errors; - $form.renderFormErrors("result", errors, true, e); - animateSpinner(null, false); - }); -} - -applyEditResultAssetCallback(); -initPreviewModal(); + ResutlAssetHandler.initNewResultAsset(); + ResutlAssetHandler.applyEditResultAssetCallback(); + global.initPreviewModal(); +})(window); diff --git a/app/assets/javascripts/results/result_tables.js.erb b/app/assets/javascripts/results/result_tables.js.erb index 8994d10e5..c9c05b8fc 100644 --- a/app/assets/javascripts/results/result_tables.js.erb +++ b/app/assets/javascripts/results/result_tables.js.erb @@ -96,8 +96,8 @@ function formAjaxResultTable($form) { $(this).remove(); applyEditResultTableCallback(); - applyCollapseLinkCallBack(); - initHandsOnTables($result); + Results.applyCollapseLinkCallBack(); + Results.initHandsOnTables($result); toggleResultEditButtons(true); expandResult($result); Comments.initialize(); diff --git a/app/assets/javascripts/results/result_texts.js b/app/assets/javascripts/results/result_texts.js index d13bb7d5d..466a68ded 100644 --- a/app/assets/javascripts/results/result_texts.js +++ b/app/assets/javascripts/results/result_texts.js @@ -56,7 +56,7 @@ function formAjaxResultText($form) { $(this).remove(); applyEditResultTextCallback(); - applyCollapseLinkCallBack(); + Results.applyCollapseLinkCallBack(); toggleResultEditButtons(true); expandResult(newResult); TinyMCE.destroyAll(); diff --git a/app/assets/javascripts/sitewide/image_preview.js b/app/assets/javascripts/sitewide/image_preview.js index 170e843df..06bfb80ad 100644 --- a/app/assets/javascripts/sitewide/image_preview.js +++ b/app/assets/javascripts/sitewide/image_preview.js @@ -1,43 +1,48 @@ -function initPreviewModal() { - $('.image-preview-link').off(); - $('.image-preview-link').click(function(e) { - e.preventDefault(); - var name = $(this).find('p').text(); - var url = $(this).find('img').data('preview-url'); - var downloadUrl = $(this).attr('href'); - var description = $(this).data('description'); - openPreviewModal(name, url, downloadUrl, description); - }); -} +(function(global) { + 'use strict'; -function openPreviewModal(name, url, downloadUrl, description) { - var modal = $('#imagePreviewModal'); - $.ajax({ - url: url, - type: 'GET', - dataType: 'json', - success: function(data) { - modal.find('.modal-body img').remove(); - modal.find('.image-name').text(name); - var link = modal.find('.image-download-link'); - link.attr('href', downloadUrl); - link.attr('data-no-turbolink', true); - link.attr('data-status', 'asset-present'); - modal.find('.modal-body').append($('') - .attr('src', data['large-preview-url']) - .attr('alt', name) - .click(function(ev) { - ev.stopPropagation(); - })); - modal.find('.modal-footer .image-description').text(description); - modal.find('.modal-body').click(function() { - modal.modal('hide'); - }); - modal.modal(); - $('.modal-backdrop').last().css('z-index', modal.css('z-index') - 1); - }, - error: function(ev) { - // TODO - } - }); -} + global.initPreviewModal = function initPreviewModal() { + var name, url, downloadUrl, description; + $('.image-preview-link').off(); + $('.image-preview-link').click(function(e) { + e.preventDefault(); + name = $(this).find('p').text(); + url = $(this).find('img').data('preview-url'); + downloadUrl = $(this).attr('href'); + description = $(this).data('description'); + openPreviewModal(name, url, downloadUrl, description); + }); + } + + function openPreviewModal(name, url, downloadUrl, description) { + var modal = $('#imagePreviewModal'); + $.ajax({ + url: url, + type: 'GET', + dataType: 'json', + success: function(data) { + modal.find('.modal-body img').remove(); + modal.find('.image-name').text(name); + var link = modal.find('.image-download-link'); + link.attr('href', downloadUrl); + link.attr('data-no-turbolink', true); + link.attr('data-status', 'asset-present'); + modal.find('.modal-body').append($('') + .attr('src', data['large-preview-url']) + .attr('alt', name) + .click(function(ev) { + ev.stopPropagation(); + })); + modal.find('.modal-footer .image-description').text(description); + modal.find('.modal-body').click(function() { + modal.modal('hide'); + }); + modal.modal(); + $('.modal-backdrop').last().css('z-index', modal.css('z-index') - 1); + }, + error: function(ev) { + // TODO + } + }); + } +})(window); From 8c83b3a19618bdf276afbddeea3eda1911c34057 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Thu, 11 May 2017 11:08:36 +0200 Subject: [PATCH 03/29] Added updated_at values and unnecessary migration rollback [fixes SCI-1145] --- app/utilities/first_time_data_generator.rb | 28 +++++++++++++++---- ...9113030_remove_updated_at_from_activity.rb | 5 ---- 2 files changed, 22 insertions(+), 11 deletions(-) delete mode 100644 db/migrate/20170509113030_remove_updated_at_from_activity.rb diff --git a/app/utilities/first_time_data_generator.rb b/app/utilities/first_time_data_generator.rb index 5a30fed09..c77cf8ca0 100644 --- a/app/utilities/first_time_data_generator.rb +++ b/app/utilities/first_time_data_generator.rb @@ -137,7 +137,8 @@ module FirstTimeDataGenerator user: user.full_name, project: project.name ), - created_at: project.created_at + created_at: project.created_at, + updated_at: project.created_at ).sneaky_save # Add a comment @@ -210,7 +211,8 @@ module FirstTimeDataGenerator user: user.full_name, module: my_module.name ), - created_at: my_module.created_at + created_at: my_module.created_at, + updated_at: my_module.created_at ).sneaky_save UserMyModule.create( @@ -230,7 +232,8 @@ module FirstTimeDataGenerator module: my_module.name, assigned_by_user: user.full_name ), - created_at: generate_random_time(my_module.created_at, 2.minutes) + created_at: generate_random_time(my_module.created_at, 2.minutes), + updated_at: generate_random_time(my_module.created_at, 2.minutes) ).sneaky_save end @@ -262,7 +265,8 @@ module FirstTimeDataGenerator user: user.full_name, module: archived_module.name ), - created_at: archived_module.created_at + created_at: archived_module.created_at, + updated_at: archived_module.created_at ).sneaky_save # Activity for archiving archived module @@ -276,7 +280,8 @@ module FirstTimeDataGenerator user: user.full_name, module: archived_module.name ), - created_at: archived_module.archived_on + created_at: archived_module.archived_on, + updated_at: archived_module.archived_on ).sneaky_save # Assign new user to archived module @@ -297,7 +302,8 @@ module FirstTimeDataGenerator module: archived_module.name, assigned_by_user: user.full_name ), - created_at: generate_random_time(archived_module.created_at, 2.minutes) + created_at: generate_random_time(archived_module.created_at, 2.minutes), + updated_at: generate_random_time(archived_module.created_at, 2.minutes) ).sneaky_save # Assign 4 samples to modules @@ -526,6 +532,7 @@ module FirstTimeDataGenerator my_module: my_modules[1], user: user, created_at: temp_result.created_at, + updated_at: temp_result.created_at, message: I18n.t( 'activities.add_text_result', user: user.full_name, @@ -578,6 +585,7 @@ module FirstTimeDataGenerator my_module: my_modules[2], user: user, created_at: temp_result.created_at, + updated_at: temp_result.created_at, message: I18n.t( 'activities.add_text_result', user: user.full_name, @@ -734,6 +742,7 @@ module FirstTimeDataGenerator my_module: my_modules[5], user: user, created_at: temp_result.created_at, + updated_at: temp_result.created_at, message: I18n.t( 'activities.add_table_result', user: user.full_name, @@ -863,6 +872,7 @@ module FirstTimeDataGenerator my_module: my_modules[7], user: user, created_at: temp_result.created_at, + updated_at: temp_result.created_at, message: I18n.t( 'activities.add_text_result', user: user.full_name, @@ -922,6 +932,7 @@ module FirstTimeDataGenerator my_module: my_module, user: step.user, created_at: created_at, + updated_at: created_at, message: I18n.t( 'activities.create_step', user: step.user.full_name, @@ -936,6 +947,7 @@ module FirstTimeDataGenerator my_module: my_module, user: step.user, created_at: completed_on, + updated_at: completed_on, message: I18n.t( 'activities.complete_step', user: step.user.full_name, @@ -980,6 +992,7 @@ module FirstTimeDataGenerator user: user, project: project, created_at: created_at, + updated_at: created_at, message: t('activities.add_comment_to_project', user: user.full_name, project: project.name) @@ -1000,6 +1013,7 @@ module FirstTimeDataGenerator project: my_module.experiment.project, my_module: my_module, created_at: created_at, + updated_at: created_at, message: t('activities.add_comment_to_module', user: user.full_name, module: my_module.name) @@ -1020,6 +1034,7 @@ module FirstTimeDataGenerator project: result.my_module.experiment.project, my_module: result.my_module, created_at: created_at, + updated_at: created_at, message: t('activities.add_comment_to_result', user: user.full_name, result: result.name) @@ -1040,6 +1055,7 @@ module FirstTimeDataGenerator project: step.protocol.my_module.experiment.project, my_module: step.protocol.my_module, created_at: created_at, + updated_at: created_at, message: t('activities.add_comment_to_step', user: user.full_name, step: step.position + 1, diff --git a/db/migrate/20170509113030_remove_updated_at_from_activity.rb b/db/migrate/20170509113030_remove_updated_at_from_activity.rb deleted file mode 100644 index b38a2fa20..000000000 --- a/db/migrate/20170509113030_remove_updated_at_from_activity.rb +++ /dev/null @@ -1,5 +0,0 @@ -class RemoveUpdatedAtFromActivity < ActiveRecord::Migration - def change - remove_column :activities, :updated_at, :datetime - end -end From 81a3cb0a418b57c2d9dd854aa4924af69d96664c Mon Sep 17 00:00:00 2001 From: zmagod Date: Thu, 11 May 2017 16:54:28 +0200 Subject: [PATCH 04/29] adds results js code in modules --- .../javascripts/my_modules/results.js.erb | 15 +- .../javascripts/results/result_assets.js | 146 ++++++------ .../javascripts/results/result_tables.js.erb | 221 +++++++++--------- .../javascripts/results/result_texts.js | 155 ++++++------ app/views/result_assets/_edit.html.erb | 4 +- app/views/result_assets/_new.html.erb | 4 +- app/views/result_comments/_index.html.erb | 3 +- app/views/result_tables/_edit.html.erb | 4 +- app/views/result_tables/_new.html.erb | 4 +- app/views/result_texts/_edit.html.erb | 4 +- app/views/result_texts/_new.html.erb | 4 +- 11 files changed, 302 insertions(+), 262 deletions(-) diff --git a/app/assets/javascripts/my_modules/results.js.erb b/app/assets/javascripts/my_modules/results.js.erb index 9f0c1221c..3f8d801c0 100644 --- a/app/assets/javascripts/my_modules/results.js.erb +++ b/app/assets/javascripts/my_modules/results.js.erb @@ -5,7 +5,6 @@ 'use strict'; global.Results = (function() { - var self = this; var ResultTypeEnum = Object.freeze({ FILE: 0, TABLE: 1, @@ -14,10 +13,10 @@ }); function init() { - self.initHandsOnTables($(document)); + initHandsOnTables($(document)); _expandAllResults(); _initTutorial(); - self.applyCollapseLinkCallBack(); + applyCollapseLinkCallBack(); Comments.bindNewElement(); Comments.initialize(); @@ -143,7 +142,7 @@ var steps = [{ element: $('#results-toolbar')[0], intro: I18n.t('tutorial.module_results_html') - }, {ResultTypeEnum + }, { element: samplesTab[0], intro: I18n.t('tutorial.module_results_click_samples_html'), position: 'left' @@ -158,7 +157,7 @@ $form.clearFormErrors(); switch(resultTypeEnum) { - case self.ResultTypeEnum.FILE: + case ResultTypeEnum.FILE: var $nameInput = $form.find('#result_name'); var nameValid = textValidator(ev, $nameInput, 0, <%= Constants::NAME_MAX_LENGTH %>); @@ -175,19 +174,19 @@ } break; - case self.ResultTypeEnum.TABLE: + case ResultTypeEnum.TABLE: var $nameInput = $form.find('#result_name'); var nameValid = textValidator(ev, $nameInput, 0, <%= Constants::NAME_MAX_LENGTH %>); break; - case self.ResultTypeEnum.TEXT: + case ResultTypeEnum.TEXT: var $nameInput = $form.find('#result_name'); var nameValid = textValidator(ev, $nameInput, 0, <%= Constants::NAME_MAX_LENGTH %>); var $textInput = TinyMCE.getContent(); textValidator(ev, $textInput, 1, <%= Constants::TEXT_MAX_LENGTH %>, false, true); break; - case self.ResultTypeEnum.COMMENT: + case ResultTypeEnum.COMMENT: var $commentInput = $form.find('#comment_message'); var commentValid = textValidator(ev, $commentInput, 1, <%= Constants::TEXT_MAX_LENGTH %>); diff --git a/app/assets/javascripts/results/result_assets.js b/app/assets/javascripts/results/result_assets.js index 0e729fc74..10ffad4e8 100644 --- a/app/assets/javascripts/results/result_assets.js +++ b/app/assets/javascripts/results/result_assets.js @@ -1,93 +1,93 @@ (function(global) { 'use strict'; - var ResutlAssetHandler = (function() { - var self = this; - var publicAPI = Object.freeze({ - initNewResultAsset: function initNewResultAsset() { - // New result asset behaviour - $('#new-result-asset').on('ajax:success', function(e, data) { - var $form = $(data.html); - $('#results').prepend($form); - debugger; - self.formAjaxResultAsset($form); + var ResutlAssets = (function() { + // New result asset behaviour + function initNewResultAsset() { + $('#new-result-asset').on('ajax:success', function(e, data) { + var $form = $(data.html); + $('#results').prepend($form); - // Cancel button - $form.find('.cancel-new').click(function () { - $form.remove(); - toggleResultEditButtons(true); - }); + _formAjaxResultAsset($form); - toggleResultEditButtons(false); - - $('#result_name').focus(); + // Cancel button + $form.find('.cancel-new').click(function () { + $form.remove(); + Results.toggleResultEditButtons(true); }); - $('#new-result-asset') - .on('ajax:error', function(e, xhr, status, error) { - animateSpinner(null, false); - }); - }, - applyEditResultAssetCallback: function applyEditResultAssetCallback() { - $('.edit-result-asset').on('ajax:success', function(e, data) { - var $result = $(this).closest('.result'); - var $form = $(data.html); - var $prevResult = $result; - $result.after($form); - $result.remove(); + Results.toggleResultEditButtons(false); - formAjaxResultAsset($form); + $('#result_name').focus(); + }).on('ajax:error', function(e, xhr, status, error) { + animateSpinner(null, false); + }); + } - // Cancel button - $form.find('.cancel-edit').click(function () { - $form.after($prevResult); - $form.remove(); - applyEditResultAssetCallback(); - toggleResultEditButtons(true); - initPreviewModal(); - }); + function applyEditResultAssetCallback() { + $('.edit-result-asset').on('ajax:success', function(e, data) { + var $result = $(this).closest('.result'); + var $form = $(data.html); + var $prevResult = $result; + $result.after($form); + $result.remove(); - toggleResultEditButtons(false); + _formAjaxResultAsset($form); - $('#result_name').focus(); - }); - - $('.edit-result-asset') - .on('ajax:error', function(e, xhr, status, error) { - animateSpinner(null, false); - }); - }, - formAjaxResultAsset: function formAjaxResultAsset($form) { - $form.on('ajax:success', function(e, data) { - $form.after(data.html); - var $newResult = $form.next(); - initFormSubmitLinks($newResult); - $(this).remove(); + // Cancel button + $form.find('.cancel-edit').click(function () { + $form.after($prevResult); + $form.remove(); applyEditResultAssetCallback(); - Results.applyCollapseLinkCallBack(); - - toggleResultEditButtons(true); - expandResult($newResult); + Results.toggleResultEditButtons(true); initPreviewModal(); - Comments.initialize(); - }).on('ajax:error', function(e, data) { - // This check is here only because of remotipart bug, which returns - // HTML instead of JSON, go figure - var errors = ''; - if (data.errors) - errors = data.errors; - else - errors = data.responseJSON.errors; - $form.renderFormErrors('result', errors, true, e); - animateSpinner(null, false); }); - } + + Results.toggleResultEditButtons(false); + + $('#result_name').focus(); + }).on('ajax:error', function(e, xhr, status, error) { + animateSpinner(null, false); + }); + } + + function _formAjaxResultAsset($form) { + $form.on('ajax:success', function(e, data) { + $form.after(data.html); + var $newResult = $form.next(); + initFormSubmitLinks($newResult); + $(this).remove(); + applyEditResultAssetCallback(); + Results.applyCollapseLinkCallBack(); + + Results.toggleResultEditButtons(true); + Results.expandResult($newResult); + initPreviewModal(); + Comments.initialize(); + }).on('ajax:error', function(e, data) { + // This check is here only because of remotipart bug, which returns + // HTML instead of JSON, go figure + var errors = ''; + if (data.errors) + errors = data.errors; + else + errors = data.responseJSON.errors; + $form.renderFormErrors('result', errors, true, e); + animateSpinner(null, false); + }); + } + + var publicAPI = Object.freeze({ + initNewResultAsset: initNewResultAsset, + applyEditResultAssetCallback: applyEditResultAssetCallback }); return publicAPI; })(); - ResutlAssetHandler.initNewResultAsset(); - ResutlAssetHandler.applyEditResultAssetCallback(); - global.initPreviewModal(); + $(document).ready(function() { + ResutlAssets.initNewResultAsset(); + ResutlAssets.applyEditResultAssetCallback(); + global.initPreviewModal(); + }); })(window); diff --git a/app/assets/javascripts/results/result_tables.js.erb b/app/assets/javascripts/results/result_tables.js.erb index c9c05b8fc..c2c6a2c59 100644 --- a/app/assets/javascripts/results/result_tables.js.erb +++ b/app/assets/javascripts/results/result_tables.js.erb @@ -1,111 +1,124 @@ -// Init handsontable which can be edited -function initEditableHandsOnTable(root) { - root.find(".editable-table").each(function() { - var $container = $(this).find(".hot"); - var data = null; - var contents = $(this).find('.hot-contents'); - if (contents.attr("value")) { - data = JSON.parse(contents.attr("value")).data; - } +(function() { + 'use strict'; - $container.handsontable({ - data: data, - startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>, - startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>, - minRows: 1, - minCols: 1, - rowHeaders: true, - colHeaders: true, - contextMenu: true, - formulas: true, - preventOverflow: 'horizontal' - }); - }); -} + var ResultTables = (function() { + // Init handsontable which can be edited + function _initEditableHandsOnTable(root) { + root.find('.editable-table').each(function() { + var $container = $(this).find('.hot'); + var data = null; + var contents = $(this).find('.hot-contents'); + if (contents.attr('value')) { + data = JSON.parse(contents.attr('value')).data; + } -function onSubmitExtractTable($form) { - $form.submit(function(){ - var hot = $(".hot").handsontable('getInstance'); - var contents = $('.hot-contents'); - var data = JSON.stringify({data: hot.getData()}); - contents.attr("value", data); - return true; - }); -} + $container.handsontable({ + data: data, + startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>, + startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>, + minRows: 1, + minCols: 1, + rowHeaders: true, + colHeaders: true, + contextMenu: true, + formulas: true, + preventOverflow: 'horizontal' + }); + }); + } -// Edit result table button behaviour -function applyEditResultTableCallback() { - $(".edit-result-table").on("ajax:success", function(e, data) { - var $result = $(this).closest(".result"); - var $form = $(data.html); - var $prevResult = $result; - $result.after($form); - $result.remove(); + function _onSubmitExtractTable($form) { + $form.submit(function(){ + var hot = $('.hot').handsontable('getInstance'); + var contents = $('.hot-contents'); + var data = JSON.stringify({data: hot.getData()}); + contents.attr('value', data); + return true; + }); + } - formAjaxResultTable($form); - initEditableHandsOnTable($form); - onSubmitExtractTable($form); + // Apply ajax callback to form + function _formAjaxResultTable($form) { + $form.on('ajax:success', function(e, data) { + var $result; + $form.after(data.html); + $result = $(this).next(); + initFormSubmitLinks($result); + $(this).remove(); - // Cancel button - $form.find(".cancel-edit").click(function () { - $form.after($prevResult); - $form.remove(); - applyEditResultTableCallback(); - toggleResultEditButtons(true); + applyEditResultTableCallback(); + Results.applyCollapseLinkCallBack(); + Results.initHandsOnTables($result); + Results.toggleResultEditButtons(true); + Results.expandResult($result); + Comments.initialize(); + }); + $form.on('ajax:error', function(e, xhr, status, error) { + var data = xhr.responseJSON; + $form.renderFormErrors('result', data); + }); + } + + // Edit result table button behaviour + function applyEditResultTableCallback() { + $('.edit-result-table').on('ajax:success', function(e, data) { + var $result = $(this).closest('.result'); + var $form = $(data.html); + var $prevResult = $result; + $result.after($form); + $result.remove(); + + _formAjaxResultTable($form); + _initEditableHandsOnTable($form); + _onSubmitExtractTable($form); + + // Cancel button + $form.find('.cancel-edit').click(function () { + $form.after($prevResult); + $form.remove(); + applyEditResultTableCallback(); + Results.toggleResultEditButtons(true); + }); + + Results.toggleResultEditButtons(false); + + $('#result_name').focus(); + }); + } + + // New result text behaviour + function initNewResultTable() { + $('#new-result-table').on('ajax:success', function(e, data) { + var $form = $(data.html); + $('#results').prepend($form); + + _formAjaxResultTable($form); + _initEditableHandsOnTable($form); + _onSubmitExtractTable($form); + + // Cancel button + $form.find('.cancel-new').click(function () { + $form.remove(); + Results.toggleResultEditButtons(true); + }); + + Results.toggleResultEditButtons(false); + + $('#result_name').focus(); + }); + } + + var publicAPI = Object.freeze({ + initNewResultTable: initNewResultTable, + applyEditResultTableCallback: applyEditResultTableCallback + }); + + return publicAPI; + })(); + + $(document).ready(function() { + ResultTables.initNewResultTable(); + ResultTables.applyEditResultTableCallback(); }); - toggleResultEditButtons(false); - - $("#result_name").focus(); - }); - - $(".edit-result-table").on("ajax:error", function(e, xhr, status, error) { - //TODO: Add error handling - }); -} -// New result text behaviour -$("#new-result-table").on("ajax:success", function(e, data) { - var $form = $(data.html); - $("#results").prepend($form); - - formAjaxResultTable($form); - initEditableHandsOnTable($form); - onSubmitExtractTable($form); - - // Cancel button - $form.find(".cancel-new").click(function () { - $form.remove(); - toggleResultEditButtons(true); - }); - - toggleResultEditButtons(false); - - $("#result_name").focus(); -}); - -$("#new-result-table").on("ajax:error", function(e, xhr, status, error) { - //TODO: Add error handling -}); - -// Apply ajax callback to form -function formAjaxResultTable($form) { - $form.on("ajax:success", function(e, data) { - $form.after(data.html); - $result = $(this).next(); - initFormSubmitLinks($result); - $(this).remove(); - - applyEditResultTableCallback(); - Results.applyCollapseLinkCallBack(); - Results.initHandsOnTables($result); - toggleResultEditButtons(true); - expandResult($result); - Comments.initialize(); - }); - $form.on("ajax:error", function(e, xhr, status, error) { - var data = xhr.responseJSON; - $form.renderFormErrors("result", data); - }); -} - -applyEditResultTableCallback(); +})(); diff --git a/app/assets/javascripts/results/result_texts.js b/app/assets/javascripts/results/result_texts.js index 466a68ded..0c7bb9403 100644 --- a/app/assets/javascripts/results/result_texts.js +++ b/app/assets/javascripts/results/result_texts.js @@ -1,81 +1,96 @@ -// New result text behaviour -$("#new-result-text").on("ajax:success", function(e, data) { - var $form = $(data.html); - $("#results").prepend($form); +(function() { + 'use strict'; - formAjaxResultText($form); + var ResultText = (function() { + // New result text behaviour + function initNewReslutText() { + $('#new-result-text').on('ajax:success', function(e, data) { + var $form = $(data.html); + $('#results').prepend($form); - // Cancel button - $form.find(".cancel-new").click(function () { - $form.remove(); - toggleResultEditButtons(true); - }); - toggleResultEditButtons(false); - TinyMCE.refresh(); - $("#result_name").focus(); -}); + _formAjaxResultText($form); -$("#new-result-text").on("ajax:error", function(e, xhr, status, error) { - //TODO: Add error handling -}); + // Cancel button + $form.find('.cancel-new').click(function() { + $form.remove(); + Results.toggleResultEditButtons(true); + }); + Results.toggleResultEditButtons(false); + TinyMCE.refresh(); + TinyMCE.highlight(); + $('#result_name').focus(); + }).on('ajax:error', function() { + TinyMCE.refresh(); + }); + } -// Edit result text button behaviour -function applyEditResultTextCallback() { - $(".edit-result-text").on("ajax:success", function(e, data) { - var $result = $(this).closest(".result"); - var $form = $(data.html); - var $prevResult = $result; - $result.after($form); - $result.remove(); - formAjaxResultText($form); + // Edit result text button behaviour + function applyEditResultTextCallback() { + $('.edit-result-text').on('ajax:success', function(e, data) { + var $result = $(this).closest('.result'); + var $form = $(data.html); + var $prevResult = $result; + $result.after($form); + $result.remove(); - // Cancel button - $form.find(".cancel-edit").click(function () { - $form.after($prevResult); - $form.remove(); - applyEditResultTextCallback(); - toggleResultEditButtons(true); + _formAjaxResultText($form); + + // Cancel button + $form.find('.cancel-edit').click(function () { + $form.after($prevResult); + $form.remove(); + applyEditResultTextCallback(); + Results.toggleResultEditButtons(true); + }); + Results.toggleResultEditButtons(false); + TinyMCE.refresh(); + $('#result_name').focus(); }); - toggleResultEditButtons(false); - TinyMCE.refresh(); - $("#result_name").focus(); + } + + // Apply ajax callback to form + function _formAjaxResultText($form) { + $form.on('ajax:success', function(e, data) { + $form.after(data.html); + var newResult = $form.next(); + initFormSubmitLinks(newResult); + $(this).remove(); + + applyEditResultTextCallback(); + Results.applyCollapseLinkCallBack(); + Results.toggleResultEditButtons(true); + Results.expandResult(newResult); + TinyMCE.destroyAll(); + Comments.initialize(); + }); + $form.on('ajax:error', function(e, xhr, status, error) { + var data = xhr.responseJSON; + $form.renderFormErrors('result', data); + TinyMCE.highlight(); + if (data['result_text.text']) { + var $el = $form.find( + 'textarea[name=result\\[result_text_attributes\\]\\[text\\]]' + ); + + $el.closest('.form-group').addClass('has-error'); + $el.parent().append('' + + data['result_text.text'] + ''); + } + }); + } + + var publicAPI = Object.freeze({ + initNewReslutText: initNewReslutText, + applyEditResultTextCallback: applyEditResultTextCallback }); - $(".edit-result-text").on("ajax:error", function(e, xhr, status, error) { - //TODO: Add error handling - }); -} + return publicAPI; + })(); -// Apply ajax callback to form -function formAjaxResultText($form) { - $form.on("ajax:success", function(e, data) { - $form.after(data.html); - var newResult = $form.next(); - initFormSubmitLinks(newResult); - $(this).remove(); + $(document).ready(function() { + ResultText.initNewReslutText(); + ResultText.applyEditResultTextCallback(); + }); - applyEditResultTextCallback(); - Results.applyCollapseLinkCallBack(); - toggleResultEditButtons(true); - expandResult(newResult); - TinyMCE.destroyAll(); - Comments.initialize(); - }); - $form.on("ajax:error", function(e, xhr, status, error) { - var data = xhr.responseJSON; - $form.renderFormErrors("result", data); - TinyMCE.highlight(); - if (data["result_text.text"]) { - var $el = $form.find("textarea[name=result\\[result_text_attributes\\]\\[text\\]]"); - - $el.closest(".form-group").addClass("has-error"); - $el.parent().append("" + data["result_text.text"] + ""); - } - }); -} - -$(document).ready(function() { - TinyMCE.highlight(); -}); -applyEditResultTextCallback(); +})(); diff --git a/app/views/result_assets/_edit.html.erb b/app/views/result_assets/_edit.html.erb index 2de29c1e0..f27e4bee2 100644 --- a/app/views/result_assets/_edit.html.erb +++ b/app/views/result_assets/_edit.html.erb @@ -10,7 +10,9 @@ <%= ff.file_field :file %> <% end %>
- <%= f.submit t("result_assets.edit.update"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.FILE, true);" %> + <%= f.submit t("result_assets.edit.update"), + class: 'btn btn-primary save-result', + onclick: "Results.processResult(event, Results.ResultTypeEnum.FILE, true);" %> diff --git a/app/views/result_assets/_new.html.erb b/app/views/result_assets/_new.html.erb index d938ac740..d4fa8e0bf 100644 --- a/app/views/result_assets/_new.html.erb +++ b/app/views/result_assets/_new.html.erb @@ -4,7 +4,9 @@ <%= 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: "processResult(event, ResultTypeEnum.FILE, false);" %> + <%= f.submit t("result_assets.new.create"), + class: 'btn btn-primary save-result', + onclick: "Results.processResult(event, Results.ResultTypeEnum.FILE, false);" %> diff --git a/app/views/result_comments/_index.html.erb b/app/views/result_comments/_index.html.erb index f68116d0d..12cd6d445 100644 --- a/app/views/result_comments/_index.html.erb +++ b/app/views/result_comments/_index.html.erb @@ -26,7 +26,8 @@ single_line: true, hide_label: true, placeholder: t("general.comment_placeholder"), - append: f.submit("+", onclick: "processResult(event, ResultTypeEnum.COMMENT, false);"), + append: f.submit("+", + onclick: "Results.processResult(event, Results.ResultTypeEnum.COMMENT, false);"), help: '.', data: { 'atwho-edit' => '' } %> <% end %> diff --git a/app/views/result_tables/_edit.html.erb b/app/views/result_tables/_edit.html.erb index 03d3897b0..d71d87624 100644 --- a/app/views/result_tables/_edit.html.erb +++ b/app/views/result_tables/_edit.html.erb @@ -9,7 +9,9 @@ <% end %>
- <%= f.submit t("result_tables.edit.update"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TABLE, true);" %> + <%= f.submit t("result_tables.edit.update"), + class: 'btn btn-primary save-result', + onclick: "Results.processResult(event, Results.ResultTypeEnum.TABLE, true);" %> diff --git a/app/views/result_tables/_new.html.erb b/app/views/result_tables/_new.html.erb index 60037e93e..c76dc472e 100644 --- a/app/views/result_tables/_new.html.erb +++ b/app/views/result_tables/_new.html.erb @@ -8,7 +8,9 @@ <% end %> - <%= f.submit t("result_tables.new.create"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TABLE, false);" %> + <%= f.submit t("result_tables.new.create"), + class: 'btn btn-primary save-result', + onclick: "Results.processResult(event, Results.ResultTypeEnum.TABLE, false);" %> diff --git a/app/views/result_texts/_edit.html.erb b/app/views/result_texts/_edit.html.erb index 10acf25ce..f49606663 100644 --- a/app/views/result_texts/_edit.html.erb +++ b/app/views/result_texts/_edit.html.erb @@ -9,7 +9,9 @@ object_id: @result.result_text.id }) %> <% end %>
- <%= f.submit t("result_texts.edit.update"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TEXT, true);" %> + <%= f.submit t("result_texts.edit.update"), + class: 'btn btn-primary save-result', + onclick: "Results.processResult(event, Results.ResultTypeEnum.TEXT, true);" %> diff --git a/app/views/result_texts/_new.html.erb b/app/views/result_texts/_new.html.erb index fc340637c..8d97a98ef 100644 --- a/app/views/result_texts/_new.html.erb +++ b/app/views/result_texts/_new.html.erb @@ -7,7 +7,9 @@ object_id: @result.result_text.id }) %> <% end %>
- <%= f.submit t("result_texts.new.create"), class: 'btn btn-primary save-result', onclick: "processResult(event, ResultTypeEnum.TEXT, false);" %> + <%= f.submit t("result_texts.new.create"), + class: 'btn btn-primary save-result', + onclick: "Results.processResult(event, Results.ResultTypeEnum.TEXT, false);" %> From 070a829c490c468a0eb3ffe7e026f013125d2d5d Mon Sep 17 00:00:00 2001 From: zmagod Date: Fri, 12 May 2017 10:02:33 +0200 Subject: [PATCH 05/29] change new results hendlers --- app/assets/javascripts/results/result_assets.js | 1 + app/views/my_modules/results.html.erb | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/app/assets/javascripts/results/result_assets.js b/app/assets/javascripts/results/result_assets.js index 10ffad4e8..f99113396 100644 --- a/app/assets/javascripts/results/result_assets.js +++ b/app/assets/javascripts/results/result_assets.js @@ -5,6 +5,7 @@ // New result asset behaviour function initNewResultAsset() { $('#new-result-asset').on('ajax:success', function(e, data) { + debugger; var $form = $(data.html); $('#results').prepend($form); diff --git a/app/views/my_modules/results.html.erb b/app/views/my_modules/results.html.erb index f935e446e..f03a6b250 100644 --- a/app/views/my_modules/results.html.erb +++ b/app/views/my_modules/results.html.erb @@ -18,19 +18,28 @@ <% end %> <% if can_create_result_text_in_module(@my_module) %> - + <% end %> <% if can_create_result_table_in_module(@my_module) %> - + <% end %> <% if can_create_result_asset_in_module(@my_module) %> - + From d34b2520b51b06df77942b47ba23c3854aacf98d Mon Sep 17 00:00:00 2001 From: zmagod Date: Fri, 12 May 2017 15:59:58 +0200 Subject: [PATCH 06/29] refactor results javascript, fixes bug with results archive [fixes SCI-1262] prevents duplicate request [fixes SCI-1248] --- .../javascripts/my_modules/results.js.erb | 29 +++- .../javascripts/results/result_assets.js | 41 +++--- .../javascripts/results/result_tables.js.erb | 43 +++--- .../javascripts/results/result_texts.js | 130 ++++++++++-------- app/views/my_modules/_result.html.erb | 7 +- 5 files changed, 155 insertions(+), 95 deletions(-) diff --git a/app/assets/javascripts/my_modules/results.js.erb b/app/assets/javascripts/my_modules/results.js.erb index 3f8d801c0..ad3608600 100644 --- a/app/assets/javascripts/my_modules/results.js.erb +++ b/app/assets/javascripts/my_modules/results.js.erb @@ -88,7 +88,7 @@ // Toggle editing buttons function toggleResultEditButtons(show) { - if (show) { + if(show) { $('#results-toolbar').show(); $('.edit-result-button').show(); } else { @@ -194,6 +194,29 @@ } } + // init cancel button + function initCancelFormButton(form, callback) { + $(form).find('.cancel-new').click(function(event) { + event.preventDefault(); + event.stopPropagation(); + event.stopImmediatePropagation(); + $(form).remove(); + toggleResultEditButtons(true); + callback(); + }); + } + + function archive(e, element) { + e.preventDefault(); + e.stopPropagation(); + e.stopImmediatePropagation(); + var el = $(element); + if(confirm(el.data('confirm-text'))) { + animateSpinner(); + $('#' + el.data('form-id')).submit(); + } + } + var publicAPI = Object.freeze({ init: init, initHandsOnTables: initHandsOnTables, @@ -201,7 +224,9 @@ toggleResultEditButtons: toggleResultEditButtons, expandResult: expandResult, processResult: processResult, - ResultTypeEnum: ResultTypeEnum + ResultTypeEnum: ResultTypeEnum, + initCancelFormButton: initCancelFormButton, + archive: archive }); return publicAPI; diff --git a/app/assets/javascripts/results/result_assets.js b/app/assets/javascripts/results/result_assets.js index f99113396..cf9f0e456 100644 --- a/app/assets/javascripts/results/result_assets.js +++ b/app/assets/javascripts/results/result_assets.js @@ -4,24 +4,32 @@ var ResutlAssets = (function() { // New result asset behaviour function initNewResultAsset() { - $('#new-result-asset').on('ajax:success', function(e, data) { - debugger; - var $form = $(data.html); - $('#results').prepend($form); + $('#new-result-asset').on('click', function(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + event.stopPropagation(); + var $btn = $(this); + $btn.off(); + animateSpinner(null, true); - _formAjaxResultAsset($form); - - // Cancel button - $form.find('.cancel-new').click(function () { - $form.remove(); - Results.toggleResultEditButtons(true); + // get new result form + $.ajax({ + url: $btn.data('href'), + method: 'GET', + success: function(data) { + var $form = $(data.html); + animateSpinner(null, false); + $('#results').prepend($form); + _formAjaxResultAsset($form); + Results.initCancelFormButton($form, initNewResultAsset); + Results.toggleResultEditButtons(false); + $('#result_name').focus(); + }, + error: function() { + animateSpinner(null, false); + initNewResultAsset(); + } }); - - Results.toggleResultEditButtons(false); - - $('#result_name').focus(); - }).on('ajax:error', function(e, xhr, status, error) { - animateSpinner(null, false); }); } @@ -65,6 +73,7 @@ Results.expandResult($newResult); initPreviewModal(); Comments.initialize(); + initNewResultAsset(); }).on('ajax:error', function(e, data) { // This check is here only because of remotipart bug, which returns // HTML instead of JSON, go figure diff --git a/app/assets/javascripts/results/result_tables.js.erb b/app/assets/javascripts/results/result_tables.js.erb index c2c6a2c59..c14ae013f 100644 --- a/app/assets/javascripts/results/result_tables.js.erb +++ b/app/assets/javascripts/results/result_tables.js.erb @@ -52,6 +52,7 @@ Results.toggleResultEditButtons(true); Results.expandResult($result); Comments.initialize(); + initNewResultTable(); }); $form.on('ajax:error', function(e, xhr, status, error) { var data = xhr.responseJSON; @@ -88,23 +89,33 @@ // New result text behaviour function initNewResultTable() { - $('#new-result-table').on('ajax:success', function(e, data) { - var $form = $(data.html); - $('#results').prepend($form); - - _formAjaxResultTable($form); - _initEditableHandsOnTable($form); - _onSubmitExtractTable($form); - - // Cancel button - $form.find('.cancel-new').click(function () { - $form.remove(); - Results.toggleResultEditButtons(true); + $('#new-result-table').on('click', function(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + event.stopPropagation(); + var $btn = $(this); + $btn.off(); + animateSpinner(null, true); + // get new result form + $.ajax({ + url: $btn.data('href'), + method: 'GET', + success: function(data) { + var $form = $(data.html); + animateSpinner(null, false); + $('#results').prepend($form); + _formAjaxResultTable($form); + _initEditableHandsOnTable($form); + _onSubmitExtractTable($form); + Results.initCancelFormButton($form, initNewResultTable); + Results.toggleResultEditButtons(false); + $('#result_name').focus(); + }, + error: function() { + animateSpinner(null, false); + initNewResultTable(); + } }); - - Results.toggleResultEditButtons(false); - - $('#result_name').focus(); }); } diff --git a/app/assets/javascripts/results/result_texts.js b/app/assets/javascripts/results/result_texts.js index 0c7bb9403..8a8a83516 100644 --- a/app/assets/javascripts/results/result_texts.js +++ b/app/assets/javascripts/results/result_texts.js @@ -4,80 +4,91 @@ var ResultText = (function() { // New result text behaviour function initNewReslutText() { - $('#new-result-text').on('ajax:success', function(e, data) { - var $form = $(data.html); - $('#results').prepend($form); + $('#new-result-text').on('click', function(event) { + event.preventDefault(); + event.stopImmediatePropagation(); + event.stopPropagation(); + var $btn = $(this); + $btn.off(); + animateSpinner(null, true); - _formAjaxResultText($form); - - // Cancel button - $form.find('.cancel-new').click(function() { - $form.remove(); - Results.toggleResultEditButtons(true); - }); - Results.toggleResultEditButtons(false); - TinyMCE.refresh(); - TinyMCE.highlight(); - $('#result_name').focus(); - }).on('ajax:error', function() { - TinyMCE.refresh(); + // get new result form + $.ajax({ + url: $btn.data('href'), + method: 'GET', + success: function(data) { + var $form = $(data.html); + animateSpinner(null, false); + $('#results').prepend($form); + _formAjaxResultText($form); + Results.initCancelFormButton($form, initNewReslutText); + Results.toggleResultEditButtons(false); + TinyMCE.refresh(); + TinyMCE.highlight(); + $('#result_name').focus(); + }, + error: function() { + animateSpinner(null, false); + initNewReslutText(); + } + }) }); } - // Edit result text button behaviour function applyEditResultTextCallback() { - $('.edit-result-text').on('ajax:success', function(e, data) { - var $result = $(this).closest('.result'); - var $form = $(data.html); - var $prevResult = $result; - $result.after($form); - $result.remove(); + $('.edit-result-text').on('ajax:success', function(e, data) { + var $result = $(this).closest('.result'); + var $form = $(data.html); + var $prevResult = $result; + $result.after($form); + $result.remove(); - _formAjaxResultText($form); + _formAjaxResultText($form); - // Cancel button - $form.find('.cancel-edit').click(function () { - $form.after($prevResult); - $form.remove(); - applyEditResultTextCallback(); - Results.toggleResultEditButtons(true); - }); - Results.toggleResultEditButtons(false); - TinyMCE.refresh(); - $('#result_name').focus(); + // Cancel button + $form.find('.cancel-edit').click(function() { + $form.after($prevResult); + $form.remove(); + applyEditResultTextCallback(); + Results.toggleResultEditButtons(true); }); + Results.toggleResultEditButtons(false); + TinyMCE.refresh(); + $('#result_name').focus(); + }); } // Apply ajax callback to form function _formAjaxResultText($form) { - $form.on('ajax:success', function(e, data) { - $form.after(data.html); - var newResult = $form.next(); - initFormSubmitLinks(newResult); - $(this).remove(); + $form.on('ajax:success', function(e, data) { + $form.after(data.html); + var newResult = $form.next(); + initFormSubmitLinks(newResult); + $(this).remove(); - applyEditResultTextCallback(); - Results.applyCollapseLinkCallBack(); - Results.toggleResultEditButtons(true); - Results.expandResult(newResult); - TinyMCE.destroyAll(); - Comments.initialize(); - }); - $form.on('ajax:error', function(e, xhr, status, error) { - var data = xhr.responseJSON; - $form.renderFormErrors('result', data); - TinyMCE.highlight(); - if (data['result_text.text']) { - var $el = $form.find( - 'textarea[name=result\\[result_text_attributes\\]\\[text\\]]' - ); + applyEditResultTextCallback(); + Results.applyCollapseLinkCallBack(); + Results.toggleResultEditButtons(true); + Results.expandResult(newResult); + TinyMCE.destroyAll(); + Comments.initialize(); + initNewReslutText(); + }); + $form.on('ajax:error', function(e, xhr, status, error) { + var data = xhr.responseJSON; + $form.renderFormErrors('result', data); + TinyMCE.highlight(); + if (data['result_text.text']) { + var $el = $form.find( + 'textarea[name=result\\[result_text_attributes\\]\\[text\\]]' + ); - $el.closest('.form-group').addClass('has-error'); - $el.parent().append('' + - data['result_text.text'] + ''); - } - }); + $el.closest('.form-group').addClass('has-error'); + $el.parent().append('' + + data['result_text.text'] + ''); + } + }); } var publicAPI = Object.freeze({ @@ -92,5 +103,4 @@ ResultText.initNewReslutText(); ResultText.applyEditResultTextCallback(); }); - })(); diff --git a/app/views/my_modules/_result.html.erb b/app/views/my_modules/_result.html.erb index 07fcc5956..5c11d0553 100644 --- a/app/views/my_modules/_result.html.erb +++ b/app/views/my_modules/_result.html.erb @@ -19,7 +19,12 @@ <% end %> <% if can_archive_result(result) && !result.archived && result_unlocked?(result) %> - + <%= form_for :result, url: result_path_of_type(result), method: :patch, html: {id: 'result-archive-form-' + result.id.to_s } do |f| %> From 01972ab6a7c0e2bed0cda0538b42d3d24144574f Mon Sep 17 00:00:00 2001 From: zmagod Date: Mon, 15 May 2017 15:22:43 +0200 Subject: [PATCH 07/29] changes load protocol label [fixes SCI-1240] --- config/locales/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index c3578c908..befc67aa0 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -544,7 +544,7 @@ en: load_from_repository_modal: title: "Load protocol from repository" text: "Choose the protocol to be loaded to the task." - text2: "This will overwrite the current protocol!" + text2: "This action will overwrite the current protocol in the task and unlink it from repository. The current protocol will remain unchanged in repository." tab_public: "Public protocols" tab_private: "Private protocols" thead_name: "Name" From 27cfd55ea589892c2424cede3a0f98326369a3fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Tue, 9 May 2017 14:22:26 +0200 Subject: [PATCH 08/29] Simplified popup modal for adding contents to report. [fixes SCI-487] --- app/assets/stylesheets/reports.scss | 9 ++ .../new/modal/_experiment_contents.html.erb | 8 +- .../new/modal/_module_contents.html.erb | 10 +- .../new/modal/_module_contents_inner.html.erb | 81 +++++----- .../new/modal/_project_contents.html.erb | 140 +++++++++--------- .../modal/_project_contents_inner.html.erb | 55 +++---- .../new/modal/_result_contents_inner.html.erb | 7 +- .../reports/new/modal/_step_contents.html.erb | 6 +- .../new/modal/_step_contents_inner.html.erb | 66 +++++---- config/locales/en.yml | 12 +- 10 files changed, 206 insertions(+), 188 deletions(-) diff --git a/app/assets/stylesheets/reports.scss b/app/assets/stylesheets/reports.scss index 9b330ca54..eb5c15ee8 100644 --- a/app/assets/stylesheets/reports.scss +++ b/app/assets/stylesheets/reports.scss @@ -44,6 +44,15 @@ display: inline-block; } +// Modal for adding content +label { + &[for="_module_content_all"], + &[for="_step_content_all"], + &[for="result_content_all"] { + font-weight: bold; + } +} + /* New page sidebar */ .report-sidebar-wrapper { background-color: $color-white !important; diff --git a/app/views/reports/new/modal/_experiment_contents.html.erb b/app/views/reports/new/modal/_experiment_contents.html.erb index a5920617a..3f9b23caf 100644 --- a/app/views/reports/new/modal/_experiment_contents.html.erb +++ b/app/views/reports/new/modal/_experiment_contents.html.erb @@ -53,8 +53,8 @@ } }); - var moduleCheckAll = moduleTab.find(".module-check-all"); - var moduleOthers = moduleTab.find("input:checkbox:not(.module-check-all)"); + var moduleCheckAll = moduleTab.find("#_module_content_all"); + var moduleOthers = moduleTab.find("input:checkbox:not(#_module_content_all)"); var moduleResultsAll = moduleTab.find(".results-all"); var moduleResults = moduleTab.find(".result-cb"); moduleCheckAll.click(function() { @@ -70,8 +70,8 @@ moduleResultsAll.prop("checked", false); }); - var stepsCheckAll = stepsTab.find(".step-check-all"); - var stepsOthers = stepsTab.find("input:checkbox:not(.step-check-all)"); + var stepsCheckAll = stepsTab.find("#_step_content_all"); + var stepsOthers = stepsTab.find("input:checkbox:not(#_step_content_all)"); stepsCheckAll.click(function() { stepsOthers.prop("checked", this.checked); }); diff --git a/app/views/reports/new/modal/_module_contents.html.erb b/app/views/reports/new/modal/_module_contents.html.erb index feeda0bbe..f4536923a 100644 --- a/app/views/reports/new/modal/_module_contents.html.erb +++ b/app/views/reports/new/modal/_module_contents.html.erb @@ -29,8 +29,8 @@ var moduleTab = form.find("#module-tab"); var stepsTab = form.find("#module-steps-tab"); - var moduleCheckAll = moduleTab.find(".module-check-all"); - var moduleOthers = moduleTab.find("input:checkbox:not(.module-check-all)"); + var moduleCheckAll = moduleTab.find("#_module_content_all"); + var moduleOthers = moduleTab.find("input:checkbox:not(#_module_content_all)"); var moduleResultsAll = moduleTab.find(".results-all"); var moduleResults = moduleTab.find(".result-cb"); moduleCheckAll.click(function() { @@ -46,8 +46,8 @@ moduleResultsAll.prop("checked", false); }); - var stepsCheckAll = stepsTab.find(".step-check-all"); - var stepsOthers = stepsTab.find("input:checkbox:not(.step-check-all)"); + var stepsCheckAll = stepsTab.find("#_step_content_all"); + var stepsOthers = stepsTab.find("input:checkbox:not(#_step_content_all)"); stepsCheckAll.click(function() { stepsOthers.prop("checked", this.checked); }); @@ -55,4 +55,4 @@ stepsCheckAll.prop("checked", false); }); }); - \ No newline at end of file + diff --git a/app/views/reports/new/modal/_module_contents_inner.html.erb b/app/views/reports/new/modal/_module_contents_inner.html.erb index c2692d9d9..3143a99ca 100644 --- a/app/views/reports/new/modal/_module_contents_inner.html.erb +++ b/app/views/reports/new/modal/_module_contents_inner.html.erb @@ -6,47 +6,50 @@ -<%= form.check_box :module_all, label: t("general.check_all"), class: "module-check-all" %> +<%= form.check_box :module_content_all, label: t("projects.reports.elements.modals.module_contents_inner.check_all") %> +
-<%= form.label t("projects.reports.elements.modals.module_contents_inner.header") %> + <% if my_module_undefined or my_module.protocol.steps.count > 0 %> + <%= form.check_box :module_steps, label: t("projects.reports.elements.modals.module_contents_inner.steps") %> + <% else %> +
+ + <%= t("projects.reports.elements.modals.module_contents_inner.no_steps") %> + +
+ <% end %> -<% if my_module_undefined or my_module.protocol.steps.count > 0 %> - <%= form.check_box :module_steps, label: t("projects.reports.elements.modals.module_contents_inner.steps") %> -<% else %> -
- - <%= t("projects.reports.elements.modals.module_contents_inner.no_steps") %> - -
-<% end %> + <% if my_module_undefined or (my_module.results.select { |r| r.active? }).count > 0 %> + <%= form.check_box :module_results, label: t("projects.reports.elements.modals.module_contents_inner.results"), class: "results-all" %> +
    + <% if my_module_undefined or (my_module.results.select { |r| r.is_asset && r.active? }).count > 0 %> +
  • + <%= form.check_box :module_result_assets, label: t("projects.reports.elements.modals.module_contents_inner.result_assets"), class: "result-cb" %> +
  • + <% end %> -<% if my_module_undefined or (my_module.results.select { |r| r.active? }).count > 0 %> - <%= form.check_box :module_results, label: t("projects.reports.elements.modals.module_contents_inner.results"), class: "results-all" %> -
      - <% if my_module_undefined or (my_module.results.select { |r| r.is_asset && r.active? }).count > 0 %> -
    • - <%= form.check_box :module_result_assets, label: t("projects.reports.elements.modals.module_contents_inner.result_assets"), class: "result-cb" %> -
    • - <% end %> - <% if my_module_undefined or (my_module.results.select { |r| r.is_table && r.active? }).count > 0 %> -
    • - <%= form.check_box :module_result_tables, label: t("projects.reports.elements.modals.module_contents_inner.result_tables"), class: "result-cb" %> -
    • - <% end %> - <% if my_module_undefined or (my_module.results.select { |r| r.is_text && r.active? }).count > 0 %> -
    • - <%= form.check_box :module_result_texts, label: t("projects.reports.elements.modals.module_contents_inner.result_texts"), class: "result-cb" %> -
    • - <% end %> -
    -<% else %> -
    - - <%= t("projects.reports.elements.modals.module_contents_inner.no_results") %> - -
    -<% end %> + <% if my_module_undefined or (my_module.results.select { |r| r.is_table && r.active? }).count > 0 %> +
  • + <%= form.check_box :module_result_tables, label: t("projects.reports.elements.modals.module_contents_inner.result_tables"), class: "result-cb" %> +
  • + <% end %> -<%= form.check_box :module_activity, label: t("projects.reports.elements.modals.module_contents_inner.activity") %> + <% if my_module_undefined or (my_module.results.select { |r| r.is_text && r.active? }).count > 0 %> +
  • + <%= form.check_box :module_result_texts, label: t("projects.reports.elements.modals.module_contents_inner.result_texts"), class: "result-cb" %> +
  • + <% end %> +
+ <% else %> +
+ + <%= t("projects.reports.elements.modals.module_contents_inner.no_results") %> + +
+ <% end %> -<%= form.check_box :module_samples, label: t("projects.reports.elements.modals.module_contents_inner.samples") %> + <%= form.check_box :module_activity, label: t("projects.reports.elements.modals.module_contents_inner.activity") %> + + <%= form.check_box :module_samples, label: t("projects.reports.elements.modals.module_contents_inner.samples") %> + +
diff --git a/app/views/reports/new/modal/_project_contents.html.erb b/app/views/reports/new/modal/_project_contents.html.erb index f5b9a2193..45964152b 100644 --- a/app/views/reports/new/modal/_project_contents.html.erb +++ b/app/views/reports/new/modal/_project_contents.html.erb @@ -4,28 +4,16 @@ diff --git a/app/views/reports/new/modal/_result_contents_inner.html.erb b/app/views/reports/new/modal/_result_contents_inner.html.erb index b3dc03c16..d71992ec9 100644 --- a/app/views/reports/new/modal/_result_contents_inner.html.erb +++ b/app/views/reports/new/modal/_result_contents_inner.html.erb @@ -6,7 +6,7 @@
<% end %> - <% if step_undefined or step.tables.present? %> + <% if step_undefined or step.tables.exists? %>
  • <%= form.check_box :step_tables, label: t("projects.reports.elements.modals.step_contents_inner.tables") %>
  • From b21923cf980a3892c6916d1221bc2dac1e1bce59 Mon Sep 17 00:00:00 2001 From: zmagod Date: Tue, 16 May 2017 11:52:07 +0200 Subject: [PATCH 15/29] prevent to duplicate new step [fixes SCI-1280] --- app/assets/javascripts/protocols/steps.js.erb | 1204 +++++++++-------- app/views/protocols/_steps.html.erb | 5 +- 2 files changed, 624 insertions(+), 585 deletions(-) diff --git a/app/assets/javascripts/protocols/steps.js.erb b/app/assets/javascripts/protocols/steps.js.erb index a536e33be..55c68a895 100644 --- a/app/assets/javascripts/protocols/steps.js.erb +++ b/app/assets/javascripts/protocols/steps.js.erb @@ -4,637 +4,673 @@ //= require assets //= require comments -// Sets callbacks for toggling checkboxes -function applyCheckboxCallBack() { - $("[data-action='check-item']").on('click', function(e){ - var checkboxitem = $(this).find("input"); - var checked = checkboxitem.is(":checked"); - $.ajax({ - url: checkboxitem.data("link-url"), - type: "POST", - dataType: "json", - data: {checklistitem_id: checkboxitem.data("id"), checked: checked}, - success: function (data) { - checkboxitem.prop("checked", checked); - }, - error: function (data) { - checkboxitem.prop("checked", !checked); - } - }); - }); -} +(function(global) { + 'use strict'; -// Complete mymodule -function complete_my_module_actions() { - var modal = $('#completed-task-modal'); - - modal.find('[data-action="complete"]') - .off().on().click(function(event) { - event.stopPropagation(); - event.preventDefault(); - event.stopImmediatePropagation(); + // Sets callbacks for toggling checkboxes + function applyCheckboxCallBack() { + $("[data-action='check-item']").on('click', function(e){ + var checkboxitem = $(this).find("input"); + var checked = checkboxitem.is(":checked"); $.ajax({ - url: modal.data('url'), - type: 'GET', - success: function(data) { - var task_button = $("[data-action='complete-task']"); - task_button.attr('data-action', 'uncomplete-task'); - task_button.find('.btn') - .removeClass('btn-primary').addClass('btn-greyed'); - $('.task-due-date').html(data.module_header_due_date_label); - $('.task-state-label').html(data.module_state_label); - task_button - .find('button') - .html(' ' + - data.task_button_title); - modal.modal('hide'); + url: checkboxitem.data("link-url"), + type: "POST", + dataType: "json", + data: {checklistitem_id: checkboxitem.data("id"), checked: checked}, + success: function (data) { + checkboxitem.prop("checked", checked); }, - error: function() { - modal.modal('hide'); + error: function (data) { + checkboxitem.prop("checked", !checked); } }); }); -} + } -// Sets callback for completing/uncompleting step -function applyStepCompletedCallBack() { - // First, remove old event handlers, as we use turbolinks - $("[data-action='complete-step'], [data-action='uncomplete-step']") - .off().on('click', function(e){ - var button = $(this); - var step = $(this).parents(".step"); - var completed = !step.hasClass("completed"); + // Complete mymodule + function complete_my_module_actions() { + var modal = $('#completed-task-modal'); - $.ajax({ - url: button.data("link-url"), - type: "POST", - dataType: "json", - data: {completed: completed}, - success: function (data) { - var button; - if (completed) { - step.addClass("completed").removeClass("not-completed"); - - button = step.find("[data-action='complete-step']"); - button.attr("data-action", "uncomplete-step"); - button.find(".btn").removeClass("btn-primary").addClass("btn-default"); - - if (data.task_ready_to_complete) { - $('#completed-task-modal').modal('show'); - complete_my_module_actions(); + modal.find('[data-action="complete"]') + .off().on().click(function(event) { + event.stopPropagation(); + event.preventDefault(); + event.stopImmediatePropagation(); + $.ajax({ + url: modal.data('url'), + type: 'GET', + success: function(data) { + var task_button = $("[data-action='complete-task']"); + task_button.attr('data-action', 'uncomplete-task'); + task_button.find('.btn') + .removeClass('btn-primary').addClass('btn-greyed'); + $('.task-due-date').html(data.module_header_due_date_label); + $('.task-state-label').html(data.module_state_label); + task_button + .find('button') + .html(' ' + + data.task_button_title); + modal.modal('hide'); + }, + error: function() { + modal.modal('hide'); } - } - else { - step.addClass("not-completed").removeClass("completed"); + }); + }); + } - button = step.find("[data-action='uncomplete-step']"); - button.attr("data-action", "complete-step"); - button.find(".btn").removeClass("btn-default").addClass("btn-primary"); - } + // Sets callback for completing/uncompleting step + function applyStepCompletedCallBack() { + // First, remove old event handlers, as we use turbolinks + $("[data-action='complete-step'], [data-action='uncomplete-step']") + .off().on('click', function(e){ + var button = $(this); + var step = $(this).parents(".step"); + var completed = !step.hasClass("completed"); - button.find("button").html(data.new_title); - }, - error: function (data) { - console.log ("error"); + $.ajax({ + url: button.data("link-url"), + type: "POST", + dataType: "json", + data: {completed: completed}, + success: function (data) { + var button; + if (completed) { + step.addClass("completed").removeClass("not-completed"); + + button = step.find("[data-action='complete-step']"); + button.attr("data-action", "uncomplete-step"); + button.find(".btn").removeClass("btn-primary").addClass("btn-default"); + + if (data.task_ready_to_complete) { + $('#completed-task-modal').modal('show'); + complete_my_module_actions(); + } + } + else { + step.addClass("not-completed").removeClass("completed"); + + button = step.find("[data-action='uncomplete-step']"); + button.attr("data-action", "complete-step"); + button.find(".btn").removeClass("btn-default").addClass("btn-primary"); + } + + button.find("button").html(data.new_title); + }, + error: function (data) { + console.log ("error"); + } + }); + }); + } + + function applyCancelCallBack() { + //Click on cancel button + $("[data-action='cancel-edit']") + .on("ajax:success", function(e, data) { + var $form = $(this).closest("form"); + + $form.after(data.html); + var $new_step = $(this).next(); + $(this).remove(); + + initCallBacks(); + initHandsOnTable($new_step); + toggleButtons(true); + + setTimeout(function() { + initStepsComments(); + initPreviewModal(); + SmartAnnotation.preventPropagation('.atwho-user-popover'); + TinyMCE.destroyAll(); + }, 1000); + + }) + .on("ajax:error", function(e, xhr, status, error) { + // TODO: error handling + }); + } + + // Set callback for click on edit button + function applyEditCallBack() { + $("[data-action='edit-step']") + .on("ajax:success", function(e, data) { + var $step = $(this).closest(".step"); + var $edit_step = $step.after(data.html); + var $form = $step.next(); + $step.remove(); + + formCallback($form); + initEditableHandsOnTable($form); + applyCancelCallBack(); + formEditAjax($form); + toggleButtons(false); + initializeCheckboxSorting(); + animateSpinner(null, false); + initPreviewModal(); + + TinyMCE.refresh() + $("#new-step-checklists fieldset.nested_step_checklists ul").each(function () { + enableCheckboxSorting(this); + }); + $("#step_name").focus(); + $("#new-step-main-tab a").on("shown.bs.tab", function() { + $("#step_name").focus(); + }); + }); + } + + // Set callback for click on edit button + function applyMoveStepCallBack() { + $("[data-action='move-step']").off("ajax:success"); + $("[data-action='move-step']") + .on("ajax:success", function(e, data) { + var $step = $(this).closest(".step"); + var stepUpPosition = data.step_up_position; + var stepDownPosition = data.step_down_position; + var $stepDown, $stepUp; + switch (data.move_direction) { + case "up": + $stepDown = $step.prev(".step"); + $stepUp = $step; + break; + case "down": + $stepDown = $step; + $stepUp = $step.next(".step"); + } + + // Switch position of top and bottom steps + if (!_.isUndefined($stepDown) && !_.isUndefined($stepUp)) { + $stepDown.insertAfter($stepUp); + $stepDown.find(".badge").html(stepDownPosition+1); + $stepUp.find(".badge").html(stepUpPosition+1); + $("html, body").animate({ scrollTop: $step.offset().top - window.innerHeight / 2 }); } }); - }); -} + } -function applyCancelCallBack() { - //Click on cancel button - $("[data-action='cancel-edit']") - .on("ajax:success", function(e, data) { - var $form = $(this).closest("form"); + function applyCollapseLinkCallBack() { + $(".step-panel-collapse-link") + .on("ajax:success", function() { + var collapseIcon = $(this).find(".collapse-step-icon"); + var collapsed = $(this).hasClass("collapsed"); + // Toggle collapse button + collapseIcon.toggleClass("glyphicon-collapse-up", !collapsed); + collapseIcon.toggleClass("glyphicon-collapse-down", collapsed); - $form.after(data.html); - var $new_step = $(this).next(); - $(this).remove(); + }); + } - initCallBacks(); - initHandsOnTable($new_step); - toggleButtons(true); + function formCallback($form) { + $form + .on("fields_added.nested_form_fields", function(e, param) { + if (param.object_class == "table") { + initEditableHandsOnTable($form); + } + }) + .on("fields_removed.nested_form_fields", function(e, param) { + if (param.object_class == "asset") { + // Clear file input + $(e.target).find("input[type='file']").val(""); + } + }); - setTimeout(function() { - initStepsComments(); + // 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 + function formEditAjax($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); + toggleButtons(true); initPreviewModal(); - SmartAnnotation.preventPropagation('.atwho-user-popover'); + TinyMCE.destroyAll(); - }, 1000); - - }) - .on("ajax:error", function(e, xhr, status, error) { - // TODO: error handling - }); -} - -// Set callback for click on edit button -function applyEditCallBack() { - $("[data-action='edit-step']") - .on("ajax:success", function(e, data) { - var $step = $(this).closest(".step"); - var $edit_step = $step.after(data.html); - var $form = $step.next(); - $step.remove(); - - formCallback($form); - initEditableHandsOnTable($form); - applyCancelCallBack(); - formEditAjax($form); - toggleButtons(false); - initializeCheckboxSorting(); - animateSpinner(null, false); - initPreviewModal(); - - TinyMCE.refresh() - $("#new-step-checklists fieldset.nested_step_checklists ul").each(function () { - enableCheckboxSorting(this); - }); - $("#step_name").focus(); - $("#new-step-main-tab a").on("shown.bs.tab", function() { - $("#step_name").focus(); - }); - }); -} - -// Set callback for click on edit button -function applyMoveStepCallBack() { - $("[data-action='move-step']").off("ajax:success"); - $("[data-action='move-step']") - .on("ajax:success", function(e, data) { - var $step = $(this).closest(".step"); - var stepUpPosition = data.step_up_position; - var stepDownPosition = data.step_down_position; - var $stepDown, $stepUp; - switch (data.move_direction) { - case "up": - $stepDown = $step.prev(".step"); - $stepUp = $step; - break; - case "down": - $stepDown = $step; - $stepUp = $step.next(".step"); - } - - // Switch position of top and bottom steps - if (!_.isUndefined($stepDown) && !_.isUndefined($stepUp)) { - $stepDown.insertAfter($stepUp); - $stepDown.find(".badge").html(stepDownPosition+1); - $stepUp.find(".badge").html(stepUpPosition+1); - $("html, body").animate({ scrollTop: $step.offset().top - window.innerHeight / 2 }); - } - }); -} - -function applyCollapseLinkCallBack() { - $(".step-panel-collapse-link") - .on("ajax:success", function() { - var collapseIcon = $(this).find(".collapse-step-icon"); - var collapsed = $(this).hasClass("collapsed"); - // Toggle collapse button - collapseIcon.toggleClass("glyphicon-collapse-up", !collapsed); - collapseIcon.toggleClass("glyphicon-collapse-down", collapsed); - - }); -} - -function formCallback($form) { - $form - .on("fields_added.nested_form_fields", function(e, param) { - if (param.object_class == "table") { - initEditableHandsOnTable($form); - } - }) - .on("fields_removed.nested_form_fields", function(e, param) { - if (param.object_class == "asset") { - // Clear file input - $(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; - }); -} + // Show the edited step + $new_step.find(".panel-collapse:first").addClass("collapse in"); -// Init ajax success/error for edit form -function formEditAjax($form) { - $form - .on("ajax:beforeSend", function () { - $(".nested_step_checklists ul").each(function () { - reorderCheckboxData(this); + //Rerender tables + $new_step.find("[data-role='step-hot-table']").each(function() { + renderTable($(this)); + }); + setupAssetsLoading(); + }) + .on("ajax:error", function(e, xhr, status, error) { + $form.renderFormErrors('step', xhr.responseJSON, true, e); + + formCallback($form); + initEditableHandsOnTable($form); + applyCancelCallBack(); + + TinyMCE.refresh(); + SmartAnnotation.preventPropagation('.atwho-user-popover'); + + //Rerender tables + $form.find("[data-role='step-hot-table']").each(function() { + renderTable($(this)); + }); }); - }) - .on("ajax:success", function(e, data) { - $(this).after(data.html); - var $new_step = $(this).next(); - $(this).remove(); + } - initCallBacks(); - initHandsOnTable($new_step); - toggleButtons(true); - initPreviewModal(); + 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(); - TinyMCE.destroyAll(); - SmartAnnotation.preventPropagation('.atwho-user-popover'); - // Show the edited step - $new_step.find(".panel-collapse:first").addClass("collapse in"); + initCallBacks(); + initHandsOnTable($new_step); + expandStep($new_step); + toggleButtons(true); + SmartAnnotation.preventPropagation('.atwho-user-popover'); - //Rerender tables - $new_step.find("[data-role='step-hot-table']").each(function() { - renderTable($(this)); + //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'); }); - setupAssetsLoading(); - }) - .on("ajax:error", function(e, xhr, status, error) { - $form.renderFormErrors('step', xhr.responseJSON, true, e); + } - formCallback($form); - initEditableHandsOnTable($form); - applyCancelCallBack(); + function toggleButtons(show) { + if (show) { + $("[data-action='new-step']").show(); + $("[data-action='edit-step']").show(); - TinyMCE.refresh(); - SmartAnnotation.preventPropagation('.atwho-user-popover'); + // Also show "no steps" label if no steps are present + if (!$(".step").length) { + $("[data-role='no-steps-text']").show(); + } else { + $("[data-role='no-steps-text']").hide(); + } - //Rerender tables - $form.find("[data-role='step-hot-table']").each(function() { - renderTable($(this)); - }); - }); -} - -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(); - $("[data-action='edit-step']").show(); - - // Also show "no steps" label if no steps are present - if (!$(".step").length) { - $("[data-role='no-steps-text']").show(); } else { + $("[data-action='new-step']").hide(); + $("[data-action='edit-step']").hide(); + + // Also hide "no steps" label if no steps are present $("[data-role='no-steps-text']").hide(); } - - } else { - $("[data-action='new-step']").hide(); - $("[data-action='edit-step']").hide(); - - // Also hide "no steps" label if no steps are present - $("[data-role='no-steps-text']").hide(); } -} -// Creates handsontable where needed -function initHandsOnTable(root) { - root.find("[data-role='hot-table']").each(function() { - var $container = $(this).find("[data-role='step-hot-table']"); - var contents = $(this).find('.hot-contents'); + // Creates handsontable where needed + function initHandsOnTable(root) { + root.find("[data-role='hot-table']").each(function() { + var $container = $(this).find("[data-role='step-hot-table']"); + var contents = $(this).find('.hot-contents'); - $container.handsontable({ - startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>, - startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>, - rowHeaders: true, - colHeaders: true, - fillHandle: false, - formulas: true, - cells: function (row, col, prop) { - var cellProperties = {}; + $container.handsontable({ + startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>, + startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>, + rowHeaders: true, + colHeaders: true, + fillHandle: false, + formulas: true, + cells: function (row, col, prop) { + var cellProperties = {}; - if (col >= 0) - cellProperties.readOnly = true; - else - cellProperties.readOnly = false; + if (col >= 0) + cellProperties.readOnly = true; + else + cellProperties.readOnly = false; - return cellProperties; + return cellProperties; + } + }); + var hot = $container.handsontable('getInstance'); + + if (contents.attr("value")) { + var data = JSON.parse(contents.attr("value")); + hot.loadData(data.data); } }); - var hot = $container.handsontable('getInstance'); - - if (contents.attr("value")) { - var data = JSON.parse(contents.attr("value")); - hot.loadData(data.data); - } - }); -} - -// Init handsontable which can be edited -function initEditableHandsOnTable(root) { - root.find("[data-role='editable-table']").each(function() { - var $container = $(this).find(".hot"); - - if ($container.is("[initialized]")) { - return true; - } - - var contents = $(this).find('.hot-contents'); - var data = null; - if (contents.attr("value")) { - data = JSON.parse(contents.attr("value")).data; - } - if ($container.is(":visible")) { - $(this).css("width", $("#new-step-tables").css("width")); - } - - $container.handsontable({ - data: data, - startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>, - startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>, - minRows: 1, - minCols: 1, - rowHeaders: true, - colHeaders: true, - contextMenu: true, - formulas: true, - preventOverflow: 'horizontal' - }); - - $container.attr("initialized", true); - renderTable($container); - }); - - $("#new-step-tables-tab a") - .on("shown.bs.tab", function() { - $(this).parents("form").find("div.hot").each(function() { - $(this).parent().css("width", $("#new-step-tables").css("width")); - renderTable($(this)); - }); - }); -} - -function applyCancelOnNew() { - $("[data-action='cancel-new']").click(function() { - var $form = $(this).closest("form"); - $form.parent().remove(); - toggleButtons(true); - }); -} - -function initDeleteStep(){ - $("[data-action='delete-step']").on("confirm:complete", function (e, answer) { - if (answer) { - animateLoading(); - } - }); -} - -function initCallBacks() { - applyCheckboxCallBack(); - applyStepCompletedCallBack(); - applyEditCallBack(); - applyMoveStepCallBack(); - applyCollapseLinkCallBack(); - initDeleteStep(); - TinyMCE.highlight(); -} - -/* - * Correction for sorting with "Sortable.min" JS library to work correctly with - * "nested_form_fields" gem. - */ -function reorderCheckboxData(checkboxUl) { - // Make sure checkbox item insertion script is always at the bottom of "ul" - // tag, otherwise item will not be inserted at bottom - if(!$(checkboxUl).children().last().is('script')) { - $(checkboxUl).find("script").appendTo(checkboxUl); } - var $checkboxes = $(checkboxUl).find(".nested_fields"); - $checkboxes.each(function (itemPos) { - var $this = $(this); + // Init handsontable which can be edited + function initEditableHandsOnTable(root) { + root.find("[data-role='editable-table']").each(function() { + var $container = $(this).find(".hot"); - var $formGroup = $this.find(".form-group"); - var $label = $formGroup.find(".control-label"); - var $textInput = $formGroup.find(".checklist-item-text"); - var $posInput = $formGroup.parent().find(".checklist-item-pos"); - var $destroyLink = $this.find(".remove_nested_fields_link"); + if ($container.is("[initialized]")) { + return true; + } - var labelFor = $label.attr("for"); - var textName = $textInput.attr("name"); - var textId = $textInput.attr("id"); - var posName = $posInput.attr("name"); - var posId = $posInput.attr("id"); - var destroyLink = $destroyLink.attr("data-delete-association-field-name"); + var contents = $(this).find('.hot-contents'); + var data = null; + if (contents.attr("value")) { + data = JSON.parse(contents.attr("value")).data; + } + if ($container.is(":visible")) { + $(this).css("width", $("#new-step-tables").css("width")); + } - labelFor = labelFor.replace(/\d+_text/, itemPos + "_text"); - textName = textName.replace(/\[\d+\]\[text\]/, "[" + itemPos + "][text]"); - textId = textId.replace(/\d+_text/, itemPos + "_text"); - posName = posName.replace(/\[\d+\]\[position\]/, "[" + itemPos + "][position]"); - posId = posId.replace(/\d+_position/, itemPos + "_position"); - destroyLink = destroyLink.replace(/\[\d+\]\[_destroy\]/, "[" + itemPos + "][_destroy]"); + $container.handsontable({ + data: data, + startRows: <%= Constants::HANDSONTABLE_INIT_ROWS_CNT %>, + startCols: <%= Constants::HANDSONTABLE_INIT_COLS_CNT %>, + minRows: 1, + minCols: 1, + rowHeaders: true, + colHeaders: true, + contextMenu: true, + formulas: true, + preventOverflow: 'horizontal' + }); - $label.attr("for", labelFor); - $textInput.attr("name", textName); // Actually needed for sorting to work - $textInput.attr("id", textId); - $posInput.attr("name", posName); - $posInput.attr("id", posId); - $posInput.val(itemPos); - $destroyLink.attr("data-delete-association-field-name", destroyLink); - - var $idInput = $this.find("> input"); - if ($idInput.length) { - var idName = $idInput.attr("name"); - var idId = $idInput.attr("id"); - - idName = idName.replace(/\[\d+\]\[id\]/, "[" + itemPos + "][id]"); - idId = idId.replace(/\d+_id/, itemPos + "_id"); - - $idInput.attr("name", idName); - $idInput.attr("id", idId); - } - - if ($this.css('display') == 'none') { - // Actually needed for deleting to work - var $destroyInput = $this.prev(); - var destroyName = $destroyInput.attr("name"); - destroyName = destroyName.replace(/\[\d+\]\[_destroy\]/, "[" + itemPos + "][_destroy]"); - $destroyInput.attr("name", destroyName); - } - }); -} - -function enableCheckboxSorting(el) { - Sortable.create(el, { - draggable: 'fieldset', - handle: '.glyphicon-chevron-right', - onUpdate: function () { - reorderCheckboxData(el); - } - }); -} - -function initializeCheckboxSorting() { - var el = $("#new-step-checklists a[data-association-path=step_checklists]"); - - el.click(function () { - // calling code below must be defered because at this step HTML is not - // inserted into DOM. - setTimeout(function () { - var list = el.parent().find("fieldset.nested_step_checklists:last ul"); - enableCheckboxSorting(list.get(0)); + $container.attr("initialized", true); + renderTable($container); }); - }); -} -// New step AJAX -$("[data-action='new-step']").on("ajax:success", function(e, data) { - var $form = $(data.html); - $("#steps").append($form); - - // Scroll to bottom - $("html, body").animate({ scrollTop: $(document).height()-$(window).height() }); - formCallback($form); - formNewAjax($form); - applyCancelOnNew(); - toggleButtons(false); - initializeCheckboxSorting(); - - $("#step_name").focus(); - $("#new-step-main-tab a").on("shown.bs.tab", function() { - $("#step_name").focus(); - }); - - TinyMCE.refresh(); -}); - -// Needed because server-side validation failure clears locations of -// files to be uploaded and checklist's items etc. Also user -// experience is improved -function processStep(ev, editMode) { - 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"); - var nameValid = textValidator(ev, $nameInput, 1, - <%= Constants::NAME_MAX_LENGTH %>); - var $descrTextarea = $form.find("#step_description"); - var descriptionValid = textValidator(ev, $descrTextarea, 0, - <%= Constants::TEXT_MAX_LENGTH %>); - - if (filesValid && checklistsValid && nameValid && descriptionValid) { - // Local file uploading - animateSpinner(); - } -} - -// Expand all steps -function expandAllSteps() { - $('.step .panel-collapse').collapse('show'); - $(document).find("[data-role='step-hot-table']").each(function() { - renderTable($(this)); - }); - $(document).find("span.collapse-step-icon").each(function() { - $(this).addClass("glyphicon-collapse-up"); - $(this).removeClass("glyphicon-collapse-down"); - }); -} - -function expandStep(step) { - $('.panel-collapse', step).collapse('show'); - $(step).find("span.collapse-step-icon") - .addClass("glyphicon-collapse-up") - .removeClass("glyphicon-collapse-down"); - $(step).find("div.step-result-hot-table").each(function() { - renderTable($(this)); - }); -} - -function renderTable(table) { - $(table).handsontable("render"); - // Yet another dirty hack to solve HandsOnTable problems - if (parseInt($(table).css("height"), 10) < parseInt($(table).css("max-height"), 10) - 30) { - $(table).find(".ht_master .wtHolder").css("height", "100%"); - } -} - -function initStepsComments() { - Comments.initialize(); - Comments.initCommentOptions("ul.content-comments"); - Comments.initEditComments("#steps"); - Comments.initDeleteComments("#steps"); -} - -$(document).ready(function() { - // On init - initCallBacks(); - initHandsOnTable($(document)); - expandAllSteps(); - setupAssetsLoading(); - initStepsComments(); - initPreviewModal(); - TinyMCE.highlight(); - SmartAnnotation.preventPropagation('.atwho-user-popover'); - - $(function () { - - $("[data-action='collapse-steps']").click(function () { - $('.step .panel-collapse').collapse('hide'); - $(document).find("span.collapse-step-icon").each(function() { - $(this).addClass("glyphicon-collapse-down"); - $(this).removeClass("glyphicon-collapse-up"); + $("#new-step-tables-tab a") + .on("shown.bs.tab", function() { + $(this).parents("form").find("div.hot").each(function() { + $(this).parent().css("width", $("#new-step-tables").css("width")); + renderTable($(this)); }); }); + } - $("[data-action='expand-steps']").click(expandAllSteps); - }); -}) + function applyCancelOnNew() { + $("[data-action='cancel-new']").click(function(event) { + event.preventDefault(); + event.stopPropagation(); + event.stopImmediatePropagation(); + + var $form = $(this).closest("form"); + $form.parent().remove().promise().done(function() { + newStepHandler(); + }); + toggleButtons(true); + }); + } + + function initDeleteStep(){ + $("[data-action='delete-step']").on("confirm:complete", function (e, answer) { + if (answer) { + animateLoading(); + } + }); + } + + function initCallBacks() { + applyCheckboxCallBack(); + applyStepCompletedCallBack(); + applyEditCallBack(); + applyMoveStepCallBack(); + applyCollapseLinkCallBack(); + initDeleteStep(); + TinyMCE.highlight(); + } + + /* + * Correction for sorting with "Sortable.min" JS library to work correctly with + * "nested_form_fields" gem. + */ + function reorderCheckboxData(checkboxUl) { + // Make sure checkbox item insertion script is always at the bottom of "ul" + // tag, otherwise item will not be inserted at bottom + if(!$(checkboxUl).children().last().is('script')) { + $(checkboxUl).find("script").appendTo(checkboxUl); + } + + var $checkboxes = $(checkboxUl).find(".nested_fields"); + $checkboxes.each(function (itemPos) { + var $this = $(this); + + var $formGroup = $this.find(".form-group"); + var $label = $formGroup.find(".control-label"); + var $textInput = $formGroup.find(".checklist-item-text"); + var $posInput = $formGroup.parent().find(".checklist-item-pos"); + var $destroyLink = $this.find(".remove_nested_fields_link"); + + var labelFor = $label.attr("for"); + var textName = $textInput.attr("name"); + var textId = $textInput.attr("id"); + var posName = $posInput.attr("name"); + var posId = $posInput.attr("id"); + var destroyLink = $destroyLink.attr("data-delete-association-field-name"); + + labelFor = labelFor.replace(/\d+_text/, itemPos + "_text"); + textName = textName.replace(/\[\d+\]\[text\]/, "[" + itemPos + "][text]"); + textId = textId.replace(/\d+_text/, itemPos + "_text"); + posName = posName.replace(/\[\d+\]\[position\]/, "[" + itemPos + "][position]"); + posId = posId.replace(/\d+_position/, itemPos + "_position"); + destroyLink = destroyLink.replace(/\[\d+\]\[_destroy\]/, "[" + itemPos + "][_destroy]"); + + $label.attr("for", labelFor); + $textInput.attr("name", textName); // Actually needed for sorting to work + $textInput.attr("id", textId); + $posInput.attr("name", posName); + $posInput.attr("id", posId); + $posInput.val(itemPos); + $destroyLink.attr("data-delete-association-field-name", destroyLink); + + var $idInput = $this.find("> input"); + if ($idInput.length) { + var idName = $idInput.attr("name"); + var idId = $idInput.attr("id"); + + idName = idName.replace(/\[\d+\]\[id\]/, "[" + itemPos + "][id]"); + idId = idId.replace(/\d+_id/, itemPos + "_id"); + + $idInput.attr("name", idName); + $idInput.attr("id", idId); + } + + if ($this.css('display') == 'none') { + // Actually needed for deleting to work + var $destroyInput = $this.prev(); + var destroyName = $destroyInput.attr("name"); + destroyName = destroyName.replace(/\[\d+\]\[_destroy\]/, "[" + itemPos + "][_destroy]"); + $destroyInput.attr("name", destroyName); + } + }); + } + + function enableCheckboxSorting(el) { + Sortable.create(el, { + draggable: 'fieldset', + handle: '.glyphicon-chevron-right', + onUpdate: function () { + reorderCheckboxData(el); + } + }); + } + + function initializeCheckboxSorting() { + var el = $("#new-step-checklists a[data-association-path=step_checklists]"); + + el.click(function () { + // calling code below must be defered because at this step HTML is not + // inserted into DOM. + setTimeout(function () { + var list = el.parent().find("fieldset.nested_step_checklists:last ul"); + enableCheckboxSorting(list.get(0)); + }); + }); + } + + // New step AJAX + function newStepHandler() { + $("[data-action='new-step']").off().on('click', function(event) { + event.preventDefault(); + event.stopPropagation(); + event.stopImmediatePropagation(); + var $btn = $(this); + $btn.off(); + animateSpinner(null, true); + + $.ajax({ + url: $btn.data('href'), + method: 'GET', + success: function(data) { + var $form = $(data.html); + $('#steps').append($form).promise().done(function() { + animateSpinner(null, false); + // Scroll to bottom + $('html, body').animate({ + scrollTop: $(document).height() - $(window).height() + }); + formCallback($form); + formNewAjax($form); + applyCancelOnNew(); + toggleButtons(false); + initializeCheckboxSorting(); + + $('#step_name').focus(); + $('#new-step-main-tab a').on('shown.bs.tab', function() { + $('#step_name').focus(); + }); + + TinyMCE.refresh(); + }); + + }, + error: function() { + newStepHandler(); + } + }) + }); + } + + // Needed because server-side validation failure clears locations of + // files to be uploaded and checklist's items etc. Also user + // experience is improved + global.processStep = function processStep(ev, editMode) { + ev.stopPropagation(); + + 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"); + var nameValid = textValidator(ev, $nameInput, 1, + <%= Constants::NAME_MAX_LENGTH %>); + var $descrTextarea = $form.find("#step_description"); + var descriptionValid = textValidator(ev, $descrTextarea, 0, + <%= Constants::TEXT_MAX_LENGTH %>); + + if (filesValid && checklistsValid && nameValid && descriptionValid) { + // Local file uploading + animateSpinner(); + newStepHandler(); + } + } + + // Expand all steps + function expandAllSteps() { + $('.step .panel-collapse').collapse('show'); + $(document).find("[data-role='step-hot-table']").each(function() { + renderTable($(this)); + }); + $(document).find("span.collapse-step-icon").each(function() { + $(this).addClass("glyphicon-collapse-up"); + $(this).removeClass("glyphicon-collapse-down"); + }); + } + + function expandStep(step) { + $('.panel-collapse', step).collapse('show'); + $(step).find("span.collapse-step-icon") + .addClass("glyphicon-collapse-up") + .removeClass("glyphicon-collapse-down"); + $(step).find("div.step-result-hot-table").each(function() { + renderTable($(this)); + }); + } + + function renderTable(table) { + $(table).handsontable("render"); + // Yet another dirty hack to solve HandsOnTable problems + if (parseInt($(table).css("height"), 10) < parseInt($(table).css("max-height"), 10) - 30) { + $(table).find(".ht_master .wtHolder").css("height", "100%"); + } + } + + function initStepsComments() { + Comments.initialize(); + Comments.initCommentOptions("ul.content-comments"); + Comments.initEditComments("#steps"); + Comments.initDeleteComments("#steps"); + } + + $(document).ready(function() { + // On init + initCallBacks(); + initHandsOnTable($(document)); + expandAllSteps(); + setupAssetsLoading(); + initStepsComments(); + initPreviewModal(); + TinyMCE.highlight(); + SmartAnnotation.preventPropagation('.atwho-user-popover'); + newStepHandler(); + $(function () { + + $("[data-action='collapse-steps']").click(function () { + $('.step .panel-collapse').collapse('hide'); + $(document).find("span.collapse-step-icon").each(function() { + $(this).addClass("glyphicon-collapse-down"); + $(this).removeClass("glyphicon-collapse-up"); + }); + }); + + $("[data-action='expand-steps']").click(expandAllSteps); + }); + }) + +})(window); diff --git a/app/views/protocols/_steps.html.erb b/app/views/protocols/_steps.html.erb index 5869c5cfa..a3c8c4617 100644 --- a/app/views/protocols/_steps.html.erb +++ b/app/views/protocols/_steps.html.erb @@ -1,7 +1,10 @@
    <% if can_create_step_in_protocol(@protocol) %> - + From e0397f8a5470f563284a91aff8be59805c20d83a Mon Sep 17 00:00:00 2001 From: zmagod Date: Tue, 16 May 2017 14:58:39 +0200 Subject: [PATCH 16/29] fix search label [fixes SCI-1285] --- config/locales/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index befc67aa0..9d28e5f4d 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -102,7 +102,7 @@ en: search: whole_word: "Match any whole word" whole_phrase: "Match whole phrase" - match_case: "Match case" + match_case: "Match case sensitive" index: head_title: "Search" page_title: "Search" From b8b47542a6bffe7c04ed409fbc7daed3cfe55d9e Mon Sep 17 00:00:00 2001 From: zmagod Date: Tue, 16 May 2017 16:07:44 +0200 Subject: [PATCH 17/29] fix label [fixes SCI-1240] --- config/locales/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 9d28e5f4d..b4ec0382c 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -555,7 +555,7 @@ en: thead_published_on: "Published at" thead_created_at: "Created at" thead_updated_at: "Last modified at" - confirm_message: "Are you sure you wish to load protocol from repository? This action will overwrite the current protocol." + confirm_message: "Are you sure you wish to load protocol from repository? This action will overwrite the current protocol in the task and unlink it from repository. The current protocol will remain unchanged in repository." import_to_linked_task_rep: "Are you sure you wish to load protocol from repository? This action will overwrite the current protocol in the task and unlink it from repository. The current protocol will remain unchanged in repository." load: "Load" copy_to_repository_modal: From f28df506f97232198573b066113b3aeed18ee53e Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Wed, 17 May 2017 09:08:40 +0200 Subject: [PATCH 18/29] Fix bug in counting search results for assets [SCI-1284] --- app/controllers/search_controller.rb | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/controllers/search_controller.rb b/app/controllers/search_controller.rb index e9fb7cde2..db576ee32 100644 --- a/app/controllers/search_controller.rb +++ b/app/controllers/search_controller.rb @@ -96,7 +96,14 @@ class SearchController < ApplicationController end def count_by_name(model) - search_by_name(model).limit(nil).offset(nil).size + model.search(current_user, + true, + @search_query, + Constants::SEARCH_NO_LIMIT, + nil, + match_case: @search_case, + whole_word: @search_whole_word, + whole_phrase: @search_whole_phrase).size end def count_search_results From f78c80b1483ff5184c5eee30a0785abd58956df5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Wed, 17 May 2017 13:11:42 +0200 Subject: [PATCH 19/29] Added possibility to add uncompleted steps to report. [closes SCI-414] --- app/controllers/concerns/report_actions.rb | 19 ++++---- .../elements/_my_module_step_element.html.erb | 6 ++- .../new/modal/_module_contents_inner.html.erb | 11 +++-- config/initializers/extends/report_extends.rb | 45 ++++++++++++------- config/locales/en.yml | 9 +++- 5 files changed, 58 insertions(+), 32 deletions(-) diff --git a/app/controllers/concerns/report_actions.rb b/app/controllers/concerns/report_actions.rb index c66e7ac13..18462799c 100644 --- a/app/controllers/concerns/report_actions.rb +++ b/app/controllers/concerns/report_actions.rb @@ -70,17 +70,20 @@ module ReportActions def generate_module_contents_json(my_module) res = [] ReportExtends::MODULE_CONTENTS.each do |contents| - protocol = contents.element == :steps ? my_module.protocol.present? : true - next unless (in_params?("module_#{contents.element}".to_sym) || - in_params?('#{contents.element}'.to_sym)) && protocol + present = false + contents.values.each do |element| + present = in_params?("module_#{element}".to_sym) || + in_params?(element.to_sym) + break if present + end + next unless present + if contents.children - contents.collection(my_module).each do |report_el| + contents.collection(my_module, params).each do |report_el| res << generate_new_el(false) el = generate_el( - "reports/elements/my_module_#{contents - .element - .to_s - .singularize}_element.html.erb", + "reports/elements/my_module_#{contents.element.to_s.singularize}"\ + "_element.html.erb", contents.parse_locals([report_el]) ) if :step.in? contents.locals diff --git a/app/views/reports/elements/_my_module_step_element.html.erb b/app/views/reports/elements/_my_module_step_element.html.erb index 97a16d8e2..4c34e3da3 100644 --- a/app/views/reports/elements/_my_module_step_element.html.erb +++ b/app/views/reports/elements/_my_module_step_element.html.erb @@ -1,5 +1,7 @@ <% if step.blank? and @step.present? then step = @step end %> -<% timestamp = step.completed_on %> +<% step_type_str = step.completed ? 'completed' : 'uncompleted' %> +<% user = step.completed || !step.changed? ? step.user : step.last_modified_by %> +<% timestamp = step.completed ? step.completed_on : step.updated_at %> <% tables = step.tables %> <% assets = step.assets %> <% checklists = step.checklists %> @@ -8,7 +10,7 @@
    - <%=t "projects.reports.elements.step.user_time", user: step.user.full_name , timestamp: l(timestamp, format: :full) %> + <%=t "projects.reports.elements.step.#{step_type_str}.user_time", user: user.full_name , timestamp: l(timestamp, format: :full) %>
    <%= render partial: "reports/elements/element_controls.html.erb", locals: { show_sort: true } %> diff --git a/app/views/reports/new/modal/_module_contents_inner.html.erb b/app/views/reports/new/modal/_module_contents_inner.html.erb index e9761ee60..d1fc6f688 100644 --- a/app/views/reports/new/modal/_module_contents_inner.html.erb +++ b/app/views/reports/new/modal/_module_contents_inner.html.erb @@ -15,6 +15,14 @@ <% if my_module_undefined or my_module.protocol.steps.exists? %>
  • <%= form.check_box :module_steps, label: t("projects.reports.elements.modals.module_contents_inner.steps") %> +
      +
    • + <%= form.check_box :module_completed_steps, label: t("projects.reports.elements.modals.module_contents_inner.completed_steps") %> +
    • +
    • + <%= form.check_box :module_uncompleted_steps, label: t("projects.reports.elements.modals.module_contents_inner.uncompleted_steps") %> +
    • +
  • <% else %>
    @@ -34,13 +42,11 @@ <%= form.check_box :module_result_assets, label: t("projects.reports.elements.modals.module_contents_inner.result_assets") %> <% end %> - <% if my_module_undefined or (my_module.results.select { |r| r.is_table && r.active? }).exists? %>
  • <%= form.check_box :module_result_tables, label: t("projects.reports.elements.modals.module_contents_inner.result_tables") %>
  • <% end %> - <% if my_module_undefined or (my_module.results.select { |r| r.is_text && r.active? }).exists? %>
  • <%= form.check_box :module_result_texts, label: t("projects.reports.elements.modals.module_contents_inner.result_texts") %> @@ -60,7 +66,6 @@
  • <%= form.check_box :module_activity, label: t("projects.reports.elements.modals.module_contents_inner.activity") %>
  • -
  • <%= form.check_box :module_samples, label: t("projects.reports.elements.modals.module_contents_inner.samples") %>
  • diff --git a/config/initializers/extends/report_extends.rb b/config/initializers/extends/report_extends.rb index 3245d8af0..7634da9a3 100644 --- a/config/initializers/extends/report_extends.rb +++ b/config/initializers/extends/report_extends.rb @@ -11,25 +11,27 @@ module ReportExtends # ModuleElement struct creates an argument objects which is needed in # generate_module_contents_json method. It takes 3 parameters a Proc and # additional options wich can be extended. + # :values => name of the hook/identifier for specific module element state # :element => name of module element in plural # :children => bolean if element has children elements in report # :locals => an array of names of local variables which are passed in the view - # :coll => a prock which the my_module is passed and have to return a - # collection of element - # :singular => true by defaut change the enum type to singular - # needed when querying partials by name + # :coll => a procedure which the my_module is passed and have to return a + # collection of elements + # :singular => true by defaut; change the enum type to singular - needed when + # querying partials by name - ModuleElement = Struct.new(:element, + ModuleElement = Struct.new(:values, + :element, :children, :locals, :coll, :singular) do - def initialize(element, children, locals, coll = nil, singular = true) - super(element, children, locals, coll, singular) + def initialize(values, element, children, locals, coll = nil, singular = true) + super(values, element, children, locals, coll, singular) end - def collection(my_module) - coll.call(my_module) if coll + def collection(my_module, params2) + coll.call(my_module, params2) if coll end def parse_locals(values) @@ -48,34 +50,43 @@ module ReportExtends # Module contents element MODULE_CONTENTS = [ - ModuleElement.new(:steps, + ModuleElement.new(%i(completed_steps uncompleted_steps), + :steps, true, [:step], - proc do |my_module| - my_module.protocol.completed_steps.order(:position) + proc do |my_module, params2| + steps = [] + steps << true if params2["module_completed_steps"] == '1' + steps << false if params2["module_uncompleted_steps"] == '1' + my_module.protocol.steps.where(completed: steps).order(:position) end), - ModuleElement.new(:result_assets, + ModuleElement.new([:result_assets], + :result_assets, true, [:result], proc do |my_module| my_module.results.select { |r| r.is_asset && r.active? } end), - ModuleElement.new(:result_tables, + ModuleElement.new([:result_tables], + :result_tables, true, [:result], proc do |my_module| my_module.results.select { |r| r.is_table && r.active? } end), - ModuleElement.new(:result_texts, + ModuleElement.new([:result_texts], + :result_texts, true, [:result], proc do |my_module| my_module.results.select { |r| r.is_text && r.active? } end), - ModuleElement.new(:activity, + ModuleElement.new([:activity], + :activity, false, [:my_module, :order]), - ModuleElement.new(:samples, + ModuleElement.new([:samples], + :samples, false, [:my_module, :order]) ] diff --git a/config/locales/en.yml b/config/locales/en.yml index 37589f4c4..0579ef698 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -291,7 +291,9 @@ en: module_contents_inner: instructions: "Choose what information from task/s to include in the report" check_all: "All tasks content" - steps: "Completed protocol steps" + steps: "Steps" + completed_steps: "Completed" + uncompleted_steps: "Uncompleted" no_steps: "Task has no steps" results: "Results" result_assets: "Files" @@ -376,9 +378,12 @@ en: user_time: "Created by %{user} on %{timestamp}." step: sidebar_name: "Step %{pos}: %{name}" - user_time: "Completed by %{user} on %{timestamp}." step_pos: "Step %{pos}:" no_description: "No description" + completed: + user_time: "Completed by %{user} on %{timestamp}." + uncompleted: + user_time: "Created by %{user} on %{timestamp}." step_table: table_name: "[ %{name} ]" user_time: "Table created on %{timestamp}." From bbf6d38c50b4ded6aaee635fb4184aae78d334d3 Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Wed, 17 May 2017 15:14:35 +0200 Subject: [PATCH 20/29] Fix error handling in result_assets [SCI-1288] --- app/assets/javascripts/results/result_assets.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/results/result_assets.js b/app/assets/javascripts/results/result_assets.js index 93493a8a2..47a23013e 100644 --- a/app/assets/javascripts/results/result_assets.js +++ b/app/assets/javascripts/results/result_assets.js @@ -75,7 +75,7 @@ initPreviewModal(); Comments.initialize(); initNewResultAsset(); - }).on('ajax:error', function(xhr, status, e) { + }).on('ajax:error', function(e, xhr) { $form.renderFormErrors('result', xhr.responseJSON, true, e); animateSpinner(null, false); }); From 20265ddd69963a8e6f6ddb161b9c190cd2462f07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Wed, 17 May 2017 18:18:57 +0200 Subject: [PATCH 21/29] Readded result content modal for report creation and updated checkbox hierarchy logic accordingly. [fixes SCI-487] --- app/assets/javascripts/reports/new.js.erb | 6 ++ app/assets/javascripts/sitewide/utils.js | 12 ++- app/assets/stylesheets/reports.scss | 2 +- app/controllers/reports_controller.rb | 102 +++++++++++++++++- app/views/reports/new.html.erb | 2 + .../new/modal/_result_contents_inner.html.erb | 2 - 6 files changed, 117 insertions(+), 9 deletions(-) diff --git a/app/assets/javascripts/reports/new.js.erb b/app/assets/javascripts/reports/new.js.erb index 063659a62..cf4c9d66a 100644 --- a/app/assets/javascripts/reports/new.js.erb +++ b/app/assets/javascripts/reports/new.js.erb @@ -203,6 +203,12 @@ function initializeNewElement(newEl) { url = dh.data("add-experiment-contents-url"); break; case "my_module": url = dh.data("add-module-contents-url"); break; + case "step": + url = dh.data("add-step-contents-url"); break; + case "result_asset": + case "result_table": + case "result_text": + url = dh.data("add-result-contents-url"); break; } } diff --git a/app/assets/javascripts/sitewide/utils.js b/app/assets/javascripts/sitewide/utils.js index eb7c0c307..dbb1d7f28 100644 --- a/app/assets/javascripts/sitewide/utils.js +++ b/app/assets/javascripts/sitewide/utils.js @@ -228,10 +228,14 @@ $.fn.checkboxTreeLogic = function(dependencies, checkAll) { } // Disable/enable dependent checkboxes - $.each(dependencies, function(k, $v) { - var enable = $checkboxTree.find('#' + k).closest('li') - .find('input:checkbox:checked').length - $v.closest('li').find('input:checkbox').prop('disabled', !enable); + $.each(dependencies, function(responsibleParentID, $dependentParent) { + var $responsibleParent = $checkboxTree.find('#' + responsibleParentID); + if ($responsibleParent.length) { + var enable = $responsibleParent.closest('li') + .find('input:checkbox:checked').length + $dependentParent.closest('li').find('input:checkbox') + .prop('disabled', !enable); + } }); }).trigger('change'); }; diff --git a/app/assets/stylesheets/reports.scss b/app/assets/stylesheets/reports.scss index b4cf5fde8..056e01774 100644 --- a/app/assets/stylesheets/reports.scss +++ b/app/assets/stylesheets/reports.scss @@ -49,7 +49,7 @@ label { &[for="_experiment_all"], &[for="_module_all"], &[for="_step_all"], - &[for="result_all"] { + &[for="_result_all"] { font-weight: bold; } } diff --git a/app/controllers/reports_controller.rb b/app/controllers/reports_controller.rb index 4b0c922b9..5aca8e35d 100644 --- a/app/controllers/reports_controller.rb +++ b/app/controllers/reports_controller.rb @@ -21,8 +21,12 @@ class ReportsController < ApplicationController :project_contents_modal, :experiment_contents_modal, :module_contents_modal, + :step_contents_modal, + :result_contents_modal, :project_contents, - :module_contents + :module_contents, + :step_contents, + :result_contents ] before_action :check_view_permissions, only: :index @@ -36,8 +40,12 @@ class ReportsController < ApplicationController :project_contents_modal, :experiment_contents_modal, :module_contents_modal, + :step_contents_modal, + :result_contents_modal, :project_contents, - :module_contents + :module_contents, + :step_contents, + :result_contents ] before_action :check_destroy_permissions, only: :destroy @@ -267,6 +275,50 @@ class ReportsController < ApplicationController end end + # Modal for adding contents into step element + def step_contents_modal + step = Step.find_by_id(params[:id]) + + respond_to do |format| + if step.blank? + format.json do + render json: {}, status: :not_found + end + else + format.json do + render json: { + html: render_to_string( + partial: 'reports/new/modal/step_contents.html.erb', + locals: { project: @project, step: step } + ) + } + end + end + end + end + + # Modal for adding contents into result element + def result_contents_modal + result = Result.find_by_id(params[:id]) + + respond_to do |format| + if result.blank? + format.json do + render json: {}, status: :not_found + end + else + format.json do + render json: { + html: render_to_string( + partial: 'reports/new/modal/result_contents.html.erb', + locals: { project: @project, result: result } + ) + } + end + end + end + end + def project_contents respond_to do |format| elements = generate_project_contents_json @@ -335,6 +387,52 @@ class ReportsController < ApplicationController end end + def step_contents + step = Step.find_by_id(params[:id]) + + respond_to do |format| + if step.blank? + format.json { render json: {}, status: :not_found } + else + elements = generate_step_contents_json(step) + + if elements_empty? elements + format.json { render json: {}, status: :no_content } + else + format.json { + render json: { + status: :ok, + elements: elements + } + } + end + end + end + end + + def result_contents + result = Result.find_by_id(params[:id]) + + respond_to do |format| + if result.blank? + format.json { render json: {}, status: :not_found } + else + elements = generate_result_contents_json(result) + + if elements_empty? elements + format.json { render json: {}, status: :no_content } + else + format.json { + render json: { + status: :ok, + elements: elements + } + } + end + end + end + end + private def load_vars diff --git a/app/views/reports/new.html.erb b/app/views/reports/new.html.erb index 69eb41ced..41c43a58f 100644 --- a/app/views/reports/new.html.erb +++ b/app/views/reports/new.html.erb @@ -13,6 +13,8 @@ data-add-project-contents-url="<%= project_contents_modal_project_reports_url %>" data-add-experiment-contents-url="<%= experiment_contents_modal_project_reports_url %>" data-add-module-contents-url="<%= module_contents_modal_project_reports_url %>" + data-add-step-contents-url="<%= step_contents_modal_project_reports_url %>" + data-add-result-contents-url="<%= result_contents_modal_project_reports_url %>" data-stylesheet-url="<%= stylesheet_path "application" %>" data-print-title="<%=t "projects.reports.print_title", project: @project.name %>" data-project-id="<%= @project.id %>" diff --git a/app/views/reports/new/modal/_result_contents_inner.html.erb b/app/views/reports/new/modal/_result_contents_inner.html.erb index af31f4964..6a1af6bcb 100644 --- a/app/views/reports/new/modal/_result_contents_inner.html.erb +++ b/app/views/reports/new/modal/_result_contents_inner.html.erb @@ -9,11 +9,9 @@
  • <%= form.label :result_all, t("projects.reports.elements.modals.result_contents_inner.check_all"), class: "checkbox" %>
      -
    • <%= form.check_box :result_comments, label: t("projects.reports.elements.modals.result_contents_inner.comments") %>
    • -
  • From 1abaefce4f1c518b6e22787f9bf9dcb3239bad12 Mon Sep 17 00:00:00 2001 From: ajugo Date: Thu, 18 May 2017 09:19:44 +0200 Subject: [PATCH 22/29] At importing large sample file, error flash message appears [fixes SCI-903] (#625) * At importing large sample file, error flash message appears [fixes SCI-903] * Changing double quotes to single * Adding animatedSpinner --- .../javascripts/samples/samples_importer.js | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/app/assets/javascripts/samples/samples_importer.js b/app/assets/javascripts/samples/samples_importer.js index 463d9342d..2f6afa3c8 100644 --- a/app/assets/javascripts/samples/samples_importer.js +++ b/app/assets/javascripts/samples/samples_importer.js @@ -1,41 +1,50 @@ var previousIndex; var disabledOptions; -$("select").focus(function() { +var loadingSamples = false; +$('select').focus(function() { previousIndex = $(this)[0].selectedIndex; -}).change(function () { +}).change(function() { var currSelect = $(this); var currIndex = $(currSelect)[0].selectedIndex; - $("select").each(function() { + $('select').each(function() { if (currSelect !== $(this) && currIndex > 0) { - $(this).children().eq(currIndex).attr("disabled", "disabled"); + $(this).children().eq(currIndex).attr('disabled', 'disabled'); } - $(this).children().eq(previousIndex).removeAttr("disabled"); + $(this).children().eq(previousIndex).removeAttr('disabled'); }); previousIndex = currIndex; }); // Create import samples ajax -$("form#form-import") +$('form#form-import') .submit(function(e) { + // Check if we already uploading samples + if (loadingSamples) { + return false; + } disabledOptions = $("option[disabled='disabled']"); - disabledOptions.removeAttr("disabled"); + disabledOptions.removeAttr('disabled'); + loadingSamples = true; + animateSpinner(); }) -.on("ajax:success", function(ev, data, status) { +.on('ajax:success', function(ev, data, status) { // Simply reload page to show flash and updated samples list + loadingSamples = false; location.reload(); }) -.on("ajax:error", function(ev, data, status) { +.on('ajax:error', function(ev, data, status) { + loadingSamples = false; if (_.isUndefined(data.responseJSON.html)) { // Simply reload page to show flash - location.reload(); + location.reload(); } else { // Re-disable options - disabledOptions.attr("disabled", "disabled"); + disabledOptions.attr('disabled', 'disabled'); // Populate the errors container - $("#import-errors-container").html(data.responseJSON.html); + $('#import-errors-container').html(data.responseJSON.html); } }); From 4c5d7267acaf3104268b2390d96e764b1c34a725 Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Thu, 18 May 2017 13:48:02 +0200 Subject: [PATCH 23/29] Version bump to 1.11.0 --- config/initializers/constants.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/initializers/constants.rb b/config/initializers/constants.rb index c91632ac8..7ad024929 100644 --- a/config/initializers/constants.rb +++ b/config/initializers/constants.rb @@ -194,7 +194,7 @@ class Constants #============================================================================= # Application version - APP_VERSION = '1.10.0'.freeze + APP_VERSION = '1.11.0'.freeze TEXT_EXTRACT_FILE_TYPES = [ 'application/pdf', From 7310763184d877de528b3f44128d54949533edf0 Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Thu, 25 May 2017 08:57:50 +0200 Subject: [PATCH 24/29] Add missing include [SCI-1306] --- app/controllers/result_texts_controller.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/controllers/result_texts_controller.rb b/app/controllers/result_texts_controller.rb index cd713caad..b1c1e85c0 100644 --- a/app/controllers/result_texts_controller.rb +++ b/app/controllers/result_texts_controller.rb @@ -3,6 +3,7 @@ class ResultTextsController < ApplicationController include ActionView::Helpers::UrlHelper include ApplicationHelper include TinyMceHelper + include InputSanitizeHelper include Rails.application.routes.url_helpers before_action :load_vars, only: [:edit, :update, :download] From 157b1630b9c0516b0dcc1be04589f12a94ff64a6 Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Thu, 25 May 2017 16:28:06 +0200 Subject: [PATCH 25/29] Add missing include for sinitize_input [SCI-1309] --- app/helpers/application_helper.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 0b6c0b199..a59b5e729 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -1,6 +1,7 @@ module ApplicationHelper include ActionView::Helpers::AssetTagHelper include ActionView::Helpers::UrlHelper + include InputSanitizeHelper def module_page? controller_name == 'my_modules' From 853096634db2259eb341d9715f5d4ca9b1502cb9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Fri, 26 May 2017 11:13:27 +0200 Subject: [PATCH 26/29] Fixed permission error while cloning workflows. [fixes SCI-1291] --- app/controllers/canvas_controller.rb | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/app/controllers/canvas_controller.rb b/app/controllers/canvas_controller.rb index 3b4b0c93a..4f0291a64 100644 --- a/app/controllers/canvas_controller.rb +++ b/app/controllers/canvas_controller.rb @@ -73,10 +73,10 @@ class CanvasController < ApplicationController poss = update_params[:positions].split(";") center = "" (poss.collect { |pos| pos.split(",") }).each_with_index do |pos, index| - unless (pos.length == 3 and - pos[0].is_a? String and - is_int? pos[1] and - is_int? pos[2]) + unless pos.length == 3 && + pos[0].is_a?(String) && + float?(pos[1]) && + float?(pos[2]) error = true break end @@ -318,4 +318,9 @@ class CanvasController < ApplicationController /\A[-+]?\d+\z/ === val end + def float?(val) + true if Float(val) + rescue ArgumentError + false + end end From 19ffd77d32b0457aad4f1ad4577f8c9f5fb31a1e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Fri, 26 May 2017 18:09:29 +0200 Subject: [PATCH 27/29] Requests failed if smart annotation referenced a user who was no longer in the team. [fixes SCI-1305] --- app/helpers/application_helper.rb | 32 ++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index a59b5e729..95e991dff 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -184,6 +184,7 @@ module ApplicationHelper new_text = text.gsub(sa_user) do |el| match = el.match(sa_user) user = User.find_by_id(match[2].base62_decode) + next unless user team ||= current_team popover_for_user_name(user, team) end @@ -192,13 +193,8 @@ module ApplicationHelper # Generate smart annotation link for one user object def popover_for_user_name(user, team = nil) - if user && - team && - UserTeam.user_in_team(user, team).any? - user_t = user.user_teams - .where('user_teams.team_id = ?', team) - .first - end + user_still_in_team = user.teams.include?(team) + user_description = %(
    thumb
    @@ -207,9 +203,12 @@ module ApplicationHelper

    #{user.email}

    ) - if team.present? + if user_still_in_team + user_t = user.user_teams + .where('user_teams.team_id = ?', team) + .first user_description += %(

    - #{I18n.t('atwho.popover_html', + #{I18n.t('atwho.users.popover_html', role: user_t.role.capitalize, team: user_t.team.name, time: user_t.created_at.strftime('%B %Y'))} @@ -218,13 +217,16 @@ module ApplicationHelper user_description += %(

    ) end + user_name = user.full_name + user_name << ' ' + I18n.t('atwho.res.removed') if !user_still_in_team + raw("") + - raw('') + user.full_name + raw('') + "alt='avatar' class='atwho-user-img-popover'>") + + raw('') + user_name + raw('') end def user_avatar_absolute_url(user, style) From 5806cb8e6736f0ae5bb1732bf1929f908b958284 Mon Sep 17 00:00:00 2001 From: zmagod Date: Mon, 29 May 2017 09:10:11 +0200 Subject: [PATCH 28/29] removes unneeded animateSpinner call --- app/assets/javascripts/protocols/steps.js.erb | 1 - 1 file changed, 1 deletion(-) diff --git a/app/assets/javascripts/protocols/steps.js.erb b/app/assets/javascripts/protocols/steps.js.erb index 55c68a895..ca5a5e461 100644 --- a/app/assets/javascripts/protocols/steps.js.erb +++ b/app/assets/javascripts/protocols/steps.js.erb @@ -606,7 +606,6 @@ if (filesValid && checklistsValid && nameValid && descriptionValid) { // Local file uploading - animateSpinner(); newStepHandler(); } } From e8f842c29faf739c5bc61f18a27af00347f2501c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Mon, 29 May 2017 11:39:17 +0200 Subject: [PATCH 29/29] Forgot to add the updated locales. [fixes SCI-1305] --- config/locales/en.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index c792e8955..b2f1e77b4 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1575,10 +1575,11 @@ en: confirm_2: "to confirm" dismiss_1: "esc" dismiss_2: "to dismiss" + popover_html: "Team: %{team}
    Role: %{role}
    Joined: %{time}" res: archived: "(archived)" + removed: "(removed)" deleted: "(deleted)" - popover_html: "Team: %{team}
    Role: %{role}
    Joined: %{time}" zip_export: notification_title: 'Your package is ready to be exported!'