Skip to content

Commit

Permalink
References #82, added activity stream and socket.
Browse files Browse the repository at this point in the history
Introduces own events for action cases. Extended WebSocket and
ActivityStream logic to handle those. Socket defaults to sending out the
task:update event as the front-end will handle it like that for now
(might change to be more specific in the future). Extended activity
stream to handle the more advanced logic needed by multiple objects
being part of the action (participant and task, resource and task,
outcome and task). The logic got extended, not rewritten. This should
keep the compatibility with previous activities (already stored). In
case of some more drastic changes, the logic should probably be
rewritten in full, keeping it compatible with previous version is not
required (as no public instances exist, yet).
  • Loading branch information
pjotrsavitski committed Nov 14, 2016
1 parent 0b1ee3a commit 35fe845
Show file tree
Hide file tree
Showing 7 changed files with 111 additions and 21 deletions.
55 changes: 48 additions & 7 deletions app/activity.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,30 @@
const Activity = require('mongoose').model('Activity');

module.exports = function (app) {
const activityPopulateOptions = [{
path: 'actor',
model: 'User'
}];
const activityPopulateOptions = Activity.getPopulateOptions();

function extractModelFromData(data, type) {
if ( type ) {
return data.data[type];
}

function extractModelFromData(data) {
return data.data;
}

function extractActorFromData(data) {
return data.actor;
}

function getModelTypeToExtract(actionType, objectType) {
if ( actionType === 'attach' || actionType === 'detach' ) {
return objectType;
}

return null;
}

function createActivityFromEvent(activityType, objectType, data) {
const object = extractModelFromData(data);
const object = extractModelFromData(data, getModelTypeToExtract(activityType, objectType));
const actor = extractActorFromData(data);
let activityData = {};

Expand All @@ -35,10 +44,18 @@ module.exports = function (app) {
activityData.end = object.end;
}
}
if ( objectType === 'participant' && ( activityType === 'invite' || activityType === 'remove' ) ) {
if ( objectType === 'participant' && ( activityType === 'invite' || activityType === 'remove' || activityType === 'attach' || activityType === 'detach' ) ) {
activityData.user = ( object.user._id ) ? object.user._id : object.user;
}

if ( activityType === 'attach' || activityType === 'detach' ) {
const taskObject = extractModelFromData(data, 'task');

activityData.task = {};
activityData.task.title = taskObject.title;
activityData.task._id = taskObject._id;
}

new Activity({
activityType: activityType,
objectType: objectType,
Expand Down Expand Up @@ -166,4 +183,28 @@ module.exports = function (app) {
app.on('remove:participant', function(data) {
createActivityFromEvent('remove', 'participant', data);
});

app.on('attach:participant', function(data) {
createActivityFromEvent('attach', 'participant', data);
});

app.on('detach:participant', function(data) {
createActivityFromEvent('detach', 'participant', data);
});

app.on('attach:resource', function(data) {
createActivityFromEvent('attach', 'resource', data);
});

app.on('detach:resource', function(data) {
createActivityFromEvent('detach', 'resource', data);
});

app.on('attach:outcome', function(data) {
createActivityFromEvent('attach', 'outcome', data);
});

app.on('detach:outcome', function(data) {
createActivityFromEvent('detach', 'outcome', data);
});
};
11 changes: 11 additions & 0 deletions app/models/activity.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ activitySchema.pre('save', function(done) {
done();
});

activitySchema.statics.getPopulateOptions = function() {
return [{
path: 'actor',
model: 'User'
},
{
path: 'data.user',
model: 'User'
}];
};

const Activity = mongoose.model('Activity', activitySchema);

module.exports = Activity;
8 changes: 1 addition & 7 deletions app/routes/api/project/activity.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,7 @@ const Middleware = require(__dirname + '/../../../lib/middleware');

module.exports = function (projectRouter) {

const activityPopulateOptions = [{
path: 'actor',
model: 'User'
}, {
path: 'data.user',
model: 'User'
}];
const activityPopulateOptions = Activity.getPopulateOptions();

const activityRouter = new Router({ prefix: '/:project/activities' });

Expand Down
2 changes: 2 additions & 0 deletions app/routes/api/project/outcome.js
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,8 @@ module.exports = function (projectRouter, config) {
}
});

// TODO This should run a query to remove any connections between for tasks
// It might also be needed to notify the front-end about the change (unless the logic is implemented there)
outcomeRouter.delete('/:outcome', Auth.ensureAuthenticated, Auth.ensureUser, Middleware.ensureActiveProjectParticipant, function *() {
let outcome;

Expand Down
2 changes: 2 additions & 0 deletions app/routes/api/project/resource.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,8 @@ module.exports = function (projectRouter, config) {
}
});

// TODO This should run a query to remove any connections between for tasks
// It might also be needed to notify the front-end about the change (unless the logic is implemented there)
resourceRouter.delete('/:resource', Auth.ensureAuthenticated, Auth.ensureUser, Middleware.ensureActiveProjectParticipant, function *() {
let resource;

Expand Down
12 changes: 6 additions & 6 deletions app/routes/api/project/task.js
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ module.exports = function (projectRouter) {

task = yield Task.populate(task, taskPopulateOptions);

this.emitApiAction('update', 'task', task, this.user);
this.emitApiAction('attach', 'participant', { task: task, participant: participant }, this.user);

this.apiRespond(task);
} catch(err) {
Expand Down Expand Up @@ -252,7 +252,7 @@ module.exports = function (projectRouter) {

task = yield Task.populate(task, taskPopulateOptions);

this.emitApiAction('update', 'task', task, this.user);
this.emitApiAction('detach', 'participant', { task: task, participant: participant }, this.user);

this.apiRespond(task);
} catch(err) {
Expand Down Expand Up @@ -307,7 +307,7 @@ module.exports = function (projectRouter) {

task = yield Task.populate(task, taskPopulateOptions);

this.emitApiAction('update', 'task', task, this.user);
this.emitApiAction('attach', 'resource', { task: task, resource: resource }, this.user);

this.apiRespond(task);
} catch(err) {
Expand Down Expand Up @@ -361,7 +361,7 @@ module.exports = function (projectRouter) {

task = yield Task.populate(task, taskPopulateOptions);

this.emitApiAction('update', 'task', task, this.user);
this.emitApiAction('detach', 'resource', { task: task, resource: resource }, this.user);

this.apiRespond(task);
} catch(err) {
Expand Down Expand Up @@ -415,7 +415,7 @@ module.exports = function (projectRouter) {

task = yield Task.populate(task, taskPopulateOptions);

this.emitApiAction('update', 'task', task, this.user);
this.emitApiAction('attach', 'outcome', { task: task, outcome: outcome }, this.user);

this.apiRespond(task);
} catch(err) {
Expand Down Expand Up @@ -469,7 +469,7 @@ module.exports = function (projectRouter) {

task = yield Task.populate(task, taskPopulateOptions);

this.emitApiAction('update', 'task', task, this.user);
this.emitApiAction('detach', 'outcome', { task: task, outcome: outcome }, this.user);

this.apiRespond(task);
} catch(err) {
Expand Down
42 changes: 41 additions & 1 deletion app/socket.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,11 @@ module.exports = function (app) {
return decodedToken.sub;
}

function extractModelFromData(data) {
function extractModelFromData(data, key) {
if ( key ) {
return data.data[key];
}

return data.data;
}
io.attach(app);
Expand Down Expand Up @@ -411,4 +415,40 @@ module.exports = function (app) {
const participant = extractModelFromData(data);
app._io.in(participant.project).emit('update:participant', participant);
});

app.on('attach:participant', function(data) {
const participant = extractModelFromData(data, 'participant');
const task = extractModelFromData(data, 'task');
app._io.in(participant.project).emit('update:task', task);
});

app.on('detach:participant', function(data) {
const participant = extractModelFromData(data, 'participant');
const task = extractModelFromData(data, 'task');
app._io.in(participant.project).emit('update:task', task);
});

app.on('attach:resource', function(data) {
const resource = extractModelFromData(data, 'resource');
const task = extractModelFromData(data, 'task');
app._io.in(resource.project).emit('update:task', task);
});

app.on('detach:resource', function(data) {
const resource = extractModelFromData(data, 'resource');
const task = extractModelFromData(data, 'task');
app._io.in(resource.project).emit('update:task', task);
});

app.on('attach:outcome', function(data) {
const outcome = extractModelFromData(data, 'outcome');
const task = extractModelFromData(data, 'task');
app._io.in(outcome.project).emit('update:task', task);
});

app.on('detach:outcome', function(data) {
const outcome = extractModelFromData(data, 'outcome');
const task = extractModelFromData(data, 'task');
app._io.in(outcome.project).emit('update:task', task);
});
};

0 comments on commit 35fe845

Please sign in to comment.