Jelajahi Sumber

Export/Import done for rules

Angelo Gallarello 6 tahun lalu
induk
melakukan
8cb132f492
2 mengubah file dengan 351 tambahan dan 192 penghapusan
  1. 63 17
      models/export.js
  2. 288 175
      models/wekanCreator.js

+ 63 - 17
models/export.js

@@ -14,7 +14,7 @@ if (Meteor.isServer) {
    * See https://blog.kayla.com.au/server-side-route-authentication-in-meteor/
    * for detailed explanations
    */
-  JsonRoutes.add('get', '/api/boards/:boardId/export', function (req, res) {
+  JsonRoutes.add('get', '/api/boards/:boardId/export', function(req, res) {
     const boardId = req.params.boardId;
     let user = null;
     // todo XXX for real API, first look for token in Authentication: header
@@ -28,8 +28,11 @@ if (Meteor.isServer) {
     }
 
     const exporter = new Exporter(boardId);
-    if(exporter.canExport(user)) {
-      JsonRoutes.sendResult(res, { code: 200, data: exporter.build() });
+    if (exporter.canExport(user)) {
+      JsonRoutes.sendResult(res, {
+        code: 200,
+        data: exporter.build()
+      });
     } else {
       // we could send an explicit error message, but on the other hand the only
       // way to get there is by hacking the UI so let's keep it raw.
@@ -44,25 +47,52 @@ class Exporter {
   }
 
   build() {
-    const byBoard = { boardId: this._boardId };
+    const byBoard = {
+      boardId: this._boardId
+    };
     // we do not want to retrieve boardId in related elements
-    const noBoardId = { fields: { boardId: 0 } };
+    const noBoardId = {
+      fields: {
+        boardId: 0
+      }
+    };
     const result = {
       _format: 'wekan-board-1.0.0',
     };
-    _.extend(result, Boards.findOne(this._boardId, { fields: { stars: 0 } }));
+    _.extend(result, Boards.findOne(this._boardId, {
+      fields: {
+        stars: 0
+      }
+    }));
     result.lists = Lists.find(byBoard, noBoardId).fetch();
     result.cards = Cards.find(byBoard, noBoardId).fetch();
     result.swimlanes = Swimlanes.find(byBoard, noBoardId).fetch();
     result.comments = CardComments.find(byBoard, noBoardId).fetch();
     result.activities = Activities.find(byBoard, noBoardId).fetch();
+    result.rules = Rules.find(byBoard, noBoardId).fetch();
     result.checklists = [];
     result.checklistItems = [];
     result.subtaskItems = [];
+    result.triggers = [];
+    result.actions = [];
     result.cards.forEach((card) => {
-      result.checklists.push(...Checklists.find({ cardId: card._id }).fetch());
-      result.checklistItems.push(...ChecklistItems.find({ cardId: card._id }).fetch());
-      result.subtaskItems.push(...Cards.find({ parentid: card._id }).fetch());
+      result.checklists.push(...Checklists.find({
+        cardId: card._id
+      }).fetch());
+      result.checklistItems.push(...ChecklistItems.find({
+        cardId: card._id
+      }).fetch());
+      result.subtaskItems.push(...Cards.find({
+        parentid: card._id
+      }).fetch());
+    });
+    result.rules.forEach((rule) => {
+      result.triggers.push(...Triggers.find({
+        _id: rule.triggerId
+      }, noBoardId).fetch());
+      result.actions.push(...Actions.find({
+        _id: rule.actionId
+      }, noBoardId).fetch());
     });
 
     // [Old] for attachments we only export IDs and absolute url to original doc
@@ -99,18 +129,34 @@ class Exporter {
     // 1- only exports users that are linked somehow to that board
     // 2- do not export any sensitive information
     const users = {};
-    result.members.forEach((member) => { users[member.userId] = true; });
-    result.lists.forEach((list) => { users[list.userId] = true; });
+    result.members.forEach((member) => {
+      users[member.userId] = true;
+    });
+    result.lists.forEach((list) => {
+      users[list.userId] = true;
+    });
     result.cards.forEach((card) => {
       users[card.userId] = true;
       if (card.members) {
-        card.members.forEach((memberId) => { users[memberId] = true; });
+        card.members.forEach((memberId) => {
+          users[memberId] = true;
+        });
       }
     });
-    result.comments.forEach((comment) => { users[comment.userId] = true; });
-    result.activities.forEach((activity) => { users[activity.userId] = true; });
-    result.checklists.forEach((checklist) => { users[checklist.userId] = true; });
-    const byUserIds = { _id: { $in: Object.getOwnPropertyNames(users) } };
+    result.comments.forEach((comment) => {
+      users[comment.userId] = true;
+    });
+    result.activities.forEach((activity) => {
+      users[activity.userId] = true;
+    });
+    result.checklists.forEach((checklist) => {
+      users[checklist.userId] = true;
+    });
+    const byUserIds = {
+      _id: {
+        $in: Object.getOwnPropertyNames(users)
+      }
+    };
     // we use whitelist to be sure we do not expose inadvertently
     // some secret fields that gets added to User later.
     const userFields = {
@@ -136,4 +182,4 @@ class Exporter {
     const board = Boards.findOne(this._boardId);
     return board && board.isVisibleBy(user);
   }
-}
+}

+ 288 - 175
models/wekanCreator.js

@@ -1,4 +1,4 @@
-const DateString = Match.Where(function (dateAsString) {
+const DateString = Match.Where(function(dateAsString) {
   check(dateAsString, String);
   return moment(dateAsString, moment.ISO_8601).isValid();
 });
@@ -42,6 +42,10 @@ export class WekanCreator {
     this.comments = {};
     // the members, indexed by Wekan member id => Wekan user ID
     this.members = data.membersMapping ? data.membersMapping : {};
+    // Map of triggers Wekan ID => Wekan ID
+    this.triggers = {};
+    // Map of actions Wekan ID => Wekan ID
+    this.actions = {};
 
     // maps a wekanCardId to an array of wekanAttachments
     this.attachments = {};
@@ -57,10 +61,10 @@ export class WekanCreator {
    * @param {String} dateString a properly formatted Date
    */
   _now(dateString) {
-    if(dateString) {
+    if (dateString) {
       return new Date(dateString);
     }
-    if(!this._nowDate) {
+    if (!this._nowDate) {
       this._nowDate = new Date();
     }
     return this._nowDate;
@@ -72,9 +76,9 @@ export class WekanCreator {
    * Otherwise return current logged user.
    * @param wekanUserId
    * @private
-     */
+   */
   _user(wekanUserId) {
-    if(wekanUserId && this.members[wekanUserId]) {
+    if (wekanUserId && this.members[wekanUserId]) {
       return this.members[wekanUserId];
     }
     return Meteor.userId();
@@ -96,7 +100,7 @@ export class WekanCreator {
       // allowed values (is it worth the maintenance?)
       color: String,
       permission: Match.Where((value) => {
-        return ['private', 'public'].indexOf(value)>= 0;
+        return ['private', 'public'].indexOf(value) >= 0;
       }),
     }));
   }
@@ -147,6 +151,30 @@ export class WekanCreator {
     })]);
   }
 
+  checkRules(wekanRules) {
+    check(wekanRules, [Match.ObjectIncluding({
+      triggerId: String,
+      actionId: String,
+      title: String,
+    })]);
+  }
+
+  checkTriggers(wekanTriggers) {
+    // XXX More check based on trigger type
+    check(wekanTriggers, [Match.ObjectIncluding({
+      activityType: String,
+      desc: String,
+    })]);
+  }
+
+  checkActions(wekanActions) {
+    // XXX More check based on action type
+    check(wekanActions, [Match.ObjectIncluding({
+      actionType: String,
+      desc: String,
+    })]);
+  }
+
   // You must call parseActions before calling this one.
   createBoardAndLabels(boardToImport) {
     const boardToCreate = {
@@ -171,12 +199,12 @@ export class WekanCreator {
       title: boardToImport.title,
     };
     // now add other members
-    if(boardToImport.members) {
+    if (boardToImport.members) {
       boardToImport.members.forEach((wekanMember) => {
         // do we already have it in our list?
-        if(!boardToCreate.members.some((member) => member.wekanId === wekanMember.wekanId))
+        if (!boardToCreate.members.some((member) => member.wekanId === wekanMember.wekanId))
           boardToCreate.members.push({
-            ... wekanMember,
+            ...wekanMember,
             userId: wekanMember.wekanId,
           });
       });
@@ -193,7 +221,11 @@ export class WekanCreator {
       boardToCreate.labels.push(labelToCreate);
     });
     const boardId = Boards.direct.insert(boardToCreate);
-    Boards.direct.update(boardId, {$set: {modifiedAt: this._now()}});
+    Boards.direct.update(boardId, {
+      $set: {
+        modifiedAt: this._now()
+      }
+    });
     // log activity
     Activities.direct.insert({
       activityType: 'importBoard',
@@ -245,21 +277,21 @@ export class WekanCreator {
         });
       }
       // add members {
-      if(card.members) {
+      if (card.members) {
         const wekanMembers = [];
         // we can't just map, as some members may not have been mapped
         card.members.forEach((sourceMemberId) => {
-          if(this.members[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(!wekanMembers.find((wId) => wId === wekanId)){
+            if (!wekanMembers.find((wId) => wId === wekanId)) {
               wekanMembers.push(wekanId);
             }
           }
           return true;
         });
-        if(wekanMembers.length>0) {
+        if (wekanMembers.length > 0) {
           cardToCreate.members = wekanMembers;
         }
       }
@@ -320,9 +352,9 @@ export class WekanCreator {
           // - the template then tries to display the url to the attachment which causes other errors
           // so we make it server only, and let UI catch up once it is done, forget about latency comp.
           const self = this;
-          if(Meteor.isServer) {
+          if (Meteor.isServer) {
             if (att.url) {
-              file.attachData(att.url, function (error) {
+              file.attachData(att.url, function(error) {
                 file.boardId = boardId;
                 file.cardId = cardId;
                 file.userId = self._user(att.userId);
@@ -330,20 +362,26 @@ export class WekanCreator {
                 // attachments' related activities automatically
                 file.source = 'import';
                 if (error) {
-                  throw(error);
+                  throw (error);
                 } else {
                   const wekanAtt = Attachments.insert(file, () => {
                     // we do nothing
                   });
                   self.attachmentIds[att._id] = wekanAtt._id;
                   //
-                  if(wekanCoverId === att._id) {
-                    Cards.direct.update(cardId, { $set: {coverId: wekanAtt._id}});
+                  if (wekanCoverId === att._id) {
+                    Cards.direct.update(cardId, {
+                      $set: {
+                        coverId: wekanAtt._id
+                      }
+                    });
                   }
                 }
               });
             } else if (att.file) {
-              file.attachData(new Buffer(att.file, 'base64'), {type: att.type}, (error) => {
+              file.attachData(new Buffer(att.file, 'base64'), {
+                type: att.type
+              }, (error) => {
                 file.name(att.name);
                 file.boardId = boardId;
                 file.cardId = cardId;
@@ -352,15 +390,19 @@ export class WekanCreator {
                 // attachments' related activities automatically
                 file.source = 'import';
                 if (error) {
-                  throw(error);
+                  throw (error);
                 } else {
                   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}});
+                  if (wekanCoverId === att._id) {
+                    Cards.direct.update(cardId, {
+                      $set: {
+                        coverId: wekanAtt._id
+                      }
+                    });
                   }
                 }
               });
@@ -403,7 +445,11 @@ export class WekanCreator {
         sort: list.sort ? list.sort : listIndex,
       };
       const listId = Lists.direct.insert(listToCreate);
-      Lists.direct.update(listId, {$set: {'updatedAt': this._now()}});
+      Lists.direct.update(listId, {
+        $set: {
+          'updatedAt': this._now()
+        }
+      });
       this.lists[list._id] = listId;
       // // log activity
       // Activities.direct.insert({
@@ -436,7 +482,11 @@ export class WekanCreator {
         sort: swimlane.sort ? swimlane.sort : swimlaneIndex,
       };
       const swimlaneId = Swimlanes.direct.insert(swimlaneToCreate);
-      Swimlanes.direct.update(swimlaneId, {$set: {'updatedAt': this._now()}});
+      Swimlanes.direct.update(swimlaneId, {
+        $set: {
+          'updatedAt': this._now()
+        }
+      });
       this.swimlanes[swimlane._id] = swimlaneId;
     });
   }
@@ -458,6 +508,47 @@ export class WekanCreator {
     return result;
   }
 
+  createTriggers(wekanTriggers, boardId) {
+    wekanTriggers.forEach((trigger, ruleIndex) => {
+      if (trigger.hasOwnProperty('labelId')) {
+        trigger['labelId'] = this.labels[trigger['labelId']]
+      }
+      if (trigger.hasOwnProperty('memberId')) {
+        trigger['memberId'] = this.members[trigger['memberId']]
+      }
+      trigger['boardId'] = boardId;
+      const oldId = trigger['_id'];
+      delete trigger._id;
+      this.triggers[oldId] = Triggers.direct.insert(trigger);
+    });
+  }
+
+  createActions(wekanActions, boardId) {
+    wekanActions.forEach((action, ruleIndex) => {
+      if (action.hasOwnProperty('labelId')) {
+        action['labelId'] = this.labels[action['labelId']]
+      }
+      if (action.hasOwnProperty('memberId')) {
+        action['memberId'] = this.members[action['memberId']]
+      }
+      action['boardId'] = boardId;
+      const oldId = action['_id'];
+      delete action._id;
+      this.actions[oldId] = Actions.direct.insert(action);
+    });
+  }
+
+  createRules(wekanRules, boardId) {
+    wekanRules.forEach((rule, ruleIndex) => {
+      // Create the rule
+      rule['boardId'] = boardId;
+      rule['triggerId'] = this.triggers[rule['triggerId']];
+      rule['actionId'] = this.actions[rule['actionId']];
+      delete rule._id;
+      Rules.direct.insert(rule);
+    });
+  }
+
   createChecklistItems(wekanChecklistItems) {
     wekanChecklistItems.forEach((checklistitem, checklistitemIndex) => {
       // Create the checklistItem
@@ -476,166 +567,182 @@ export class WekanCreator {
   parseActivities(wekanBoard) {
     wekanBoard.activities.forEach((activity) => {
       switch (activity.activityType) {
-      case 'addAttachment': {
-        // We have to be cautious, because the attachment could have been removed later.
-        // In that case Wekan still reports its addition, but removes its 'url' field.
-        // So we test for that
-        const wekanAttachment = wekanBoard.attachments.filter((attachment) => {
-          return attachment._id === activity.attachmentId;
-        })[0];
+        case 'addAttachment':
+          {
+            // We have to be cautious, because the attachment could have been removed later.
+            // In that case Wekan still reports its addition, but removes its 'url' field.
+            // So we test for that
+            const wekanAttachment = wekanBoard.attachments.filter((attachment) => {
+              return attachment._id === activity.attachmentId;
+            })[0];
 
-        if ( typeof wekanAttachment !== 'undefined' && wekanAttachment ) {
-          if(wekanAttachment.url || wekanAttachment.file) {
-          // we cannot actually create the Wekan attachment, because we don't yet
-          // have the cards to attach it to, so we store it in the instance variable.
-            const wekanCardId = activity.cardId;
-            if(!this.attachments[wekanCardId]) {
-              this.attachments[wekanCardId] = [];
+            if (typeof wekanAttachment !== 'undefined' && wekanAttachment) {
+              if (wekanAttachment.url || wekanAttachment.file) {
+                // we cannot actually create the Wekan attachment, because we don't yet
+                // have the cards to attach it to, so we store it in the instance variable.
+                const wekanCardId = activity.cardId;
+                if (!this.attachments[wekanCardId]) {
+                  this.attachments[wekanCardId] = [];
+                }
+                this.attachments[wekanCardId].push(wekanAttachment);
+              }
             }
-            this.attachments[wekanCardId].push(wekanAttachment);
+            break;
+          }
+        case 'addComment':
+          {
+            const wekanComment = wekanBoard.comments.filter((comment) => {
+              return comment._id === activity.commentId;
+            })[0];
+            const id = activity.cardId;
+            if (!this.comments[id]) {
+              this.comments[id] = [];
+            }
+            this.comments[id].push(wekanComment);
+            break;
+          }
+        case 'createBoard':
+          {
+            this.createdAt.board = activity.createdAt;
+            break;
+          }
+        case 'createCard':
+          {
+            const cardId = activity.cardId;
+            this.createdAt.cards[cardId] = activity.createdAt;
+            this.createdBy.cards[cardId] = activity.userId;
+            break;
+          }
+        case 'createList':
+          {
+            const listId = activity.listId;
+            this.createdAt.lists[listId] = activity.createdAt;
+            break;
+          }
+        case 'createSwimlane':
+          {
+            const swimlaneId = activity.swimlaneId;
+            this.createdAt.swimlanes[swimlaneId] = activity.createdAt;
+            break;
           }
-        }
-        break;
-      }
-      case 'addComment': {
-        const wekanComment = wekanBoard.comments.filter((comment) => {
-          return comment._id === activity.commentId;
-        })[0];
-        const id = activity.cardId;
-        if (!this.comments[id]) {
-          this.comments[id] = [];
-        }
-        this.comments[id].push(wekanComment);
-        break;
-      }
-      case 'createBoard': {
-        this.createdAt.board = activity.createdAt;
-        break;
-      }
-      case 'createCard': {
-        const cardId = activity.cardId;
-        this.createdAt.cards[cardId] = activity.createdAt;
-        this.createdBy.cards[cardId] = activity.userId;
-        break;
-      }
-      case 'createList': {
-        const listId = activity.listId;
-        this.createdAt.lists[listId] = activity.createdAt;
-        break;
       }
-      case 'createSwimlane': {
-        const swimlaneId = activity.swimlaneId;
-        this.createdAt.swimlanes[swimlaneId] = activity.createdAt;
-        break;
-      }}
     });
   }
 
   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
-      case 'addAttachment': {
-        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;
+        // 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
+        case 'addAttachment':
+          {
+            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;
+          }
       }
-      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;
-      }}
     });
   }
 
@@ -651,6 +758,9 @@ export class WekanCreator {
       this.checkSwimlanes(board.swimlanes);
       this.checkCards(board.cards);
       this.checkChecklists(board.checklists);
+      this.checkRules(board.rules);
+      this.checkActions(board.actions);
+      this.checkTriggers(board.triggers);
       this.checkChecklistItems(board.checklistItems);
     } catch (e) {
       throw new Meteor.Error('error-json-schema');
@@ -673,7 +783,10 @@ export class WekanCreator {
     this.createChecklists(board.checklists);
     this.createChecklistItems(board.checklistItems);
     this.importActivities(board.activities, boardId);
+    this.createTriggers(board.triggers, boardId);
+    this.createActions(board.actions, boardId);
+    this.createRules(board.rules, boardId);
     // XXX add members
     return boardId;
   }
-}
+}