Implement project search with grouping by folder [SCI-5207]

This commit is contained in:
Oleksii Kriuchykhin 2020-11-16 20:47:58 +01:00
parent dc62e2780a
commit 0de237cece
4 changed files with 74 additions and 14 deletions

View file

@ -28,15 +28,25 @@ class ProjectsController < ApplicationController
current_folder = current_team.project_folders.find_by(id: params[:project_folder_id])
end
overview_service = ProjectsOverviewService.new(current_team, current_user, current_folder, params)
render json: {
html: render_to_string(
partial: 'projects/index/team_projects.html.erb',
locals: {
projects: overview_service.project_cards,
project_folders: overview_service.project_folder_cards
}
)
}
if params[:search].present?
render json: {
html: render_to_string(
partial: 'projects/index/team_projects_grouped_by_folder.html.erb',
locals: { projects_by_folder: overview_service.grouped_by_folder_project_cards }
)
}
else
render json: {
html: render_to_string(
partial: 'projects/index/team_projects.html.erb',
locals: {
projects: overview_service.project_cards,
project_folders: overview_service.project_folder_cards
}
)
}
end
end
def index_dt

View file

@ -35,6 +35,30 @@ class ProjectFolder < ApplicationRecord
end
end
def self.inner_folders(team, project_folder = nil)
entry_point_condition = project_folder ? 'parent_folder_id = ?' : 'parent_folder_id IS NULL'
inner_folders_sql =
"WITH RECURSIVE inner_project_folders(id, selected_folders_ids) AS (
SELECT id, ARRAY[id]
FROM project_folders
WHERE team_id = ? AND #{entry_point_condition}
UNION ALL
SELECT project_folders.id, selected_folders_ids || project_folders.id
FROM inner_project_folders
JOIN project_folders ON project_folders.parent_folder_id = inner_project_folders.id
WHERE NOT project_folders.id = ANY(selected_folders_ids)
)
SELECT id FROM inner_project_folders ORDER BY selected_folders_ids".gsub(/\n|\t/, ' ').gsub(/ +/, ' ')
new_query =
if project_folder.present?
where("project_folders.id IN (#{inner_folders_sql})", team.id, project_folder.id)
else
where("project_folders.id IN (#{inner_folders_sql})", team.id)
end
new_query.order(:parent_folder_id)
end
def inner_projects
project_folders.map do |inner_folder|
projects + inner_folder.inner_projects

View file

@ -15,11 +15,30 @@ class ProjectsOverviewService
end
def project_cards
sort_records(filter_project_records(fetch_project_records))
sort_records(
filter_project_records(
fetch_project_records.where(project_folder: @current_folder)
)
)
end
def project_folder_cards
sort_records(filter_project_folder_records(fetch_project_folder_records))
sort_records(
filter_project_folder_records(
fetch_project_folder_records.where(parent_folder: @current_folder)
)
)
end
def grouped_by_folder_project_cards
project_records =
if @current_folder.present?
fetch_project_records.where(project_folder: ProjectFolder.inner_folders(@team, @current_folder))
else
fetch_project_records
end
project_records = project_records.includes(:project_folder)
sort_records(filter_project_records(project_records)).group_by(&:project_folder)
end
def projects_datatable
@ -73,8 +92,6 @@ class ProjectsOverviewService
'LEFT OUTER JOIN user_projects ON user_projects.project_id = projects.id'
).left_outer_joins(:project_comments)
projects = projects.where(project_folder: @current_folder)
# Only admins see all projects of the team
unless @user.is_admin_of_team?(@team)
projects = projects.where(
@ -92,7 +109,6 @@ class ProjectsOverviewService
def fetch_project_folder_records
project_folders = @team.project_folders.left_outer_joins(:projects, :project_folders)
project_folders = project_folders.where(parent_folder: @current_folder)
project_folders.select('project_folders.*')
.select('COUNT(DISTINCT projects.id) AS projects_count')
.select('COUNT(DISTINCT project_folders.id) AS folders_count')

View file

@ -0,0 +1,10 @@
<% projects_by_folder.each do |folder, projects| %>
<% if folder.present? %>
<h3><%= folder.name %></h3>
<% end %>
<% projects.each do |project| %>
<% cache [current_user, project] do %>
<%= render partial: 'projects/index/project_card', locals: { project: project } %>
<% end %>
<% end %>
<% end %>