From 4540bd36c4b07080ea5d29f0fb31bb20e637c2d5 Mon Sep 17 00:00:00 2001 From: Xavier Priour Date: Mon, 19 Oct 2015 00:59:50 +0200 Subject: Import board: import comments and log activities --- client/components/activities/activities.jade | 56 +++++---- client/components/activities/activities.js | 17 ++- client/components/import/import.js | 2 +- i18n/en.i18n.json | 1 + models/import.js | 166 +++++++++++++++++++-------- 5 files changed, 164 insertions(+), 78 deletions(-) diff --git a/client/components/activities/activities.jade b/client/components/activities/activities.jade index c611ad75..28a9f9c9 100644 --- a/client/components/activities/activities.jade +++ b/client/components/activities/activities.jade @@ -14,41 +14,56 @@ template(name="boardActivities") p.activity-desc +memberName(user=user) - if($eq activityType 'createBoard') - | {{_ 'activity-created' boardLabel}}. + if($eq activityType 'addAttachment') + | {{{_ 'activity-attached' attachmentLink cardLink}}}. - if($eq activityType 'createList') - | {{_ 'activity-added' list.title boardLabel}}. + if($eq activityType 'addBoardMember') + | {{{_ 'activity-added' memberLink boardLabel}}}. + + if($eq activityType 'addComment') + | {{{_ 'activity-on' cardLink}}} + a.activity-comment(href="{{ card.absoluteUrl }}") + +viewer + = comment.text + + if($eq activityType 'archivedCard') + | {{{_ 'activity-archived' cardLink}}}. if($eq activityType 'archivedList') | {{_ 'activity-archived' list.title}}. + if($eq activityType 'createBoard') + | {{_ 'activity-created' boardLabel}}. + if($eq activityType 'createCard') | {{{_ 'activity-added' cardLink boardLabel}}}. + if($eq activityType 'createList') + | {{_ 'activity-added' list.title boardLabel}}. + + if($eq activityType 'importBoard') + | {{{_ 'activity-imported-board' boardLabel sourceLink}}}. + if($eq activityType 'importCard') | {{{_ 'activity-imported' cardLink boardLabel sourceLink}}}. - if($eq activityType 'archivedCard') - | {{{_ 'activity-archived' cardLink}}}. + if($eq activityType 'importList') + | {{{_ 'activity-imported' listLabel boardLabel sourceLink}}}. - if($eq activityType 'restoredCard') - | {{{_ 'activity-sent' cardLink boardLabel}}}. + if($eq activityType 'joinMember') + if($eq currentUser._id member._id) + | {{{_ 'activity-joined' cardLink}}}. + else + | {{{_ 'activity-added' memberLink cardLink}}}. if($eq activityType 'moveCard') | {{{_ 'activity-moved' cardLink oldList.title list.title}}}. - if($eq activityType 'addBoardMember') - | {{{_ 'activity-added' memberLink boardLabel}}}. - if($eq activityType 'removeBoardMember') | {{{_ 'activity-excluded' memberLink boardLabel}}}. - if($eq activityType 'joinMember') - if($eq currentUser._id member._id) - | {{{_ 'activity-joined' cardLink}}}. - else - | {{{_ 'activity-added' memberLink cardLink}}}. + if($eq activityType 'restoredCard') + | {{{_ 'activity-sent' cardLink boardLabel}}}. if($eq activityType 'unjoinMember') if($eq currentUser._id member._id) @@ -56,15 +71,6 @@ template(name="boardActivities") else | {{{_ 'activity-removed' memberLink cardLink}}}. - if($eq activityType 'addComment') - | {{{_ 'activity-on' cardLink}}} - a.activity-comment(href="{{ card.absoluteUrl }}") - +viewer - = comment.text - - if($eq activityType 'addAttachment') - | {{{_ 'activity-attached' attachmentLink cardLink}}}. - span.activity-meta {{ moment createdAt }} template(name="cardActivities") diff --git a/client/components/activities/activities.js b/client/components/activities/activities.js index b80493f7..b25c0ca8 100644 --- a/client/components/activities/activities.js +++ b/client/components/activities/activities.js @@ -60,11 +60,22 @@ BlazeComponent.extendComponent({ }, card.title)); }, + listLabel() { + return this.currentData().list().title; + }, + sourceLink() { const source = this.currentData().source; - return source && Blaze.toHTML(HTML.A({ - href: source.url, - }, source.system)); + if(source) { + if(source.url) { + return Blaze.toHTML(HTML.A({ + href: source.url, + }, source.system)); + } else { + return source.system; + } + } + return null; }, memberLink() { diff --git a/client/components/import/import.js b/client/components/import/import.js index a2972562..00918aac 100644 --- a/client/components/import/import.js +++ b/client/components/import/import.js @@ -46,7 +46,7 @@ const ImportPopup = BlazeComponent.extendComponent({ onFinish() { Popup.close(); - } + }, }); ImportPopup.extendComponent({ diff --git a/i18n/en.i18n.json b/i18n/en.i18n.json index 82ea14e5..0823ba08 100644 --- a/i18n/en.i18n.json +++ b/i18n/en.i18n.json @@ -8,6 +8,7 @@ "activity-created": "created %s", "activity-excluded": "excluded %s from %s", "activity-imported": "imported %s into %s from %s", + "activity-imported-board": "imported %s from %s", "activity-joined": "joined %s", "activity-moved": "moved %s from %s to %s", "activity-on": "on %s", diff --git a/models/import.js b/models/import.js index d0b25173..5095ee2e 100644 --- a/models/import.js +++ b/models/import.js @@ -10,12 +10,14 @@ class TrelloCreator { this.labels = {}; // the lists we created, indexed by Trello id (to map when importing cards) this.lists = {}; + // the comments, indexed by Trello card id (to map when importing cards) + this.comments = {}; } /** * must call parseActions before calling this one */ - createBoardAndLabels(trelloBoard, dateOfImport) { + createBoardAndLabels(trelloBoard) { const createdAt = this.createdAt.board; const boardToCreate = { archived: trelloBoard.closed, @@ -35,7 +37,7 @@ class TrelloCreator { title: trelloBoard.name, }; trelloBoard.labels.forEach((label) => { - labelToCreate = { + const labelToCreate = { _id: Random.id(6), color: label.color, name: label.name, @@ -45,11 +47,23 @@ class TrelloCreator { boardToCreate.labels.push(labelToCreate); }); const boardId = Boards.direct.insert(boardToCreate); - // XXX add activities + // log activity + Activities.direct.insert({ + activityType: 'importBoard', + boardId, + createdAt: new Date(), + source: { + id: trelloBoard.id, + system: 'Trello', + url: trelloBoard.url, + }, + // we attribute the import to current user, not the one from the original object + userId: Meteor.userId(), + }); return boardId; } - createLists(trelloLists, boardId, dateOfImport) { + createLists(trelloLists, boardId) { trelloLists.forEach((list) => { const listToCreate = { archived: list.closed, @@ -60,17 +74,29 @@ class TrelloCreator { }; listToCreate._id = Lists.direct.insert(listToCreate); this.lists[list.id] = listToCreate; - // XXX add activities + // log activity + Activities.direct.insert({ + activityType: 'importList', + boardId, + createdAt: new Date(), + listId: listToCreate._id, + source: { + id: list.id, + system: 'Trello', + }, + // we attribute the import to current user, not the one from the original object + userId: Meteor.userId(), + }); }); } - createCards(trelloCards, boardId, dateOfImport) { + createCardsAndComments(trelloCards, boardId) { trelloCards.forEach((card) => { const cardToCreate = { archived: card.closed, boardId, createdAt: this.createdAt.cards[card.id], - dateLastActivity: dateOfImport, + dateLastActivity: new Date(), description: card.desc, listId: this.lists[card.idList]._id, sort: card.pos, @@ -84,37 +110,102 @@ class TrelloCreator { return this.labels[trelloId]._id; }); } - Cards.direct.insert(cardToCreate); - // XXX add comments + // insert card + const cardId = Cards.direct.insert(cardToCreate); + // log activity + Activities.direct.insert({ + activityType: 'importCard', + boardId, + cardId, + createdAt: new Date(), + listId: cardToCreate.listId, + source: { + id: card.id, + system: 'Trello', + url: card.url, + }, + // we attribute the import to current user, not the one from the original card + userId: Meteor.userId(), + }); + // add comments + const comments = this.comments[card.id]; + if(comments) { + comments.forEach((comment) => { + const commentToCreate = { + boardId, + cardId, + createdAt: comment.date, + text: comment.data.text, + // XXX use the original comment user instead + userId: Meteor.userId(), + }; + const commentId = CardComments.direct.insert(commentToCreate); + Activities.direct.insert({ + activityType: 'addComment', + boardId: commentToCreate.boardId, + cardId: commentToCreate.cardId, + commentId, + createdAt: commentToCreate.createdAt, + userId: commentToCreate.userId, + }); + }); + } // XXX add attachments - // XXX add activities }); } parseActions(trelloActions) { - trelloActions.forEach((action) =>{ + trelloActions.forEach((action) => { switch (action.type) { - case 'createBoard': - this.createdAt.board = action.date; - break; - case 'createCard': - const cardId = action.data.card.id; - this.createdAt.cards[cardId] = action.date; - break; - case 'createList': - const listId = action.data.list.id; - this.createdAt.lists[listId] = action.date; - break; - // XXX extract comments as well - default: - // do nothing - break; + case 'createBoard': + this.createdAt.board = action.date; + break; + case 'createCard': + const cardId = action.data.card.id; + this.createdAt.cards[cardId] = action.date; + break; + case 'createList': + const listId = action.data.list.id; + this.createdAt.lists[listId] = action.date; + break; + case 'commentCard': + const id = action.data.card.id; + if(this.comments[id]) { + this.comments[id].push(action); + } else { + this.comments[id] = [action]; + } + break; + default: + // do nothing + break; } }); } } Meteor.methods({ + importTrelloBoard(trelloBoard, data) { + const trelloCreator = new TrelloCreator(); + // 1. check parameters are ok from a syntax point of view + try { + // XXX do proper checking + check(trelloBoard, Object); + check(data, Object); + } catch(e) { + throw new Meteor.Error('error-json-schema'); + } + // 2. check parameters are ok from a business point of view (exist & authorized) + // XXX check we are allowed + // 3. create all elements + trelloCreator.parseActions(trelloBoard.actions); + const boardId = trelloCreator.createBoardAndLabels(trelloBoard); + trelloCreator.createLists(trelloBoard.lists, boardId); + trelloCreator.createCardsAndComments(trelloBoard.cards, boardId); + // XXX set modifiedAt or lastActivity + // XXX add members + return boardId; + }, importTrelloCard(trelloCard, data) { // 1. check parameters are ok from a syntax point of view const DateString = Match.Where(function (dateAsString) { @@ -245,27 +336,4 @@ Meteor.methods({ }); return cardId; }, - importTrelloBoard(trelloBoard, data) { - const trelloCreator = new TrelloCreator(); - // 1. check parameters are ok from a syntax point of view - try { - // XXX do proper checking - check(trelloBoard, Object); - check(data, Object); - } catch(e) { - throw new Meteor.Error('error-json-schema'); - } - // 2. check parameters are ok from a business point of view (exist & authorized) - // XXX check we are allowed - // 3. create all elements - const dateOfImport = new Date(); - trelloCreator.parseActions(trelloBoard.actions); - const boardId = trelloCreator.createBoardAndLabels(trelloBoard, dateOfImport); - trelloCreator.createLists(trelloBoard.lists, boardId, dateOfImport); - trelloCreator.createCards(trelloBoard.cards, boardId, dateOfImport); - // XXX add activities - // XXX set modifiedAt or lastActivity - // XXX add members - return boardId; - }, }); -- cgit v1.2.3-1-g7c22