Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 15 additions & 18 deletions app/controllers/header/projects_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -141,31 +141,28 @@ def user_project_favorites
# Builds a nested structure from a flat, lft-ordered list of projects.
# Each level is sorted alphabetically by project name.
def build_tree(projects)
nodes = projects.index_by(&:id).transform_values do |p|
{ project: p, children: [], matches_query: @matching_ids.nil? || @matching_ids.include?(p.id) }
end

roots = []
projects.each do |project|
node = nodes[project.id]
parent = nodes[project.parent_id]
nodes = Project.build_projects_hierarchy(projects)
mark_query_matches(nodes)
sort_nodes(nodes)
end
Comment on lines 143 to +147

if parent
parent[:children] << node
else
roots << node
end
def mark_query_matches(nodes)
nodes.each do |node|
node[:matches_query] = @matching_ids.nil? || @matching_ids.include?(node[:project].id)
mark_query_matches(node[:children])
end

sort_nodes(roots)
end

def sort_nodes(nodes)
nodes.sort_by { |n| n[:project].name.downcase }.each do |node|
node[:children] = sort_nodes(node[:children])
node[:expanded] = filter_mode == "favorited" || node[:children].any? do |c|
c[:project].id == @current_project_id || c[:expanded]
end
node[:expanded] = expanded_node?(node)
end
end

def expanded_node?(node)
filter_mode == "favorited" || node[:children].any? do |child|
child[:project].id == @current_project_id || child[:expanded]
end
end
end
21 changes: 21 additions & 0 deletions spec/controllers/header/projects_controller_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,27 @@
expect(response).to render_template(layout: false)
end

context "when an invisible project is between two visible projects" do
shared_let(:invisible_project) { create(:private_project, name: "Invisible", parent: parent_project) }
shared_let(:visible_grandchild) { create(:project, name: "Visible Grandchild", parent: invisible_project) }

before do
create(:member, principal: current_user, project: visible_grandchild, roles: [role])
end

it "nests the grandchild below its nearest visible ancestor", :aggregate_failures do
make_request

tree = assigns(:tree)
parent_node = tree.find { |node| node[:project] == parent_project }

expect(assigns(:projects)).to include(visible_grandchild)
expect(assigns(:projects)).not_to include(invisible_project)
expect(tree.pluck(:project)).not_to include(visible_grandchild)
expect(parent_node[:children].pluck(:project)).to include(visible_grandchild)
end
end

context "when searching by query" do
subject(:make_request) { get :index, params: { query: "Beta" } }

Expand Down
Loading