Commit 575798ef authored by Kushal Pandya's avatar Kushal Pandya

Merge branch '323415-design-review-mvc-1' into 'master'

Epic Boards - MVC1 bug fixes [RUN AS-IF-FOSS]

See merge request gitlab-org/gitlab!55709
parents 7f0ad6bc 3ca1235e
...@@ -29,8 +29,8 @@ export default { ...@@ -29,8 +29,8 @@ export default {
}; };
}, },
computed: { computed: {
...mapState(['labels', 'labelsLoading', 'isEpicBoard']), ...mapState(['labels', 'labelsLoading']),
...mapGetters(['getListByLabelId', 'shouldUseGraphQL']), ...mapGetters(['getListByLabelId', 'shouldUseGraphQL', 'isEpicBoard']),
selectedLabel() { selectedLabel() {
if (!this.selectedId) { if (!this.selectedId) {
return null; return null;
......
...@@ -13,7 +13,7 @@ export default { ...@@ -13,7 +13,7 @@ export default {
</script> </script>
<template> <template>
<span class="gl-ml-3 gl-display-flex gl-align-items-center"> <span class="gl-ml-3 gl-display-flex gl-align-items-center" data-testid="boards-create-list">
<gl-button variant="confirm" @click="setAddColumnFormVisibility(true)" <gl-button variant="confirm" @click="setAddColumnFormVisibility(true)"
>{{ __('Create list') }} >{{ __('Create list') }}
</gl-button> </gl-button>
......
<script> <script>
import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui'; import { GlLabel, GlTooltipDirective, GlIcon } from '@gitlab/ui';
import { sortBy } from 'lodash'; import { sortBy } from 'lodash';
import { mapActions, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import boardCardInner from 'ee_else_ce/boards/mixins/board_card_inner'; import boardCardInner from 'ee_else_ce/boards/mixins/board_card_inner';
import { isScopedLabel } from '~/lib/utils/common_utils'; import { isScopedLabel } from '~/lib/utils/common_utils';
import { updateHistory } from '~/lib/utils/url_utility'; import { updateHistory } from '~/lib/utils/url_utility';
...@@ -52,7 +52,8 @@ export default { ...@@ -52,7 +52,8 @@ export default {
}; };
}, },
computed: { computed: {
...mapState(['isShowingLabels', 'isEpicBoard']), ...mapState(['isShowingLabels']),
...mapGetters(['isEpicBoard']),
cappedAssignees() { cappedAssignees() {
// e.g. maxRender is 4, // e.g. maxRender is 4,
// Render up to all 4 assignees if there are only 4 assigness // Render up to all 4 assignees if there are only 4 assigness
......
...@@ -38,8 +38,8 @@ export default { ...@@ -38,8 +38,8 @@ export default {
}, },
}, },
computed: { computed: {
...mapState(['boardLists', 'error', 'addColumnForm', 'isEpicBoard']), ...mapState(['boardLists', 'error', 'addColumnForm']),
...mapGetters(['isSwimlanesOn']), ...mapGetters(['isSwimlanesOn', 'isEpicBoard']),
addColumnFormVisible() { addColumnFormVisible() {
return this.addColumnForm?.visible; return this.addColumnForm?.visible;
}, },
......
<script> <script>
import { GlModal } from '@gitlab/ui'; import { GlModal } from '@gitlab/ui';
import { mapGetters } from 'vuex';
import { deprecatedCreateFlash as Flash } from '~/flash'; import { deprecatedCreateFlash as Flash } from '~/flash';
import { convertToGraphQLId } from '~/graphql_shared/utils'; import { convertToGraphQLId } from '~/graphql_shared/utils';
import { getParameterByName } from '~/lib/utils/common_utils'; import { getParameterByName } from '~/lib/utils/common_utils';
...@@ -106,6 +107,7 @@ export default { ...@@ -106,6 +107,7 @@ export default {
}; };
}, },
computed: { computed: {
...mapGetters(['isEpicBoard']),
isNewForm() { isNewForm() {
return this.currentPage === formType.new; return this.currentPage === formType.new;
}, },
...@@ -322,7 +324,7 @@ export default { ...@@ -322,7 +324,7 @@ export default {
/> />
<board-scope <board-scope
v-if="scopedIssueBoardFeatureEnabled" v-if="scopedIssueBoardFeatureEnabled && !isEpicBoard"
:collapse-scope="isNewForm" :collapse-scope="isNewForm"
:board="board" :board="board"
:can-admin-board="canAdminBoard" :can-admin-board="canAdminBoard"
......
<script> <script>
import { GlLoadingIcon } from '@gitlab/ui'; import { GlLoadingIcon } from '@gitlab/ui';
import Draggable from 'vuedraggable'; import Draggable from 'vuedraggable';
import { mapActions, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import { sortableStart, sortableEnd } from '~/boards/mixins/sortable_default_options'; import { sortableStart, sortableEnd } from '~/boards/mixins/sortable_default_options';
import { sprintf, __ } from '~/locale'; import { sprintf, __ } from '~/locale';
import defaultSortableConfig from '~/sortable/sortable_config'; import defaultSortableConfig from '~/sortable/sortable_config';
...@@ -49,6 +49,7 @@ export default { ...@@ -49,6 +49,7 @@ export default {
}, },
computed: { computed: {
...mapState(['pageInfoByListId', 'listsFlags']), ...mapState(['pageInfoByListId', 'listsFlags']),
...mapGetters(['isEpicBoard']),
paginatedIssueText() { paginatedIssueText() {
return sprintf(__('Showing %{pageSize} of %{total} issues'), { return sprintf(__('Showing %{pageSize} of %{total} issues'), {
pageSize: this.boardItems.length, pageSize: this.boardItems.length,
...@@ -69,13 +70,13 @@ export default { ...@@ -69,13 +70,13 @@ export default {
}, },
listRef() { listRef() {
// When list is draggable, the reference to the list needs to be accessed differently // When list is draggable, the reference to the list needs to be accessed differently
return this.canAdminList ? this.$refs.list.$el : this.$refs.list; return this.canAdminList && !this.isEpicBoard ? this.$refs.list.$el : this.$refs.list;
}, },
showingAllIssues() { showingAllIssues() {
return this.boardItems.length === this.list.issuesCount; return this.boardItems.length === this.list.issuesCount;
}, },
treeRootWrapper() { treeRootWrapper() {
return this.canAdminList ? Draggable : 'ul'; return this.canAdminList && !this.isEpicBoard ? Draggable : 'ul';
}, },
treeRootOptions() { treeRootOptions() {
const options = { const options = {
......
...@@ -8,7 +8,7 @@ import { ...@@ -8,7 +8,7 @@ import {
GlSprintf, GlSprintf,
GlTooltipDirective, GlTooltipDirective,
} from '@gitlab/ui'; } from '@gitlab/ui';
import { mapActions, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import { isListDraggable } from '~/boards/boards_util'; import { isListDraggable } from '~/boards/boards_util';
import { isScopedLabel, parseBoolean } from '~/lib/utils/common_utils'; import { isScopedLabel, parseBoolean } from '~/lib/utils/common_utils';
import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants'; import { BV_HIDE_TOOLTIP } from '~/lib/utils/constants';
...@@ -69,7 +69,8 @@ export default { ...@@ -69,7 +69,8 @@ export default {
}, },
}, },
computed: { computed: {
...mapState(['activeId', 'isEpicBoard']), ...mapState(['activeId']),
...mapGetters(['isEpicBoard']),
isLoggedIn() { isLoggedIn() {
return Boolean(this.currentUserId); return Boolean(this.currentUserId);
}, },
......
import { __ } from '~/locale'; import { __ } from '~/locale';
export const issuableTypes = {
issue: 'issue',
epic: 'epic',
};
export const BoardType = { export const BoardType = {
project: 'project', project: 'project',
group: 'group', group: 'group',
......
...@@ -23,6 +23,7 @@ import '~/boards/models/milestone'; ...@@ -23,6 +23,7 @@ import '~/boards/models/milestone';
import '~/boards/models/project'; import '~/boards/models/project';
import '~/boards/filters/due_date_filters'; import '~/boards/filters/due_date_filters';
import BoardAddIssuesModal from '~/boards/components/modal/index.vue'; import BoardAddIssuesModal from '~/boards/components/modal/index.vue';
import { issuableTypes } from '~/boards/constants';
import eventHub from '~/boards/eventhub'; import eventHub from '~/boards/eventhub';
import FilteredSearchBoards from '~/boards/filtered_search_boards'; import FilteredSearchBoards from '~/boards/filtered_search_boards';
import modalMixin from '~/boards/mixins/modal_mixins'; import modalMixin from '~/boards/mixins/modal_mixins';
...@@ -124,6 +125,7 @@ export default () => { ...@@ -124,6 +125,7 @@ export default () => {
fullPath: $boardApp.dataset.fullPath, fullPath: $boardApp.dataset.fullPath,
boardType: this.parent, boardType: this.parent,
disabled: this.disabled, disabled: this.disabled,
issuableType: issuableTypes.issue,
boardConfig: { boardConfig: {
milestoneId: parseInt($boardApp.dataset.boardMilestoneId, 10), milestoneId: parseInt($boardApp.dataset.boardMilestoneId, 10),
milestoneTitle: $boardApp.dataset.boardMilestoneTitle || '', milestoneTitle: $boardApp.dataset.boardMilestoneTitle || '',
......
...@@ -48,10 +48,10 @@ export default (params = {}) => { ...@@ -48,10 +48,10 @@ export default (params = {}) => {
return { boardsSelectorProps }; return { boardsSelectorProps };
}, },
computed: { computed: {
...mapGetters(['shouldUseGraphQL']), ...mapGetters(['shouldUseGraphQL', 'isEpicBoard']),
}, },
render(createElement) { render(createElement) {
if (this.shouldUseGraphQL || params.isEpicBoard) { if (this.shouldUseGraphQL || this.isEpicBoard) {
return createElement(BoardsSelector, { return createElement(BoardsSelector, {
props: this.boardsSelectorProps, props: this.boardsSelectorProps,
}); });
......
...@@ -176,7 +176,7 @@ export default { ...@@ -176,7 +176,7 @@ export default {
}, },
fetchLabels: ({ state, commit, getters }, searchTerm) => { fetchLabels: ({ state, commit, getters }, searchTerm) => {
const { fullPath, boardType, isEpicBoard } = state; const { fullPath, boardType } = state;
const variables = { const variables = {
fullPath, fullPath,
...@@ -195,7 +195,7 @@ export default { ...@@ -195,7 +195,7 @@ export default {
.then(({ data }) => { .then(({ data }) => {
let labels = data[boardType]?.labels.nodes; let labels = data[boardType]?.labels.nodes;
if (!getters.shouldUseGraphQL && !isEpicBoard) { if (!getters.shouldUseGraphQL && !getters.isEpicBoard) {
labels = labels.map((label) => ({ labels = labels.map((label) => ({
...label, ...label,
id: getIdFromGraphQLId(label.id), id: getIdFromGraphQLId(label.id),
......
...@@ -38,6 +38,10 @@ export default { ...@@ -38,6 +38,10 @@ export default {
return find(state.boardLists, (l) => l.title === title); return find(state.boardLists, (l) => l.title === title);
}, },
isEpicBoard: () => {
return false;
},
shouldUseGraphQL: () => { shouldUseGraphQL: () => {
return gon?.features?.graphqlBoardLists; return gon?.features?.graphqlBoardLists;
}, },
......
...@@ -32,13 +32,13 @@ export const addIssueToList = ({ state, listId, issueId, moveBeforeId, moveAfter ...@@ -32,13 +32,13 @@ export const addIssueToList = ({ state, listId, issueId, moveBeforeId, moveAfter
export default { export default {
[mutationTypes.SET_INITIAL_BOARD_DATA](state, data) { [mutationTypes.SET_INITIAL_BOARD_DATA](state, data) {
const { boardType, disabled, boardId, fullPath, boardConfig, isEpicBoard } = data; const { boardType, disabled, boardId, fullPath, boardConfig, issuableType } = data;
state.boardId = boardId; state.boardId = boardId;
state.fullPath = fullPath; state.fullPath = fullPath;
state.boardType = boardType; state.boardType = boardType;
state.disabled = disabled; state.disabled = disabled;
state.boardConfig = boardConfig; state.boardConfig = boardConfig;
state.isEpicBoard = isEpicBoard; state.issuableType = issuableType;
}, },
[mutationTypes.RECEIVE_BOARD_LISTS_SUCCESS]: (state, lists) => { [mutationTypes.RECEIVE_BOARD_LISTS_SUCCESS]: (state, lists) => {
......
...@@ -2,6 +2,7 @@ import { inactiveId, ListType } from '~/boards/constants'; ...@@ -2,6 +2,7 @@ import { inactiveId, ListType } from '~/boards/constants';
export default () => ({ export default () => ({
boardType: null, boardType: null,
issuableType: null,
fullPath: null, fullPath: null,
disabled: false, disabled: false,
isShowingLabels: true, isShowingLabels: true,
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
color: var(--gray-500, $gray-500); color: var(--gray-500, $gray-500);
} }
[data-page$='epic_boards:index'],
[data-page$='epic_boards:show'], [data-page$='epic_boards:show'],
.issue-boards-page { .issue-boards-page {
.content-wrapper { .content-wrapper {
...@@ -37,8 +38,11 @@ ...@@ -37,8 +38,11 @@
} }
} }
[data-page$='epic_boards:show'] .filter-form { [data-page$='epic_boards:index'],
[data-page$='epic_boards:show'] {
.filter-form {
display: none; display: none;
}
} }
.boards-app { .boards-app {
......
...@@ -5,7 +5,10 @@ ...@@ -5,7 +5,10 @@
- placeholder = local_assigns[:placeholder] || _('Search or filter results...') - placeholder = local_assigns[:placeholder] || _('Search or filter results...')
- is_not_boards_modal_or_productivity_analytics = type != :boards_modal && type != :productivity_analytics - is_not_boards_modal_or_productivity_analytics = type != :boards_modal && type != :productivity_analytics
- block_css_class = is_not_boards_modal_or_productivity_analytics ? 'row-content-block second-block' : '' - block_css_class = is_not_boards_modal_or_productivity_analytics ? 'row-content-block second-block' : ''
- user_can_admin_list = board && can?(current_user, :admin_issue_board_list, board.resource_parent) - if board && board.to_type == "EpicBoard"
- user_can_admin_list = can?(current_user, :admin_epic_board_list, board.resource_parent)
- elsif board
- user_can_admin_list = can?(current_user, :admin_issue_board_list, board.resource_parent)
.issues-filters{ class: ("w-100" if type == :boards_modal) } .issues-filters{ class: ("w-100" if type == :boards_modal) }
.issues-details-filters.filtered-search-block.d-flex.flex-column.flex-lg-row{ class: block_css_class, "v-pre" => type == :boards_modal } .issues-details-filters.filtered-search-block.d-flex.flex-column.flex-lg-row{ class: block_css_class, "v-pre" => type == :boards_modal }
......
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
// This is a false violation of @gitlab/no-runtime-template-compiler, since it // This is a false violation of @gitlab/no-runtime-template-compiler, since it
// extends a valid Vue single file component. // extends a valid Vue single file component.
/* eslint-disable @gitlab/no-runtime-template-compiler */ /* eslint-disable @gitlab/no-runtime-template-compiler */
import { mapState } from 'vuex'; import { mapGetters } from 'vuex';
import BoardFormFoss from '~/boards/components/board_form.vue'; import BoardFormFoss from '~/boards/components/board_form.vue';
import createEpicBoardMutation from '../graphql/epic_board_create.mutation.graphql'; import createEpicBoardMutation from '../graphql/epic_board_create.mutation.graphql';
export default { export default {
extends: BoardFormFoss, extends: BoardFormFoss,
computed: { computed: {
...mapState(['isEpicBoard']), ...mapGetters(['isEpicBoard']),
epicBoardCreateQuery() { epicBoardCreateQuery() {
return createEpicBoardMutation; return createEpicBoardMutation;
}, },
......
<script> <script>
import { mapState } from 'vuex'; import { mapGetters } from 'vuex';
// This is a false violation of @gitlab/no-runtime-template-compiler, since it // This is a false violation of @gitlab/no-runtime-template-compiler, since it
// extends a valid Vue single file component. // extends a valid Vue single file component.
/* eslint-disable @gitlab/no-runtime-template-compiler */ /* eslint-disable @gitlab/no-runtime-template-compiler */
...@@ -10,7 +10,7 @@ export default { ...@@ -10,7 +10,7 @@ export default {
extends: BoardListHeaderFoss, extends: BoardListHeaderFoss,
inject: ['weightFeatureAvailable'], inject: ['weightFeatureAvailable'],
computed: { computed: {
...mapState(['isEpicBoard']), ...mapGetters(['isEpicBoard']),
countIcon() { countIcon() {
return this.isEpicBoard ? 'epic' : 'issues'; return this.isEpicBoard ? 'epic' : 'issues';
}, },
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// This is a false violation of @gitlab/no-runtime-template-compiler, since it // This is a false violation of @gitlab/no-runtime-template-compiler, since it
// extends a valid Vue single file component. // extends a valid Vue single file component.
/* eslint-disable @gitlab/no-runtime-template-compiler */ /* eslint-disable @gitlab/no-runtime-template-compiler */
import { mapState } from 'vuex'; import { mapGetters } from 'vuex';
import BoardsSelectorFoss from '~/boards/components/boards_selector.vue'; import BoardsSelectorFoss from '~/boards/components/boards_selector.vue';
import { getIdFromGraphQLId } from '~/graphql_shared/utils'; import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import epicBoardsQuery from '../graphql/epic_boards.query.graphql'; import epicBoardsQuery from '../graphql/epic_boards.query.graphql';
...@@ -10,7 +10,7 @@ import epicBoardsQuery from '../graphql/epic_boards.query.graphql'; ...@@ -10,7 +10,7 @@ import epicBoardsQuery from '../graphql/epic_boards.query.graphql';
export default { export default {
extends: BoardsSelectorFoss, extends: BoardsSelectorFoss,
computed: { computed: {
...mapState(['isEpicBoard']), ...mapGetters(['isEpicBoard']),
showCreate() { showCreate() {
return this.isEpicBoard || this.multipleIssueBoardsAvailable; return this.isEpicBoard || this.multipleIssueBoardsAvailable;
}, },
......
...@@ -148,7 +148,7 @@ export default { ...@@ -148,7 +148,7 @@ export default {
commit(types.SET_FILTERS, filterParams); commit(types.SET_FILTERS, filterParams);
}, },
performSearch({ dispatch, getters, state }) { performSearch({ dispatch, getters }) {
dispatch( dispatch(
'setFilters', 'setFilters',
convertObjectPropsToCamelCase(urlParamsToObject(window.location.search)), convertObjectPropsToCamelCase(urlParamsToObject(window.location.search)),
...@@ -158,7 +158,7 @@ export default { ...@@ -158,7 +158,7 @@ export default {
dispatch('resetEpics'); dispatch('resetEpics');
dispatch('resetIssues'); dispatch('resetIssues');
dispatch('fetchEpicsSwimlanes', {}); dispatch('fetchEpicsSwimlanes', {});
} else if (gon.features.graphqlBoardLists || state.isEpicBoard) { } else if (gon.features.graphqlBoardLists || getters.isEpicBoard) {
dispatch('fetchLists'); dispatch('fetchLists');
dispatch('resetIssues'); dispatch('resetIssues');
} }
...@@ -300,7 +300,10 @@ export default { ...@@ -300,7 +300,10 @@ export default {
notImplemented(); notImplemented();
}, },
fetchItemsForList: ({ state, commit }, { listId, fetchNext = false, noEpicIssues = false }) => { fetchItemsForList: (
{ state, commit, getters },
{ listId, fetchNext = false, noEpicIssues = false },
) => {
commit(types.REQUEST_ITEMS_FOR_LIST, { listId, fetchNext }); commit(types.REQUEST_ITEMS_FOR_LIST, { listId, fetchNext });
const { epicId, ...filterParams } = state.filterParams; const { epicId, ...filterParams } = state.filterParams;
...@@ -317,7 +320,7 @@ export default { ...@@ -317,7 +320,7 @@ export default {
first: 20, first: 20,
}; };
if (state.isEpicBoard) { if (getters.isEpicBoard) {
return fetchAndFormatListEpics(state, variables) return fetchAndFormatListEpics(state, variables)
.then(({ listItems, listPageInfo }) => { .then(({ listItems, listPageInfo }) => {
commit(types.RECEIVE_ITEMS_FOR_LIST_SUCCESS, { commit(types.RECEIVE_ITEMS_FOR_LIST_SUCCESS, {
...@@ -525,10 +528,8 @@ export default { ...@@ -525,10 +528,8 @@ export default {
); );
}, },
fetchLists: ({ state, dispatch }) => { fetchLists: ({ getters, dispatch }) => {
const { isEpicBoard } = state; if (!getters.isEpicBoard) {
if (!isEpicBoard) {
dispatch('fetchIssueLists'); dispatch('fetchIssueLists');
} else { } else {
dispatch('fetchEpicLists'); dispatch('fetchEpicLists');
...@@ -556,10 +557,8 @@ export default { ...@@ -556,10 +557,8 @@ export default {
.catch(() => commit(types.RECEIVE_BOARD_LISTS_FAILURE)); .catch(() => commit(types.RECEIVE_BOARD_LISTS_FAILURE));
}, },
createList: ({ state, dispatch }, { backlog, labelId, milestoneId, assigneeId }) => { createList: ({ getters, dispatch }, { backlog, labelId, milestoneId, assigneeId }) => {
const { isEpicBoard } = state; if (!getters.isEpicBoard) {
if (!isEpicBoard) {
dispatch('createIssueList', { backlog, labelId, milestoneId, assigneeId }); dispatch('createIssueList', { backlog, labelId, milestoneId, assigneeId });
} else { } else {
dispatch('createEpicList', { backlog, labelId }); dispatch('createEpicList', { backlog, labelId });
......
import { issuableTypes } from '~/boards/constants';
import gettersCE from '~/boards/stores/getters'; import gettersCE from '~/boards/stores/getters';
export default { export default {
...@@ -16,6 +17,10 @@ export default { ...@@ -16,6 +17,10 @@ export default {
return getters.getBoardItemsByList(listId).filter((i) => Boolean(i.epic) === false); return getters.getBoardItemsByList(listId).filter((i) => Boolean(i.epic) === false);
}, },
isEpicBoard: (state) => {
return state.issuableType === issuableTypes.epic;
},
shouldUseGraphQL: (state) => { shouldUseGraphQL: (state) => {
return state.isShowingEpicsSwimlanes || gon?.features?.graphqlBoardLists; return state.isShowingEpicsSwimlanes || gon?.features?.graphqlBoardLists;
}, },
......
import { union, unionBy } from 'lodash'; import { union, unionBy } from 'lodash';
import Vue from 'vue'; import Vue from 'vue';
import { moveIssueListHelper } from '~/boards/boards_util'; import { moveIssueListHelper } from '~/boards/boards_util';
import { issuableTypes } from '~/boards/constants';
import mutationsCE, { addIssueToList, removeIssueFromList } from '~/boards/stores/mutations'; import mutationsCE, { addIssueToList, removeIssueFromList } from '~/boards/stores/mutations';
import { s__ } from '~/locale'; import { s__ } from '~/locale';
import { ErrorMessages } from '../constants'; import { ErrorMessages } from '../constants';
...@@ -84,7 +85,10 @@ export default { ...@@ -84,7 +85,10 @@ export default {
}, },
[mutationTypes.RECEIVE_ITEMS_FOR_LIST_FAILURE]: (state, listId) => { [mutationTypes.RECEIVE_ITEMS_FOR_LIST_FAILURE]: (state, listId) => {
state.error = state.isEpicBoard ? ErrorMessages.fetchEpicsError : ErrorMessages.fetchIssueError; state.error =
state.issuableType === issuableTypes.epic
? ErrorMessages.fetchEpicsError
: ErrorMessages.fetchIssueError;
Vue.set(state.listsFlags, listId, { isLoading: false, isLoadingMore: false }); Vue.set(state.listsFlags, listId, { isLoading: false, isLoadingMore: false });
}, },
......
...@@ -12,5 +12,4 @@ export default () => ({ ...@@ -12,5 +12,4 @@ export default () => ({
epicsCacheById: {}, epicsCacheById: {},
epicFetchInProgress: false, epicFetchInProgress: false,
epicsFlags: {}, epicsFlags: {},
isEpicBoard: false,
}); });
...@@ -12,6 +12,7 @@ import toggleLabels from 'ee_component/boards/toggle_labels'; ...@@ -12,6 +12,7 @@ import toggleLabels from 'ee_component/boards/toggle_labels';
import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue'; import BoardAddNewColumnTrigger from '~/boards/components/board_add_new_column_trigger.vue';
import BoardContent from '~/boards/components/board_content.vue'; import BoardContent from '~/boards/components/board_content.vue';
import BoardAddIssuesModal from '~/boards/components/modal/index.vue'; import BoardAddIssuesModal from '~/boards/components/modal/index.vue';
import { issuableTypes } from '~/boards/constants';
import mountMultipleBoardsSwitcher from '~/boards/mount_multiple_boards_switcher'; import mountMultipleBoardsSwitcher from '~/boards/mount_multiple_boards_switcher';
import store from '~/boards/stores'; import store from '~/boards/stores';
import createDefaultClient from '~/lib/graphql'; import createDefaultClient from '~/lib/graphql';
...@@ -84,7 +85,7 @@ export default () => { ...@@ -84,7 +85,7 @@ export default () => {
fullPath: $boardApp.dataset.fullPath, fullPath: $boardApp.dataset.fullPath,
boardType: this.parent, boardType: this.parent,
disabled: this.disabled, disabled: this.disabled,
isEpicBoard: true, issuableType: issuableTypes.epic,
boardConfig: { boardConfig: {
milestoneId: parseInt($boardApp.dataset.boardMilestoneId, 10), milestoneId: parseInt($boardApp.dataset.boardMilestoneId, 10),
milestoneTitle: $boardApp.dataset.boardMilestoneTitle || '', milestoneTitle: $boardApp.dataset.boardMilestoneTitle || '',
...@@ -131,6 +132,5 @@ export default () => { ...@@ -131,6 +132,5 @@ export default () => {
mountMultipleBoardsSwitcher({ mountMultipleBoardsSwitcher({
fullPath: $boardApp.dataset.fullPath, fullPath: $boardApp.dataset.fullPath,
rootPath: $boardApp.dataset.boardsEndpoint, rootPath: $boardApp.dataset.boardsEndpoint,
isEpicBoard: true,
}); });
}; };
...@@ -79,6 +79,32 @@ RSpec.describe 'epic boards', :js do ...@@ -79,6 +79,32 @@ RSpec.describe 'epic boards', :js do
end end
end end
context 'when user can admin epic boards' do
before do
stub_licensed_features(epics: true)
group.add_maintainer(user)
sign_in(user)
visit_epic_boards_page
end
it "shows 'Create list' button" do
expect(page).to have_selector('[data-testid="boards-create-list"]')
end
end
context 'when user cannot admin epic boards' do
before do
stub_licensed_features(epics: true)
group.add_guest(user)
sign_in(user)
visit_epic_boards_page
end
it "does not show 'Create list'" do
expect(page).not_to have_selector('[data-testid="boards-create-list"]')
end
end
def visit_epic_boards_page def visit_epic_boards_page
visit group_epic_boards_path(group) visit group_epic_boards_path(group)
wait_for_requests wait_for_requests
......
...@@ -54,8 +54,8 @@ describe('BoardForm', () => { ...@@ -54,8 +54,8 @@ describe('BoardForm', () => {
const createStore = () => { const createStore = () => {
return new Vuex.Store({ return new Vuex.Store({
state: { getters: {
isEpicBoard: true, isEpicBoard: () => true,
}, },
}); });
}; };
......
...@@ -34,8 +34,8 @@ describe('BoardsSelector', () => { ...@@ -34,8 +34,8 @@ describe('BoardsSelector', () => {
const createStore = () => { const createStore = () => {
return new Vuex.Store({ return new Vuex.Store({
state: { getters: {
isEpicBoard: false, isEpicBoard: () => false,
}, },
}); });
}; };
......
...@@ -7,6 +7,7 @@ import * as types from 'ee/boards/stores/mutation_types'; ...@@ -7,6 +7,7 @@ import * as types from 'ee/boards/stores/mutation_types';
import { TEST_HOST } from 'helpers/test_constants'; import { TEST_HOST } from 'helpers/test_constants';
import testAction from 'helpers/vuex_action_helper'; import testAction from 'helpers/vuex_action_helper';
import { formatListIssues, formatBoardLists } from '~/boards/boards_util'; import { formatListIssues, formatBoardLists } from '~/boards/boards_util';
import { issuableTypes } from '~/boards/constants';
import * as typesCE from '~/boards/stores/mutation_types'; import * as typesCE from '~/boards/stores/mutation_types';
import * as commonUtils from '~/lib/utils/common_utils'; import * as commonUtils from '~/lib/utils/common_utils';
import { mergeUrlParams, removeParams } from '~/lib/utils/url_utility'; import { mergeUrlParams, removeParams } from '~/lib/utils/url_utility';
...@@ -136,18 +137,20 @@ describe('performSearch', () => { ...@@ -136,18 +137,20 @@ describe('performSearch', () => {
}); });
describe('fetchLists', () => { describe('fetchLists', () => {
it('should dispatch fetchIssueLists action when isEpicBoard is false on state', async () => { it('should dispatch fetchIssueLists action when isEpicBoard is false', async () => {
const getters = { isEpicBoard: false };
await testAction({ await testAction({
action: actions.fetchLists, action: actions.fetchLists,
state: { isEpicBoard: false }, state: { issuableType: issuableTypes.issue, ...getters },
expectedActions: [{ type: 'fetchIssueLists' }], expectedActions: [{ type: 'fetchIssueLists' }],
}); });
}); });
it('should dispatch fetchEpicLists action when isEpicBoard is true on state', async () => { it('should dispatch fetchEpicLists action when isEpicBoard is true', async () => {
const getters = { isEpicBoard: true };
await testAction({ await testAction({
action: actions.fetchLists, action: actions.fetchLists,
state: { isEpicBoard: true }, state: { issuableType: issuableTypes.epic, ...getters },
expectedActions: [{ type: 'fetchEpicLists' }], expectedActions: [{ type: 'fetchEpicLists' }],
}); });
}); });
...@@ -949,15 +952,15 @@ describe('moveIssue', () => { ...@@ -949,15 +952,15 @@ describe('moveIssue', () => {
}); });
describe.each` describe.each`
isEpicBoard | dispatchedAction isEpicBoard | issuableType | dispatchedAction
${false} | ${'createIssueList'} ${false} | ${'issuableTypes.issue'} | ${'createIssueList'}
${true} | ${'createEpicList'} ${true} | ${'issuableTypes.epic'} | ${'createEpicList'}
`('createList', ({ isEpicBoard, dispatchedAction }) => { `('createList', ({ isEpicBoard, issuableType, dispatchedAction }) => {
it(`should dispatch ${dispatchedAction} action when isEpicBoard is ${isEpicBoard} on state`, async () => { it(`should dispatch ${dispatchedAction} action when isEpicBoard is ${isEpicBoard}`, async () => {
await testAction({ await testAction({
action: actions.createList, action: actions.createList,
payload: { backlog: true }, payload: { backlog: true },
state: { isEpicBoard }, state: { isEpicBoard, issuableType },
expectedActions: [{ type: dispatchedAction, payload: { backlog: true } }], expectedActions: [{ type: dispatchedAction, payload: { backlog: true } }],
}); });
}); });
......
...@@ -19,6 +19,7 @@ const createStore = (state = defaultState) => { ...@@ -19,6 +19,7 @@ const createStore = (state = defaultState) => {
return new Vuex.Store({ return new Vuex.Store({
state, state,
actions, actions,
getters: { isEpicBoard: () => false },
}); });
}; };
......
...@@ -29,6 +29,7 @@ describe('Board card layout', () => { ...@@ -29,6 +29,7 @@ describe('Board card layout', () => {
actions: mockActions, actions: mockActions,
getters: { getters: {
isSwimlanesOn: () => isSwimlanesOn, isSwimlanesOn: () => isSwimlanesOn,
isEpicBoard: () => false,
}, },
}); });
}; };
......
...@@ -53,7 +53,7 @@ describe('Board List Header Component', () => { ...@@ -53,7 +53,7 @@ describe('Board List Header Component', () => {
store = new Vuex.Store({ store = new Vuex.Store({
state: {}, state: {},
actions: { updateList: updateListSpy, toggleListCollapsed: toggleListCollapsedSpy }, actions: { updateList: updateListSpy, toggleListCollapsed: toggleListCollapsedSpy },
getters: {}, getters: { isEpicBoard: () => false },
}); });
wrapper = extendedWrapper( wrapper = extendedWrapper(
......
import { issuableTypes } from '~/boards/constants';
import * as types from '~/boards/stores/mutation_types'; import * as types from '~/boards/stores/mutation_types';
import mutations from '~/boards/stores/mutations'; import mutations from '~/boards/stores/mutations';
import defaultState from '~/boards/stores/state'; import defaultState from '~/boards/stores/state';
...@@ -37,7 +38,7 @@ describe('Board Store Mutations', () => { ...@@ -37,7 +38,7 @@ describe('Board Store Mutations', () => {
const boardConfig = { const boardConfig = {
milestoneTitle: 'Milestone 1', milestoneTitle: 'Milestone 1',
}; };
const isEpicBoard = true; const issuableType = issuableTypes.issue;
mutations[types.SET_INITIAL_BOARD_DATA](state, { mutations[types.SET_INITIAL_BOARD_DATA](state, {
boardId, boardId,
...@@ -45,7 +46,7 @@ describe('Board Store Mutations', () => { ...@@ -45,7 +46,7 @@ describe('Board Store Mutations', () => {
boardType, boardType,
disabled, disabled,
boardConfig, boardConfig,
isEpicBoard, issuableType,
}); });
expect(state.boardId).toEqual(boardId); expect(state.boardId).toEqual(boardId);
...@@ -53,7 +54,7 @@ describe('Board Store Mutations', () => { ...@@ -53,7 +54,7 @@ describe('Board Store Mutations', () => {
expect(state.boardType).toEqual(boardType); expect(state.boardType).toEqual(boardType);
expect(state.disabled).toEqual(disabled); expect(state.disabled).toEqual(disabled);
expect(state.boardConfig).toEqual(boardConfig); expect(state.boardConfig).toEqual(boardConfig);
expect(state.isEpicBoard).toEqual(isEpicBoard); expect(state.issuableType).toEqual(issuableType);
}); });
}); });
......
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