Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/boards/stores')
-rw-r--r--app/assets/javascripts/boards/stores/actions.js193
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js7
-rw-r--r--app/assets/javascripts/boards/stores/getters.js11
-rw-r--r--app/assets/javascripts/boards/stores/mutation_types.js9
-rw-r--r--app/assets/javascripts/boards/stores/mutations.js41
5 files changed, 214 insertions, 47 deletions
diff --git a/app/assets/javascripts/boards/stores/actions.js b/app/assets/javascripts/boards/stores/actions.js
index 1fed1228106..dd950a45076 100644
--- a/app/assets/javascripts/boards/stores/actions.js
+++ b/app/assets/javascripts/boards/stores/actions.js
@@ -1,26 +1,30 @@
-import Cookies from 'js-cookie';
import { pick } from 'lodash';
import boardListsQuery from 'ee_else_ce/boards/queries/board_lists.query.graphql';
-import { __ } from '~/locale';
-import { parseBoolean } from '~/lib/utils/common_utils';
import createGqClient, { fetchPolicies } from '~/lib/graphql';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
-import { BoardType, ListType, inactiveId } from '~/boards/constants';
+import { BoardType, ListType, inactiveId, DEFAULT_LABELS } from '~/boards/constants';
import * as types from './mutation_types';
import {
formatBoardLists,
formatListIssues,
fullBoardId,
formatListsPageInfo,
+ formatIssue,
} from '../boards_util';
import boardStore from '~/boards/stores/boards_store';
+import updateAssignees from '~/vue_shared/components/sidebar/queries/updateAssignees.mutation.graphql';
import listsIssuesQuery from '../queries/lists_issues.query.graphql';
+import boardLabelsQuery from '../queries/board_labels.query.graphql';
import createBoardListMutation from '../queries/board_list_create.mutation.graphql';
import updateBoardListMutation from '../queries/board_list_update.mutation.graphql';
import issueMoveListMutation from '../queries/issue_move_list.mutation.graphql';
+import destroyBoardListMutation from '../queries/board_list_destroy.mutation.graphql';
+import issueCreateMutation from '../queries/issue_create.mutation.graphql';
import issueSetLabels from '../queries/issue_set_labels.mutation.graphql';
+import issueSetDueDate from '../queries/issue_set_due_date.mutation.graphql';
+import issueSetSubscriptionMutation from '../graphql/mutations/issue_set_subscription.mutation.graphql';
const notImplemented = () => {
/* eslint-disable-next-line @gitlab/require-i18n-strings */
@@ -83,7 +87,7 @@ export default {
if (!lists.nodes.find(l => l.listType === ListType.backlog) && !hideBacklogList) {
dispatch('createList', { backlog: true });
}
- dispatch('showWelcomeList');
+ dispatch('generateDefaultLists');
})
.catch(() => commit(types.RECEIVE_BOARD_LISTS_FAILURE));
},
@@ -121,7 +125,32 @@ export default {
);
},
- showWelcomeList: ({ state, dispatch }) => {
+ showPromotionList: () => {},
+
+ fetchLabels: ({ state, commit }, searchTerm) => {
+ const { endpoints, boardType } = state;
+ const { fullPath } = endpoints;
+
+ const variables = {
+ fullPath,
+ searchTerm,
+ isGroup: boardType === BoardType.group,
+ isProject: boardType === BoardType.project,
+ };
+
+ return gqlClient
+ .query({
+ query: boardLabelsQuery,
+ variables,
+ })
+ .then(({ data }) => {
+ const labels = data[boardType]?.labels;
+ return labels.nodes;
+ })
+ .catch(() => commit(types.RECEIVE_LABELS_FAILURE));
+ },
+
+ generateDefaultLists: async ({ state, commit, dispatch }) => {
if (state.disabled) {
return;
}
@@ -132,22 +161,18 @@ export default {
) {
return;
}
- if (parseBoolean(Cookies.get('issue_board_welcome_hidden'))) {
- return;
- }
- dispatch('addList', {
- id: 'blank',
- listType: ListType.blank,
- title: __('Welcome to your issue board!'),
- position: 0,
- });
- },
-
- showPromotionList: () => {},
+ const fetchLabelsAndCreateList = label => {
+ return dispatch('fetchLabels', label)
+ .then(res => {
+ if (res.length > 0) {
+ dispatch('createList', { labelId: res[0].id });
+ }
+ })
+ .catch(() => commit(types.GENERATE_DEFAULT_LISTS_FAILURE));
+ };
- generateDefaultLists: () => {
- notImplemented();
+ await Promise.all(DEFAULT_LABELS.map(fetchLabelsAndCreateList));
},
moveList: (
@@ -191,8 +216,26 @@ export default {
});
},
- deleteList: () => {
- notImplemented();
+ removeList: ({ state, commit }, listId) => {
+ const listsBackup = { ...state.boardLists };
+
+ commit(types.REMOVE_LIST, listId);
+
+ return gqlClient
+ .mutate({
+ mutation: destroyBoardListMutation,
+ variables: {
+ listId,
+ },
+ })
+ .then(({ data: { destroyBoardList: { errors } } }) => {
+ if (errors.length > 0) {
+ commit(types.REMOVE_LIST_FAILURE, listsBackup);
+ }
+ })
+ .catch(() => {
+ commit(types.REMOVE_LIST_FAILURE, listsBackup);
+ });
},
fetchIssuesForList: ({ state, commit }, { listId, fetchNext = false }) => {
@@ -271,20 +314,69 @@ export default {
);
},
- createNewIssue: () => {
- notImplemented();
+ setAssignees: ({ commit, getters }, assigneeUsernames) => {
+ return gqlClient
+ .mutate({
+ mutation: updateAssignees,
+ variables: {
+ iid: getters.activeIssue.iid,
+ projectPath: getters.activeIssue.referencePath.split('#')[0],
+ assigneeUsernames,
+ },
+ })
+ .then(({ data }) => {
+ commit('UPDATE_ISSUE_BY_ID', {
+ issueId: getters.activeIssue.id,
+ prop: 'assignees',
+ value: data.issueSetAssignees.issue.assignees.nodes,
+ });
+ });
+ },
+
+ createNewIssue: ({ commit, state }, issueInput) => {
+ const input = issueInput;
+ const { boardType, endpoints } = state;
+ if (boardType === BoardType.project) {
+ input.projectPath = endpoints.fullPath;
+ }
+
+ return gqlClient
+ .mutate({
+ mutation: issueCreateMutation,
+ variables: { input },
+ })
+ .then(({ data }) => {
+ if (data.createIssue.errors.length) {
+ commit(types.CREATE_ISSUE_FAILURE);
+ } else {
+ return data.createIssue?.issue;
+ }
+ return null;
+ })
+ .catch(() => commit(types.CREATE_ISSUE_FAILURE));
},
addListIssue: ({ commit }, { list, issue, position }) => {
commit(types.ADD_ISSUE_TO_LIST, { list, issue, position });
},
- addListIssueFailure: ({ commit }, { list, issue }) => {
- commit(types.ADD_ISSUE_TO_LIST_FAILURE, { list, issue });
+ addListNewIssue: ({ commit, dispatch }, { issueInput, list }) => {
+ const issue = formatIssue({ ...issueInput, id: 'tmp' });
+ commit(types.ADD_ISSUE_TO_LIST, { list, issue, position: 0 });
+
+ dispatch('createNewIssue', issueInput)
+ .then(res => {
+ commit(types.ADD_ISSUE_TO_LIST, {
+ list,
+ issue: formatIssue({ ...res, id: getIdFromGraphQLId(res.id) }),
+ });
+ commit(types.REMOVE_ISSUE_FROM_LIST, { list, issue });
+ })
+ .catch(() => commit(types.ADD_ISSUE_TO_LIST_FAILURE, { list, issueId: issueInput.id }));
},
setActiveIssueLabels: async ({ commit, getters }, input) => {
- const activeIssue = getters.getActiveIssue;
+ const { activeIssue } = getters;
const { data } = await gqlClient.mutate({
mutation: issueSetLabels,
variables: {
@@ -308,6 +400,53 @@ export default {
});
},
+ setActiveIssueDueDate: async ({ commit, getters }, input) => {
+ const { activeIssue } = getters;
+ const { data } = await gqlClient.mutate({
+ mutation: issueSetDueDate,
+ variables: {
+ input: {
+ iid: String(activeIssue.iid),
+ projectPath: input.projectPath,
+ dueDate: input.dueDate,
+ },
+ },
+ });
+
+ if (data.updateIssue?.errors?.length > 0) {
+ throw new Error(data.updateIssue.errors);
+ }
+
+ commit(types.UPDATE_ISSUE_BY_ID, {
+ issueId: activeIssue.id,
+ prop: 'dueDate',
+ value: data.updateIssue.issue.dueDate,
+ });
+ },
+
+ setActiveIssueSubscribed: async ({ commit, getters }, input) => {
+ const { data } = await gqlClient.mutate({
+ mutation: issueSetSubscriptionMutation,
+ variables: {
+ input: {
+ iid: String(getters.activeIssue.iid),
+ projectPath: input.projectPath,
+ subscribedState: input.subscribed,
+ },
+ },
+ });
+
+ if (data.issueSetSubscription?.errors?.length > 0) {
+ throw new Error(data.issueSetSubscription.errors);
+ }
+
+ commit(types.UPDATE_ISSUE_BY_ID, {
+ issueId: getters.activeIssue.id,
+ prop: 'subscribed',
+ value: data.issueSetSubscription.issue.subscribed,
+ });
+ },
+
fetchBacklog: () => {
notImplemented();
},
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index d1a5db1bcc5..337b2897fe9 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -1,7 +1,6 @@
/* eslint-disable no-shadow, no-param-reassign,consistent-return */
/* global List */
/* global ListIssue */
-import $ from 'jquery';
import { sortBy, pick } from 'lodash';
import Vue from 'vue';
import Cookies from 'js-cookie';
@@ -119,8 +118,12 @@ const boardsStore = {
// https://gitlab.com/gitlab-org/gitlab-foss/issues/30821
});
},
+
updateNewListDropdown(listId) {
- $(`.js-board-list-${listId}`).removeClass('is-active');
+ // eslint-disable-next-line no-unused-expressions
+ document
+ .querySelector(`.js-board-list-${getIdFromGraphQLId(listId)}`)
+ ?.classList.remove('is-active');
},
shouldAddBlankState() {
// Decide whether to add the blank state
diff --git a/app/assets/javascripts/boards/stores/getters.js b/app/assets/javascripts/boards/stores/getters.js
index 89a3b14b262..cd28b4a0ff7 100644
--- a/app/assets/javascripts/boards/stores/getters.js
+++ b/app/assets/javascripts/boards/stores/getters.js
@@ -2,7 +2,7 @@ import { find } from 'lodash';
import { inactiveId } from '../constants';
export default {
- getLabelToggleState: state => (state.isShowingLabels ? 'on' : 'off'),
+ labelToggleState: state => (state.isShowingLabels ? 'on' : 'off'),
isSidebarOpen: state => state.activeId !== inactiveId,
isSwimlanesOn: state => {
if (!gon?.features?.boardsWithSwimlanes && !gon?.features?.swimlanes) {
@@ -15,15 +15,20 @@ export default {
return state.issues[id] || {};
},
- getIssues: (state, getters) => listId => {
+ getIssuesByList: (state, getters) => listId => {
const listIssueIds = state.issuesByListId[listId] || [];
return listIssueIds.map(id => getters.getIssueById(id));
},
- getActiveIssue: state => {
+ activeIssue: state => {
return state.issues[state.activeId] || {};
},
+ projectPathForActiveIssue: (_, getters) => {
+ const referencePath = getters.activeIssue.referencePath || '';
+ return referencePath.slice(0, referencePath.indexOf('#'));
+ },
+
getListByLabelId: state => labelId => {
return find(state.boardLists, l => l.label?.id === labelId);
},
diff --git a/app/assets/javascripts/boards/stores/mutation_types.js b/app/assets/javascripts/boards/stores/mutation_types.js
index 09ab08062df..3a57cb9b5e1 100644
--- a/app/assets/javascripts/boards/stores/mutation_types.js
+++ b/app/assets/javascripts/boards/stores/mutation_types.js
@@ -2,6 +2,8 @@ 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 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';
export const SHOW_PROMOTION_LIST = 'SHOW_PROMOTION_LIST';
@@ -10,12 +12,12 @@ export const RECEIVE_ADD_LIST_SUCCESS = 'RECEIVE_ADD_LIST_SUCCESS';
export const RECEIVE_ADD_LIST_ERROR = 'RECEIVE_ADD_LIST_ERROR';
export const MOVE_LIST = 'MOVE_LIST';
export const UPDATE_LIST_FAILURE = 'UPDATE_LIST_FAILURE';
-export const REQUEST_REMOVE_LIST = 'REQUEST_REMOVE_LIST';
-export const RECEIVE_REMOVE_LIST_SUCCESS = 'RECEIVE_REMOVE_LIST_SUCCESS';
-export const RECEIVE_REMOVE_LIST_ERROR = 'RECEIVE_REMOVE_LIST_ERROR';
+export const REMOVE_LIST = 'REMOVE_LIST';
+export const REMOVE_LIST_FAILURE = 'REMOVE_LIST_FAILURE';
export const REQUEST_ISSUES_FOR_LIST = 'REQUEST_ISSUES_FOR_LIST';
export const RECEIVE_ISSUES_FOR_LIST_FAILURE = 'RECEIVE_ISSUES_FOR_LIST_FAILURE';
export const RECEIVE_ISSUES_FOR_LIST_SUCCESS = 'RECEIVE_ISSUES_FOR_LIST_SUCCESS';
+export const CREATE_ISSUE_FAILURE = 'CREATE_ISSUE_FAILURE';
export const REQUEST_ADD_ISSUE = 'REQUEST_ADD_ISSUE';
export const RECEIVE_ADD_ISSUE_SUCCESS = 'RECEIVE_ADD_ISSUE_SUCCESS';
export const RECEIVE_ADD_ISSUE_ERROR = 'RECEIVE_ADD_ISSUE_ERROR';
@@ -27,6 +29,7 @@ export const RECEIVE_UPDATE_ISSUE_SUCCESS = 'RECEIVE_UPDATE_ISSUE_SUCCESS';
export const RECEIVE_UPDATE_ISSUE_ERROR = 'RECEIVE_UPDATE_ISSUE_ERROR';
export const ADD_ISSUE_TO_LIST = 'ADD_ISSUE_TO_LIST';
export const ADD_ISSUE_TO_LIST_FAILURE = 'ADD_ISSUE_TO_LIST_FAILURE';
+export const REMOVE_ISSUE_FROM_LIST = 'REMOVE_ISSUE_FROM_LIST';
export const SET_CURRENT_PAGE = 'SET_CURRENT_PAGE';
export const TOGGLE_EMPTY_STATE = 'TOGGLE_EMPTY_STATE';
export const SET_ACTIVE_ID = 'SET_ACTIVE_ID';
diff --git a/app/assets/javascripts/boards/stores/mutations.js b/app/assets/javascripts/boards/stores/mutations.js
index 0c7dbc0d2ef..bb083158c8f 100644
--- a/app/assets/javascripts/boards/stores/mutations.js
+++ b/app/assets/javascripts/boards/stores/mutations.js
@@ -62,6 +62,14 @@ 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.GENERATE_DEFAULT_LISTS_FAILURE]: state => {
+ state.error = s__('Boards|An error occurred while generating lists. Please reload the page.');
+ },
+
[mutationTypes.REQUEST_ADD_LIST]: () => {
notImplemented();
},
@@ -85,16 +93,13 @@ export default {
Vue.set(state, 'boardLists', backupList);
},
- [mutationTypes.REQUEST_REMOVE_LIST]: () => {
- notImplemented();
+ [mutationTypes.REMOVE_LIST]: (state, listId) => {
+ Vue.delete(state.boardLists, listId);
},
- [mutationTypes.RECEIVE_REMOVE_LIST_SUCCESS]: () => {
- notImplemented();
- },
-
- [mutationTypes.RECEIVE_REMOVE_LIST_ERROR]: () => {
- notImplemented();
+ [mutationTypes.REMOVE_LIST_FAILURE](state, listsBackup) {
+ state.error = s__('Boards|An error occurred while removing the list. Please try again.');
+ state.boardLists = listsBackup;
},
[mutationTypes.REQUEST_ISSUES_FOR_LIST]: (state, { listId, fetchNext }) => {
@@ -196,16 +201,28 @@ export default {
notImplemented();
},
+ [mutationTypes.CREATE_ISSUE_FAILURE]: state => {
+ state.error = s__('Boards|An error occurred while creating the issue. Please try again.');
+ },
+
[mutationTypes.ADD_ISSUE_TO_LIST]: (state, { list, issue, position }) => {
- const listIssues = state.issuesByListId[list.id];
- listIssues.splice(position, 0, issue.id);
- Vue.set(state.issuesByListId, list.id, listIssues);
+ addIssueToList({
+ state,
+ listId: list.id,
+ issueId: issue.id,
+ atIndex: position,
+ });
Vue.set(state.issues, issue.id, issue);
},
- [mutationTypes.ADD_ISSUE_TO_LIST_FAILURE]: (state, { list, issue }) => {
+ [mutationTypes.ADD_ISSUE_TO_LIST_FAILURE]: (state, { list, issueId }) => {
state.error = s__('Boards|An error occurred while creating the issue. Please try again.');
+ removeIssueFromList({ state, listId: list.id, issueId });
+ },
+
+ [mutationTypes.REMOVE_ISSUE_FROM_LIST]: (state, { list, issue }) => {
removeIssueFromList({ state, listId: list.id, issueId: issue.id });
+ Vue.delete(state.issues, issue.id);
},
[mutationTypes.SET_CURRENT_PAGE]: () => {