Commit 8d802266 authored by Jose Ivan Vargas's avatar Jose Ivan Vargas

Merge branch '285491-swimlanes-parallelize-graphql-calls' into 'master'

Swimlanes - Optimize/split queries

See merge request gitlab-org/gitlab!56810
parents fb781f4e 6d5a5c15
#import "ee_else_ce/boards/graphql/board_list.fragment.graphql"
#import "./board_epic.fragment.graphql"
query BoardEE(
$fullPath: ID!
$boardId: ID!
$issueFilters: BoardIssueInput
$withLists: Boolean = true
$isGroup: Boolean = false
$isProject: Boolean = false
$after: String
) {
group(fullPath: $fullPath) @include(if: $isGroup) {
board(id: $boardId) {
lists(issueFilters: $issueFilters) @include(if: $withLists) {
nodes {
...BoardListFragment
}
}
epics(first: 20, issueFilters: $issueFilters, after: $after) {
edges {
node {
......@@ -35,11 +28,6 @@ query BoardEE(
}
project(fullPath: $fullPath) @include(if: $isProject) {
board(id: $boardId) {
lists(issueFilters: $issueFilters) @include(if: $withLists) {
nodes {
...BoardListFragment
}
}
epics(first: 20, issueFilters: $issueFilters, after: $after) {
edges {
node {
......
......@@ -164,21 +164,21 @@ export default {
if (getters.isSwimlanesOn) {
dispatch('resetEpics');
dispatch('resetIssues');
dispatch('fetchEpicsSwimlanes', {});
dispatch('fetchEpicsSwimlanes');
dispatch('fetchIssueLists');
} else if (gon.features.graphqlBoardLists || getters.isEpicBoard) {
dispatch('fetchLists');
dispatch('resetIssues');
}
},
fetchEpicsSwimlanes({ state, commit, dispatch }, { withLists = true, endCursor = null }) {
fetchEpicsSwimlanes({ state, commit, dispatch }, { endCursor = null } = {}) {
const { fullPath, boardId, boardType, filterParams } = state;
const variables = {
fullPath,
boardId: `gid://gitlab/Board/${boardId}`,
issueFilters: filterParams,
withLists,
isGroup: boardType === BoardType.group,
isProject: boardType === BoardType.project,
after: endCursor,
......@@ -190,31 +190,21 @@ export default {
variables,
})
.then(({ data }) => {
const { epics, lists } = data[boardType]?.board;
const { epics } = data[boardType]?.board;
const epicsFormatted = epics.edges.map((e) => ({
...e.node,
}));
if (!withLists) {
commit(types.RECEIVE_EPICS_SUCCESS, epicsFormatted);
if (epicsFormatted) {
commit(types.RECEIVE_EPICS_SUCCESS, {
epics: epicsFormatted,
canAdminEpic: epics.edges[0]?.node?.userPermissions?.adminEpic,
});
commit(types.UPDATE_CACHED_EPICS, epicsFormatted);
} else {
if (lists) {
commit(types.RECEIVE_BOARD_LISTS_SUCCESS, formatBoardLists(lists));
}
if (epicsFormatted) {
commit(types.RECEIVE_FIRST_EPICS_SUCCESS, {
epics: epicsFormatted,
canAdminEpic: epics.edges[0]?.node?.userPermissions?.adminEpic,
});
commit(types.UPDATE_CACHED_EPICS, epicsFormatted);
}
}
if (epics.pageInfo?.hasNextPage) {
dispatch('fetchEpicsSwimlanes', {
withLists: false,
endCursor: epics.pageInfo.endCursor,
});
}
......@@ -377,7 +367,8 @@ export default {
spreadArrays: true,
}),
);
dispatch('fetchEpicsSwimlanes', {});
dispatch('fetchEpicsSwimlanes');
dispatch('fetchIssueLists');
} else if (!gon.features.graphqlBoardLists) {
historyPushState(removeParams(['group_by']), window.location.href, true);
boardsStore.create();
......@@ -387,10 +378,8 @@ export default {
}
},
setEpicSwimlanes: ({ commit, dispatch }) => {
setEpicSwimlanes: ({ commit }) => {
commit(types.SET_EPICS_SWIMLANES);
dispatch('fetchEpicsSwimlanes', {});
},
resetEpics: ({ commit }) => {
......@@ -454,7 +443,7 @@ export default {
const { epic } = data.issueSetEpic.issue;
if (epic !== null) {
commit(types.RECEIVE_FIRST_EPICS_SUCCESS, { epics: [epic, ...state.epics] });
commit(types.RECEIVE_EPICS_SUCCESS, { epics: [epic, ...state.epics] });
commit(types.UPDATE_CACHED_EPICS, [epic]);
}
......
......@@ -21,7 +21,6 @@ export const RECEIVE_BOARD_LISTS_FAILURE = 'RECEIVE_BOARD_LISTS_FAILURE';
export const UPDATE_LIST_SUCCESS = 'UPDATE_LIST_SUCCESS';
export const UPDATE_LIST_FAILURE = 'UPDATE_LIST_FAILURE';
export const RECEIVE_SWIMLANES_FAILURE = 'RECEIVE_SWIMLANES_FAILURE';
export const RECEIVE_FIRST_EPICS_SUCCESS = 'RECEIVE_FIRST_EPICS_SUCCESS';
export const RECEIVE_EPICS_SUCCESS = 'RECEIVE_EPICS_SUCCESS';
export const UPDATE_CACHED_EPICS = 'UPDATE_CACHED_EPICS';
export const SET_EPIC_FETCH_IN_PROGRESS = 'SET_EPIC_FETCH_IN_PROGRESS';
......
......@@ -136,17 +136,13 @@ export default {
state.epicsSwimlanesFetchInProgress = false;
},
[mutationTypes.RECEIVE_FIRST_EPICS_SUCCESS]: (state, { epics, canAdminEpic }) => {
[mutationTypes.RECEIVE_EPICS_SUCCESS]: (state, { epics, canAdminEpic }) => {
Vue.set(state, 'epics', unionBy(state.epics || [], epics, 'id'));
if (canAdminEpic !== undefined) {
state.canAdminEpic = canAdminEpic;
}
},
[mutationTypes.RECEIVE_EPICS_SUCCESS]: (state, epics) => {
Vue.set(state, 'epics', unionBy(state.epics || [], epics, 'id'));
},
[mutationTypes.UPDATE_CACHED_EPICS]: (state, epics) => {
epics.forEach((e) => {
Vue.set(state.epicsCacheById, e.id, e);
......
......@@ -135,7 +135,7 @@ describe('performSearch', () => {
});
});
it('should dispatch setFilters, resetEpics, fetchEpicsSwimlanes and resetIssues action when isSwimlanesOn', async () => {
it('should dispatch setFilters, resetEpics, fetchEpicsSwimlanes, fetchIssueLists and resetIssues action when isSwimlanesOn', async () => {
const getters = { isSwimlanesOn: true };
await testAction({
action: actions.performSearch,
......@@ -144,7 +144,8 @@ describe('performSearch', () => {
{ type: 'setFilters', payload: {} },
{ type: 'resetEpics' },
{ type: 'resetIssues' },
{ type: 'fetchEpicsSwimlanes', payload: {} },
{ type: 'fetchEpicsSwimlanes' },
{ type: 'fetchIssueLists' },
],
});
});
......@@ -242,17 +243,17 @@ describe('fetchEpicsSwimlanes', () => {
},
};
it('should commit mutation RECEIVE_EPICS_SUCCESS and UPDATE_CACHED_EPICS on success without lists', (done) => {
it('should commit mutation RECEIVE_EPICS_SUCCESS and UPDATE_CACHED_EPICS on success', (done) => {
jest.spyOn(gqlClient, 'query').mockResolvedValue(queryResponse);
testAction(
actions.fetchEpicsSwimlanes,
{ withLists: false },
{},
state,
[
{
type: types.RECEIVE_EPICS_SUCCESS,
payload: [mockEpic],
payload: { epics: [mockEpic] },
},
{
type: types.UPDATE_CACHED_EPICS,
......@@ -297,12 +298,12 @@ describe('fetchEpicsSwimlanes', () => {
testAction(
actions.fetchEpicsSwimlanes,
{ withLists: false },
{},
state,
[
{
type: types.RECEIVE_EPICS_SUCCESS,
payload: [mockEpic],
payload: { epics: [mockEpic] },
},
{
type: types.UPDATE_CACHED_EPICS,
......@@ -312,7 +313,7 @@ describe('fetchEpicsSwimlanes', () => {
[
{
type: 'fetchEpicsSwimlanes',
payload: { withLists: false, endCursor: 'ENDCURSOR' },
payload: { endCursor: 'ENDCURSOR' },
},
],
done,
......@@ -574,7 +575,7 @@ describe('toggleEpicSwimlanes', () => {
);
});
it('should dispatch fetchEpicsSwimlanes action when isShowingEpicsSwimlanes is true', () => {
it('should dispatch fetchEpicsSwimlanes and fetchIssueLists actions when isShowingEpicsSwimlanes is true', () => {
global.jsdom.reconfigure({
url: `${TEST_HOST}/groups/gitlab-org/-/boards/1`,
});
......@@ -592,7 +593,7 @@ describe('toggleEpicSwimlanes', () => {
null,
state,
[{ type: types.TOGGLE_EPICS_SWIMLANES }],
[{ type: 'fetchEpicsSwimlanes', payload: {} }],
[{ type: 'fetchEpicsSwimlanes' }, { type: 'fetchIssueLists' }],
() => {
expect(commonUtils.historyPushState).toHaveBeenCalledWith(
mergeUrlParams({ group_by: GroupByParamType.epic }, window.location.href),
......@@ -606,7 +607,7 @@ describe('toggleEpicSwimlanes', () => {
});
describe('setEpicSwimlanes', () => {
it('should commit mutation SET_EPICS_SWIMLANES and dispatch fetchEpicsSwimlanes action', () => {
it('should commit mutation SET_EPICS_SWIMLANES', () => {
jest.spyOn(gqlClient, 'query').mockResolvedValue({});
return testAction(
......@@ -614,7 +615,7 @@ describe('setEpicSwimlanes', () => {
null,
{},
[{ type: types.SET_EPICS_SWIMLANES }],
[{ type: 'fetchEpicsSwimlanes', payload: {} }],
[],
);
});
});
......@@ -726,7 +727,7 @@ describe('setActiveIssueEpic', () => {
};
describe('when the updated issue has an assigned epic', () => {
it('should commit mutation RECEIVE_FIRST_EPICS_SUCCESS, UPDATE_CACHED_EPICS and UPDATE_ISSUE_BY_ID on success', async () => {
it('should commit mutation RECEIVE_EPICS_SUCCESS, UPDATE_CACHED_EPICS and UPDATE_ISSUE_BY_ID on success', async () => {
jest
.spyOn(gqlClient, 'mutate')
.mockResolvedValue({ data: { issueSetEpic: { issue: { epic: epicWithData } } } });
......@@ -741,7 +742,7 @@ describe('setActiveIssueEpic', () => {
payload: true,
},
{
type: types.RECEIVE_FIRST_EPICS_SUCCESS,
type: types.RECEIVE_EPICS_SUCCESS,
payload: { epics: [epicWithData, ...state.epics] },
},
{
......
......@@ -205,7 +205,7 @@ describe('RECEIVE_SWIMLANES_FAILURE', () => {
});
});
describe('RECEIVE_FIRST_EPICS_SUCCESS', () => {
describe('RECEIVE_EPICS_SUCCESS', () => {
it('populates epics and canAdminEpic with payload', () => {
state = {
...state,
......@@ -213,7 +213,7 @@ describe('RECEIVE_FIRST_EPICS_SUCCESS', () => {
canAdminEpic: false,
};
mutations.RECEIVE_FIRST_EPICS_SUCCESS(state, { epics: mockEpics, canAdminEpic: true });
mutations.RECEIVE_EPICS_SUCCESS(state, { epics: mockEpics, canAdminEpic: true });
expect(state.epics).toEqual(mockEpics);
expect(state.canAdminEpic).toEqual(true);
......@@ -226,30 +226,6 @@ describe('RECEIVE_FIRST_EPICS_SUCCESS', () => {
canAdminEpic: false,
};
mutations.RECEIVE_FIRST_EPICS_SUCCESS(state, mockEpics);
expect(state.epics).toEqual(mockEpics);
});
});
describe('RECEIVE_EPICS_SUCCESS', () => {
it('populates epics with payload', () => {
state = {
...state,
epics: {},
};
mutations.RECEIVE_EPICS_SUCCESS(state, mockEpics);
expect(state.epics).toEqual(mockEpics);
});
it("doesn't add duplicate epics", () => {
state = {
...state,
epics: mockEpics,
};
mutations.RECEIVE_EPICS_SUCCESS(state, mockEpics);
expect(state.epics).toEqual(mockEpics);
......
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