mirror of
https://github.com/vale981/Vulcan
synced 2025-03-06 10:01:40 -05:00
Merge branch 'Kestanous-herald-integration'
This commit is contained in:
commit
c46cf1cb24
13 changed files with 197 additions and 176 deletions
|
@ -46,6 +46,8 @@ jparker:crypto-core@0.1.0
|
|||
jparker:crypto-md5@0.1.1
|
||||
jquery@1.0.0
|
||||
json@1.0.0
|
||||
kestanous:herald-email@0.2.1
|
||||
kestanous:herald@0.6.0
|
||||
less@1.0.9
|
||||
livedata@1.0.10
|
||||
localstorage@1.0.0
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
// Notifications - only load if user is logged in
|
||||
// Not mandatory, because server won't publish anything even if we try to load.
|
||||
// Remember about Deps.autorun - user can log in and log out several times
|
||||
Tracker.autorun(function() {
|
||||
// userId() can be changed before user(), because loading profile takes time
|
||||
if(Meteor.userId()) {
|
||||
Meteor.subscribe('notifications');
|
||||
}
|
||||
});
|
|
@ -3,17 +3,17 @@ Template[getTemplate('notificationItem')].helpers({
|
|||
return moment(this.timestamp).fromNow();
|
||||
},
|
||||
properties: function(){
|
||||
return this.properties;
|
||||
return this.data;
|
||||
},
|
||||
notificationHTML: function(){
|
||||
return buildSiteNotification(this);
|
||||
return this.message();
|
||||
}
|
||||
});
|
||||
|
||||
Template[getTemplate('notificationItem')].events({
|
||||
'click .action-link': function(event, instance){
|
||||
var notificationId=instance.data._id;
|
||||
Notifications.update(
|
||||
Herald.collection.update(
|
||||
{_id: notificationId},
|
||||
{
|
||||
$set:{
|
||||
|
|
|
@ -3,13 +3,13 @@ Template[getTemplate('notificationsMenu')].helpers({
|
|||
return getTemplate('notificationItem');
|
||||
},
|
||||
notifications: function(){
|
||||
return Notifications.find({userId: Meteor.userId(), read: false}, {sort: {timestamp: -1}});
|
||||
return Herald.collection.find({userId: Meteor.userId(), read: false}, {sort: {timestamp: -1}});
|
||||
},
|
||||
hasNotifications: function () {
|
||||
return !!Notifications.find({userId: Meteor.userId(), read: false}, {sort: {timestamp: -1}}).count();
|
||||
return !!Herald.collection.find({userId: Meteor.userId(), read: false}, {sort: {timestamp: -1}}).count();
|
||||
},
|
||||
notification_count: function(){
|
||||
var notifications=Notifications.find({userId: Meteor.userId(), read: false}).fetch();
|
||||
var notifications=Herald.collection.find({userId: Meteor.userId(), read: false}).fetch();
|
||||
if(notifications.length==0){
|
||||
return i18n.t('No notifications');
|
||||
}else if(notifications.length==1){
|
||||
|
@ -19,7 +19,7 @@ Template[getTemplate('notificationsMenu')].helpers({
|
|||
}
|
||||
},
|
||||
notification_class: function(){
|
||||
var notifications=Notifications.find({userId: Meteor.userId(), read: false}).fetch();
|
||||
var notifications=Herald.collection.find({userId: Meteor.userId(), read: false}).fetch();
|
||||
if(notifications.length==0)
|
||||
return 'no-notifications';
|
||||
}
|
||||
|
|
110
packages/telescope-notifications/lib/herald.js
Normal file
110
packages/telescope-notifications/lib/herald.js
Normal file
|
@ -0,0 +1,110 @@
|
|||
Herald.collection.deny({
|
||||
update: ! can.editById,
|
||||
remove: ! can.editById
|
||||
});
|
||||
|
||||
Meteor.startup(function () {
|
||||
// disable all email notifications when "emailNotifications" is set to false
|
||||
if (getSetting('emailNotifications', true)) {
|
||||
Herald.settings.overrides.email = false;
|
||||
} else {
|
||||
Herald.settings.overrides.email = true;
|
||||
};
|
||||
});
|
||||
|
||||
var commentEmail = function (userToNotify) {
|
||||
var notification = this;
|
||||
// put in setTimeout so it doesn't hold up the rest of the method
|
||||
Meteor.setTimeout(function () {
|
||||
notificationEmail = buildEmailNotification(notification);
|
||||
sendEmail(getEmail(userToNotify), notificationEmail.subject, notificationEmail.html);
|
||||
}, 1);
|
||||
}
|
||||
|
||||
Herald.addCourier('newPost', {
|
||||
media: {
|
||||
email: {
|
||||
emailRunner: function (user) {
|
||||
var p = getPostProperties(this.data);
|
||||
var subject = p.postAuthorName+' has created a new post: '+p.postTitle;
|
||||
var html = buildEmailTemplate(getEmailTemplate('emailNewPost')(p));
|
||||
sendEmail(getEmail(user), subject, html);
|
||||
}
|
||||
}
|
||||
}
|
||||
// message: function (user) { return 'email template?' }
|
||||
});
|
||||
|
||||
Herald.addCourier('newComment', {
|
||||
media: {
|
||||
onsite: {},
|
||||
email: {
|
||||
emailRunner: commentEmail
|
||||
}
|
||||
},
|
||||
message: {
|
||||
default: function (user) {
|
||||
return Blaze.toHTML(Blaze.With(this, function(){
|
||||
return Template[getTemplate('notificationNewComment')]
|
||||
}));
|
||||
}
|
||||
},
|
||||
transform: {
|
||||
profileUrl: function () {
|
||||
var user = Meteor.users.findOne(this.data.comment.userId);
|
||||
if(user)
|
||||
return getProfileUrl(user);
|
||||
},
|
||||
postCommentUrl: function () {
|
||||
return '/posts/'+ this.data.post._id;
|
||||
},
|
||||
author: function () {
|
||||
var user = Meteor.users.findOne(this.data.comment.userId);
|
||||
if(user)
|
||||
return getUserName(user);
|
||||
},
|
||||
postTitle: function () {
|
||||
return this.data.post.title;
|
||||
},
|
||||
url: function () {
|
||||
return /comments/ + this.comment._id;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Herald.addCourier('newReply', {
|
||||
media: {
|
||||
onsite: {},
|
||||
email: {
|
||||
emailRunner: commentEmail
|
||||
}
|
||||
},
|
||||
message: {
|
||||
default: function (user) {
|
||||
return Blaze.toHTML(Blaze.With(this, function(){
|
||||
return Template[getTemplate('notificationNewReply')]
|
||||
}));
|
||||
}
|
||||
},
|
||||
transform: {
|
||||
profileUrl: function () {
|
||||
var user = Meteor.users.findOne(this.data.comment.userId);
|
||||
if(user)
|
||||
return getProfileUrl(user);
|
||||
},
|
||||
postCommentUrl: function () {
|
||||
return '/posts/'+ this.data.post._id;
|
||||
},
|
||||
author: function () {
|
||||
var user = Meteor.users.findOne(this.data.comment.userId);
|
||||
if(user)
|
||||
return getUserName(user);
|
||||
},
|
||||
postTitle: function () {
|
||||
return this.data.post.title;
|
||||
},
|
||||
url: function () {
|
||||
return /comments/ + this.parentComment._id;
|
||||
}
|
||||
}
|
||||
});
|
|
@ -1,125 +1,24 @@
|
|||
Notifications = new Meteor.Collection('notifications');
|
||||
|
||||
// Notifications = new Meteor.Collection("notifications", {
|
||||
// schema: new SimpleSchema({
|
||||
// properties: {
|
||||
// type: Object
|
||||
// },
|
||||
// event: {
|
||||
// type: String
|
||||
// },
|
||||
// read: {
|
||||
// type: Boolean
|
||||
// },
|
||||
// createdAt: {
|
||||
// type: Date
|
||||
// },
|
||||
// userId: {
|
||||
// type: "???"
|
||||
// }
|
||||
// })
|
||||
// });
|
||||
|
||||
Notifications.allow({
|
||||
insert: function(userId, doc){
|
||||
// new notifications can only be created via a Meteor method
|
||||
return false;
|
||||
},
|
||||
update: can.editById,
|
||||
remove: can.editById
|
||||
});
|
||||
|
||||
createNotification = function(event, properties, userToNotify) {
|
||||
// 1. Store notification in database
|
||||
var notification = {
|
||||
timestamp: new Date().getTime(),
|
||||
userId: userToNotify._id,
|
||||
event: event,
|
||||
properties: properties,
|
||||
read: false
|
||||
};
|
||||
var newNotificationId = Notifications.insert(notification);
|
||||
|
||||
// 2. Send notification by email (if on server)
|
||||
if(Meteor.isServer && getUserSetting('notifications.replies', false, userToNotify)){
|
||||
// put in setTimeout so it doesn't hold up the rest of the method
|
||||
Meteor.setTimeout(function () {
|
||||
notificationEmail = buildEmailNotification(notification);
|
||||
sendEmail(getEmail(userToNotify), notificationEmail.subject, notificationEmail.html);
|
||||
}, 1);
|
||||
}
|
||||
};
|
||||
|
||||
buildSiteNotification = function (notification) {
|
||||
var event = notification.event,
|
||||
comment = notification.properties.comment,
|
||||
post = notification.properties.post,
|
||||
userToNotify = Meteor.users.findOne(notification.userId),
|
||||
template,
|
||||
html;
|
||||
|
||||
var properties = {
|
||||
profileUrl: getProfileUrlById(comment.userId),
|
||||
author: comment.author,
|
||||
postCommentUrl: getPostCommentUrl(post._id, comment._id),
|
||||
postTitle: post.title
|
||||
};
|
||||
|
||||
switch(event){
|
||||
case 'newReply':
|
||||
template = 'notificationNewReply';
|
||||
break;
|
||||
|
||||
case 'newComment':
|
||||
template = 'notificationNewComment';
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
html = Blaze.toHTML(Blaze.With(properties, function(){
|
||||
return Template[getTemplate(template)]
|
||||
}));
|
||||
|
||||
return html;
|
||||
};
|
||||
|
||||
Meteor.methods({
|
||||
markAllNotificationsAsRead: function() {
|
||||
Notifications.update(
|
||||
{userId: Meteor.userId()},
|
||||
{
|
||||
$set:{
|
||||
read: true
|
||||
}
|
||||
},
|
||||
{multi: true}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// add new post notification callback on post submit
|
||||
postAfterSubmitMethodCallbacks.push(function (post) {
|
||||
if(Meteor.isServer && !!getSetting('emailNotifications', true)){
|
||||
// we don't want emails to hold up the post submission, so we make the whole thing async with setTimeout
|
||||
Meteor.setTimeout(function () {
|
||||
newPostNotification(post, [post.userId])
|
||||
}, 1);
|
||||
if(Meteor.isServer){
|
||||
var userIds = Meteor.users.find({'profile.notifications.posts': 1}, {fields: {}}).map(function (user) {
|
||||
return user._id
|
||||
});
|
||||
Herald.createNotification(userIds, {courier: 'newPost', data: post})
|
||||
}
|
||||
return post;
|
||||
});
|
||||
|
||||
// add new comment notification callback on comment submit
|
||||
commentAfterSubmitMethodCallbacks.push(function (comment) {
|
||||
if(Meteor.isServer && !!getSetting('emailNotifications', true)){
|
||||
if(Meteor.isServer){
|
||||
|
||||
var parentCommentId = comment.parentCommentId;
|
||||
var user = Meteor.user();
|
||||
var post = Posts.findOne(comment.postId);
|
||||
var postUser = Meteor.users.findOne(post.userId);
|
||||
|
||||
var notificationProperties = {
|
||||
var notificationData = {
|
||||
comment: _.pick(comment, '_id', 'userId', 'author', 'body'),
|
||||
post: _.pick(post, '_id', 'title', 'url')
|
||||
};
|
||||
|
@ -129,23 +28,23 @@ commentAfterSubmitMethodCallbacks.push(function (comment) {
|
|||
var parentComment = Comments.findOne(parentCommentId);
|
||||
var parentUser = Meteor.users.findOne(parentComment.userId);
|
||||
|
||||
notificationProperties.parentComment = _.pick(parentComment, '_id', 'userId', 'author');
|
||||
notificationData.parentComment = _.pick(parentComment, '_id', 'userId', 'author');
|
||||
|
||||
// reply notification
|
||||
// do not notify users of their own actions (i.e. they're replying to themselves)
|
||||
if(parentUser._id != user._id)
|
||||
createNotification('newReply', notificationProperties, parentUser);
|
||||
Herald.createNotification(parentUser._id, {courier: 'newReply', data: notificationData})
|
||||
|
||||
// comment notification
|
||||
// if the original poster is different from the author of the parent comment, notify them too
|
||||
if(postUser._id != user._id && parentComment.userId != post.userId)
|
||||
createNotification('newComment', notificationProperties, postUser);
|
||||
Herald.createNotification(postUser._id, {courier: 'newComment', data: notificationData})
|
||||
|
||||
}else{
|
||||
// root comment
|
||||
// don't notify users of their own comments
|
||||
if(postUser._id != user._id)
|
||||
createNotification('newComment', notificationProperties, postUser);
|
||||
Herald.createNotification(postUser._id, {courier: 'newComment', data: notificationData})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -160,7 +59,7 @@ var emailNotifications = {
|
|||
defaultValue: true,
|
||||
autoform: {
|
||||
group: 'notifications',
|
||||
instructions: 'Enable email notifications for new posts and new comments.'
|
||||
instructions: 'Enable email notifications for new posts and new comments (requires restart).'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,10 +6,10 @@ getUnsubscribeLink = function(user){
|
|||
buildEmailNotification = function (notification) {
|
||||
|
||||
var subject, template;
|
||||
var post = notification.properties.post;
|
||||
var comment = notification.properties.comment;
|
||||
var post = notification.data.post;
|
||||
var comment = notification.data.comment;
|
||||
|
||||
switch(notification.event){
|
||||
switch(notification.courier){
|
||||
case 'newReply':
|
||||
subject = 'Someone replied to your comment on "'+post.title+'"';
|
||||
template = 'emailNewReply';
|
||||
|
@ -24,7 +24,7 @@ buildEmailNotification = function (notification) {
|
|||
break;
|
||||
}
|
||||
|
||||
var emailProperties = _.extend(notification.properties, {
|
||||
var emailProperties = _.extend(notification.data, {
|
||||
body: marked(comment.body),
|
||||
profileUrl: getProfileUrlById(comment.userId),
|
||||
postCommentUrl: getPostCommentUrl(post._id, comment._id),
|
||||
|
@ -42,20 +42,6 @@ buildEmailNotification = function (notification) {
|
|||
}
|
||||
};
|
||||
|
||||
newPostNotification = function(post, excludedIDs){
|
||||
var excludedIDs = typeof excludedIDs == 'undefined' ? [] : excludedIDs;
|
||||
var p = getPostProperties(post);
|
||||
var subject = p.postAuthorName+' has created a new post: '+p.postTitle;
|
||||
var html = buildEmailTemplate(getEmailTemplate('emailNewPost')(p));
|
||||
|
||||
// send a notification to every user according to their notifications settings
|
||||
Meteor.users.find({'profile.notifications.posts': 1}).forEach(function(user) {
|
||||
// don't send user a notification if their ID is in excludedIDs
|
||||
if(excludedIDs.indexOf(user._id) == -1)
|
||||
sendEmail(getEmail(user), subject, html);
|
||||
});
|
||||
};
|
||||
|
||||
Meteor.methods({
|
||||
unsubscribeUser : function(hash){
|
||||
// TO-DO: currently, if you have somebody's email you can unsubscribe them
|
||||
|
|
|
@ -1,7 +0,0 @@
|
|||
Meteor.publish('notifications', function() {
|
||||
// only publish notifications belonging to the current user
|
||||
if(canViewById(this.userId)){
|
||||
return Notifications.find({userId:this.userId});
|
||||
}
|
||||
return [];
|
||||
});
|
|
@ -10,13 +10,14 @@ Package.onUse(function (api) {
|
|||
'telescope-lib',
|
||||
'telescope-base',
|
||||
'telescope-email',
|
||||
'aldeed:simple-schema'
|
||||
'kestanous:herald@0.6.0',
|
||||
'kestanous:herald-email@0.2.1'
|
||||
], ['client', 'server']);
|
||||
|
||||
api.use([
|
||||
'iron:router',
|
||||
'jquery',
|
||||
'underscore',
|
||||
'iron:router',
|
||||
'templating',
|
||||
'tracker'
|
||||
], 'client');
|
||||
|
@ -27,10 +28,10 @@ Package.onUse(function (api) {
|
|||
|
||||
api.add_files([
|
||||
'lib/notifications.js',
|
||||
'lib/herald.js'
|
||||
], ['client', 'server']);
|
||||
|
||||
api.add_files([
|
||||
'lib/client/notifications-client.js',
|
||||
'lib/client/templates/notification_item.html',
|
||||
'lib/client/templates/notification_item.js',
|
||||
'lib/client/templates/notification_new_comment.html',
|
||||
|
@ -42,18 +43,13 @@ Package.onUse(function (api) {
|
|||
], ['client']);
|
||||
|
||||
api.add_files([
|
||||
'lib/server/notifications-server.js',
|
||||
'lib/server/publication.js'
|
||||
'lib/server/notifications-server.js'
|
||||
], ['server']);
|
||||
|
||||
api.export([
|
||||
'Notifications',
|
||||
'createNotification',
|
||||
'buildSiteNotification',
|
||||
'newPostNotification',
|
||||
'Herald',
|
||||
'buildEmailNotification',
|
||||
'getUnsubscribeLink',
|
||||
'postSubmitMethodCallbacks'
|
||||
'getUnsubscribeLink'
|
||||
]);
|
||||
});
|
||||
|
||||
|
|
|
@ -1,13 +1,13 @@
|
|||
{
|
||||
"dependencies": [
|
||||
[
|
||||
"aldeed:simple-schema",
|
||||
"1.0.3"
|
||||
],
|
||||
[
|
||||
"application-configuration",
|
||||
"1.0.2"
|
||||
],
|
||||
[
|
||||
"autoupdate",
|
||||
"1.1.1"
|
||||
],
|
||||
[
|
||||
"base64",
|
||||
"1.0.0"
|
||||
|
@ -52,6 +52,10 @@
|
|||
"ejson",
|
||||
"1.0.3"
|
||||
],
|
||||
[
|
||||
"fastclick",
|
||||
"1.0.0"
|
||||
],
|
||||
[
|
||||
"follower-livedata",
|
||||
"1.0.1"
|
||||
|
@ -72,6 +76,10 @@
|
|||
"htmljs",
|
||||
"1.0.1"
|
||||
],
|
||||
[
|
||||
"http",
|
||||
"1.0.6"
|
||||
],
|
||||
[
|
||||
"id-map",
|
||||
"1.0.0"
|
||||
|
@ -100,6 +108,18 @@
|
|||
"json",
|
||||
"1.0.0"
|
||||
],
|
||||
[
|
||||
"kestanous:herald",
|
||||
"0.6.0"
|
||||
],
|
||||
[
|
||||
"kestanous:herald-email",
|
||||
"0.2.1"
|
||||
],
|
||||
[
|
||||
"livedata",
|
||||
"1.0.10"
|
||||
],
|
||||
[
|
||||
"logging",
|
||||
"1.0.3"
|
||||
|
@ -108,6 +128,10 @@
|
|||
"meteor",
|
||||
"1.1.1"
|
||||
],
|
||||
[
|
||||
"meteor-platform",
|
||||
"1.1.1"
|
||||
],
|
||||
[
|
||||
"minifiers",
|
||||
"1.1.0"
|
||||
|
@ -116,6 +140,10 @@
|
|||
"minimongo",
|
||||
"1.0.3"
|
||||
],
|
||||
[
|
||||
"mobile-status-bar",
|
||||
"1.0.0"
|
||||
],
|
||||
[
|
||||
"mongo",
|
||||
"1.0.6"
|
||||
|
@ -140,6 +168,10 @@
|
|||
"reactive-var",
|
||||
"1.0.2"
|
||||
],
|
||||
[
|
||||
"reload",
|
||||
"1.1.0"
|
||||
],
|
||||
[
|
||||
"retry",
|
||||
"1.0.0"
|
||||
|
@ -148,6 +180,10 @@
|
|||
"routepolicy",
|
||||
"1.0.1"
|
||||
],
|
||||
[
|
||||
"session",
|
||||
"1.0.2"
|
||||
],
|
||||
[
|
||||
"spacebars",
|
||||
"1.0.2"
|
||||
|
@ -156,6 +192,10 @@
|
|||
"spacebars-compiler",
|
||||
"1.0.2"
|
||||
],
|
||||
[
|
||||
"standard-app-packages",
|
||||
"1.0.2"
|
||||
],
|
||||
[
|
||||
"telescope-base",
|
||||
"0.0.0"
|
||||
|
@ -188,6 +228,10 @@
|
|||
"underscore",
|
||||
"1.0.0"
|
||||
],
|
||||
[
|
||||
"url",
|
||||
"1.0.0"
|
||||
],
|
||||
[
|
||||
"webapp",
|
||||
"1.1.2"
|
||||
|
|
Loading…
Add table
Reference in a new issue