diff --git a/app/controllers/my_modules_controller.rb b/app/controllers/my_modules_controller.rb index c6838aa15..70807b723 100644 --- a/app/controllers/my_modules_controller.rb +++ b/app/controllers/my_modules_controller.rb @@ -384,10 +384,8 @@ class MyModulesController < ApplicationController @draw = params[:draw].to_i per_page = params[:length] == '-1' ? 100 : params[:length].to_i page = (params[:start].to_i / per_page) + 1 - datatable_service = RepositoryDatatableService.new(@repository, - params, - current_user, - @my_module) + datatable_service = RepositoryDatatableService.new(@repository, params, current_user, @my_module) + @all_rows_count = datatable_service.all_count @columns_mappings = datatable_service.mappings @repository_rows = datatable_service.repository_rows diff --git a/app/controllers/repository_rows_controller.rb b/app/controllers/repository_rows_controller.rb index cf0320f0b..b4f5da94d 100644 --- a/app/controllers/repository_rows_controller.rb +++ b/app/controllers/repository_rows_controller.rb @@ -147,7 +147,7 @@ class RepositoryRowsController < ApplicationController def copy_records duplicate_service = RepositoryActions::DuplicateRows.new( - current_user, @repository, params[:selected_rows] + current_user, @repository, copy_records_params ) duplicate_service.call render json: { @@ -223,6 +223,11 @@ class RepositoryRowsController < ApplicationController params.permit(selected_rows: []).to_h[:selected_rows] end + def copy_records_params + process_ids = params[:selected_rows].map(&:to_i).uniq + @repository.repository_rows.where(id: process_ids).pluck(:id) + end + def load_available_rows(query) @repository.repository_rows .includes(:repository_cells) diff --git a/app/models/repository_cell_values_checklist_item.rb b/app/models/repository_cell_values_checklist_item.rb deleted file mode 100644 index 167f5ee53..000000000 --- a/app/models/repository_cell_values_checklist_item.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -class RepositoryCellValuesChecklistItem < ApplicationRecord - belongs_to :repository_checklist_item - belongs_to :repository_checklist_value - - validates :repository_checklist_item, :repository_checklist_value, presence: true -end diff --git a/app/models/repository_checklist_item.rb b/app/models/repository_checklist_item.rb index d3d5947b8..0021ea8af 100644 --- a/app/models/repository_checklist_item.rb +++ b/app/models/repository_checklist_item.rb @@ -11,6 +11,6 @@ class RepositoryChecklistItem < ApplicationRecord inverse_of: :created_repository_checklist_types belongs_to :last_modified_by, foreign_key: 'last_modified_by_id', class_name: 'User', inverse_of: :modified_repository_checklist_types - has_many :repository_cell_values_checklist_items, dependent: :destroy - has_many :repository_checklist_values, through: :repository_cell_values_checklist_items + has_many :repository_checklist_items_values, dependent: :destroy + has_many :repository_checklist_values, through: :repository_checklist_items_values end diff --git a/app/models/repository_checklist_items_value.rb b/app/models/repository_checklist_items_value.rb new file mode 100644 index 000000000..bcc9da3fd --- /dev/null +++ b/app/models/repository_checklist_items_value.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class RepositoryChecklistItemsValue < ApplicationRecord + belongs_to :repository_checklist_item + belongs_to :repository_checklist_value + + validates :repository_checklist_item, :repository_checklist_value, presence: true + + after_destroy :destroy_empty_value + + def destroy_empty_value + repository_checklist_value.destroy! if repository_checklist_value.repository_checklist_items_values.blank? + end +end diff --git a/app/models/repository_checklist_value.rb b/app/models/repository_checklist_value.rb index 81535791e..fd75a4824 100644 --- a/app/models/repository_checklist_value.rb +++ b/app/models/repository_checklist_value.rb @@ -6,11 +6,12 @@ class RepositoryChecklistValue < ApplicationRecord belongs_to :last_modified_by, foreign_key: 'last_modified_by_id', class_name: 'User', inverse_of: :modified_repository_checklist_values has_one :repository_cell, as: :value, dependent: :destroy, inverse_of: :value - has_many :repository_cell_values_checklist_items, dependent: :destroy - has_many :repository_checklist_items, through: :repository_cell_values_checklist_items + has_many :repository_checklist_items_values, dependent: :destroy + has_many :repository_checklist_items, -> { order('data ASC') }, through: :repository_checklist_items_values accepts_nested_attributes_for :repository_cell validates :repository_cell, presence: true + validates :repository_checklist_items, presence: true SORTABLE_COLUMN_NAME = 'repository_checklist_items.data' SORTABLE_VALUE_INCLUDE = { repository_checklist_value: :repository_checklist_items }.freeze @@ -24,7 +25,7 @@ class RepositoryChecklistValue < ApplicationRecord end def data - repository_checklist_items.map { |i| { value: i.id, label: i.data } }.sort_by { |item| item[:label] } + repository_checklist_items.map { |i| { value: i.id, label: i.data } } end def data_changed?(new_data) @@ -32,10 +33,10 @@ class RepositoryChecklistValue < ApplicationRecord end def update_data!(new_data, user) - repository_cell_values_checklist_items.destroy_all + repository_checklist_items_values.destroy_all repository_cell.repository_column .repository_checklist_items.where(id: JSON.parse(new_data)).find_each do |item| - repository_cell_values_checklist_items.create!(repository_checklist_item: item) + repository_checklist_items_values.create!(repository_checklist_item: item) end self.last_modified_by = user save! @@ -46,7 +47,7 @@ class RepositoryChecklistValue < ApplicationRecord value.repository_cell .repository_column .repository_checklist_items.where(id: JSON.parse(payload)).find_each do |item| - value.repository_cell_values_checklist_items.new(repository_checklist_item: item) + value.repository_checklist_items_values.new(repository_checklist_item: item) end value end diff --git a/app/services/model_exporters/team_exporter.rb b/app/services/model_exporters/team_exporter.rb index fbd08a334..52523236d 100644 --- a/app/services/model_exporters/team_exporter.rb +++ b/app/services/model_exporters/team_exporter.rb @@ -174,7 +174,7 @@ module ModelExporters def get_cell_value_checklist(cell) return unless cell.value_type == 'RepositoryChecklistValue' - cell.value.repository_cell_values_checklist_items + cell.value.repository_checklist_items_values end end end diff --git a/app/services/repository_actions/duplicate_cell.rb b/app/services/repository_actions/duplicate_cell.rb index 949b111c9..95b0183a9 100644 --- a/app/services/repository_actions/duplicate_cell.rb +++ b/app/services/repository_actions/duplicate_cell.rb @@ -2,70 +2,34 @@ module RepositoryActions class DuplicateCell - def initialize(cell, new_row, user, team) + def initialize(cell, new_row, user) @cell = cell @new_row = new_row @user = user - @team = team end def call - __send__("duplicate_#{@cell.value_type.split('::').last.underscore}") + new_value = @cell.value.dup + new_value.repository_cell = RepositoryCell.new(repository_row: @new_row, + repository_column: @cell.repository_column) + new_value.created_by = @user + new_value.last_modified_by = @user + + if respond_to?("#{@cell.value_type.split('::').last.underscore}_extra_attributes", true) + __send__("#{@cell.value_type.split('::').last.underscore}_extra_attributes", new_value) + end + new_value.save! end private - def duplicate_repository_list_value - old_value = @cell.value - RepositoryListValue.create( - old_value.attributes.merge( - id: nil, created_by: @user, last_modified_by: @user, - repository_cell_attributes: { - repository_row: @new_row, - repository_column: @cell.repository_column - } - ) - ) + def repository_asset_value_extra_attributes(value) + new_asset = @cell.value.asset.duplicate + value.asset = new_asset end - def duplicate_repository_text_value - old_value = @cell.value - RepositoryTextValue.create( - old_value.attributes.merge( - id: nil, created_by: @user, last_modified_by: @user, - repository_cell_attributes: { - repository_row: @new_row, - repository_column: @cell.repository_column - } - ) - ) - end - - def duplicate_repository_asset_value - old_value = @cell.value - new_asset = old_value.asset.duplicate - RepositoryAssetValue.create( - old_value.attributes.merge( - id: nil, asset: new_asset, created_by: @user, last_modified_by: @user, - repository_cell_attributes: { - repository_row: @new_row, - repository_column: @cell.repository_column - } - ) - ) - end - - def duplicate_repository_date_value - old_value = @cell.value - RepositoryDateTimeValue.create( - old_value.attributes.merge( - id: nil, created_by: @user, last_modified_by: @user, - repository_cell_attributes: { - repository_row: @new_row, - repository_column: @cell.repository_column - } - ) - ) + def repository_checklist_value_extra_attributes(value) + value.repository_checklist_items = @cell.value.repository_checklist_items end end end diff --git a/app/services/repository_actions/duplicate_rows.rb b/app/services/repository_actions/duplicate_rows.rb index 0bd28ee38..359574f7b 100644 --- a/app/services/repository_actions/duplicate_rows.rb +++ b/app/services/repository_actions/duplicate_rows.rb @@ -6,7 +6,7 @@ module RepositoryActions def initialize(user, repository, rows_ids = []) @user = user @repository = repository - @rows_to_duplicate = sanitize_rows_to_duplicate(rows_ids) + @rows_to_duplicate = rows_ids @number_of_duplicated_items = 0 end @@ -18,23 +18,21 @@ module RepositoryActions private - def sanitize_rows_to_duplicate(rows_ids) - process_ids = rows_ids.map(&:to_i).uniq - @repository.repository_rows.where(id: process_ids).pluck(:id) - end - def duplicate_row(id) - row = RepositoryRow.find_by_id(id) - new_row = RepositoryRow.new( - row.attributes.merge(new_row_attributes(row.name, @user.id)) - ) + RepositoryRow.transaction do + row = @repository.repository_rows.find_by(id: id) + return unless row + + new_row = RepositoryRow.create!( + row.attributes.merge(new_row_attributes(row.name, @user.id)) + ) - if new_row.save - @number_of_duplicated_items += 1 row.repository_cells.each do |cell| - duplicate_repository_cell(cell, new_row) + RepositoryActions::DuplicateCell.new(cell, new_row, @user).call end + @number_of_duplicated_items += 1 + Activities::CreateActivityService .call(activity_type: :copy_inventory_item, owner: @user, @@ -52,11 +50,5 @@ module RepositoryActions created_at: timestamp, updated_at: timestamp } end - - def duplicate_repository_cell(cell, new_row) - RepositoryActions::DuplicateCell.new( - cell, new_row, @user, @repository.team - ).call - end end end diff --git a/app/services/repository_datatable_service.rb b/app/services/repository_datatable_service.rb index 43f94d378..6692a4d29 100644 --- a/app/services/repository_datatable_service.rb +++ b/app/services/repository_datatable_service.rb @@ -44,18 +44,13 @@ class RepositoryDatatableService 'AND "my_module_repository_rows"."my_module_id" = ' + @my_module.id.to_s ) end - repository_rows = repository_rows - .select('repository_rows.*') - .select('COUNT(my_module_repository_rows.id) AS "assigned_my_modules_count"') - .group('repository_rows.id') + repository_rows = repository_rows.select('COUNT(my_module_repository_rows.id) AS "assigned_my_modules_count"') else repository_rows = repository_rows .left_outer_joins(my_module_repository_rows: { my_module: :experiment }) - .select('repository_rows.*') .select('COUNT(my_module_repository_rows.id) AS "assigned_my_modules_count"') .select('COUNT(DISTINCT my_modules.experiment_id) AS "assigned_experiments_count"') .select('COUNT(DISTINCT experiments.project_id) AS "assigned_projects_count"') - .group('repository_rows.id') end @repository_rows = sort_rows(order_obj, repository_rows) @@ -91,6 +86,9 @@ class RepositoryDatatableService end repository_rows.left_outer_joins(:created_by) + .select('repository_rows.*') + .select('COUNT("repository_rows"."id") OVER() AS filtered_count') + .group('repository_rows.id') end def build_conditions(params) diff --git a/app/services/team_importer.rb b/app/services/team_importer.rb index 1f52256cb..e62dea72c 100644 --- a/app/services/team_importer.rb +++ b/app/services/team_importer.rb @@ -981,7 +981,7 @@ class TeamImporter if repository_cell.value_type == 'RepositoryChecklistValue' value_json['repository_value_checklist'].each do |item| item_id = find_checklist_item_id(item['repository_checklist_item_id']).to_i - RepositoryCellValuesChecklistItem.create!(repository_checklist_value: repository_value, + RepositoryChecklistItemsValue.create!(repository_checklist_value: repository_value, repository_checklist_item_id: item_id) end end diff --git a/app/views/repository_rows/index.json.jbuilder b/app/views/repository_rows/index.json.jbuilder index 962ea36c7..427135853 100644 --- a/app/views/repository_rows/index.json.jbuilder +++ b/app/views/repository_rows/index.json.jbuilder @@ -7,5 +7,5 @@ json.data do @columns_mappings, @repository.team) end -json.recordsFiltered @repository_rows.length +json.recordsFiltered @repository_rows.first ? @repository_rows.first.filtered_count : 0 json.recordsTotal @all_rows_count diff --git a/config/initializers/extends.rb b/config/initializers/extends.rb index 98436813e..8b81b6743 100644 --- a/config/initializers/extends.rb +++ b/config/initializers/extends.rb @@ -65,7 +65,7 @@ class Extends 'repository_list_items.data' => { repository_list_value: :repository_list_item }, 'repository_checklist_items.data' => { repository_checklist_value: - { repository_cell_values_checklist_items: :repository_checklist_item } }, + { repository_checklist_items_values: :repository_checklist_item } }, 'repository_status_items.status' => { repository_status_value: :repository_status_item }, 'active_storage_blobs.filename' => diff --git a/db/migrate/20191205133522_create_repository_checklists.rb b/db/migrate/20191205133522_create_repository_checklists.rb index c62951065..4d0619c62 100644 --- a/db/migrate/20191205133522_create_repository_checklists.rb +++ b/db/migrate/20191205133522_create_repository_checklists.rb @@ -19,11 +19,9 @@ class CreateRepositoryChecklists < ActiveRecord::Migration[6.0] t.timestamps end - create_table :repository_cell_values_checklist_items do |t| - t.references :repository_checklist_item, null: false, foreign_key: true, - index: { name: :repository_cell_values_checklist_item_id } - t.references :repository_checklist_value, null: false, foreign_key: true, - index: { name: :repository_cell_values_checklist_value_id } + create_table :repository_checklist_items_values do |t| + t.belongs_to :repository_checklist_value, index: { name: 'index_on_repository_checklist_value_id' } + t.belongs_to :repository_checklist_item, index: { name: 'index_on_repository_checklist_item_id' } t.timestamps end end diff --git a/db/structure.sql b/db/structure.sql index 8f1fe481c..254b35498 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -1133,38 +1133,6 @@ CREATE SEQUENCE public.repository_asset_values_id_seq ALTER SEQUENCE public.repository_asset_values_id_seq OWNED BY public.repository_asset_values.id; --- --- Name: repository_cell_values_checklist_items; Type: TABLE; Schema: public; Owner: - --- - -CREATE TABLE public.repository_cell_values_checklist_items ( - id bigint NOT NULL, - repository_checklist_item_id bigint NOT NULL, - repository_checklist_value_id bigint NOT NULL, - created_at timestamp(6) without time zone NOT NULL, - updated_at timestamp(6) without time zone NOT NULL -); - - --- --- Name: repository_cell_values_checklist_items_id_seq; Type: SEQUENCE; Schema: public; Owner: - --- - -CREATE SEQUENCE public.repository_cell_values_checklist_items_id_seq - START WITH 1 - INCREMENT BY 1 - NO MINVALUE - NO MAXVALUE - CACHE 1; - - --- --- Name: repository_cell_values_checklist_items_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - --- - -ALTER SEQUENCE public.repository_cell_values_checklist_items_id_seq OWNED BY public.repository_cell_values_checklist_items.id; - - -- -- Name: repository_cells; Type: TABLE; Schema: public; Owner: - -- @@ -1234,6 +1202,38 @@ CREATE SEQUENCE public.repository_checklist_items_id_seq ALTER SEQUENCE public.repository_checklist_items_id_seq OWNED BY public.repository_checklist_items.id; +-- +-- Name: repository_checklist_items_values; Type: TABLE; Schema: public; Owner: - +-- + +CREATE TABLE public.repository_checklist_items_values ( + id bigint NOT NULL, + repository_checklist_value_id bigint, + repository_checklist_item_id bigint, + created_at timestamp(6) without time zone NOT NULL, + updated_at timestamp(6) without time zone NOT NULL +); + + +-- +-- Name: repository_checklist_items_values_id_seq; Type: SEQUENCE; Schema: public; Owner: - +-- + +CREATE SEQUENCE public.repository_checklist_items_values_id_seq + START WITH 1 + INCREMENT BY 1 + NO MINVALUE + NO MAXVALUE + CACHE 1; + + +-- +-- Name: repository_checklist_items_values_id_seq; Type: SEQUENCE OWNED BY; Schema: public; Owner: - +-- + +ALTER SEQUENCE public.repository_checklist_items_values_id_seq OWNED BY public.repository_checklist_items_values.id; + + -- -- Name: repository_checklist_values; Type: TABLE; Schema: public; Owner: - -- @@ -2970,13 +2970,6 @@ ALTER TABLE ONLY public.repositories ALTER COLUMN id SET DEFAULT nextval('public ALTER TABLE ONLY public.repository_asset_values ALTER COLUMN id SET DEFAULT nextval('public.repository_asset_values_id_seq'::regclass); --- --- Name: repository_cell_values_checklist_items id; Type: DEFAULT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.repository_cell_values_checklist_items ALTER COLUMN id SET DEFAULT nextval('public.repository_cell_values_checklist_items_id_seq'::regclass); - - -- -- Name: repository_cells id; Type: DEFAULT; Schema: public; Owner: - -- @@ -2991,6 +2984,13 @@ ALTER TABLE ONLY public.repository_cells ALTER COLUMN id SET DEFAULT nextval('pu ALTER TABLE ONLY public.repository_checklist_items ALTER COLUMN id SET DEFAULT nextval('public.repository_checklist_items_id_seq'::regclass); +-- +-- Name: repository_checklist_items_values id; Type: DEFAULT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.repository_checklist_items_values ALTER COLUMN id SET DEFAULT nextval('public.repository_checklist_items_values_id_seq'::regclass); + + -- -- Name: repository_checklist_values id; Type: DEFAULT; Schema: public; Owner: - -- @@ -3545,14 +3545,6 @@ ALTER TABLE ONLY public.repository_asset_values ADD CONSTRAINT repository_asset_values_pkey PRIMARY KEY (id); --- --- Name: repository_cell_values_checklist_items repository_cell_values_checklist_items_pkey; Type: CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.repository_cell_values_checklist_items - ADD CONSTRAINT repository_cell_values_checklist_items_pkey PRIMARY KEY (id); - - -- -- Name: repository_cells repository_cells_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -3569,6 +3561,14 @@ ALTER TABLE ONLY public.repository_checklist_items ADD CONSTRAINT repository_checklist_items_pkey PRIMARY KEY (id); +-- +-- Name: repository_checklist_items_values repository_checklist_items_values_pkey; Type: CONSTRAINT; Schema: public; Owner: - +-- + +ALTER TABLE ONLY public.repository_checklist_items_values + ADD CONSTRAINT repository_checklist_items_values_pkey PRIMARY KEY (id); + + -- -- Name: repository_checklist_values repository_checklist_values_pkey; Type: CONSTRAINT; Schema: public; Owner: - -- @@ -4421,6 +4421,20 @@ CREATE UNIQUE INDEX index_oauth_applications_on_uid ON public.oauth_applications CREATE INDEX index_on_rep_status_type_id ON public.repository_status_values USING btree (repository_status_item_id); +-- +-- Name: index_on_repository_checklist_item_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_on_repository_checklist_item_id ON public.repository_checklist_items_values USING btree (repository_checklist_item_id); + + +-- +-- Name: index_on_repository_checklist_value_id; Type: INDEX; Schema: public; Owner: - +-- + +CREATE INDEX index_on_repository_checklist_value_id ON public.repository_checklist_items_values USING btree (repository_checklist_value_id); + + -- -- Name: index_projects_on_archived_by_id; Type: INDEX; Schema: public; Owner: - -- @@ -5695,20 +5709,6 @@ CREATE INDEX index_wopi_actions_on_extension_and_action ON public.wopi_actions U CREATE INDEX index_zip_exports_on_user_id ON public.zip_exports USING btree (user_id); --- --- Name: repository_cell_values_checklist_item_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX repository_cell_values_checklist_item_id ON public.repository_cell_values_checklist_items USING btree (repository_checklist_item_id); - - --- --- Name: repository_cell_values_checklist_value_id; Type: INDEX; Schema: public; Owner: - --- - -CREATE INDEX repository_cell_values_checklist_value_id ON public.repository_cell_values_checklist_items USING btree (repository_checklist_value_id); - - -- -- Name: repository_status_items fk_rails_00642f1707; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -6901,14 +6901,6 @@ ALTER TABLE ONLY public.oauth_access_tokens ADD CONSTRAINT fk_rails_ee63f25419 FOREIGN KEY (resource_owner_id) REFERENCES public.users(id); --- --- Name: repository_cell_values_checklist_items fk_rails_efd3251ebf; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.repository_cell_values_checklist_items - ADD CONSTRAINT fk_rails_efd3251ebf FOREIGN KEY (repository_checklist_value_id) REFERENCES public.repository_checklist_values(id); - - -- -- Name: repository_date_time_range_values fk_rails_efe428fafe; Type: FK CONSTRAINT; Schema: public; Owner: - -- @@ -6933,14 +6925,6 @@ ALTER TABLE ONLY public.report_elements ADD CONSTRAINT fk_rails_f36eac136b FOREIGN KEY (experiment_id) REFERENCES public.experiments(id); --- --- Name: repository_cell_values_checklist_items fk_rails_f5260bda13; Type: FK CONSTRAINT; Schema: public; Owner: - --- - -ALTER TABLE ONLY public.repository_cell_values_checklist_items - ADD CONSTRAINT fk_rails_f5260bda13 FOREIGN KEY (repository_checklist_item_id) REFERENCES public.repository_checklist_items(id); - - -- -- Name: user_projects fk_rails_f58e9073ce; Type: FK CONSTRAINT; Schema: public; Owner: - -- diff --git a/spec/models/repository_checklist_value_spec.rb b/spec/models/repository_checklist_value_spec.rb index 0e823b61a..05c26b359 100644 --- a/spec/models/repository_checklist_value_spec.rb +++ b/spec/models/repository_checklist_value_spec.rb @@ -3,9 +3,11 @@ require 'rails_helper' RSpec.describe RepositoryChecklistValue, type: :model do + let(:repository_checklist_item) { build :repository_checklist_item } let(:repository_checklist_value) { build :repository_checklist_value } it 'is valid' do + repository_checklist_value.repository_checklist_items << repository_checklist_item expect(repository_checklist_value).to be_valid end