2018-03-06 23:32:39 +08:00
|
|
|
class RepositoryDatatableService
|
|
|
|
|
2018-03-09 21:22:00 +08:00
|
|
|
attr_reader :repository_rows, :assigned_rows, :mappings
|
2018-03-06 23:32:39 +08:00
|
|
|
|
2018-03-09 21:22:00 +08:00
|
|
|
def initialize(repository, params, user, my_module = nil)
|
2018-03-06 23:32:39 +08:00
|
|
|
@repository = repository
|
2018-03-09 00:36:10 +08:00
|
|
|
@user = user
|
|
|
|
@my_module = my_module
|
|
|
|
@params = params
|
2018-03-09 21:22:00 +08:00
|
|
|
create_columns_mappings
|
2018-03-09 00:36:10 +08:00
|
|
|
process_query
|
2018-03-06 23:32:39 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
private
|
|
|
|
|
2018-03-09 21:22:00 +08:00
|
|
|
def create_columns_mappings
|
2018-03-09 21:43:12 +08:00
|
|
|
# Make mappings of custom columns, so we have same id for every
|
|
|
|
# column
|
2018-04-06 18:03:39 +08:00
|
|
|
index = 6
|
2018-03-09 21:22:00 +08:00
|
|
|
@mappings = {}
|
|
|
|
@repository.repository_columns.order(:id).each do |column|
|
2018-03-20 00:49:09 +08:00
|
|
|
@mappings[column.id] = index.to_s
|
|
|
|
index += 1
|
2018-03-09 21:22:00 +08:00
|
|
|
end
|
|
|
|
end
|
|
|
|
|
2018-03-09 00:36:10 +08:00
|
|
|
def process_query
|
2018-03-09 21:43:12 +08:00
|
|
|
search_value = build_conditions(@params)[:search_value]
|
2019-03-01 03:39:10 +08:00
|
|
|
order_obj = build_conditions(@params)[:order_by_column]
|
2018-03-06 23:32:39 +08:00
|
|
|
|
2019-03-01 03:39:10 +08:00
|
|
|
repository_rows = fetch_rows(search_value)
|
|
|
|
assigned_rows = repository_rows.joins(:my_module_repository_rows)
|
2018-03-09 00:36:10 +08:00
|
|
|
if @my_module
|
2019-03-01 03:39:10 +08:00
|
|
|
assigned_rows = assigned_rows
|
|
|
|
.where(my_module_repository_rows: {
|
|
|
|
my_module_id: @my_module
|
|
|
|
})
|
|
|
|
repository_rows = assigned_rows if @params[:assigned] == 'assigned'
|
2018-03-09 00:36:10 +08:00
|
|
|
end
|
2019-03-01 03:39:10 +08:00
|
|
|
|
|
|
|
@assigned_rows = assigned_rows
|
|
|
|
@repository_rows = sort_rows(order_obj, repository_rows)
|
2018-03-06 23:32:39 +08:00
|
|
|
end
|
|
|
|
|
2019-03-01 03:39:10 +08:00
|
|
|
def fetch_rows(search_value)
|
|
|
|
repository_rows = @repository.repository_rows
|
|
|
|
.left_outer_joins(:created_by)
|
|
|
|
|
|
|
|
if search_value.present?
|
|
|
|
includes_json = { repository_cells: Extends::REPOSITORY_SEARCH_INCLUDES }
|
|
|
|
searchable_attributes = ['repository_rows.name',
|
|
|
|
'users.full_name',
|
|
|
|
'repository_rows.id'] +
|
|
|
|
Extends::REPOSITORY_EXTRA_SEARCH_ATTR
|
|
|
|
|
2019-03-20 13:00:10 +08:00
|
|
|
# Using distinct raises error when combined with sort on a custom column
|
|
|
|
repository_row_ids = repository_rows
|
|
|
|
.left_outer_joins(includes_json)
|
|
|
|
.where_attributes_like(searchable_attributes,
|
|
|
|
search_value)
|
|
|
|
.pluck(:id)
|
|
|
|
.uniq
|
2019-04-25 22:28:37 +08:00
|
|
|
repository_rows = RepositoryRow.left_outer_joins(:created_by)
|
|
|
|
.where(id: repository_row_ids)
|
2019-03-01 03:39:10 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
repository_rows
|
2018-03-06 23:32:39 +08:00
|
|
|
end
|
|
|
|
|
|
|
|
def build_conditions(params)
|
|
|
|
search_value = params[:search][:value]
|
2018-03-09 00:36:10 +08:00
|
|
|
order = params[:order].values.first
|
|
|
|
order_by_column = { column: order[:column].to_i,
|
|
|
|
dir: order[:dir] }
|
2018-03-06 23:32:39 +08:00
|
|
|
{ search_value: search_value, order_by_column: order_by_column }
|
|
|
|
end
|
|
|
|
|
|
|
|
def sortable_columns
|
2018-03-09 00:36:10 +08:00
|
|
|
array = [
|
2018-03-06 23:32:39 +08:00
|
|
|
'assigned',
|
2018-04-04 17:55:11 +08:00
|
|
|
'repository_rows.id',
|
2018-03-09 00:36:10 +08:00
|
|
|
'repository_rows.name',
|
|
|
|
'repository_rows.created_at',
|
|
|
|
'users.full_name'
|
2018-03-06 23:32:39 +08:00
|
|
|
]
|
2018-03-09 00:36:10 +08:00
|
|
|
@repository.repository_columns.count.times do
|
|
|
|
array << 'repository_cell.value'
|
|
|
|
end
|
|
|
|
array
|
|
|
|
end
|
|
|
|
|
|
|
|
def sort_rows(column_obj, records)
|
2018-03-16 19:27:19 +08:00
|
|
|
dir = %w(DESC ASC).find do |direction|
|
|
|
|
direction == column_obj[:dir].upcase
|
2018-03-09 21:43:12 +08:00
|
|
|
end || 'ASC'
|
2018-03-09 00:36:10 +08:00
|
|
|
column_index = column_obj[:column]
|
2018-04-18 21:53:48 +08:00
|
|
|
service = RepositoryTableStateService.new(@user, @repository)
|
|
|
|
col_order = service.load_state.state['ColReorder']
|
2018-03-09 00:36:10 +08:00
|
|
|
column_id = col_order[column_index].to_i
|
2018-03-06 23:32:39 +08:00
|
|
|
|
2018-03-09 00:36:10 +08:00
|
|
|
if sortable_columns[column_id - 1] == 'assigned'
|
2018-03-20 00:49:09 +08:00
|
|
|
return records if @my_module && @params[:assigned] == 'assigned'
|
2018-03-09 00:36:10 +08:00
|
|
|
if @my_module
|
|
|
|
# Depending on the sort, order nulls first or
|
|
|
|
# nulls last on repository_cells association
|
|
|
|
return records.joins(
|
|
|
|
"LEFT OUTER JOIN my_module_repository_rows ON
|
2018-03-09 21:43:12 +08:00
|
|
|
(repository_rows.id =
|
|
|
|
my_module_repository_rows.repository_row_id
|
|
|
|
AND (my_module_repository_rows.my_module_id =
|
|
|
|
#{@my_module.id}
|
|
|
|
OR my_module_repository_rows.id IS NULL))"
|
2018-03-09 00:36:10 +08:00
|
|
|
).order(
|
2018-03-09 21:43:12 +08:00
|
|
|
"my_module_repository_rows.id NULLS
|
|
|
|
#{sort_null_direction(dir)}"
|
2018-03-09 00:36:10 +08:00
|
|
|
)
|
|
|
|
else
|
|
|
|
return sort_assigned_records(records, dir)
|
|
|
|
end
|
|
|
|
elsif sortable_columns[column_id - 1] == 'repository_cell.value'
|
|
|
|
id = @mappings.key(column_id.to_s)
|
2019-06-06 23:28:59 +08:00
|
|
|
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,
|
|
|
|
#{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")
|
|
|
|
.order("values.value #{dir}")
|
2018-04-26 17:05:02 +08:00
|
|
|
elsif sortable_columns[column_id - 1] == 'users.full_name'
|
2019-04-19 21:24:13 +08:00
|
|
|
# We don't need join user table, because it already joined in fetch_row method
|
|
|
|
return records.order("users.full_name #{dir}")
|
2018-03-09 00:36:10 +08:00
|
|
|
else
|
2018-03-09 21:43:12 +08:00
|
|
|
return records.order(
|
|
|
|
"#{sortable_columns[column_id - 1]} #{dir}"
|
|
|
|
)
|
2018-03-09 00:36:10 +08:00
|
|
|
end
|
2018-03-06 23:32:39 +08:00
|
|
|
end
|
|
|
|
|
2018-03-09 00:36:10 +08:00
|
|
|
def sort_assigned_records(records, direction)
|
2018-03-09 21:43:12 +08:00
|
|
|
assigned = records.joins(:my_module_repository_rows)
|
|
|
|
.distinct
|
|
|
|
.pluck(:id)
|
2018-03-09 00:36:10 +08:00
|
|
|
unassigned = records.where.not(id: assigned).pluck(:id)
|
|
|
|
if direction == 'ASC'
|
|
|
|
ids = assigned + unassigned
|
|
|
|
elsif direction == 'DESC'
|
|
|
|
ids = unassigned + assigned
|
2018-03-06 23:32:39 +08:00
|
|
|
end
|
2018-03-09 00:36:10 +08:00
|
|
|
|
|
|
|
order_by_index = ActiveRecord::Base.send(
|
|
|
|
:sanitize_sql_array,
|
|
|
|
["position((',' || repository_rows.id || ',') in ?)",
|
|
|
|
ids.join(',') + ',']
|
|
|
|
)
|
|
|
|
records.order(order_by_index)
|
|
|
|
end
|
|
|
|
|
|
|
|
def sort_null_direction(val)
|
|
|
|
val == 'ASC' ? 'LAST' : 'FIRST'
|
|
|
|
end
|
|
|
|
|
2018-04-06 18:03:39 +08:00
|
|
|
def filter_by_asset_value(records, id, dir)
|
|
|
|
records.joins(
|
|
|
|
"LEFT OUTER JOIN (SELECT repository_cells.repository_row_id,
|
2019-07-09 16:28:15 +08:00
|
|
|
active_storage_blobs.filename AS value
|
2018-04-06 18:03:39 +08:00
|
|
|
FROM repository_cells
|
|
|
|
INNER JOIN repository_asset_values
|
|
|
|
ON repository_asset_values.id = repository_cells.value_id
|
|
|
|
INNER JOIN assets
|
|
|
|
ON repository_asset_values.asset_id = assets.id
|
2019-07-09 16:28:15 +08:00
|
|
|
INNER JOIN active_storage_attachments
|
|
|
|
ON active_storage_attachments.record_id = assets.id
|
|
|
|
AND active_storage_attachments.record_type = 'Asset'
|
|
|
|
AND active_storage_attachments.name = 'file'
|
|
|
|
INNER JOIN active_storage_blobs
|
|
|
|
ON active_storage_blobs.id = active_storage_attachments.blob_id
|
2018-04-06 18:03:39 +08:00
|
|
|
WHERE repository_cells.repository_column_id = #{id}) AS values
|
|
|
|
ON values.repository_row_id = repository_rows.id"
|
|
|
|
).order("values.value #{dir}")
|
|
|
|
end
|
|
|
|
|
2018-03-09 00:36:10 +08:00
|
|
|
def filter_by_text_value(records, id, dir)
|
2018-03-09 21:43:12 +08:00
|
|
|
records.joins(
|
2018-03-09 00:36:10 +08:00
|
|
|
"LEFT OUTER JOIN (SELECT repository_cells.repository_row_id,
|
|
|
|
repository_text_values.data AS value
|
|
|
|
FROM repository_cells
|
|
|
|
INNER JOIN repository_text_values
|
|
|
|
ON repository_text_values.id = repository_cells.value_id
|
|
|
|
WHERE repository_cells.repository_column_id = #{id}) AS values
|
|
|
|
ON values.repository_row_id = repository_rows.id"
|
|
|
|
).order("values.value #{dir}")
|
|
|
|
end
|
|
|
|
|
|
|
|
def filter_by_list_value(records, id, dir)
|
2018-03-09 21:43:12 +08:00
|
|
|
records.joins(
|
2018-03-09 00:36:10 +08:00
|
|
|
"LEFT OUTER JOIN (SELECT repository_cells.repository_row_id,
|
|
|
|
repository_list_items.data AS value
|
|
|
|
FROM repository_cells
|
|
|
|
INNER JOIN repository_list_values
|
|
|
|
ON repository_list_values.id = repository_cells.value_id
|
|
|
|
INNER JOIN repository_list_items
|
|
|
|
ON repository_list_values.repository_list_item_id =
|
|
|
|
repository_list_items.id
|
|
|
|
WHERE repository_cells.repository_column_id = #{id}) AS values
|
|
|
|
ON values.repository_row_id = repository_rows.id"
|
|
|
|
).order("values.value #{dir}")
|
|
|
|
end
|
2018-03-06 23:32:39 +08:00
|
|
|
end
|