mirror of
https://github.com/scinote-eln/scinote-web.git
synced 2025-11-01 17:17:04 +08:00
Optimize cells preloads for inventory datatables, improve permission checking for columns [SCI-11134] (#7927)
This commit is contained in:
parent
a24726ec39
commit
3d32296fc2
16 changed files with 83 additions and 82 deletions
|
|
@ -15,7 +15,14 @@ class MyModuleRepositoriesController < ApplicationController
|
|||
@draw = params[:draw].to_i
|
||||
per_page = params[:length].to_i < 1 ? Constants::REPOSITORY_DEFAULT_PAGE_SIZE : params[:length].to_i
|
||||
page = (params[:start].to_i / per_page) + 1
|
||||
datatable_service = RepositoryDatatableService.new(@repository, params, current_user, @my_module)
|
||||
if params[:simple_view]
|
||||
rows_view = 'repository_rows/simple_view_index'
|
||||
preload_cells = false
|
||||
else
|
||||
rows_view = 'repository_rows/index'
|
||||
preload_cells = true
|
||||
end
|
||||
datatable_service = RepositoryDatatableService.new(@repository, params, current_user, @my_module, preload_cells: preload_cells)
|
||||
|
||||
@datatable_params = {
|
||||
view_mode: params[:view_mode],
|
||||
|
|
@ -26,21 +33,9 @@ class MyModuleRepositoriesController < ApplicationController
|
|||
|
||||
@all_rows_count = datatable_service.all_count
|
||||
@columns_mappings = datatable_service.mappings
|
||||
|
||||
if params[:simple_view]
|
||||
repository_rows = datatable_service.repository_rows
|
||||
rows_view = 'repository_rows/simple_view_index'
|
||||
else
|
||||
repository_rows = datatable_service.repository_rows
|
||||
.preload(:repository_columns,
|
||||
:created_by,
|
||||
:archived_by,
|
||||
:last_modified_by,
|
||||
repository_cells: { value: @repository.cell_preload_includes })
|
||||
rows_view = 'repository_rows/index'
|
||||
end
|
||||
repository_rows = datatable_service.repository_rows
|
||||
@repository_rows = repository_rows.page(page).per(per_page)
|
||||
|
||||
@filtered_rows_count = @repository_rows.load.take&.filtered_count || 0
|
||||
render rows_view
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -16,20 +16,16 @@ class MyModuleRepositorySnapshotsController < ApplicationController
|
|||
|
||||
@all_rows_count = datatable_service.all_count
|
||||
@columns_mappings = datatable_service.mappings
|
||||
repository_rows = datatable_service.repository_rows
|
||||
|
||||
if params[:simple_view]
|
||||
repository_rows = datatable_service.repository_rows
|
||||
@repository = @repository_snapshot
|
||||
rows_view = 'repository_rows/simple_view_index'
|
||||
else
|
||||
repository_rows =
|
||||
datatable_service.repository_rows
|
||||
.preload(:repository_columns,
|
||||
:created_by,
|
||||
repository_cells: { value: @repository_snapshot.cell_preload_includes })
|
||||
rows_view = 'repository_rows/snapshot_index'
|
||||
end
|
||||
@repository_rows = repository_rows.page(page).per(per_page)
|
||||
|
||||
@filtered_rows_count = @repository_rows.load.take&.filtered_count || 0
|
||||
render rows_view
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ class MyModuleShareableLinksController < ApplicationController
|
|||
@draw = params[:draw].to_i
|
||||
per_page = params[:length].to_i < 1 ? Constants::REPOSITORY_DEFAULT_PAGE_SIZE : params[:length].to_i
|
||||
page = (params[:start].to_i / per_page) + 1
|
||||
datatable_service = RepositoryDatatableService.new(@repository, params, nil, @my_module)
|
||||
datatable_service = RepositoryDatatableService.new(@repository, params, nil, @my_module, preload_cells: false)
|
||||
|
||||
@datatable_params = {
|
||||
view_mode: params[:view_mode],
|
||||
|
|
@ -76,6 +76,7 @@ class MyModuleShareableLinksController < ApplicationController
|
|||
@columns_mappings = datatable_service.mappings
|
||||
|
||||
@repository_rows = datatable_service.repository_rows.page(page).per(per_page)
|
||||
@filtered_rows_count = @repository_rows.load.take&.filtered_count || 0
|
||||
|
||||
render 'repository_rows/simple_view_index'
|
||||
end
|
||||
|
|
@ -84,13 +85,14 @@ class MyModuleShareableLinksController < ApplicationController
|
|||
@draw = params[:draw].to_i
|
||||
per_page = params[:length].to_i < 1 ? Constants::REPOSITORY_DEFAULT_PAGE_SIZE : params[:length].to_i
|
||||
page = (params[:start].to_i / per_page) + 1
|
||||
datatable_service = RepositorySnapshotDatatableService.new(@repository_snapshot, params, nil, @my_module)
|
||||
datatable_service = RepositorySnapshotDatatableService.new(@repository_snapshot, params, nil, @my_module, preload_cells: false)
|
||||
|
||||
@all_rows_count = datatable_service.all_count
|
||||
@columns_mappings = datatable_service.mappings
|
||||
|
||||
@repository = @repository_snapshot
|
||||
@repository_rows = datatable_service.repository_rows.page(page).per(per_page)
|
||||
@filtered_rows_count = @repository_rows.load.take&.filtered_count || 0
|
||||
|
||||
render 'repository_rows/simple_view_index'
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,12 +28,10 @@ class RepositoryRowsController < ApplicationController
|
|||
|
||||
@all_rows_count = datatable_service.all_count
|
||||
@columns_mappings = datatable_service.mappings
|
||||
@repository_rows = datatable_service.repository_rows
|
||||
.preload(:repository_columns, repository_cells: { value: @repository.cell_preload_includes })
|
||||
.page(page)
|
||||
.per(per_page)
|
||||
|
||||
@repository_rows = @repository_rows.where(archived: params[:archived]) unless @repository.archived?
|
||||
repository_rows = datatable_service.repository_rows
|
||||
repository_rows = repository_rows.where(archived: params[:archived]) unless @repository.archived?
|
||||
@repository_rows = repository_rows.page(page).per(per_page)
|
||||
@filtered_rows_count = @repository_rows.load.take&.filtered_count || 0
|
||||
rescue RepositoryFilters::ColumnNotFoundException
|
||||
render json: { custom_error: I18n.t('repositories.show.repository_filter.errors.column_not_found') }
|
||||
rescue RepositoryFilters::ValueNotFoundException
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ module RepositoryDatatableHelper
|
|||
include Rails.application.routes.url_helpers
|
||||
|
||||
def prepare_row_columns(repository_rows, repository, columns_mappings, team, options = {})
|
||||
# repository_rows collection is already preloaded in controllers, do not modify scopes or query params
|
||||
# otherwise it will result in duplicated SQL queries
|
||||
has_stock_management = repository.has_stock_management?
|
||||
stock_management_column_exists = repository.repository_columns.stock_type.exists?
|
||||
repository_row_connections_enabled = Repository.repository_row_connections_enabled?
|
||||
reminders_enabled = Repository.reminders_enabled?
|
||||
repository_rows = reminders_enabled ? with_reminders_status(repository_rows, repository) : repository_rows
|
||||
stock_managable = has_stock_management && !options[:disable_stock_management] &&
|
||||
can_manage_repository_stock?(repository) &&
|
||||
!repository.is_a?(SoftLockedRepository)
|
||||
|
|
@ -97,9 +98,10 @@ module RepositoryDatatableHelper
|
|||
end
|
||||
|
||||
def prepare_simple_view_row_columns(repository_rows, repository, my_module, options = {})
|
||||
# repository_rows collection is already preloaded in controllers, do not modify scopes or query params
|
||||
# otherwise it will result in duplicated SQL queries
|
||||
has_stock_management = repository.has_stock_management?
|
||||
reminders_enabled = !options[:disable_reminders] && Repository.reminders_enabled?
|
||||
repository_rows = reminders_enabled ? with_reminders_status(repository_rows, repository) : repository_rows
|
||||
# Always disabled in a simple view
|
||||
stock_managable = false
|
||||
stock_consumption_permitted = has_stock_management && stock_consumption_permitted?(repository, my_module)
|
||||
|
|
@ -304,35 +306,6 @@ module RepositoryDatatableHelper
|
|||
''
|
||||
end
|
||||
|
||||
def with_reminders_status(repository_rows, repository)
|
||||
# don't load reminders for archived repositories or snapshots
|
||||
if repository.archived? || repository.is_a?(RepositorySnapshot)
|
||||
return repository_rows.select('FALSE AS has_active_stock_reminders')
|
||||
.select('FALSE AS has_active_datetime_reminders')
|
||||
end
|
||||
|
||||
repository_cells = RepositoryCell.joins(
|
||||
"INNER JOIN repository_columns ON repository_columns.id = repository_cells.repository_column_id " \
|
||||
"AND repository_columns.repository_id = #{repository.id}"
|
||||
)
|
||||
|
||||
repository_rows
|
||||
.joins(
|
||||
"LEFT OUTER JOIN (#{RepositoryCell.stock_reminder_repository_cells_scope(repository_cells, current_user)
|
||||
.select(:id, :repository_row_id).to_sql}) " \
|
||||
"AS repository_cells_with_active_stock_reminders " \
|
||||
"ON repository_cells_with_active_stock_reminders.repository_row_id = repository_rows.id"
|
||||
)
|
||||
.joins(
|
||||
"LEFT OUTER JOIN (#{RepositoryCell.date_time_reminder_repository_cells_scope(repository_cells, current_user)
|
||||
.select(:id, :repository_row_id).to_sql}) " \
|
||||
"AS repository_cells_with_active_datetime_reminders " \
|
||||
"ON repository_cells_with_active_datetime_reminders.repository_row_id = repository_rows.id"
|
||||
)
|
||||
.select('COUNT(repository_cells_with_active_stock_reminders.id) > 0 AS has_active_stock_reminders')
|
||||
.select('COUNT(repository_cells_with_active_datetime_reminders.id) > 0 AS has_active_datetime_reminders')
|
||||
end
|
||||
|
||||
def stock_consumption_permitted?(repository, my_module)
|
||||
return false unless repository.is_a?(Repository) && current_user
|
||||
|
||||
|
|
|
|||
|
|
@ -171,6 +171,35 @@ class RepositoryRow < ApplicationRecord
|
|||
.update_all(created_by_id: new_owner.id)
|
||||
end
|
||||
|
||||
def self.with_reminders_status(repository_rows, repository, user)
|
||||
# don't load reminders for archived repositories or snapshots
|
||||
if repository.archived? || repository.is_a?(RepositorySnapshot)
|
||||
return repository_rows.select('FALSE AS has_active_stock_reminders')
|
||||
.select('FALSE AS has_active_datetime_reminders')
|
||||
end
|
||||
|
||||
repository_cells = RepositoryCell.joins(
|
||||
"INNER JOIN repository_columns ON repository_columns.id = repository_cells.repository_column_id " \
|
||||
"AND repository_columns.repository_id = #{repository.id}"
|
||||
)
|
||||
|
||||
repository_rows
|
||||
.joins(
|
||||
"LEFT OUTER JOIN (#{RepositoryCell.stock_reminder_repository_cells_scope(repository_cells, user)
|
||||
.select(:id, :repository_row_id).to_sql}) " \
|
||||
"AS repository_cells_with_active_stock_reminders " \
|
||||
"ON repository_cells_with_active_stock_reminders.repository_row_id = repository_rows.id"
|
||||
)
|
||||
.joins(
|
||||
"LEFT OUTER JOIN (#{RepositoryCell.date_time_reminder_repository_cells_scope(repository_cells, user)
|
||||
.select(:id, :repository_row_id).to_sql}) " \
|
||||
"AS repository_cells_with_active_datetime_reminders " \
|
||||
"ON repository_cells_with_active_datetime_reminders.repository_row_id = repository_rows.id"
|
||||
)
|
||||
.select('COUNT(repository_cells_with_active_stock_reminders.id) > 0 AS has_active_stock_reminders')
|
||||
.select('COUNT(repository_cells_with_active_datetime_reminders.id) > 0 AS has_active_datetime_reminders')
|
||||
end
|
||||
|
||||
def editable?
|
||||
true
|
||||
end
|
||||
|
|
|
|||
|
|
@ -104,6 +104,10 @@ Canaid::Permissions.register_for(Repository) do
|
|||
repository.permission_granted?(user, RepositoryPermissions::COLUMNS_CREATE)
|
||||
end
|
||||
|
||||
can :manage_repository_columns do |user, repository|
|
||||
repository.repository_snapshots.provisioning.none? && can_create_repository_columns?(user, repository)
|
||||
end
|
||||
|
||||
# repository: create/update/delete filters
|
||||
can :manage_repository_filters do |user, repository|
|
||||
repository.permission_granted?(user, RepositoryPermissions::FILTERS_MANAGE)
|
||||
|
|
@ -113,3 +117,11 @@ Canaid::Permissions.register_for(Repository) do
|
|||
RepositoryBase.stock_management_enabled? && can_manage_repository_rows?(user, repository)
|
||||
end
|
||||
end
|
||||
|
||||
Canaid::Permissions.register_for(RepositoryColumn) do
|
||||
# repository: update/delete field
|
||||
# Tested in scope of RepositoryPermissions spec
|
||||
can :manage_repository_column do |user, repository_column|
|
||||
repository_column.repository.repository_snapshots.provisioning.none? && can_create_repository_columns?(user, repository_column.repository)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,12 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
Canaid::Permissions.register_for(RepositoryColumn) do
|
||||
# repository: update/delete field
|
||||
# Tested in scope of RepositoryPermissions spec
|
||||
can :manage_repository_column do |user, repository_column|
|
||||
managable = repository_column.repository.repository_snapshots.provisioning.none? &&
|
||||
can_create_repository_columns?(user, repository_column.repository)
|
||||
|
||||
managable
|
||||
end
|
||||
end
|
||||
|
|
@ -13,7 +13,7 @@ module Reports::Docx::DrawMyModuleRepository
|
|||
|
||||
return false unless repository_data[:rows].any? && can_read_repository?(@user, repository)
|
||||
|
||||
table = prepare_row_columns(repository_data, my_module, repository)
|
||||
table = prepare_row_columns_for_docx(repository_data, my_module, repository)
|
||||
|
||||
@docx.p
|
||||
@docx.p I18n.t('projects.reports.elements.module_repository.name',
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ module Reports::Docx::RepositoryHelper
|
|||
include InputSanitizeHelper
|
||||
include ActionView::Helpers::NumberHelper
|
||||
|
||||
def prepare_row_columns(repository_data, my_module, repository)
|
||||
def prepare_row_columns_for_docx(repository_data, my_module, repository)
|
||||
result = [repository_data[:headers]]
|
||||
repository_data[:rows].each do |record|
|
||||
row = []
|
||||
|
|
|
|||
|
|
@ -13,10 +13,11 @@ class RepositoryDatatableService
|
|||
PREDEFINED_COLUMNS = %w(row_id row_name added_on added_by archived_on archived_by
|
||||
assigned relationships updated_on updated_by).freeze
|
||||
|
||||
def initialize(repository, params, user, my_module = nil)
|
||||
def initialize(repository, params, user, my_module = nil, preload_cells: true)
|
||||
@repository = repository
|
||||
@user = user
|
||||
@my_module = my_module
|
||||
@preload_cells = preload_cells
|
||||
@params = params
|
||||
@assigned_view = @params[:assigned].in?(%w(assigned assigned_simple))
|
||||
@sortable_columns = build_sortable_columns
|
||||
|
|
@ -77,6 +78,8 @@ class RepositoryDatatableService
|
|||
.group('current_my_module_repository_rows.id')
|
||||
end
|
||||
end
|
||||
|
||||
repository_rows = RepositoryRow.with_reminders_status(repository_rows, @repository, @user) if Repository.reminders_enabled?
|
||||
repository_rows = repository_rows
|
||||
.left_outer_joins(my_module_repository_rows: { my_module: :experiment })
|
||||
.select('COUNT(DISTINCT all_my_module_repository_rows.id) AS "assigned_my_modules_count"')
|
||||
|
|
@ -85,6 +88,8 @@ class RepositoryDatatableService
|
|||
.select('COALESCE(parent_connections_count, 0) + COALESCE(child_connections_count, 0)
|
||||
AS "relationships_count"')
|
||||
repository_rows = repository_rows.preload(Extends::REPOSITORY_ROWS_PRELOAD_RELATIONS)
|
||||
repository_rows = repository_rows.preload(:repository_columns, repository_cells: { value: @repository.cell_preload_includes }) if @preload_cells
|
||||
repository_rows = repository_rows.preload(:repository_stock_cell, :repository_stock_value) if @repository.has_stock_management?
|
||||
|
||||
sort_rows(order_by_column, repository_rows)
|
||||
end
|
||||
|
|
@ -101,7 +106,7 @@ class RepositoryDatatableService
|
|||
.where(my_module_repository_rows: { my_module_id: @my_module })
|
||||
.count
|
||||
else
|
||||
repository_rows.count
|
||||
@repository.repository_rows_count
|
||||
end
|
||||
|
||||
repository_rows = repository_rows.where(external_id: @params[:external_ids]) if @params[:external_ids]
|
||||
|
|
@ -621,7 +626,7 @@ class RepositoryDatatableService
|
|||
.group('values.value')
|
||||
.order("values.value #{dir}")
|
||||
when 'users.full_name'
|
||||
records.group('users.full_name').order("users.full_name #{dir}")
|
||||
records.group('created_by.full_name').order("created_by.full_name #{dir}")
|
||||
when 'consumed_stock'
|
||||
records.order("#{@sortable_columns[column_id - 1]} #{dir}")
|
||||
when 'relationships'
|
||||
|
|
|
|||
|
|
@ -18,6 +18,8 @@ class RepositorySnapshotDatatableService < RepositoryDatatableService
|
|||
order_by_column = { column: order_params[:column].to_i, dir: order_params[:dir] }
|
||||
|
||||
repository_rows = fetch_rows(search_value).preload(Extends::REPOSITORY_ROWS_PRELOAD_RELATIONS)
|
||||
repository_rows = repository_rows.preload(:repository_columns, repository_cells: { value: @repository.cell_preload_includes }) if @preload_cells
|
||||
repository_rows = repository_rows.preload(:repository_stock_cell, :repository_stock_value) if @repository.has_stock_management?
|
||||
|
||||
sort_rows(order_by_column, repository_rows)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -48,6 +48,7 @@
|
|||
<% if @repository.is_a?(LinkedRepository) %>
|
||||
<th id="row-external-id"><%= t('repositories.table.external_id') %></th>
|
||||
<% end %>
|
||||
<% columns_editable = can_manage_repository_columns?(@repository) && !repository.is_a?(SoftLockedRepository) %>
|
||||
<% repository.repository_columns.order(:id).each do |column| %>
|
||||
<th
|
||||
class="repository-column <%= 'row-stock item-stock' if column.data_type == 'RepositoryStockValue' %>"
|
||||
|
|
@ -55,7 +56,7 @@
|
|||
data-type="<%= column.data_type %>"
|
||||
data-edit-column-url="<%= edit_repository_repository_column_path(repository, column) %>"
|
||||
data-destroy-column-url="<%= repository_columns_destroy_html_path(repository, column) %>"
|
||||
data-editable-row="<%= can_manage_repository_column?(column) && !repository.is_a?(SoftLockedRepository) %>"
|
||||
data-editable-row="<%= columns_editable %>"
|
||||
<% column.metadata.each do |k, v| %>
|
||||
<%= "data-metadata-#{k}=#{v}" %>
|
||||
<% end %>
|
||||
|
|
|
|||
|
|
@ -8,5 +8,5 @@ json.data do
|
|||
@repository.team,
|
||||
(@datatable_params || {}).merge(omit_editable: true))
|
||||
end
|
||||
json.recordsFiltered @repository_rows.first ? @repository_rows.first.filtered_count : 0
|
||||
json.recordsFiltered @filtered_rows_count
|
||||
json.recordsTotal @all_rows_count
|
||||
|
|
|
|||
|
|
@ -6,5 +6,5 @@ json.data do
|
|||
@repository_rows, @repository, @my_module, @datatable_params || {}
|
||||
)
|
||||
end
|
||||
json.recordsFiltered @repository_rows.first ? @repository_rows.first.filtered_count : 0
|
||||
json.recordsFiltered @filtered_rows_count
|
||||
json.recordsTotal @all_rows_count
|
||||
|
|
|
|||
|
|
@ -7,5 +7,5 @@ json.data do
|
|||
@repository_snapshot.team,
|
||||
@repository_snapshot)
|
||||
end
|
||||
json.recordsFiltered @repository_rows.first ? @repository_rows.first.filtered_count : 0
|
||||
json.recordsFiltered @filtered_rows_count
|
||||
json.recordsTotal @all_rows_count
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue