mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2024-12-29 19:51:01 +08:00
dfa2a7775d
Fix repository cell joining and preloading [SCI-5847]
179 lines
7.1 KiB
Ruby
179 lines
7.1 KiB
Ruby
# frozen_string_literal: true
|
|
|
|
class RepositoryDatatableService
|
|
attr_reader :repository_rows, :all_count, :mappings
|
|
|
|
def initialize(repository, params, user, my_module = nil)
|
|
@repository = repository
|
|
@user = user
|
|
@my_module = my_module
|
|
@params = params
|
|
@sortable_columns = build_sortable_columns
|
|
create_columns_mappings
|
|
@repository_rows = process_query
|
|
end
|
|
|
|
private
|
|
|
|
def create_columns_mappings
|
|
# Make mappings of custom columns, so we have same id for every
|
|
# column
|
|
index = @repository.default_columns_count
|
|
@mappings = {}
|
|
@repository.repository_columns.order(:id).each do |column|
|
|
@mappings[column.id] = index.to_s
|
|
index += 1
|
|
end
|
|
end
|
|
|
|
def process_query
|
|
search_value = build_conditions(@params)[:search_value]
|
|
order_obj = build_conditions(@params)[:order_by_column]
|
|
|
|
repository_rows = fetch_rows(search_value)
|
|
|
|
# Adding assigned counters
|
|
if @my_module
|
|
if @params[:assigned] == 'assigned'
|
|
repository_rows = repository_rows.joins(:my_module_repository_rows)
|
|
.where(my_module_repository_rows: { my_module_id: @my_module })
|
|
else
|
|
repository_rows = repository_rows
|
|
.joins(:repository)
|
|
.joins('LEFT OUTER JOIN "my_module_repository_rows" "current_my_module_repository_rows"'\
|
|
'ON "current_my_module_repository_rows"."repository_row_id" = "repository_rows"."id" '\
|
|
'AND "current_my_module_repository_rows"."my_module_id" = ' + @my_module.id.to_s)
|
|
.where('current_my_module_repository_rows.id IS NOT NULL '\
|
|
'OR (repository_rows.archived = FALSE AND repositories.archived = FALSE)')
|
|
.select('CASE WHEN current_my_module_repository_rows.id IS NOT NULL '\
|
|
'THEN true ELSE false END as row_assigned')
|
|
.group('current_my_module_repository_rows.id')
|
|
end
|
|
end
|
|
repository_rows = repository_rows
|
|
.left_outer_joins(my_module_repository_rows: { my_module: :experiment })
|
|
.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"')
|
|
repository_rows = repository_rows.preload(Extends::REPOSITORY_ROWS_PRELOAD_RELATIONS)
|
|
|
|
sort_rows(order_obj, repository_rows)
|
|
end
|
|
|
|
def fetch_rows(search_value)
|
|
repository_rows = @repository.repository_rows
|
|
if @params[:archived] && !@repository.archived?
|
|
repository_rows = repository_rows.where(archived: @params[:archived])
|
|
end
|
|
|
|
@all_count =
|
|
if @my_module && @params[:assigned] == 'assigned'
|
|
repository_rows.joins(:my_module_repository_rows)
|
|
.where(my_module_repository_rows: { my_module_id: @my_module })
|
|
.count
|
|
else
|
|
repository_rows.count
|
|
end
|
|
|
|
if search_value.present?
|
|
matched_by_user = repository_rows.joins(:created_by).where_attributes_like('users.full_name', search_value)
|
|
|
|
repository_row_matches = repository_rows
|
|
.where_attributes_like(
|
|
['repository_rows.name', RepositoryRow::PREFIXED_ID_SQL],
|
|
search_value
|
|
)
|
|
results = repository_rows.where(id: repository_row_matches)
|
|
results = results.or(repository_rows.where(id: matched_by_user))
|
|
|
|
data_types = @repository.repository_columns.pluck(:data_type).uniq
|
|
|
|
Extends::REPOSITORY_EXTRA_SEARCH_ATTR.each do |data_type, config|
|
|
next unless data_types.include?(data_type.to_s)
|
|
|
|
custom_cell_matches = repository_rows.joins(config[:includes])
|
|
.where_attributes_like(config[:field], search_value)
|
|
results = results.or(repository_rows.where(id: custom_cell_matches))
|
|
end
|
|
|
|
repository_rows = results
|
|
end
|
|
|
|
repository_rows.left_outer_joins(:created_by, :archived_by)
|
|
.select('repository_rows.*')
|
|
.select('COUNT("repository_rows"."id") OVER() AS filtered_count')
|
|
.group('repository_rows.id')
|
|
end
|
|
|
|
def build_conditions(params)
|
|
search_value = params[:search][:value]
|
|
order = params[:order].values.first
|
|
order_by_column = { column: order[:column].to_i,
|
|
dir: order[:dir] }
|
|
{ search_value: search_value, order_by_column: order_by_column }
|
|
end
|
|
|
|
def build_sortable_columns
|
|
array = [
|
|
'assigned',
|
|
'repository_rows.id',
|
|
'repository_rows.name',
|
|
'repository_rows.created_at',
|
|
'users.full_name',
|
|
'repository_rows.archived_on',
|
|
'archived_bies_repository_rows.full_name',
|
|
]
|
|
@repository.repository_columns.count.times do
|
|
array << 'repository_cell.value'
|
|
end
|
|
array
|
|
end
|
|
|
|
def sort_rows(column_obj, records)
|
|
dir = %w(DESC ASC).find do |direction|
|
|
direction == column_obj[:dir].upcase
|
|
end || 'ASC'
|
|
|
|
column_index = column_obj[:column]
|
|
service = RepositoryTableStateService.new(@user, @repository)
|
|
col_order = service.load_state.state['ColReorder']
|
|
column_id = col_order[column_index].to_i
|
|
|
|
case @sortable_columns[column_id - 1]
|
|
when 'assigned'
|
|
return records if @my_module && @params[:assigned] == 'assigned'
|
|
|
|
records.order("assigned_my_modules_count #{dir}")
|
|
when 'repository_cell.value'
|
|
id = @mappings.key(column_id.to_s)
|
|
sorting_column = @repository.repository_columns.find_by(id: id)
|
|
return records unless sorting_column
|
|
|
|
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
|
|
.select("repository_cells.repository_row_id, \
|
|
STRING_AGG(#{sorting_data_type::SORTABLE_COLUMN_NAME}, ' ' \
|
|
ORDER BY #{sorting_data_type::SORTABLE_COLUMN_NAME}) AS value")
|
|
.group('repository_cells.repository_row_id')
|
|
else
|
|
cells
|
|
.select("repository_cells.repository_row_id, #{sorting_data_type::SORTABLE_COLUMN_NAME} AS value")
|
|
end
|
|
|
|
records.joins("LEFT OUTER JOIN (#{cells.to_sql}) AS values ON values.repository_row_id = repository_rows.id")
|
|
.group('values.value')
|
|
.order("values.value #{dir}")
|
|
when 'users.full_name'
|
|
records.group('users.full_name').order("users.full_name #{dir}")
|
|
else
|
|
records.group(@sortable_columns[column_id - 1]).order("#{@sortable_columns[column_id - 1]} #{dir}")
|
|
end
|
|
end
|
|
end
|