diff --git a/app/assets/javascripts/dashboard/current_tasks.js b/app/assets/javascripts/dashboard/current_tasks.js index c539aa9f3..b1a36e6e5 100644 --- a/app/assets/javascripts/dashboard/current_tasks.js +++ b/app/assets/javascripts/dashboard/current_tasks.js @@ -117,7 +117,6 @@ var DasboardCurrentTasksWidget = (function() { } } appendTasksList(result, '.current-tasks-list-wrapper'); - PerfectSb().update_all(); InfiniteScroll.init('.current-tasks-list-wrapper', { url: $currentTasksList.data('tasksListUrl'), diff --git a/app/assets/javascripts/dashboard/recent_work.js b/app/assets/javascripts/dashboard/recent_work.js index 2e57b1b01..b25c36826 100644 --- a/app/assets/javascripts/dashboard/recent_work.js +++ b/app/assets/javascripts/dashboard/recent_work.js @@ -32,8 +32,6 @@ var DasboardRecentWorkWidget = (function() { } else { container.append($('#recent-work-no-results-template').html()); } - - PerfectSb().update_all(); }); } diff --git a/app/assets/javascripts/sitewide/dropdown_selector.js b/app/assets/javascripts/sitewide/dropdown_selector.js index c178e3245..d6c2d7d32 100644 --- a/app/assets/javascripts/sitewide/dropdown_selector.js +++ b/app/assets/javascripts/sitewide/dropdown_selector.js @@ -1,4 +1,4 @@ -/* global PerfectScrollbar activePSB PerfectSb I18n */ +/* global I18n */ /* eslint-disable no-unused-vars, no-use-before-define */ /* @@ -301,7 +301,6 @@ var dropdownSelector = (function() { function generateDropdown(selector, config = {}) { var selectElement = $(selector); var optionContainer; - var perfectScroll; var dropdownContainer; var toggleElement; @@ -410,10 +409,6 @@ var dropdownSelector = (function() { } }); - // Initialize scroll bar inside options container - perfectScroll = new PerfectScrollbar(dropdownContainer.find('.dropdown-container')[0]); - activePSB.push(perfectScroll); - // Select options container optionContainer = dropdownContainer.find('.dropdown-container'); @@ -450,7 +445,6 @@ var dropdownSelector = (function() { if (dropdownContainer.hasClass('open')) { // Each time we open option container we must scroll it dropdownContainer.find('.dropdown-container').scrollTop(0); - PerfectSb().update_all(); // on Open we load new data loadData(selectElement, dropdownContainer); @@ -652,9 +646,6 @@ var dropdownSelector = (function() { $(`
${I18n.t('dropdown_selector.nothing_found')}
`).appendTo(container.find('.dropdown-container')); } - // Update scrollbar - PerfectSb().update_all(); - // Check position of option dropdown refreshDropdownSelection(selector, container); @@ -865,7 +856,6 @@ var dropdownSelector = (function() { }].concat(optionsAjax); } loadData(selector, container, optionsAjax); - PerfectSb().update_all(); }); // For local options we convert options element from select to correct array } else if (selector.data('select-by-group')) { diff --git a/app/assets/stylesheets/dashboard/recent_work.scss b/app/assets/stylesheets/dashboard/recent_work.scss index d4424e4f7..aa0ffe90c 100644 --- a/app/assets/stylesheets/dashboard/recent_work.scss +++ b/app/assets/stylesheets/dashboard/recent_work.scss @@ -8,6 +8,7 @@ .recent-work-container { height: 100%; + overflow-y: auto; padding: 0 8px; position: relative; diff --git a/app/assets/stylesheets/global_activities.scss b/app/assets/stylesheets/global_activities.scss index e3c918061..b299b6897 100644 --- a/app/assets/stylesheets/global_activities.scss +++ b/app/assets/stylesheets/global_activities.scss @@ -155,6 +155,7 @@ .activities-container { height: 100%; + overflow-y: auto; padding-top: 10px; position: absolute; width: 100%; @@ -284,6 +285,7 @@ .filters-container { height: 100%; margin-bottom: 60px; + overflow-y: auto; padding: 15px 20px; position: absolute; } diff --git a/app/assets/stylesheets/shared/dropdown_selector.scss b/app/assets/stylesheets/shared/dropdown_selector.scss index a272ab601..2fe5b69c9 100644 --- a/app/assets/stylesheets/shared/dropdown_selector.scss +++ b/app/assets/stylesheets/shared/dropdown_selector.scss @@ -135,7 +135,7 @@ bottom: calc(100% - 30px); box-shadow: $flyout-shadow; display: none; - overflow: hidden; + overflow-y: auto; position: fixed; transition: .2s; transition-property: top, bottom, box-shadow; diff --git a/app/controllers/protocols_controller.rb b/app/controllers/protocols_controller.rb index 62453f642..3282a8e8e 100644 --- a/app/controllers/protocols_controller.rb +++ b/app/controllers/protocols_controller.rb @@ -40,6 +40,7 @@ class ProtocolsController < ApplicationController unlink unlink_modal delete_steps + list_published_protocol_templates ) before_action :check_manage_with_read_protocol_permissions, only: %i( @@ -798,6 +799,26 @@ class ProtocolsController < ApplicationController } end + def list_published_protocol_templates + protocols = Protocol.latest_available_versions_without_drafts(current_team) + .active + .with_granted_permissions(current_user, ProtocolPermissions::READ) + + if params[:query].present? + protocols = protocols.where_attributes_like( + ['protocols.name', Protocol::PREFIXED_ID_SQL], + params[:query] + ) + end + + protocols = protocols.order('LOWER(protocols.name) asc').page(params[:page]) + render json: { + paginated: true, + next_page: protocols.next_page, + data: protocols.map { |protocol_template| [protocol_template.id, protocol_template.name] } + } + end + def protocol_status_bar render json: { html: render_to_string(partial: 'my_modules/protocols/protocol_status_bar', formats: :html) diff --git a/app/controllers/repositories_controller.rb b/app/controllers/repositories_controller.rb index 92780b3d5..4baf20faa 100644 --- a/app/controllers/repositories_controller.rb +++ b/app/controllers/repositories_controller.rb @@ -151,17 +151,31 @@ class RepositoriesController < ApplicationController end def create - @repository = Repository.new( - team: current_team, - created_by: current_user - ) - @repository.assign_attributes(repository_params) + Repository.transaction do + @repository = Repository.new(team: current_team, created_by: current_user) + @repository.assign_attributes(repository_params) - if @repository.save + @repository.save! log_activity(:create_inventory) + + repository_template = current_team.repository_templates.find_by(id: repository_params[:repository_template_id]) + if repository_template.present? + repository_template.column_definitions&.each do |column_attributes| + service = RepositoryColumns::CreateColumnService + .call(user: current_user, repository: @repository, team: current_team, + column_type: column_attributes['column_type'], + params: column_attributes['params'].with_indifferent_access) + unless service.succeed? + render json: service.errors, status: :unprocessable_entity + raise ActiveRecord::Rollback + end + end + end render json: { message: t('repositories.index.modal_create.success_flash_html', name: @repository.name) } - else + rescue ActiveRecord::RecordInvalid => e + Rails.logger.error e.message render json: @repository.errors, status: :unprocessable_entity + raise ActiveRecord::Rollback end end @@ -548,7 +562,7 @@ class RepositoriesController < ApplicationController end def repository_params - params.require(:repository).permit(:name) + params.require(:repository).permit(:name, :repository_template_id) end def import_params diff --git a/app/controllers/repository_templates_controller.rb b/app/controllers/repository_templates_controller.rb new file mode 100644 index 000000000..21a12609c --- /dev/null +++ b/app/controllers/repository_templates_controller.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +class RepositoryTemplatesController < ApplicationController + before_action :check_read_permissions + before_action :load_repository_template, only: :list_repository_columns + + def index + repository_templates = current_team.repository_templates.order(:id) + render json: { + data: repository_templates.map { |repository_template| [repository_template.id, repository_template.name] } + } + end + + def list_repository_columns + render json: { + name: @repository_template.name, + columns: @repository_template.column_definitions&.map do |column| + [column.dig('params', 'name'), I18n.t("libraries.manange_modal_column.select.#{RepositoryColumn.data_types.key(column['column_type']).underscore}")] + end + } + end + + private + + def load_repository_template + @repository_template = current_team.repository_templates.find_by(id: params[:id]) + render_404 unless @repository_template + end + + def check_read_permissions + render_403 unless can_create_repositories?(current_team) + end +end diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb index fa3d8f386..b01ef291c 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -7,11 +7,11 @@ class StepsController < ApplicationController before_action :load_vars, only: %i(update destroy show toggle_step_state update_view_state update_asset_view_mode elements attachments upload_attachment duplicate) - before_action :load_vars_nested, only: %i(create index reorder) + before_action :load_vars_nested, only: %i(create index reorder list_protocol_steps add_protocol_steps) before_action :convert_table_contents_to_utf8, only: %i(create update) - before_action :check_protocol_manage_permissions, only: %i(reorder) - before_action :check_view_permissions, only: %i(show index attachments elements) + before_action :check_protocol_manage_permissions, only: %i(reorder add_protocol_steps) + before_action :check_view_permissions, only: %i(show index attachments elements list_protocol_steps) before_action :check_create_permissions, only: %i(create) before_action :check_manage_permissions, only: %i(update destroy update_view_state update_asset_view_mode upload_attachment) @@ -267,6 +267,49 @@ class StepsController < ApplicationController } end + def list_protocol_steps + steps = @protocol.steps + + if params[:query].present? + steps = steps.where_attributes_like( + ['steps.name'], + params[:query] + ) + end + + steps = steps.order(position: :asc).page(params[:page]) + render json: { + paginated: true, + next_page: steps.next_page, + data: steps.map { |step| [step.id, step.name] } + } + end + + def add_protocol_steps + Protocol.transaction do + selected_protocol = Protocol.find_by(id: params[:selected_protocol]) + render_403 unless selected_protocol.present? && can_read_protocol_in_repository?(selected_protocol) + + steps = selected_protocol.steps.where(id: params[:steps]).order(position: :asc).map do |step| + step.duplicate(@protocol, current_user, original_protocol: selected_protocol) + end + + message_items = { + protocol: selected_protocol.id, + count: steps.count + } + + if @protocol.in_module? + message_items[:my_module] = @protocol.my_module.id + log_activity(:task_steps_loaded_from_template, @my_module.experiment.project, message_items) + else + log_activity(:protocol_steps_loaded_from_template, nil, message_items) + end + + render json: steps, each_serializer: StepSerializer, user: current_user + end + end + private def load_vars diff --git a/app/datatables/load_from_repository_protocols_datatable.rb b/app/datatables/load_from_repository_protocols_datatable.rb index 12a3f38f5..3cafff7cb 100644 --- a/app/datatables/load_from_repository_protocols_datatable.rb +++ b/app/datatables/load_from_repository_protocols_datatable.rb @@ -81,18 +81,7 @@ class LoadFromRepositoryProtocolsDatatable < CustomDatatable end def get_raw_records_base - original_without_versions = @team.protocols - .left_outer_joins(:published_versions) - .where(protocol_type: Protocol.protocol_types[:in_repository_published_original]) - .where(published_versions: { id: nil }) - .select(:id) - - published_versions = @team.protocols - .where(protocol_type: Protocol.protocol_types[:in_repository_published_version]) - .order('parent_id, version_number DESC') - .select('DISTINCT ON (parent_id) id') - - Protocol.where("protocols.id IN ((#{original_without_versions.to_sql}) UNION (#{published_versions.to_sql}))") + Protocol.latest_available_versions_without_drafts(@team) .active .with_granted_permissions(@user, ProtocolPermissions::READ) end diff --git a/app/javascript/vue/protocol/container.vue b/app/javascript/vue/protocol/container.vue index f03d23e42..834691191 100644 --- a/app/javascript/vue/protocol/container.vue +++ b/app/javascript/vue/protocol/container.vue @@ -46,7 +46,9 @@