Commit 983f7d1e authored by Florie Guibert's avatar Florie Guibert

Add Confidential filter to issue boards new filtered search

New filtered search
parent 8e4fed9e
import { sortBy, cloneDeep } from 'lodash';
import { isGid } from '~/graphql_shared/utils';
import { parseBoolean } from '~/lib/utils/common_utils';
import { ListType, MilestoneIDs, AssigneeFilterType, MilestoneFilterType } from './constants';
export function getMilestone() {
......@@ -220,6 +221,10 @@ export const FiltersInfo = {
types: {
negatedSupport: true,
},
confidential: {
negatedSupport: false,
transform: (val) => parseBoolean(val),
},
search: {
negatedSupport: false,
},
......
......@@ -45,6 +45,7 @@ export default {
epicId,
myReactionEmoji,
releaseTag,
confidential,
} = this.filterParams;
const filteredSearchValue = [];
......@@ -113,6 +114,13 @@ export default {
});
}
if (confidential !== undefined) {
filteredSearchValue.push({
type: 'confidential',
value: { data: confidential },
});
}
if (epicId) {
filteredSearchValue.push({
type: 'epic',
......@@ -211,6 +219,7 @@ export default {
myReactionEmoji,
iterationId,
releaseTag,
confidential,
} = this.filterParams;
let notParams = {};
......@@ -245,6 +254,7 @@ export default {
epic_id: isGid(epicId) ? getIdFromGraphQLId(epicId) : epicId,
my_reaction_emoji: myReactionEmoji,
release_tag: releaseTag,
confidential,
};
},
},
......@@ -311,6 +321,9 @@ export default {
case 'release':
filterParams.releaseTag = filter.value.data;
break;
case 'confidential':
filterParams.confidential = filter.value.data;
break;
case 'filtered-search-term':
if (filter.value.data) plainText.push(filter.value.data);
break;
......
......@@ -13,6 +13,7 @@ import { __ } from '~/locale';
import {
TOKEN_TITLE_MY_REACTION,
OPERATOR_IS_AND_IS_NOT,
OPERATOR_IS_ONLY,
} from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import EmojiToken from '~/vue_shared/components/filtered_search_bar/tokens/emoji_token.vue';
......@@ -36,6 +37,7 @@ export default {
issue: __('Issue'),
milestone: __('Milestone'),
release: __('Release'),
confidential: __('Confidential'),
},
components: { BoardFilteredSearch },
inject: ['isSignedIn', 'releasesFetchPath'],
......@@ -68,6 +70,7 @@ export default {
type,
milestone,
release,
confidential,
} = this.$options.i18n;
const { types } = this.$options;
const { fetchAuthors, fetchLabels } = issueBoardFilters(
......@@ -132,6 +135,18 @@ export default {
});
},
},
{
type: 'confidential',
icon: 'eye-slash',
title: confidential,
unique: true,
token: GlFilteredSearchToken,
operators: OPERATOR_IS_ONLY,
options: [
{ icon: 'eye-slash', value: true, title: __('Yes') },
{ icon: 'eye', value: false, title: __('No') },
],
},
]
: []),
{
......
......@@ -104,6 +104,7 @@ export const FilterFields = {
'assigneeUsername',
'assigneeWildcardId',
'authorUsername',
'confidential',
'labelName',
'milestoneTitle',
'milestoneWildcardId',
......
......@@ -448,6 +448,18 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, fetchIter
token: EmojiToken,
fetchEmojis: expect.any(Function),
},
{
type: 'confidential',
icon: 'eye-slash',
title: 'Confidential',
unique: true,
token: GlFilteredSearchToken,
operators: [{ value: '=', description: 'is' }],
options: [
{ icon: 'eye-slash', value: true, title: 'Yes' },
{ icon: 'eye', value: false, title: 'No' },
],
},
{
icon: 'clock',
title: __('Milestone'),
......
......@@ -12,7 +12,7 @@ RSpec.describe 'Issue board filters', :js do
let_it_be(:release) { create(:release, tag: 'v1.0', project: project, milestones: [milestone_1]) }
let_it_be(:release_2) { create(:release, tag: 'v2.0', project: project, milestones: [milestone_2]) }
let_it_be(:issue_1) { create(:issue, project: project, milestone: milestone_1, author: user) }
let_it_be(:issue_2) { create(:labeled_issue, project: project, milestone: milestone_2, assignees: [user], labels: [project_label]) }
let_it_be(:issue_2) { create(:labeled_issue, project: project, milestone: milestone_2, assignees: [user], labels: [project_label], confidential: true) }
let_it_be(:award_emoji1) { create(:award_emoji, name: 'thumbsup', user: user, awardable: issue_1) }
let(:filtered_search) { find('[data-testid="issue_1-board-filtered-search"]') }
......@@ -100,6 +100,25 @@ RSpec.describe 'Issue board filters', :js do
end
end
describe 'filters by confidentiality' do
before do
filter_input.click
filter_input.set("confidential:")
end
it 'loads all the confidentiality options when opened and submit one as filter', :aggregate_failures do
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 2)
expect_filtered_search_dropdown_results(filter_dropdown, 2)
filter_dropdown.click_on 'Yes'
filter_submit.click
expect(find('.board:nth-child(1)')).to have_selector('.board-card', count: 1)
expect(find('.board-card')).to have_content(issue_2.title)
end
end
describe 'filters by milestone' do
before do
set_filter('milestone')
......
......@@ -552,7 +552,20 @@ export const mockEmojiToken = {
fetchEmojis: expect.any(Function),
};
export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji) => [
export const mockConfidentialToken = {
type: 'confidential',
icon: 'eye-slash',
title: 'Confidential',
unique: true,
token: GlFilteredSearchToken,
operators: [{ value: '=', description: 'is' }],
options: [
{ icon: 'eye-slash', value: true, title: 'Yes' },
{ icon: 'eye', value: false, title: 'No' },
],
};
export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, isSignedIn) => [
{
icon: 'user',
title: __('Assignee'),
......@@ -593,7 +606,7 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, hasEmoji)
symbol: '~',
fetchLabels,
},
...(hasEmoji ? [mockEmojiToken] : []),
...(isSignedIn ? [mockEmojiToken, mockConfidentialToken] : []),
{
icon: 'clock',
title: __('Milestone'),
......
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