From 5665c755cb23b3a14520c52c16d9c18b8ac5bfe9 Mon Sep 17 00:00:00 2001 From: Ghassen Rjab Date: Sun, 20 Aug 2017 22:45:57 +0100 Subject: Import Wekan board activities There is a minor catch here, we can't import activities related to adding attachments for now --- models/wekanCreator.js | 206 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 166 insertions(+), 40 deletions(-) diff --git a/models/wekanCreator.js b/models/wekanCreator.js index b5f9b0ff..86e3dfc6 100644 --- a/models/wekanCreator.js +++ b/models/wekanCreator.js @@ -27,6 +27,12 @@ export class WekanCreator { this.lists = {}; // Map of cards Wekan ID => Wekan ID this.cards = {}; + // Map of comments Wekan ID => Wekan ID + this.commentIds = {}; + // Map of attachments Wekan ID => Wekan ID + this.attachmentIds = {}; + // Map of checklists Wekan ID => Wekan ID + this.checklists = {}; // The comments, indexed by Wekan card id (to map when importing cards) this.comments = {}; // the members, indexed by Wekan member id => Wekan user ID @@ -248,21 +254,21 @@ export class WekanCreator { const cardId = Cards.direct.insert(cardToCreate); // keep track of Wekan id => WeKan id this.cards[card._id] = cardId; - // log activity - Activities.direct.insert({ - activityType: 'importCard', - boardId, - cardId, - createdAt: this._now(), - listId: cardToCreate.listId, - source: { - id: card._id, - system: 'Wekan', - }, - // we attribute the import to current user, - // not the author of the original card - userId: this._user(), - }); + // // log activity + // Activities.direct.insert({ + // activityType: 'importCard', + // boardId, + // cardId, + // createdAt: this._now(), + // listId: cardToCreate.listId, + // source: { + // id: card._id, + // system: 'Wekan', + // }, + // // we attribute the import to current user, + // // not the author of the original card + // userId: this._user(), + // }); // add comments const comments = this.comments[card._id]; if (comments) { @@ -270,7 +276,7 @@ export class WekanCreator { const commentToCreate = { boardId, cardId, - createdAt: this._now(comment.date), + createdAt: this._now(comment.createdAt), text: comment.text, // we attribute the comment to the original author, default to current user userId: this._user(comment.userId), @@ -278,16 +284,17 @@ export class WekanCreator { // dateLastActivity will be set from activity insert, no need to // update it ourselves const commentId = CardComments.direct.insert(commentToCreate); - Activities.direct.insert({ - activityType: 'addComment', - boardId: commentToCreate.boardId, - cardId: commentToCreate.cardId, - commentId, - createdAt: this._now(commentToCreate.createdAt), - // we attribute the addComment (not the import) - // to the original author - it is needed by some UI elements. - userId: commentToCreate.userId, - }); + this.commentIds[comment._id] = commentId; + // Activities.direct.insert({ + // activityType: 'addComment', + // boardId: commentToCreate.boardId, + // cardId: commentToCreate.cardId, + // commentId, + // createdAt: this._now(commentToCreate.createdAt), + // // we attribute the addComment (not the import) + // // to the original author - it is needed by some UI elements. + // userId: commentToCreate.userId, + // }); }); } const attachments = this.attachments[card._id]; @@ -310,6 +317,7 @@ export class WekanCreator { const wekanAtt = Attachments.insert(file, () => { // we do nothing }); + this.attachmentIds[att._id] = wekanAtt._id; // if(wekanCoverId === att._id) { Cards.direct.update(cardId, { $set: {coverId: wekanAtt._id}}); @@ -327,6 +335,7 @@ export class WekanCreator { const wekanAtt = Attachments.insert(file, () => { // we do nothing }); + this.attachmentIds[att._id] = wekanAtt._id; // if(wekanCoverId === att._id) { Cards.direct.update(cardId, { $set: {coverId: wekanAtt._id}}); @@ -373,20 +382,20 @@ export class WekanCreator { const listId = Lists.direct.insert(listToCreate); Lists.direct.update(listId, {$set: {'updatedAt': this._now()}}); this.lists[list._id] = listId; - // log activity - Activities.direct.insert({ - activityType: 'importList', - boardId, - createdAt: this._now(), - listId, - source: { - id: list._id, - system: 'Wekan', - }, - // We attribute the import to current user, - // not the creator of the original object - userId: this._user(), - }); + // // log activity + // Activities.direct.insert({ + // activityType: 'importList', + // boardId, + // createdAt: this._now(), + // listId, + // source: { + // id: list._id, + // system: 'Wekan', + // }, + // // We attribute the import to current user, + // // not the creator of the original object + // userId: this._user(), + // }); }); } @@ -399,6 +408,8 @@ export class WekanCreator { createdAt: checklist.createdAt, }; const checklistId = Checklists.direct.insert(checklistToCreate); + // keep track of Wekan id => WeKan id + this.checklists[checklist._id] = checklistId; // Now add the items to the checklist const itemsToCreate = []; checklist.items.forEach((item) => { @@ -462,6 +473,120 @@ export class WekanCreator { }); } + importActivities(activities, boardId) { + activities.forEach((activity) => { + switch (activity.activityType) { + // Board related activities + // TODO: addBoardMember, removeBoardMember + case 'createBoard': { + Activities.direct.insert({ + userId: this._user(activity.userId), + type: 'board', + activityTypeId: boardId, + activityType: activity.activityType, + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + // List related activities + // TODO: removeList, archivedList + case 'createList': { + Activities.direct.insert({ + userId: this._user(activity.userId), + type: 'list', + activityType: activity.activityType, + listId: this.lists[activity.listId], + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + // Card related activities + // TODO: archivedCard, restoredCard, joinMember, unjoinMember + case 'createCard': { + Activities.direct.insert({ + userId: this._user(activity.userId), + activityType: activity.activityType, + listId: this.lists[activity.listId], + cardId: this.cards[activity.cardId], + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + case 'moveCard': { + Activities.direct.insert({ + userId: this._user(activity.userId), + oldListId: this.lists[activity.oldListId], + activityType: activity.activityType, + listId: this.lists[activity.listId], + cardId: this.cards[activity.cardId], + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + // Comment related activities + case 'addComment': { + Activities.direct.insert({ + userId: this._user(activity.userId), + activityType: activity.activityType, + cardId: this.cards[activity.cardId], + commentId: this.commentIds[activity.commentId], + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + // Attachment related activities + // TODO: We can't add activities related to adding attachments + // because when we import an attachment, an activity is + // autmatically created. We need to directly insert the attachment + // without calling the "Attachments.files.after.insert" hook first, + // then we can uncomment the code below + // case 'addAttachment': { + // console.log(this.attachmentIds); + // Activities.direct.insert({ + // userId: this._user(activity.userId), + // type: 'card', + // activityType: activity.activityType, + // attachmentId: this.attachmentIds[activity.attachmentId], + // cardId: this.cards[activity.cardId], + // boardId, + // createdAt: this._now(activity.createdAt), + // }); + // break; + // } + // Checklist related activities + case 'addChecklist': { + Activities.direct.insert({ + userId: this._user(activity.userId), + activityType: activity.activityType, + cardId: this.cards[activity.cardId], + checklistId: this.checklists[activity.checklistId], + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + } + case 'addChecklistItem': { + Activities.direct.insert({ + userId: this._user(activity.userId), + activityType: activity.activityType, + cardId: this.cards[activity.cardId], + checklistId: this.checklists[activity.checklistId], + checklistItemId: activity.checklistItemId.replace( + activity.checklistId, + this.checklists[activity.checklistId]), + boardId, + createdAt: this._now(activity.createdAt), + }); + break; + }} + }); + } + check(board) { try { // check(data, { @@ -491,6 +616,7 @@ export class WekanCreator { this.createLists(board.lists, boardId); this.createCards(board.cards, boardId); this.createChecklists(board.checklists); + this.importActivities(board.activities, boardId); // XXX add members return boardId; } -- cgit v1.2.3-1-g7c22 From f1488436b8ec69d960ef958581880828bc828efe Mon Sep 17 00:00:00 2001 From: Ghassen Rjab Date: Wed, 23 Aug 2017 06:42:25 +0100 Subject: Import Trello board activities --- models/trelloCreator.js | 159 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 131 insertions(+), 28 deletions(-) diff --git a/models/trelloCreator.js b/models/trelloCreator.js index aa86a5c8..57d4e626 100644 --- a/models/trelloCreator.js +++ b/models/trelloCreator.js @@ -27,6 +27,10 @@ export class TrelloCreator { this.lists = {}; // Map of cards Trello ID => Wekan ID this.cards = {}; + // Map of attachments Wekan ID => Wekan ID + this.attachmentIds = {}; + // Map of checklists Wekan ID => Wekan ID + this.checklists = {}; // The comments, indexed by Trello card id (to map when importing cards) this.comments = {}; // the members, indexed by Trello member id => Wekan user ID @@ -261,21 +265,21 @@ export class TrelloCreator { // keep track of Trello id => WeKan id this.cards[card.id] = cardId; // log activity - Activities.direct.insert({ - activityType: 'importCard', - boardId, - cardId, - createdAt: this._now(), - listId: cardToCreate.listId, - source: { - id: card.id, - system: 'Trello', - url: card.url, - }, - // we attribute the import to current user, - // not the author of the original card - userId: this._user(), - }); + // Activities.direct.insert({ + // activityType: 'importCard', + // boardId, + // cardId, + // createdAt: this._now(), + // listId: cardToCreate.listId, + // source: { + // id: card.id, + // system: 'Trello', + // url: card.url, + // }, + // // we attribute the import to current user, + // // not the author of the original card + // userId: this._user(), + // }); // add comments const comments = this.comments[card.id]; if (comments) { @@ -291,6 +295,8 @@ export class TrelloCreator { // dateLastActivity will be set from activity insert, no need to // update it ourselves const commentId = CardComments.direct.insert(commentToCreate); + // We need to keep adding comment activities this way with Trello + // because it doesn't provide a comment ID Activities.direct.insert({ activityType: 'addComment', boardId: commentToCreate.boardId, @@ -322,6 +328,7 @@ export class TrelloCreator { const wekanAtt = Attachments.insert(file, () => { // we do nothing }); + this.attachmentIds[att.id] = wekanAtt._id; // if(trelloCoverId === att.id) { Cards.direct.update(cardId, { $set: {coverId: wekanAtt._id}}); @@ -368,19 +375,19 @@ export class TrelloCreator { Lists.direct.update(listId, {$set: {'updatedAt': this._now()}}); this.lists[list.id] = listId; // log activity - Activities.direct.insert({ - activityType: 'importList', - boardId, - createdAt: this._now(), - listId, - source: { - id: list.id, - system: 'Trello', - }, - // We attribute the import to current user, - // not the creator of the original object - userId: this._user(), - }); + // Activities.direct.insert({ + // activityType: 'importList', + // boardId, + // createdAt: this._now(), + // listId, + // source: { + // id: list.id, + // system: 'Trello', + // }, + // // We attribute the import to current user, + // // not the creator of the original object + // userId: this._user(), + // }); }); } @@ -393,6 +400,8 @@ export class TrelloCreator { createdAt: this._now(), }; const checklistId = Checklists.direct.insert(checklistToCreate); + // keep track of Trello id => WeKan id + this.checklists[checklist.id] = checklistId; // Now add the items to the checklist const itemsToCreate = []; checklist.checkItems.forEach((item) => { @@ -472,6 +481,99 @@ export class TrelloCreator { }); } + importActions(actions, boardId) { + actions.forEach((action) => { + switch (action.type) { + // Board related actions + // TODO: addBoardMember, removeBoardMember + case 'createBoard': { + Activities.direct.insert({ + userId: this._user(action.idMemberCreator), + type: 'board', + activityTypeId: boardId, + activityType: 'createBoard', + boardId, + createdAt: this._now(action.date), + }); + break; + } + // List related activities + // TODO: removeList, archivedList + case 'createList': { + Activities.direct.insert({ + userId: this._user(action.idMemberCreator), + type: 'list', + activityType: 'createList', + listId: this.lists[action.data.list.id], + boardId, + createdAt: this._now(action.date), + }); + break; + } + // Card related activities + // TODO: archivedCard, restoredCard, joinMember, unjoinMember + case 'createCard': { + Activities.direct.insert({ + userId: this._user(action.idMemberCreator), + activityType: 'createCard', + listId: this.lists[action.data.list.id], + cardId: this.cards[action.data.card.id], + boardId, + createdAt: this._now(action.date), + }); + break; + } + case 'updateCard': { + if (action.data.old.idList) { + Activities.direct.insert({ + userId: this._user(action.idMemberCreator), + oldListId: this.lists[action.data.old.idList], + activityType: 'moveCard', + listId: this.lists[action.data.listAfter.id], + cardId: this.cards[action.data.card.id], + boardId, + createdAt: this._now(action.date), + }); + } + break; + } + // Comment related activities + // Trello doesn't export the comment id + // Attachment related activities + // TODO: We can't add activities related to adding attachments + // because when we import an attachment, an activity is + // autmatically created. We need to directly insert the attachment + // without calling the "Attachments.files.after.insert" hook first, + // then we can uncomment the code below + // case 'addAttachment': { + // console.log(this.attachmentIds); + // Activities.direct.insert({ + // userId: this._user(activity.userId), + // type: 'card', + // activityType: activity.activityType, + // attachmentId: this.attachmentIds[activity.attachmentId], + // cardId: this.cards[activity.cardId], + // boardId, + // createdAt: this._now(activity.createdAt), + // }); + // break; + // } + // Checklist related activities + case 'addChecklistToCard': { + Activities.direct.insert({ + userId: this._user(action.idMemberCreator), + activityType: 'addChecklist', + cardId: this.cards[action.data.card.id], + checklistId: this.checklists[action.data.checklist.id], + boardId, + createdAt: this._now(action.date), + }); + break; + }} + // Trello doesn't have an add checklist item action + }); + } + check(board) { try { // check(data, { @@ -501,6 +603,7 @@ export class TrelloCreator { this.createLists(board.lists, boardId); this.createCards(board.cards, boardId); this.createChecklists(board.checklists); + this.importActions(board.actions, boardId); // XXX add members return boardId; } -- cgit v1.2.3-1-g7c22 From a2d7e2cb741186218c87c34a18f82d526a63d54b Mon Sep 17 00:00:00 2001 From: Ghassen Rjab Date: Thu, 24 Aug 2017 01:05:53 +0100 Subject: Fix dates of activities related to comments imported from Trello --- models/trelloCreator.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/models/trelloCreator.js b/models/trelloCreator.js index 57d4e626..60207546 100644 --- a/models/trelloCreator.js +++ b/models/trelloCreator.js @@ -302,7 +302,7 @@ export class TrelloCreator { boardId: commentToCreate.boardId, cardId: commentToCreate.cardId, commentId, - createdAt: this._now(commentToCreate.createdAt), + createdAt: this._now(comment.date), // we attribute the addComment (not the import) // to the original author - it is needed by some UI elements. userId: commentToCreate.userId, -- cgit v1.2.3-1-g7c22