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 @@