mirror of
https://github.com/plankanban/planka.git
synced 2025-07-19 05:09:43 +02:00
Preserve members and labels when transfer card to another board
This commit is contained in:
parent
5e0b2b9f0a
commit
044fe17dbf
17 changed files with 321 additions and 64 deletions
|
@ -34,11 +34,22 @@ export const createCardRequested = (localId, data) => ({
|
|||
},
|
||||
});
|
||||
|
||||
export const createCardSucceeded = (localId, card) => ({
|
||||
export const createCardSucceeded = (
|
||||
localId,
|
||||
card,
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
attachments,
|
||||
) => ({
|
||||
type: ActionTypes.CARD_CREATE_SUCCEEDED,
|
||||
payload: {
|
||||
localId,
|
||||
card,
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
attachments,
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -50,10 +61,14 @@ export const createCardFailed = (localId, error) => ({
|
|||
},
|
||||
});
|
||||
|
||||
export const createCardReceived = (card) => ({
|
||||
export const createCardReceived = (card, cardMemberships, cardLabels, tasks, attachments) => ({
|
||||
type: ActionTypes.CARD_CREATE_RECEIVED,
|
||||
payload: {
|
||||
card,
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
attachments,
|
||||
},
|
||||
});
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import socket from './socket';
|
||||
import { transformAttachment } from './attachments';
|
||||
|
||||
/* Transformers */
|
||||
|
||||
|
@ -38,6 +39,10 @@ const createCard = (listId, data, headers) =>
|
|||
socket.post(`/lists/${listId}/cards`, transformCardData(data), headers).then((body) => ({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
included: {
|
||||
...body.included,
|
||||
attachments: body.included.attachments.map(transformAttachment),
|
||||
},
|
||||
}));
|
||||
|
||||
const getCard = (id, headers) =>
|
||||
|
@ -64,12 +69,21 @@ const makeHandleCardCreate = (next) => (body) => {
|
|||
next({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
included: {
|
||||
...body.included,
|
||||
attachments: body.included.attachments.map(transformAttachment),
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const makeHandleCardUpdate = makeHandleCardCreate;
|
||||
const makeHandleCardUpdate = (next) => (body) => {
|
||||
next({
|
||||
...body,
|
||||
item: transformCard(body.item),
|
||||
});
|
||||
};
|
||||
|
||||
const makeHandleCardDelete = makeHandleCardCreate;
|
||||
const makeHandleCardDelete = makeHandleCardUpdate;
|
||||
|
||||
export default {
|
||||
createCard,
|
||||
|
|
|
@ -20,6 +20,8 @@ export default class extends Model {
|
|||
static reducer({ type, payload }, Attachment) {
|
||||
switch (type) {
|
||||
case ActionTypes.BOARD_FETCH_SUCCEEDED:
|
||||
case ActionTypes.CARD_CREATE_SUCCEEDED:
|
||||
case ActionTypes.CARD_CREATE_RECEIVED:
|
||||
payload.attachments.forEach((attachment) => {
|
||||
Attachment.upsert(attachment);
|
||||
});
|
||||
|
|
|
@ -80,27 +80,15 @@ export default class extends Model {
|
|||
|
||||
break;
|
||||
case ActionTypes.CARD_CREATE:
|
||||
case ActionTypes.CARD_CREATE_RECEIVED:
|
||||
case ActionTypes.CARD_FETCH_SUCCEEDED:
|
||||
case ActionTypes.NOTIFICATION_CREATE_RECEIVED:
|
||||
Card.upsert(payload.card);
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_UPDATE: {
|
||||
const card = Card.withId(payload.id);
|
||||
|
||||
// FIXME: hack
|
||||
if (payload.data.boardId && payload.data.boardId !== card.boardId) {
|
||||
card.isSubscribed = false;
|
||||
|
||||
card.users.clear();
|
||||
card.labels.clear();
|
||||
}
|
||||
|
||||
card.update(payload.data);
|
||||
case ActionTypes.CARD_UPDATE:
|
||||
Card.withId(payload.id).update(payload.data);
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_DELETE:
|
||||
Card.withId(payload.id).deleteWithRelated();
|
||||
|
||||
|
@ -109,11 +97,36 @@ export default class extends Model {
|
|||
Card.withId(payload.localId).delete();
|
||||
Card.upsert(payload.card);
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_UPDATE_RECEIVED:
|
||||
Card.withId(payload.card.id).update(payload.card);
|
||||
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
||||
Card.withId(cardId).users.add(userId);
|
||||
});
|
||||
|
||||
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
||||
Card.withId(cardId).labels.add(labelId);
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_CREATE_RECEIVED:
|
||||
Card.upsert(payload.card);
|
||||
|
||||
payload.cardMemberships.forEach(({ cardId, userId }) => {
|
||||
Card.withId(cardId).users.add(userId);
|
||||
});
|
||||
|
||||
payload.cardLabels.forEach(({ cardId, labelId }) => {
|
||||
Card.withId(cardId).labels.add(labelId);
|
||||
});
|
||||
|
||||
break;
|
||||
case ActionTypes.CARD_UPDATE_RECEIVED: {
|
||||
const card = Card.withId(payload.card.id);
|
||||
|
||||
if (card) {
|
||||
card.update(payload.card);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case ActionTypes.CARD_DELETE_RECEIVED:
|
||||
Card.withId(payload.card.id).deleteWithRelated();
|
||||
|
||||
|
@ -177,6 +190,7 @@ export default class extends Model {
|
|||
|
||||
deleteWithRelated() {
|
||||
this.tasks.delete();
|
||||
this.attachments.delete();
|
||||
this.actions.delete();
|
||||
|
||||
this.delete();
|
||||
|
|
|
@ -21,6 +21,8 @@ export default class extends Model {
|
|||
static reducer({ type, payload }, Task) {
|
||||
switch (type) {
|
||||
case ActionTypes.BOARD_FETCH_SUCCEEDED:
|
||||
case ActionTypes.CARD_CREATE_SUCCEEDED:
|
||||
case ActionTypes.CARD_CREATE_RECEIVED:
|
||||
payload.tasks.forEach((task) => {
|
||||
Task.upsert(task);
|
||||
});
|
||||
|
|
|
@ -26,9 +26,19 @@ export function* createCardRequest(listId, localId, data) {
|
|||
);
|
||||
|
||||
try {
|
||||
const { item } = yield call(request, api.createCard, listId, data);
|
||||
const {
|
||||
item,
|
||||
included: { cardMemberships, cardLabels, tasks, attachments },
|
||||
} = yield call(request, api.createCard, listId, data);
|
||||
|
||||
const action = createCardSucceeded(localId, item);
|
||||
const action = createCardSucceeded(
|
||||
localId,
|
||||
item,
|
||||
cardMemberships,
|
||||
cardLabels,
|
||||
tasks,
|
||||
attachments,
|
||||
);
|
||||
yield put(action);
|
||||
|
||||
return {
|
||||
|
|
|
@ -2,11 +2,19 @@ import { call, put, select } from 'redux-saga/effects';
|
|||
|
||||
import { goToBoardService } from './router';
|
||||
import { createCardRequest, deleteCardRequest, updateCardRequest } from '../requests';
|
||||
import { nextCardPositionSelector, pathSelector } from '../../../selectors';
|
||||
import {
|
||||
boardByIdSelector,
|
||||
cardByIdSelector,
|
||||
listByIdSelector,
|
||||
nextCardPositionSelector,
|
||||
pathSelector,
|
||||
} from '../../../selectors';
|
||||
import { createCard, deleteCard, updateCard } from '../../../actions';
|
||||
import { createLocalId } from '../../../utils/local-id';
|
||||
|
||||
export function* createCardService(listId, data) {
|
||||
const { boardId } = yield select(listByIdSelector, listId);
|
||||
|
||||
const nextData = {
|
||||
...data,
|
||||
position: yield select(nextCardPositionSelector, listId),
|
||||
|
@ -18,6 +26,7 @@ export function* createCardService(listId, data) {
|
|||
createCard({
|
||||
...nextData,
|
||||
listId,
|
||||
boardId,
|
||||
id: localId,
|
||||
}),
|
||||
);
|
||||
|
@ -52,19 +61,40 @@ export function* moveCurrentCardService(listId, index) {
|
|||
}
|
||||
|
||||
export function* transferCardService(id, boardId, listId, index) {
|
||||
const position = yield select(nextCardPositionSelector, listId, index, id);
|
||||
const { cardId: currentCardId, boardId: currentBoardId } = yield select(pathSelector);
|
||||
|
||||
yield call(updateCardService, id, {
|
||||
boardId,
|
||||
listId,
|
||||
position,
|
||||
});
|
||||
if (id === currentCardId) {
|
||||
yield call(goToBoardService, currentBoardId);
|
||||
}
|
||||
|
||||
const card = yield select(cardByIdSelector, id);
|
||||
const board = yield select(boardByIdSelector, boardId);
|
||||
|
||||
yield put(deleteCard(id));
|
||||
|
||||
if (board.isFetching === false) {
|
||||
const position = yield select(nextCardPositionSelector, listId, index, id);
|
||||
|
||||
yield put(
|
||||
createCard({
|
||||
...card,
|
||||
listId,
|
||||
boardId,
|
||||
position,
|
||||
}),
|
||||
);
|
||||
|
||||
yield call(updateCardRequest, id, {
|
||||
listId,
|
||||
boardId,
|
||||
position,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export function* transferCurrentCardService(boardId, listId, index) {
|
||||
const { cardId, boardId: currentBoardId } = yield select(pathSelector);
|
||||
const { cardId } = yield select(pathSelector);
|
||||
|
||||
yield call(goToBoardService, currentBoardId);
|
||||
yield call(transferCardService, cardId, boardId, listId, index);
|
||||
}
|
||||
|
||||
|
|
|
@ -163,8 +163,8 @@ export function* deleteLabelReceivedService(label) {
|
|||
yield put(deleteLabelReceived(label));
|
||||
}
|
||||
|
||||
export function* createCardReceivedService(card) {
|
||||
yield put(createCardReceived(card));
|
||||
export function* createCardReceivedService(card, cardMemberships, cardLabels, tasks, attachments) {
|
||||
yield put(createCardReceived(card, cardMemberships, cardLabels, tasks, attachments));
|
||||
}
|
||||
|
||||
export function* updateCardReceivedService(card) {
|
||||
|
|
|
@ -116,9 +116,11 @@ const createSocketEventsChannel = () =>
|
|||
emit([deleteLabelReceivedService, item]);
|
||||
};
|
||||
|
||||
const handleCardCreate = api.makeHandleCardCreate(({ item }) => {
|
||||
emit([createCardReceivedService, item]);
|
||||
});
|
||||
const handleCardCreate = api.makeHandleCardCreate(
|
||||
({ item, included: { cardMemberships, cardLabels, tasks, attachments } }) => {
|
||||
emit([createCardReceivedService, item, cardMemberships, cardLabels, tasks, attachments]);
|
||||
},
|
||||
);
|
||||
|
||||
const handleCardUpdate = api.makeHandleCardUpdate(({ item }) => {
|
||||
emit([updateCardReceivedService, item]);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue