mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-12-26 09:42:46 +08:00
Refactor checklist column data structure
This commit is contained in:
parent
2da7eeaedd
commit
dc91893d7e
11 changed files with 128 additions and 105 deletions
8
app/models/repository_cell_values_checklist_item.rb
Normal file
8
app/models/repository_cell_values_checklist_item.rb
Normal file
|
@ -0,0 +1,8 @@
|
|||
# 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
|
|
@ -11,4 +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
|
||||
end
|
||||
|
|
|
@ -6,9 +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
|
||||
|
||||
accepts_nested_attributes_for :repository_cell
|
||||
|
||||
SORTABLE_COLUMN_NAME = 'repository_checklistitems'
|
||||
SORTABLE_COLUMN_NAME = 'repository_checklist_items.data'
|
||||
SORTABLE_VALUE_INCLUDE = { repository_checklist_value: :repository_checklist_items }.freeze
|
||||
|
||||
def formatted
|
||||
|
@ -16,24 +19,30 @@ class RepositoryChecklistValue < ApplicationRecord
|
|||
end
|
||||
|
||||
def data
|
||||
repository_cell.repository_column.repository_checklist_items
|
||||
.where(id: repository_checklist_items).select(:id, :data)
|
||||
.map { |i| { value: i.id, label: i.data } }
|
||||
repository_checklist_items.order(created_at: :asc).map { |i| { value: i.id, label: i.data } }
|
||||
end
|
||||
|
||||
def data_changed?(new_data)
|
||||
JSON.parse(new_data) != repository_checklist_items
|
||||
JSON.parse(new_data) != repository_checklist_items.pluck(:id)
|
||||
end
|
||||
|
||||
def update_data!(new_data, user)
|
||||
self.repository_checklist_items = JSON.parse(new_data)
|
||||
repository_cell_values_checklist_items.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)
|
||||
end
|
||||
self.last_modified_by = user
|
||||
save!
|
||||
end
|
||||
|
||||
def self.new_with_payload(payload, attributes)
|
||||
value = new(attributes)
|
||||
value.repository_checklist_items = JSON.parse(payload)
|
||||
value = create(attributes)
|
||||
value.repository_cell
|
||||
.repository_column
|
||||
.repository_checklist_items.where(id: JSON.parse(payload)).find_each do |item|
|
||||
value.repository_cell_values_checklist_items.create(repository_checklist_item: item)
|
||||
end
|
||||
value
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
class RepositoryDatatableService
|
||||
# frozen_string_literal: true
|
||||
|
||||
class RepositoryDatatableService
|
||||
attr_reader :repository_rows, :assigned_rows, :mappings
|
||||
|
||||
def initialize(repository, params, user, my_module = nil)
|
||||
|
@ -100,6 +101,7 @@ class RepositoryDatatableService
|
|||
|
||||
if sortable_columns[column_id - 1] == 'assigned'
|
||||
return records if @my_module && @params[:assigned] == 'assigned'
|
||||
|
||||
if @my_module
|
||||
# Depending on the sort, order nulls first or
|
||||
# nulls last on repository_cells association
|
||||
|
@ -119,14 +121,14 @@ class RepositoryDatatableService
|
|||
end
|
||||
elsif sortable_columns[column_id - 1] == 'repository_cell.value'
|
||||
id = @mappings.key(column_id.to_s)
|
||||
sorting_column = RepositoryColumn.find_by_id(id)
|
||||
sorting_column = RepositoryColumn.find_by(id: id)
|
||||
return records unless sorting_column
|
||||
|
||||
sorting_data_type = sorting_column.data_type.constantize
|
||||
|
||||
cells = RepositoryCell.joins(sorting_data_type::SORTABLE_VALUE_INCLUDE)
|
||||
.where('repository_cells.repository_column_id': sorting_column.id)
|
||||
.select("repository_cells.repository_row_id,
|
||||
.select("DISTINCT ON (repository_cells.repository_row_id) repository_row_id,
|
||||
#{sorting_data_type::SORTABLE_COLUMN_NAME} AS value")
|
||||
|
||||
records.joins("LEFT OUTER JOIN (#{cells.to_sql}) AS values ON values.repository_row_id = repository_rows.id")
|
||||
|
|
|
@ -63,11 +63,13 @@ class Extends
|
|||
# are only supported
|
||||
REPOSITORY_EXTRA_SEARCH_ATTR = ['repository_text_values.data',
|
||||
'repository_list_items.data',
|
||||
'repository_checklist_items.data',
|
||||
'active_storage_blobs.filename']
|
||||
|
||||
# Array of includes used in search query for repository rows
|
||||
REPOSITORY_SEARCH_INCLUDES = [:repository_text_value,
|
||||
repository_list_value: :repository_list_item,
|
||||
repository_checklist_value: :repository_checklist_items,
|
||||
repository_asset_value: { asset: { file_attachment: :blob } }]
|
||||
|
||||
# List of implemented core API versions
|
||||
|
|
|
@ -5,7 +5,6 @@ class CreateRepositoryChecklistValues < ActiveRecord::Migration[6.0]
|
|||
create_table :repository_checklist_values do |t|
|
||||
t.references :created_by, index: true, foreign_key: { to_table: :users }, null: true
|
||||
t.references :last_modified_by, index: true, foreign_key: { to_table: :users }, null: true
|
||||
t.jsonb :repository_checklist_items,
|
||||
|
||||
t.timestamps
|
||||
end
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateRepositoryCellValuesChecklistItems < ActiveRecord::Migration[6.0]
|
||||
def change
|
||||
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 }
|
||||
t.timestamps
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1142,6 +1142,38 @@ 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: -
|
||||
--
|
||||
|
@ -1220,9 +1252,7 @@ CREATE TABLE public.repository_checklist_values (
|
|||
created_by_id bigint,
|
||||
last_modified_by_id bigint,
|
||||
created_at timestamp(6) without time zone NOT NULL,
|
||||
updated_at timestamp(6) without time zone NOT NULL,
|
||||
repository_checklist_items jsonb,
|
||||
"#<ActiveRecord::ConnectionAdapters::PostgreSQL::TableDefinition" jsonb
|
||||
updated_at timestamp(6) without time zone NOT NULL
|
||||
);
|
||||
|
||||
|
||||
|
@ -2966,6 +2996,13 @@ 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: -
|
||||
--
|
||||
|
@ -3534,6 +3571,14 @@ 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: -
|
||||
--
|
||||
|
@ -5669,6 +5714,20 @@ 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: -
|
||||
--
|
||||
|
@ -6861,6 +6920,14 @@ 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: -
|
||||
--
|
||||
|
@ -6885,6 +6952,14 @@ 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: -
|
||||
--
|
||||
|
@ -7120,7 +7195,7 @@ INSERT INTO "schema_migrations" (version) VALUES
|
|||
('20191205133447'),
|
||||
('20191205133522'),
|
||||
('20191206105058'),
|
||||
('20191210103004');
|
||||
|
||||
('20191210103004'),
|
||||
('20191217132401');
|
||||
|
||||
|
||||
|
|
|
@ -1,86 +0,0 @@
|
|||
require 'rails_helper'
|
||||
|
||||
describe RepositoryListItemsController, type: :controller do
|
||||
login_user
|
||||
render_views
|
||||
let(:user) { subject.current_user }
|
||||
let!(:team) { create :team, created_by: user }
|
||||
let!(:user_team) { create :user_team, team: team, user: user }
|
||||
let!(:repository) { create :repository, team: team, created_by: user }
|
||||
let!(:repository_column_one) do
|
||||
create :repository_column, repository: repository,
|
||||
created_by: user,
|
||||
name: 'List Value',
|
||||
data_type: 'RepositoryListValue'
|
||||
end
|
||||
let!(:repository_list_item_one) do
|
||||
create :repository_list_item, data: 'item one',
|
||||
repository: repository,
|
||||
repository_column: repository_column_one
|
||||
end
|
||||
let!(:repository_list_item_two) do
|
||||
create :repository_list_item, data: 'item two',
|
||||
repository: repository,
|
||||
repository_column: repository_column_one
|
||||
end
|
||||
|
||||
let!(:user_two) { create :user, email: 'new@user.com' }
|
||||
let!(:team_two) { create :team, created_by: user }
|
||||
let!(:user_team_two) { create :user_team, team: team_two, user: user_two }
|
||||
let!(:repository_two) do
|
||||
create :repository, team: team_two, created_by: user_two
|
||||
end
|
||||
let!(:user_two_repository_column_two) do
|
||||
create :repository_column, repository: repository_two,
|
||||
created_by: user_two,
|
||||
name: 'List Value',
|
||||
data_type: 'RepositoryListValue'
|
||||
end
|
||||
let!(:user_two_repository_list_item_one) do
|
||||
create :repository_list_item,
|
||||
data: 'item one of user two',
|
||||
repository: repository_two,
|
||||
repository_column: user_two_repository_column_two,
|
||||
created_by: user_two,
|
||||
last_modified_by: user_two
|
||||
end
|
||||
let!(:user_two_repository_list_item_two) do
|
||||
create :repository_list_item,
|
||||
data: 'item two of user two',
|
||||
repository: repository_two,
|
||||
repository_column: user_two_repository_column_two,
|
||||
created_by: user_two,
|
||||
last_modified_by: user_two
|
||||
end
|
||||
|
||||
describe '#search' do
|
||||
let(:params) { { q: '', column_id: repository_column_one.id } }
|
||||
it 'returns all column\'s list items' do
|
||||
get :search, format: :json, params: params
|
||||
expect(response).to have_http_status(:ok)
|
||||
body = JSON.parse(response.body)
|
||||
expect(body['list_items'].count).to eq 2
|
||||
end
|
||||
|
||||
it 'returns queried item' do
|
||||
params[:q] = 'item one'
|
||||
get :search, format: :json, params: params
|
||||
expect(response).to have_http_status(:success)
|
||||
body = JSON.parse(response.body)
|
||||
expect(body['list_items'].count).to eq 1
|
||||
expect(body['list_items'].first['data']).to eq 'item one'
|
||||
end
|
||||
|
||||
it 'returns a 404 error if column does not exist' do
|
||||
params[:column_id] = 999999
|
||||
get :search, format: :json, params: params
|
||||
expect(response).to have_http_status(:not_found)
|
||||
end
|
||||
|
||||
it 'returns a 403 error user does not have permissions' do
|
||||
params[:column_id] = user_two_repository_column_two.id
|
||||
get :search, format: :json, params: params
|
||||
expect(response).to have_http_status(:forbidden)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -16,7 +16,6 @@ RSpec.describe RepositoryChecklistValue, type: :model do
|
|||
describe 'Database table' do
|
||||
it { should have_db_column :created_by_id }
|
||||
it { should have_db_column :last_modified_by_id }
|
||||
it { should have_db_column :repository_checklist_items }
|
||||
end
|
||||
|
||||
describe 'Relations' do
|
||||
|
|
|
@ -39,7 +39,7 @@ describe RepositoryRows::CreateRepositoryRowService do
|
|||
let(:params) do
|
||||
{
|
||||
repository_cells: Hash[column.id, ''],
|
||||
repository_row: { name: 'name' }
|
||||
repository_row: { name: '' }
|
||||
}
|
||||
end
|
||||
|
||||
|
|
Loading…
Reference in a new issue