mirror of
https://github.com/plankanban/planka.git
synced 2025-12-28 01:11:54 +03:00
feat: Add ability to copy/cut cards with shortcut support
This commit is contained in:
@@ -60,6 +60,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
||||
case ActionTypes.LIST_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__FAILURE:
|
||||
if (payload.attachments) {
|
||||
payload.attachments.forEach((attachment) => {
|
||||
Attachment.upsert(prepareAttachment(attachment));
|
||||
@@ -80,6 +81,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_FETCH__SUCCESS:
|
||||
case ActionTypes.CARDS_FETCH__SUCCESS:
|
||||
case ActionTypes.CARD_CREATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__SUCCESS:
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS:
|
||||
payload.attachments.forEach((attachment) => {
|
||||
Attachment.upsert(prepareAttachment(attachment));
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
* Licensed under the Fair Use License: https://github.com/plankanban/planka/blob/master/LICENSE.md
|
||||
*/
|
||||
|
||||
import keyBy from 'lodash/keyBy';
|
||||
import { attr, fk, many, oneToOne } from 'redux-orm';
|
||||
|
||||
import BaseModel from './BaseModel';
|
||||
@@ -316,33 +317,28 @@ export default class extends BaseModel {
|
||||
case ActionTypes.CARD_UPDATE: {
|
||||
const cardModel = Card.withId(payload.id);
|
||||
|
||||
// TODO: introduce separate action?
|
||||
if (payload.data.boardId && payload.data.boardId !== cardModel.boardId) {
|
||||
cardModel.deleteWithRelated();
|
||||
} else {
|
||||
if (payload.data.listId && payload.data.listId !== cardModel.listId) {
|
||||
payload.data.listChangedAt = new Date(); // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
if (payload.data.dueDate !== undefined) {
|
||||
if (payload.data.dueDate) {
|
||||
if (!cardModel.dueDate) {
|
||||
payload.data.isDueCompleted = false; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
} else {
|
||||
payload.data.isDueCompleted = null; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
}
|
||||
|
||||
if (payload.data.isClosed !== undefined && payload.data.isClosed !== cardModel.isClosed) {
|
||||
cardModel.linkedTasks.update({
|
||||
isCompleted: payload.data.isClosed,
|
||||
});
|
||||
}
|
||||
|
||||
cardModel.update(payload.data);
|
||||
if (payload.data.listId && payload.data.listId !== cardModel.listId) {
|
||||
payload.data.listChangedAt = new Date(); // eslint-disable-line no-param-reassign
|
||||
}
|
||||
|
||||
if (payload.data.dueDate !== undefined) {
|
||||
if (payload.data.dueDate) {
|
||||
if (!cardModel.dueDate) {
|
||||
payload.data.isDueCompleted = false; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
} else {
|
||||
payload.data.isDueCompleted = null; // eslint-disable-line no-param-reassign
|
||||
}
|
||||
}
|
||||
|
||||
if (payload.data.isClosed !== undefined && payload.data.isClosed !== cardModel.isClosed) {
|
||||
cardModel.linkedTasks.update({
|
||||
isCompleted: payload.data.isClosed,
|
||||
});
|
||||
}
|
||||
|
||||
cardModel.update(payload.data);
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_UPDATE_HANDLE: {
|
||||
@@ -378,14 +374,86 @@ export default class extends BaseModel {
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_DUPLICATE:
|
||||
Card.withId(payload.id).duplicate(payload.localId, payload.data);
|
||||
case ActionTypes.CARD_TRANSFER: {
|
||||
const cardModel = Card.withId(payload.id);
|
||||
|
||||
if (cardModel) {
|
||||
cardModel.update(payload.data);
|
||||
cardModel.syncAfterBoardChange();
|
||||
}
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS: {
|
||||
Card.withId(payload.localId).deleteWithRelated();
|
||||
}
|
||||
case ActionTypes.CARD_TRANSFER__SUCCESS: {
|
||||
const cardModel = Card.withId(payload.card.id);
|
||||
|
||||
const cardModel = Card.upsert(payload.card);
|
||||
if (cardModel) {
|
||||
cardModel.deleteWithRelated();
|
||||
}
|
||||
|
||||
Card.upsert(payload.card);
|
||||
|
||||
if (payload.cardMemberships) {
|
||||
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
||||
Card.withId(cardId).users.add(userId);
|
||||
});
|
||||
}
|
||||
|
||||
if (payload.cardLabels) {
|
||||
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
||||
Card.withId(cardId).labels.add(labelId);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_TRANSFER__FAILURE: {
|
||||
const cardModel = Card.withId(payload.id);
|
||||
|
||||
if (cardModel) {
|
||||
cardModel.deleteWithRelated();
|
||||
}
|
||||
|
||||
if (payload.card) {
|
||||
Card.upsert(payload.card);
|
||||
}
|
||||
|
||||
if (payload.cardMemberships) {
|
||||
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
||||
Card.withId(cardId).users.add(userId);
|
||||
});
|
||||
}
|
||||
|
||||
if (payload.cardLabels) {
|
||||
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
||||
Card.withId(cardId).labels.add(labelId);
|
||||
});
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_DUPLICATE: {
|
||||
let cardModel = Card.withId(payload.id);
|
||||
|
||||
if (cardModel) {
|
||||
cardModel = cardModel.duplicate(payload.localId, {
|
||||
...payload.data,
|
||||
listChangedAt: new Date(),
|
||||
});
|
||||
|
||||
cardModel.syncAfterBoardChange();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS: {
|
||||
let cardModel = Card.withId(payload.localId);
|
||||
|
||||
if (cardModel) {
|
||||
cardModel.deleteWithRelated();
|
||||
}
|
||||
|
||||
cardModel = Card.upsert(payload.card);
|
||||
|
||||
payload.cardMemberships.forEach(({ userId }) => {
|
||||
cardModel.users.add(userId);
|
||||
@@ -397,10 +465,15 @@ export default class extends BaseModel {
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_DUPLICATE__FAILURE:
|
||||
Card.withId(payload.localId).deleteWithRelated();
|
||||
case ActionTypes.CARD_DUPLICATE__FAILURE: {
|
||||
const cardModel = Card.withId(payload.localId);
|
||||
|
||||
if (cardModel) {
|
||||
cardModel.deleteWithRelated();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_DELETE:
|
||||
Card.withId(payload.id).deleteWithRelated();
|
||||
|
||||
@@ -637,6 +710,47 @@ export default class extends BaseModel {
|
||||
return cardModel;
|
||||
}
|
||||
|
||||
syncAfterBoardChange() {
|
||||
if (!this.board) {
|
||||
return;
|
||||
}
|
||||
|
||||
const boardMemberships = this.board.memberships.toRefArray();
|
||||
const userIdsSet = new Set(boardMemberships.map(({ userId }) => userId));
|
||||
|
||||
this.users.toRefArray().forEach((user) => {
|
||||
if (userIdsSet.has(user.id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.users.remove(user.id);
|
||||
});
|
||||
|
||||
this.taskLists.toModelArray().forEach((taskListModel) => {
|
||||
taskListModel.tasks.toModelArray().forEach((taskModel) => {
|
||||
if (!taskModel.assigneeUserId || userIdsSet.has(taskModel.assigneeUserId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
taskModel.update({
|
||||
assigneeUserId: null,
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
const labels = this.board.labels.toRefArray();
|
||||
const labelByName = keyBy(labels, 'name');
|
||||
|
||||
this.labels.toRefArray().forEach((label) => {
|
||||
if (!labelByName[label.name]) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.labels.remove(label.id);
|
||||
this.labels.add(labelByName[label.name].id);
|
||||
});
|
||||
}
|
||||
|
||||
deleteClearable() {
|
||||
this.users.clear();
|
||||
this.labels.clear();
|
||||
|
||||
@@ -38,6 +38,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
||||
case ActionTypes.LIST_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__FAILURE:
|
||||
if (payload.customFields) {
|
||||
payload.customFields.forEach((customField) => {
|
||||
CustomField.upsert(customField);
|
||||
@@ -59,6 +60,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_FETCH__SUCCESS:
|
||||
case ActionTypes.CARDS_FETCH__SUCCESS:
|
||||
case ActionTypes.CARD_CREATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__SUCCESS:
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS:
|
||||
payload.customFields.forEach((customField) => {
|
||||
CustomField.upsert(customField);
|
||||
|
||||
@@ -42,6 +42,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
||||
case ActionTypes.LIST_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__FAILURE:
|
||||
if (payload.customFieldGroups) {
|
||||
payload.customFieldGroups.forEach((customFieldGroup) => {
|
||||
CustomFieldGroup.upsert(customFieldGroup);
|
||||
@@ -62,6 +63,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_FETCH__SUCCESS:
|
||||
case ActionTypes.CARDS_FETCH__SUCCESS:
|
||||
case ActionTypes.CARD_CREATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__SUCCESS:
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS:
|
||||
payload.customFieldGroups.forEach((customFieldGroup) => {
|
||||
CustomFieldGroup.upsert(customFieldGroup);
|
||||
|
||||
@@ -53,6 +53,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
||||
case ActionTypes.LIST_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__FAILURE:
|
||||
if (payload.customFieldValues) {
|
||||
payload.customFieldValues.forEach((customFieldValue) => {
|
||||
CustomFieldValue.upsert(prepareCustomFieldValue(customFieldValue));
|
||||
@@ -73,6 +74,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_FETCH__SUCCESS:
|
||||
case ActionTypes.CARDS_FETCH__SUCCESS:
|
||||
case ActionTypes.CARD_CREATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__SUCCESS:
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS:
|
||||
payload.customFieldValues.forEach((customFieldValue) => {
|
||||
CustomFieldValue.upsert(prepareCustomFieldValue(customFieldValue));
|
||||
|
||||
@@ -45,6 +45,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
||||
case ActionTypes.LIST_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__FAILURE:
|
||||
if (payload.tasks) {
|
||||
payload.tasks.forEach((task) => {
|
||||
Task.upsert(task);
|
||||
@@ -65,6 +66,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_FETCH__SUCCESS:
|
||||
case ActionTypes.CARDS_FETCH__SUCCESS:
|
||||
case ActionTypes.CARD_CREATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__SUCCESS:
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS:
|
||||
payload.tasks.forEach((task) => {
|
||||
Task.upsert(task);
|
||||
|
||||
@@ -34,6 +34,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
||||
case ActionTypes.LIST_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__FAILURE:
|
||||
if (payload.taskLists) {
|
||||
payload.taskLists.forEach((taskList) => {
|
||||
TaskList.upsert(taskList);
|
||||
@@ -54,6 +55,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_FETCH__SUCCESS:
|
||||
case ActionTypes.CARDS_FETCH__SUCCESS:
|
||||
case ActionTypes.CARD_CREATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__SUCCESS:
|
||||
case ActionTypes.CARD_DUPLICATE__SUCCESS:
|
||||
payload.taskLists.forEach((taskList) => {
|
||||
TaskList.upsert(taskList);
|
||||
|
||||
@@ -105,6 +105,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_MEMBERSHIP_CREATE_HANDLE:
|
||||
case ActionTypes.LIST_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_UPDATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__FAILURE:
|
||||
if (payload.users) {
|
||||
payload.users.forEach((user) => {
|
||||
User.upsert(user);
|
||||
@@ -351,6 +352,7 @@ export default class extends BaseModel {
|
||||
case ActionTypes.BOARD_FETCH__SUCCESS:
|
||||
case ActionTypes.CARDS_FETCH__SUCCESS:
|
||||
case ActionTypes.CARD_CREATE_HANDLE:
|
||||
case ActionTypes.CARD_TRANSFER__SUCCESS:
|
||||
case ActionTypes.COMMENTS_FETCH__SUCCESS:
|
||||
case ActionTypes.COMMENT_CREATE_HANDLE:
|
||||
case ActionTypes.ACTIVITIES_IN_BOARD_FETCH__SUCCESS:
|
||||
|
||||
Reference in New Issue
Block a user