diff options
Diffstat (limited to 'models/wekanCreator.js')
-rw-r--r-- | models/wekanCreator.js | 277 |
1 files changed, 214 insertions, 63 deletions
diff --git a/models/wekanCreator.js b/models/wekanCreator.js index 4551979b..0f6a9d17 100644 --- a/models/wekanCreator.js +++ b/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(); }); @@ -40,8 +40,14 @@ export class WekanCreator { this.checklistItems = {}; // The comments, indexed by Wekan card id (to map when importing cards) this.comments = {}; + // Map of rules Wekan ID => Wekan ID + this.rules = {}; // 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 +63,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 +78,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 +102,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 +153,55 @@ 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, + })]); + } + + getMembersToMap(data) { + // we will work on the list itself (an ordered array of objects) when a + // mapping is done, we add a 'wekan' field to the object representing the + // imported member + const membersToMap = data.members; + const users = data.users; + // auto-map based on username + membersToMap.forEach((importedMember) => { + importedMember.id = importedMember.userId; + delete importedMember.userId; + const user = users.filter((user) => { + return user._id === importedMember.id; + })[0]; + if (user.profile && user.profile.fullname) { + importedMember.fullName = user.profile.fullname; + } + importedMember.username = user.username; + const wekanUser = Users.findOne({ username: importedMember.username }); + if (wekanUser) { + importedMember.wekanId = wekanUser._id; + } + }); + return membersToMap; + } + + 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 = { @@ -160,6 +215,7 @@ export class WekanCreator { wekanId: Meteor.userId(), isActive: true, isAdmin: true, + isNoComments: false, isCommentOnly: false, swimlaneId: false, }], @@ -171,12 +227,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 +249,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,27 +305,31 @@ 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; } } + // set color + if (card.color) { + cardToCreate.color = card.color; + } // insert card const cardId = Cards.direct.insert(cardToCreate); - // keep track of Wekan id => WeKan id + // keep track of Wekan id => Wekan id this.cards[card._id] = cardId; // // log activity // Activities.direct.insert({ @@ -320,9 +384,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 +394,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 +422,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 +477,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({ @@ -435,8 +513,16 @@ export class WekanCreator { title: swimlane.title, sort: swimlane.sort ? swimlane.sort : swimlaneIndex, }; + // set color + if (swimlane.color) { + swimlaneToCreate.color = swimlane.color; + } 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 +544,47 @@ export class WekanCreator { return result; } + createTriggers(wekanTriggers, boardId) { + wekanTriggers.forEach((trigger) => { + 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) => { + 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) => { + // 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,7 +603,8 @@ export class WekanCreator { parseActivities(wekanBoard) { wekanBoard.activities.forEach((activity) => { switch (activity.activityType) { - case 'addAttachment': { + 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 @@ -484,12 +612,12 @@ export class WekanCreator { 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. + 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]) { + if (!this.attachments[wekanCardId]) { this.attachments[wekanCardId] = []; } this.attachments[wekanCardId].push(wekanAttachment); @@ -497,7 +625,8 @@ export class WekanCreator { } break; } - case 'addComment': { + case 'addComment': + { const wekanComment = wekanBoard.comments.filter((comment) => { return comment._id === activity.commentId; })[0]; @@ -508,26 +637,31 @@ export class WekanCreator { this.comments[id].push(wekanComment); break; } - case 'createBoard': { + case 'createBoard': + { this.createdAt.board = activity.createdAt; break; } - case 'createCard': { + case 'createCard': + { const cardId = activity.cardId; this.createdAt.cards[cardId] = activity.createdAt; this.createdBy.cards[cardId] = activity.userId; break; } - case 'createList': { + case 'createList': + { const listId = activity.listId; this.createdAt.lists[listId] = activity.createdAt; break; } - case 'createSwimlane': { + case 'createSwimlane': + { const swimlaneId = activity.swimlaneId; this.createdAt.swimlanes[swimlaneId] = activity.createdAt; break; - }} + } + } }); } @@ -536,7 +670,8 @@ export class WekanCreator { switch (activity.activityType) { // Board related activities // TODO: addBoardMember, removeBoardMember - case 'createBoard': { + case 'createBoard': + { Activities.direct.insert({ userId: this._user(activity.userId), type: 'board', @@ -549,7 +684,8 @@ export class WekanCreator { } // List related activities // TODO: removeList, archivedList - case 'createList': { + case 'createList': + { Activities.direct.insert({ userId: this._user(activity.userId), type: 'list', @@ -562,7 +698,8 @@ export class WekanCreator { } // Card related activities // TODO: archivedCard, restoredCard, joinMember, unjoinMember - case 'createCard': { + case 'createCard': + { Activities.direct.insert({ userId: this._user(activity.userId), activityType: activity.activityType, @@ -573,7 +710,8 @@ export class WekanCreator { }); break; } - case 'moveCard': { + case 'moveCard': + { Activities.direct.insert({ userId: this._user(activity.userId), oldListId: this.lists[activity.oldListId], @@ -586,7 +724,8 @@ export class WekanCreator { break; } // Comment related activities - case 'addComment': { + case 'addComment': + { Activities.direct.insert({ userId: this._user(activity.userId), activityType: activity.activityType, @@ -598,7 +737,8 @@ export class WekanCreator { break; } // Attachment related activities - case 'addAttachment': { + case 'addAttachment': + { Activities.direct.insert({ userId: this._user(activity.userId), type: 'card', @@ -611,7 +751,8 @@ export class WekanCreator { break; } // Checklist related activities - case 'addChecklist': { + case 'addChecklist': + { Activities.direct.insert({ userId: this._user(activity.userId), activityType: activity.activityType, @@ -622,7 +763,8 @@ export class WekanCreator { }); break; } - case 'addChecklistItem': { + case 'addChecklistItem': + { Activities.direct.insert({ userId: this._user(activity.userId), activityType: activity.activityType, @@ -635,26 +777,32 @@ export class WekanCreator { createdAt: this._now(activity.createdAt), }); break; - }} + } + } }); } - check(board) { - try { - // check(data, { - // membersMapping: Match.Optional(Object), - // }); - this.checkActivities(board.activities); - this.checkBoard(board); - this.checkLabels(board.labels); - this.checkLists(board.lists); - this.checkSwimlanes(board.swimlanes); - this.checkCards(board.cards); - this.checkChecklists(board.checklists); - this.checkChecklistItems(board.checklistItems); - } catch (e) { - throw new Meteor.Error('error-json-schema'); - } + //check(board) { + check() { + //try { + // check(data, { + // membersMapping: Match.Optional(Object), + // }); + + // this.checkActivities(board.activities); + // this.checkBoard(board); + // this.checkLabels(board.labels); + // this.checkLists(board.lists); + // 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'); + // } } create(board, currentBoardId) { @@ -673,6 +821,9 @@ 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; } |