From 7f713b429350dbb8705ba3d50c691fbb552bdf38 Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Wed, 17 May 2017 13:06:21 +0200 Subject: [PATCH 01/79] Add smart annotations in sample info modal [SCI-960] --- app/views/samples/_info_sample_modal.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/samples/_info_sample_modal.html.erb b/app/views/samples/_info_sample_modal.html.erb index 089426109..641819516 100644 --- a/app/views/samples/_info_sample_modal.html.erb +++ b/app/views/samples/_info_sample_modal.html.erb @@ -40,7 +40,7 @@
<%= t "samples.modal_info.custom_field", cf: sample_custom_field.custom_field.name %> - <%= sample_custom_field.value %> + <%= custom_auto_link(sample_custom_field.value, simple_format: false, team: @team) %> <% end %>

From b527afd12b67023e93876883ee6ae7b0958632ce Mon Sep 17 00:00:00 2001 From: zmagod Date: Mon, 29 May 2017 14:42:55 +0200 Subject: [PATCH 02/79] generates samples csv file in background job [fixes SCI-1278] --- .../samples/sample_datatable.js.erb | 18 ++++++++- app/controllers/teams_controller.rb | 38 +++++++++---------- app/models/zip_export.rb | 6 +++ .../samples/_export_samples_modal.html.erb | 20 ++++++++++ app/views/shared/_samples.html.erb | 5 ++- config/locales/en.yml | 3 ++ 6 files changed, 66 insertions(+), 24 deletions(-) create mode 100644 app/views/samples/_export_samples_modal.html.erb diff --git a/app/assets/javascripts/samples/sample_datatable.js.erb b/app/assets/javascripts/samples/sample_datatable.js.erb index a53a1ccad..e8e7d683b 100644 --- a/app/assets/javascripts/samples/sample_datatable.js.erb +++ b/app/assets/javascripts/samples/sample_datatable.js.erb @@ -661,7 +661,14 @@ function updateButtons() { $("#deleteSamplesButton").removeClass("disabled"); $("#exportSamplesButton").removeClass("disabled"); $("#exportSamplesButton").prop("disabled",false); - $("#exportSamplesButton").on("click", function() { $('#form-export').submit(); }); + $("#exportSamplesButton").on("click", function() { + $('#modal-export-samples-success') + .modal('show') + .on('hidden.bs.modal', function() { + animateSpinner(null, true); + $('#form-export').submit(); + }); + }); $("#assignSamples").removeClass("disabled"); $("#assignSamples").prop("disabled", false); $("#unassignSamples").removeClass("disabled"); @@ -687,7 +694,14 @@ function updateButtons() { $("#deleteSamplesButton").removeClass("disabled"); $("#exportSamplesButton").removeClass("disabled"); $("#exportSamplesButton").prop("disabled",false); - $("#exportSamplesButton").on("click", function() { $('#form-export').submit(); }); + $("#exportSamplesButton").on("click", function() { + $('#modal-export-samples-success') + .modal('show') + .on('hidden.bs.modal', function() { + animateSpinner(null, true); + $('#form-export').submit(); + }); + }); $("#assignSamples").removeClass("disabled"); $("#assignSamples").prop("disabled", false); $("#unassignSamples").removeClass("disabled"); diff --git a/app/controllers/teams_controller.rb b/app/controllers/teams_controller.rb index 3472610cb..18e66b46b 100644 --- a/app/controllers/teams_controller.rb +++ b/app/controllers/teams_controller.rb @@ -262,26 +262,20 @@ class TeamsController < ApplicationController end def export_samples - require "csv" - - respond_to do |format| - if params[:sample_ids].present? and params[:header_ids].present? - samples = [] - - params[:sample_ids].each do |id| - sample = Sample.find_by_id(id) - - if sample - samples << sample - end - end - format.csv { send_data @team.to_csv(samples, params[:header_ids]) } - else - format.csv { render nothing: true } - end + if params[:sample_ids] && params[:header_ids] + generate_zip + else + flash[:alert] = t('zip_export.export_error') end + redirect_to :back end + def routing_error(error = 'Routing error', status = :not_found, exception=nil) + redirect_to root_path + end + + private + def load_vars @team = Team.find_by_id(params[:id]) @@ -302,8 +296,12 @@ class TeamsController < ApplicationController end end - def routing_error(error = 'Routing error', status = :not_found, exception=nil) - redirect_to root_path + def generate_zip + zip = ZipExport.create(user: current_user) + zip.generate_exportable_zip( + current_user, + @team.to_csv(Sample.where(id: params[:sample_ids]), params[:header_ids]), + :samples + ) end - end diff --git a/app/models/zip_export.rb b/app/models/zip_export.rb index 0b3f21d6b..38e92d44e 100644 --- a/app/models/zip_export.rb +++ b/app/models/zip_export.rb @@ -101,4 +101,10 @@ class ZipExport < ActiveRecord::Base end end end + + # generates zip export file for samples + def generate_samples_zip(tmp_dir, data, options = {}) + file = FileUtils.touch("#{tmp_dir}/export.csv").first + File.open(file, 'wb') { |f| f.write(data) } + end end diff --git a/app/views/samples/_export_samples_modal.html.erb b/app/views/samples/_export_samples_modal.html.erb new file mode 100644 index 000000000..06515abab --- /dev/null +++ b/app/views/samples/_export_samples_modal.html.erb @@ -0,0 +1,20 @@ + diff --git a/app/views/shared/_samples.html.erb b/app/views/shared/_samples.html.erb index 501260837..62c55a47d 100644 --- a/app/views/shared/_samples.html.erb +++ b/app/views/shared/_samples.html.erb @@ -1,6 +1,7 @@ <%= render partial: "samples/import_samples_modal" %> <%= render partial: "samples/delete_samples_modal" %> <%= render partial: "samples/delete_custom_field_modal" %> +<%= render partial: 'samples/export_samples_modal' %> @@ -8,8 +9,8 @@
<% if can_view_samples(@team) %> - <%= bootstrap_form_tag(url: export_samples_team_path(@team, format: :csv), - html: { id: 'form-export', class: 'hidden' }) do |f| %> + <%= bootstrap_form_tag(url: export_samples_team_path(@team, format: :json), + html: { id: 'form-export', class: 'hidden' }) do |f| %> <% end %> <% end %> diff --git a/config/locales/en.yml b/config/locales/en.yml index cf345468a..6c13daedd 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1584,6 +1584,9 @@ en: notification_title: 'Your package is ready to be exported!' expired_title: 'The required file was expired!' expired_description: 'The downloadable file expires in 7 days after its creation.' + export_error: 'An error occured.' + modal_label: 'Export request received' + modal_html: "

Your export request is being processed.

When completed we will send an email to %{email} inbox with a link to your exported samples. Note that the link will expire in 7 days.

" # This section contains general words that can be used in any parts of # application. tiny_mce: From 6e1f93dd116538a4394985f3d71c4a2ce77c8a35 Mon Sep 17 00:00:00 2001 From: zmagod Date: Mon, 29 May 2017 14:47:05 +0200 Subject: [PATCH 03/79] minor fix --- app/views/shared/_samples.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/shared/_samples.html.erb b/app/views/shared/_samples.html.erb index 62c55a47d..33b2a0475 100644 --- a/app/views/shared/_samples.html.erb +++ b/app/views/shared/_samples.html.erb @@ -9,7 +9,7 @@
<% if can_view_samples(@team) %> - <%= bootstrap_form_tag(url: export_samples_team_path(@team, format: :json), + <%= bootstrap_form_tag(url: export_samples_team_path(@team), html: { id: 'form-export', class: 'hidden' }) do |f| %> <% end %> <% end %> From d88b21fb5e7e2073c7ca49c117ebdd6fc8b6b3fe Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Thu, 1 Jun 2017 15:09:01 +0200 Subject: [PATCH 04/79] truncate all titles in activities --- app/helpers/activity_helper.rb | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/app/helpers/activity_helper.rb b/app/helpers/activity_helper.rb index bf0841b81..f65882547 100644 --- a/app/helpers/activity_helper.rb +++ b/app/helpers/activity_helper.rb @@ -1,13 +1,16 @@ module ActivityHelper def activity_truncate(message, len = Constants::NAME_TRUNCATION_LENGTH) - activity_title = message.match(/(.*?)<\/strong>/)[1] - if activity_title.length > Constants::NAME_TRUNCATION_LENGTH - title = "" - else - title = truncate(activity_title, length: len) + activity_titles = message.scan(/(.*?)<\/strong>/) + activity_titles.each do |activity_title| + activity_title = activity_title[0] + if activity_title.length > Constants::NAME_TRUNCATION_LENGTH + title = "" + else + title = truncate(activity_title, length: len) + end + message = message.gsub(/#{activity_title}/, title ) end - message = message.gsub(/#{activity_title}/, title ) sanitize_input(message) if message end From 7c2b657b0e628585eca0f0e2d9cc1b029a020b80 Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Thu, 1 Jun 2017 15:10:26 +0200 Subject: [PATCH 05/79] fix bug with special characters when truncating activities titles --- app/helpers/activity_helper.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/helpers/activity_helper.rb b/app/helpers/activity_helper.rb index f65882547..965e828a2 100644 --- a/app/helpers/activity_helper.rb +++ b/app/helpers/activity_helper.rb @@ -9,7 +9,7 @@ module ActivityHelper else title = truncate(activity_title, length: len) end - message = message.gsub(/#{activity_title}/, title ) + message = message.gsub(/#{Regexp.escape(activity_title)}/, title ) end sanitize_input(message) if message end From a9bd86352dab39e0628c60929aeadc841d1dcebf Mon Sep 17 00:00:00 2001 From: ajugo Date: Thu, 1 Jun 2017 15:52:02 +0200 Subject: [PATCH 06/79] Step: wrong last columns of table [fixes SCI-405] (#600) * Step: wrong last two columns of table after add table results [fixes SCI-405] * Changing double quotes to single * Adding empty line back --- app/assets/javascripts/protocols/steps.js.erb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/assets/javascripts/protocols/steps.js.erb b/app/assets/javascripts/protocols/steps.js.erb index ca5a5e461..e236eb124 100644 --- a/app/assets/javascripts/protocols/steps.js.erb +++ b/app/assets/javascripts/protocols/steps.js.erb @@ -635,8 +635,9 @@ 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%"); + if (parseInt($(table).css('height'), 10) < parseInt($(table).css('max-height'), 10) - 30) { + $(table).find('.ht_master .wtHolder').css({ 'height': '100%', + 'width': '100%' }); } } From 33252e6f3ec642b1a24f293170e8b7a666cf60a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Fri, 2 Jun 2017 16:34:01 +0200 Subject: [PATCH 07/79] Fixed DB dump loading (wasn't changed when docker composing was changed). --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 946f44e0a..bc41aaeee 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ APP_HOME="/usr/src/app" -DB_IP=$(shell docker inspect web_db_1 | grep -m 1 "\"IPAddress\": " | awk '{ match($$0, /"IPAddress": "([0-9\.]*)",/, a); print a[1] }') +DB_IP=$(shell docker inspect scinote_db_development | grep "\"IPAddress\": " | awk '{ match($$0, /"IPAddress": "([0-9\.]*)",/, a); print a[1] }') define PRODUCTION_CONFIG_BODY SECRET_KEY_BASE=$(shell openssl rand -hex 64) From 1c021b11db184f73624c1010ef16cd9b8a1ff315 Mon Sep 17 00:00:00 2001 From: zmagod Date: Fri, 2 Jun 2017 16:34:09 +0200 Subject: [PATCH 08/79] adds drag and drop files upload to steps [fixes SCI-1310] --- app/assets/javascripts/protocols/steps.js.erb | 296 ++++++++++++++---- app/assets/stylesheets/themes/scinote.scss | 39 +++ app/controllers/steps_controller.rb | 1 - app/views/my_modules/protocols.html.erb | 4 + app/views/steps/_empty_step.html.erb | 16 +- app/views/steps/_new.html.erb | 2 +- 6 files changed, 288 insertions(+), 70 deletions(-) diff --git a/app/assets/javascripts/protocols/steps.js.erb b/app/assets/javascripts/protocols/steps.js.erb index ca5a5e461..8b5f4974c 100644 --- a/app/assets/javascripts/protocols/steps.js.erb +++ b/app/assets/javascripts/protocols/steps.js.erb @@ -216,21 +216,21 @@ }); // 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; - }); + // $form.submit(function(){ + // $(this).find("[data-role='editable-table']").each(function() { + // var hot = $(this).find(".hot").handsontable('getInstance'); + // var contents = $(this).find('.hot-contents'); + // var data = JSON.stringify({data: hot.getData()}); + // contents.attr("value", data); + // }); + // + // setTimeout(function() { + // initStepsComments(); + // animateSpinner(null, false); + // SmartAnnotation.preventPropagation('.atwho-user-popover'); + // }, 1000); + // return true; + // }); } // Init ajax success/error for edit form @@ -279,49 +279,6 @@ }); } - function formNewAjax($form) { - $form - .on("ajax:beforeSend", function () { - $(".nested_step_checklists ul").each(function () { - reorderCheckboxData(this); - }); - }) - .on("ajax:success", function(e, data) { - $(this).after(data.html); - var $new_step = $(this).next(); - $(this).remove(); - - initCallBacks(); - initHandsOnTable($new_step); - expandStep($new_step); - toggleButtons(true); - SmartAnnotation.preventPropagation('.atwho-user-popover'); - - //Rerender tables - $new_step.find("div.step-result-hot-table").each(function() { - $(this).handsontable("render"); - }); - animateSpinner(null, false); - setupAssetsLoading(); - }) - .on("ajax:error", function(e, xhr, status, error) { - $(this).after(xhr.responseJSON.html); - var $form = $(this).next(); - $(this).remove(); - - $errInput = $form.find(".form-group.has-error").first().find("input"); - renderFormError(e, $errInput); - - formCallback($form); - formNewAjax($form); - applyCancelOnNew(); - animateSpinner(null, false); - - TinyMCE.destroyAll(); - SmartAnnotation.preventPropagation('.atwho-user-popover'); - }); - } - function toggleButtons(show) { if (show) { $("[data-action='new-step']").show(); @@ -540,6 +497,150 @@ }); } + global.DroppedFiles = (function() { + var droppedFiles = []; + var filesValid = true; + var totalSize = 0; + + function init(files, action) { + for(var i = 0; i < files.length; i++) { + droppedFiles.push(files[i]); + } + if(action === 'select') { + listItems(); + } + } + + function filesStatus() { + return filesValid; + } + + function listItems() { + $('.panel-step-attachment-new').remove(); + dragNdropAssetsOff(); + for(var i = 0; i < droppedFiles.length; i++) { + $('#new-step-assets') + .append(_uploadedAseetPreview(droppedFiles[i], i)) + .promise() + .done(function() { + _removeItemHandler(i); + }); + } + _validateTotalSize(); + dragNdropAssetsInit(); + } + + function appendFilesToForm(ev) { + var regex = /step\[assets_attributes\]\[[0-9]*\]\[id\]/; + var prevEls = $('input').filter(function() { + return this.name.match(regex); + }); + + var fd = new FormData($(ev.target).closest('form').get(0)); + for(var i = 0; i < droppedFiles.length; i++) { + var index = i + prevEls.length; + var name = 'step[assets_attributes][' + index + '][file]'; + fd.append(name, droppedFiles[i]); + } + droppedFiles = []; + filesValid = true; + totalSize = 0; + dragNdropAssetsOff(); + return fd; + } + + function _validateFilesSize(file) { + if((file.size/1048576) > <%= Constants::FILE_MAX_SIZE_MB %> && filesValid ) { + return "

<%= I18n.t 'general.file.size_exceeded', file_size: Constants::FILE_MAX_SIZE_MB %>

"; + } + totalSize += parseInt(file.size/1048576); + return ''; + } + + function _validateTotalSize() { + if(totalSize > <%= Constants::FILE_MAX_SIZE_MB %>) { + filesValid = false; + $.each($('.panel-step-attachment-new'), function() { + $(this) + .find('.panel-body') + .append("

<%= I18n.t('general.file.total_size', size: Constants::FILE_MAX_SIZE_MB) %>

"); + }); + } else { + $('.dnd-error').remove(); + filesValid = true; + } + } + + function _uploadedAseetPreview(asset, i) { + var html = '
'; + html += '
'; + html += ''; + html += 'File'; + html += '
'; + html += ''; + html += '
'; + html += '
'; + html += ' '; + html += truncateLongString(asset.name, + <%= Constants::FILENAME_TRUNCATION_LENGTH %>); + html += _validateFilesSize(asset); + html += '
'; + return html; + } + + function _removeItemHandler(id) { + $('[data-item-id="' + id +'"]').off('click').on('click', function(e) { + e.preventDefault(); + e.stopImmediatePropagation(); + e.stopPropagation(); + var $el = $(this); + var index = $el.data('item-id'); + totalSize -= parseInt(droppedFiles[index]/1048576); + droppedFiles.splice(parseInt(index), 1); + $el.closest('.panel-step-attachment-new').remove(); + _validateTotalSize(); + }); + } + + return Object.freeze({ + init: init, + appendFilesToForm: appendFilesToForm, + listItems: listItems, + filesStatus: filesStatus + }) + })(); + + global.dragNdropAssetsInit = function() { + var in_window = true; + + $('body').on('drag dragstart dragend dragover dragenter dragleave drop', + function(e) { + e.preventDefault(); + e.stopPropagation(); + }).on('dragover', function() { + in_window = true; + $('.is-dragover').show(); + }).on('dragleave', function() { + in_window = false; + setTimeout(function() { + if(!in_window) { + $('.is-dragover').hide(); + } + }, 5000); + + }).on('drop', function(e) { + $('.is-dragover').hide(); + DroppedFiles.init(e.originalEvent.dataTransfer.files); + DroppedFiles.listItems(); + }); + + } + + global.dragNdropAssetsOff = function() { + $('body').off('drag dragstart dragend dragover dragenter dragleave drop'); + $('.is-dragover').hide(); + } + // New step AJAX function newStepHandler() { $("[data-action='new-step']").off().on('click', function(event) { @@ -562,7 +663,6 @@ scrollTop: $(document).height() - $(window).height() }); formCallback($form); - formNewAjax($form); applyCancelOnNew(); toggleButtons(false); initializeCheckboxSorting(); @@ -588,13 +688,16 @@ // experience is improved global.processStep = function processStep(ev, editMode) { ev.stopPropagation(); + ev.preventDefault(); + ev.stopImmediatePropagation(); var $form = $(ev.target.form); $form.clearFormErrors(); $form.removeBlankFileForms(); - var $fileInputs = $form.find("input[type=file]"); - var filesValid = filesValidator(ev, $fileInputs, FileTypeEnum.FILE); + // var $fileInputs = $form.find("input[type=file]"); + // var filesValid = filesValidator(ev, $fileInputs, FileTypeEnum.FILE, true); + // debugger; var $checklists = $form.find(".nested_step_checklists"); var checklistsValid = checklistsValidator(ev, $checklists, editMode); var $nameInput = $form.find("#step_name"); @@ -604,9 +707,76 @@ var descriptionValid = textValidator(ev, $descrTextarea, 0, <%= Constants::TEXT_MAX_LENGTH %>); - if (filesValid && checklistsValid && nameValid && descriptionValid) { - // Local file uploading + if (DroppedFiles.filesStatus() && + checklistsValid && + nameValid && + descriptionValid) { + + $form.find("[data-role='editable-table']").each(function() { + var hot = $(this).find(".hot").handsontable('getInstance'); + var contents = $(this).find('.hot-contents'); + var data = JSON.stringify({data: hot.getData()}); + contents.attr("value", data); + }); + + setTimeout(function() { + initStepsComments(); + animateSpinner(null, false); + SmartAnnotation.preventPropagation('.atwho-user-popover'); + }, 1000); + + animateSpinner(null, true); + var data = DroppedFiles.appendFilesToForm(ev); + data.append('step[description]', TinyMCE.getContent()); + $.ajax({ + url: $form.attr('action'), + method: 'POST', + data: data, + contentType: false, + processData: false, + beforeSend: function() { + $(".nested_step_checklists ul").each(function () { + reorderCheckboxData(this); + }); + }, + success: function(data) { + $($form.closest('.well')).after(data.html); + var $new_step = $($form.closest('.well')).next(); + $($form.closest('.well')).remove(); + + initCallBacks(); + initHandsOnTable($new_step); + expandStep($new_step); + toggleButtons(true); + SmartAnnotation.preventPropagation('.atwho-user-popover'); + + //Rerender tables + $new_step.find("div.step-result-hot-table").each(function() { + $(this).handsontable("render"); + }); + animateSpinner(null, false); + setupAssetsLoading(); + }, + error: function(e) { + $form.after(xhr.responseJSON.html); + var $new_form = $form.next(); + $form.remove(); + + $errInput = $new_form.find(".form-group.has-error") + .first() + .find("input"); + renderFormError(e, $errInput); + + formCallback($form); + applyCancelOnNew(); + animateSpinner(null, false); + + TinyMCE.destroyAll(); + SmartAnnotation.preventPropagation('.atwho-user-popover'); + } + }); newStepHandler(); + } } diff --git a/app/assets/stylesheets/themes/scinote.scss b/app/assets/stylesheets/themes/scinote.scss index 7429fa6ff..bf72c7cdb 100644 --- a/app/assets/stylesheets/themes/scinote.scss +++ b/app/assets/stylesheets/themes/scinote.scss @@ -1265,6 +1265,45 @@ ul.content-module-activities { } } +.new-asset-box { + border: 1px solid $color-silver; + border-radius: 2px; + margin-bottom: 20px; + margin-top: 20px; + padding-bottom: 30px; + padding-top: 30px; + font-size: 2rem; +} + +.dnd-error { + color: $color-milano-red; +} + +.is-dragover { + background: rgba(0,0,0,0.4); + bottom: 0; + display: none; + height: 100%; + left: 0; + min-height: 100%; + pointer-events: none; + position: fixed; + right: 0; + top: 0; + width: 100%; + z-index: 999999; + + span { + color: $color-white; + display: block; + font-size: 4em; + font-weight: bold; + padding-top: 25%; + pointer-events: none; + text-align: center; + } +} + .step, .result { .panel { diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb index a9cbf6409..20ee1b81b 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -44,7 +44,6 @@ class StepsController < ApplicationController table.created_by = current_user table.team = current_team end - # Update default checked state @step.checklists.each do |checklist| checklist.checklist_items.each do |checklist_item| diff --git a/app/views/my_modules/protocols.html.erb b/app/views/my_modules/protocols.html.erb index d90814371..d4ebcd9de 100644 --- a/app/views/my_modules/protocols.html.erb +++ b/app/views/my_modules/protocols.html.erb @@ -1,4 +1,8 @@ <% provide(:head_title, t("my_modules.protocols.head_title", project: h(@project.name), module: h(@my_module.name)).html_safe) %> + +
+ Drop to add to Step +
<%= render partial: "shared/sidebar" %> <%= render partial: "shared/secondary_navigation" %> diff --git a/app/views/steps/_empty_step.html.erb b/app/views/steps/_empty_step.html.erb index 9e93a0f9a..8fa02775d 100644 --- a/app/views/steps/_empty_step.html.erb +++ b/app/views/steps/_empty_step.html.erb @@ -10,7 +10,9 @@ <%= t("protocols.steps.new.tab_checklists") %> -
  • - + <%= t('nav.label.repositories') %>
  • From c3d289291fc9ae1d8bd5c436dee5c2cc00e4d60a Mon Sep 17 00:00:00 2001 From: Luka Murn Date: Tue, 13 Jun 2017 09:09:07 +0200 Subject: [PATCH 41/79] Fix case statement Closes SCI-1335. --- app/helpers/sidebar_helper.rb | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/app/helpers/sidebar_helper.rb b/app/helpers/sidebar_helper.rb index 134d3121c..47952732d 100644 --- a/app/helpers/sidebar_helper.rb +++ b/app/helpers/sidebar_helper.rb @@ -31,16 +31,15 @@ module SidebarHelper end def module_action_to_link_to(my_module) - case action_name - when 'results' + if action_name == 'results' results_my_module_url(my_module) - when 'activities' + elsif action_name == 'activities' activities_my_module_url(my_module) - when 'samples' + elsif action_name == 'samples' samples_my_module_url(my_module) - when 'archive', 'module_archive', 'experiment_archive' + elsif action_name.in?(%w(archive module_archive experiment_archive)) archive_my_module_url(my_module) - when 'repository' && @repository + elsif action_name == 'repository' && @repository repository_my_module_url( id: my_module.id, repository_id: @repository.id From 4b0d7acabe55fc54c413320a3ace68709a1efda2 Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Mon, 12 Jun 2017 17:53:39 +0200 Subject: [PATCH 42/79] Fix search when viewing only assigned repository records [SCI-1342] --- app/datatables/repository_datatable.rb | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/app/datatables/repository_datatable.rb b/app/datatables/repository_datatable.rb index a5bc29e07..175d9ec54 100644 --- a/app/datatables/repository_datatable.rb +++ b/app/datatables/repository_datatable.rb @@ -138,20 +138,23 @@ class RepositoryDatatable < AjaxDatatablesRails::Base # after that "data" function will return json def get_raw_records repository_rows = RepositoryRow - .includes( + .preload( :repository_columns, - :created_by - # repository_cells: :value - ).references( - :repository_columns, - :created_by + :created_by, + repository_cells: :value ) + .joins(:created_by) .where(repository: @repository) if @my_module - @assigned_rows = @my_module - .repository_rows - .where(repository: @repository) + @assigned_rows = @my_module.repository_rows + .preload( + :repository_columns, + :created_by, + repository_cells: :value + ) + .joins(:created_by) + .where(repository: @repository) end # Make mappings of custom columns, so we have same id for every column From 77d922a5e8bf7335b75af4bfc12ab3515b1d68db Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Tue, 13 Jun 2017 09:45:18 +0200 Subject: [PATCH 43/79] change the name of add record/repository in repositories --- config/locales/en.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 1a6b409b8..297f87eff 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -845,7 +845,7 @@ en: index: head_title: "Repositories" title: "Repositories" - add_new_repository_tab: "Create new repository" + add_new_repository_tab: "Add repository" delete_flash: "\"%{name}\" repository was successfully deleted!" rename_flash: "\"%{old_name}\" repository was successfully renamed to \"%{new_name}\"!" copy_flash: "\"%{new}\" repository was successfully copied from \"%{old}\"!" @@ -888,7 +888,7 @@ en: row_name: "Name" added_on: "Added on" added_by: "Added by" - add_new_record: "Add record" + add_new_record: "Add new item" edit_record: "Edit" delete_record: "Delete" save_record: "Save" From 2d693a3fb798346c4ebe07fa2c6c2957d4b6d9a4 Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Tue, 13 Jun 2017 10:33:08 +0200 Subject: [PATCH 44/79] Fix repository view permissions for team guests [SCI-1345] --- app/helpers/permission_helper.rb | 6 +----- app/views/shared/_secondary_navigation.html.erb | 2 +- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/app/helpers/permission_helper.rb b/app/helpers/permission_helper.rb index d2b264af5..ed092bbb6 100644 --- a/app/helpers/permission_helper.rb +++ b/app/helpers/permission_helper.rb @@ -1058,12 +1058,8 @@ module PermissionHelper team.repositories.count < Constants::REPOSITORIES_LIMIT end - def can_view_repositories(team) - is_normal_user_or_admin_of_team(team) - end - def can_view_repository(repository) - is_normal_user_or_admin_of_team(repository.team) + is_member_of_team(repository.team) end def can_edit_and_destroy_repository(repository) diff --git a/app/views/shared/_secondary_navigation.html.erb b/app/views/shared/_secondary_navigation.html.erb index d1de50a94..75350d047 100644 --- a/app/views/shared/_secondary_navigation.html.erb +++ b/app/views/shared/_secondary_navigation.html.erb @@ -188,7 +188,7 @@ <% end %> - <% if can_view_repositories(@my_module.experiment.project.team) && + <% if can_view_team_repositories(@my_module.experiment.project.team) && @my_module.experiment.project.team.repositories.exists? %>
  • "> " data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> From 2e98433abcbe3e8b38bbb5216ae8265722ad8231 Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Tue, 13 Jun 2017 16:56:28 +0200 Subject: [PATCH 45/79] Remove row selection after assign/unassign in repositories [SCI-1365] --- .../javascripts/repositories/repository_datatable.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index 61cff3be0..851b07c15 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -453,10 +453,12 @@ function onClickAssignRecords() { success: function(data) { HelperModule.flashAlertMsg(data.flash, 'success'); onClickCancel(); + clearRowSelection(); }, error: function(data) { HelperModule.flashAlertMsg(data.responseJSON.flash, 'danger'); onClickCancel(); + clearRowSelection(); } }); } @@ -471,10 +473,12 @@ function onClickUnassignRecords() { success: function(data) { HelperModule.flashAlertMsg(data.flash, 'success'); onClickCancel(); + clearRowSelection(); }, error: function(data) { HelperModule.flashAlertMsg(data.responseJSON.flash, 'danger'); onClickCancel(); + clearRowSelection(); } }); } @@ -764,6 +768,13 @@ function clearAllErrors() { $('#alert-container').find('div').remove(); } +function clearRowSelection() { + $('.dt-body-center .repository-row-selector').prop('checked', false); + $('.dt-body-center .repository-row-selector').closest('tr') + .removeClass('selected'); + rowsSelected = []; +} + // Restore previous table function onClickCancel() { if ($('#assigned').text().length === 0) { From 849b269d8734e825e9b1892f7809990a14a0162e Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Tue, 13 Jun 2017 16:56:34 +0200 Subject: [PATCH 46/79] fix errors in repo table --- .../repositories/repository_datatable.js | 2 +- app/controllers/repository_rows_controller.rb | 73 ++++++++++--------- 2 files changed, 38 insertions(+), 37 deletions(-) diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index 61cff3be0..a1fc47553 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -670,7 +670,7 @@ function onClickSave() { if (input) { input.closest('.form-group').addClass('has-error'); input.parent().append("" + - val.value[0] + '
    '); + val.data[0] + '
    '); } }); }); diff --git a/app/controllers/repository_rows_controller.rb b/app/controllers/repository_rows_controller.rb index 2d52bdecc..ac2c4cf92 100644 --- a/app/controllers/repository_rows_controller.rb +++ b/app/controllers/repository_rows_controller.rb @@ -21,7 +21,6 @@ class RepositoryRowsController < ApplicationController record.name = record_params[:name] unless record_params[:name].blank? unless record.save errors[:default_fields] = record.errors.messages - raise ActiveRecord::RecordInvalid end if params[:repository_cells] params[:repository_cells].each do |key, value| @@ -37,29 +36,30 @@ class RepositoryRowsController < ApplicationController repository_column: column } ) - unless cell_value.save + if cell_value.save + record_annotation_notification(record, cell_value.repository_cell) + else errors[:repository_cells] << { - "#{cell.repository_column.id}": cell_value.errors.messages + "#{column.id}": cell_value.errors.messages } - raise ActiveRecord::RecordInvalid end - record_annotation_notification(record, cell_value.repository_cell) end end end respond_to do |format| format.json do - render json: { id: record.id, - flash: t('repositories.create.success_flash', - record: escape_input(record.name), - repository: escape_input(@repository.name)) }, - status: :ok + if errors[:default_fields].empty? && errors[:repository_cells].empty? + render json: { id: record.id, + flash: t('repositories.create.success_flash', + record: escape_input(record.name), + repository: escape_input(@repository.name)) }, + status: :ok + else + render json: errors, + status: :bad_request + end end end - rescue - respond_to do |format| - format.json { render json: errors, status: :bad_request } - end end def edit @@ -94,7 +94,6 @@ class RepositoryRowsController < ApplicationController @record.name = record_params[:name].blank? ? nil : record_params[:name] unless @record.save errors[:default_fields] = @record.errors.messages - raise ActiveRecord::RecordInvalid end if params[:repository_cells] params[:repository_cells].each do |key, value| @@ -104,13 +103,13 @@ class RepositoryRowsController < ApplicationController if existing # Cell exists and new value present, so update value existing.value.data = value - unless existing.value.save + if existing.value.save + record_annotation_notification(@record, existing) + else errors[:repository_cells] << { - "#{cell.repository_column_id}": existing.value.errors.messages + "#{existing.repository_column_id}": existing.value.errors.messages } - raise ActiveRecord::RecordInvalid end - record_annotation_notification(@record, existing) else # Looks like it is a new cell, so we need to create new value, cell # will be created automatically @@ -126,13 +125,13 @@ class RepositoryRowsController < ApplicationController repository_column: column } ) - unless value.save + if value.save + record_annotation_notification(@record, value.repository_cell) + else errors[:repository_cells] << { "#{cell.repository_column_id}": value.errors.messages } - raise ActiveRecord::RecordInvalid end - record_annotation_notification(@record, value.repository_cell) end end # Clean up empty cells, not present in updated record @@ -145,24 +144,26 @@ class RepositoryRowsController < ApplicationController end end - # Row sucessfully updated, so sending response to client respond_to do |format| format.json do - render json: { - id: @record.id, - flash: t( - 'repositories.update.success_flash', - record: escape_input(@record.name), - repository: escape_input(@repository.name) - ) - }, - status: :ok + if errors[:default_fields].empty? && errors[:repository_cells].empty? + # Row sucessfully updated, so sending response to client + render json: { + id: @record.id, + flash: t( + 'repositories.update.success_flash', + record: escape_input(@record.name), + repository: escape_input(@repository.name) + ) + }, + status: :ok + else + # Errors + render json: errors, + status: :bad_request + end end end - rescue - respond_to do |format| - format.json { render json: errors, status: :bad_request } - end end def delete_records From 1bc46fe0cb9d4f4ed1d40cb06d822b950ab33a76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Tue, 13 Jun 2017 18:12:42 +0200 Subject: [PATCH 47/79] Reverted the part of the repository row controller code that didn't needed changes. [SCI-1351] --- app/controllers/repository_rows_controller.rb | 69 +++++++++---------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/app/controllers/repository_rows_controller.rb b/app/controllers/repository_rows_controller.rb index ac2c4cf92..f501167ab 100644 --- a/app/controllers/repository_rows_controller.rb +++ b/app/controllers/repository_rows_controller.rb @@ -21,6 +21,7 @@ class RepositoryRowsController < ApplicationController record.name = record_params[:name] unless record_params[:name].blank? unless record.save errors[:default_fields] = record.errors.messages + raise ActiveRecord::RecordInvalid end if params[:repository_cells] params[:repository_cells].each do |key, value| @@ -36,30 +37,29 @@ class RepositoryRowsController < ApplicationController repository_column: column } ) - if cell_value.save - record_annotation_notification(record, cell_value.repository_cell) - else + unless cell_value.save errors[:repository_cells] << { "#{column.id}": cell_value.errors.messages } + raise ActiveRecord::RecordInvalid end + record_annotation_notification(record, cell_value.repository_cell) end end end respond_to do |format| format.json do - if errors[:default_fields].empty? && errors[:repository_cells].empty? - render json: { id: record.id, - flash: t('repositories.create.success_flash', - record: escape_input(record.name), - repository: escape_input(@repository.name)) }, - status: :ok - else - render json: errors, - status: :bad_request - end + render json: { id: record.id, + flash: t('repositories.create.success_flash', + record: escape_input(record.name), + repository: escape_input(@repository.name)) }, + status: :ok end end + rescue + respond_to do |format| + format.json { render json: errors, status: :bad_request } + end end def edit @@ -94,6 +94,7 @@ class RepositoryRowsController < ApplicationController @record.name = record_params[:name].blank? ? nil : record_params[:name] unless @record.save errors[:default_fields] = @record.errors.messages + raise ActiveRecord::RecordInvalid end if params[:repository_cells] params[:repository_cells].each do |key, value| @@ -103,13 +104,13 @@ class RepositoryRowsController < ApplicationController if existing # Cell exists and new value present, so update value existing.value.data = value - if existing.value.save - record_annotation_notification(@record, existing) - else + unless existing.value.save errors[:repository_cells] << { "#{existing.repository_column_id}": existing.value.errors.messages } + raise ActiveRecord::RecordInvalid end + record_annotation_notification(@record, existing) else # Looks like it is a new cell, so we need to create new value, cell # will be created automatically @@ -125,13 +126,13 @@ class RepositoryRowsController < ApplicationController repository_column: column } ) - if value.save - record_annotation_notification(@record, value.repository_cell) - else + unless value.save errors[:repository_cells] << { "#{cell.repository_column_id}": value.errors.messages } + raise ActiveRecord::RecordInvalid end + record_annotation_notification(@record, value.repository_cell) end end # Clean up empty cells, not present in updated record @@ -144,26 +145,24 @@ class RepositoryRowsController < ApplicationController end end + # Row sucessfully updated, so sending response to client respond_to do |format| format.json do - if errors[:default_fields].empty? && errors[:repository_cells].empty? - # Row sucessfully updated, so sending response to client - render json: { - id: @record.id, - flash: t( - 'repositories.update.success_flash', - record: escape_input(@record.name), - repository: escape_input(@repository.name) - ) - }, - status: :ok - else - # Errors - render json: errors, - status: :bad_request - end + render json: { + id: @record.id, + flash: t( + 'repositories.update.success_flash', + record: escape_input(@record.name), + repository: escape_input(@repository.name) + ) + }, + status: :ok end end + rescue + respond_to do |format| + format.json { render json: errors, status: :bad_request } + end end def delete_records From cea6d15d3ed663d1a3237abde3415bd878534d13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Tue, 13 Jun 2017 18:15:47 +0200 Subject: [PATCH 48/79] Fixed Hound warning. [SCI-1351] --- app/controllers/repository_rows_controller.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/repository_rows_controller.rb b/app/controllers/repository_rows_controller.rb index f501167ab..69ed6a3cf 100644 --- a/app/controllers/repository_rows_controller.rb +++ b/app/controllers/repository_rows_controller.rb @@ -106,7 +106,8 @@ class RepositoryRowsController < ApplicationController existing.value.data = value unless existing.value.save errors[:repository_cells] << { - "#{existing.repository_column_id}": existing.value.errors.messages + "#{existing.repository_column_id}": + existing.value.errors.messages } raise ActiveRecord::RecordInvalid end From 6dd85d6c3956751b5089aef20cb7d1737f82ad6c Mon Sep 17 00:00:00 2001 From: zmagod Date: Wed, 14 Jun 2017 09:45:49 +0200 Subject: [PATCH 49/79] fixes drag'n drop bug in results on safari [fixes SCI-1370] --- app/assets/javascripts/sitewide/drag_n_drop.js.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/assets/javascripts/sitewide/drag_n_drop.js.erb b/app/assets/javascripts/sitewide/drag_n_drop.js.erb index f53fa1adf..0f1c62068 100644 --- a/app/assets/javascripts/sitewide/drag_n_drop.js.erb +++ b/app/assets/javascripts/sitewide/drag_n_drop.js.erb @@ -167,7 +167,7 @@ var fd = new FormData(); var result_names = []; - $.each($('input[rel="results[name]"'), function() { + $.each($('input[rel="results[name]"]'), function() { result_names.push($(this).val()); }); result_names.reverse(); From e6ec184dba97992c2199c8df7e749a679e1c79b6 Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Wed, 14 Jun 2017 13:09:23 +0200 Subject: [PATCH 50/79] fix multiple errors handling on fields in repositories tables --- app/controllers/repository_rows_controller.rb | 70 ++++++++++--------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/app/controllers/repository_rows_controller.rb b/app/controllers/repository_rows_controller.rb index 69ed6a3cf..973373022 100644 --- a/app/controllers/repository_rows_controller.rb +++ b/app/controllers/repository_rows_controller.rb @@ -21,7 +21,6 @@ class RepositoryRowsController < ApplicationController record.name = record_params[:name] unless record_params[:name].blank? unless record.save errors[:default_fields] = record.errors.messages - raise ActiveRecord::RecordInvalid end if params[:repository_cells] params[:repository_cells].each do |key, value| @@ -37,29 +36,31 @@ class RepositoryRowsController < ApplicationController repository_column: column } ) - unless cell_value.save + if cell_value.save + record_annotation_notification(record, cell_value.repository_cell) + else errors[:repository_cells] << { "#{column.id}": cell_value.errors.messages } - raise ActiveRecord::RecordInvalid end - record_annotation_notification(record, cell_value.repository_cell) end end end + respond_to do |format| format.json do - render json: { id: record.id, - flash: t('repositories.create.success_flash', - record: escape_input(record.name), - repository: escape_input(@repository.name)) }, - status: :ok + if errors[:default_fields].empty? && errors[:repository_cells].empty? + render json: { id: record.id, + flash: t('repositories.create.success_flash', + record: escape_input(record.name), + repository: escape_input(@repository.name)) }, + status: :ok + else + render json: errors, + status: :bad_request + end end end - rescue - respond_to do |format| - format.json { render json: errors, status: :bad_request } - end end def edit @@ -94,7 +95,6 @@ class RepositoryRowsController < ApplicationController @record.name = record_params[:name].blank? ? nil : record_params[:name] unless @record.save errors[:default_fields] = @record.errors.messages - raise ActiveRecord::RecordInvalid end if params[:repository_cells] params[:repository_cells].each do |key, value| @@ -104,14 +104,14 @@ class RepositoryRowsController < ApplicationController if existing # Cell exists and new value present, so update value existing.value.data = value - unless existing.value.save + if existing.value.save + record_annotation_notification(@record, existing) + else errors[:repository_cells] << { "#{existing.repository_column_id}": existing.value.errors.messages } - raise ActiveRecord::RecordInvalid end - record_annotation_notification(@record, existing) else # Looks like it is a new cell, so we need to create new value, cell # will be created automatically @@ -127,13 +127,13 @@ class RepositoryRowsController < ApplicationController repository_column: column } ) - unless value.save + if value.save + record_annotation_notification(@record, value.repository_cell) + else errors[:repository_cells] << { "#{cell.repository_column_id}": value.errors.messages } - raise ActiveRecord::RecordInvalid end - record_annotation_notification(@record, value.repository_cell) end end # Clean up empty cells, not present in updated record @@ -146,24 +146,26 @@ class RepositoryRowsController < ApplicationController end end - # Row sucessfully updated, so sending response to client respond_to do |format| format.json do - render json: { - id: @record.id, - flash: t( - 'repositories.update.success_flash', - record: escape_input(@record.name), - repository: escape_input(@repository.name) - ) - }, - status: :ok + if errors[:default_fields].empty? && errors[:repository_cells].empty? + # Row sucessfully updated, so sending response to client + render json: { + id: @record.id, + flash: t( + 'repositories.update.success_flash', + record: escape_input(@record.name), + repository: escape_input(@repository.name) + ) + }, + status: :ok + else + # Errors + render json: errors, + status: :bad_request + end end end - rescue - respond_to do |format| - format.json { render json: errors, status: :bad_request } - end end def delete_records From 13fdbf885076b22af69bb54dfcac2d9edda36b7d Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Wed, 14 Jun 2017 14:29:59 +0200 Subject: [PATCH 51/79] Fix sorting in repositories when only assigned selected [SCI-1349] --- app/datatables/repository_datatable.rb | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/app/datatables/repository_datatable.rb b/app/datatables/repository_datatable.rb index 175d9ec54..d6f4ae306 100644 --- a/app/datatables/repository_datatable.rb +++ b/app/datatables/repository_datatable.rb @@ -244,18 +244,14 @@ class RepositoryDatatable < AjaxDatatablesRails::Base # as sq ORDER BY CASE WHEN sq.custom_field_id = #{column_id} THEN 1 ELSE 2 END #{dir}, sq.value #{dir} # LIMIT #{per_page} OFFSET #{offset}") - RepositoryRow.find_by_sql( - "SELECT repository_rows.*, values.value AS value - FROM repository_rows - LEFT OUTER JOIN (SELECT repository_cells.*, + records.joins( + "LEFT OUTER JOIN (SELECT repository_cells.repository_row_id, repository_text_values.data AS value FROM repository_cells INNER JOIN repository_text_values ON repository_text_values.id = repository_cells.value_id WHERE repository_cells.repository_column_id = #{column_id}) AS values - ON values.repository_row_id = repository_rows.id - WHERE repository_rows.repository_id = #{@repository.id} - ORDER BY value #{dir} LIMIT #{per_page} OFFSET #{offset}" - ) + ON values.repository_row_id = repository_rows.id" + ).order("values.value #{dir}") else super(records) end From 107aa76e5510901e8720b73575363bdbeba264ae Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Wed, 14 Jun 2017 14:48:22 +0200 Subject: [PATCH 52/79] fix bug with audit trail - ajax error --- app/helpers/application_helper.rb | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 37da2903d..fd3ddf0e4 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -246,7 +246,11 @@ module ApplicationHelper if !prefix.empty? && !prefix.include?('http://') && !prefix.include?('https://') - prefix = request.ssl? ? "https://#{prefix}" : "http://#{prefix}" + prefix = if respond_to?(:request) && request.ssl? + "https://#{prefix}" + else + "http://#{prefix}" + end end unless user.avatar(style) == '/images/icon_small/missing.png' From 5d6fba7153e006a6e2bbf0ef9342f49969698973 Mon Sep 17 00:00:00 2001 From: zmagod Date: Wed, 14 Jun 2017 17:35:41 +0200 Subject: [PATCH 53/79] fixes bug with sorting columns [fixes SCI-1371] --- app/assets/javascripts/repositories/repository_datatable.js | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index 79e28abd0..28cf3c22d 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -42,7 +42,6 @@ function dataTableInit() { originalHeader = $('#repository-table thead').children().clone(); viewAssigned = 'assigned'; table = $('#repository-table').DataTable({ - order: [[2, 'desc']], dom: "R<'row'<'col-sm-9-custom toolbar'l><'col-sm-3-custom'f>>tpi", stateSave: true, processing: true, @@ -52,7 +51,7 @@ function dataTableInit() { scrollY: '64vh', scrollCollapse: true, colReorder: { - fixedColumnsLeft: $('#assigned').text().length === 0 ? 1 : 2, + fixedColumnsLeft: 2, realtime: false }, destroy: true, @@ -92,7 +91,6 @@ function dataTableInit() { columns: (function() { var numOfColumns = $('#repository-table').data('num-columns'); var columns = []; - for (var i = 0; i < numOfColumns; i++) { var visible = (i <= 4); var searchable = (i > 0 && i <= 4); @@ -164,7 +162,7 @@ function dataTableInit() { } else { table.column(1).visible(true); } - for (var i = 2; i < table.columns()[0].length; i++) { + for (var i = 1; i < table.columns()[0].length; i++) { var visibility = false; if (myData.columns[i]) { visibility = myData.columns[i].visible; From be4a8d494a00789d30da72c979a3aeeb192c69e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Wed, 14 Jun 2017 19:28:12 +0200 Subject: [PATCH 54/79] Search functionality added to custom columns of custom repositories. [SCI-1357] --- app/datatables/repository_datatable.rb | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/app/datatables/repository_datatable.rb b/app/datatables/repository_datatable.rb index 175d9ec54..f2d7ecb4f 100644 --- a/app/datatables/repository_datatable.rb +++ b/app/datatables/repository_datatable.rb @@ -174,16 +174,33 @@ class RepositoryDatatable < AjaxDatatablesRails::Base def fetch_records records = get_raw_records records = @assigned_rows if @my_module && params[:assigned] == 'assigned' - records = sort_records(records) if params[:order].present? - escape_special_chars records = filter_records(records) if params[:search].present? && !sorting_by_custom_column + records = sort_records(records) if params[:order].present? records = paginate_records(records) if !(params[:length].present? && params[:length] == '-1') && !sorting_by_custom_column + escape_special_chars records end + # Overriden to make it work for custom columns, because they are polymorphic + def simple_search(records) + return records unless params[:search].present? && + params[:search][:value].present? + search_val = params[:search][:value] + + filtered_ids = RepositoryRow.select do |r| + [r.name, r.created_at.to_s, r.created_by.full_name].any? do |s| + s.include?(search_val) + end || + r.repository_cells.map do |c| + c.value.data.include?(search_val) + end.any? + end + records.where!(id: filtered_ids) + end + # Override default sort method if needed def sort_records(records) if params[:order].present? && params[:order].length == 1 From e38947b1f8de50486eb2697e985292bc1c51dc86 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Wed, 14 Jun 2017 19:28:53 +0200 Subject: [PATCH 55/79] Minor repository search refactoring. [SCI-1357] --- app/datatables/repository_datatable.rb | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/app/datatables/repository_datatable.rb b/app/datatables/repository_datatable.rb index f2d7ecb4f..7ca2f07c0 100644 --- a/app/datatables/repository_datatable.rb +++ b/app/datatables/repository_datatable.rb @@ -191,12 +191,9 @@ class RepositoryDatatable < AjaxDatatablesRails::Base search_val = params[:search][:value] filtered_ids = RepositoryRow.select do |r| - [r.name, r.created_at.to_s, r.created_by.full_name].any? do |s| - s.include?(search_val) - end || - r.repository_cells.map do |c| - c.value.data.include?(search_val) - end.any? + row_cells = [r.name, r.created_at.to_s, r.created_by.full_name] + row_cells.push(*r.repository_cells.collect { |c| c.value.data }) + row_cells.any? { |c| c.include?(search_val) } end records.where!(id: filtered_ids) end From 092e82c7224aa32ce2e786eb2ef6e4c856c5e08a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Wed, 14 Jun 2017 19:33:06 +0200 Subject: [PATCH 56/79] Date search fix for repositories. [SCI-1357] --- app/datatables/repository_datatable.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/datatables/repository_datatable.rb b/app/datatables/repository_datatable.rb index 7ca2f07c0..bf1f2f947 100644 --- a/app/datatables/repository_datatable.rb +++ b/app/datatables/repository_datatable.rb @@ -184,14 +184,15 @@ class RepositoryDatatable < AjaxDatatablesRails::Base records end - # Overriden to make it work for custom columns, because they are polymorphic + # Overriden to make it work for custom columns, because they are polymorphic def simple_search(records) return records unless params[:search].present? && params[:search][:value].present? search_val = params[:search][:value] filtered_ids = RepositoryRow.select do |r| - row_cells = [r.name, r.created_at.to_s, r.created_by.full_name] + row_cells = [r.name, r.created_at.strftime(Constants::DATE_FORMAT), + r.created_by.full_name] row_cells.push(*r.repository_cells.collect { |c| c.value.data }) row_cells.any? { |c| c.include?(search_val) } end From bae1e298d76cff11e7079f6062fc202f97a6400c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Zrim=C5=A1ek?= Date: Wed, 14 Jun 2017 19:49:08 +0200 Subject: [PATCH 57/79] Fixed repositories search to only search the current repository. [SCI-1357] --- app/datatables/repository_datatable.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/datatables/repository_datatable.rb b/app/datatables/repository_datatable.rb index bf1f2f947..9e9550c98 100644 --- a/app/datatables/repository_datatable.rb +++ b/app/datatables/repository_datatable.rb @@ -185,18 +185,20 @@ class RepositoryDatatable < AjaxDatatablesRails::Base end # Overriden to make it work for custom columns, because they are polymorphic - def simple_search(records) - return records unless params[:search].present? && - params[:search][:value].present? + # NOTE: Function assumes the provided records/rows are only from the current + # repository! + def simple_search(repo_rows) + return repo_rows unless params[:search].present? && + params[:search][:value].present? search_val = params[:search][:value] - filtered_ids = RepositoryRow.select do |r| + filtered_rows = repo_rows.select do |r| row_cells = [r.name, r.created_at.strftime(Constants::DATE_FORMAT), r.created_by.full_name] row_cells.push(*r.repository_cells.collect { |c| c.value.data }) row_cells.any? { |c| c.include?(search_val) } end - records.where!(id: filtered_ids) + repo_rows.where(id: filtered_rows) end # Override default sort method if needed From ea455d359693a4bd09b58099600d28d6d44a2d60 Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Thu, 15 Jun 2017 09:43:10 +0200 Subject: [PATCH 58/79] fix no repository name in activity bug --- app/controllers/my_modules_controller.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/my_modules_controller.rb b/app/controllers/my_modules_controller.rb index 67621878e..be9eec021 100644 --- a/app/controllers/my_modules_controller.rb +++ b/app/controllers/my_modules_controller.rb @@ -417,7 +417,7 @@ class MyModulesController < ApplicationController 'activities.assign_repository_records', user: current_user.full_name, task: @my_module.name, - repository: @repository, + repository: @repository.name, records: records_names.join(', ') ) ) @@ -462,7 +462,7 @@ class MyModulesController < ApplicationController 'activities.unassign_repository_records', user: current_user.full_name, task: @my_module.name, - repository: @repository, + repository: @repository.name, records: records.map(&:name).join(', ') ) ) From 4566fc7191f6eb605a0043493b58575d860b004b Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Thu, 15 Jun 2017 10:06:12 +0200 Subject: [PATCH 59/79] fix text in activity for assign/unassign records message --- config/locales/en.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 297f87eff..df9393351 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1122,8 +1122,8 @@ en: uncomplete_module: "%{user} uncompleted task %{module}." assign_sample: "%{user} assigned sample(s) %{samples} to task(s) %{tasks}" unassign_sample: "%{user} unassigned sample(s) %{samples} from task(s) %{tasks}" - assign_repository_records: "%{user} assigned %{repository} repository records(s) %{records} to task %{task}" - unassign_repository_records: "%{user} unassigned %{repository} repository records(s) %{records} from task %{task}" + assign_repository_records: "%{user} assigned records(s) %{records} from %{repository} repository to task %{task}" + unassign_repository_records: "%{user} unassigned records(s) %{records} from %{repository} repository from task %{task}" create_step: "%{user} created Step %{step} %{step_name}." destroy_step: "%{user} deleted Step %{step} %{step_name}." add_comment_to_step: "%{user} commented on Step %{step} %{step_name}." From a195c9a5af1b01eaf714dde42a3dd8f0637f9da4 Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Thu, 15 Jun 2017 15:06:02 +0200 Subject: [PATCH 60/79] truncate and display text in tooltip in custom repository fields --- .../javascripts/repositories/repository_datatable.js | 11 ++++++++++- app/assets/stylesheets/themes/scinote.scss | 5 +++++ app/datatables/repository_datatable.rb | 9 ++++++--- config/initializers/constants.rb | 2 ++ 4 files changed, 23 insertions(+), 4 deletions(-) diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index 28cf3c22d..c9592123c 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -355,6 +355,13 @@ function initHeaderTooltip() { offsetLeft -= 150; } var offsetTop = $tooltip.offset().top; + var width = 200; + + // set tooltip params in the table body + if ( $(this).parents('#repository-table').length ) { + offsetLeft -= 130; + width = $('#repository-table').width() - 200; + } $('body').append($tooltip); $tooltip.css('background-color', '#d2d2d2'); $tooltip.css('border-radius', '6px'); @@ -366,7 +373,7 @@ function initHeaderTooltip() { $tooltip.css('text-align', 'center'); $tooltip.css('top', offsetTop + 'px'); $tooltip.css('visibility', 'visible'); - $tooltip.css('width', '200px'); + $tooltip.css('width', width + 'px'); $tooltip.css('word-wrap', 'break-word'); $(this).data('dropdown-tooltip', $tooltip); }, function() { @@ -431,12 +438,14 @@ function onClickAddRecord() { viewAssigned = 'assigned'; table.ajax.reload(function() { initRowSelection(); + initHeaderTooltip(); }, false); }); $('#all-repo-records').on('click', function() { viewAssigned = 'all'; table.ajax.reload(function() { initRowSelection(); + initHeaderTooltip(); }, false); }); })(); diff --git a/app/assets/stylesheets/themes/scinote.scss b/app/assets/stylesheets/themes/scinote.scss index a2825f52f..f01dd4139 100644 --- a/app/assets/stylesheets/themes/scinote.scss +++ b/app/assets/stylesheets/themes/scinote.scss @@ -1576,6 +1576,11 @@ table.dataTable { visibility: visible; } +// don't display tooltip, it's handeled with js +.repository-table .modal-tooltip:hover .modal-tooltiptext { + visibility: hidden; +} + // Comments .comment-more { diff --git a/app/datatables/repository_datatable.rb b/app/datatables/repository_datatable.rb index 265ce6fdc..d0f42981c 100644 --- a/app/datatables/repository_datatable.rb +++ b/app/datatables/repository_datatable.rb @@ -118,9 +118,12 @@ class RepositoryDatatable < AjaxDatatablesRails::Base # Add custom columns record.repository_cells.each do |cell| row[@columns_mappings[cell.repository_column.id]] = - custom_auto_link(cell.value.data, - simple_format: true, - team: @team) + custom_auto_link( + display_tooltip(cell.value.data, + Constants::TABLE_FIELDS_TRUNCATION_LENGTH), + simple_format: true, + team: @team + ) end row end diff --git a/config/initializers/constants.rb b/config/initializers/constants.rb index e5ad7c680..9e7d8fec2 100644 --- a/config/initializers/constants.rb +++ b/config/initializers/constants.rb @@ -11,6 +11,8 @@ class Constants NAME_TRUNCATION_LENGTH = 25 # Max characters for short text fields, in dropdownList NAME_TRUNCATION_LENGTH_DROPDOWN = 20 + # Max characters for datatables fields + TABLE_FIELDS_TRUNCATION_LENGTH = 250 # Max characters for long text fields TEXT_MAX_LENGTH = 10000 # Max characters for rich text fields (in html format) From 94d74b8101698f79269432e98c95ab50a0465153 Mon Sep 17 00:00:00 2001 From: Oleksii Kriuchykhin Date: Fri, 16 Jun 2017 11:47:41 +0200 Subject: [PATCH 61/79] Make assigned column always visible in repositories [SCI-1346] --- .../repositories/repository_datatable.js | 9 +++------ app/datatables/repository_datatable.rb | 14 ++++++++++++-- app/views/repositories/_repository_table.html.erb | 6 +----- 3 files changed, 16 insertions(+), 13 deletions(-) diff --git a/app/assets/javascripts/repositories/repository_datatable.js b/app/assets/javascripts/repositories/repository_datatable.js index 28cf3c22d..a1e486a6a 100644 --- a/app/assets/javascripts/repositories/repository_datatable.js +++ b/app/assets/javascripts/repositories/repository_datatable.js @@ -42,6 +42,7 @@ function dataTableInit() { originalHeader = $('#repository-table thead').children().clone(); viewAssigned = 'assigned'; table = $('#repository-table').DataTable({ + order: [[2, 'desc']], dom: "R<'row'<'col-sm-9-custom toolbar'l><'col-sm-3-custom'f>>tpi", stateSave: true, processing: true, @@ -157,12 +158,8 @@ function dataTableInit() { // Reload correct column order and visibility (if you refresh page) // First two columns are fixed table.column(0).visible(true); - if ($('#assigned').text().length === 0) { - table.column(1).visible(false); - } else { - table.column(1).visible(true); - } - for (var i = 1; i < table.columns()[0].length; i++) { + table.column(1).visible(true); + for (var i = 2; i < table.columns()[0].length; i++) { var visibility = false; if (myData.columns[i]) { visibility = myData.columns[i].visible; diff --git a/app/datatables/repository_datatable.rb b/app/datatables/repository_datatable.rb index d6f4ae306..3a86ede29 100644 --- a/app/datatables/repository_datatable.rb +++ b/app/datatables/repository_datatable.rb @@ -102,7 +102,7 @@ class RepositoryDatatable < AjaxDatatablesRails::Base records.map do |record| row = { 'DT_RowId': record.id, - '1': @my_module ? assigned_row(record) : '', + '1': assigned_row(record), '2': escape_input(record.name), '3': I18n.l(record.created_at, format: :full), '4': escape_input(record.created_by.full_name), @@ -155,6 +155,11 @@ class RepositoryDatatable < AjaxDatatablesRails::Base ) .joins(:created_by) .where(repository: @repository) + else + @assigned_rows = repository_rows.joins( + 'INNER JOIN my_module_repository_rows ON + (repository_rows.id = my_module_repository_rows.repository_row_id)' + ) end # Make mappings of custom columns, so we have same id for every column @@ -189,16 +194,21 @@ class RepositoryDatatable < AjaxDatatablesRails::Base if params[:order].present? && params[:order].length == 1 if sort_column(params[:order].values[0]) == ASSIGNED_SORT_COL # If "assigned" column is sorted + direction = sort_null_direction(params[:order].values[0]) if @my_module # Depending on the sort, order nulls first or # nulls last on repository_cells association - direction = sort_null_direction(params[:order].values[0]) records.joins( "LEFT OUTER JOIN my_module_repository_rows ON (repository_rows.id = my_module_repository_rows.repository_row_id AND (my_module_repository_rows.my_module_id = #{@my_module.id} OR my_module_repository_rows.id IS NULL))" ).order("my_module_repository_rows.id NULLS #{direction}") + else + records.joins( + 'LEFT OUTER JOIN my_module_repository_rows ON + (repository_rows.id = my_module_repository_rows.repository_row_id)' + ).order("my_module_repository_rows.id NULLS #{direction}") end elsif sorting_by_custom_column # Check if have to filter records first diff --git a/app/views/repositories/_repository_table.html.erb b/app/views/repositories/_repository_table.html.erb index 8d841be46..3147dae51 100644 --- a/app/views/repositories/_repository_table.html.erb +++ b/app/views/repositories/_repository_table.html.erb @@ -15,11 +15,7 @@ - <% if @my_module %> - <%= t("repositories.table.assigned") %> - <% else %> - - <% end %> + <%= t("repositories.table.assigned") %> <%= t("repositories.table.row_name") %> <%= t("repositories.table.added_on") %> <%= t("repositories.table.added_by") %> From b6f146f177222c48f894030d667709492aa4bfda Mon Sep 17 00:00:00 2001 From: Mojca Lorber Date: Fri, 16 Jun 2017 11:52:26 +0200 Subject: [PATCH 62/79] fix cog position on repositories page --- app/assets/javascripts/repositories/edit.js | 8 ++++ app/assets/javascripts/repositories/index.js | 5 -- app/assets/stylesheets/repositories.scss | 6 +++ app/views/repositories/_repository.html.erb | 48 ++++++++++++++++++++ app/views/repositories/index.html.erb | 47 +------------------ config/initializers/assets.rb | 1 + 6 files changed, 65 insertions(+), 50 deletions(-) create mode 100644 app/assets/javascripts/repositories/edit.js diff --git a/app/assets/javascripts/repositories/edit.js b/app/assets/javascripts/repositories/edit.js new file mode 100644 index 000000000..1abca27ca --- /dev/null +++ b/app/assets/javascripts/repositories/edit.js @@ -0,0 +1,8 @@ +(function() { + 'use strict'; + + $('.delete-repo-option').initializeModal('#delete-repo-modal'); + $('.rename-repo-option').initializeModal('#rename-repo-modal'); + $('.copy-repo-option').initializeModal('#copy-repo-modal'); + +})(); diff --git a/app/assets/javascripts/repositories/index.js b/app/assets/javascripts/repositories/index.js index 03787aabd..12fc7f531 100644 --- a/app/assets/javascripts/repositories/index.js +++ b/app/assets/javascripts/repositories/index.js @@ -1,13 +1,8 @@ (function() { 'use strict'; - $('.delete-repo-option').initializeModal('#delete-repo-modal'); - $('.rename-repo-option').initializeModal('#rename-repo-modal'); - $('.copy-repo-option').initializeModal('#copy-repo-modal'); $('.create-repository').initializeModal('#create-repo-modal'); - loadRepositoryTab(); - })(); function loadRepositoryTab() { diff --git a/app/assets/stylesheets/repositories.scss b/app/assets/stylesheets/repositories.scss index 4e2399bc1..c8b884161 100644 --- a/app/assets/stylesheets/repositories.scss +++ b/app/assets/stylesheets/repositories.scss @@ -12,3 +12,9 @@ display: inline-block; } } + +.repository-cog { + display: inline-block; + float: right; + padding-left: 4px; +} diff --git a/app/views/repositories/_repository.html.erb b/app/views/repositories/_repository.html.erb index 97303e654..b79a4db68 100644 --- a/app/views/repositories/_repository.html.erb +++ b/app/views/repositories/_repository.html.erb @@ -21,6 +21,52 @@
    <% end %> +
    + +
    +