Commit ce2bf106 authored by Florie Guibert's avatar Florie Guibert

Swimlanes - Filters

VueX filtering for Swimlanes and GraphQL boards
parent 2b6d2bdd
......@@ -27,6 +27,11 @@ export default class FilteredSearchBoards extends FilteredSearchManager {
updateObject(path) {
this.store.path = path.substr(1);
if (gon.features.boardsWithSwimlanes) {
boardsStore.updateFiltersUrl();
boardsStore.performSearch();
}
if (this.updateUrl) {
boardsStore.updateFiltersUrl();
}
......
import $ from 'jquery';
import Vue from 'vue';
import { mapActions } from 'vuex';
import { mapActions, mapState } from 'vuex';
import 'ee_else_ce/boards/models/issue';
import 'ee_else_ce/boards/models/list';
......@@ -42,6 +42,7 @@ import {
NavigationType,
convertObjectPropsToCamelCase,
parseBoolean,
urlParamsToObject,
} from '~/lib/utils/common_utils';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import mountMultipleBoardsSwitcher from './mount_multiple_boards_switcher';
......@@ -104,6 +105,7 @@ export default () => {
};
},
computed: {
...mapState(['isShowingEpicsSwimlanes']),
detailIssueVisible() {
return Object.keys(this.detailIssue.issue).length;
},
......@@ -125,17 +127,21 @@ export default () => {
eventHub.$on('newDetailIssue', this.updateDetailIssue);
eventHub.$on('clearDetailIssue', this.clearDetailIssue);
sidebarEventHub.$on('toggleSubscription', this.toggleSubscription);
eventHub.$on('performSearch', this.performSearch);
},
beforeDestroy() {
eventHub.$off('updateTokens', this.updateTokens);
eventHub.$off('newDetailIssue', this.updateDetailIssue);
eventHub.$off('clearDetailIssue', this.clearDetailIssue);
sidebarEventHub.$off('toggleSubscription', this.toggleSubscription);
eventHub.$off('performSearch', this.performSearch);
},
mounted() {
this.filterManager = new FilteredSearchBoards(boardsStore.filter, true, boardsStore.cantEdit);
this.filterManager.setup();
this.performSearch();
boardsStore.disabled = this.disabled;
if (gon.features.graphqlBoardLists) {
......@@ -189,10 +195,16 @@ export default () => {
}
},
methods: {
...mapActions(['setInitialBoardData']),
...mapActions(['setInitialBoardData', 'setFilters', 'fetchEpicsSwimlanes']),
updateTokens() {
this.filterManager.updateTokens();
},
performSearch() {
this.setFilters(convertObjectPropsToCamelCase(urlParamsToObject(window.location.search)));
if (gon.features.boardsWithSwimlanes && this.isShowingEpicsSwimlanes) {
this.fetchEpicsSwimlanes(false);
}
},
updateDetailIssue(newIssue, multiSelect = false) {
const { sidebarInfoEndpoint } = newIssue;
if (sidebarInfoEndpoint && newIssue.subscribed === undefined) {
......
......@@ -21,6 +21,11 @@ export default {
commit(types.SET_ACTIVE_ID, id);
},
setFilters: ({ commit }, filters) => {
const { scope, utf8, state, ...filterParams } = filters;
commit(types.SET_FILTERS, filterParams);
},
fetchLists: () => {
notImplemented();
},
......
......@@ -513,6 +513,10 @@ const boardsStore = {
eventHub.$emit('updateTokens');
},
performSearch() {
eventHub.$emit('performSearch');
},
setListDetail(newList) {
this.detail.list = newList;
},
......
export const SET_INITIAL_BOARD_DATA = 'SET_INITIAL_BOARD_DATA';
export const SET_FILTERS = 'SET_FILTERS';
export const REQUEST_ADD_LIST = 'REQUEST_ADD_LIST';
export const RECEIVE_ADD_LIST_SUCCESS = 'RECEIVE_ADD_LIST_SUCCESS';
export const RECEIVE_ADD_LIST_ERROR = 'RECEIVE_ADD_LIST_ERROR';
......
......@@ -17,6 +17,10 @@ export default {
state.activeId = id;
},
[mutationTypes.SET_FILTERS](state, filterParams) {
state.filterParams = filterParams;
},
[mutationTypes.REQUEST_ADD_LIST]: () => {
notImplemented();
},
......
......@@ -8,6 +8,7 @@ export default () => ({
boardLists: [],
issuesByListId: {},
isLoadingIssues: false,
filterParams: {},
error: undefined,
// TODO: remove after ce/ee split of board_content.vue
isShowingEpicsSwimlanes: false,
......
#import "ee_else_ce/boards/queries/board_list.fragment.graphql"
#import "~/graphql_shared/fragments/epic.fragment.graphql"
query GroupBoardEE($fullPath: ID!, $boardId: ID!) {
group(fullPath: $fullPath) {
query BoardEE(
$fullPath: ID!
$boardId: ID!
$issueFilters: BoardEpicIssueInput
$withLists: Boolean = true
$isGroup: Boolean = false
$isProject: Boolean = false
) {
group(fullPath: $fullPath) @include(if: $isGroup) {
board(id: $boardId) {
lists {
lists @include(if: $withLists) {
nodes {
...BoardListFragment
}
}
epics {
epics(issueFilters: $issueFilters) {
nodes {
...EpicNode
}
}
}
}
project(fullPath: $fullPath) @include(if: $isProject) {
board(id: $boardId) {
lists @include(if: $withLists) {
nodes {
...BoardListFragment
}
}
epics(issueFilters: $issueFilters) {
nodes {
...EpicNode
}
......
#import "ee_else_ce/boards/queries/board_list.fragment.graphql"
#import "~/graphql_shared/fragments/epic.fragment.graphql"
query ProjectBoardEE($fullPath: ID!, $boardId: ID!) {
project(fullPath: $fullPath) {
board(id: $boardId) {
lists {
nodes {
...BoardListFragment
}
}
epics {
nodes {
...EpicNode
}
}
}
}
}
......@@ -8,7 +8,6 @@ import * as types from './mutation_types';
import createDefaultClient from '~/lib/graphql';
import { BoardType } from '~/boards/constants';
import groupEpicsSwimlanesQuery from '../queries/group_epics_swimlanes.query.graphql';
import projectEpicsSwimlanesQuery from '../queries/project_epics_swimlanes.query.graphql';
const notImplemented = () => {
/* eslint-disable-next-line @gitlab/require-i18n-strings */
......@@ -17,42 +16,49 @@ const notImplemented = () => {
const gqlClient = createDefaultClient();
const fetchEpicsSwimlanes = ({ endpoints, boardType }) => {
const { fullPath, boardId } = endpoints;
const query =
boardType === BoardType.group ? groupEpicsSwimlanesQuery : projectEpicsSwimlanesQuery;
const variables = {
fullPath,
boardId: `gid://gitlab/Board/${boardId}`,
};
return gqlClient
.query({
query,
variables,
})
.then(({ data }) => {
const { epics, lists } = data[boardType]?.board;
const epicsFormatted = epics.nodes.map(e => ({
...e,
issues: (e?.issues?.nodes || []).map(i => ({
...i,
labels: i.labels?.nodes || [],
assignees: i.assignees?.nodes || [],
})),
}));
return {
epics: epicsFormatted,
lists: lists.nodes,
};
});
};
export default {
...actionsCE,
fetchEpicsSwimlanes({ state, commit }, withLists = true) {
const { endpoints, boardType, filterParams } = state;
const { fullPath, boardId } = endpoints;
const variables = {
fullPath,
boardId: `gid://gitlab/Board/${boardId}`,
issueFilters: filterParams,
withLists,
isGroup: boardType === BoardType.group,
isProject: boardType === BoardType.project,
};
return gqlClient
.query({
query: groupEpicsSwimlanesQuery,
variables,
})
.then(({ data }) => {
const { epics, lists } = data[boardType]?.board;
const epicsFormatted = epics.nodes.map(e => ({
...e,
issues: (e?.issues?.nodes || []).map(i => ({
...i,
labels: i.labels?.nodes || [],
assignees: i.assignees?.nodes || [],
})),
}));
if (!withLists) {
commit(types.RECEIVE_EPICS_SUCCESS, epicsFormatted);
}
return {
epics: epicsFormatted,
lists: lists?.nodes,
};
});
},
setShowLabels({ commit }, val) {
commit(types.SET_SHOW_LABELS, val);
},
......@@ -91,11 +97,11 @@ export default {
notImplemented();
},
toggleEpicSwimlanes: ({ state, commit }) => {
toggleEpicSwimlanes: ({ state, commit, dispatch }) => {
commit(types.TOGGLE_EPICS_SWIMLANES);
if (state.isShowingEpicsSwimlanes) {
fetchEpicsSwimlanes(state)
dispatch('fetchEpicsSwimlanes')
.then(({ lists, epics }) => {
if (lists) {
let boardLists = lists.map(list =>
......
......@@ -26,6 +26,25 @@ describe('setInitialBoardData', () => {
});
});
describe('setFilters', () => {
it('should commit mutation SET_FILTERS', done => {
const state = {
filters: {},
};
const filters = { labelName: 'label' };
testAction(
actions.setFilters,
filters,
state,
[{ type: types.SET_FILTERS, payload: filters }],
[],
done,
);
});
});
describe('setActiveId', () => {
it('should commit mutation SET_ACTIVE_ID', done => {
const state = {
......
......@@ -44,6 +44,16 @@ describe('Board Store Mutations', () => {
});
});
describe('SET_FILTERS', () => {
it('updates filterParams to be the value that is passed', () => {
const filterParams = { labelName: 'label' };
mutations.SET_FILTERS(state, filterParams);
expect(state.filterParams).toBe(filterParams);
});
});
describe('REQUEST_ADD_LIST', () => {
expectNotImplemented(mutations.REQUEST_ADD_LIST);
});
......
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