Prettier & eslint project style update

This commit is contained in:
Justin Reynolds 2019-06-28 12:52:09 -05:00
parent a0a482aa8e
commit 3eb4d2c341
116 changed files with 6216 additions and 5240 deletions

View file

@ -37,7 +37,7 @@ AccountSettings.attachSchema(
}
},
},
})
}),
);
AccountSettings.allow({
@ -47,11 +47,6 @@ AccountSettings.allow({
},
});
AccountSettings.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
if (Meteor.isServer) {
Meteor.startup(() => {
AccountSettings._collection._ensureIndex({ modifiedAt: -1 });
@ -62,7 +57,7 @@ if (Meteor.isServer) {
booleanValue: false,
sort: 0,
},
}
},
);
AccountSettings.upsert(
{ _id: 'accounts-allowUserNameChange' },
@ -71,7 +66,7 @@ if (Meteor.isServer) {
booleanValue: false,
sort: 1,
},
}
},
);
});
}

View file

@ -20,11 +20,6 @@ Actions.helpers({
},
});
Actions.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
if (Meteor.isServer) {
Meteor.startup(() => {
Actions._collection._ensureIndex({ modifiedAt: -1 });

View file

@ -71,11 +71,6 @@ Activities.after.insert((userId, doc) => {
RulesHelper.executeRules(activity);
});
Activities.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
if (Meteor.isServer) {
// For efficiency create indexes on the date of creation, and on the date of
// creation in conjunction with the card or board id, as corresponding views
@ -87,15 +82,15 @@ if (Meteor.isServer) {
Activities._collection._ensureIndex({ boardId: 1, createdAt: -1 });
Activities._collection._ensureIndex(
{ commentId: 1 },
{ partialFilterExpression: { commentId: { $exists: true } } }
{ partialFilterExpression: { commentId: { $exists: true } } },
);
Activities._collection._ensureIndex(
{ attachmentId: 1 },
{ partialFilterExpression: { attachmentId: { $exists: true } } }
{ partialFilterExpression: { attachmentId: { $exists: true } } },
);
Activities._collection._ensureIndex(
{ customFieldId: 1 },
{ partialFilterExpression: { customFieldId: { $exists: true } } }
{ partialFilterExpression: { customFieldId: { $exists: true } } },
);
// Label activity did not work yet, unable to edit labels when tried this.
//Activities._collection._dropIndex({ labelId: 1 }, { "indexKey": -1 });
@ -205,20 +200,20 @@ if (Meteor.isServer) {
if (board) {
const watchingUsers = _.pluck(
_.where(board.watchers, { level: 'watching' }),
'userId'
'userId',
);
const trackingUsers = _.pluck(
_.where(board.watchers, { level: 'tracking' }),
'userId'
'userId',
);
watchers = _.union(
watchers,
watchingUsers,
_.intersection(participants, trackingUsers)
_.intersection(participants, trackingUsers),
);
}
Notifications.getUsers(watchers).forEach((user) => {
Notifications.getUsers(watchers).forEach(user => {
Notifications.notify(user, title, description, params);
});

View file

@ -42,7 +42,7 @@ Announcements.attachSchema(
}
},
},
})
}),
);
Announcements.allow({
@ -52,11 +52,6 @@ Announcements.allow({
},
});
Announcements.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
if (Meteor.isServer) {
Meteor.startup(() => {
Announcements._collection._ensureIndex({ modifiedAt: -1 });

View file

@ -12,7 +12,7 @@ Attachments = new FS.Collection('attachments', {
// XXX Should we use `beforeWrite` option of CollectionFS instead of
// collection-hooks?
// We should use `beforeWrite`.
beforeWrite: (fileObj) => {
beforeWrite: fileObj => {
if (!fileObj.isImage()) {
return {
type: 'application/octet-stream',
@ -84,7 +84,7 @@ if (Meteor.isServer) {
$unset: {
source: '',
},
}
},
);
}
});

View file

@ -101,7 +101,7 @@ Boards.attachSchema(
const colors = Boards.simpleSchema()._schema['labels.$.color']
.allowedValues;
const defaultLabelsColors = _.clone(colors).splice(0, 6);
return defaultLabelsColors.map((color) => ({
return defaultLabelsColors.map(color => ({
color,
_id: Random.id(6),
name: '',
@ -342,7 +342,7 @@ Boards.attachSchema(
type: String,
defaultValue: 'board',
},
})
}),
);
Boards.helpers({
@ -355,7 +355,7 @@ Boards.helpers({
Swimlanes.find({
boardId: oldId,
archived: false,
}).forEach((swimlane) => {
}).forEach(swimlane => {
swimlane.type = 'swimlane';
swimlane.copy(_id);
});
@ -382,7 +382,7 @@ Boards.helpers({
isActiveMember(userId) {
if (userId) {
return this.members.find(
(member) => member.userId === userId && member.isActive
member => member.userId === userId && member.isActive,
);
} else {
return false;
@ -396,14 +396,14 @@ Boards.helpers({
cards() {
return Cards.find(
{ boardId: this._id, archived: false },
{ sort: { title: 1 } }
{ sort: { title: 1 } },
);
},
lists() {
return Lists.find(
{ boardId: this._id, archived: false },
{ sort: { sort: 1 } }
{ sort: { sort: 1 } },
);
},
@ -418,7 +418,7 @@ Boards.helpers({
swimlanes() {
return Swimlanes.find(
{ boardId: this._id, archived: false },
{ sort: { sort: 1 } }
{ sort: { sort: 1 } },
);
},
@ -432,7 +432,7 @@ Boards.helpers({
},
{
sort: { sort: 1 },
}
},
);
},
@ -535,7 +535,7 @@ Boards.helpers({
customFields() {
return CustomFields.find(
{ boardIds: { $in: [this._id] } },
{ sort: { name: 1 } }
{ sort: { name: 1 } },
);
},
@ -848,7 +848,7 @@ Boards.mutations({
isAdmin,
isNoComments,
isCommentOnly,
currentUserId = Meteor.userId()
currentUserId = Meteor.userId(),
) {
const memberIndex = this.memberIndex(memberId);
// do not allow change permission of self
@ -884,9 +884,9 @@ Boards.mutations({
function boardRemover(userId, doc) {
[Cards, Lists, Swimlanes, Integrations, Rules, Activities].forEach(
(element) => {
element => {
element.remove({ boardId: doc._id });
}
},
);
}
@ -927,7 +927,7 @@ if (Meteor.isServer) {
_.findWhere(doc.members, {
userId: removedMemberId,
isAdmin: true,
})
}),
);
},
fetch: ['members'],
@ -973,7 +973,7 @@ if (Meteor.isServer) {
_id: 1,
'members.userId': 1,
},
{ unique: true }
{ unique: true },
);
Boards._collection._ensureIndex({ 'members.userId': 1 });
});
@ -1009,12 +1009,12 @@ if (Meteor.isServer) {
labelIds: removedLabelId,
},
},
{ multi: true }
{ multi: true },
);
});
const foreachRemovedMember = (doc, modifier, callback) => {
Object.keys(modifier).forEach((set) => {
Object.keys(modifier).forEach(set => {
if (modifier[set] !== false) {
return;
}
@ -1030,11 +1030,6 @@ if (Meteor.isServer) {
});
};
Boards.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
// Remove a member from all objects of the board before leaving the board
Boards.before.update((userId, doc, fieldNames, modifier) => {
if (!_.contains(fieldNames, 'members')) {
@ -1043,7 +1038,7 @@ if (Meteor.isServer) {
if (modifier.$set) {
const boardId = doc._id;
foreachRemovedMember(doc, modifier.$set, (memberId) => {
foreachRemovedMember(doc, modifier.$set, memberId => {
Cards.update(
{ boardId },
{
@ -1052,7 +1047,7 @@ if (Meteor.isServer) {
watchers: memberId,
},
},
{ multi: true }
{ multi: true },
);
Lists.update(
@ -1062,7 +1057,7 @@ if (Meteor.isServer) {
watchers: memberId,
},
},
{ multi: true }
{ multi: true },
);
const board = Boards._transform(doc);
@ -1112,7 +1107,7 @@ if (Meteor.isServer) {
// Say goodbye to the former member
if (modifier.$set) {
foreachRemovedMember(doc, modifier.$set, (memberId) => {
foreachRemovedMember(doc, modifier.$set, memberId => {
Activities.insert({
userId,
memberId,
@ -1143,7 +1138,7 @@ if (Meteor.isServer) {
// admins can access boards of any user
Authentication.checkAdminOrCondition(
req.userId,
req.userId === paramUserId
req.userId === paramUserId,
);
const data = Boards.find(
@ -1153,7 +1148,7 @@ if (Meteor.isServer) {
},
{
sort: ['title'],
}
},
).map(function(board) {
return {
_id: board._id,
@ -1332,7 +1327,7 @@ if (Meteor.isServer) {
if (!board.getLabel(name, color)) {
Boards.direct.update(
{ _id: id },
{ $push: { labels: { _id: labelId, name, color } } }
{ $push: { labels: { _id: labelId, name, color } } },
);
JsonRoutes.sendResult(res, {
code: 200,
@ -1364,7 +1359,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('POST', '/api/boards/:boardId/members/:memberId', function(
req,
res
res,
) {
try {
const boardId = req.params.boardId;
@ -1384,7 +1379,7 @@ if (Meteor.isServer) {
isTrue(isAdmin),
isTrue(isNoComments),
isTrue(isCommentOnly),
req.userId
req.userId,
);
JsonRoutes.sendResult(res, {

View file

@ -64,7 +64,7 @@ CardComments.attachSchema(
}
},
},
})
}),
);
CardComments.allow({
@ -107,11 +107,6 @@ function commentCreation(userId, doc) {
});
}
CardComments.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
if (Meteor.isServer) {
// Comments are often fetched within a card, so we create an index to make these
// queries more efficient.
@ -125,7 +120,6 @@ if (Meteor.isServer) {
});
CardComments.after.update((userId, doc) => {
const activity = Activities.findOne({ commentId: doc._id });
const card = Cards.findOne(doc.cardId);
Activities.insert({
userId,
@ -139,7 +133,6 @@ if (Meteor.isServer) {
});
CardComments.before.remove((userId, doc) => {
const activity = Activities.findOne({ commentId: doc._id });
const card = Cards.findOne(doc.cardId);
Activities.insert({
userId,
@ -174,7 +167,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('GET', '/api/boards/:boardId/cards/:cardId/comments', function(
req,
res
res,
) {
try {
Authentication.checkUserId(req.userId);
@ -233,7 +226,7 @@ if (Meteor.isServer) {
data: error,
});
}
}
},
);
/**
@ -280,7 +273,7 @@ if (Meteor.isServer) {
data: error,
});
}
}
},
);
/**
@ -318,7 +311,7 @@ if (Meteor.isServer) {
data: error,
});
}
}
},
);
}

File diff suppressed because it is too large Load diff

View file

@ -61,7 +61,7 @@ ChecklistItems.attachSchema(
}
},
},
})
}),
);
ChecklistItems.allow({
@ -225,11 +225,6 @@ if (Meteor.isServer) {
publishChekListUncompleted(userId, doc, fieldNames);
});
ChecklistItems.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
ChecklistItems.after.insert((userId, doc) => {
itemCreation(userId, doc);
});
@ -281,7 +276,7 @@ if (Meteor.isServer) {
code: 500,
});
}
}
},
);
/**
@ -308,13 +303,13 @@ if (Meteor.isServer) {
if (req.body.hasOwnProperty('isFinished')) {
ChecklistItems.direct.update(
{ _id: paramItemId },
{ $set: { isFinished: req.body.isFinished } }
{ $set: { isFinished: req.body.isFinished } },
);
}
if (req.body.hasOwnProperty('title')) {
ChecklistItems.direct.update(
{ _id: paramItemId },
{ $set: { title: req.body.title } }
{ $set: { title: req.body.title } },
);
}
@ -324,7 +319,7 @@ if (Meteor.isServer) {
_id: paramItemId,
},
});
}
},
);
/**
@ -353,7 +348,7 @@ if (Meteor.isServer) {
_id: paramItemId,
},
});
}
},
);
}

View file

@ -59,7 +59,7 @@ Checklists.attachSchema(
type: Number,
decimal: true,
},
})
}),
);
Checklists.helpers({
@ -68,7 +68,7 @@ Checklists.helpers({
this._id = null;
this.cardId = newCardId;
const newChecklistId = Checklists.insert(this);
ChecklistItems.find({ checklistId: oldChecklistId }).forEach((item) => {
ChecklistItems.find({ checklistId: oldChecklistId }).forEach(item => {
item._id = null;
item.checklistId = newChecklistId;
item.cardId = newCardId;
@ -84,7 +84,7 @@ Checklists.helpers({
{
checklistId: this._id,
},
{ sort: ['sort'] }
{ sort: ['sort'] },
);
},
finishedCount() {
@ -160,16 +160,11 @@ if (Meteor.isServer) {
});
});
Checklists.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
Checklists.before.remove((userId, doc) => {
const activities = Activities.find({ checklistId: doc._id });
const card = Cards.findOne(doc.cardId);
if (activities) {
activities.forEach((activity) => {
activities.forEach(activity => {
Activities.remove(activity._id);
});
}
@ -203,7 +198,7 @@ if (Meteor.isServer) {
Authentication.checkUserId(req.userId);
const paramCardId = req.params.cardId;
const checklists = Checklists.find({ cardId: paramCardId }).map(function(
doc
doc,
) {
return {
_id: doc._id,
@ -220,7 +215,7 @@ if (Meteor.isServer) {
code: 500,
});
}
}
},
);
/**
@ -269,7 +264,7 @@ if (Meteor.isServer) {
code: 500,
});
}
}
},
);
/**
@ -313,7 +308,7 @@ if (Meteor.isServer) {
code: 400,
});
}
}
},
);
/**
@ -340,7 +335,7 @@ if (Meteor.isServer) {
_id: paramChecklistId,
},
});
}
},
);
}

View file

@ -95,7 +95,7 @@ CustomFields.attachSchema(
}
},
},
})
}),
);
CustomFields.mutations({
@ -118,7 +118,7 @@ CustomFields.allow({
userId,
Boards.find({
_id: { $in: doc.boardIds },
}).fetch()
}).fetch(),
);
},
update(userId, doc) {
@ -126,7 +126,7 @@ CustomFields.allow({
userId,
Boards.find({
_id: { $in: doc.boardIds },
}).fetch()
}).fetch(),
);
},
remove(userId, doc) {
@ -134,7 +134,7 @@ CustomFields.allow({
userId,
Boards.find({
_id: { $in: doc.boardIds },
}).fetch()
}).fetch(),
);
},
fetch: ['userId', 'boardIds'],
@ -152,7 +152,7 @@ function customFieldCreation(userId, doc) {
});
}
function customFieldDeletion(userId, doc){
function customFieldDeletion(userId, doc) {
Activities.insert({
userId,
activityType: 'deleteCustomField',
@ -163,7 +163,7 @@ function customFieldDeletion(userId, doc){
// This has some bug, it does not show edited customField value at Outgoing Webhook,
// instead it shows undefined, and no listId and swimlaneId.
function customFieldEdit(userId, doc){
function customFieldEdit(userId, doc) {
const card = Cards.findOne(doc.cardId);
Activities.insert({
userId,
@ -185,17 +185,12 @@ if (Meteor.isServer) {
customFieldCreation(userId, doc);
});
CustomFields.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
CustomFields.before.update((userId, doc, fieldNames, modifier) => {
if (_.contains(fieldNames, 'boardIds') && modifier.$pull) {
Cards.update(
{ boardId: modifier.$pull.boardIds, 'customFields._id': doc._id },
{ $pull: { customFields: { _id: doc._id } } },
{ multi: true }
{ multi: true },
);
customFieldEdit(userId, doc);
Activities.remove({
@ -223,7 +218,7 @@ if (Meteor.isServer) {
Cards.update(
{ boardId: { $in: doc.boardIds }, 'customFields._id': doc._id },
{ $pull: { customFields: { _id: doc._id } } },
{ multi: true }
{ multi: true },
);
});
}
@ -241,7 +236,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('GET', '/api/boards/:boardId/custom-fields', function(
req,
res
res,
) {
Authentication.checkUserId(req.userId);
const paramBoardId = req.params.boardId;
@ -254,7 +249,7 @@ if (Meteor.isServer) {
name: cf.name,
type: cf.type,
};
}
},
),
});
});
@ -281,7 +276,7 @@ if (Meteor.isServer) {
boardIds: { $in: [paramBoardId] },
}),
});
}
},
);
/**
@ -299,7 +294,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('POST', '/api/boards/:boardId/custom-fields', function(
req,
res
res,
) {
Authentication.checkUserId(req.userId);
const paramBoardId = req.params.boardId;
@ -351,7 +346,7 @@ if (Meteor.isServer) {
_id: id,
},
});
}
},
);
}

View file

@ -57,7 +57,10 @@ export class Exporter {
build() {
const byBoard = { boardId: this._boardId };
const byBoardNoLinked = { boardId: this._boardId, linkedId: {$in: ['', null] } };
const byBoardNoLinked = {
boardId: this._boardId,
linkedId: { $in: ['', null] },
};
// we do not want to retrieve boardId in related elements
const noBoardId = {
fields: {
@ -67,15 +70,21 @@ export class Exporter {
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(byBoardNoLinked, noBoardId).fetch();
result.swimlanes = Swimlanes.find(byBoard, noBoardId).fetch();
result.customFields = CustomFields.find({boardIds: {$in: [this.boardId]}}, {fields: {boardId: 0}}).fetch();
result.customFields = CustomFields.find(
{ boardIds: { $in: [this.boardId] } },
{ fields: { boardId: 0 } },
).fetch();
result.comments = CardComments.find(byBoard, noBoardId).fetch();
result.activities = Activities.find(byBoard, noBoardId).fetch();
result.rules = Rules.find(byBoard, noBoardId).fetch();
@ -84,24 +93,40 @@ export class Exporter {
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.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.rules.forEach((rule) => {
result.triggers.push(...Triggers.find({
_id: rule.triggerId,
}, noBoardId).fetch());
result.actions.push(...Actions.find({
_id: rule.actionId,
}, noBoardId).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
@ -122,43 +147,45 @@ export class Exporter {
});
};
const getBase64DataSync = Meteor.wrapAsync(getBase64Data);
result.attachments = Attachments.find(byBoard).fetch().map((attachment) => {
return {
_id: attachment._id,
cardId: attachment.cardId,
// url: FlowRouter.url(attachment.url()),
file: getBase64DataSync(attachment),
name: attachment.original.name,
type: attachment.original.type,
};
});
result.attachments = Attachments.find(byBoard)
.fetch()
.map(attachment => {
return {
_id: attachment._id,
cardId: attachment.cardId,
// url: FlowRouter.url(attachment.url()),
file: getBase64DataSync(attachment),
name: attachment.original.name,
type: attachment.original.type,
};
});
// we also have to export some user data - as the other elements only
// include id but we have to be careful:
// 1- only exports users that are linked somehow to that board
// 2- do not export any sensitive information
const users = {};
result.members.forEach((member) => {
result.members.forEach(member => {
users[member.userId] = true;
});
result.lists.forEach((list) => {
result.lists.forEach(list => {
users[list.userId] = true;
});
result.cards.forEach((card) => {
result.cards.forEach(card => {
users[card.userId] = true;
if (card.members) {
card.members.forEach((memberId) => {
card.members.forEach(memberId => {
users[memberId] = true;
});
}
});
result.comments.forEach((comment) => {
result.comments.forEach(comment => {
users[comment.userId] = true;
});
result.activities.forEach((activity) => {
result.activities.forEach(activity => {
users[activity.userId] = true;
});
result.checklists.forEach((checklist) => {
result.checklists.forEach(checklist => {
users[checklist.userId] = true;
});
const byUserIds = {
@ -177,13 +204,15 @@ export class Exporter {
'profile.avatarUrl': 1,
},
};
result.users = Users.find(byUserIds, userFields).fetch().map((user) => {
// user avatar is stored as a relative url, we export absolute
if ((user.profile || {}).avatarUrl) {
user.profile.avatarUrl = FlowRouter.url(user.profile.avatarUrl);
}
return user;
});
result.users = Users.find(byUserIds, userFields)
.fetch()
.map(user => {
// user avatar is stored as a relative url, we export absolute
if ((user.profile || {}).avatarUrl) {
user.profile.avatarUrl = FlowRouter.url(user.profile.avatarUrl);
}
return user;
});
return result;
}

View file

@ -1,6 +1,6 @@
import { TrelloCreator } from './trelloCreator';
import { WekanCreator } from './wekanCreator';
import {Exporter} from './export';
import { Exporter } from './export';
import wekanMembersMapper from './wekanmapper';
Meteor.methods({
@ -11,12 +11,12 @@ Meteor.methods({
check(currentBoard, Match.Maybe(String));
let creator;
switch (importSource) {
case 'trello':
creator = new TrelloCreator(data);
break;
case 'wekan':
creator = new WekanCreator(data);
break;
case 'trello':
creator = new TrelloCreator(data);
break;
case 'wekan':
creator = new WekanCreator(data);
break;
}
// 1. check all parameters are ok from a syntax point of view
@ -38,11 +38,9 @@ Meteor.methods({
const data = exporter.build();
const addData = {};
addData.membersMapping = wekanMembersMapper.getMembersToMap(data);
const creator = new WekanCreator(addData);
const creator = new WekanCreator(addData);
//data.title = `${data.title } - ${ TAPi18n.__('copy-tag')}`;
data.title = `${data.title}`;
return creator.create(data, currentBoardId);
},
});

View file

@ -86,14 +86,9 @@ Integrations.attachSchema(
*/
type: String,
},
})
}),
);
Integrations.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
Integrations.allow({
insert(userId, doc) {
return allowIsBoardAdmin(userId, Boards.findOne(doc.boardId));
@ -123,7 +118,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('GET', '/api/boards/:boardId/integrations', function(
req,
res
res,
) {
try {
const paramBoardId = req.params.boardId;
@ -131,7 +126,7 @@ if (Meteor.isServer) {
const data = Integrations.find(
{ boardId: paramBoardId },
{ fields: { token: 0 } }
{ fields: { token: 0 } },
).map(function(doc) {
return doc;
});
@ -155,7 +150,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('GET', '/api/boards/:boardId/integrations/:intId', function(
req,
res
res,
) {
try {
const paramBoardId = req.params.boardId;
@ -166,7 +161,7 @@ if (Meteor.isServer) {
code: 200,
data: Integrations.findOne(
{ _id: paramIntId, boardId: paramBoardId },
{ fields: { token: 0 } }
{ fields: { token: 0 } },
),
});
} catch (error) {
@ -187,7 +182,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('POST', '/api/boards/:boardId/integrations', function(
req,
res
res,
) {
try {
const paramBoardId = req.params.boardId;
@ -228,7 +223,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('PUT', '/api/boards/:boardId/integrations/:intId', function(
req,
res
res,
) {
try {
const paramBoardId = req.params.boardId;
@ -239,35 +234,35 @@ if (Meteor.isServer) {
const newEnabled = req.body.enabled;
Integrations.direct.update(
{ _id: paramIntId, boardId: paramBoardId },
{ $set: { enabled: newEnabled } }
{ $set: { enabled: newEnabled } },
);
}
if (req.body.hasOwnProperty('title')) {
const newTitle = req.body.title;
Integrations.direct.update(
{ _id: paramIntId, boardId: paramBoardId },
{ $set: { title: newTitle } }
{ $set: { title: newTitle } },
);
}
if (req.body.hasOwnProperty('url')) {
const newUrl = req.body.url;
Integrations.direct.update(
{ _id: paramIntId, boardId: paramBoardId },
{ $set: { url: newUrl } }
{ $set: { url: newUrl } },
);
}
if (req.body.hasOwnProperty('token')) {
const newToken = req.body.token;
Integrations.direct.update(
{ _id: paramIntId, boardId: paramBoardId },
{ $set: { token: newToken } }
{ $set: { token: newToken } },
);
}
if (req.body.hasOwnProperty('activities')) {
const newActivities = req.body.activities;
Integrations.direct.update(
{ _id: paramIntId, boardId: paramBoardId },
{ $set: { activities: newActivities } }
{ $set: { activities: newActivities } },
);
}
@ -306,14 +301,14 @@ if (Meteor.isServer) {
Integrations.direct.update(
{ _id: paramIntId, boardId: paramBoardId },
{ $pullAll: { activities: newActivities } }
{ $pullAll: { activities: newActivities } },
);
JsonRoutes.sendResult(res, {
code: 200,
data: Integrations.findOne(
{ _id: paramIntId, boardId: paramBoardId },
{ fields: { _id: 1, activities: 1 } }
{ fields: { _id: 1, activities: 1 } },
),
});
} catch (error) {
@ -322,7 +317,7 @@ if (Meteor.isServer) {
data: error,
});
}
}
},
);
/**
@ -346,14 +341,14 @@ if (Meteor.isServer) {
Integrations.direct.update(
{ _id: paramIntId, boardId: paramBoardId },
{ $addToSet: { activities: { $each: newActivities } } }
{ $addToSet: { activities: { $each: newActivities } } },
);
JsonRoutes.sendResult(res, {
code: 200,
data: Integrations.findOne(
{ _id: paramIntId, boardId: paramBoardId },
{ fields: { _id: 1, activities: 1 } }
{ fields: { _id: 1, activities: 1 } },
),
});
} catch (error) {
@ -362,7 +357,7 @@ if (Meteor.isServer) {
data: error,
});
}
}
},
);
/**
@ -375,7 +370,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('DELETE', '/api/boards/:boardId/integrations/:intId', function(
req,
res
res,
) {
try {
const paramBoardId = req.params.boardId;

View file

@ -47,7 +47,7 @@ InvitationCodes.attachSchema(
type: Boolean,
defaultValue: true,
},
})
}),
);
InvitationCodes.helpers({
@ -56,11 +56,6 @@ InvitationCodes.helpers({
},
});
InvitationCodes.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
// InvitationCodes.before.insert((userId, doc) => {
// doc.createdAt = new Date();
// doc.authorId = userId;

View file

@ -156,7 +156,7 @@ Lists.attachSchema(
type: String,
defaultValue: 'list',
},
})
}),
);
Lists.allow({
@ -198,7 +198,7 @@ Lists.helpers({
swimlaneId: oldSwimlaneId,
listId: oldId,
archived: false,
}).forEach((card) => {
}).forEach(card => {
card.copy(boardId, swimlaneId, _id);
});
},
@ -262,7 +262,7 @@ Lists.mutations({
archive() {
if (this.isTemplateList()) {
this.cards().forEach((card) => {
this.cards().forEach(card => {
return card.archive();
});
}
@ -271,7 +271,7 @@ Lists.mutations({
restore() {
if (this.isTemplateList()) {
this.allCards().forEach((card) => {
this.allCards().forEach(card => {
return card.restore();
});
}
@ -346,15 +346,10 @@ if (Meteor.isServer) {
});
});
Lists.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
Lists.before.remove((userId, doc) => {
const cards = Cards.find({ listId: doc._id });
if (cards) {
cards.forEach((card) => {
cards.forEach(card => {
Cards.remove(card._id);
});
}
@ -404,7 +399,7 @@ if (Meteor.isServer) {
_id: doc._id,
title: doc.title,
};
}
},
),
});
} catch (error) {
@ -425,7 +420,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('GET', '/api/boards/:boardId/lists/:listId', function(
req,
res
res,
) {
try {
const paramBoardId = req.params.boardId;
@ -492,7 +487,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('DELETE', '/api/boards/:boardId/lists/:listId', function(
req,
res
res,
) {
try {
Authentication.checkUserId(req.userId);

View file

@ -44,7 +44,7 @@ Rules.attachSchema(
}
},
},
})
}),
);
Rules.mutations({
@ -74,11 +74,6 @@ Rules.allow({
},
});
Rules.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
if (Meteor.isServer) {
Meteor.startup(() => {
Rules._collection._ensureIndex({ modifiedAt: -1 });

View file

@ -76,7 +76,7 @@ Settings.attachSchema(
}
},
},
})
}),
);
Settings.helpers({
mailUrl() {
@ -88,7 +88,7 @@ Settings.helpers({
return `${protocol}${this.mailServer.host}:${this.mailServer.port}/`;
}
return `${protocol}${this.mailServer.username}:${encodeURIComponent(
this.mailServer.password
this.mailServer.password,
)}@${this.mailServer.host}:${this.mailServer.port}/`;
},
});
@ -99,11 +99,6 @@ Settings.allow({
},
});
Settings.before.update((userId, doc, fieldNames, modifier) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = new Date();
});
if (Meteor.isServer) {
Meteor.startup(() => {
Settings._collection._ensureIndex({ modifiedAt: -1 });
@ -111,7 +106,7 @@ if (Meteor.isServer) {
if (!setting) {
const now = new Date();
const domain = process.env.ROOT_URL.match(
/\/\/(?:www\.)?(.*)?(?:\/)?/
/\/\/(?:www\.)?(.*)?(?:\/)?/,
)[1];
const from = `Boards Support <support@${domain}>`;
const defaultSetting = {
@ -143,9 +138,7 @@ if (Meteor.isServer) {
if (_.contains(fieldNames, 'mailServer') && doc.mailServer.host) {
const protocol = doc.mailServer.enableTLS ? 'smtps://' : 'smtp://';
if (!doc.mailServer.username && !doc.mailServer.password) {
process.env.MAIL_URL = `${protocol}${doc.mailServer.host}:${
doc.mailServer.port
}/`;
process.env.MAIL_URL = `${protocol}${doc.mailServer.host}:${doc.mailServer.port}/`;
} else {
process.env.MAIL_URL = `${protocol}${
doc.mailServer.username
@ -220,14 +213,14 @@ if (Meteor.isServer) {
if (!user.isAdmin) {
throw new Meteor.Error('not-allowed');
}
emails.forEach((email) => {
emails.forEach(email => {
if (email && SimpleSchema.RegEx.Email.test(email)) {
// Checks if the email is already link to an account.
const userExist = Users.findOne({ email });
if (userExist) {
throw new Meteor.Error(
'user-exist',
`The user with the email ${email} has already an account.`
`The user with the email ${email} has already an account.`,
);
}
// Checks if the email is already link to an invitation.
@ -253,10 +246,10 @@ if (Meteor.isServer) {
} else {
throw new Meteor.Error(
'invitation-generated-fail',
err.message
err.message,
);
}
}
},
);
}
}
@ -284,7 +277,7 @@ if (Meteor.isServer) {
throw new Meteor.Error(
'email-fail',
`${TAPi18n.__('email-fail-text', { lng: lang })}: ${message}`,
message
message,
);
}
return {

View file

@ -120,7 +120,7 @@ Swimlanes.attachSchema(
type: String,
defaultValue: 'swimlane',
},
})
}),
);
Swimlanes.allow({
@ -153,7 +153,7 @@ Swimlanes.helpers({
}
// Copy all lists in swimlane
Lists.find(query).forEach((list) => {
Lists.find(query).forEach(list => {
list.type = 'list';
list.swimlaneId = oldId;
list.boardId = boardId;
@ -167,7 +167,7 @@ Swimlanes.helpers({
swimlaneId: this._id,
archived: false,
}),
{ sort: ['sort'] }
{ sort: ['sort'] },
);
},
@ -178,7 +178,7 @@ Swimlanes.helpers({
swimlaneId: { $in: [this._id, ''] },
archived: false,
},
{ sort: ['sort'] }
{ sort: ['sort'] },
);
},
@ -234,7 +234,7 @@ Swimlanes.mutations({
archive() {
if (this.isTemplateSwimlane()) {
this.myLists().forEach((list) => {
this.myLists().forEach(list => {
return list.archive();
});
}
@ -243,7 +243,7 @@ Swimlanes.mutations({
restore() {
if (this.isTemplateSwimlane()) {
this.myLists().forEach((list) => {
this.myLists().forEach(list => {
return list.restore();
});
}
@ -262,11 +262,6 @@ Swimlanes.mutations({
},
});
Swimlanes.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
Swimlanes.hookOptions.after.update = { fetchPrevious: false };
if (Meteor.isServer) {
@ -292,11 +287,11 @@ if (Meteor.isServer) {
swimlaneId: { $in: [doc._id, ''] },
archived: false,
},
{ sort: ['sort'] }
{ sort: ['sort'] },
);
if (lists.count() < 2) {
lists.forEach((list) => {
lists.forEach(list => {
list.remove();
});
} else {
@ -350,7 +345,7 @@ if (Meteor.isServer) {
_id: doc._id,
title: doc.title,
};
}
},
),
});
} catch (error) {
@ -372,7 +367,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('GET', '/api/boards/:boardId/swimlanes/:swimlaneId', function(
req,
res
res,
) {
try {
const paramBoardId = req.params.boardId;
@ -459,7 +454,7 @@ if (Meteor.isServer) {
data: error,
});
}
}
},
);
}

View file

@ -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();
});
@ -52,10 +52,10 @@ export class TrelloCreator {
* @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;
@ -67,75 +67,90 @@ export class TrelloCreator {
* Otherwise return current logged user.
* @param trelloUserId
* @private
*/
*/
_user(trelloUserId) {
if(trelloUserId && this.members[trelloUserId]) {
if (trelloUserId && this.members[trelloUserId]) {
return this.members[trelloUserId];
}
return Meteor.userId();
}
checkActions(trelloActions) {
check(trelloActions, [Match.ObjectIncluding({
data: Object,
date: DateString,
type: String,
})]);
check(trelloActions, [
Match.ObjectIncluding({
data: Object,
date: DateString,
type: String,
}),
]);
// XXX we could perform more thorough checks based on action type
}
checkBoard(trelloBoard) {
check(trelloBoard, Match.ObjectIncluding({
closed: Boolean,
name: String,
prefs: Match.ObjectIncluding({
// XXX refine control by validating 'background' against a list of
// allowed values (is it worth the maintenance?)
background: String,
permissionLevel: Match.Where((value) => {
return ['org', 'private', 'public'].indexOf(value)>= 0;
check(
trelloBoard,
Match.ObjectIncluding({
closed: Boolean,
name: String,
prefs: Match.ObjectIncluding({
// XXX refine control by validating 'background' against a list of
// allowed values (is it worth the maintenance?)
background: String,
permissionLevel: Match.Where(value => {
return ['org', 'private', 'public'].indexOf(value) >= 0;
}),
}),
}),
}));
);
}
checkCards(trelloCards) {
check(trelloCards, [Match.ObjectIncluding({
closed: Boolean,
dateLastActivity: DateString,
desc: String,
idLabels: [String],
idMembers: [String],
name: String,
pos: Number,
})]);
check(trelloCards, [
Match.ObjectIncluding({
closed: Boolean,
dateLastActivity: DateString,
desc: String,
idLabels: [String],
idMembers: [String],
name: String,
pos: Number,
}),
]);
}
checkLabels(trelloLabels) {
check(trelloLabels, [Match.ObjectIncluding({
// XXX refine control by validating 'color' against a list of allowed
// values (is it worth the maintenance?)
name: String,
})]);
check(trelloLabels, [
Match.ObjectIncluding({
// XXX refine control by validating 'color' against a list of allowed
// values (is it worth the maintenance?)
name: String,
}),
]);
}
checkLists(trelloLists) {
check(trelloLists, [Match.ObjectIncluding({
closed: Boolean,
name: String,
})]);
check(trelloLists, [
Match.ObjectIncluding({
closed: Boolean,
name: String,
}),
]);
}
checkChecklists(trelloChecklists) {
check(trelloChecklists, [Match.ObjectIncluding({
idBoard: String,
idCard: String,
name: String,
checkItems: [Match.ObjectIncluding({
state: String,
check(trelloChecklists, [
Match.ObjectIncluding({
idBoard: String,
idCard: String,
name: String,
})],
})]);
checkItems: [
Match.ObjectIncluding({
state: String,
name: String,
}),
],
}),
]);
}
// You must call parseActions before calling this one.
@ -146,31 +161,35 @@ export class TrelloCreator {
// very old boards won't have a creation activity so no creation date
createdAt: this._now(this.createdAt.board),
labels: [],
members: [{
userId: Meteor.userId(),
isAdmin: true,
isActive: true,
isNoComments: false,
isCommentOnly: false,
swimlaneId: false,
}],
members: [
{
userId: Meteor.userId(),
isAdmin: true,
isActive: true,
isNoComments: false,
isCommentOnly: false,
swimlaneId: false,
},
],
permission: this.getPermission(trelloBoard.prefs.permissionLevel),
slug: getSlug(trelloBoard.name) || 'board',
stars: 0,
title: trelloBoard.name,
};
// now add other members
if(trelloBoard.memberships) {
trelloBoard.memberships.forEach((trelloMembership) => {
if (trelloBoard.memberships) {
trelloBoard.memberships.forEach(trelloMembership => {
const trelloId = trelloMembership.idMember;
// do we have a mapping?
if(this.members[trelloId]) {
if (this.members[trelloId]) {
const wekanId = this.members[trelloId];
// do we already have it in our list?
const wekanMember = boardToCreate.members.find((wekanMember) => wekanMember.userId === wekanId);
if(wekanMember) {
const wekanMember = boardToCreate.members.find(
wekanMember => wekanMember.userId === wekanId,
);
if (wekanMember) {
// we're already mapped, but maybe with lower rights
if(!wekanMember.isAdmin) {
if (!wekanMember.isAdmin) {
wekanMember.isAdmin = this.getAdmin(trelloMembership.memberType);
}
} else {
@ -186,7 +205,7 @@ export class TrelloCreator {
}
});
}
trelloBoard.labels.forEach((label) => {
trelloBoard.labels.forEach(label => {
const labelToCreate = {
_id: Random.id(6),
color: label.color ? label.color : 'black',
@ -198,7 +217,7 @@ export class TrelloCreator {
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',
@ -225,7 +244,7 @@ export class TrelloCreator {
*/
createCards(trelloCards, boardId) {
const result = [];
trelloCards.forEach((card) => {
trelloCards.forEach(card => {
const cardToCreate = {
archived: card.closed,
boardId,
@ -243,26 +262,26 @@ export class TrelloCreator {
};
// add labels
if (card.idLabels) {
cardToCreate.labelIds = card.idLabels.map((trelloId) => {
cardToCreate.labelIds = card.idLabels.map(trelloId => {
return this.labels[trelloId];
});
}
// add members {
if(card.idMembers) {
if (card.idMembers) {
const wekanMembers = [];
// we can't just map, as some members may not have been mapped
card.idMembers.forEach((trelloId) => {
if(this.members[trelloId]) {
card.idMembers.forEach(trelloId => {
if (this.members[trelloId]) {
const wekanId = this.members[trelloId];
// we may map multiple Trello 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;
}
}
@ -289,7 +308,7 @@ export class TrelloCreator {
// add comments
const comments = this.comments[card.id];
if (comments) {
comments.forEach((comment) => {
comments.forEach(comment => {
const commentToCreate = {
boardId,
cardId,
@ -318,15 +337,15 @@ export class TrelloCreator {
const attachments = this.attachments[card.id];
const trelloCoverId = card.idAttachmentCover;
if (attachments) {
attachments.forEach((att) => {
attachments.forEach(att => {
const file = new FS.File();
// Simulating file.attachData on the client generates multiple errors
// - HEAD returns null, which causes exception down the line
// - 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) {
file.attachData(att.url, function (error) {
if (Meteor.isServer) {
file.attachData(att.url, function(error) {
file.boardId = boardId;
file.cardId = cardId;
file.userId = self._user(att.idMemberCreator);
@ -334,15 +353,17 @@ export class TrelloCreator {
// 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(trelloCoverId === att.id) {
Cards.direct.update(cardId, { $set: {coverId: wekanAtt._id}});
if (trelloCoverId === att.id) {
Cards.direct.update(cardId, {
$set: { coverId: wekanAtt._id },
});
}
}
});
@ -357,7 +378,7 @@ export class TrelloCreator {
// Create labels if they do not exist and load this.labels.
createLabels(trelloLabels, board) {
trelloLabels.forEach((label) => {
trelloLabels.forEach(label => {
const color = label.color;
const name = label.name;
const existingLabel = board.getLabel(name, color);
@ -371,7 +392,7 @@ export class TrelloCreator {
}
createLists(trelloLists, boardId) {
trelloLists.forEach((list) => {
trelloLists.forEach(list => {
const listToCreate = {
archived: list.closed,
boardId,
@ -384,7 +405,7 @@ export class TrelloCreator {
sort: list.pos,
};
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({
@ -416,12 +437,12 @@ export class TrelloCreator {
sort: 1,
};
const swimlaneId = Swimlanes.direct.insert(swimlaneToCreate);
Swimlanes.direct.update(swimlaneId, {$set: {'updatedAt': this._now()}});
Swimlanes.direct.update(swimlaneId, { $set: { updatedAt: this._now() } });
this.swimlane = swimlaneId;
}
createChecklists(trelloChecklists) {
trelloChecklists.forEach((checklist) => {
trelloChecklists.forEach(checklist => {
if (this.cards[checklist.idCard]) {
// Create the checklist
const checklistToCreate = {
@ -435,7 +456,7 @@ export class TrelloCreator {
this.checklists[checklist.id] = checklistId;
// Now add the items to the checklistItems
let counter = 0;
checklist.checkItems.forEach((item) => {
checklist.checkItems.forEach(item => {
counter++;
const checklistItemTocreate = {
_id: checklistId + counter,
@ -458,15 +479,15 @@ export class TrelloCreator {
getColor(trelloColorCode) {
// trello color name => wekan color
const mapColors = {
'blue': 'belize',
'orange': 'pumpkin',
'green': 'nephritis',
'red': 'pomegranate',
'purple': 'wisteria',
'pink': 'pomegranate',
'lime': 'nephritis',
'sky': 'belize',
'grey': 'midnight',
blue: 'belize',
orange: 'pumpkin',
green: 'nephritis',
red: 'pomegranate',
purple: 'wisteria',
pink: 'pomegranate',
lime: 'nephritis',
sky: 'belize',
grey: 'midnight',
};
const wekanColor = mapColors[trelloColorCode];
return wekanColor || Boards.simpleSchema()._schema.color.allowedValues[0];
@ -482,7 +503,7 @@ export class TrelloCreator {
}
parseActions(trelloActions) {
trelloActions.forEach((action) => {
trelloActions.forEach(action => {
if (action.type === 'addAttachmentToCard') {
// We have to be cautious, because the attachment could have been removed later.
// In that case Trello still reports its addition, but removes its 'url' field.
@ -490,11 +511,11 @@ export class TrelloCreator {
const trelloAttachment = action.data.attachment;
// We need the idMemberCreator
trelloAttachment.idMemberCreator = action.idMemberCreator;
if(trelloAttachment.url) {
if (trelloAttachment.url) {
// 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 trelloCardId = action.data.card.id;
if(!this.attachments[trelloCardId]) {
if (!this.attachments[trelloCardId]) {
this.attachments[trelloCardId] = [];
}
this.attachments[trelloCardId].push(trelloAttachment);
@ -520,88 +541,89 @@ export class TrelloCreator {
}
importActions(actions, boardId) {
actions.forEach((action) => {
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) {
// Board related actions
// TODO: addBoardMember, removeBoardMember
case 'createBoard': {
Activities.direct.insert({
userId: this._user(action.idMemberCreator),
oldListId: this.lists[action.data.old.idList],
activityType: 'moveCard',
listId: this.lists[action.data.listAfter.id],
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
case 'addAttachmentToCard': {
Activities.direct.insert({
userId: this._user(action.idMemberCreator),
type: 'card',
activityType: 'addAttachment',
attachmentId: this.attachmentIds[action.data.attachment.id],
cardId: this.cards[action.data.card.id],
boardId,
createdAt: this._now(action.date),
});
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;
}
break;
}
// Comment related activities
// Trello doesn't export the comment id
// Attachment related activities
case 'addAttachmentToCard': {
Activities.direct.insert({
userId: this._user(action.idMemberCreator),
type: 'card',
activityType: 'addAttachment',
attachmentId: this.attachmentIds[action.data.attachment.id],
cardId: this.cards[action.data.card.id],
boardId,
createdAt: this._now(action.date),
});
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
});
}
@ -624,7 +646,9 @@ export class TrelloCreator {
create(board, currentBoardId) {
// TODO : Make isSandstorm variable global
const isSandstorm = Meteor.settings && Meteor.settings.public &&
const isSandstorm =
Meteor.settings &&
Meteor.settings.public &&
Meteor.settings.public.sandstorm;
if (isSandstorm && currentBoardId) {
const currentBoard = Boards.findOne(currentBoardId);

View file

@ -51,18 +51,13 @@ Triggers.helpers({
labels() {
const boardLabels = this.board().labels;
const cardLabels = _.filter(boardLabels, (label) => {
const cardLabels = _.filter(boardLabels, label => {
return _.contains(this.labelIds, label._id);
});
return cardLabels;
},
});
Triggers.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
if (Meteor.isServer) {
Meteor.startup(() => {
Triggers._collection._ensureIndex({ modifiedAt: -1 });

View file

@ -46,14 +46,7 @@ UnsavedEditCollection.attachSchema(
}
},
},
})
);
UnsavedEditCollection.before.update(
(userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
}
}),
);
if (Meteor.isServer) {

View file

@ -247,7 +247,7 @@ Users.attachSchema(
optional: false,
defaultValue: 'password',
},
})
}),
);
Users.allow({
@ -259,7 +259,7 @@ Users.allow({
const adminsNumber = Users.find({ isAdmin: true }).count();
const { isAdmin } = Users.findOne(
{ _id: userId },
{ fields: { isAdmin: 1 } }
{ fields: { isAdmin: 1 } },
);
// Prevents remove of the only one administrator
@ -533,7 +533,7 @@ Meteor.methods({
check(email, String);
const existingUser = Users.findOne(
{ 'emails.address': email },
{ fields: { _id: 1 } }
{ fields: { _id: 1 } },
);
if (existingUser) {
throw new Meteor.Error('email-already-taken');
@ -700,7 +700,7 @@ if (Meteor.isServer) {
if (!options || !options.profile) {
throw new Meteor.Error(
'error-invitation-code-blank',
'The invitation code is required'
'The invitation code is required',
);
}
const invitationCode = InvitationCodes.findOne({
@ -711,7 +711,8 @@ if (Meteor.isServer) {
if (!invitationCode) {
throw new Meteor.Error(
'error-invitation-code-not-exist',
'The invitation code doesn\'t exist'
// eslint-disable-next-line quotes
"The invitation code doesn't exist",
);
} else {
user.profile = { icode: options.profile.invitationcode };
@ -722,18 +723,13 @@ if (Meteor.isServer) {
Meteor.bindEnvironment(() => {
InvitationCodes.remove({ _id: invitationCode._id });
}),
200
200,
);
return user;
}
});
}
Users.before.update((userId, doc, fieldNames, modifier, options) => {
modifier.$set = modifier.$set || {};
modifier.$set.modifiedAt = Date.now();
});
if (Meteor.isServer) {
// Let mongoDB ensure username unicity
Meteor.startup(() => {
@ -742,7 +738,7 @@ if (Meteor.isServer) {
{
username: 1,
},
{ unique: true }
{ unique: true },
);
});
@ -786,7 +782,7 @@ if (Meteor.isServer) {
// b. We use it to find deleted and newly inserted ids by using it in one
// direction and then in the other.
function incrementBoards(boardsIds, inc) {
boardsIds.forEach((boardId) => {
boardsIds.forEach(boardId => {
Boards.update(boardId, { $inc: { stars: inc } });
});
}
@ -855,7 +851,7 @@ if (Meteor.isServer) {
Users.update(fakeUserId.get(), {
$set: { 'profile.cardTemplatesSwimlaneId': swimlaneId },
});
}
},
);
// Insert the list templates swimlane
@ -872,7 +868,7 @@ if (Meteor.isServer) {
Users.update(fakeUserId.get(), {
$set: { 'profile.listTemplatesSwimlaneId': swimlaneId },
});
}
},
);
// Insert the board templates swimlane
@ -889,9 +885,9 @@ if (Meteor.isServer) {
Users.update(fakeUserId.get(), {
$set: { 'profile.boardTemplatesSwimlaneId': swimlaneId },
});
}
},
);
}
},
);
});
});
@ -921,7 +917,7 @@ if (Meteor.isServer) {
if (!invitationCode) {
throw new Meteor.Error('error-invitation-code-not-exist');
} else {
invitationCode.boardsToBeInvited.forEach((boardId) => {
invitationCode.boardsToBeInvited.forEach(boardId => {
const board = Boards.findOne(boardId);
board.addMember(doc._id);
});
@ -1071,7 +1067,7 @@ if (Meteor.isServer) {
loginDisabled: true,
'services.resume.loginTokens': '',
},
}
},
);
} else if (action === 'enableLogin') {
Users.update({ _id: id }, { $set: { loginDisabled: '' } });
@ -1112,7 +1108,7 @@ if (Meteor.isServer) {
*/
JsonRoutes.add('POST', '/api/boards/:boardId/members/:userId/add', function(
req,
res
res,
) {
try {
Authentication.checkUserId(req.userId);
@ -1136,7 +1132,7 @@ if (Meteor.isServer) {
isTrue(isAdmin),
isTrue(isNoComments),
isTrue(isCommentOnly),
userId
userId,
);
}
return {
@ -1207,7 +1203,7 @@ if (Meteor.isServer) {
data: error,
});
}
}
},
);
/**

View file

@ -1,5 +1,5 @@
// simple version, only toggle watch / unwatch
const simpleWatchable = (collection) => {
const simpleWatchable = collection => {
collection.attachSchema({
watchers: {
type: [String],
@ -24,8 +24,8 @@ const simpleWatchable = (collection) => {
collection.mutations({
setWatcher(userId, level) {
// if level undefined or null or false, then remove
if (!level) return { $pull: { watchers: userId }};
return { $addToSet: { watchers: userId }};
if (!level) return { $pull: { watchers: userId } };
return { $addToSet: { watchers: userId } };
},
});
};
@ -34,7 +34,7 @@ const simpleWatchable = (collection) => {
const complexWatchOptions = ['watching', 'tracking', 'muted'];
const complexWatchDefault = 'muted';
const complexWatchable = (collection) => {
const complexWatchable = collection => {
collection.attachSchema({
'watchers.$.userId': {
type: String,
@ -72,9 +72,9 @@ const complexWatchable = (collection) => {
setWatcher(userId, level) {
// if level undefined or null or false, then remove
if (level === complexWatchDefault) level = null;
if (!level) return { $pull: { watchers: { userId }}};
if (!level) return { $pull: { watchers: { userId } } };
const index = this.watcherIndex(userId);
if (index<0) return { $push: { watchers: { userId, level }}};
if (index < 0) return { $push: { watchers: { userId, level } } };
return {
$set: {
[`watchers.${index}.level`]: level,

View file

@ -87,99 +87,120 @@ export class WekanCreator {
}
checkActivities(wekanActivities) {
check(wekanActivities, [Match.ObjectIncluding({
activityType: String,
createdAt: DateString,
})]);
check(wekanActivities, [
Match.ObjectIncluding({
activityType: String,
createdAt: DateString,
}),
]);
// XXX we could perform more thorough checks based on action type
}
checkBoard(wekanBoard) {
check(wekanBoard, Match.ObjectIncluding({
archived: Boolean,
title: String,
// XXX refine control by validating 'color' against a list of
// allowed values (is it worth the maintenance?)
color: String,
permission: Match.Where((value) => {
return ['private', 'public'].indexOf(value) >= 0;
check(
wekanBoard,
Match.ObjectIncluding({
archived: Boolean,
title: String,
// XXX refine control by validating 'color' against a list of
// allowed values (is it worth the maintenance?)
color: String,
permission: Match.Where(value => {
return ['private', 'public'].indexOf(value) >= 0;
}),
}),
}));
);
}
checkCards(wekanCards) {
check(wekanCards, [Match.ObjectIncluding({
archived: Boolean,
dateLastActivity: DateString,
labelIds: [String],
title: String,
sort: Number,
})]);
check(wekanCards, [
Match.ObjectIncluding({
archived: Boolean,
dateLastActivity: DateString,
labelIds: [String],
title: String,
sort: Number,
}),
]);
}
checkLabels(wekanLabels) {
check(wekanLabels, [Match.ObjectIncluding({
// XXX refine control by validating 'color' against a list of allowed
// values (is it worth the maintenance?)
color: String,
})]);
check(wekanLabels, [
Match.ObjectIncluding({
// XXX refine control by validating 'color' against a list of allowed
// values (is it worth the maintenance?)
color: String,
}),
]);
}
checkLists(wekanLists) {
check(wekanLists, [Match.ObjectIncluding({
archived: Boolean,
title: String,
})]);
check(wekanLists, [
Match.ObjectIncluding({
archived: Boolean,
title: String,
}),
]);
}
checkSwimlanes(wekanSwimlanes) {
check(wekanSwimlanes, [Match.ObjectIncluding({
archived: Boolean,
title: String,
})]);
check(wekanSwimlanes, [
Match.ObjectIncluding({
archived: Boolean,
title: String,
}),
]);
}
checkChecklists(wekanChecklists) {
check(wekanChecklists, [Match.ObjectIncluding({
cardId: String,
title: String,
})]);
check(wekanChecklists, [
Match.ObjectIncluding({
cardId: String,
title: String,
}),
]);
}
checkChecklistItems(wekanChecklistItems) {
check(wekanChecklistItems, [Match.ObjectIncluding({
cardId: String,
title: String,
})]);
check(wekanChecklistItems, [
Match.ObjectIncluding({
cardId: String,
title: String,
}),
]);
}
checkRules(wekanRules) {
check(wekanRules, [Match.ObjectIncluding({
triggerId: String,
actionId: String,
title: String,
})]);
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,
})]);
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
// 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) => {
membersToMap.forEach(importedMember => {
importedMember.id = importedMember.userId;
delete importedMember.userId;
const user = users.filter((user) => {
const user = users.filter(user => {
return user._id === importedMember.id;
})[0];
if (user.profile && user.profile.fullname) {
@ -196,10 +217,12 @@ export class WekanCreator {
checkActions(wekanActions) {
// XXX More check based on action type
check(wekanActions, [Match.ObjectIncluding({
actionType: String,
desc: String,
})]);
check(wekanActions, [
Match.ObjectIncluding({
actionType: String,
desc: String,
}),
]);
}
// You must call parseActions before calling this one.
@ -210,15 +233,17 @@ export class WekanCreator {
// very old boards won't have a creation activity so no creation date
createdAt: this._now(boardToImport.createdAt),
labels: [],
members: [{
userId: Meteor.userId(),
wekanId: Meteor.userId(),
isActive: true,
isAdmin: true,
isNoComments: false,
isCommentOnly: false,
swimlaneId: false,
}],
members: [
{
userId: Meteor.userId(),
wekanId: Meteor.userId(),
isActive: true,
isAdmin: true,
isNoComments: false,
isCommentOnly: false,
swimlaneId: false,
},
],
// Standalone Export has modifiedAt missing, adding modifiedAt to fix it
modifiedAt: this._now(boardToImport.modifiedAt),
permission: boardToImport.permission,
@ -228,16 +253,20 @@ export class WekanCreator {
};
// now add other members
if (boardToImport.members) {
boardToImport.members.forEach((wekanMember) => {
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,
userId: wekanMember.wekanId,
});
});
}
boardToImport.labels.forEach((label) => {
boardToImport.labels.forEach(label => {
const labelToCreate = {
_id: Random.id(6),
color: label.color,
@ -279,7 +308,7 @@ export class WekanCreator {
*/
createCards(wekanCards, boardId) {
const result = [];
wekanCards.forEach((card) => {
wekanCards.forEach(card => {
const cardToCreate = {
archived: card.archived,
boardId,
@ -300,7 +329,7 @@ export class WekanCreator {
};
// add labels
if (card.labelIds) {
cardToCreate.labelIds = card.labelIds.map((wekanId) => {
cardToCreate.labelIds = card.labelIds.map(wekanId => {
return this.labels[wekanId];
});
}
@ -308,12 +337,12 @@ export class WekanCreator {
if (card.members) {
const wekanMembers = [];
// we can't just map, as some members may not have been mapped
card.members.forEach((sourceMemberId) => {
card.members.forEach(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);
}
}
@ -349,7 +378,7 @@ export class WekanCreator {
// add comments
const comments = this.comments[card._id];
if (comments) {
comments.forEach((comment) => {
comments.forEach(comment => {
const commentToCreate = {
boardId,
cardId,
@ -377,7 +406,7 @@ export class WekanCreator {
const attachments = this.attachments[card._id];
const wekanCoverId = card.coverId;
if (attachments) {
attachments.forEach((att) => {
attachments.forEach(att => {
const file = new FS.File();
// Simulating file.attachData on the client generates multiple errors
// - HEAD returns null, which causes exception down the line
@ -394,7 +423,7 @@ 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
@ -411,33 +440,37 @@ export class WekanCreator {
}
});
} else if (att.file) {
file.attachData(new Buffer(att.file, 'base64'), {
type: att.type,
}, (error) => {
file.name(att.name);
file.boardId = boardId;
file.cardId = cardId;
file.userId = self._user(att.userId);
// The field source will only be used to prevent adding
// attachments' related activities automatically
file.source = 'import';
if (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,
},
file.attachData(
new Buffer(att.file, 'base64'),
{
type: att.type,
},
error => {
file.name(att.name);
file.boardId = boardId;
file.cardId = cardId;
file.userId = self._user(att.userId);
// The field source will only be used to prevent adding
// attachments' related activities automatically
file.source = 'import';
if (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,
},
});
}
}
}
});
},
);
}
}
// todo XXX set cover - if need be
@ -450,7 +483,7 @@ export class WekanCreator {
// Create labels if they do not exist and load this.labels.
createLabels(wekanLabels, board) {
wekanLabels.forEach((label) => {
wekanLabels.forEach(label => {
const color = label.color;
const name = label.name;
const existingLabel = board.getLabel(name, color);
@ -479,7 +512,7 @@ export class WekanCreator {
const listId = Lists.direct.insert(listToCreate);
Lists.direct.update(listId, {
$set: {
'updatedAt': this._now(),
updatedAt: this._now(),
},
});
this.lists[list._id] = listId;
@ -520,7 +553,7 @@ export class WekanCreator {
const swimlaneId = Swimlanes.direct.insert(swimlaneToCreate);
Swimlanes.direct.update(swimlaneId, {
$set: {
'updatedAt': this._now(),
updatedAt: this._now(),
},
});
this.swimlanes[swimlane._id] = swimlaneId;
@ -545,7 +578,7 @@ export class WekanCreator {
}
createTriggers(wekanTriggers, boardId) {
wekanTriggers.forEach((trigger) => {
wekanTriggers.forEach(trigger => {
if (trigger.hasOwnProperty('labelId')) {
trigger.labelId = this.labels[trigger.labelId];
}
@ -560,7 +593,7 @@ export class WekanCreator {
}
createActions(wekanActions, boardId) {
wekanActions.forEach((action) => {
wekanActions.forEach(action => {
if (action.hasOwnProperty('labelId')) {
action.labelId = this.labels[action.labelId];
}
@ -575,7 +608,7 @@ export class WekanCreator {
}
createRules(wekanRules, boardId) {
wekanRules.forEach((rule) => {
wekanRules.forEach(rule => {
// Create the rule
rule.boardId = boardId;
rule.triggerId = this.triggers[rule.triggerId];
@ -595,189 +628,178 @@ export class WekanCreator {
sort: checklistitem.sort ? checklistitem.sort : checklistitemIndex,
isFinished: checklistitem.isFinished,
};
const checklistItemId = ChecklistItems.direct.insert(checklistItemTocreate);
const checklistItemId = ChecklistItems.direct.insert(
checklistItemTocreate,
);
this.checklistItems[checklistitem._id] = checklistItemId;
});
}
parseActivities(wekanBoard) {
wekanBoard.activities.forEach((activity) => {
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;
}
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] = [];
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;
}
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) => {
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;
}
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;
}
// 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;
}
}
});
}
@ -788,7 +810,6 @@ export class WekanCreator {
// check(data, {
// membersMapping: Match.Optional(Object),
// });
// this.checkActivities(board.activities);
// this.checkBoard(board);
// this.checkLabels(board.labels);
@ -807,7 +828,9 @@ export class WekanCreator {
create(board, currentBoardId) {
// TODO : Make isSandstorm variable global
const isSandstorm = Meteor.settings && Meteor.settings.public &&
const isSandstorm =
Meteor.settings &&
Meteor.settings.public &&
Meteor.settings.public.sandstorm;
if (isSandstorm && currentBoardId) {
const currentBoard = Boards.findOne(currentBoardId);

View file

@ -5,10 +5,10 @@ export function getMembersToMap(data) {
const membersToMap = data.members;
const users = data.users;
// auto-map based on username
membersToMap.forEach((importedMember) => {
membersToMap.forEach(importedMember => {
importedMember.id = importedMember.userId;
delete importedMember.userId;
const user = users.filter((user) => {
const user = users.filter(user => {
return user._id === importedMember.id;
})[0];
if (user.profile && user.profile.fullname) {