From bc112dd6af47db34859d89aa3925d12579b91c14 Mon Sep 17 00:00:00 2001 From: Anton Date: Tue, 23 Aug 2022 17:54:33 +0200 Subject: [PATCH] Add step duplication [SCI-7109] --- app/controllers/steps_controller.rb | 16 +++++++++- app/javascript/vue/protocol/container.vue | 1 + app/javascript/vue/protocol/step.vue | 9 ++++++ app/models/protocol.rb | 35 +------------------- app/models/step.rb | 39 +++++++++++++++++++++++ app/serializers/step_serializer.rb | 3 +- config/locales/en.yml | 1 + config/routes.rb | 1 + 8 files changed, 69 insertions(+), 36 deletions(-) diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb index a8fc4e33c..44558c1c6 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -5,7 +5,8 @@ class StepsController < ApplicationController include MarvinJsActions before_action :load_vars, only: %i(edit update destroy show toggle_step_state checklistitem_state update_view_state - move_up move_down update_asset_view_mode elements attachments upload_attachment) + move_up move_down update_asset_view_mode elements + attachments upload_attachment duplicate) before_action :load_vars_nested, only: %i(new create index reorder) before_action :convert_table_contents_to_utf8, only: %i(create update) @@ -231,6 +232,19 @@ class StepsController < ApplicationController end end + def duplicate + ActiveRecord::Base.transaction do + position = @step.position + @protocol.steps.where('position > ?', position).order(position: :desc).each do |step| + step.update(position: step.position + 1) + end + new_step = @step.duplicate(@protocol, current_user, position + 1) + render json: new_step, serializer: StepSerializer, user: current_user + end + rescue ActiveRecord::RecordInvalid + head :unprocessable_entity + end + def update_old respond_to do |format| old_description = @step.description diff --git a/app/javascript/vue/protocol/container.vue b/app/javascript/vue/protocol/container.vue index 1b8d9ad1b..9607fffc8 100644 --- a/app/javascript/vue/protocol/container.vue +++ b/app/javascript/vue/protocol/container.vue @@ -104,6 +104,7 @@ @step:delete="updateStepsPosition" @step:update="updateStep" @stepUpdated="refreshProtocolStatus" + @step:insert="updateStepsPosition" :reorderStepUrl="steps.length > 1 ? urls.reorder_steps_url : null" /> diff --git a/app/javascript/vue/protocol/step.vue b/app/javascript/vue/protocol/step.vue index bed532b32..b11637f9e 100644 --- a/app/javascript/vue/protocol/step.vue +++ b/app/javascript/vue/protocol/step.vue @@ -113,6 +113,10 @@ {{ i18n.t('protocols.steps.options_dropdown.rearrange') }} +
  • + + {{ i18n.t('protocols.steps.options_dropdown.duplicate') }} +
  • {{ i18n.t('protocols.steps.options_dropdown.delete') }} @@ -452,6 +456,11 @@ }) elements.push(element); this.reorderElements(elements); + }, + duplicateStep() { + $.post(this.urls.duplicate_step_url, (result) => { + this.$emit('step:insert', result.data); + }); } } } diff --git a/app/models/protocol.rb b/app/models/protocol.rb index a328cf142..4d3aaea2b 100644 --- a/app/models/protocol.rb +++ b/app/models/protocol.rb @@ -254,7 +254,6 @@ class Protocol < ApplicationRecord end def self.clone_contents(src, dest, current_user, clone_keywords, only_contents = false) - assets_to_clone = [] dest.update(description: src.description, name: src.name) unless only_contents src.clone_tinymce_assets(dest, dest.team) @@ -271,40 +270,8 @@ class Protocol < ApplicationRecord # Copy steps src.steps.each do |step| - step2 = Step.new( - name: step.name, - position: step.position, - completed: false, - user: current_user, - protocol: dest - ) - step2.save! - - # Copy texts - step.step_texts.each do |step_text| - step_text.duplicate(step2, step_text.step_orderable_element.position) - end - - # Copy checklists - step.checklists.asc.each do |checklist| - checklist.duplicate(step2, current_user, checklist.step_orderable_element.position) - end - - # "Shallow" Copy assets - step.assets.each do |asset| - asset2 = asset.dup - asset2.save! - step2.assets << asset2 - assets_to_clone << [asset.id, asset2.id] - end - - # Copy tables - step.tables.each do |table| - table.duplicate(step2, current_user, table.step_table.step_orderable_element.position) - end + step.duplicate(dest, current_user, step.position) end - # Call clone helper - Protocol.delay(queue: :assets).deep_clone_assets(assets_to_clone) end def in_repository_active? diff --git a/app/models/step.rb b/app/models/step.rb index a12b929fd..5f33f7b99 100644 --- a/app/models/step.rb +++ b/app/models/step.rb @@ -151,6 +151,45 @@ class Step < ApplicationRecord step_texts.order(created_at: :asc).first end + def duplicate(protocol, user, step_position = 0) + assets_to_clone = [] + + new_step = protocol.steps.new( + name: name, + position: step_position || protocol.steps.length, + completed: false, + user: user + ) + new_step.save! + + # Copy texts + step_texts.each do |step_text| + step_text.duplicate(new_step, step_text.step_orderable_element.position) + end + + # Copy checklists + checklists.asc.each do |checklist| + checklist.duplicate(new_step, user, checklist.step_orderable_element.position) + end + + # "Shallow" Copy assets + assets.each do |asset| + new_asset = asset.dup + new_asset.save! + new_step.assets << new_asset + assets_to_clone << [asset.id, new_asset.id] + end + + # Copy tables + tables.each do |table| + table.duplicate(new_step, user, table.step_table.step_orderable_element.position) + end + + # Call clone helper + Protocol.delay(queue: :assets).deep_clone_assets(assets_to_clone) + + new_step + end private def move_in_protocol(direction) diff --git a/app/serializers/step_serializer.rb b/app/serializers/step_serializer.rb index 17674da02..128454adf 100644 --- a/app/serializers/step_serializer.rb +++ b/app/serializers/step_serializer.rb @@ -89,7 +89,8 @@ class StepSerializer < ActiveModel::Serializer update_view_state_step_url: update_view_state_step_path(object), direct_upload_url: rails_direct_uploads_url, upload_attachment_url: upload_attachment_step_path(object), - reorder_elements_url: reorder_step_step_orderable_elements_path(step_id: object.id) + reorder_elements_url: reorder_step_step_orderable_elements_path(step_id: object.id), + duplicate_step_url: duplicate_step_path(object) }) end diff --git a/config/locales/en.yml b/config/locales/en.yml index 32cb83050..f8a14e4c2 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2558,6 +2558,7 @@ en: options_dropdown: title: 'Step options' rearrange: 'Rearrange content' + duplicate: 'Duplicate' delete: 'Delete' insert: button: 'Insert' diff --git a/config/routes.rb b/config/routes.rb index 31acbe05d..83954e89d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -482,6 +482,7 @@ Rails.application.routes.draw do put 'move_up' post 'update_view_state' post 'update_asset_view_mode' + post 'duplicate' end end