Commit 86e00214 authored by James Lopez's avatar James Lopez

Merge branch 'jprovazn-project-search' into 'master'

Order projects by name in the "Move issue" dropdown

See merge request gitlab-org/gitlab-ce!30778
parents 5ca1899a 972b5f45
...@@ -3,7 +3,9 @@ ...@@ -3,7 +3,9 @@
module Autocomplete module Autocomplete
# Finder that retrieves a list of projects that an issue can be moved to. # Finder that retrieves a list of projects that an issue can be moved to.
class MoveToProjectFinder class MoveToProjectFinder
attr_reader :current_user, :search, :project_id, :offset_id attr_reader :current_user, :search, :project_id
LIMIT = 20
# current_user - The User object of the user that wants to view the list of # current_user - The User object of the user that wants to view the list of
# projects. # projects.
...@@ -14,13 +16,10 @@ module Autocomplete ...@@ -14,13 +16,10 @@ module Autocomplete
# #
# * search: An optional search query to apply to the list of projects. # * search: An optional search query to apply to the list of projects.
# * project_id: The ID of a project to exclude from the returned relation. # * project_id: The ID of a project to exclude from the returned relation.
# * offset_id: The ID of a project to use for pagination. When given, only
# projects with a lower ID are included in the list.
def initialize(current_user, params = {}) def initialize(current_user, params = {})
@current_user = current_user @current_user = current_user
@search = params[:search] @search = params[:search]
@project_id = params[:project_id] @project_id = params[:project_id]
@offset_id = params[:offset_id]
end end
def execute def execute
...@@ -28,8 +27,8 @@ module Autocomplete ...@@ -28,8 +27,8 @@ module Autocomplete
.projects_where_can_admin_issues .projects_where_can_admin_issues
.optionally_search(search) .optionally_search(search)
.excluding_project(project_id) .excluding_project(project_id)
.paginate_in_descending_order_using_id(before: offset_id)
.eager_load_namespace_and_owner .eager_load_namespace_and_owner
.sorted_by_name_asc_limited(LIMIT)
end end
end end
end end
...@@ -357,6 +357,7 @@ class Project < ApplicationRecord ...@@ -357,6 +357,7 @@ class Project < ApplicationRecord
scope :sorted_by_activity, -> { reorder(Arel.sql("GREATEST(COALESCE(last_activity_at, '1970-01-01'), COALESCE(last_repository_updated_at, '1970-01-01')) DESC")) } scope :sorted_by_activity, -> { reorder(Arel.sql("GREATEST(COALESCE(last_activity_at, '1970-01-01'), COALESCE(last_repository_updated_at, '1970-01-01')) DESC")) }
scope :sorted_by_stars_desc, -> { reorder(star_count: :desc) } scope :sorted_by_stars_desc, -> { reorder(star_count: :desc) }
scope :sorted_by_stars_asc, -> { reorder(star_count: :asc) } scope :sorted_by_stars_asc, -> { reorder(star_count: :asc) }
scope :sorted_by_name_asc_limited, ->(limit) { reorder(name: :asc).limit(limit) }
scope :in_namespace, ->(namespace_ids) { where(namespace_id: namespace_ids) } scope :in_namespace, ->(namespace_ids) { where(namespace_id: namespace_ids) }
scope :personal, ->(user) { where(namespace_id: user.namespace_id) } scope :personal, ->(user) { where(namespace_id: user.namespace_id) }
...@@ -441,22 +442,6 @@ class Project < ApplicationRecord ...@@ -441,22 +442,6 @@ class Project < ApplicationRecord
without_deleted.find_by_id(id) without_deleted.find_by_id(id)
end end
# Paginates a collection using a `WHERE id < ?` condition.
#
# before - A project ID to use for filtering out projects with an equal or
# greater ID. If no ID is given, all projects are included.
#
# limit - The maximum number of rows to include.
def self.paginate_in_descending_order_using_id(
before: nil,
limit: Kaminari.config.default_per_page
)
relation = order_id_desc.limit(limit)
relation = relation.where('projects.id < ?', before) if before
relation
end
def self.eager_load_namespace_and_owner def self.eager_load_namespace_and_owner
includes(namespace: :owner) includes(namespace: :owner)
end end
......
---
title: Order projects in 'Move issue' dropdown by name.
merge_request: 30778
author:
type: fixed
...@@ -295,28 +295,6 @@ describe AutocompleteController do ...@@ -295,28 +295,6 @@ describe AutocompleteController do
end end
end end
context 'authorized projects with offset' do
before do
authorized_project2 = create(:project)
authorized_project3 = create(:project)
authorized_project.add_maintainer(user)
authorized_project2.add_maintainer(user)
authorized_project3.add_maintainer(user)
end
describe 'GET #projects with project ID and offset_id' do
before do
get(:projects, params: { project_id: project.id, offset_id: authorized_project.id })
end
it 'returns projects' do
expect(json_response).to be_kind_of(Array)
expect(json_response.size).to eq 2 # Of a total of 3
end
end
end
context 'authorized projects without admin_issue ability' do context 'authorized projects without admin_issue ability' do
before do before do
authorized_project.add_guest(user) authorized_project.add_guest(user)
......
...@@ -6,9 +6,9 @@ describe Autocomplete::MoveToProjectFinder do ...@@ -6,9 +6,9 @@ describe Autocomplete::MoveToProjectFinder do
let(:no_access_project) { create(:project) } let(:no_access_project) { create(:project) }
let(:guest_project) { create(:project) } let(:guest_project) { create(:project) }
let(:reporter_project) { create(:project) } let(:reporter_project) { create(:project, name: 'name') }
let(:developer_project) { create(:project) } let(:developer_project) { create(:project, name: 'name2') }
let(:maintainer_project) { create(:project) } let(:maintainer_project) { create(:project, name: 'name3') }
describe '#execute' do describe '#execute' do
context 'filter' do context 'filter' do
...@@ -20,14 +20,14 @@ describe Autocomplete::MoveToProjectFinder do ...@@ -20,14 +20,14 @@ describe Autocomplete::MoveToProjectFinder do
expect(finder.execute).to be_empty expect(finder.execute).to be_empty
end end
it 'returns projects equal or above Gitlab::Access::REPORTER ordered by id in descending order' do it 'returns projects equal or above Gitlab::Access::REPORTER ordered by name' do
reporter_project.add_reporter(user) reporter_project.add_reporter(user)
developer_project.add_developer(user) developer_project.add_developer(user)
maintainer_project.add_maintainer(user) maintainer_project.add_maintainer(user)
finder = described_class.new(user, project_id: project.id) finder = described_class.new(user, project_id: project.id)
expect(finder.execute.to_a).to eq([maintainer_project, developer_project, reporter_project]) expect(finder.execute.to_a).to eq([reporter_project, developer_project, maintainer_project])
end end
it 'does not include the source project' do it 'does not include the source project' do
...@@ -60,46 +60,32 @@ describe Autocomplete::MoveToProjectFinder do ...@@ -60,46 +60,32 @@ describe Autocomplete::MoveToProjectFinder do
expect(finder.execute.to_a).to eq([other_reporter_project]) expect(finder.execute.to_a).to eq([other_reporter_project])
end end
it 'returns a page of projects ordered by id in descending order' do it 'returns a page of projects ordered by name' do
allow(Kaminari.config).to receive(:default_per_page).and_return(2) stub_const('Autocomplete::MoveToProjectFinder::LIMIT', 2)
projects = create_list(:project, 2) do |project| projects = create_list(:project, 3) do |project|
project.add_developer(user) project.add_developer(user)
end end
finder = described_class.new(user, project_id: project.id) finder = described_class.new(user, project_id: project.id)
page = finder.execute.to_a page = finder.execute.to_a
expect(page.length).to eq(Kaminari.config.default_per_page) expected_projects = projects.sort_by(&:name).first(2)
expect(page[0]).to eq(projects.last) expect(page.length).to eq(2)
end expect(page).to eq(expected_projects)
it 'returns projects after the given offset id' do
reporter_project.add_reporter(user)
developer_project.add_developer(user)
maintainer_project.add_maintainer(user)
expect(described_class.new(user, project_id: project.id, offset_id: maintainer_project.id).execute.to_a)
.to eq([developer_project, reporter_project])
expect(described_class.new(user, project_id: project.id, offset_id: developer_project.id).execute.to_a)
.to eq([reporter_project])
expect(described_class.new(user, project_id: project.id, offset_id: reporter_project.id).execute.to_a)
.to be_empty
end end
end end
context 'search' do context 'search' do
it 'returns projects matching a search query' do it 'returns projects matching a search query' do
foo_project = create(:project) foo_project = create(:project, name: 'foo')
foo_project.add_maintainer(user) foo_project.add_maintainer(user)
wadus_project = create(:project, name: 'wadus') wadus_project = create(:project, name: 'wadus')
wadus_project.add_maintainer(user) wadus_project.add_maintainer(user)
expect(described_class.new(user, project_id: project.id).execute.to_a) expect(described_class.new(user, project_id: project.id).execute.to_a)
.to eq([wadus_project, foo_project]) .to eq([foo_project, wadus_project])
expect(described_class.new(user, project_id: project.id, search: 'wadus').execute.to_a) expect(described_class.new(user, project_id: project.id, search: 'wadus').execute.to_a)
.to eq([wadus_project]) .to eq([wadus_project])
......
...@@ -1675,26 +1675,6 @@ describe Project do ...@@ -1675,26 +1675,6 @@ describe Project do
end end
end end
describe '.paginate_in_descending_order_using_id' do
let!(:project1) { create(:project) }
let!(:project2) { create(:project) }
it 'orders the relation in descending order' do
expect(described_class.paginate_in_descending_order_using_id)
.to eq([project2, project1])
end
it 'applies a limit to the relation' do
expect(described_class.paginate_in_descending_order_using_id(limit: 1))
.to eq([project2])
end
it 'limits projects by and ID when given' do
expect(described_class.paginate_in_descending_order_using_id(before: project2.id))
.to eq([project1])
end
end
describe '.including_namespace_and_owner' do describe '.including_namespace_and_owner' do
it 'eager loads the namespace and namespace owner' do it 'eager loads the namespace and namespace owner' do
create(:project) create(:project)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment