mirror of
https://github.com/wekan/wekan.git
synced 2026-02-05 16:11:47 +01:00
Merge pull request #6126 from harryadel/fix/issue-6105-copy-move-remaining
Await async setDone before closing popup in copy/move dialogs
This commit is contained in:
commit
404dd0735d
4 changed files with 68 additions and 44 deletions
|
|
@ -1012,6 +1012,9 @@ Template.editCardAssignerForm.events({
|
|||
return ret;
|
||||
}
|
||||
async setDone(cardId, options) {
|
||||
// Capture DOM values immediately before any async operations
|
||||
const position = this.$('input[name="position"]:checked').val();
|
||||
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
let sortIndex = 0;
|
||||
|
|
@ -1019,7 +1022,6 @@ Template.editCardAssignerForm.events({
|
|||
if (cardId) {
|
||||
const targetCard = ReactiveCache.getCard(cardId);
|
||||
if (targetCard) {
|
||||
const position = this.$('input[name="position"]:checked').val();
|
||||
if (position === 'above') {
|
||||
sortIndex = targetCard.sort - 0.5;
|
||||
} else {
|
||||
|
|
@ -1042,37 +1044,40 @@ Template.editCardAssignerForm.events({
|
|||
return ret;
|
||||
}
|
||||
async setDone(cardId, options) {
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
// const textarea = $('#copy-card-title');
|
||||
// Capture DOM values immediately before any async operations
|
||||
const textarea = this.$('#copy-card-title');
|
||||
const title = textarea.val().trim();
|
||||
const position = this.$('input[name="position"]:checked').val();
|
||||
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
if (title) {
|
||||
const newCardId = await Meteor.callAsync('copyCard', card._id, options.boardId, options.swimlaneId, options.listId, true, {title: title});
|
||||
|
||||
// Position the copied card
|
||||
// Position the copied card (newCard may be null for cross-board copies
|
||||
// if the client hasn't received the publication update yet)
|
||||
if (newCardId) {
|
||||
const newCard = ReactiveCache.getCard(newCardId);
|
||||
let sortIndex = 0;
|
||||
if (newCard) {
|
||||
let sortIndex = 0;
|
||||
|
||||
if (cardId) {
|
||||
const targetCard = ReactiveCache.getCard(cardId);
|
||||
if (targetCard) {
|
||||
const position = this.$('input[name="position"]:checked').val();
|
||||
if (position === 'above') {
|
||||
sortIndex = targetCard.sort - 0.5;
|
||||
} else {
|
||||
sortIndex = targetCard.sort + 0.5;
|
||||
if (cardId) {
|
||||
const targetCard = ReactiveCache.getCard(cardId);
|
||||
if (targetCard) {
|
||||
if (position === 'above') {
|
||||
sortIndex = targetCard.sort - 0.5;
|
||||
} else {
|
||||
sortIndex = targetCard.sort + 0.5;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// If no card selected, copy to end
|
||||
sortIndex = newCard.getMaxSort(options.listId, options.swimlaneId) + 1;
|
||||
}
|
||||
} else {
|
||||
// If no card selected, copy to end
|
||||
sortIndex = newCard.getMaxSort(options.listId, options.swimlaneId) + 1;
|
||||
}
|
||||
|
||||
await newCard.move(options.boardId, options.swimlaneId, options.listId, sortIndex);
|
||||
await newCard.move(options.boardId, options.swimlaneId, options.listId, sortIndex);
|
||||
}
|
||||
}
|
||||
|
||||
// In case the filter is active we need to add the newly inserted card in
|
||||
|
|
@ -1091,11 +1096,13 @@ Template.editCardAssignerForm.events({
|
|||
return ret;
|
||||
}
|
||||
async setDone(cardId, options) {
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
// Capture DOM values immediately before any async operations
|
||||
const textarea = this.$('#copy-card-title');
|
||||
const title = textarea.val().trim();
|
||||
const position = this.$('input[name="position"]:checked').val();
|
||||
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
if (title) {
|
||||
const _id = Cards.insert({
|
||||
|
|
@ -1111,7 +1118,6 @@ Template.editCardAssignerForm.events({
|
|||
if (cardId) {
|
||||
const targetCard = ReactiveCache.getCard(cardId);
|
||||
if (targetCard) {
|
||||
const position = this.$('input[name="position"]:checked').val();
|
||||
if (position === 'above') {
|
||||
sortIndex = targetCard.sort - 0.5;
|
||||
} else {
|
||||
|
|
@ -1136,11 +1142,13 @@ Template.editCardAssignerForm.events({
|
|||
return ret;
|
||||
}
|
||||
async setDone(cardId, options) {
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
// Capture DOM values immediately before any async operations
|
||||
const textarea = this.$('#copy-card-title');
|
||||
const title = textarea.val().trim();
|
||||
const position = this.$('input[name="position"]:checked').val();
|
||||
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
if (title) {
|
||||
const titleList = JSON.parse(title);
|
||||
|
|
@ -1155,7 +1163,6 @@ Template.editCardAssignerForm.events({
|
|||
if (cardId) {
|
||||
const targetCard = ReactiveCache.getCard(cardId);
|
||||
if (targetCard) {
|
||||
const position = this.$('input[name="position"]:checked').val();
|
||||
if (position === 'above') {
|
||||
sortIndex = targetCard.sort - 0.5;
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -186,7 +186,7 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent {
|
|||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-done'() {
|
||||
async 'click .js-done'() {
|
||||
const boardSelect = this.$('.js-select-boards')[0];
|
||||
const boardId = boardSelect.options[boardSelect.selectedIndex].value;
|
||||
|
||||
|
|
@ -201,7 +201,11 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent {
|
|||
'swimlaneId' : swimlaneId,
|
||||
'listId' : listId,
|
||||
}
|
||||
this.setDone(boardId, swimlaneId, listId, options);
|
||||
try {
|
||||
await this.setDone(boardId, swimlaneId, listId, options);
|
||||
} catch (e) {
|
||||
console.error('Error in list dialog operation:', e);
|
||||
}
|
||||
Popup.back(2);
|
||||
},
|
||||
'change .js-select-boards'(event) {
|
||||
|
|
|
|||
|
|
@ -80,7 +80,7 @@ export class DialogWithBoardSwimlaneListCard extends DialogWithBoardSwimlaneList
|
|||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-done'() {
|
||||
async 'click .js-done'() {
|
||||
const boardSelect = this.$('.js-select-boards')[0];
|
||||
const boardId = boardSelect.options[boardSelect.selectedIndex].value;
|
||||
|
||||
|
|
@ -99,7 +99,11 @@ export class DialogWithBoardSwimlaneListCard extends DialogWithBoardSwimlaneList
|
|||
'listId' : listId,
|
||||
'cardId': cardId,
|
||||
}
|
||||
this.setDone(cardId, options);
|
||||
try {
|
||||
await this.setDone(cardId, options);
|
||||
} catch (e) {
|
||||
console.error('Error in card dialog operation:', e);
|
||||
}
|
||||
Popup.back(2);
|
||||
},
|
||||
'change .js-select-boards'(event) {
|
||||
|
|
|
|||
|
|
@ -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