浏览代码

Merge pull request #418 from xavierpriour/devel

Import Trello: set creation date for older Trello elements
Maxime Quandalle 9 年之前
父节点
当前提交
8d5d7ee678
共有 1 个文件被更改,包括 84 次插入32 次删除
  1. 84 32
      models/import.js

+ 84 - 32
models/import.js

@@ -5,13 +5,22 @@ const DateString = Match.Where(function (dateAsString) {
 
 
 class TrelloCreator {
 class TrelloCreator {
   constructor(data) {
   constructor(data) {
-    // The object creation dates, indexed by Trello id (so we only parse actions
-    // once!)
+    // we log current date, to use the same timestamp for all our actions.
+    // this helps to retrieve all elements performed by the same import.
+    this._nowDate = new Date();
+    // The object creation dates, indexed by Trello id
+    // (so we only parse actions once!)
     this.createdAt = {
     this.createdAt = {
       board: null,
       board: null,
       cards: {},
       cards: {},
       lists: {},
       lists: {},
     };
     };
+    // The object creator Trello Id, indexed by the object Trello id
+    // (so we only parse actions once!)
+    this.createdBy = {
+      cards: {}, // only cards have a field for that
+    };
+
     // Map of labels Trello ID => Wekan ID
     // Map of labels Trello ID => Wekan ID
     this.labels = {};
     this.labels = {};
     // Map of lists Trello ID => Wekan ID
     // Map of lists Trello ID => Wekan ID
@@ -25,6 +34,39 @@ class TrelloCreator {
     this.attachments = {};
     this.attachments = {};
   }
   }
 
 
+  /**
+   * If dateString is provided,
+   * return the Date it represents.
+   * If not, will return the date when it was first called.
+   * This is useful for us, as we want all import operations to
+   * have the exact same date for easier later retrieval.
+   *
+   * @param {String} dateString a properly formatted Date
+   */
+  _now(dateString) {
+    if(dateString) {
+      return new Date(dateString);
+    }
+    if(!this._nowDate) {
+      this._nowDate = new Date();
+    }
+    return this._nowDate;
+  }
+
+  /**
+   * if trelloUserId is provided and we have a mapping,
+   * return it.
+   * Otherwise return current logged user.
+   * @param trelloUserId
+   * @private
+     */
+  _user(trelloUserId) {
+    if(trelloUserId && this.members[trelloUserId]) {
+      return this.members[trelloUserId];
+    }
+    return Meteor.userId();
+  }
+
   checkActions(trelloActions) {
   checkActions(trelloActions) {
     check(trelloActions, [Match.ObjectIncluding({
     check(trelloActions, [Match.ObjectIncluding({
       data: Object,
       data: Object,
@@ -79,11 +121,11 @@ class TrelloCreator {
 
 
   // You must call parseActions before calling this one.
   // You must call parseActions before calling this one.
   createBoardAndLabels(trelloBoard) {
   createBoardAndLabels(trelloBoard) {
-    const createdAt = this.createdAt.board;
     const boardToCreate = {
     const boardToCreate = {
       archived: trelloBoard.closed,
       archived: trelloBoard.closed,
       color: this.getColor(trelloBoard.prefs.background),
       color: this.getColor(trelloBoard.prefs.background),
-      createdAt,
+      // very old boards won't have a creation activity so no creation date
+      createdAt: this._now(this.createdAt.board),
       labels: [],
       labels: [],
       members: [{
       members: [{
         userId: Meteor.userId(),
         userId: Meteor.userId(),
@@ -103,10 +145,16 @@ class TrelloCreator {
         if(this.members[trelloId]) {
         if(this.members[trelloId]) {
           const wekanId = this.members[trelloId];
           const wekanId = this.members[trelloId];
           // do we already have it in our list?
           // do we already have it in our list?
-          if(!boardToCreate.members.find((wekanMember) => wekanMember.userId === wekanId)) {
+          const wekanMember = boardToCreate.members.find((wekanMember) => wekanMember.userId === wekanId);
+          if(wekanMember) {
+            // we're already mapped, but maybe with lower rights
+            if(!wekanMember.isAdmin) {
+              wekanMember.isAdmin = this.getAdmin(trelloMembership.memberType);
+            }
+          } else {
             boardToCreate.members.push({
             boardToCreate.members.push({
               userId: wekanId,
               userId: wekanId,
-              isAdmin: false,
+              isAdmin: this.getAdmin(trelloMembership.memberType),
               isActive: true,
               isActive: true,
             });
             });
           }
           }
@@ -124,22 +172,21 @@ class TrelloCreator {
       this.labels[label.id] = labelToCreate._id;
       this.labels[label.id] = labelToCreate._id;
       boardToCreate.labels.push(labelToCreate);
       boardToCreate.labels.push(labelToCreate);
     });
     });
-    const now = new Date();
     const boardId = Boards.direct.insert(boardToCreate);
     const boardId = Boards.direct.insert(boardToCreate);
-    Boards.direct.update(boardId, {$set: {modifiedAt: now}});
+    Boards.direct.update(boardId, {$set: {modifiedAt: this._now()}});
     // log activity
     // log activity
     Activities.direct.insert({
     Activities.direct.insert({
       activityType: 'importBoard',
       activityType: 'importBoard',
       boardId,
       boardId,
-      createdAt: now,
+      createdAt: this._now(),
       source: {
       source: {
         id: trelloBoard.id,
         id: trelloBoard.id,
         system: 'Trello',
         system: 'Trello',
         url: trelloBoard.url,
         url: trelloBoard.url,
       },
       },
-      // We attribute the import to current user, not the one from the original
-      // object.
-      userId: Meteor.userId(),
+      // We attribute the import to current user,
+      // not the author from the original object.
+      userId: this._user(),
     });
     });
     return boardId;
     return boardId;
   }
   }
@@ -157,14 +204,15 @@ class TrelloCreator {
       const cardToCreate = {
       const cardToCreate = {
         archived: card.closed,
         archived: card.closed,
         boardId,
         boardId,
-        createdAt: new Date(this.createdAt.cards[card.id]  || Date.now()),
-        dateLastActivity: new Date(),
+        // very old boards won't have a creation activity so no creation date
+        createdAt: this._now(this.createdAt.cards[card.id]),
+        dateLastActivity: this._now(),
         description: card.desc,
         description: card.desc,
         listId: this.lists[card.idList],
         listId: this.lists[card.idList],
         sort: card.pos,
         sort: card.pos,
         title: card.name,
         title: card.name,
-        // XXX use the original user?
-        userId: Meteor.userId(),
+        // we attribute the card to its creator if available
+        userId: this._user(this.createdBy.cards[card.id]),
       };
       };
       // add labels
       // add labels
       if (card.idLabels) {
       if (card.idLabels) {
@@ -198,16 +246,16 @@ class TrelloCreator {
         activityType: 'importCard',
         activityType: 'importCard',
         boardId,
         boardId,
         cardId,
         cardId,
-        createdAt: new Date(),
+        createdAt: this._now(),
         listId: cardToCreate.listId,
         listId: cardToCreate.listId,
         source: {
         source: {
           id: card.id,
           id: card.id,
           system: 'Trello',
           system: 'Trello',
           url: card.url,
           url: card.url,
         },
         },
-        // we attribute the import to current user, not the one from the
-        // original card
-        userId: Meteor.userId(),
+        // we attribute the import to current user,
+        // not the author of the original card
+        userId: this._user(),
       });
       });
       // add comments
       // add comments
       const comments = this.comments[card.id];
       const comments = this.comments[card.id];
@@ -216,10 +264,10 @@ class TrelloCreator {
           const commentToCreate = {
           const commentToCreate = {
             boardId,
             boardId,
             cardId,
             cardId,
-            createdAt: comment.date,
+            createdAt: this._now(comment.date),
             text: comment.data.text,
             text: comment.data.text,
-            // XXX use the original comment user instead
-            userId: Meteor.userId(),
+            // we attribute the comment to the original author, default to current user
+            userId: this._user(comment.memberCreator.id),
           };
           };
           // dateLastActivity will be set from activity insert, no need to
           // dateLastActivity will be set from activity insert, no need to
           // update it ourselves
           // update it ourselves
@@ -229,7 +277,9 @@ class TrelloCreator {
             boardId: commentToCreate.boardId,
             boardId: commentToCreate.boardId,
             cardId: commentToCreate.cardId,
             cardId: commentToCreate.cardId,
             commentId,
             commentId,
-            createdAt: commentToCreate.createdAt,
+            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,
             userId: commentToCreate.userId,
           });
           });
         });
         });
@@ -292,31 +342,32 @@ class TrelloCreator {
         // creation date wasn't found on the action log. This happen on old
         // creation date wasn't found on the action log. This happen on old
         // Trello boards (eg from 2013) that didn't log the 'createList' action
         // Trello boards (eg from 2013) that didn't log the 'createList' action
         // we require.
         // we require.
-        createdAt: new Date(this.createdAt.lists[list.id] || Date.now()),
+        createdAt: this._now(this.createdAt.lists[list.id]),
         title: list.name,
         title: list.name,
-        userId: Meteor.userId(),
       };
       };
       const listId = Lists.direct.insert(listToCreate);
       const listId = Lists.direct.insert(listToCreate);
-      const now = new Date();
-      Lists.direct.update(listId, {$set: {'updatedAt': now}});
+      Lists.direct.update(listId, {$set: {'updatedAt': this._now()}});
       this.lists[list.id] = listId;
       this.lists[list.id] = listId;
       // log activity
       // log activity
       Activities.direct.insert({
       Activities.direct.insert({
         activityType: 'importList',
         activityType: 'importList',
         boardId,
         boardId,
-        createdAt: now,
+        createdAt: this._now(),
         listId,
         listId,
         source: {
         source: {
           id: list.id,
           id: list.id,
           system: 'Trello',
           system: 'Trello',
         },
         },
-        // We attribute the import to current user, not the one from the
-        // original object
-        userId: Meteor.userId(),
+        // We attribute the import to current user,
+        // not the creator of the original object
+        userId: this._user(),
       });
       });
     });
     });
   }
   }
 
 
+  getAdmin(trelloMemberType) {
+    return trelloMemberType === 'admin';
+  }
 
 
   getColor(trelloColorCode) {
   getColor(trelloColorCode) {
     // trello color name => wekan color
     // trello color name => wekan color
@@ -376,6 +427,7 @@ class TrelloCreator {
       case 'createCard':
       case 'createCard':
         const cardId = action.data.card.id;
         const cardId = action.data.card.id;
         this.createdAt.cards[cardId] = action.date;
         this.createdAt.cards[cardId] = action.date;
+        this.createdBy.cards[cardId] = action.idMemberCreator;
         break;
         break;
       case 'createList':
       case 'createList':
         const listId = action.data.list.id;
         const listId = action.data.list.id;