mirror of
https://github.com/wekan/wekan.git
synced 2025-12-17 07:50:12 +01:00
Merge branch 'daniel-eder-fix/clone-board'
This commit is contained in:
commit
1fe0059402
2 changed files with 120 additions and 3 deletions
|
|
@ -42,9 +42,23 @@ Meteor.methods({
|
||||||
check(currentBoardId, Match.Maybe(String));
|
check(currentBoardId, Match.Maybe(String));
|
||||||
const exporter = new Exporter(sourceBoardId);
|
const exporter = new Exporter(sourceBoardId);
|
||||||
const data = exporter.build();
|
const data = exporter.build();
|
||||||
const addData = {};
|
const additionalData = {};
|
||||||
addData.membersMapping = getMembersToMap(data);
|
|
||||||
const creator = new WekanCreator(addData);
|
//get the members to map
|
||||||
|
const membersMapping = getMembersToMap(data);
|
||||||
|
|
||||||
|
//now mirror the mapping done in finishImport in client/components/import/import.js:
|
||||||
|
if (membersMapping) {
|
||||||
|
const mappingById = {};
|
||||||
|
membersMapping.forEach(member => {
|
||||||
|
if (member.wekanId) {
|
||||||
|
mappingById[member.id] = member.wekanId;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
additionalData.membersMapping = mappingById;
|
||||||
|
}
|
||||||
|
|
||||||
|
const creator = new WekanCreator(additionalData);
|
||||||
//data.title = `${data.title } - ${ TAPi18n.__('copy-tag')}`;
|
//data.title = `${data.title } - ${ TAPi18n.__('copy-tag')}`;
|
||||||
data.title = `${data.title}`;
|
data.title = `${data.title}`;
|
||||||
return creator.create(data, currentBoardId);
|
return creator.create(data, currentBoardId);
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ export class WekanCreator {
|
||||||
cards: {},
|
cards: {},
|
||||||
lists: {},
|
lists: {},
|
||||||
swimlanes: {},
|
swimlanes: {},
|
||||||
|
customFields: {},
|
||||||
};
|
};
|
||||||
// The object creator Wekan Id, indexed by the object Wekan id
|
// The object creator Wekan Id, indexed by the object Wekan id
|
||||||
// (so we only parse actions once!)
|
// (so we only parse actions once!)
|
||||||
|
|
@ -30,6 +31,8 @@ export class WekanCreator {
|
||||||
this.lists = {};
|
this.lists = {};
|
||||||
// Map of cards Wekan ID => Wekan ID
|
// Map of cards Wekan ID => Wekan ID
|
||||||
this.cards = {};
|
this.cards = {};
|
||||||
|
// Map of custom fields Wekan ID => Wekan ID
|
||||||
|
this.customFields = {};
|
||||||
// Map of comments Wekan ID => Wekan ID
|
// Map of comments Wekan ID => Wekan ID
|
||||||
this.commentIds = {};
|
this.commentIds = {};
|
||||||
// Map of attachments Wekan ID => Wekan ID
|
// Map of attachments Wekan ID => Wekan ID
|
||||||
|
|
@ -244,6 +247,7 @@ export class WekanCreator {
|
||||||
swimlaneId: false,
|
swimlaneId: false,
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
|
presentParentTask: boardToImport.presentParentTask,
|
||||||
// Standalone Export has modifiedAt missing, adding modifiedAt to fix it
|
// Standalone Export has modifiedAt missing, adding modifiedAt to fix it
|
||||||
modifiedAt: this._now(boardToImport.modifiedAt),
|
modifiedAt: this._now(boardToImport.modifiedAt),
|
||||||
permission: boardToImport.permission,
|
permission: boardToImport.permission,
|
||||||
|
|
@ -352,10 +356,40 @@ export class WekanCreator {
|
||||||
cardToCreate.members = wekanMembers;
|
cardToCreate.members = wekanMembers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// add assignees
|
||||||
|
if (card.assignees) {
|
||||||
|
const wekanAssignees = [];
|
||||||
|
// we can't just map, as some members may not have been mapped
|
||||||
|
card.assignees.forEach(sourceMemberId => {
|
||||||
|
if (this.members[sourceMemberId]) {
|
||||||
|
const wekanId = this.members[sourceMemberId];
|
||||||
|
// we may map multiple Wekan members to the same wekan user
|
||||||
|
// in which case we risk adding the same user multiple times
|
||||||
|
if (!wekanAssignees.find(wId => wId === wekanId)) {
|
||||||
|
wekanAssignees.push(wekanId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
if (wekanAssignees.length > 0) {
|
||||||
|
cardToCreate.assignees = wekanAssignees;
|
||||||
|
}
|
||||||
|
}
|
||||||
// set color
|
// set color
|
||||||
if (card.color) {
|
if (card.color) {
|
||||||
cardToCreate.color = card.color;
|
cardToCreate.color = card.color;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// add custom fields
|
||||||
|
if (card.customFields) {
|
||||||
|
cardToCreate.customFields = card.customFields.map(field => {
|
||||||
|
return {
|
||||||
|
_id: this.customFields[field._id],
|
||||||
|
value: field.value,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// insert card
|
// insert card
|
||||||
const cardId = Cards.direct.insert(cardToCreate);
|
const cardId = Cards.direct.insert(cardToCreate);
|
||||||
// keep track of Wekan id => Wekan id
|
// keep track of Wekan id => Wekan id
|
||||||
|
|
@ -481,6 +515,39 @@ export class WekanCreator {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create the Wekan custom fields corresponding to the supplied Wekan
|
||||||
|
* custom fields.
|
||||||
|
* @param wekanCustomFields
|
||||||
|
* @param boardId
|
||||||
|
*/
|
||||||
|
createCustomFields(wekanCustomFields, boardId) {
|
||||||
|
wekanCustomFields.forEach((field, fieldIndex) => {
|
||||||
|
const fieldToCreate = {
|
||||||
|
boardIds: [boardId],
|
||||||
|
name: field.name,
|
||||||
|
type: field.type,
|
||||||
|
settings: field.settings,
|
||||||
|
showOnCard: field.showOnCard,
|
||||||
|
showLabelOnMiniCard: field.showLabelOnMiniCard,
|
||||||
|
automaticallyOnCard: field.automaticallyOnCard,
|
||||||
|
//use date "now" if now created at date is provided (e.g. for very old boards)
|
||||||
|
createdAt: this._now(this.createdAt.customFields[field._id]),
|
||||||
|
modifiedAt: field.modifiedAt,
|
||||||
|
};
|
||||||
|
//insert copy of custom field
|
||||||
|
const fieldId = CustomFields.direct.insert(fieldToCreate);
|
||||||
|
//set modified date to now
|
||||||
|
CustomFields.direct.update(fieldId, {
|
||||||
|
$set: {
|
||||||
|
modifiedAt: this._now(),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
//store mapping of old id to new id
|
||||||
|
this.customFields[field._id] = fieldId;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Create labels if they do not exist and load this.labels.
|
// Create labels if they do not exist and load this.labels.
|
||||||
createLabels(wekanLabels, board) {
|
createLabels(wekanLabels, board) {
|
||||||
wekanLabels.forEach(label => {
|
wekanLabels.forEach(label => {
|
||||||
|
|
@ -560,6 +627,35 @@ export class WekanCreator {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
createSubtasks(wekanCards) {
|
||||||
|
wekanCards.forEach(card => {
|
||||||
|
// get new id of card (in created / new board)
|
||||||
|
const cardIdInNewBoard = this.cards[card._id];
|
||||||
|
|
||||||
|
//If there is a mapped parent card, use the mapped card
|
||||||
|
// this means, the card and parent were in the same source board
|
||||||
|
//If there is no mapped parent card, use the original parent id,
|
||||||
|
// this should handle cases where source and parent are in different boards
|
||||||
|
// Note: This can only handle board cloning (within the same wekan instance).
|
||||||
|
// When importing boards between instances the IDs are definitely
|
||||||
|
// lost if source and parent are two different boards
|
||||||
|
// This is not the place to fix it, the entire subtask system needs to be rethought there.
|
||||||
|
const parentIdInNewBoard = this.cards[card.parentId]
|
||||||
|
? this.cards[card.parentId]
|
||||||
|
: card.parentId;
|
||||||
|
|
||||||
|
//if the parent card exists, proceed
|
||||||
|
if (Cards.findOne(parentIdInNewBoard)) {
|
||||||
|
//set parent id of the card in the new board to the new id of the parent
|
||||||
|
Cards.direct.update(cardIdInNewBoard, {
|
||||||
|
$set: {
|
||||||
|
parentId: parentIdInNewBoard,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
createChecklists(wekanChecklists) {
|
createChecklists(wekanChecklists) {
|
||||||
const result = [];
|
const result = [];
|
||||||
wekanChecklists.forEach((checklist, checklistIndex) => {
|
wekanChecklists.forEach((checklist, checklistIndex) => {
|
||||||
|
|
@ -690,6 +786,11 @@ export class WekanCreator {
|
||||||
this.createdAt.swimlanes[swimlaneId] = activity.createdAt;
|
this.createdAt.swimlanes[swimlaneId] = activity.createdAt;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
case 'createCustomField': {
|
||||||
|
const customFieldId = activity.customFieldId;
|
||||||
|
this.createdAt.customFields[customFieldId] = activity.createdAt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
@ -840,7 +941,9 @@ export class WekanCreator {
|
||||||
const boardId = this.createBoardAndLabels(board);
|
const boardId = this.createBoardAndLabels(board);
|
||||||
this.createLists(board.lists, boardId);
|
this.createLists(board.lists, boardId);
|
||||||
this.createSwimlanes(board.swimlanes, boardId);
|
this.createSwimlanes(board.swimlanes, boardId);
|
||||||
|
this.createCustomFields(board.customFields, boardId);
|
||||||
this.createCards(board.cards, boardId);
|
this.createCards(board.cards, boardId);
|
||||||
|
this.createSubtasks(board.cards);
|
||||||
this.createChecklists(board.checklists);
|
this.createChecklists(board.checklists);
|
||||||
this.createChecklistItems(board.checklistItems);
|
this.createChecklistItems(board.checklistItems);
|
||||||
this.importActivities(board.activities, boardId);
|
this.importActivities(board.activities, boardId);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue