From 1bac9aeb4ca6b8f42eb3a39c5e3265de3cb8562d Mon Sep 17 00:00:00 2001 From: Anton Date: Mon, 22 Aug 2022 14:02:19 +0200 Subject: [PATCH] Add duplication to components [SCI-7108] --- .../step_elements/checklists_controller.rb | 15 +++++- .../step_elements/tables_controller.rb | 17 ++++++- .../step_elements/texts_controller.rb | 15 +++++- app/javascript/vue/protocol/step.vue | 12 +++++ .../vue/protocol/step_elements/checklist.vue | 8 +++ .../vue/protocol/step_elements/table.vue | 8 +++ .../vue/protocol/step_elements/text.vue | 8 +++ app/models/checklist.rb | 25 +++++++++ app/models/protocol.rb | 51 ++----------------- app/models/step_text.rb | 16 ++++++ app/models/table.rb | 17 +++++++ app/serializers/checklist_serializer.rb | 1 + app/serializers/step_text_serializer.rb | 1 + app/serializers/table_serializer.rb | 1 + config/routes.rb | 15 +++++- 15 files changed, 157 insertions(+), 53 deletions(-) diff --git a/app/controllers/step_elements/checklists_controller.rb b/app/controllers/step_elements/checklists_controller.rb index 4ae72573d..3f818678e 100644 --- a/app/controllers/step_elements/checklists_controller.rb +++ b/app/controllers/step_elements/checklists_controller.rb @@ -2,7 +2,7 @@ module StepElements class ChecklistsController < BaseController - before_action :load_checklist, only: %i(update destroy) + before_action :load_checklist, only: %i(update destroy duplicate) def create checklist = @step.checklists.build( @@ -37,6 +37,19 @@ module StepElements end end + def duplicate + ActiveRecord::Base.transaction do + position = @checklist.step_orderable_element.position + @step.step_orderable_elements.where('position > ?', position).order(position: :desc).each do |element| + element.update(position: element.position + 1) + end + new_checklist = @checklist.duplicate(@step, current_user, position + 1) + render_step_orderable_element(new_checklist) + end + rescue ActiveRecord::RecordInvalid + head :unprocessable_entity + end + private def checklist_params diff --git a/app/controllers/step_elements/tables_controller.rb b/app/controllers/step_elements/tables_controller.rb index b58b0edd6..63023a850 100644 --- a/app/controllers/step_elements/tables_controller.rb +++ b/app/controllers/step_elements/tables_controller.rb @@ -2,7 +2,7 @@ module StepElements class TablesController < BaseController - before_action :load_table, only: %i(update destroy) + before_action :load_table, only: %i(update destroy duplicate) def create step_table = @step.step_tables.new(table: @@ -42,6 +42,21 @@ module StepElements end end + def duplicate + ActiveRecord::Base.transaction do + position = @table.step_table.step_orderable_element.position + @step.step_orderable_elements.where('position > ?', position).order(position: :desc).each do |element| + element.update(position: element.position + 1) + end + new_table = @table.duplicate(@step, current_user, position + 1) + render_step_orderable_element(new_table.step_table) + end + rescue ActiveRecord::RecordInvalid + head :unprocessable_entity + end + + private + def table_params params.permit(:name, :contents) end diff --git a/app/controllers/step_elements/texts_controller.rb b/app/controllers/step_elements/texts_controller.rb index 4e33d1178..53add8bcf 100644 --- a/app/controllers/step_elements/texts_controller.rb +++ b/app/controllers/step_elements/texts_controller.rb @@ -2,7 +2,7 @@ module StepElements class TextsController < BaseController - before_action :load_step_text, only: %i(update destroy) + before_action :load_step_text, only: %i(update destroy duplicate) def create step_text = @step.step_texts.build @@ -38,6 +38,19 @@ module StepElements end end + def duplicate + ActiveRecord::Base.transaction do + position = @step_text.step_orderable_element.position + @step.step_orderable_elements.where('position > ?', position).order(position: :desc).each do |element| + element.update(position: element.position + 1) + end + new_step_text = @step_text.duplicate(@step, position + 1) + render_step_orderable_element(new_step_text) + end + rescue ActiveRecord::RecordInvalid + head :unprocessable_entity + end + private def step_text_params diff --git a/app/javascript/vue/protocol/step.vue b/app/javascript/vue/protocol/step.vue index c130a4fef..bed532b32 100644 --- a/app/javascript/vue/protocol/step.vue +++ b/app/javascript/vue/protocol/step.vue @@ -135,6 +135,7 @@ @component:delete="deleteElement" @update="updateElement" @reorder="openReorderModal" + @component:insert="insertElement" /> { + if (s.attributes.position >= position) { + s.attributes.position += 1; + } + return s; + }) + elements.push(element); + this.reorderElements(elements); } } } diff --git a/app/javascript/vue/protocol/step_elements/checklist.vue b/app/javascript/vue/protocol/step_elements/checklist.vue index bc1df0d79..01a586c2d 100644 --- a/app/javascript/vue/protocol/step_elements/checklist.vue +++ b/app/javascript/vue/protocol/step_elements/checklist.vue @@ -25,6 +25,9 @@ + @@ -264,6 +267,11 @@ }; synchronousPost(0); + }, + duplicateElement() { + $.post(this.element.attributes.orderable.urls.duplicate_url, (result) => { + this.$emit('component:insert', result.data); + }); } } } diff --git a/app/javascript/vue/protocol/step_elements/table.vue b/app/javascript/vue/protocol/step_elements/table.vue index 3f642837a..0db622d5b 100644 --- a/app/javascript/vue/protocol/step_elements/table.vue +++ b/app/javascript/vue/protocol/step_elements/table.vue @@ -22,6 +22,9 @@ + @@ -171,6 +174,11 @@ readOnly: !this.editingTable, afterUnlisten: () => setTimeout(this.updateTable, 100) // delay makes cancel button work }); + }, + duplicateElement() { + $.post(this.element.attributes.orderable.urls.duplicate_url, (result) => { + this.$emit('component:insert', result.data); + }); } } } diff --git a/app/javascript/vue/protocol/step_elements/text.vue b/app/javascript/vue/protocol/step_elements/text.vue index dbac21282..92ae17f16 100644 --- a/app/javascript/vue/protocol/step_elements/text.vue +++ b/app/javascript/vue/protocol/step_elements/text.vue @@ -8,6 +8,9 @@ + @@ -87,6 +90,11 @@ this.element.attributes.orderable.name = data.data.attributes.name this.element.attributes.orderable.updated_at = data.data.attributes.updated_at this.$emit('update', this.element, true) + }, + duplicateElement() { + $.post(this.element.attributes.orderable.urls.duplicate_url, (result) => { + this.$emit('component:insert', result.data); + }); } } } diff --git a/app/models/checklist.rb b/app/models/checklist.rb index 43a396425..db8ec58a0 100644 --- a/app/models/checklist.rb +++ b/app/models/checklist.rb @@ -52,4 +52,29 @@ class Checklist < ApplicationRecord new_query.limit(Constants::SEARCH_LIMIT).offset((page - 1) * Constants::SEARCH_LIMIT) end end + + def duplicate(step, user, position = nil) + new_checklist = step.checklists.create!( + name: name, + created_by: user, + last_modified_by: user + ) + + checklist_items.each do |item| + new_checklist.checklist_items.create!( + text: item.text, + checked: false, + position: item.position, + created_by: user, + last_modified_by: user + ) + end + + step.step_orderable_elements.create!( + position: position || step.step_orderable_elements.length, + orderable: new_checklist + ) + + new_checklist + end end diff --git a/app/models/protocol.rb b/app/models/protocol.rb index b712fe9a3..a328cf142 100644 --- a/app/models/protocol.rb +++ b/app/models/protocol.rb @@ -282,45 +282,12 @@ class Protocol < ApplicationRecord # Copy texts step.step_texts.each do |step_text| - step_text2 = StepText.new( - text: step_text.text, - step: step2 - ) - step_text2.save! - - # Copy steps tinyMce assets - step_text.clone_tinymce_assets(step_text2, dest.team) - - step2.step_orderable_elements.create!( - position: step_text.step_orderable_element.position, - orderable: step_text2 - ) + step_text.duplicate(step2, step_text.step_orderable_element.position) end # Copy checklists step.checklists.asc.each do |checklist| - checklist2 = Checklist.create!( - name: checklist.name, - step: step2, - created_by: current_user, - last_modified_by: current_user - ) - - checklist.checklist_items.each do |item| - ChecklistItem.create!( - text: item.text, - checked: false, - checklist: checklist2, - position: item.position, - created_by: current_user, - last_modified_by: current_user - ) - end - - step2.step_orderable_elements.create!( - position: checklist.step_orderable_element.position, - orderable: checklist2 - ) + checklist.duplicate(step2, current_user, checklist.step_orderable_element.position) end # "Shallow" Copy assets @@ -333,19 +300,7 @@ class Protocol < ApplicationRecord # Copy tables step.tables.each do |table| - table2 = Table.create!( - name: table.name, - step: step2, - contents: table.contents.encode('UTF-8', 'UTF-8'), - team: dest.team, - created_by: current_user, - last_modified_by: current_user - ) - - step2.step_orderable_elements.create!( - position: table.step_table.step_orderable_element.position, - orderable: table2.step_table - ) + table.duplicate(step2, current_user, table.step_table.step_orderable_element.position) end end # Call clone helper diff --git a/app/models/step_text.rb b/app/models/step_text.rb index 69acc3888..4dd3ba9c7 100644 --- a/app/models/step_text.rb +++ b/app/models/step_text.rb @@ -17,4 +17,20 @@ class StepText < ApplicationRecord strip_tags(text.truncate(64)) end + + def duplicate(step, position = nil) + new_step_text = step.step_texts.create!( + text: text + ) + + # Copy steps tinyMce assets + clone_tinymce_assets(new_step_text, step.protocol.team) + + step.step_orderable_elements.create!( + position: position || step.step_orderable_elements.length, + orderable: new_step_text + ) + + new_step_text + end end diff --git a/app/models/table.rb b/app/models/table.rb index 130971ea5..39ff9255a 100644 --- a/app/models/table.rb +++ b/app/models/table.rb @@ -129,4 +129,21 @@ class Table < ApplicationRecord end end end + + def duplicate(step, user, position = nil) + new_table = step.tables.create!( + name: name, + contents: contents.encode('UTF-8', 'UTF-8'), + team: step.protocol.team, + created_by: user, + last_modified_by: user + ) + + step.step_orderable_elements.create!( + position: position || step.step_orderable_elements.length, + orderable: new_table.step_table + ) + + new_table + end end diff --git a/app/serializers/checklist_serializer.rb b/app/serializers/checklist_serializer.rb index 067d88a14..1b6d25379 100644 --- a/app/serializers/checklist_serializer.rb +++ b/app/serializers/checklist_serializer.rb @@ -30,6 +30,7 @@ class ChecklistSerializer < ActiveModel::Serializer return {} if object.destroyed? || !can_manage_step?(scope[:user] || @instance_options[:user], object.step) { + duplicate_url: duplicate_step_checklist_path(object.step, object), delete_url: step_checklist_path(object.step, object), update_url: step_checklist_path(object.step, object), reorder_url: reorder_step_checklist_checklist_items_path(object.step, object), diff --git a/app/serializers/step_text_serializer.rb b/app/serializers/step_text_serializer.rb index c0aa8eb4f..ee027ea9f 100644 --- a/app/serializers/step_text_serializer.rb +++ b/app/serializers/step_text_serializer.rb @@ -36,6 +36,7 @@ class StepTextSerializer < ActiveModel::Serializer return {} if object.destroyed? || !can_manage_step?(scope[:user] || @instance_options[:user], object.step) { + duplicate_url: duplicate_step_text_path(object.step, object), delete_url: step_text_path(object.step, object), update_url: step_text_path(object.step, object) } diff --git a/app/serializers/table_serializer.rb b/app/serializers/table_serializer.rb index 5c6511821..b43f4f5e4 100644 --- a/app/serializers/table_serializer.rb +++ b/app/serializers/table_serializer.rb @@ -22,6 +22,7 @@ class TableSerializer < ActiveModel::Serializer return {} unless can_manage_step?(scope[:user] || @instance_options[:user], object.step) { + duplicate_url: duplicate_step_table_path(object.step, object), delete_url: step_table_path(object.step, object), update_url: step_table_path(object.step, object) } diff --git a/config/routes.rb b/config/routes.rb index e7c808ff0..31acbe05d 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -453,9 +453,20 @@ Rails.application.routes.draw do resources :step_comments, path: '/comments', only: %i(create index update destroy) - resources :tables, controller: 'step_elements/tables', only: %i(create destroy update) - resources :texts, controller: 'step_elements/texts', only: %i(create destroy update) + resources :tables, controller: 'step_elements/tables', only: %i(create destroy update) do + member do + post :duplicate + end + end + resources :texts, controller: 'step_elements/texts', only: %i(create destroy update) do + member do + post :duplicate + end + end resources :checklists, controller: 'step_elements/checklists', only: %i(create destroy update) do + member do + post :duplicate + end resources :checklist_items, controller: 'step_elements/checklist_items', only: %i(create update destroy) do patch :toggle, on: :member post :reorder, on: :collection