diff --git a/app/assets/javascripts/issues/list/constants.js b/app/assets/javascripts/issues/list/constants.js index 181fb580d2266409fda6a31e4a1bb3323f220f90..ebeb21f3791068793478e3b046fe13aef5a5bbdf 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_APPROVED_BY, + TOKEN_TYPE_APPROVER, TOKEN_TYPE_ASSIGNEE, TOKEN_TYPE_REVIEWER, TOKEN_TYPE_AUTHOR, @@ -166,6 +167,16 @@ export const filtersMap = { }, }, }, + [TOKEN_TYPE_APPROVER]: { + [API_PARAM]: { + [NORMAL_FILTER]: 'approver', + }, + [URL_PARAM]: { + [OPERATOR_IS]: { + [NORMAL_FILTER]: 'approver[]', + }, + }, + }, [TOKEN_TYPE_AUTHOR]: { [API_PARAM]: { [NORMAL_FILTER]: 'authorUsername', 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 ecc868a27da97362c2ef6608746aa6dedfa333a6..2c869a2609a5bf22e77857a787e7223073d4b60e 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 @@ -19,6 +19,8 @@ import { OPERATORS_IS_NOT, TOKEN_TITLE_APPROVED_BY, TOKEN_TYPE_APPROVED_BY, + TOKEN_TITLE_APPROVER, + TOKEN_TYPE_APPROVER, TOKEN_TITLE_AUTHOR, TOKEN_TYPE_AUTHOR, TOKEN_TITLE_DRAFT, @@ -221,6 +223,19 @@ export default { preloadedUsers, multiSelect: false, }, + { + type: TOKEN_TYPE_APPROVER, + title: TOKEN_TITLE_APPROVER, + icon: 'approval', + token: UserToken, + dataType: 'user', + operators: OPERATORS_IS, + fullPath: this.fullPath, + isProject: true, + recentSuggestionsStorageKey: `${this.fullPath}-merge_requests-recent-tokens-approvers`, + preloadedUsers, + multiSelect: false, + }, { type: TOKEN_TYPE_ASSIGNEE, title: TOKEN_TITLE_ASSIGNEE, 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 b386a7e8cf30611a9fdf1f1a76eaf83d656c4730..26fbc1ddb8072789bad7adc6c543ed849385d0b7 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 @@ -8,6 +8,7 @@ query getMergeRequests( $sort: MergeRequestSort $state: MergeRequestState $approvedBy: [String!] + $approver: [String!] $assigneeUsernames: String $assigneeWildcardId: AssigneeWildcardId $reviewerUsername: String @@ -36,6 +37,7 @@ query getMergeRequests( sort: $sort state: $state approvedBy: $approvedBy + approver: $approver assigneeUsername: $assigneeUsernames assigneeWildcardId: $assigneeWildcardId reviewerUsername: $reviewerUsername diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js index 620e0698972494d265477efe4faaac9f30f2f5f6..a9a59f240d91764327f603e89354eafdca9f46a8 100644 --- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js +++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/constants.js @@ -63,6 +63,7 @@ export const TOKEN_EMPTY_SEARCH_TERM = { export const TOKEN_TITLE_APPROVED_BY = __('Approved-By'); export const TOKEN_TITLE_MERGE_USER = __('Merged-By'); +export const TOKEN_TITLE_APPROVER = __('Approver'); export const TOKEN_TITLE_ASSIGNEE = s__('SearchToken|Assignee'); export const TOKEN_TITLE_AUTHOR = __('Author'); export const TOKEN_TITLE_CONFIDENTIAL = __('Confidential'); @@ -90,6 +91,7 @@ export const TOKEN_TITLE_DEPLOYED_BEFORE = __('Deployed-before'); export const TOKEN_TITLE_DEPLOYED_AFTER = __('Deployed-after'); export const TOKEN_TITLE_ASSIGNED_SEAT = __('Assigned seat'); +export const TOKEN_TYPE_APPROVER = 'approver'; export const TOKEN_TYPE_APPROVED_BY = 'approved-by'; export const TOKEN_TYPE_MERGE_USER = 'merge-user'; export const TOKEN_TYPE_ASSIGNEE = 'assignee'; 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 576349328994ef097e99da1f088a057259ef8808..5ad5b8af29a507b40dda89e0a60ff3be0928349a 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 @@ -15,6 +15,7 @@ import { TYPENAME_USER } from '~/graphql_shared/constants'; import { convertToGraphQLId } from '~/graphql_shared/utils'; import { TOKEN_TYPE_APPROVED_BY, + TOKEN_TYPE_APPROVER, TOKEN_TYPE_AUTHOR, TOKEN_TYPE_DRAFT, TOKEN_TYPE_LABEL, @@ -151,6 +152,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_APPROVED_BY, preloadedUsers: [] }, + { type: TOKEN_TYPE_APPROVER, preloadedUsers: [] }, { type: TOKEN_TYPE_ASSIGNEE }, { type: TOKEN_TYPE_REVIEWER, preloadedUsers: [] }, { type: TOKEN_TYPE_AUTHOR, preloadedUsers: [] }, @@ -171,6 +173,7 @@ describe('Merge requests list app', () => { describe('when all tokens are available', () => { const urlParams = { 'approved_by_usernames[]': 'anthony', + 'approver[]': 'angus', assignee_username: 'bob', reviewer_username: 'bill', draft: 'yes', @@ -208,6 +211,7 @@ describe('Merge requests list app', () => { expect(findIssuableList().props('searchTokens')).toMatchObject([ { type: TOKEN_TYPE_APPROVED_BY, preloadedUsers }, + { type: TOKEN_TYPE_APPROVER, preloadedUsers }, { type: TOKEN_TYPE_ASSIGNEE }, { type: TOKEN_TYPE_REVIEWER, preloadedUsers }, { type: TOKEN_TYPE_AUTHOR, preloadedUsers }, @@ -227,6 +231,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_APPROVED_BY }, + { type: TOKEN_TYPE_APPROVER }, { type: TOKEN_TYPE_ASSIGNEE }, { type: TOKEN_TYPE_REVIEWER }, { type: TOKEN_TYPE_DRAFT },