From 6a827022f690da324d73fcecc682f6d31c21e0fc Mon Sep 17 00:00:00 2001 From: Anton Date: Fri, 29 Apr 2022 12:29:42 +0200 Subject: [PATCH] Add insert step element dropdown [SCI-6758] --- app/assets/stylesheets/steps/step.scss | 29 +++++++++ .../step_components/checklists_controller.rb | 17 ++++++ .../step_components/tables_controller.rb | 20 ++++++ .../step_components/texts_controller.rb | 15 +++++ .../step_orderable_elements_controller.rb | 35 +++++++++++ app/controllers/steps_controller.rb | 6 +- app/javascript/vue/protocol/container.vue | 6 +- app/javascript/vue/protocol/step.vue | 61 +++++++++++++++++-- .../protocol/step_components/checklist.vue | 11 ++++ .../vue/protocol/step_components/table.vue | 11 ++++ .../vue/protocol/step_components/text.vue | 11 ++++ app/models/step_orderable_element.rb | 2 +- app/models/step_text.rb | 1 - app/serializers/checklist_serializer.rb | 5 ++ .../step_orderable_element_serializer.rb | 16 +++++ app/serializers/step_serializer.rb | 6 +- app/serializers/step_table_serializer.rb | 5 ++ app/serializers/step_text_serializer.rb | 5 ++ config/locales/en.yml | 11 ++++ config/routes.rb | 5 ++ ...083335_generate_step_orderable_relation.rb | 33 ++++++++++ 21 files changed, 300 insertions(+), 11 deletions(-) create mode 100644 app/controllers/step_components/checklists_controller.rb create mode 100644 app/controllers/step_components/tables_controller.rb create mode 100644 app/controllers/step_components/texts_controller.rb create mode 100644 app/controllers/step_orderable_elements_controller.rb create mode 100644 app/javascript/vue/protocol/step_components/checklist.vue create mode 100644 app/javascript/vue/protocol/step_components/table.vue create mode 100644 app/javascript/vue/protocol/step_components/text.vue create mode 100644 app/serializers/checklist_serializer.rb create mode 100644 app/serializers/step_orderable_element_serializer.rb create mode 100644 app/serializers/step_table_serializer.rb create mode 100644 app/serializers/step_text_serializer.rb create mode 100644 db/migrate/20220429083335_generate_step_orderable_relation.rb diff --git a/app/assets/stylesheets/steps/step.scss b/app/assets/stylesheets/steps/step.scss index 4d6dca1b7..abab4534e 100644 --- a/app/assets/stylesheets/steps/step.scss +++ b/app/assets/stylesheets/steps/step.scss @@ -53,6 +53,35 @@ .step-actions-container { display: flex; justify-content: flex-end; + + .insert-button { + .caret { + margin-left: .5em; + } + } + + .insert-element-dropdown { + @include font-button; + padding: 0; + + li { + padding: .5em 1em; + + &.action { + cursor: pointer; + + &:hover { + background: $color-concrete; + } + } + + &.title { + @include font-small; + color: $color-alto; + text-transform: uppercase; + } + } + } } } } diff --git a/app/controllers/step_components/checklists_controller.rb b/app/controllers/step_components/checklists_controller.rb new file mode 100644 index 000000000..af5b1e7d3 --- /dev/null +++ b/app/controllers/step_components/checklists_controller.rb @@ -0,0 +1,17 @@ +# frozen_string_literal: true + +module StepComponents + class ChecklistsController < StepOrderableElementsController + private + + def create_step_element + @step.checklists.create!( + name: t('protocols.steps.checklist.default_name', position: @step.step_tables.length + 1) + ) + end + + def element_params + params.require(:checklist).permit(:name) + end + end +end diff --git a/app/controllers/step_components/tables_controller.rb b/app/controllers/step_components/tables_controller.rb new file mode 100644 index 000000000..630f3f9e4 --- /dev/null +++ b/app/controllers/step_components/tables_controller.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module StepComponents + class TablesController < StepOrderableElementsController + private + + def create_step_element + @step.step_tables.create!(table: + Table.create!( + name: t('protocols.steps.table.default_name', position: @step.step_tables.length + 1), + contents: '{"data":[["",""],["",""],["",""],["",""],["",""]]}', + created_by: current_user + )) + end + + def element_params + params.require(:table).permit(:name, :contents) + end + end +end diff --git a/app/controllers/step_components/texts_controller.rb b/app/controllers/step_components/texts_controller.rb new file mode 100644 index 000000000..7e04b94d9 --- /dev/null +++ b/app/controllers/step_components/texts_controller.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +module StepComponents + class TextsController < StepOrderableElementsController + private + + def create_step_element + @step.step_texts.create! + end + + def element_params + params.require(:step_text).permit(:text) + end + end +end diff --git a/app/controllers/step_orderable_elements_controller.rb b/app/controllers/step_orderable_elements_controller.rb new file mode 100644 index 000000000..2ee9a4a5a --- /dev/null +++ b/app/controllers/step_orderable_elements_controller.rb @@ -0,0 +1,35 @@ +# frozen_string_literal: true + +class StepOrderableElementsController < ApplicationController + before_action :load_vars_nested + before_action :check_manage_permissions, only: :create + + def create + ActiveRecord::Base.transaction do + element = @step.step_orderable_elements.create!( + position: @step.step_orderable_elements.length, + orderable: create_step_element + ) + render json: element, serializer: StepOrderableElementSerializer + rescue ActiveRecord::RecordInvalid + render json: {}, status: :unprocessable_entity + end + end + + private + + def load_vars_nested + @step = Step.find_by(id: params[:step_id]) + return render_404 unless @step + + @protocol = @step.protocol + end + + def check_view_permissions + render_403 unless can_read_protocol_in_module?(@protocol) || can_read_protocol_in_repository?(@protocol) + end + + def check_manage_permissions + render_403 unless can_manage_step?(@step) + end +end diff --git a/app/controllers/steps_controller.rb b/app/controllers/steps_controller.rb index 4d8fc2b93..439ca08e7 100644 --- a/app/controllers/steps_controller.rb +++ b/app/controllers/steps_controller.rb @@ -5,7 +5,7 @@ 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) + move_up move_down update_asset_view_mode elements) before_action :load_vars_nested, only: %i(new create index) before_action :convert_table_contents_to_utf8, only: %i(create update) @@ -19,6 +19,10 @@ class StepsController < ApplicationController render json: @protocol.steps.in_order, each_serializer: StepSerializer end + def elements + render json: @step.step_orderable_elements.order(:position), each_serializer: StepOrderableElementSerializer + end + def new @step = Step.new diff --git a/app/javascript/vue/protocol/container.vue b/app/javascript/vue/protocol/container.vue index dda2c5db2..5b606ca28 100644 --- a/app/javascript/vue/protocol/container.vue +++ b/app/javascript/vue/protocol/container.vue @@ -14,7 +14,7 @@
- + New step @@ -166,8 +166,8 @@ this.reorderSteps(unordered_steps) }, - updateStep(step) { - this.$set(this.steps, step.attributes.position, step) + updateStep(attributes) { + this.steps[attributes.position].attributes = attributes }, reorderSteps(steps) { this.steps = steps.sort((a, b) => a.attributes.position - b.attributes.position); diff --git a/app/javascript/vue/protocol/step.vue b/app/javascript/vue/protocol/step.vue index c3e95a758..ad9c91b34 100644 --- a/app/javascript/vue/protocol/step.vue +++ b/app/javascript/vue/protocol/step.vue @@ -23,19 +23,50 @@ />
+
- Components here +
\ No newline at end of file diff --git a/app/javascript/vue/protocol/step_components/table.vue b/app/javascript/vue/protocol/step_components/table.vue new file mode 100644 index 000000000..9c744d468 --- /dev/null +++ b/app/javascript/vue/protocol/step_components/table.vue @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/app/javascript/vue/protocol/step_components/text.vue b/app/javascript/vue/protocol/step_components/text.vue new file mode 100644 index 000000000..10825cc0c --- /dev/null +++ b/app/javascript/vue/protocol/step_components/text.vue @@ -0,0 +1,11 @@ + + + \ No newline at end of file diff --git a/app/models/step_orderable_element.rb b/app/models/step_orderable_element.rb index 01e282ebc..1f8081142 100644 --- a/app/models/step_orderable_element.rb +++ b/app/models/step_orderable_element.rb @@ -6,7 +6,7 @@ class StepOrderableElement < ApplicationRecord around_destroy :decrement_following_elements_positions - belongs_to :step, inverse_of: :step_oerderable_elements, touch: true + belongs_to :step, inverse_of: :step_orderable_elements, touch: true belongs_to :orderable, polymorphic: true, inverse_of: :step_orderable_elements private diff --git a/app/models/step_text.rb b/app/models/step_text.rb index e19805d9d..dff232a91 100644 --- a/app/models/step_text.rb +++ b/app/models/step_text.rb @@ -4,7 +4,6 @@ class StepText < ApplicationRecord include TinyMceImages auto_strip_attributes :text, nullify: false - validates :text, presence: true validates :text, length: { maximum: Constants::RICH_TEXT_MAX_LENGTH } belongs_to :step, inverse_of: :step_texts, touch: true diff --git a/app/serializers/checklist_serializer.rb b/app/serializers/checklist_serializer.rb new file mode 100644 index 000000000..e087236fd --- /dev/null +++ b/app/serializers/checklist_serializer.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class ChecklistSerializer < ActiveModel::Serializer + attributes :name +end diff --git a/app/serializers/step_orderable_element_serializer.rb b/app/serializers/step_orderable_element_serializer.rb new file mode 100644 index 000000000..b36b44b2f --- /dev/null +++ b/app/serializers/step_orderable_element_serializer.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +class StepOrderableElementSerializer < ActiveModel::Serializer + attributes :position, :element, :orderable_type + + def element + case object.orderable_type + when 'Checklist' + ChecklistSerializer + when 'StepTable' + StepTableSerializer + when 'StepText' + StepTextSerializer + end + end +end diff --git a/app/serializers/step_serializer.rb b/app/serializers/step_serializer.rb index 3fa75c0cf..3636dff1a 100644 --- a/app/serializers/step_serializer.rb +++ b/app/serializers/step_serializer.rb @@ -7,7 +7,11 @@ class StepSerializer < ActiveModel::Serializer { delete_url: step_path(object), state_url: toggle_step_state_step_path(object), - update_url: step_path(object) + update_url: step_path(object), + elements_url: elements_step_path(object), + create_table_url: step_tables_path(object), + create_text_url: step_texts_path(object), + create_checklist_url: step_checklists_path(object) } end end diff --git a/app/serializers/step_table_serializer.rb b/app/serializers/step_table_serializer.rb new file mode 100644 index 000000000..5aa4d8d70 --- /dev/null +++ b/app/serializers/step_table_serializer.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class StepTableSerializer < ActiveModel::Serializer + attributes :name +end diff --git a/app/serializers/step_text_serializer.rb b/app/serializers/step_text_serializer.rb new file mode 100644 index 000000000..d916477eb --- /dev/null +++ b/app/serializers/step_text_serializer.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +class StepTextSerializer < ActiveModel::Serializer + attributes :text +end diff --git a/config/locales/en.yml b/config/locales/en.yml index ebf198065..10dd0f723 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -2512,6 +2512,17 @@ en: comments: "Comments" empty_checklist: "No items" comment_title: "%{user} at %{time}:" + insert: + button: 'Insert' + title: 'insert content' + table: 'Add table' + text: 'Add text' + checklist: 'Add checklist' + table: + default_name: 'Table %{position}' + checklist: + default_name: 'Checklist %{position}' + options: up_arrow_title: "Move step up" down_arrow_title: "Move step down" diff --git a/config/routes.rb b/config/routes.rb index 274e479f3..0a0e2e642 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -448,7 +448,12 @@ Rails.application.routes.draw do resources :step_comments, path: '/comments', only: %i(create index update destroy) + + resources :tables, controller: 'step_components/tables', only: :create + resources :texts, controller: 'step_components/texts', only: :create + resources :checklists, controller: 'step_components/checklists', only: :create member do + get 'elements' post 'checklistitem_state' post 'toggle_step_state' put 'move_down' diff --git a/db/migrate/20220429083335_generate_step_orderable_relation.rb b/db/migrate/20220429083335_generate_step_orderable_relation.rb new file mode 100644 index 000000000..0c75d887b --- /dev/null +++ b/db/migrate/20220429083335_generate_step_orderable_relation.rb @@ -0,0 +1,33 @@ +# frozen_string_literal: true + +require File.expand_path('app/helpers/database_helper') +class GenerateStepOrderableRelation < ActiveRecord::Migration[6.1] + include DatabaseHelper + + def up + Step.find_in_batches(batch_size: 100) do |steps| + steps.each do |step| + position = 0 + orderable_elements = [] + step.step_texts.each do |text| + orderable_elements << step.step_orderable_elements.new(orderable: text, position: position) + position += 1 + end + step.step_tables.each do |table| + orderable_elements << step.step_orderable_elements.new(orderable: table, position: position) + position += 1 + end + step.checklists.each do |checklist| + orderable_elements << step.step_orderable_elements.new(orderable: checklist, position: position) + position += 1 + end + + StepOrderableElement.import(orderable_elements) + end + end + end + + def down + StepOrderableElement.destroy_all + end +end