diff options
author | Lauri Ojansivu <x@xet7.org> | 2017-08-30 00:59:29 +0300 |
---|---|---|
committer | Lauri Ojansivu <x@xet7.org> | 2017-08-30 00:59:29 +0300 |
commit | 51206cb108b92eec80e35610ef88551fe8a43feb (patch) | |
tree | 3b30e330c3e4b62551f18463be9204990ece480c | |
parent | ecb4863c39279c8a93684369c20674aa255bbd8e (diff) | |
parent | 200d49d369275b190943a24ad3834b07f3a2a06e (diff) | |
download | wekan-51206cb108b92eec80e35610ef88551fe8a43feb.tar.gz wekan-51206cb108b92eec80e35610ef88551fe8a43feb.tar.bz2 wekan-51206cb108b92eec80e35610ef88551fe8a43feb.zip |
Merge branch 'GhassenRjab-feature/import-activities' into devel
Import Trello and Wekan board times of creation of activities.
Thanks to GhassenRjab ! Related #1157
-rw-r--r-- | CHANGELOG.md | 12 | ||||
-rw-r--r-- | i18n/de.i18n.json | 2 | ||||
-rw-r--r-- | i18n/fr.i18n.json | 2 | ||||
-rw-r--r-- | models/trelloCreator.js | 161 | ||||
-rw-r--r-- | models/wekanCreator.js | 206 |
5 files changed, 312 insertions, 71 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md index 865f523f..2cdf4215 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,15 @@ +# Upcoming Wekan release + +This release adds the following new features: + +* [Import Trello and Wekan board times of creation of activities](https://github.com/wekan/wekan/pull/1187). + +Known issues: + +* [Attachment creation times are not imported to Trello and Wekan](https://github.com/wekan/wekan/issues/1157). + +Thanks to GitHub user GhassenRjab for contributions. + # v0.33 2017-08-29 Wekan release This release adds the following new features: diff --git a/i18n/de.i18n.json b/i18n/de.i18n.json index 4573c6c3..f3070ee2 100644 --- a/i18n/de.i18n.json +++ b/i18n/de.i18n.json @@ -144,7 +144,7 @@ "comment-only": "Nur kommentierbar", "comment-only-desc": "Kann Karten nur Kommentieren", "computer": "Computer", - "copy-card-link-to-clipboard": "Copy card link to clipboard", + "copy-card-link-to-clipboard": "Kopiere die Karte in die Zwischenablage", "create": "Erstellen", "createBoardPopup-title": "Board erstellen", "chooseBoardSourcePopup-title": "Board importieren", diff --git a/i18n/fr.i18n.json b/i18n/fr.i18n.json index 37f82303..48b9ee66 100644 --- a/i18n/fr.i18n.json +++ b/i18n/fr.i18n.json @@ -144,7 +144,7 @@ "comment-only": "Commentaire uniquement", "comment-only-desc": "Ne peut que commenter des cartes.", "computer": "Ordinateur", - "copy-card-link-to-clipboard": "Copy card link to clipboard", + "copy-card-link-to-clipboard": "Copier le lien vers la carte dans le presse-papier", "create": "Créer", "createBoardPopup-title": "Créer un tableau", "chooseBoardSourcePopup-title": "Importer un tableau", diff --git a/models/trelloCreator.js b/models/trelloCreator.js index aa86a5c8..60207546 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,12 +295,14 @@ 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, 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, @@ -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; } diff --git a/models/wekanCreator.js b/models/wekanCreator.js index 36e5e1ca..1a02339a 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 @@ -249,21 +255,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) { @@ -271,7 +277,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), @@ -279,16 +285,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]; @@ -311,6 +318,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}}); @@ -328,6 +336,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}}); @@ -374,20 +383,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(), + // }); }); } @@ -400,6 +409,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) => { @@ -463,6 +474,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, { @@ -492,6 +617,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; } |