diff --git a/app/assets/javascripts/issues/list/constants.js b/app/assets/javascripts/issues/list/constants.js index a6850c8bdc99c97a0cb69d75aa48bd89313c277a..7aae0a325c3a4d67ede8503eaa7812c1e648273b 100644 --- a/app/assets/javascripts/issues/list/constants.js +++ b/app/assets/javascripts/issues/list/constants.js @@ -12,6 +12,7 @@ import { OPERATOR_AFTER, OPERATOR_BEFORE, TOKEN_TYPE_ASSIGNEE, + TOKEN_TYPE_REVIEWER, TOKEN_TYPE_AUTHOR, TOKEN_TYPE_CONFIDENTIAL, TOKEN_TYPE_CONTACT, @@ -234,6 +235,23 @@ export const filtersMap = { }, }, }, + [TOKEN_TYPE_REVIEWER]: { + [API_PARAM]: { + [NORMAL_FILTER]: 'reviewerUsername', + [SPECIAL_FILTER]: 'reviewerWildcardId', + [ALTERNATIVE_FILTER]: 'reviewerId', + }, + [URL_PARAM]: { + [OPERATOR_IS]: { + [NORMAL_FILTER]: 'reviewer_username', + [SPECIAL_FILTER]: 'reviewer_id', + [ALTERNATIVE_FILTER]: 'reviewer_username', + }, + [OPERATOR_NOT]: { + [NORMAL_FILTER]: 'not[reviewer_username]', + }, + }, + }, [TOKEN_TYPE_MILESTONE]: { [API_PARAM]: { [NORMAL_FILTER]: 'milestoneTitle', diff --git a/app/assets/javascripts/issues/list/utils.js b/app/assets/javascripts/issues/list/utils.js index 7d8886e048062eff50ddd651b7a6b0cccddb4eec..15085321e0b278c9152c47c35f5e365a04b8cb2c 100644 --- a/app/assets/javascripts/issues/list/utils.js +++ b/app/assets/javascripts/issues/list/utils.js @@ -11,6 +11,7 @@ import { OPERATOR_AFTER, OPERATORS_TO_GROUP, TOKEN_TYPE_ASSIGNEE, + TOKEN_TYPE_REVIEWER, TOKEN_TYPE_AUTHOR, TOKEN_TYPE_DRAFT, TOKEN_TYPE_CONFIDENTIAL, @@ -326,6 +327,7 @@ const wildcardTokens = [ TOKEN_TYPE_RELEASE, TOKEN_TYPE_EPIC, TOKEN_TYPE_ASSIGNEE, + TOKEN_TYPE_REVIEWER, TOKEN_TYPE_WEIGHT, ]; diff --git a/app/assets/javascripts/merge_requests/list/components/merge_requests_list_app.vue b/app/assets/javascripts/merge_requests/list/components/merge_requests_list_app.vue index f51ccc04059c7888a23ebf3ef8d44d111bbf8337..482578217a09485efc567d6d28511b2a1a1bb5f2 100644 --- a/app/assets/javascripts/merge_requests/list/components/merge_requests_list_app.vue +++ b/app/assets/javascripts/merge_requests/list/components/merge_requests_list_app.vue @@ -25,6 +25,8 @@ import { TOKEN_TYPE_SOURCE_BRANCH, TOKEN_TITLE_ASSIGNEE, TOKEN_TYPE_ASSIGNEE, + TOKEN_TITLE_REVIEWER, + TOKEN_TYPE_REVIEWER, TOKEN_TITLE_MILESTONE, TOKEN_TYPE_MILESTONE, } from '~/vue_shared/components/filtered_search_bar/constants'; @@ -191,6 +193,20 @@ export default { multiSelect: false, unique: true, }, + { + type: TOKEN_TYPE_REVIEWER, + title: TOKEN_TITLE_REVIEWER, + icon: 'user', + token: UserToken, + dataType: 'user', + operators: OPERATORS_IS, + fullPath: this.fullPath, + isProject: true, + recentSuggestionsStorageKey: `${this.fullPath}-merge-requests-recent-tokens-reviewer`, + preloadedUsers, + multiSelect: false, + unique: true, + }, { type: TOKEN_TYPE_AUTHOR, title: TOKEN_TITLE_AUTHOR, diff --git a/app/assets/javascripts/merge_requests/list/queries/get_merge_requests.query.graphql b/app/assets/javascripts/merge_requests/list/queries/get_merge_requests.query.graphql index 2b8d940991601f998ffd2404453606368e34d360..ea81f5ea2baa0d239c61992340ad323d008bc201 100644 --- a/app/assets/javascripts/merge_requests/list/queries/get_merge_requests.query.graphql +++ b/app/assets/javascripts/merge_requests/list/queries/get_merge_requests.query.graphql @@ -9,6 +9,8 @@ query getMergeRequests( $state: MergeRequestState $assigneeUsernames: String $assigneeWildcardId: AssigneeWildcardId + $reviewerUsername: String + $reviewerWildcardId: ReviewerWildcardId $authorUsername: String $draft: Boolean $milestoneTitle: String @@ -27,6 +29,8 @@ query getMergeRequests( state: $state assigneeUsername: $assigneeUsernames assigneeWildcardId: $assigneeWildcardId + reviewerUsername: $reviewerUsername + reviewerWildcardId: $reviewerWildcardId authorUsername: $authorUsername draft: $draft milestoneTitle: $milestoneTitle diff --git a/spec/frontend/merge_requests/list/components/merge_requests_list_app_spec.js b/spec/frontend/merge_requests/list/components/merge_requests_list_app_spec.js index 1844dba15a28fba9b7e0797fce73f253e5e0e60a..295631bfbcdd2353dfd50c53382f8dfe685edff2 100644 --- a/spec/frontend/merge_requests/list/components/merge_requests_list_app_spec.js +++ b/spec/frontend/merge_requests/list/components/merge_requests_list_app_spec.js @@ -14,6 +14,7 @@ import { TOKEN_TYPE_SOURCE_BRANCH, TOKEN_TYPE_TARGET_BRANCH, TOKEN_TYPE_ASSIGNEE, + TOKEN_TYPE_REVIEWER, } from '~/vue_shared/components/filtered_search_bar/constants'; import { mergeRequestListTabs } from '~/vue_shared/issuable/list/constants'; import { getSortOptions } from '~/issues/list/utils'; @@ -110,6 +111,7 @@ describe('Merge requests list app', () => { it('does not have preloaded users when gon.current_user_id does not exist', () => { expect(findIssuableList().props('searchTokens')).toMatchObject([ { type: TOKEN_TYPE_ASSIGNEE }, + { type: TOKEN_TYPE_REVIEWER, preloadedUsers: [] }, { type: TOKEN_TYPE_AUTHOR, preloadedUsers: [] }, { type: TOKEN_TYPE_DRAFT }, { type: TOKEN_TYPE_MILESTONE }, @@ -122,6 +124,7 @@ describe('Merge requests list app', () => { describe('when all tokens are available', () => { const urlParams = { assignee_username: 'bob', + reviewer_username: 'bill', draft: 'yes', milestone_title: 'milestone', 'target_branches[]': 'branch-a', @@ -154,6 +157,7 @@ describe('Merge requests list app', () => { expect(findIssuableList().props('searchTokens')).toMatchObject([ { type: TOKEN_TYPE_ASSIGNEE }, + { type: TOKEN_TYPE_REVIEWER, preloadedUsers }, { type: TOKEN_TYPE_AUTHOR, preloadedUsers }, { type: TOKEN_TYPE_DRAFT }, { type: TOKEN_TYPE_MILESTONE }, @@ -165,6 +169,7 @@ describe('Merge requests list app', () => { it('pre-displays tokens that are in the url search parameters', () => { expect(findIssuableList().props('initialFilterValue')).toMatchObject([ { type: TOKEN_TYPE_ASSIGNEE }, + { type: TOKEN_TYPE_REVIEWER }, { type: TOKEN_TYPE_DRAFT }, { type: TOKEN_TYPE_MILESTONE }, { type: TOKEN_TYPE_TARGET_BRANCH },