diff options
Diffstat (limited to 'app/assets/javascripts/boards/stores')
-rw-r--r-- | app/assets/javascripts/boards/stores/actions.js | 105 | ||||
-rw-r--r-- | app/assets/javascripts/boards/stores/boards_store.js | 22 | ||||
-rw-r--r-- | app/assets/javascripts/boards/stores/getters.js | 10 | ||||
-rw-r--r-- | app/assets/javascripts/boards/stores/index.js | 4 | ||||
-rw-r--r-- | app/assets/javascripts/boards/stores/mutation_types.js | 7 | ||||
-rw-r--r-- | app/assets/javascripts/boards/stores/mutations.js | 34 | ||||
-rw-r--r-- | app/assets/javascripts/boards/stores/state.js | 4 |
7 files changed, 124 insertions, 62 deletions
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js index 1d34f21798a..a7cf1e9e647 100644 --- a/app/assets/javascripts/boards/stores/actions.js +++ b/app/assets/javascripts/boards/stores/actions.js @@ -1,11 +1,9 @@ import { pick } from 'lodash'; - import boardListsQuery from 'ee_else_ce/boards/graphql/board_lists.query.graphql'; -import createGqClient, { fetchPolicies } from '~/lib/graphql'; +import { BoardType, ListType, inactiveId, flashAnimationDuration } from '~/boards/constants'; import { getIdFromGraphQLId } from '~/graphql_shared/utils'; +import createGqClient, { fetchPolicies } from '~/lib/graphql'; import { convertObjectPropsToCamelCase, urlParamsToObject } from '~/lib/utils/common_utils'; -import { BoardType, ListType, inactiveId } from '~/boards/constants'; -import * as types from './mutation_types'; import { formatBoardLists, formatListIssues, @@ -14,23 +12,22 @@ import { formatIssue, formatIssueInput, updateListPosition, + transformNotFilters, } from '../boards_util'; -import createFlash from '~/flash'; -import { __ } from '~/locale'; -import updateAssigneesMutation from '~/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql'; -import listsIssuesQuery from '../graphql/lists_issues.query.graphql'; import boardLabelsQuery from '../graphql/board_labels.query.graphql'; import createBoardListMutation from '../graphql/board_list_create.mutation.graphql'; -import updateBoardListMutation from '../graphql/board_list_update.mutation.graphql'; -import issueMoveListMutation from '../graphql/issue_move_list.mutation.graphql'; import destroyBoardListMutation from '../graphql/board_list_destroy.mutation.graphql'; +import updateBoardListMutation from '../graphql/board_list_update.mutation.graphql'; +import groupProjectsQuery from '../graphql/group_projects.query.graphql'; import issueCreateMutation from '../graphql/issue_create.mutation.graphql'; -import issueSetLabelsMutation from '../graphql/issue_set_labels.mutation.graphql'; +import issueMoveListMutation from '../graphql/issue_move_list.mutation.graphql'; import issueSetDueDateMutation from '../graphql/issue_set_due_date.mutation.graphql'; -import issueSetSubscriptionMutation from '../graphql/issue_set_subscription.mutation.graphql'; +import issueSetLabelsMutation from '../graphql/issue_set_labels.mutation.graphql'; import issueSetMilestoneMutation from '../graphql/issue_set_milestone.mutation.graphql'; +import issueSetSubscriptionMutation from '../graphql/issue_set_subscription.mutation.graphql'; import issueSetTitleMutation from '../graphql/issue_set_title.mutation.graphql'; -import groupProjectsQuery from '../graphql/group_projects.query.graphql'; +import listsIssuesQuery from '../graphql/lists_issues.query.graphql'; +import * as types from './mutation_types'; const notImplemented = () => { /* eslint-disable-next-line @gitlab/require-i18n-strings */ @@ -66,6 +63,7 @@ export default { 'releaseTag', 'search', ]); + filterParams.not = transformNotFilters(filters); commit(types.SET_FILTERS, filterParams); }, @@ -108,9 +106,31 @@ export default { .catch(() => commit(types.RECEIVE_BOARD_LISTS_FAILURE)); }, - createList: ({ state, commit, dispatch }, { backlog, labelId, milestoneId, assigneeId }) => { + highlightList: ({ commit, state }, listId) => { + if ([ListType.backlog, ListType.closed].includes(state.boardLists[listId].listType)) { + return; + } + + commit(types.ADD_LIST_TO_HIGHLIGHTED_LISTS, listId); + + setTimeout(() => { + commit(types.REMOVE_LIST_FROM_HIGHLIGHTED_LISTS, listId); + }, flashAnimationDuration); + }, + + createList: ( + { state, commit, dispatch, getters }, + { backlog, labelId, milestoneId, assigneeId }, + ) => { const { boardId } = state; + const existingList = getters.getListByLabelId(labelId); + + if (existingList) { + dispatch('highlightList', existingList.id); + return; + } + gqlClient .mutate({ mutation: createBoardListMutation, @@ -128,6 +148,7 @@ export default { } else { const list = data.boardListCreate?.list; dispatch('addList', list); + dispatch('highlightList', list.id); } }) .catch(() => commit(types.CREATE_LIST_FAILURE)); @@ -153,10 +174,10 @@ export default { variables, }) .then(({ data }) => { - const labels = data[boardType]?.labels; - return labels.nodes; - }) - .catch(() => commit(types.RECEIVE_LABELS_FAILURE)); + const labels = data[boardType]?.labels.nodes; + commit(types.RECEIVE_LABELS_SUCCESS, labels); + return labels; + }); }, moveList: ( @@ -308,34 +329,11 @@ export default { }, setAssignees: ({ commit, getters }, assigneeUsernames) => { - commit(types.SET_ASSIGNEE_LOADING, true); - - return gqlClient - .mutate({ - mutation: updateAssigneesMutation, - variables: { - iid: getters.activeIssue.iid, - projectPath: getters.activeIssue.referencePath.split('#')[0], - assigneeUsernames, - }, - }) - .then(({ data }) => { - const { nodes } = data.issueSetAssignees?.issue?.assignees || []; - - commit('UPDATE_ISSUE_BY_ID', { - issueId: getters.activeIssue.id, - prop: 'assignees', - value: nodes, - }); - - return nodes; - }) - .catch(() => { - createFlash({ message: __('An error occurred while updating assignees.') }); - }) - .finally(() => { - commit(types.SET_ASSIGNEE_LOADING, false); - }); + commit('UPDATE_ISSUE_BY_ID', { + issueId: getters.activeIssue.id, + prop: 'assignees', + value: assigneeUsernames, + }); }, setActiveIssueMilestone: async ({ commit, getters }, input) => { @@ -534,6 +532,21 @@ export default { commit(types.SET_SELECTED_PROJECT, project); }, + toggleBoardItemMultiSelection: ({ commit, state }, boardItem) => { + const { selectedBoardItems } = state; + const index = selectedBoardItems.indexOf(boardItem); + + if (index === -1) { + commit(types.ADD_BOARD_ITEM_TO_SELECTION, boardItem); + } else { + commit(types.REMOVE_BOARD_ITEM_FROM_SELECTION, boardItem); + } + }, + + setAddColumnFormVisibility: ({ commit }, visible) => { + commit(types.SET_ADD_COLUMN_FORM_VISIBLE, visible); + }, + fetchBacklog: () => { notImplemented(); }, diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js index f59530ddf8f..fbff736c7e1 100644 --- a/app/assets/javascripts/boards/stores/boards_store.js +++ b/app/assets/javascripts/boards/stores/boards_store.js @@ -4,22 +4,22 @@ import { sortBy } from 'lodash'; import Vue from 'vue'; import BoardsStoreEE from 'ee_else_ce/boards/stores/boards_store_ee'; +import { getIdFromGraphQLId } from '~/graphql_shared/utils'; +import createDefaultClient from '~/lib/graphql'; +import axios from '~/lib/utils/axios_utils'; import { urlParamsToObject, getUrlParamsArray, parseBoolean, convertObjectPropsToCamelCase, } from '~/lib/utils/common_utils'; -import createDefaultClient from '~/lib/graphql'; -import axios from '~/lib/utils/axios_utils'; import { mergeUrlParams } from '~/lib/utils/url_utility'; -import { getIdFromGraphQLId } from '~/graphql_shared/utils'; +import { ListType, flashAnimationDuration } from '../constants'; import eventHub from '../eventhub'; -import { ListType } from '../constants'; -import IssueProject from '../models/project'; -import ListLabel from '../models/label'; import ListAssignee from '../models/assignee'; +import ListLabel from '../models/label'; import ListMilestone from '../models/milestone'; +import IssueProject from '../models/project'; const PER_PAGE = 20; export const gqlClient = createDefaultClient(); @@ -106,6 +106,11 @@ const boardsStore = { list .save() .then(() => { + list.highlighted = true; + setTimeout(() => { + list.highlighted = false; + }, flashAnimationDuration); + // Remove any new issues from the backlog // as they will be visible in the new list list.issues.forEach(backlogList.removeIssue.bind(backlogList)); @@ -117,7 +122,6 @@ const boardsStore = { }, updateNewListDropdown(listId) { - // eslint-disable-next-line no-unused-expressions document .querySelector(`.js-board-list-${getIdFromGraphQLId(listId)}`) ?.classList.remove('is-active'); @@ -720,6 +724,10 @@ const boardsStore = { } }, + setIssueAssignees(issue, assignees) { + issue.assignees = [...assignees]; + }, + removeIssueLabels(issue, labels) { labels.forEach(issue.removeLabel.bind(issue)); }, diff --git a/app/assets/javascripts/boards/stores/getters.js b/app/assets/javascripts/boards/stores/getters.js index d72b5c6fb8e..cab97088bc6 100644 --- a/app/assets/javascripts/boards/stores/getters.js +++ b/app/assets/javascripts/boards/stores/getters.js @@ -17,12 +17,20 @@ export default { return state.issues[state.activeId] || {}; }, + groupPathForActiveIssue: (_, getters) => { + const { referencePath = '' } = getters.activeIssue; + return referencePath.slice(0, referencePath.indexOf('/')); + }, + projectPathForActiveIssue: (_, getters) => { - const referencePath = getters.activeIssue.referencePath || ''; + const { referencePath = '' } = getters.activeIssue; return referencePath.slice(0, referencePath.indexOf('#')); }, getListByLabelId: (state) => (labelId) => { + if (!labelId) { + return null; + } return find(state.boardLists, (l) => l.label?.id === labelId); }, diff --git a/app/assets/javascripts/boards/stores/index.js b/app/assets/javascripts/boards/stores/index.js index 471b952a212..0a87c6ab821 100644 --- a/app/assets/javascripts/boards/stores/index.js +++ b/app/assets/javascripts/boards/stores/index.js @@ -1,9 +1,9 @@ import Vue from 'vue'; import Vuex from 'vuex'; -import state from 'ee_else_ce/boards/stores/state'; -import getters from 'ee_else_ce/boards/stores/getters'; import actions from 'ee_else_ce/boards/stores/actions'; +import getters from 'ee_else_ce/boards/stores/getters'; import mutations from 'ee_else_ce/boards/stores/mutations'; +import state from 'ee_else_ce/boards/stores/state'; Vue.use(Vuex); diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js index 4697f39498a..a89e961ae2d 100644 --- a/app/assets/javascripts/boards/stores/mutation_types.js +++ b/app/assets/javascripts/boards/stores/mutation_types.js @@ -2,7 +2,7 @@ export const SET_INITIAL_BOARD_DATA = 'SET_INITIAL_BOARD_DATA'; export const SET_FILTERS = 'SET_FILTERS'; export const CREATE_LIST_SUCCESS = 'CREATE_LIST_SUCCESS'; export const CREATE_LIST_FAILURE = 'CREATE_LIST_FAILURE'; -export const RECEIVE_LABELS_FAILURE = 'RECEIVE_LABELS_FAILURE'; +export const RECEIVE_LABELS_SUCCESS = 'RECEIVE_LABELS_SUCCESS'; export const GENERATE_DEFAULT_LISTS_FAILURE = 'GENERATE_DEFAULT_LISTS_FAILURE'; export const RECEIVE_BOARD_LISTS_SUCCESS = 'RECEIVE_BOARD_LISTS_SUCCESS'; export const RECEIVE_BOARD_LISTS_FAILURE = 'RECEIVE_BOARD_LISTS_FAILURE'; @@ -40,3 +40,8 @@ export const REQUEST_GROUP_PROJECTS = 'REQUEST_GROUP_PROJECTS'; export const RECEIVE_GROUP_PROJECTS_SUCCESS = 'RECEIVE_GROUP_PROJECTS_SUCCESS'; export const RECEIVE_GROUP_PROJECTS_FAILURE = 'RECEIVE_GROUP_PROJECTS_FAILURE'; export const SET_SELECTED_PROJECT = 'SET_SELECTED_PROJECT'; +export const ADD_BOARD_ITEM_TO_SELECTION = 'ADD_BOARD_ITEM_TO_SELECTION'; +export const REMOVE_BOARD_ITEM_FROM_SELECTION = 'REMOVE_BOARD_ITEM_FROM_SELECTION'; +export const SET_ADD_COLUMN_FORM_VISIBLE = 'SET_ADD_COLUMN_FORM_VISIBLE'; +export const ADD_LIST_TO_HIGHLIGHTED_LISTS = 'ADD_LIST_TO_HIGHLIGHTED_LISTS'; +export const REMOVE_LIST_FROM_HIGHLIGHTED_LISTS = 'REMOVE_LIST_FROM_HIGHLIGHTED_LISTS'; diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js index 6c79b22d308..79c98c3d90c 100644 --- a/app/assets/javascripts/boards/stores/mutations.js +++ b/app/assets/javascripts/boards/stores/mutations.js @@ -1,9 +1,9 @@ -import Vue from 'vue'; import { pull, union } from 'lodash'; +import Vue from 'vue'; +import { getIdFromGraphQLId } from '~/graphql_shared/utils'; +import { s__ } from '~/locale'; import { formatIssue, moveIssueListHelper } from '../boards_util'; import * as mutationTypes from './mutation_types'; -import { s__ } from '~/locale'; -import { getIdFromGraphQLId } from '~/graphql_shared/utils'; const notImplemented = () => { /* eslint-disable-next-line @gitlab/require-i18n-strings */ @@ -63,8 +63,8 @@ export default { state.error = s__('Boards|An error occurred while creating the list. Please try again.'); }, - [mutationTypes.RECEIVE_LABELS_FAILURE]: (state) => { - state.error = s__('Boards|An error occurred while fetching labels. Please reload the page.'); + [mutationTypes.RECEIVE_LABELS_SUCCESS]: (state, labels) => { + state.labels = labels; }, [mutationTypes.GENERATE_DEFAULT_LISTS_FAILURE]: (state) => { @@ -258,4 +258,28 @@ export default { [mutationTypes.SET_SELECTED_PROJECT]: (state, project) => { state.selectedProject = project; }, + + [mutationTypes.ADD_BOARD_ITEM_TO_SELECTION]: (state, boardItem) => { + state.selectedBoardItems = [...state.selectedBoardItems, boardItem]; + }, + + [mutationTypes.REMOVE_BOARD_ITEM_FROM_SELECTION]: (state, boardItem) => { + Vue.set( + state, + 'selectedBoardItems', + state.selectedBoardItems.filter((obj) => obj !== boardItem), + ); + }, + + [mutationTypes.SET_ADD_COLUMN_FORM_VISIBLE]: (state, visible) => { + state.addColumnFormVisible = visible; + }, + + [mutationTypes.ADD_LIST_TO_HIGHLIGHTED_LISTS]: (state, listId) => { + state.highlightedLists.push(listId); + }, + + [mutationTypes.REMOVE_LIST_FROM_HIGHLIGHTED_LISTS]: (state, listId) => { + state.highlightedLists = state.highlightedLists.filter((id) => id !== listId); + }, }; diff --git a/app/assets/javascripts/boards/stores/state.js b/app/assets/javascripts/boards/stores/state.js index aba7da373cf..91544d6c9c5 100644 --- a/app/assets/javascripts/boards/stores/state.js +++ b/app/assets/javascripts/boards/stores/state.js @@ -14,6 +14,9 @@ export default () => ({ issues: {}, filterParams: {}, boardConfig: {}, + labels: [], + highlightedLists: [], + selectedBoardItems: [], groupProjects: [], groupProjectsFlags: { isLoading: false, @@ -22,6 +25,7 @@ export default () => ({ }, selectedProject: {}, error: undefined, + addColumnFormVisible: false, // TODO: remove after ce/ee split of board_content.vue isShowingEpicsSwimlanes: false, }); |