diff options
author | Bob Van Landuyt <bob@vanlanduyt.co> | 2017-09-08 19:22:33 +0200 |
---|---|---|
committer | Bob Van Landuyt <bob@vanlanduyt.co> | 2017-10-04 22:49:41 +0200 |
commit | 8f6dac4991ba7f5771a24175784f19dc1bbd4103 (patch) | |
tree | 5d4f4c06f6bd56db03474dd5d97002d82331a91e | |
parent | 518216c0627cb6c4b3db62f10877b44d0e912ddb (diff) | |
download | gitlab-ce-8f6dac4991ba7f5771a24175784f19dc1bbd4103.tar.gz |
Allow filtering children for a group
When fetching children for a group with a filter, we will search all
nested groups for results and render them in an expanded tree
-rw-r--r-- | app/controllers/groups_controller.rb | 10 | ||||
-rw-r--r-- | app/serializers/group_child_serializer.rb | 14 | ||||
-rw-r--r-- | spec/controllers/groups_controller_spec.rb | 30 | ||||
-rw-r--r-- | spec/serializers/group_child_serializer_spec.rb | 47 |
4 files changed, 89 insertions, 12 deletions
diff --git a/app/controllers/groups_controller.rb b/app/controllers/groups_controller.rb index a714f2cc7b0..575d5476867 100644 --- a/app/controllers/groups_controller.rb +++ b/app/controllers/groups_controller.rb @@ -74,11 +74,11 @@ class GroupsController < Groups::ApplicationController respond_to do |format| format.json do - render json: GroupChildSerializer - .new(current_user: current_user) - .with_pagination(request, response) - .hierarchy_base(parent, open_hierarchy: filter[:filter].present) - .represent(@children) + serializer = GroupChildSerializer + .new(current_user: current_user) + .with_pagination(request, response) + serializer.expand_hierarchy(parent) if params[:filter].present? + render json: serializer.represent(@children) end end end diff --git a/app/serializers/group_child_serializer.rb b/app/serializers/group_child_serializer.rb index ed84c3ae1d7..363f0c9b3d8 100644 --- a/app/serializers/group_child_serializer.rb +++ b/app/serializers/group_child_serializer.rb @@ -18,11 +18,14 @@ class GroupChildSerializer < BaseSerializer end end + protected + def represent_hierarchies(children, opts) if children.is_a?(GroupHierarchy) - represent_hierarchy(children.hierarchy(hierarchy_root), opts) + represent_hierarchy(children.hierarchy(hierarchy_root), opts).first else - children.map { |child| represent_hierarchy(child.hierarchy(hierarchy_root), opts) } + hierarchies = Array.wrap(GroupHierarchy.merge_hierarchies(children, hierarchy_root)) + hierarchies.map { |hierarchy| represent_hierarchy(hierarchy, opts) }.flatten end end @@ -30,9 +33,10 @@ class GroupChildSerializer < BaseSerializer serializer = self.class.new(parameters) result = if hierarchy.is_a?(Hash) - parent = hierarchy.keys.first - serializer.represent(parent, opts) - .merge(children: [serializer.represent_hierarchy(hierarchy[parent], opts)]) + hierarchy.map do |parent, children| + serializer.represent(parent, opts) + .merge(children: Array.wrap(serializer.represent_hierarchy(children, opts))) + end else serializer.represent(hierarchy, opts) end diff --git a/spec/controllers/groups_controller_spec.rb b/spec/controllers/groups_controller_spec.rb index 9b4654dc3e4..9cddb538a59 100644 --- a/spec/controllers/groups_controller_spec.rb +++ b/spec/controllers/groups_controller_spec.rb @@ -224,6 +224,36 @@ describe GroupsController do expect(assigns(:children)).to contain_exactly(public_subgroup, public_project) end end + + context 'filtering children' do + def get_filtered_list + get :children, id: group.to_param, filter: 'filter', format: :json + end + + it 'expands the tree for matching projects' do + project = create(:project, :public, namespace: public_subgroup, name: 'filterme') + + get_filtered_list + + group_json = json_response.first + project_json = group_json['children'].first + + expect(group_json['id']).to eq(public_subgroup.id) + expect(project_json['id']).to eq(project.id) + end + + it 'expands the tree for matching subgroups' do + matched_group = create(:group, :public, parent: public_subgroup, name: 'filterme') + + get_filtered_list + + group_json = json_response.first + matched_group_json = group_json['children'].first + + expect(group_json['id']).to eq(public_subgroup.id) + expect(matched_group_json['id']).to eq(matched_group.id) + end + end end end diff --git a/spec/serializers/group_child_serializer_spec.rb b/spec/serializers/group_child_serializer_spec.rb index 967ed06d316..7a87c1adc8f 100644 --- a/spec/serializers/group_child_serializer_spec.rb +++ b/spec/serializers/group_child_serializer_spec.rb @@ -16,7 +16,7 @@ describe GroupChildSerializer do end end - context 'with a hierarchy' do + context 'with a hierarchy', :nested_groups do let(:parent) { create(:group) } subject(:serializer) do @@ -35,8 +35,51 @@ describe GroupChildSerializer do expect(subsub_group_json[:id]).to eq(subsub_group.id) end - it 'can expand multiple trees' do + it 'can render a nested tree' do + subgroup1 = create(:group, parent: parent) + subsub_group1 = create(:group, parent: subgroup1) + subgroup2 = create(:group, parent: parent) + subsub_group2 = create(:group, parent: subgroup2) + json = serializer.represent([subsub_group1, subsub_group2]) + subgroup1_json = json.first + subsub_group1_json = subgroup1_json[:children].first + + expect(json.size).to eq(2) + expect(subgroup1_json[:id]).to eq(subgroup1.id) + expect(subsub_group1_json[:id]).to eq(subsub_group1.id) + end + end + + context 'for projects' do + it 'can render a single project' do + expect(serializer.represent(build(:project))).to be_kind_of(Hash) + end + + it 'can render a collection of projects' do + expect(serializer.represent(build_list(:project, 2))).to be_kind_of(Array) + end + + context 'with a hierarchy', :nested_groups do + let(:parent) { create(:group) } + + subject(:serializer) do + described_class.new(current_user: user).expand_hierarchy(parent) + end + + it 'can render a nested tree' do + subgroup1 = create(:group, parent: parent) + project1 = create(:project, namespace: subgroup1) + subgroup2 = create(:group, parent: parent) + project2 = create(:project, namespace: subgroup2) + + json = serializer.represent([project1, project2]) + project1_json, project2_json = json.map { |group_json| group_json[:children].first } + + expect(json.size).to eq(2) + expect(project1_json[:id]).to eq(project1.id) + expect(project2_json[:id]).to eq(project2.id) + end end end end |