mirror of
				https://github.com/scinote-eln/scinote-web.git
				synced 2025-10-31 16:49:40 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			244 lines
		
	
	
	
		
			10 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			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
 |