summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/boards/stores/boards_store.js
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2019-10-11 12:06:29 +0000
committerGitLab Bot <gitlab-bot@gitlab.com>2019-10-11 12:06:29 +0000
commitf03a645e7409882fe8b1aceca1735bc9051c612a (patch)
tree3d055c210ff663865e5c905cab208f74ebbcef2f /app/assets/javascripts/boards/stores/boards_store.js
parent0dea53d5e575c6c15ce7384da73b8d4a95b1c8cf (diff)
downloadgitlab-ce-f03a645e7409882fe8b1aceca1735bc9051c612a.tar.gz
Add latest changes from gitlab-org/gitlab@master
Diffstat (limited to 'app/assets/javascripts/boards/stores/boards_store.js')
-rw-r--r--app/assets/javascripts/boards/stores/boards_store.js148
1 files changed, 147 insertions, 1 deletions
diff --git a/app/assets/javascripts/boards/stores/boards_store.js b/app/assets/javascripts/boards/stores/boards_store.js
index 6da1cca9628..8b737d1dab0 100644
--- a/app/assets/javascripts/boards/stores/boards_store.js
+++ b/app/assets/javascripts/boards/stores/boards_store.js
@@ -11,6 +11,7 @@ import { __ } from '~/locale';
import axios from '~/lib/utils/axios_utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import eventHub from '../eventhub';
+import { ListType } from '../constants';
const boardsStore = {
disabled: false,
@@ -39,6 +40,7 @@ const boardsStore = {
issue: {},
list: {},
},
+ multiSelect: { list: [] },
setEndpoints({ boardsEndpoint, listsEndpoint, bulkUpdatePath, boardId, recentBoardsEndpoint }) {
const listsEndpointGenerate = `${listsEndpoint}/generate.json`;
@@ -51,7 +53,6 @@ const boardsStore = {
recentBoardsEndpoint: `${recentBoardsEndpoint}.json`,
};
},
-
create() {
this.state.lists = [];
this.filter.path = getUrlParamsArray().join('&');
@@ -134,6 +135,107 @@ const boardsStore = {
Object.assign(this.moving, { list, issue });
},
+ moveMultipleIssuesToList({ listFrom, listTo, issues, newIndex }) {
+ const issueTo = issues.map(issue => listTo.findIssue(issue.id));
+ const issueLists = _.flatten(issues.map(issue => issue.getLists()));
+ const listLabels = issueLists.map(list => list.label);
+
+ const hasMoveableIssues = _.compact(issueTo).length > 0;
+
+ if (!hasMoveableIssues) {
+ // Check if target list assignee is already present in this issue
+ if (
+ listTo.type === ListType.assignee &&
+ listFrom.type === ListType.assignee &&
+ issues.some(issue => issue.findAssignee(listTo.assignee))
+ ) {
+ const targetIssues = issues.map(issue => listTo.findIssue(issue.id));
+ targetIssues.forEach(targetIssue => targetIssue.removeAssignee(listFrom.assignee));
+ } else if (listTo.type === 'milestone') {
+ const currentMilestones = issues.map(issue => issue.milestone);
+ const currentLists = this.state.lists
+ .filter(list => list.type === 'milestone' && list.id !== listTo.id)
+ .filter(list =>
+ list.issues.some(listIssue => issues.some(issue => listIssue.id === issue.id)),
+ );
+
+ issues.forEach(issue => {
+ currentMilestones.forEach(milestone => {
+ issue.removeMilestone(milestone);
+ });
+ });
+
+ issues.forEach(issue => {
+ issue.addMilestone(listTo.milestone);
+ });
+
+ currentLists.forEach(currentList => {
+ issues.forEach(issue => {
+ currentList.removeIssue(issue);
+ });
+ });
+
+ listTo.addMultipleIssues(issues, listFrom, newIndex);
+ } else {
+ // Add to new lists issues if it doesn't already exist
+ listTo.addMultipleIssues(issues, listFrom, newIndex);
+ }
+ } else {
+ listTo.updateMultipleIssues(issues, listFrom);
+ issues.forEach(issue => {
+ issue.removeLabel(listFrom.label);
+ });
+ }
+
+ if (listTo.type === ListType.closed && listFrom.type !== ListType.backlog) {
+ issueLists.forEach(list => {
+ issues.forEach(issue => {
+ list.removeIssue(issue);
+ });
+ });
+
+ issues.forEach(issue => {
+ issue.removeLabels(listLabels);
+ });
+ } else if (listTo.type === ListType.backlog && listFrom.type === ListType.assignee) {
+ issues.forEach(issue => {
+ issue.removeAssignee(listFrom.assignee);
+ });
+ issueLists.forEach(list => {
+ issues.forEach(issue => {
+ list.removeIssue(issue);
+ });
+ });
+ } else if (listTo.type === ListType.backlog && listFrom.type === ListType.milestone) {
+ issues.forEach(issue => {
+ issue.removeMilestone(listFrom.milestone);
+ });
+ issueLists.forEach(list => {
+ issues.forEach(issue => {
+ list.removeIssue(issue);
+ });
+ });
+ } else if (
+ this.shouldRemoveIssue(listFrom, listTo) &&
+ this.issuesAreContiguous(listFrom, issues)
+ ) {
+ listFrom.removeMultipleIssues(issues);
+ }
+ },
+
+ issuesAreContiguous(list, issues) {
+ // When there's only 1 issue selected, we can return early.
+ if (issues.length === 1) return true;
+
+ // Create list of ids for issues involved.
+ const listIssueIds = list.issues.map(issue => issue.id);
+ const movedIssueIds = issues.map(issue => issue.id);
+
+ // Check if moved issue IDs is sub-array
+ // of source list issue IDs (i.e. contiguous selection).
+ return listIssueIds.join('|').includes(movedIssueIds.join('|'));
+ },
+
moveIssueToList(listFrom, listTo, issue, newIndex) {
const issueTo = listTo.findIssue(issue.id);
const issueLists = issue.getLists();
@@ -195,6 +297,17 @@ const boardsStore = {
list.moveIssue(issue, oldIndex, newIndex, beforeId, afterId);
},
+ moveMultipleIssuesInList({ list, issues, oldIndicies, newIndex, idArray }) {
+ const beforeId = parseInt(idArray[newIndex - 1], 10) || null;
+ const afterId = parseInt(idArray[newIndex + issues.length], 10) || null;
+ list.moveMultipleIssues({
+ issues,
+ oldIndicies,
+ newIndex,
+ moveBeforeId: beforeId,
+ moveAfterId: afterId,
+ });
+ },
findList(key, val, type = 'label') {
const filteredList = this.state.lists.filter(list => {
const byType = type
@@ -260,6 +373,10 @@ const boardsStore = {
}`;
},
+ generateMultiDragPath(boardId) {
+ return `${gon.relative_url_root}/-/boards/${boardId ? `${boardId}` : ''}/issues/bulk_move`;
+ },
+
all() {
return axios.get(this.state.endpoints.listsEndpoint);
},
@@ -309,6 +426,16 @@ const boardsStore = {
});
},
+ moveMultipleIssues({ ids, fromListId, toListId, moveBeforeId, moveAfterId }) {
+ return axios.put(this.generateMultiDragPath(this.state.endpoints.boardId), {
+ from_list_id: fromListId,
+ to_list_id: toListId,
+ move_before_id: moveBeforeId,
+ move_after_id: moveAfterId,
+ ids,
+ });
+ },
+
newIssue(id, issue) {
return axios.post(this.generateIssuesPath(id), {
issue,
@@ -379,6 +506,25 @@ const boardsStore = {
setCurrentBoard(board) {
this.state.currentBoard = board;
},
+
+ toggleMultiSelect(issue) {
+ const selectedIssueIds = this.multiSelect.list.map(issue => issue.id);
+ const index = selectedIssueIds.indexOf(issue.id);
+
+ if (index === -1) {
+ this.multiSelect.list.push(issue);
+ return;
+ }
+
+ this.multiSelect.list = [
+ ...this.multiSelect.list.slice(0, index),
+ ...this.multiSelect.list.slice(index + 1),
+ ];
+ },
+
+ clearMultiSelect() {
+ this.multiSelect.list = [];
+ },
};
BoardsStoreEE.initEESpecific(boardsStore);