Commit 44ea3a4c authored by Enrique Alcántara's avatar Enrique Alcántara

Merge branch 'ss/sidebar-state' into 'master'

Boards Sidebar state

See merge request gitlab-org/gitlab!40553
parents b95dbfc3 e9e76315
......@@ -6,20 +6,29 @@ export function getMilestone() {
}
export function formatListIssues(listIssues) {
return listIssues.nodes.reduce((map, list) => {
const issues = {};
const listData = listIssues.nodes.reduce((map, list) => {
return {
...map,
[list.id]: list.issues.nodes.map(
i =>
new ListIssue({
[list.id]: list.issues.nodes.map(i => {
const id = getIdFromGraphQLId(i.id);
const listIssue = new ListIssue({
...i,
id: getIdFromGraphQLId(i.id),
id,
labels: i.labels?.nodes || [],
assignees: i.assignees?.nodes || [],
});
issues[id] = listIssue;
return id;
}),
),
};
}, {});
return { listData, issues };
}
export function fullBoardId(boardId) {
......
......@@ -10,4 +10,11 @@ export default {
return state.isShowingEpicsSwimlanes;
},
getIssueById: state => id => {
return state.issues[id] || {};
},
getActiveIssue: state => {
return state.issues[state.activeId] || {};
},
};
......@@ -72,8 +72,9 @@ export default {
state.isLoadingIssues = true;
},
[mutationTypes.RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS]: (state, listIssues) => {
state.issuesByListId = listIssues;
[mutationTypes.RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS]: (state, { listData, issues }) => {
state.issuesByListId = listData;
state.issues = issues;
state.isLoadingIssues = false;
},
......
......@@ -10,6 +10,7 @@ export default () => ({
sidebarType: '',
boardLists: [],
issuesByListId: {},
issues: {},
isLoadingIssues: false,
filterParams: {},
error: undefined,
......
......@@ -10,11 +10,14 @@ export default {
GlDrawer,
},
computed: {
...mapGetters(['isSidebarOpen']),
...mapGetters(['isSidebarOpen', 'getActiveIssue']),
...mapState(['sidebarType']),
showSidebar() {
return this.sidebarType === ISSUABLE;
},
issueTitle() {
return this.getActiveIssue.title;
},
},
methods: {
...mapActions(['unsetActiveId']),
......@@ -28,5 +31,12 @@ export default {
:open="isSidebarOpen"
:header-height="$options.headerHeight"
@close="unsetActiveId"
/>
>
<template #header>
<div data-testid="issue-title">
<p class="gl-font-weight-bold">{{ issueTitle }}</p>
<p class="gl-mb-0">{{ getActiveIssue.referencePath }}</p>
</div>
</template>
</gl-drawer>
</template>
......@@ -3,8 +3,10 @@ import gettersCE from '~/boards/stores/getters';
export default {
...gettersCE,
getIssues: state => listId => {
return state.issuesByListId[listId] || [];
getIssues: (state, getters) => listId => {
const listIssueIds = state.issuesByListId[listId] || [];
return listIssueIds.map(id => getters.getIssueById(id));
},
getIssuesByEpic: (state, getters) => (listId, epicId) => {
return getters.getIssues(listId).filter(issue => issue.epic && issue.epic.id === epicId);
......
import { shallowMount } from '@vue/test-utils';
import { mount } from '@vue/test-utils';
import { GlDrawer } from '@gitlab/ui';
import waitForPromises from 'helpers/wait_for_promises';
import BoardContentSidebar from 'ee_component/boards/components/board_content_sidebar.vue';
......@@ -10,7 +10,7 @@ describe('ee/BoardContentSidebar', () => {
let store;
const createComponent = () => {
wrapper = shallowMount(BoardContentSidebar, {
wrapper = mount(BoardContentSidebar, {
store,
});
};
......@@ -19,6 +19,8 @@ describe('ee/BoardContentSidebar', () => {
store = createStore();
store.state.sidebarType = ISSUABLE;
store.state.activeId = 1;
store.state.issues = { '1': { title: 'One', referencePath: 'path' } };
store.state.activeId = '1';
createComponent();
});
......@@ -35,6 +37,14 @@ describe('ee/BoardContentSidebar', () => {
expect(wrapper.find(GlDrawer).props('open')).toBe(true);
});
it('renders a title of an issue in the sidebar', () => {
expect(wrapper.find('[data-testid="issue-title"]').text()).toContain('One');
});
it('renders a referencePath of an issue in the sidebar', () => {
expect(wrapper.find('[data-testid="issue-title"]').text()).toContain('path');
});
describe('when we emit close', () => {
it('hides GlDrawer', async () => {
expect(wrapper.find(GlDrawer).props('open')).toBe(true);
......
......@@ -4,7 +4,7 @@ import EpicLane from 'ee/boards/components/epic_lane.vue';
import IssuesLaneList from 'ee/boards/components/issues_lane_list.vue';
import { GlIcon } from '@gitlab/ui';
import getters from 'ee/boards/stores/getters';
import { mockEpic, mockListsWithModel, mockIssuesByListId } from '../mock_data';
import { mockEpic, mockListsWithModel, mockIssuesByListId, issues } from '../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
......@@ -16,6 +16,7 @@ describe('EpicLane', () => {
return new Vuex.Store({
state: {
issuesByListId: mockIssuesByListId,
issues,
},
getters,
});
......
......@@ -6,7 +6,7 @@ import EpicLane from 'ee/boards/components/epic_lane.vue';
import IssueLaneList from 'ee/boards/components/issues_lane_list.vue';
import getters from 'ee/boards/stores/getters';
import { GlIcon } from '@gitlab/ui';
import { mockListsWithModel, mockEpics, mockIssuesByListId } from '../mock_data';
import { mockListsWithModel, mockEpics, mockIssuesByListId, issues } from '../mock_data';
const localVue = createLocalVue();
localVue.use(Vuex);
......@@ -23,6 +23,7 @@ describe('EpicsSwimlanes', () => {
epics: mockEpics,
isLoadingIssues: false,
issuesByListId: mockIssuesByListId,
issues,
},
getters,
});
......
......@@ -216,6 +216,13 @@ export const mockEpics = [
];
export const mockIssuesByListId = {
'gid://gitlab/List/1': [mockIssue, mockIssue3, mockIssue4],
'gid://gitlab/List/2': mockIssues,
'gid://gitlab/List/1': [mockIssue.id, mockIssue3.id, mockIssue4.id],
'gid://gitlab/List/2': mockIssues.map(({ id }) => id),
};
export const issues = {
[mockIssue.id]: mockIssue,
[mockIssue2.id]: mockIssue2,
[mockIssue3.id]: mockIssue3,
[mockIssue4.id]: mockIssue4,
};
import getters from 'ee/boards/stores/getters';
import { mockIssue, mockIssue3, mockIssue4, mockIssues, mockIssuesByListId } from '../mock_data';
import {
mockIssue,
mockIssue2,
mockIssue3,
mockIssue4,
mockIssues,
mockIssuesByListId,
issues,
} from '../mock_data';
describe('EE Boards Store Getters', () => {
const boardsState = {
issuesByListId: mockIssuesByListId,
issues,
};
describe('getIssues', () => {
it('returns issues for a given listId', () => {
expect(getters.getIssues(boardsState)('gid://gitlab/List/2')).toEqual(mockIssues);
const getIssueById = issueId => [mockIssue, mockIssue2].find(({ id }) => id === issueId);
expect(getters.getIssues(boardsState, { getIssueById })('gid://gitlab/List/2')).toEqual(
mockIssues,
);
});
});
......
......@@ -91,4 +91,28 @@ describe('Boards - Getters', () => {
});
});
});
describe('getIssueById', () => {
const state = { issues: { '1': 'issue' } };
it.each`
id | expected
${'1'} | ${'issue'}
${''} | ${{}}
`('returns $expected when $id is passed to state', ({ id, expected }) => {
expect(getters.getIssueById(state)(id)).toEqual(expected);
});
});
describe('getActiveIssue', () => {
it.each`
id | expected
${'1'} | ${'issue'}
${''} | ${{}}
`('returns $expected when $id is passed to state', ({ id, expected }) => {
const state = { issues: { '1': 'issue' }, activeId: id };
expect(getters.getActiveIssue(state)).toEqual(expected);
});
});
});
......@@ -129,19 +129,24 @@ describe('Board Store Mutations', () => {
describe('RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS', () => {
it('sets isLoadingIssues to false and updates issuesByListId object', () => {
const listIssues = {
'1': [mockIssue],
'1': [mockIssue.id],
};
const issues = {
'1': mockIssue,
};
state = {
...state,
isLoadingIssues: true,
issuesByListId: {},
issues: {},
};
mutations.RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS(state, listIssues);
mutations.RECEIVE_ISSUES_FOR_ALL_LISTS_SUCCESS(state, { listData: listIssues, issues });
expect(state.isLoadingIssues).toBe(false);
expect(state.issuesByListId).toEqual(listIssues);
expect(state.issues).toEqual(issues);
});
});
......
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