2018-11-08 19:23:39 +05:30
|
|
|
/* eslint-disable comma-dangle, no-shadow */
|
2017-08-17 22:00:37 +05:30
|
|
|
/* global List */
|
2018-05-09 12:01:36 +05:30
|
|
|
|
|
|
|
import $ from 'jquery';
|
2017-09-10 17:25:29 +05:30
|
|
|
import _ from 'underscore';
|
2017-08-17 22:00:37 +05:30
|
|
|
import Cookies from 'js-cookie';
|
2018-03-27 19:54:05 +05:30
|
|
|
import { getUrlParamsArray } from '~/lib/utils/common_utils';
|
2017-08-17 22:00:37 +05:30
|
|
|
|
|
|
|
window.gl = window.gl || {};
|
|
|
|
window.gl.issueBoards = window.gl.issueBoards || {};
|
|
|
|
|
|
|
|
gl.issueBoards.BoardsStore = {
|
|
|
|
disabled: false,
|
|
|
|
filter: {
|
|
|
|
path: '',
|
|
|
|
},
|
|
|
|
state: {},
|
|
|
|
detail: {
|
2018-03-17 18:26:18 +05:30
|
|
|
issue: {},
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
moving: {
|
|
|
|
issue: {},
|
2018-03-17 18:26:18 +05:30
|
|
|
list: {},
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
create () {
|
|
|
|
this.state.lists = [];
|
2018-03-17 18:26:18 +05:30
|
|
|
this.filter.path = getUrlParamsArray().join('&');
|
|
|
|
this.detail = {
|
|
|
|
issue: {},
|
|
|
|
};
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
addList (listObj, defaultAvatar) {
|
|
|
|
const list = new List(listObj, defaultAvatar);
|
|
|
|
this.state.lists.push(list);
|
|
|
|
|
|
|
|
return list;
|
|
|
|
},
|
|
|
|
new (listObj) {
|
|
|
|
const list = this.addList(listObj);
|
2017-09-10 17:25:29 +05:30
|
|
|
const backlogList = this.findList('type', 'backlog', 'backlog');
|
2017-08-17 22:00:37 +05:30
|
|
|
|
|
|
|
list
|
|
|
|
.save()
|
|
|
|
.then(() => {
|
2017-09-10 17:25:29 +05:30
|
|
|
// Remove any new issues from the backlog
|
|
|
|
// as they will be visible in the new list
|
|
|
|
list.issues.forEach(backlogList.removeIssue.bind(backlogList));
|
2017-08-17 22:00:37 +05:30
|
|
|
this.state.lists = _.sortBy(this.state.lists, 'position');
|
|
|
|
})
|
|
|
|
.catch(() => {
|
|
|
|
// https://gitlab.com/gitlab-org/gitlab-ce/issues/30821
|
|
|
|
});
|
|
|
|
this.removeBlankState();
|
|
|
|
},
|
|
|
|
updateNewListDropdown (listId) {
|
|
|
|
$(`.js-board-list-${listId}`).removeClass('is-active');
|
|
|
|
},
|
|
|
|
shouldAddBlankState () {
|
|
|
|
// Decide whether to add the blank state
|
2017-09-10 17:25:29 +05:30
|
|
|
return !(this.state.lists.filter(list => list.type !== 'backlog' && list.type !== 'closed')[0]);
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
addBlankState () {
|
|
|
|
if (!this.shouldAddBlankState() || this.welcomeIsHidden() || this.disabled) return;
|
|
|
|
|
|
|
|
this.addList({
|
|
|
|
id: 'blank',
|
|
|
|
list_type: 'blank',
|
|
|
|
title: 'Welcome to your Issue Board!',
|
|
|
|
position: 0
|
|
|
|
});
|
|
|
|
|
|
|
|
this.state.lists = _.sortBy(this.state.lists, 'position');
|
|
|
|
},
|
|
|
|
removeBlankState () {
|
|
|
|
this.removeList('blank');
|
|
|
|
|
|
|
|
Cookies.set('issue_board_welcome_hidden', 'true', {
|
|
|
|
expires: 365 * 10,
|
|
|
|
path: ''
|
|
|
|
});
|
|
|
|
},
|
|
|
|
welcomeIsHidden () {
|
|
|
|
return Cookies.get('issue_board_welcome_hidden') === 'true';
|
|
|
|
},
|
|
|
|
removeList (id, type = 'blank') {
|
|
|
|
const list = this.findList('id', id, type);
|
|
|
|
|
|
|
|
if (!list) return;
|
|
|
|
|
|
|
|
this.state.lists = this.state.lists.filter(list => list.id !== id);
|
|
|
|
},
|
|
|
|
moveList (listFrom, orderLists) {
|
|
|
|
orderLists.forEach((id, i) => {
|
|
|
|
const list = this.findList('id', parseInt(id, 10));
|
|
|
|
|
|
|
|
list.position = i;
|
|
|
|
});
|
|
|
|
listFrom.update();
|
|
|
|
},
|
|
|
|
moveIssueToList (listFrom, listTo, issue, newIndex) {
|
|
|
|
const issueTo = listTo.findIssue(issue.id);
|
|
|
|
const issueLists = issue.getLists();
|
|
|
|
const listLabels = issueLists.map(listIssue => listIssue.label);
|
|
|
|
|
|
|
|
if (!issueTo) {
|
2018-11-08 19:23:39 +05:30
|
|
|
// Check if target list assignee is already present in this issue
|
|
|
|
if ((listTo.type === 'assignee' && listFrom.type === 'assignee') &&
|
|
|
|
issue.findAssignee(listTo.assignee)) {
|
|
|
|
const targetIssue = listTo.findIssue(issue.id);
|
|
|
|
targetIssue.removeAssignee(listFrom.assignee);
|
2018-11-18 11:00:15 +05:30
|
|
|
} else if (listTo.type === 'milestone') {
|
|
|
|
const currentMilestone = issue.milestone;
|
|
|
|
const currentLists = this.state.lists
|
|
|
|
.filter(list => (list.type === 'milestone' && list.id !== listTo.id))
|
|
|
|
.filter(list => list.issues.some(listIssue => issue.id === listIssue.id));
|
|
|
|
|
|
|
|
issue.removeMilestone(currentMilestone);
|
|
|
|
issue.addMilestone(listTo.milestone);
|
|
|
|
currentLists.forEach(currentList => currentList.removeIssue(issue));
|
|
|
|
listTo.addIssue(issue, listFrom, newIndex);
|
2018-11-08 19:23:39 +05:30
|
|
|
} else {
|
|
|
|
// Add to new lists issues if it doesn't already exist
|
|
|
|
listTo.addIssue(issue, listFrom, newIndex);
|
|
|
|
}
|
2017-08-17 22:00:37 +05:30
|
|
|
} else {
|
|
|
|
listTo.updateIssueLabel(issue, listFrom);
|
|
|
|
issueTo.removeLabel(listFrom.label);
|
|
|
|
}
|
|
|
|
|
2017-09-10 17:25:29 +05:30
|
|
|
if (listTo.type === 'closed' && listFrom.type !== 'backlog') {
|
2017-08-17 22:00:37 +05:30
|
|
|
issueLists.forEach((list) => {
|
|
|
|
list.removeIssue(issue);
|
|
|
|
});
|
|
|
|
issue.removeLabels(listLabels);
|
2018-11-08 19:23:39 +05:30
|
|
|
} else if (listTo.type === 'backlog' && listFrom.type === 'assignee') {
|
|
|
|
issue.removeAssignee(listFrom.assignee);
|
|
|
|
listFrom.removeIssue(issue);
|
2018-11-18 11:00:15 +05:30
|
|
|
} else if (listTo.type === 'backlog' && listFrom.type === 'milestone') {
|
|
|
|
issue.removeMilestone(listFrom.milestone);
|
|
|
|
listFrom.removeIssue(issue);
|
|
|
|
} else if (this.shouldRemoveIssue(listFrom, listTo)) {
|
2017-08-17 22:00:37 +05:30
|
|
|
listFrom.removeIssue(issue);
|
|
|
|
}
|
|
|
|
},
|
2018-11-18 11:00:15 +05:30
|
|
|
shouldRemoveIssue(listFrom, listTo) {
|
|
|
|
return (
|
|
|
|
(listTo.type !== 'label' && listFrom.type === 'assignee') ||
|
|
|
|
(listTo.type !== 'assignee' && listFrom.type === 'label') ||
|
|
|
|
(listFrom.type === 'backlog')
|
|
|
|
);
|
|
|
|
},
|
2017-08-17 22:00:37 +05:30
|
|
|
moveIssueInList (list, issue, oldIndex, newIndex, idArray) {
|
|
|
|
const beforeId = parseInt(idArray[newIndex - 1], 10) || null;
|
|
|
|
const afterId = parseInt(idArray[newIndex + 1], 10) || null;
|
|
|
|
|
|
|
|
list.moveIssue(issue, oldIndex, newIndex, beforeId, afterId);
|
|
|
|
},
|
|
|
|
findList (key, val, type = 'label') {
|
2018-11-08 19:23:39 +05:30
|
|
|
const filteredList = this.state.lists.filter((list) => {
|
2018-11-18 11:00:15 +05:30
|
|
|
const byType = type ? (list.type === type) || (list.type === 'assignee') || (list.type === 'milestone') : true;
|
2017-08-17 22:00:37 +05:30
|
|
|
|
|
|
|
return list[key] === val && byType;
|
2018-11-08 19:23:39 +05:30
|
|
|
});
|
|
|
|
return filteredList[0];
|
2017-08-17 22:00:37 +05:30
|
|
|
},
|
|
|
|
updateFiltersUrl () {
|
2018-11-08 19:23:39 +05:30
|
|
|
window.history.pushState(null, null, `?${this.filter.path}`);
|
2017-08-17 22:00:37 +05:30
|
|
|
}
|
|
|
|
};
|