mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-10-10 13:59:56 +08:00
Merge pull request #3422 from okriuchykhin/ok_SCI_5847
Fix repository cell joining and preloading [SCI-5847]
This commit is contained in:
commit
dfa2a7775d
28 changed files with 97 additions and 181 deletions
|
@ -12,7 +12,7 @@ module Api
|
||||||
|
|
||||||
def index
|
def index
|
||||||
cells = @inventory_item.repository_cells
|
cells = @inventory_item.repository_cells
|
||||||
.preload(@inventory.cell_preload_includes)
|
.preload(value: @inventory.cell_preload_includes)
|
||||||
.page(params.dig(:page, :number))
|
.page(params.dig(:page, :number))
|
||||||
.per(params.dig(:page, :size))
|
.per(params.dig(:page, :size))
|
||||||
render jsonapi: cells, each_serializer: InventoryCellSerializer
|
render jsonapi: cells, each_serializer: InventoryCellSerializer
|
||||||
|
|
|
@ -14,7 +14,7 @@ module Api
|
||||||
items = @inventory.repository_rows
|
items = @inventory.repository_rows
|
||||||
.active
|
.active
|
||||||
.preload(repository_cells: :repository_column)
|
.preload(repository_cells: :repository_column)
|
||||||
.preload(repository_cells: @inventory.cell_preload_includes)
|
.preload(repository_cells: { value: @inventory.cell_preload_includes })
|
||||||
.page(params.dig(:page, :number))
|
.page(params.dig(:page, :number))
|
||||||
.per(params.dig(:page, :size))
|
.per(params.dig(:page, :size))
|
||||||
.order(:id)
|
.order(:id)
|
||||||
|
|
|
@ -12,7 +12,7 @@ module Api
|
||||||
items =
|
items =
|
||||||
@task.repository_rows
|
@task.repository_rows
|
||||||
.includes(repository_cells: :repository_column)
|
.includes(repository_cells: :repository_column)
|
||||||
.includes(repository_cells: Extends::REPOSITORY_SEARCH_INCLUDES)
|
.preload(repository_cells: :value)
|
||||||
.page(params.dig(:page, :number))
|
.page(params.dig(:page, :number))
|
||||||
.per(params.dig(:page, :size))
|
.per(params.dig(:page, :size))
|
||||||
render jsonapi: items,
|
render jsonapi: items,
|
||||||
|
|
|
@ -25,9 +25,10 @@ class MyModuleRepositoriesController < ApplicationController
|
||||||
repository_rows = datatable_service.repository_rows
|
repository_rows = datatable_service.repository_rows
|
||||||
rows_view = 'repository_rows/simple_view_index.json'
|
rows_view = 'repository_rows/simple_view_index.json'
|
||||||
else
|
else
|
||||||
repository_rows = datatable_service.repository_rows.preload(:repository_columns,
|
repository_rows = datatable_service.repository_rows
|
||||||
|
.preload(:repository_columns,
|
||||||
:created_by,
|
:created_by,
|
||||||
repository_cells: @repository.cell_preload_includes)
|
repository_cells: { value: @repository.cell_preload_includes })
|
||||||
rows_view = 'repository_rows/index.json'
|
rows_view = 'repository_rows/index.json'
|
||||||
end
|
end
|
||||||
@repository_rows = repository_rows.page(page).per(per_page)
|
@repository_rows = repository_rows.page(page).per(per_page)
|
||||||
|
|
|
@ -19,10 +19,11 @@ class MyModuleRepositorySnapshotsController < ApplicationController
|
||||||
repository_rows = datatable_service.repository_rows
|
repository_rows = datatable_service.repository_rows
|
||||||
rows_view = 'repository_rows/simple_view_index.json'
|
rows_view = 'repository_rows/simple_view_index.json'
|
||||||
else
|
else
|
||||||
repository_rows = datatable_service.repository_rows
|
repository_rows =
|
||||||
|
datatable_service.repository_rows
|
||||||
.preload(:repository_columns,
|
.preload(:repository_columns,
|
||||||
:created_by,
|
:created_by,
|
||||||
repository_cells: @repository_snapshot.cell_preload_includes)
|
repository_cells: { value: @repository_snapshot.cell_preload_includes })
|
||||||
rows_view = 'repository_rows/snapshot_index.json'
|
rows_view = 'repository_rows/snapshot_index.json'
|
||||||
end
|
end
|
||||||
@repository_rows = repository_rows.page(page).per(per_page)
|
@repository_rows = repository_rows.page(page).per(per_page)
|
||||||
|
|
|
@ -23,7 +23,7 @@ class RepositoryRowsController < ApplicationController
|
||||||
@repository_rows = datatable_service.repository_rows
|
@repository_rows = datatable_service.repository_rows
|
||||||
.preload(:repository_columns,
|
.preload(:repository_columns,
|
||||||
:created_by,
|
:created_by,
|
||||||
repository_cells: @repository.cell_preload_includes)
|
repository_cells: { value: @repository.cell_preload_includes })
|
||||||
.page(page)
|
.page(page)
|
||||||
.per(per_page)
|
.per(per_page)
|
||||||
|
|
||||||
|
|
|
@ -101,10 +101,9 @@ module RepositoryDatatableHelper
|
||||||
end
|
end
|
||||||
|
|
||||||
def display_cell_value(cell, team)
|
def display_cell_value(cell, team)
|
||||||
value_name = cell.repository_column.data_type.demodulize.underscore
|
|
||||||
serializer_class = "RepositoryDatatable::#{cell.repository_column.data_type}Serializer".constantize
|
serializer_class = "RepositoryDatatable::#{cell.repository_column.data_type}Serializer".constantize
|
||||||
serializer_class.new(
|
serializer_class.new(
|
||||||
cell.__send__(value_name),
|
cell.value,
|
||||||
scope: { team: team, user: current_user, column: cell.repository_column }
|
scope: { team: team, user: current_user, column: cell.repository_column }
|
||||||
).serializable_hash
|
).serializable_hash
|
||||||
end
|
end
|
||||||
|
|
|
@ -93,7 +93,7 @@ class Repository < RepositoryBase
|
||||||
repository_rows = repository_rows.or(readable_rows.where(id: matched_by_user))
|
repository_rows = repository_rows.or(readable_rows.where(id: matched_by_user))
|
||||||
|
|
||||||
Extends::REPOSITORY_EXTRA_SEARCH_ATTR.each do |_data_type, config|
|
Extends::REPOSITORY_EXTRA_SEARCH_ATTR.each do |_data_type, config|
|
||||||
custom_cell_matches = repository_rows.joins(repository_cells: config[:includes])
|
custom_cell_matches = repository_rows.joins(config[:includes])
|
||||||
.where_attributes_like(config[:field], query, options)
|
.where_attributes_like(config[:field], query, options)
|
||||||
repository_rows = repository_rows.or(readable_rows.where(id: custom_cell_matches))
|
repository_rows = repository_rows.or(readable_rows.where(id: custom_cell_matches))
|
||||||
end
|
end
|
||||||
|
@ -201,14 +201,6 @@ class Repository < RepositoryBase
|
||||||
new_repo
|
new_repo
|
||||||
end
|
end
|
||||||
|
|
||||||
def cell_preload_includes
|
|
||||||
cell_includes = []
|
|
||||||
repository_columns.pluck(:data_type).each do |data_type|
|
|
||||||
cell_includes << data_type.constantize::PRELOAD_INCLUDE
|
|
||||||
end
|
|
||||||
cell_includes
|
|
||||||
end
|
|
||||||
|
|
||||||
def import_records(sheet, mappings, user)
|
def import_records(sheet, mappings, user)
|
||||||
importer = RepositoryImportParser::Importer.new(sheet, mappings, user, self)
|
importer = RepositoryImportParser::Importer.new(sheet, mappings, user, self)
|
||||||
importer.run
|
importer.run
|
||||||
|
|
|
@ -18,8 +18,8 @@ class RepositoryAssetValue < ApplicationRecord
|
||||||
validates :asset, :repository_cell, presence: true
|
validates :asset, :repository_cell, presence: true
|
||||||
|
|
||||||
SORTABLE_COLUMN_NAME = 'active_storage_blobs.filename'
|
SORTABLE_COLUMN_NAME = 'active_storage_blobs.filename'
|
||||||
SORTABLE_VALUE_INCLUDE = { repository_asset_value: { asset: { file_attachment: :blob } } }.freeze
|
EXTRA_SORTABLE_VALUE_INCLUDE = { asset: { file_attachment: :blob } }.freeze
|
||||||
PRELOAD_INCLUDE = { repository_asset_value: { asset: { file_attachment: :blob } } }.freeze
|
EXTRA_PRELOAD_INCLUDE = { asset: { file_attachment: :blob } }.freeze
|
||||||
|
|
||||||
def formatted
|
def formatted
|
||||||
asset.file_name
|
asset.file_name
|
||||||
|
|
|
@ -24,7 +24,10 @@ class RepositoryBase < ApplicationRecord
|
||||||
def cell_preload_includes
|
def cell_preload_includes
|
||||||
cell_includes = []
|
cell_includes = []
|
||||||
repository_columns.pluck(:data_type).each do |data_type|
|
repository_columns.pluck(:data_type).each do |data_type|
|
||||||
cell_includes << data_type.constantize::PRELOAD_INCLUDE
|
value_class = data_type.constantize
|
||||||
|
next unless value_class.const_defined?('EXTRA_PRELOAD_INCLUDE')
|
||||||
|
|
||||||
|
cell_includes << value_class::EXTRA_PRELOAD_INCLUDE
|
||||||
end
|
end
|
||||||
cell_includes
|
cell_includes
|
||||||
end
|
end
|
||||||
|
|
|
@ -5,106 +5,32 @@ class RepositoryCell < ApplicationRecord
|
||||||
|
|
||||||
belongs_to :repository_row
|
belongs_to :repository_row
|
||||||
belongs_to :repository_column
|
belongs_to :repository_column
|
||||||
belongs_to :value, polymorphic: true,
|
belongs_to :value, polymorphic: true, inverse_of: :repository_cell, dependent: :destroy
|
||||||
inverse_of: :repository_cell,
|
|
||||||
dependent: :destroy
|
|
||||||
belongs_to :repository_text_value,
|
|
||||||
(lambda do
|
|
||||||
includes(:repository_cell)
|
|
||||||
.where(repository_cells: { value_type: 'RepositoryTextValue' })
|
|
||||||
end),
|
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
|
||||||
belongs_to :repository_number_value,
|
|
||||||
(lambda do
|
|
||||||
includes(:repository_cell)
|
|
||||||
.where(repository_cells: { value_type: 'RepositoryNumberValue' })
|
|
||||||
end),
|
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
|
||||||
belongs_to :repository_date_value,
|
|
||||||
(lambda do
|
|
||||||
includes(:repository_cell)
|
|
||||||
.where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' })
|
|
||||||
end),
|
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
|
||||||
belongs_to :repository_list_value,
|
|
||||||
(lambda do
|
|
||||||
includes(:repository_cell)
|
|
||||||
.where(repository_cells: { value_type: 'RepositoryListValue' })
|
|
||||||
end),
|
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
|
||||||
belongs_to :repository_asset_value,
|
|
||||||
(lambda do
|
|
||||||
includes(:repository_cell)
|
|
||||||
.where(repository_cells: { value_type: 'RepositoryAssetValue' })
|
|
||||||
end),
|
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
|
||||||
|
|
||||||
belongs_to :repository_status_value,
|
{
|
||||||
(lambda do
|
repository_text: 'RepositoryTextValue',
|
||||||
includes(:repository_cell)
|
repository_number: 'RepositoryNumberValue',
|
||||||
.where(repository_cells: { value_type: 'RepositoryStatusValue' })
|
repository_list: 'RepositoryListValue',
|
||||||
end),
|
repository_asset: 'RepositoryAssetValue',
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
repository_status: 'RepositoryStatusValue',
|
||||||
|
repository_checklist: 'RepositoryChecklistValue',
|
||||||
belongs_to :repository_checklist_value,
|
repository_date_time: 'RepositoryDateTimeValueBase',
|
||||||
(lambda do
|
repository_time: 'RepositoryDateTimeValueBase',
|
||||||
includes(:repository_cell)
|
repository_date: 'RepositoryDateTimeValueBase',
|
||||||
.where(repository_cells: { value_type: 'RepositoryChecklistValue' })
|
repository_date_time_range: 'RepositoryDateTimeRangeValueBase',
|
||||||
end),
|
repository_time_range: 'RepositoryDateTimeRangeValueBase',
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
repository_date_range: 'RepositoryDateTimeRangeValueBase'
|
||||||
|
}.each do |relation, class_name|
|
||||||
belongs_to :repository_date_time_value_base,
|
belongs_to "#{relation}_value".to_sym,
|
||||||
(lambda do
|
(lambda do |repository_cell|
|
||||||
includes(:repository_cell)
|
repository_cell.value_type == class_name ? self : none
|
||||||
.where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' })
|
|
||||||
end),
|
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
|
||||||
|
|
||||||
belongs_to :repository_date_time_value,
|
|
||||||
(lambda do
|
|
||||||
includes(:repository_cell)
|
|
||||||
.where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' })
|
|
||||||
end),
|
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
|
||||||
|
|
||||||
belongs_to :repository_time_value,
|
|
||||||
(lambda do
|
|
||||||
includes(:repository_cell)
|
|
||||||
.where(repository_cells: { value_type: 'RepositoryDateTimeValueBase' })
|
|
||||||
end),
|
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
|
||||||
|
|
||||||
belongs_to :repository_date_time_range_value_base,
|
|
||||||
(lambda do
|
|
||||||
includes(:repository_cell)
|
|
||||||
.where(repository_cells: { value_type: 'RepositoryDateTimeRangeValueBase' })
|
|
||||||
end),
|
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
|
||||||
|
|
||||||
belongs_to :repository_date_time_range_value,
|
|
||||||
(lambda do
|
|
||||||
includes(:repository_cell)
|
|
||||||
.where(repository_cells: { value_type: 'RepositoryDateTimeRangeValueBase' })
|
|
||||||
end),
|
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
|
||||||
|
|
||||||
belongs_to :repository_date_range_value,
|
|
||||||
(lambda do
|
|
||||||
includes(:repository_cell)
|
|
||||||
.where(repository_cells: { value_type: 'RepositoryDateTimeRangeValueBase' })
|
|
||||||
end),
|
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
|
||||||
|
|
||||||
belongs_to :repository_time_range_value,
|
|
||||||
(lambda do
|
|
||||||
includes(:repository_cell)
|
|
||||||
.where(repository_cells: { value_type: 'RepositoryDateTimeRangeValueBase' })
|
|
||||||
end),
|
end),
|
||||||
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
optional: true, foreign_key: :value_id, inverse_of: :repository_cell
|
||||||
|
end
|
||||||
|
|
||||||
validates :repository_column,
|
validates :repository_column,
|
||||||
inclusion: { in: (lambda do |cell|
|
inclusion: { in: (lambda do |repository_cell|
|
||||||
cell.repository_row&.repository&.repository_columns || []
|
repository_cell.repository_row&.repository&.repository_columns || []
|
||||||
end) },
|
end) },
|
||||||
unless: :importing
|
unless: :importing
|
||||||
validates :repository_column, presence: true
|
validates :repository_column, presence: true
|
||||||
|
|
|
@ -14,8 +14,8 @@ class RepositoryChecklistValue < ApplicationRecord
|
||||||
validates :repository_checklist_items, presence: true
|
validates :repository_checklist_items, presence: true
|
||||||
|
|
||||||
SORTABLE_COLUMN_NAME = 'repository_checklist_items.data'
|
SORTABLE_COLUMN_NAME = 'repository_checklist_items.data'
|
||||||
SORTABLE_VALUE_INCLUDE = { repository_checklist_value: :repository_checklist_items }.freeze
|
EXTRA_SORTABLE_VALUE_INCLUDE = :repository_checklist_items
|
||||||
PRELOAD_INCLUDE = { repository_checklist_value: :repository_checklist_items }.freeze
|
EXTRA_PRELOAD_INCLUDE = :repository_checklist_items
|
||||||
|
|
||||||
def formatted(separator: ' | ')
|
def formatted(separator: ' | ')
|
||||||
repository_checklist_items.pluck(:data).join(separator)
|
repository_checklist_items.pluck(:data).join(separator)
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class RepositoryDateRangeValue < RepositoryDateTimeRangeValueBase
|
class RepositoryDateRangeValue < RepositoryDateTimeRangeValueBase
|
||||||
PRELOAD_INCLUDE = :repository_date_range_value
|
|
||||||
|
|
||||||
def data_changed?(new_data)
|
def data_changed?(new_data)
|
||||||
data = new_data.is_a?(String) ? JSON.parse(new_data).symbolize_keys : new_data
|
data = new_data.is_a?(String) ? JSON.parse(new_data).symbolize_keys : new_data
|
||||||
st = Time.zone.parse(data[:start_time])
|
st = Time.zone.parse(data[:start_time])
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class RepositoryDateTimeRangeValue < RepositoryDateTimeRangeValueBase
|
class RepositoryDateTimeRangeValue < RepositoryDateTimeRangeValueBase
|
||||||
PRELOAD_INCLUDE = :repository_date_time_range_value
|
|
||||||
|
|
||||||
def data_changed?(new_data)
|
def data_changed?(new_data)
|
||||||
data = new_data.is_a?(String) ? JSON.parse(new_data).symbolize_keys : new_data
|
data = new_data.is_a?(String) ? JSON.parse(new_data).symbolize_keys : new_data
|
||||||
st = Time.zone.parse(data[:start_time])
|
st = Time.zone.parse(data[:start_time])
|
||||||
|
|
|
@ -13,7 +13,6 @@ class RepositoryDateTimeRangeValueBase < ApplicationRecord
|
||||||
validates :repository_cell, :start_time, :end_time, :type, presence: true
|
validates :repository_cell, :start_time, :end_time, :type, presence: true
|
||||||
|
|
||||||
SORTABLE_COLUMN_NAME = 'repository_date_time_range_values.start_time'
|
SORTABLE_COLUMN_NAME = 'repository_date_time_range_values.start_time'
|
||||||
SORTABLE_VALUE_INCLUDE = :repository_date_time_range_value_base
|
|
||||||
|
|
||||||
def data
|
def data
|
||||||
[start_time, end_time].compact.join(' - ')
|
[start_time, end_time].compact.join(' - ')
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class RepositoryDateTimeValue < RepositoryDateTimeValueBase
|
class RepositoryDateTimeValue < RepositoryDateTimeValueBase
|
||||||
PRELOAD_INCLUDE = :repository_date_time_value
|
|
||||||
|
|
||||||
def data_changed?(new_data)
|
def data_changed?(new_data)
|
||||||
new_time = Time.zone.parse(new_data)
|
new_time = Time.zone.parse(new_data)
|
||||||
new_time.to_i != data.to_i
|
new_time.to_i != data.to_i
|
||||||
|
|
|
@ -13,7 +13,6 @@ class RepositoryDateTimeValueBase < ApplicationRecord
|
||||||
validates :repository_cell, :data, :type, presence: true
|
validates :repository_cell, :data, :type, presence: true
|
||||||
|
|
||||||
SORTABLE_COLUMN_NAME = 'repository_date_time_values.data'
|
SORTABLE_COLUMN_NAME = 'repository_date_time_values.data'
|
||||||
SORTABLE_VALUE_INCLUDE = :repository_date_time_value_base
|
|
||||||
|
|
||||||
def formatted(format)
|
def formatted(format)
|
||||||
I18n.l(data, format: format)
|
I18n.l(data, format: format)
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class RepositoryDateValue < RepositoryDateTimeValueBase
|
class RepositoryDateValue < RepositoryDateTimeValueBase
|
||||||
PRELOAD_INCLUDE = :repository_date_value
|
|
||||||
|
|
||||||
def data_changed?(new_data)
|
def data_changed?(new_data)
|
||||||
new_time = Time.zone.parse(new_data)
|
new_time = Time.zone.parse(new_data)
|
||||||
new_time.to_date != data.to_date
|
new_time.to_date != data.to_date
|
||||||
|
|
|
@ -20,8 +20,8 @@ class RepositoryListValue < ApplicationRecord
|
||||||
end)
|
end)
|
||||||
|
|
||||||
SORTABLE_COLUMN_NAME = 'repository_list_items.data'
|
SORTABLE_COLUMN_NAME = 'repository_list_items.data'
|
||||||
SORTABLE_VALUE_INCLUDE = { repository_list_value: :repository_list_item }.freeze
|
EXTRA_SORTABLE_VALUE_INCLUDE = :repository_list_item
|
||||||
PRELOAD_INCLUDE = { repository_list_value: :repository_list_item }.freeze
|
EXTRA_PRELOAD_INCLUDE = :repository_list_item
|
||||||
|
|
||||||
def formatted
|
def formatted
|
||||||
data.to_s
|
data.to_s
|
||||||
|
|
|
@ -11,8 +11,6 @@ class RepositoryNumberValue < ApplicationRecord
|
||||||
validates :repository_cell, :data, presence: true
|
validates :repository_cell, :data, presence: true
|
||||||
|
|
||||||
SORTABLE_COLUMN_NAME = 'repository_number_values.data'
|
SORTABLE_COLUMN_NAME = 'repository_number_values.data'
|
||||||
SORTABLE_VALUE_INCLUDE = :repository_number_value
|
|
||||||
PRELOAD_INCLUDE = :repository_number_value
|
|
||||||
|
|
||||||
def formatted
|
def formatted
|
||||||
data.to_s
|
data.to_s
|
||||||
|
|
|
@ -13,16 +13,35 @@ class RepositoryRow < ApplicationRecord
|
||||||
belongs_to :created_by, foreign_key: :created_by_id, class_name: 'User'
|
belongs_to :created_by, foreign_key: :created_by_id, class_name: 'User'
|
||||||
belongs_to :last_modified_by, foreign_key: :last_modified_by_id, class_name: 'User'
|
belongs_to :last_modified_by, foreign_key: :last_modified_by_id, class_name: 'User'
|
||||||
belongs_to :archived_by,
|
belongs_to :archived_by,
|
||||||
foreign_key: :archived_by_id,
|
|
||||||
class_name: 'User',
|
class_name: 'User',
|
||||||
inverse_of: :archived_repository_rows,
|
inverse_of: :archived_repository_rows,
|
||||||
optional: true
|
optional: true
|
||||||
belongs_to :restored_by,
|
belongs_to :restored_by,
|
||||||
foreign_key: :restored_by_id,
|
|
||||||
class_name: 'User',
|
class_name: 'User',
|
||||||
inverse_of: :restored_repository_rows,
|
inverse_of: :restored_repository_rows,
|
||||||
optional: true
|
optional: true
|
||||||
has_many :repository_cells, -> { order(:id) }, dependent: :destroy
|
has_many :repository_cells, -> { order(:id) }, inverse_of: :repository_row, dependent: :destroy
|
||||||
|
|
||||||
|
{
|
||||||
|
repository_text: 'RepositoryTextValue',
|
||||||
|
repository_number: 'RepositoryNumberValue',
|
||||||
|
repository_list: 'RepositoryListValue',
|
||||||
|
repository_asset: 'RepositoryAssetValue',
|
||||||
|
repository_status: 'RepositoryStatusValue',
|
||||||
|
repository_checklist: 'RepositoryChecklistValue',
|
||||||
|
repository_date_time: 'RepositoryDateTimeValue',
|
||||||
|
repository_time: 'RepositoryTimeValue',
|
||||||
|
repository_date: 'RepositoryDateValue',
|
||||||
|
repository_date_time_range: 'RepositoryDateTimeRangeValue',
|
||||||
|
repository_time_range: 'RepositoryTimeRangeValue',
|
||||||
|
repository_date_range: 'RepositoryDateRangeValue'
|
||||||
|
}.each do |relation, class_name|
|
||||||
|
has_many "#{relation}_cells".to_sym, -> { where(value_type: class_name) }, class_name: 'RepositoryCell',
|
||||||
|
inverse_of: :repository_row
|
||||||
|
has_many "#{relation}_values".to_sym, class_name: class_name, through: "#{relation}_cells".to_sym,
|
||||||
|
source: :value, source_type: class_name
|
||||||
|
end
|
||||||
|
|
||||||
has_many :repository_columns, through: :repository_cells
|
has_many :repository_columns, through: :repository_cells
|
||||||
has_many :my_module_repository_rows,
|
has_many :my_module_repository_rows,
|
||||||
inverse_of: :repository_row, dependent: :destroy
|
inverse_of: :repository_row, dependent: :destroy
|
||||||
|
|
|
@ -12,8 +12,8 @@ class RepositoryStatusValue < ApplicationRecord
|
||||||
validates :repository_cell, :repository_status_item, presence: true
|
validates :repository_cell, :repository_status_item, presence: true
|
||||||
|
|
||||||
SORTABLE_COLUMN_NAME = 'repository_status_items.status'
|
SORTABLE_COLUMN_NAME = 'repository_status_items.status'
|
||||||
SORTABLE_VALUE_INCLUDE = { repository_status_value: :repository_status_item }.freeze
|
EXTRA_SORTABLE_VALUE_INCLUDE = :repository_status_item
|
||||||
PRELOAD_INCLUDE = { repository_status_value: :repository_status_item }.freeze
|
EXTRA_PRELOAD_INCLUDE = :repository_status_item
|
||||||
|
|
||||||
def formatted
|
def formatted
|
||||||
data
|
data
|
||||||
|
|
|
@ -14,8 +14,6 @@ class RepositoryTextValue < ApplicationRecord
|
||||||
validates :data, presence: true, length: { maximum: Constants::TEXT_MAX_LENGTH }
|
validates :data, presence: true, length: { maximum: Constants::TEXT_MAX_LENGTH }
|
||||||
|
|
||||||
SORTABLE_COLUMN_NAME = 'repository_text_values.data'
|
SORTABLE_COLUMN_NAME = 'repository_text_values.data'
|
||||||
SORTABLE_VALUE_INCLUDE = :repository_text_value
|
|
||||||
PRELOAD_INCLUDE = :repository_text_value
|
|
||||||
|
|
||||||
def formatted
|
def formatted
|
||||||
data
|
data
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class RepositoryTimeRangeValue < RepositoryDateTimeRangeValueBase
|
class RepositoryTimeRangeValue < RepositoryDateTimeRangeValueBase
|
||||||
PRELOAD_INCLUDE = :repository_time_range_value
|
|
||||||
|
|
||||||
def data_changed?(new_data)
|
def data_changed?(new_data)
|
||||||
data = new_data.is_a?(String) ? JSON.parse(new_data).symbolize_keys : new_data
|
data = new_data.is_a?(String) ? JSON.parse(new_data).symbolize_keys : new_data
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
# frozen_string_literal: true
|
# frozen_string_literal: true
|
||||||
|
|
||||||
class RepositoryTimeValue < RepositoryDateTimeValueBase
|
class RepositoryTimeValue < RepositoryDateTimeValueBase
|
||||||
PRELOAD_INCLUDE = :repository_time_value
|
|
||||||
|
|
||||||
def data_changed?(new_data)
|
def data_changed?(new_data)
|
||||||
new_time = Time.zone.parse(new_data)
|
new_time = Time.zone.parse(new_data)
|
||||||
new_time.min != data.min || new_time.hour != data.hour
|
new_time.min != data.min || new_time.hour != data.hour
|
||||||
|
|
|
@ -91,7 +91,7 @@ class RepositoryDatatableService
|
||||||
Extends::REPOSITORY_EXTRA_SEARCH_ATTR.each do |data_type, config|
|
Extends::REPOSITORY_EXTRA_SEARCH_ATTR.each do |data_type, config|
|
||||||
next unless data_types.include?(data_type.to_s)
|
next unless data_types.include?(data_type.to_s)
|
||||||
|
|
||||||
custom_cell_matches = repository_rows.joins(repository_cells: config[:includes])
|
custom_cell_matches = repository_rows.joins(config[:includes])
|
||||||
.where_attributes_like(config[:field], search_value)
|
.where_attributes_like(config[:field], search_value)
|
||||||
results = results.or(repository_rows.where(id: custom_cell_matches))
|
results = results.or(repository_rows.where(id: custom_cell_matches))
|
||||||
end
|
end
|
||||||
|
@ -139,37 +139,38 @@ class RepositoryDatatableService
|
||||||
col_order = service.load_state.state['ColReorder']
|
col_order = service.load_state.state['ColReorder']
|
||||||
column_id = col_order[column_index].to_i
|
column_id = col_order[column_index].to_i
|
||||||
|
|
||||||
if @sortable_columns[column_id - 1] == 'assigned'
|
case @sortable_columns[column_id - 1]
|
||||||
|
when 'assigned'
|
||||||
return records if @my_module && @params[:assigned] == 'assigned'
|
return records if @my_module && @params[:assigned] == 'assigned'
|
||||||
|
|
||||||
records.order("assigned_my_modules_count #{dir}")
|
records.order("assigned_my_modules_count #{dir}")
|
||||||
elsif @sortable_columns[column_id - 1] == 'repository_cell.value'
|
when 'repository_cell.value'
|
||||||
id = @mappings.key(column_id.to_s)
|
id = @mappings.key(column_id.to_s)
|
||||||
sorting_column = RepositoryColumn.find_by(id: id)
|
sorting_column = @repository.repository_columns.find_by(id: id)
|
||||||
return records unless sorting_column
|
return records unless sorting_column
|
||||||
|
|
||||||
sorting_data_type = sorting_column.data_type.constantize
|
sorting_data_type = sorting_column.data_type.constantize
|
||||||
|
cells = sorting_data_type.joins(:repository_cell)
|
||||||
|
.where('repository_cells.repository_column_id': sorting_column.id)
|
||||||
|
if sorting_data_type.const_defined?('EXTRA_SORTABLE_VALUE_INCLUDE')
|
||||||
|
cells = cells.joins(sorting_data_type::EXTRA_SORTABLE_VALUE_INCLUDE)
|
||||||
|
end
|
||||||
|
|
||||||
cells = if sorting_column.repository_checklist_value?
|
cells = if sorting_column.repository_checklist_value?
|
||||||
RepositoryCell.joins(sorting_data_type::SORTABLE_VALUE_INCLUDE)
|
cells
|
||||||
.where('repository_cells.repository_column_id': sorting_column.id)
|
.select("repository_cells.repository_row_id, \
|
||||||
.select("repository_cells.repository_row_id,
|
STRING_AGG(#{sorting_data_type::SORTABLE_COLUMN_NAME}, ' ' \
|
||||||
STRING_AGG(
|
|
||||||
#{sorting_data_type::SORTABLE_COLUMN_NAME}, ' '
|
|
||||||
ORDER BY #{sorting_data_type::SORTABLE_COLUMN_NAME}) AS value")
|
ORDER BY #{sorting_data_type::SORTABLE_COLUMN_NAME}) AS value")
|
||||||
.group('repository_cells.repository_row_id')
|
.group('repository_cells.repository_row_id')
|
||||||
|
|
||||||
else
|
else
|
||||||
RepositoryCell.joins(sorting_data_type::SORTABLE_VALUE_INCLUDE)
|
cells
|
||||||
.where('repository_cells.repository_column_id': sorting_column.id)
|
.select("repository_cells.repository_row_id, #{sorting_data_type::SORTABLE_COLUMN_NAME} AS value")
|
||||||
.select("repository_cells.repository_row_id,
|
|
||||||
#{sorting_data_type::SORTABLE_COLUMN_NAME} AS value")
|
|
||||||
end
|
end
|
||||||
|
|
||||||
records.joins("LEFT OUTER JOIN (#{cells.to_sql}) AS values ON values.repository_row_id = repository_rows.id")
|
records.joins("LEFT OUTER JOIN (#{cells.to_sql}) AS values ON values.repository_row_id = repository_rows.id")
|
||||||
.group('values.value')
|
.group('values.value')
|
||||||
.order("values.value #{dir}")
|
.order("values.value #{dir}")
|
||||||
elsif @sortable_columns[column_id - 1] == 'users.full_name'
|
when 'users.full_name'
|
||||||
records.group('users.full_name').order("users.full_name #{dir}")
|
records.group('users.full_name').order("users.full_name #{dir}")
|
||||||
else
|
else
|
||||||
records.group(@sortable_columns[column_id - 1]).order("#{@sortable_columns[column_id - 1]} #{dir}")
|
records.group(@sortable_columns[column_id - 1]).order("#{@sortable_columns[column_id - 1]} #{dir}")
|
||||||
|
|
|
@ -41,7 +41,7 @@ class RepositorySnapshotDatatableService < RepositoryDatatableService
|
||||||
Extends::REPOSITORY_EXTRA_SEARCH_ATTR.each do |data_type, config|
|
Extends::REPOSITORY_EXTRA_SEARCH_ATTR.each do |data_type, config|
|
||||||
next unless data_types.include?(data_type.to_s)
|
next unless data_types.include?(data_type.to_s)
|
||||||
|
|
||||||
custom_cell_matches = repository_rows.joins(repository_cells: config[:includes])
|
custom_cell_matches = repository_rows.joins(config[:includes])
|
||||||
.where_attributes_like(config[:field], search_value)
|
.where_attributes_like(config[:field], search_value)
|
||||||
results = results.or(repository_rows.where(id: custom_cell_matches))
|
results = results.or(repository_rows.where(id: custom_cell_matches))
|
||||||
end
|
end
|
||||||
|
|
|
@ -69,32 +69,24 @@ class Extends
|
||||||
# Extra attributes used for search in repositories, 'filed_name' => include_hash
|
# Extra attributes used for search in repositories, 'filed_name' => include_hash
|
||||||
REPOSITORY_EXTRA_SEARCH_ATTR = {
|
REPOSITORY_EXTRA_SEARCH_ATTR = {
|
||||||
RepositoryTextValue: {
|
RepositoryTextValue: {
|
||||||
field: 'repository_text_values.data', includes: :repository_text_value
|
field: 'repository_text_values.data', includes: :repository_text_values
|
||||||
}, RepositoryNumberValue: {
|
}, RepositoryNumberValue: {
|
||||||
field: 'repository_number_values.data', includes: :repository_number_value
|
field: 'repository_number_values.data', includes: :repository_number_values
|
||||||
}, RepositoryListValue: {
|
}, RepositoryListValue: {
|
||||||
field: 'repository_list_items.data',
|
field: 'repository_list_items.data',
|
||||||
includes: { repository_list_value: :repository_list_item }
|
includes: { repository_list_values: :repository_list_item }
|
||||||
}, RepositoryChecklistValue: {
|
}, RepositoryChecklistValue: {
|
||||||
field: 'repository_checklist_items.data',
|
field: 'repository_checklist_items.data',
|
||||||
includes: { repository_checklist_value: { repository_checklist_items_values: :repository_checklist_item } }
|
includes: { repository_checklist_values: { repository_checklist_items_values: :repository_checklist_item } }
|
||||||
}, RepositoryStatusValue: {
|
}, RepositoryStatusValue: {
|
||||||
field: 'repository_status_items.status',
|
field: 'repository_status_items.status',
|
||||||
includes: { repository_status_value: :repository_status_item }
|
includes: { repository_status_values: :repository_status_item }
|
||||||
}, RepositoryAssetValue: {
|
}, RepositoryAssetValue: {
|
||||||
field: 'active_storage_blobs.filename',
|
field: 'active_storage_blobs.filename',
|
||||||
includes: { repository_asset_value: { asset: { file_attachment: :blob } } }
|
includes: { repository_asset_values: { asset: { file_attachment: :blob } } }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
# Array of includes used in search query for repository rows
|
|
||||||
REPOSITORY_SEARCH_INCLUDES = [:repository_text_value,
|
|
||||||
:repository_number_value,
|
|
||||||
repository_list_value: :repository_list_item,
|
|
||||||
repository_checklist_value: :repository_checklist_items,
|
|
||||||
repository_status_value: :repository_status_item,
|
|
||||||
repository_asset_value: { asset: { file_attachment: :blob } }]
|
|
||||||
|
|
||||||
# Array of preload relations used in search query for repository rows
|
# Array of preload relations used in search query for repository rows
|
||||||
REPOSITORY_ROWS_PRELOAD_RELATIONS = []
|
REPOSITORY_ROWS_PRELOAD_RELATIONS = []
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue