Commit 272936fa authored by Florie Guibert's avatar Florie Guibert

Add Epic to new filtered search in issue boards

EE/CE separation
parent dc69a406
...@@ -9,7 +9,6 @@ import { convertToGraphQLId } from '~/graphql_shared/utils'; ...@@ -9,7 +9,6 @@ import { convertToGraphQLId } from '~/graphql_shared/utils';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { DEFAULT_MILESTONES_GRAPHQL } from '~/vue_shared/components/filtered_search_bar/constants'; import { DEFAULT_MILESTONES_GRAPHQL } from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import EpicToken from '~/vue_shared/components/filtered_search_bar/tokens/epic_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue'; import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue'; import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue'; import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue';
...@@ -34,7 +33,6 @@ export default { ...@@ -34,7 +33,6 @@ export default {
isNot: __('is not'), isNot: __('is not'),
}, },
components: { BoardFilteredSearch }, components: { BoardFilteredSearch },
inject: ['epicFeatureAvailable'],
props: { props: {
fullPath: { fullPath: {
type: String, type: String,
...@@ -54,9 +52,8 @@ export default { ...@@ -54,9 +52,8 @@ export default {
? this.fullPath ? this.fullPath
: this.fullPath.slice(0, this.fullPath.lastIndexOf('/')); : this.fullPath.slice(0, this.fullPath.lastIndexOf('/'));
}, },
tokens() { tokensCE() {
const { const {
epic,
label, label,
is, is,
isNot, isNot,
...@@ -103,21 +100,6 @@ export default { ...@@ -103,21 +100,6 @@ export default {
fetchAuthors, fetchAuthors,
preloadedAuthors: this.preloadedAuthors(), preloadedAuthors: this.preloadedAuthors(),
}, },
...(this.epicFeatureAvailable
? [
{
type: 'epic_id',
title: epic,
icon: 'epic',
token: EpicToken,
unique: true,
symbol: '&',
idProperty: 'id',
useIdValue: true,
fullPath: this.epicsGroupPath,
},
]
: []),
{ {
icon: 'labels', icon: 'labels',
title: label, title: label,
...@@ -162,6 +144,9 @@ export default { ...@@ -162,6 +144,9 @@ export default {
}, },
]; ];
}, },
tokens() {
return this.tokensCE;
},
}, },
methods: { methods: {
...mapActions(['fetchMilestones']), ...mapActions(['fetchMilestones']),
......
import Vue from 'vue'; import Vue from 'vue';
import IssueBoardFilteredSearch from '~/boards/components/issue_board_filtered_search.vue'; import IssueBoardFilteredSearch from 'ee_else_ce/boards/components/issue_board_filtered_search.vue';
import store from '~/boards/stores'; import store from '~/boards/stores';
import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils'; import { convertObjectPropsToCamelCase } from '~/lib/utils/common_utils';
import { queryToObject } from '~/lib/utils/url_utility'; import { queryToObject } from '~/lib/utils/url_utility';
export default (apolloProvider, epicFeatureAvailable = false) => { export default (apolloProvider) => {
const el = document.getElementById('js-issue-board-filtered-search'); const el = document.getElementById('js-issue-board-filtered-search');
const rawFilterParams = queryToObject(window.location.search, { gatherArrays: true }); const rawFilterParams = queryToObject(window.location.search, { gatherArrays: true });
...@@ -20,7 +20,6 @@ export default (apolloProvider, epicFeatureAvailable = false) => { ...@@ -20,7 +20,6 @@ export default (apolloProvider, epicFeatureAvailable = false) => {
el, el,
provide: { provide: {
initialFilterParams, initialFilterParams,
epicFeatureAvailable,
}, },
store, // TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/324094 store, // TODO: https://gitlab.com/gitlab-org/gitlab/-/issues/324094
apolloProvider, apolloProvider,
......
<script>
// This is a false violation of @gitlab/no-runtime-template-compiler, since it
// extends a valid Vue single file component.
/* eslint-disable @gitlab/no-runtime-template-compiler */
import IssueBoardFilteredSearchFoss from '~/boards/components/issue_board_filtered_search.vue';
import { BoardType } from '~/boards/constants';
import { __ } from '~/locale';
import EpicToken from '~/vue_shared/components/filtered_search_bar/tokens/epic_token.vue';
export default {
extends: IssueBoardFilteredSearchFoss,
i18n: {
...IssueBoardFilteredSearchFoss.i18n,
epic: __('Epic'),
},
computed: {
isGroupBoard() {
return this.boardType === BoardType.group;
},
epicsGroupPath() {
return this.isGroupBoard
? this.fullPath
: this.fullPath.slice(0, this.fullPath.lastIndexOf('/'));
},
tokens() {
const { epic } = this.$options.i18n;
return [
...this.tokensCE,
{
type: 'epic_id',
title: epic,
icon: 'epic',
token: EpicToken,
unique: true,
symbol: '&',
idProperty: 'id',
useIdValue: true,
fullPath: this.epicsGroupPath,
},
];
},
},
};
</script>
import { shallowMount } from '@vue/test-utils';
import BoardFilteredSearch from '~/boards/components/board_filtered_search.vue';
import IssueBoardFilteredSpec from 'ee/boards/components/issue_board_filtered_search.vue';
import issueBoardFilters from '~/boards/issue_board_filters';
import { mockTokens } from '../mock_data';
jest.mock('~/boards/issue_board_filters');
describe('IssueBoardFilter', () => {
let wrapper;
const createComponent = () => {
wrapper = shallowMount(IssueBoardFilteredSpec, {
propsData: { fullPath: 'gitlab-org', boardType: 'group' },
});
};
let fetchAuthorsSpy;
let fetchLabelsSpy;
beforeEach(() => {
fetchAuthorsSpy = jest.fn();
fetchLabelsSpy = jest.fn();
issueBoardFilters.mockReturnValue({
fetchAuthors: fetchAuthorsSpy,
fetchLabels: fetchLabelsSpy,
});
});
afterEach(() => {
wrapper.destroy();
});
describe('default', () => {
beforeEach(() => {
createComponent();
});
it('finds BoardFilteredSearch', () => {
expect(wrapper.find(BoardFilteredSearch).exists()).toBe(true);
});
it('passes the correct tokens to BoardFilteredSearch including epics', () => {
const tokens = mockTokens(fetchLabelsSpy, fetchAuthorsSpy, wrapper.vm.fetchMilestones);
expect(wrapper.find(BoardFilteredSearch).props('tokens')).toEqual(tokens);
});
});
});
import { GlFilteredSearchToken } from '@gitlab/ui';
import { __ } from '~/locale';
import { DEFAULT_MILESTONES_GRAPHQL } from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import EpicToken from '~/vue_shared/components/filtered_search_bar/tokens/epic_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue';
export const mockLabel = { export const mockLabel = {
id: 'gid://gitlab/GroupLabel/121', id: 'gid://gitlab/GroupLabel/121',
title: 'To Do', title: 'To Do',
...@@ -365,3 +374,86 @@ export const mockGroup2 = { ...@@ -365,3 +374,86 @@ export const mockGroup2 = {
}; };
export const mockSubGroups = [mockGroup0, mockGroup1, mockGroup2]; export const mockSubGroups = [mockGroup0, mockGroup1, mockGroup2];
export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones) => [
{
icon: 'user',
title: __('Assignee'),
type: 'assignee_username',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
],
token: AuthorToken,
unique: true,
fetchAuthors,
preloadedAuthors: [],
},
{
icon: 'pencil',
title: __('Author'),
type: 'author_username',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
],
symbol: '@',
token: AuthorToken,
unique: true,
fetchAuthors,
preloadedAuthors: [],
},
{
icon: 'labels',
title: __('Label'),
type: 'label_name',
operators: [
{ value: '=', description: 'is' },
{ value: '!=', description: 'is not' },
],
token: LabelToken,
unique: false,
symbol: '~',
fetchLabels,
},
{
icon: 'clock',
title: __('Milestone'),
symbol: '%',
type: 'milestone_title',
token: MilestoneToken,
unique: true,
defaultMilestones: DEFAULT_MILESTONES_GRAPHQL,
fetchMilestones,
},
{
icon: 'issues',
title: __('Type'),
type: 'types',
operators: [{ value: '=', description: 'is' }],
token: GlFilteredSearchToken,
unique: true,
options: [
{ icon: 'issue-type-issue', value: 'ISSUE', title: 'Issue' },
{ icon: 'issue-type-incident', value: 'INCIDENT', title: 'Incident' },
],
},
{
icon: 'weight',
title: __('Weight'),
type: 'weight',
token: WeightToken,
unique: true,
},
{
type: 'epic_id',
icon: 'epic',
title: 'Epic',
unique: true,
symbol: '&',
token: EpicToken,
idProperty: 'id',
useIdValue: true,
fullPath: 'gitlab-org',
},
];
...@@ -49,16 +49,4 @@ describe('IssueBoardFilter', () => { ...@@ -49,16 +49,4 @@ describe('IssueBoardFilter', () => {
expect(wrapper.find(BoardFilteredSearch).props('tokens')).toEqual(tokens); expect(wrapper.find(BoardFilteredSearch).props('tokens')).toEqual(tokens);
}); });
}); });
describe('when epics are available', () => {
beforeEach(() => {
createComponent({ epicFeatureAvailable: true });
});
it('passes the correct tokens to BoardFilteredSearch including epics', () => {
const tokens = mockTokens(fetchLabelsSpy, fetchAuthorsSpy, wrapper.vm.fetchMilestones, true);
expect(wrapper.find(BoardFilteredSearch).props('tokens')).toEqual(tokens);
});
});
}); });
...@@ -4,7 +4,6 @@ import { ListType } from '~/boards/constants'; ...@@ -4,7 +4,6 @@ import { ListType } from '~/boards/constants';
import { __ } from '~/locale'; import { __ } from '~/locale';
import { DEFAULT_MILESTONES_GRAPHQL } from '~/vue_shared/components/filtered_search_bar/constants'; import { DEFAULT_MILESTONES_GRAPHQL } from '~/vue_shared/components/filtered_search_bar/constants';
import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue'; import AuthorToken from '~/vue_shared/components/filtered_search_bar/tokens/author_token.vue';
import EpicToken from '~/vue_shared/components/filtered_search_bar/tokens/epic_token.vue';
import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue'; import LabelToken from '~/vue_shared/components/filtered_search_bar/tokens/label_token.vue';
import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue'; import MilestoneToken from '~/vue_shared/components/filtered_search_bar/tokens/milestone_token.vue';
import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue'; import WeightToken from '~/vue_shared/components/filtered_search_bar/tokens/weight_token.vue';
...@@ -539,19 +538,7 @@ export const mockMoveData = { ...@@ -539,19 +538,7 @@ export const mockMoveData = {
...mockMoveIssueParams, ...mockMoveIssueParams,
}; };
export const mockEpicToken = { export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones) => [
type: 'epic_id',
icon: 'epic',
title: 'Epic',
unique: true,
symbol: '&',
token: EpicToken,
idProperty: 'id',
useIdValue: true,
fullPath: 'gitlab-org',
};
export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, epics = false) => [
{ {
icon: 'user', icon: 'user',
title: __('Assignee'), title: __('Assignee'),
...@@ -579,7 +566,6 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, epics = f ...@@ -579,7 +566,6 @@ export const mockTokens = (fetchLabels, fetchAuthors, fetchMilestones, epics = f
fetchAuthors, fetchAuthors,
preloadedAuthors: [], preloadedAuthors: [],
}, },
...(epics ? [mockEpicToken] : []),
{ {
icon: 'labels', icon: 'labels',
title: __('Label'), title: __('Label'),
......
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