mirror of
https://github.com/wekan/wekan.git
synced 2026-02-05 16:11:47 +01:00
Fix Card.copy() mutating source card and normalize customFields
Card.copy() mutated `this` directly (boardId, labelIds, customFields,
etc.), corrupting the cached source card object and causing intermittent
failures on repeated copy operations. Now works on a shallow copy.
Also normalizes customFields to [] when it's not an array (e.g. legacy
{} data in the database), preventing "Custom fields must be an array"
schema validation errors on both copy and move operations.
This commit is contained in:
parent
d68ad47de6
commit
e8b9a3a163
1 changed files with 21 additions and 12 deletions
|
|
@ -611,6 +611,15 @@ Cards.helpers({
|
|||
const oldId = this._id;
|
||||
const oldCard = ReactiveCache.getCard(oldId);
|
||||
|
||||
// Work on a shallow copy to avoid mutating the source card in ReactiveCache
|
||||
const cardData = { ...this };
|
||||
delete cardData._id;
|
||||
|
||||
// Normalize customFields to ensure it's always an array
|
||||
if (!Array.isArray(cardData.customFields)) {
|
||||
cardData.customFields = [];
|
||||
}
|
||||
|
||||
// we must only copy the labels and custom fields if the target board
|
||||
// differs from the source board
|
||||
if (this.boardId !== boardId) {
|
||||
|
|
@ -633,19 +642,16 @@ Cards.helpers({
|
|||
}),
|
||||
'_id',
|
||||
);
|
||||
// now set the new label ids
|
||||
delete this.labelIds;
|
||||
this.labelIds = newCardLabels;
|
||||
cardData.labelIds = newCardLabels;
|
||||
|
||||
this.customFields = await this.mapCustomFieldsToBoard(newBoard._id);
|
||||
cardData.customFields = await this.mapCustomFieldsToBoard(newBoard._id);
|
||||
}
|
||||
|
||||
delete this._id;
|
||||
this.boardId = boardId;
|
||||
this.cardNumber = ReactiveCache.getBoard(boardId).getNextCardNumber();
|
||||
this.swimlaneId = swimlaneId;
|
||||
this.listId = listId;
|
||||
const _id = Cards.insert(this);
|
||||
cardData.boardId = boardId;
|
||||
cardData.cardNumber = ReactiveCache.getBoard(boardId).getNextCardNumber();
|
||||
cardData.swimlaneId = swimlaneId;
|
||||
cardData.listId = listId;
|
||||
const _id = Cards.insert(cardData);
|
||||
|
||||
// Copy attachments
|
||||
oldCard.attachments()
|
||||
|
|
@ -669,8 +675,6 @@ Cards.helpers({
|
|||
ReactiveCache.getCardComments({ cardId: oldId }).forEach(cmt => {
|
||||
cmt.copy(_id);
|
||||
});
|
||||
// restore the id, otherwise new copies will fail
|
||||
this._id = oldId;
|
||||
|
||||
return _id;
|
||||
},
|
||||
|
|
@ -2102,6 +2106,11 @@ Cards.helpers({
|
|||
});
|
||||
|
||||
mutatedFields.customFields = await this.mapCustomFieldsToBoard(newBoard._id);
|
||||
|
||||
// Ensure customFields is always an array (guards against legacy {} data)
|
||||
if (!Array.isArray(mutatedFields.customFields)) {
|
||||
mutatedFields.customFields = [];
|
||||
}
|
||||
}
|
||||
|
||||
await Cards.updateAsync(this._id, { $set: mutatedFields });
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue