Commit f493f885 authored by Sean McGivern's avatar Sean McGivern

Merge branch 'assignees_filter_issues' into 'master'

Search for issues with multiple assignees

See merge request !1889
parents 3c287055 f7599ef0
......@@ -18,6 +18,13 @@ const weightConditions = [{
value: 'any',
}];
const alternativeTokenKeys = [{
key: 'assignee',
type: 'string',
param: 'username',
symbol: '@',
}];
class FilteredSearchTokenKeysIssuesEE extends gl.FilteredSearchTokenKeys {
static init(availableFeatures) {
this.availableFeatures = availableFeatures;
......@@ -30,6 +37,7 @@ class FilteredSearchTokenKeysIssuesEE extends gl.FilteredSearchTokenKeys {
if (this.availableFeatures && this.availableFeatures.multipleAssignees) {
const assigneeTokenKey = tokenKeys.find(tk => tk.key === 'assignee');
assigneeTokenKey.type = 'array';
assigneeTokenKey.param = 'username[]';
}
tokenKeys.push(weightTokenKey);
......@@ -42,7 +50,7 @@ class FilteredSearchTokenKeysIssuesEE extends gl.FilteredSearchTokenKeys {
}
static getAlternatives() {
return super.getAlternatives();
return alternativeTokenKeys.concat(super.getAlternatives());
}
static getConditions() {
......@@ -62,8 +70,8 @@ class FilteredSearchTokenKeysIssuesEE extends gl.FilteredSearchTokenKeys {
static searchByKeyParam(keyParam) {
const tokenKeys = FilteredSearchTokenKeysIssuesEE.get();
const alternativeTokenKeys = FilteredSearchTokenKeysIssuesEE.getAlternatives();
const tokenKeysWithAlternative = tokenKeys.concat(alternativeTokenKeys);
const alternatives = FilteredSearchTokenKeysIssuesEE.getAlternatives();
const tokenKeysWithAlternative = tokenKeys.concat(alternatives);
return tokenKeysWithAlternative.find((tokenKey) => {
let tokenKeyParam = tokenKey.key;
......
......@@ -26,7 +26,7 @@ class IssuableFinder
IRRELEVANT_PARAMS_FOR_CACHE_KEY = %i[utf8 sort page state].freeze
SCALAR_PARAMS = %i(scope state group_id project_id milestone_title assignee_id search label_name sort assignee_username author_id author_username authorized_only due_date iids non_archived weight).freeze
ARRAY_PARAMS = { label_name: [], iids: [] }.freeze
ARRAY_PARAMS = { label_name: [], iids: [], assignee_username: [] }.freeze
VALID_PARAMS = (SCALAR_PARAMS + [ARRAY_PARAMS]).freeze
attr_accessor :current_user, :params
......@@ -309,18 +309,6 @@ class IssuableFinder
params[:sort] ? items.sort(params[:sort], excluded_labels: label_names) : items.reorder(id: :desc)
end
def by_assignee(items)
if assignee
items = items.where(assignee_id: assignee.id)
elsif no_assignee?
items = items.where(assignee_id: nil)
elsif assignee_id? || assignee_username? # assignee not found
items = items.none
end
items
end
def by_author(items)
if author
items = items.where(author_id: author.id)
......
......@@ -95,7 +95,13 @@ class IssuesFinder < IssuableFinder
end
def by_assignee(items)
if assignee
if assignees.any?
assignees.each do |assignee|
items = items.assigned_to(assignee)
end
items
elsif assignee && assignees.empty?
items.assigned_to(assignee)
elsif no_assignee?
items.unassigned
......@@ -106,6 +112,19 @@ class IssuesFinder < IssuableFinder
end
end
def assignees
return @assignees if defined?(@assignees)
@assignees =
if params[:assignee_ids]
User.where(id: params[:assignee_ids])
elsif params[:assignee_username]
User.where(username: params[:assignee_username])
else
[]
end
end
def item_project_ids(items)
items&.reorder(nil)&.select(:project_id)
end
......
......@@ -24,6 +24,18 @@ class MergeRequestsFinder < IssuableFinder
private
def by_assignee(items)
if assignee
items = items.where(assignee_id: assignee.id)
elsif no_assignee?
items = items.where(assignee_id: nil)
elsif assignee_id? || assignee_username? # assignee not found
items = items.none
end
items
end
def item_project_ids(items)
items&.reorder(nil)&.select(:target_project_id)
end
......
---
title: Search for issues with multiple assignees
merge_request:
author:
......@@ -196,7 +196,17 @@ describe 'Filter issues', js: true do
end
it 'filters issues by multiple assignees' do
skip('to be tested, issue #26546')
create(:issue, project: project, author: user, assignees: [user2, user])
input_filtered_search("assignee:@#{user.username} assignee:@#{user2.username}")
expect_tokens([
assignee_token(user.name),
assignee_token(user2.name)
])
expect_issues_list_count(1)
expect_filtered_search_input_empty
end
end
......
......@@ -59,6 +59,36 @@ describe IssuesFinder do
end
end
context 'filtering by assignee IDs' do
set(:user3) { create(:user) }
let(:params) { { assignee_ids: [user2.id, user3.id] } }
before do
project2.add_developer(user3)
issue3.assignees = [user2, user3]
end
it 'returns issues assigned to those users' do
expect(issues).to contain_exactly(issue3)
end
end
context 'filtering by assignee usernames' do
set(:user3) { create(:user) }
let(:params) { { assignee_username: [user2.username, user3.username] } }
before do
project2.add_developer(user3)
issue3.assignees = [user2, user3]
end
it 'returns issues assigned to those users' do
expect(issues).to contain_exactly(issue3)
end
end
context 'filtering by author ID' do
let(:params) { { author_id: user2.id } }
......
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