summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLauri Ojansivu <x@xet7.org>2017-08-30 00:59:29 +0300
committerLauri Ojansivu <x@xet7.org>2017-08-30 00:59:29 +0300
commit51206cb108b92eec80e35610ef88551fe8a43feb (patch)
tree3b30e330c3e4b62551f18463be9204990ece480c
parentecb4863c39279c8a93684369c20674aa255bbd8e (diff)
parent200d49d369275b190943a24ad3834b07f3a2a06e (diff)
downloadwekan-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.md12
-rw-r--r--i18n/de.i18n.json2
-rw-r--r--i18n/fr.i18n.json2
-rw-r--r--models/trelloCreator.js161
-rw-r--r--models/wekanCreator.js206
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;
}