scinote-web/app/controllers/navigator/base_controller.rb

244 lines
10 KiB
Ruby

# frozen_string_literal: true
module Navigator
class BaseController < ApplicationController
private
def project_serializer(project, archived)
{
id: project.code,
name: project.name,
url: experiments_path(project_id: project, view_mode: archived ? 'archived' : 'active'),
archived: project.archived,
type: :project,
has_children: project.has_children,
children_url: navigator_project_path(project),
disabled: project.disabled
}
end
def folder_serializer(folder, archived)
{
id: folder.code,
name: folder.name,
url: project_folder_path(folder, view_mode: archived ? 'archived' : 'active'),
archived: folder.archived,
type: :folder,
has_children: folder.try(:has_children),
children_url: navigator_project_folder_path(folder)
}
end
def experiment_serializer(experiment, archived)
{
id: experiment.code,
name: experiment.name,
url: my_modules_experiment_path(experiment, view_mode: archived ? 'archived' : 'active'),
archived: experiment.archived_branch?,
type: :experiment,
has_children: experiment.has_children,
children_url: navigator_experiment_path(experiment)
}
end
def my_module_serializer(my_module, archived)
{
id: my_module.code,
name: my_module.name,
type: :my_module,
url: protocols_my_module_path(my_module, view_mode: archived ? 'archived' : 'active'),
archived: my_module.archived_branch?,
has_children: false
}
end
def fetch_projects(object = nil, archived = false)
if object.is_a?(ProjectFolder)
folder = object
project = nil
else
folder = object&.project_folder
project = object
end
has_children_sql = if !archived
'SUM(CASE WHEN experiments.archived IS FALSE OR
(projects.archived IS TRUE AND experiments.id IS NOT NULL)
THEN 1 ELSE 0 END) > 0 AS has_children'
else
'SUM(CASE WHEN experiments.archived IS TRUE OR
my_modules.archived IS TRUE OR
(projects.archived IS TRUE AND experiments.id IS NOT NULL)
THEN 1 ELSE 0 END) > 0 AS has_children'
end
disabled_sql = 'SUM(CASE
WHEN project_user_roles IS NULL AND
project_user_group_roles IS NULL AND
project_team_roles IS NULL
THEN 0 ELSE 1 END) < 1 AS disabled'
projects =
if can_manage_team?(current_team)
# Team owners see all projects in the team
current_team.projects
else
current_team.projects.readable_by_user(current_user, current_team)
end
projects.where(project_folder_id: folder)
.with_children_viewable_by_user(current_user)
.joins("LEFT OUTER JOIN user_assignments project_user_assignments
ON project_user_assignments.assignable_type = 'Project'
AND project_user_assignments.assignable_id = projects.id
AND project_user_assignments.user_id = #{current_user.id}
LEFT OUTER JOIN user_roles project_user_roles
ON project_user_roles.id = project_user_assignments.user_role_id
AND project_user_roles.permissions @> ARRAY['#{ProjectPermissions::READ}']::varchar[]
LEFT OUTER JOIN user_group_assignments project_user_group_assignments
ON project_user_group_assignments.assignable_type = 'Project'
AND project_user_group_assignments.assignable_id = projects.id
AND project_user_group_assignments.user_group_id IN (
SELECT user_group_memberships.user_group_id FROM user_group_memberships
WHERE user_group_memberships.user_id = #{current_user.id}
)
LEFT OUTER JOIN user_roles project_user_group_roles
ON project_user_group_roles.id = project_user_group_assignments.user_role_id
AND project_user_group_roles.permissions @> ARRAY['#{ProjectPermissions::READ}']::varchar[]
LEFT OUTER JOIN team_assignments project_team_assignments
ON project_team_assignments.assignable_type = 'Project'
AND project_team_assignments.assignable_id = projects.id
AND project_team_assignments.team_id = #{current_team.id}
LEFT OUTER JOIN user_roles project_team_roles
ON project_team_roles.id = project_team_assignments.user_role_id
AND project_team_roles.permissions @> ARRAY['#{ProjectPermissions::READ}']::varchar[]
")
.where('projects.archived = :archived OR
(
(
experiments.archived = :archived OR
my_modules.archived = :archived
) AND
:archived IS TRUE
) OR
projects.id = :project_id',
archived: archived,
project_id: project&.id || -1)
.select(
'projects.id',
'projects.name',
'projects.archived',
disabled_sql,
has_children_sql
).group('projects.id')
end
def fetch_project_folders(object = nil, archived = false)
folder = if object.is_a?(ProjectFolder)
object
else
object&.project_folder
end
has_children_sql = 'SUM(CASE WHEN visible_projects.id IS NOT NULL OR project_folders_project_folders.id IS NOT NULL
THEN 1 ELSE 0 END) > 0'
visible_projects =
if can_manage_team?(current_team)
# Team owners see all projects in the team
current_team.projects
else
current_team.projects.readable_by_user(current_user, current_team)
end
current_team.project_folders.where(parent_folder: folder)
.left_outer_joins(:projects, project_folders: {})
.joins(
"LEFT OUTER JOIN (#{visible_projects.where(archived: archived).to_sql}) " \
"visible_projects ON visible_projects.project_folder_id = project_folders.id"
)
.select(
'project_folders.id',
'project_folders.name',
'project_folders.archived',
"#{has_children_sql} AS has_children"
).group('project_folders.id')
.having('project_folders.archived = :archived', archived: archived)
end
def fetch_experiments(object, archived = false)
if object.is_a?(Project)
project = object
experiment = nil
else
project = object.project
experiment = object
end
has_children_sql = if !archived
'SUM(CASE WHEN my_modules.archived IS FALSE OR
(experiments.archived IS TRUE AND my_modules.id IS NOT NULL)
THEN 1 ELSE 0 END) > 0 AS has_children'
elsif project.archived?
'COUNT(my_modules.id) > 0 AS has_children'
else
'SUM(CASE WHEN my_modules.archived IS TRUE OR
(experiments.archived IS TRUE AND my_modules.id IS NOT NULL)
THEN 1 ELSE 0 END) > 0 AS has_children'
end
experiments = project.experiments
.readable_by_user(current_user, current_team)
.with_children_viewable_by_user(current_user)
.select(
'experiments.id',
'experiments.name',
'experiments.archived',
'experiments.project_id',
has_children_sql
).group('experiments.id')
unless project.archived?
experiments = experiments.where('
experiments.archived = :archived OR
my_modules.archived = :archived AND
:archived IS TRUE OR
experiments.id = :experiment_id
', archived: archived, experiment_id: experiment&.id || -1)
end
experiments
end
def fetch_my_modules(experiment, archived = false)
my_modules = experiment.my_modules.readable_by_user(current_user, current_team)
my_modules = my_modules.where(archived: archived) unless experiment.archived_branch?
my_modules
end
def build_folder_tree(folder, children)
archived = params[:archived] == 'true'
tree = fetch_projects(folder.parent_folder, archived).map { |i| project_serializer(i, archived) } +
fetch_project_folders(folder.parent_folder, archived).map { |i| folder_serializer(i, archived) }
# Tree will not contain folder when folder archived state and params archived values are contradictory
tree.find { |i| i[:id] == folder.code } || (tree << folder_serializer(folder, archived))
tree.find { |i| i[:id] == folder.code }[:children] = children
tree = build_folder_tree(folder.parent_folder, tree) if folder.parent_folder.present?
tree
end
def project_level_branch(object = nil)
archived = params[:archived] == 'true'
fetch_projects(object, archived)
.map { |i| project_serializer(i, archived) } +
fetch_project_folders(object, archived)
.map { |i| folder_serializer(i, archived) }
end
def experiment_level_branch(object)
archived = params[:archived] == 'true'
fetch_experiments(object, archived)
.map { |i| experiment_serializer(i, archived) }
end
def my_module_level_branch(experiment)
archived = params[:archived] == 'true'
fetch_my_modules(experiment, archived)
.map { |i| my_module_serializer(i, archived) }
end
end
end