Commit be8259c5 authored by Robert Speicher's avatar Robert Speicher

Merge branch '195178-filter-issues-by-epics' into 'master'

Support filtering by epics in IssuesFinder

See merge request gitlab-org/gitlab!22477
parents fc0c8658 13dd6928
......@@ -11,13 +11,14 @@ module EE
override :scalar_params
def scalar_params
@scalar_params ||= super + [:weight]
@scalar_params ||= super + [:weight, :epic_id]
end
end
override :filter_items
def filter_items(items)
by_weight(super)
issues = by_weight(super)
by_epic(issues)
end
private
......@@ -74,5 +75,23 @@ module EE
end
end
# rubocop: enable CodeReuse/ActiveRecord
def by_epic?
params[:epic_id].present?
end
def filter_by_no_epic?
params[:epic_id].to_s.downcase == ::IssuesFinder::FILTER_NONE
end
def by_epic(items)
return items unless by_epic?
if filter_by_no_epic?
items.no_epic
else
items.in_epics(params[:epic_id])
end
end
end
end
......@@ -19,7 +19,7 @@ module EE
scope :order_weight_asc, -> { reorder ::Gitlab::Database.nulls_last_order('weight') }
scope :order_created_at_desc, -> { reorder(created_at: :desc) }
scope :service_desk, -> { where(author: ::User.support_bot) }
scope :no_epic, -> { left_outer_joins(:epic_issue).where(epic_issues: { epic_id: nil }) }
scope :in_epics, ->(epics) do
issue_ids = EpicIssue.where(epic_id: epics).select(:issue_id)
id_in(issue_ids)
......
......@@ -11,8 +11,8 @@ describe IssuesFinder do
let(:scope) { 'all' }
describe 'filter by weight' do
set(:issue_with_weight_1) { create(:issue, project: project3, weight: 1) }
set(:issue_with_weight_42) { create(:issue, project: project3, weight: 42) }
let_it_be(:issue_with_weight_1) { create(:issue, project: project3, weight: 1) }
let_it_be(:issue_with_weight_42) { create(:issue, project: project3, weight: 42) }
context 'filter issues with no weight' do
let(:params) { { weight: Issue::WEIGHT_NONE } }
......@@ -40,7 +40,7 @@ describe IssuesFinder do
end
context 'filtering by assignee IDs' do
set(:user3) { create(:user) }
let_it_be(:user3) { create(:user) }
let(:params) { { assignee_ids: [user2.id, user3.id] } }
before do
......@@ -53,16 +53,44 @@ describe IssuesFinder do
expect(issues).to contain_exactly(issue3)
end
end
context 'filter by epic' do
let_it_be(:group) { create(:group) }
let_it_be(:epic_1) { create(:epic, group: group) }
let_it_be(:epic_2) { create(:epic, group: group) }
let_it_be(:sub_epic) { create(:epic, group: group, parent: epic_1) }
let_it_be(:issue_1) { create(:issue, project: project1, epic: epic_1) }
let_it_be(:issue_2) { create(:issue, project: project1, epic: epic_2) }
let_it_be(:issue_subepic) { create(:issue, project: project1, epic: sub_epic) }
context 'filter issues with no epic' do
let(:params) { { epic_id: ::IssuesFinder::FILTER_NONE } }
it 'returns filtered issues' do
expect(issues).to contain_exactly(issue1, issue2, issue3, issue4)
end
end
context 'filter issues by epic' do
let(:params) { { epic_id: epic_1.id } }
it 'returns all issues in the epic, subepic issues excluded' do
expect(issues).to contain_exactly(issue_1)
end
end
end
end
end
describe '#with_confidentiality_access_check' do
let(:guest) { create(:user) }
let_it_be(:guest) { create(:user) }
set(:authorized_user) { create(:user) }
set(:project) { create(:project, namespace: authorized_user.namespace) }
set(:public_issue) { create(:issue, project: project) }
set(:confidential_issue) { create(:issue, project: project, confidential: true) }
let_it_be(:authorized_user) { create(:user) }
let_it_be(:project) { create(:project, namespace: authorized_user.namespace) }
let_it_be(:public_issue) { create(:issue, project: project) }
let_it_be(:confidential_issue) { create(:issue, project: project, confidential: true) }
context 'when no project filter is given' do
let(:params) { {} }
......
......@@ -67,22 +67,32 @@ describe Issue do
end
end
describe '.in_epics' do
context 'epics' do
let_it_be(:epic1) { create(:epic) }
let_it_be(:epic2) { create(:epic) }
let_it_be(:epic_issue1) { create(:epic_issue, epic: epic1) }
let_it_be(:epic_issue2) { create(:epic_issue, epic: epic2) }
let_it_be(:issue_no_epic) { create(:issue) }
before do
stub_licensed_features(epics: true)
end
describe '.no_epic' do
it 'returns only issues without an epic assigned' do
expect(described_class.count).to eq 3
expect(described_class.no_epic).to eq [issue_no_epic]
end
end
describe '.in_epics' do
it 'returns only issues in selected epics' do
expect(described_class.count).to eq 2
expect(described_class.count).to eq 3
expect(described_class.in_epics([epic1])).to eq [epic_issue1.issue]
end
end
end
end
describe 'validations' do
subject { build(:issue) }
......
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