Commit 89bea703 authored by Florie Guibert's avatar Florie Guibert

Swimlanes - Paginate epics

Chain fetch epics by chunks of 20
parent 83dede41
......@@ -155,7 +155,13 @@ export default () => {
}
},
methods: {
...mapActions(['setInitialBoardData', 'setFilters', 'fetchEpicsSwimlanes', 'resetIssues']),
...mapActions([
'setInitialBoardData',
'setFilters',
'fetchEpicsSwimlanes',
'resetIssues',
'resetEpics',
]),
initialBoardLoad() {
boardsStore
.all()
......@@ -176,7 +182,8 @@ export default () => {
performSearch() {
this.setFilters(convertObjectPropsToCamelCase(urlParamsToObject(window.location.search)));
if (gon.features.boardsWithSwimlanes && this.isShowingEpicsSwimlanes) {
this.fetchEpicsSwimlanes(false);
this.resetEpics();
this.fetchEpicsSwimlanes({ withLists: false });
this.resetIssues();
}
},
......
......@@ -8,6 +8,7 @@ query BoardEE(
$withLists: Boolean = true
$isGroup: Boolean = false
$isProject: Boolean = false
$after: String
) {
group(fullPath: $fullPath) @include(if: $isGroup) {
board(id: $boardId) {
......@@ -16,9 +17,15 @@ query BoardEE(
...BoardListFragment
}
}
epics(issueFilters: $issueFilters) {
nodes {
...BoardEpicNode
epics(first: 2, issueFilters: $issueFilters, after: $after) {
edges {
node {
...BoardEpicNode
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
......@@ -30,9 +37,15 @@ query BoardEE(
...BoardListFragment
}
}
epics(issueFilters: $issueFilters) {
nodes {
...BoardEpicNode
epics(first: 20, issueFilters: $issueFilters, after: $after) {
edges {
node {
...BoardEpicNode
}
}
pageInfo {
endCursor
hasNextPage
}
}
}
......
......@@ -75,7 +75,7 @@ export default {
commit(types.SET_FILTERS, filterParams);
},
fetchEpicsSwimlanes({ state, commit }, withLists = true) {
fetchEpicsSwimlanes({ state, commit, dispatch }, { withLists = true, endCursor = null }) {
const { endpoints, boardType, filterParams } = state;
const { fullPath, boardId } = endpoints;
......@@ -86,6 +86,7 @@ export default {
withLists,
isGroup: boardType === BoardType.group,
isProject: boardType === BoardType.project,
after: endCursor,
};
return gqlClient
......@@ -95,24 +96,27 @@ export default {
})
.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 || [],
})),
const epicsFormatted = epics.edges.map(e => ({
...e.node,
}));
if (!withLists) {
commit(types.RECEIVE_EPICS_SUCCESS, epicsFormatted);
}
if (epics.pageInfo?.hasNextPage) {
dispatch('fetchEpicsSwimlanes', {
withLists: false,
endCursor: epics.pageInfo.endCursor,
});
}
return {
epics: epicsFormatted,
lists: lists?.nodes,
};
});
})
.catch(() => commit(types.RECEIVE_SWIMLANES_FAILURE));
},
setShowLabels({ commit }, val) {
......@@ -206,7 +210,7 @@ export default {
commit(types.TOGGLE_EPICS_SWIMLANES);
if (state.isShowingEpicsSwimlanes) {
dispatch('fetchEpicsSwimlanes')
dispatch('fetchEpicsSwimlanes', {})
.then(({ lists, epics }) => {
if (lists) {
let boardLists = lists.map(list =>
......@@ -226,4 +230,8 @@ export default {
eventHub.$emit('initialBoardLoad');
}
},
resetEpics: ({ commit }) => {
commit(types.RESET_EPICS);
},
};
......@@ -20,5 +20,6 @@ export const TOGGLE_EPICS_SWIMLANES = 'TOGGLE_EPICS_SWIMLANES';
export const RECEIVE_BOARD_LISTS_SUCCESS = 'RECEIVE_BOARD_LISTS_SUCCESS';
export const RECEIVE_SWIMLANES_FAILURE = 'RECEIVE_SWIMLANES_FAILURE';
export const RECEIVE_EPICS_SUCCESS = 'RECEIVE_EPICS_SUCCESS';
export const RESET_EPICS = 'RESET_EPICS';
export const SET_SHOW_LABELS = 'SET_SHOW_LABELS';
export const SET_FILTERS = 'SET_FILTERS';
......@@ -103,6 +103,10 @@ export default {
},
[mutationTypes.RECEIVE_EPICS_SUCCESS]: (state, epics) => {
state.epics = epics;
Vue.set(state, 'epics', union(state.epics || [], epics));
},
[mutationTypes.RESET_EPICS]: state => {
Vue.set(state, 'epics', []);
},
};
......@@ -5,6 +5,6 @@ export default () => ({
isShowingEpicsSwimlanes: false,
epicsSwimlanesFetchInProgress: false,
epics: {},
epics: [],
epicsFlags: {},
});
......@@ -63,6 +63,99 @@ describe('setFilters', () => {
});
});
describe('fetchEpicsSwimlanes', () => {
const state = {
endpoints: {
fullPath: 'gitlab-org',
boardId: 1,
},
filterParams: {},
boardType: 'group',
};
const queryResponse = {
data: {
group: {
board: {
epics: {
edges: [{ node: mockEpic }],
pageInfo: {},
},
},
},
},
};
it('should commit mutation RECEIVE_EPICS_SUCCESS on success without lists', done => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
testAction(
actions.fetchEpicsSwimlanes,
{ withLists: false },
state,
[
{
type: types.RECEIVE_EPICS_SUCCESS,
payload: [mockEpic],
},
],
[],
done,
);
});
it('should commit mutation RECEIVE_SWIMLANES_FAILURE on failure', done => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(Promise.reject());
testAction(
actions.fetchEpicsSwimlanes,
{},
state,
[{ type: types.RECEIVE_SWIMLANES_FAILURE }],
[],
done,
);
});
it('should dispatch fetchEpicsSwimlanes when page info hasNextPage', done => {
const queryResponseWithNextPage = {
data: {
group: {
board: {
epics: {
edges: [{ node: mockEpic }],
pageInfo: {
hasNextPage: true,
endCursor: 'ENDCURSOR',
},
},
},
},
},
};
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponseWithNextPage);
testAction(
actions.fetchEpicsSwimlanes,
{ withLists: false },
state,
[
{
type: types.RECEIVE_EPICS_SUCCESS,
payload: [mockEpic],
},
],
[
{
type: 'fetchEpicsSwimlanes',
payload: { withLists: false, endCursor: 'ENDCURSOR' },
},
],
done,
);
});
});
describe('setShowLabels', () => {
it('should commit mutation SET_SHOW_LABELS', done => {
const state = {
......@@ -251,3 +344,9 @@ describe('toggleEpicSwimlanes', () => {
);
});
});
describe('resetEpics', () => {
it('commits RESET_EPICS mutation', () => {
return testAction(actions.resetEpics, {}, {}, [{ type: types.RESET_EPICS }], []);
});
});
......@@ -205,7 +205,7 @@ describe('RECEIVE_SWIMLANES_FAILURE', () => {
});
describe('RECEIVE_EPICS_SUCCESS', () => {
it('populates epics with payload and set epicsFlags loading to true', () => {
it('populates epics with payload', () => {
state = {
...state,
epics: {},
......@@ -216,3 +216,16 @@ describe('RECEIVE_EPICS_SUCCESS', () => {
expect(state.epics).toEqual(mockEpics);
});
});
describe('RESET_EPICS', () => {
it('should remove issues from issuesByListId state', () => {
state = {
...state,
epics: mockEpics,
};
mutations.RESET_EPICS(state);
expect(state.epics).toEqual([]);
});
});
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