improving notifications

This commit is contained in:
Sacha Greif 2013-10-23 10:21:08 +08:00
parent 497f4ca502
commit 2cfbcd2360
9 changed files with 62 additions and 40 deletions

View file

@ -6,6 +6,9 @@ Setting = FormModel.extend({
requireViewInvite: false,
requirePostInvite: false,
requirePostsApproval: false,
emailNotifications: false,
nestedComments: false,
defaultEmail: '',
scoreUpdateInterval: '',
postInterval: '',
commentInterval: '',
@ -15,10 +18,6 @@ Setting = FormModel.extend({
logoUrl: '',
logoHeight: '',
logoWidth: '',
defaultEmail: '',
newPostsNotifications: false,
newRepliesNotifications: false,
nestedComments: false,
backgroundColor: '',
secondaryColor: '',
buttonColor: '',
@ -39,8 +38,9 @@ Setting = FormModel.extend({
init: function(options) {
this._super(Settings, options);
this.overwriteTitle('scoreUpdateInterval', 'Scoring Frequency');
this.overwriteTitle('requireViewInvite', 'Require Invite to view?');
this.overwriteTitle('requirePostInvite', 'Require Invite to post?');
this.overwriteTitle('requireViewInvite', 'Require invite to view?');
this.overwriteTitle('requirePostInvite', 'Require invite to post?');
this.overwriteTitle('emailNotifications', 'Enable email notifications?');
this.overwriteTitle('requirePostsApproval', 'Posts must be approved by admin?');
this.overwriteTitle('title', 'Site Title');
this.overwriteTitle('mixpanelId', '<a href="http://mixpanel.com/">Mixpanel</a> ID');

View file

@ -50,15 +50,15 @@
<div class="control-group">
<label class="control-label">Email Notifications</label>
<div class="controls">
<label class="radio">
<input id="notifications_activity" type="radio" value="1" name="notifications" {{hasNotificationsActivity}} /> When people reply to me
<label class="checkbox">
<input id="notifications_posts" type="checkbox" name="notifications_posts" {{hasNotificationsPosts}} /> New Posts
</label>
<label class="radio">
<input id="notifications_none" type="radio" value="0" name="notifications" {{hasNotificationsNone}} /> None
<label class="checkbox">
<input id="notifications_comments" type="checkbox" name="notifications_comments" {{hasNotificationsComments}} /> Comments on my posts
</label>
<label class="checkbox">
<input id="notifications_replies" type="checkbox" name="notifications_replies" {{hasNotificationsReplies}} /> Replies to my comments
</label>
<!-- <label class="radio">
<input id="notifications_all" type="radio" value="2" name="notifications" {{hasNotificationsAll}} /> All
</label> -->
</div>
</div>
<div class="form-actions">

View file

@ -5,14 +5,14 @@ Template.user_edit.helpers({
userEmail : function(){
return getEmail(this);
},
hasNotificationsNone : function(){
return this.profile && this.profile.notificationsFrequency == 0 ? 'checked' : '';
hasNotificationsPosts : function(){
return getUserSetting('notifications.posts') ? 'checked' : '';
},
hasNotificationsActivity : function(){
return this.profile && (this.profile.notificationsFrequency == 1 || typeof this.profile.notificationsFrequency === 'undefined') ? 'checked' : '';
hasNotificationsComments : function(){
return getUserSetting('notifications.comments') ? 'checked' : '';
},
hasNotificationsAll : function(){
return this.profile && this.profile.notificationsFrequency == 2 ? 'checked' : '';
hasNotificationsReplies : function(){
return getUserSetting('notifications.replies') ? 'checked' : '';
}
})
@ -30,7 +30,9 @@ Template.user_edit.events = {
"profile.name": $target.find('[name=name]').val(),
"profile.bio": $target.find('[name=bio]').val(),
"profile.email": $target.find('[name=email]').val(),
"profile.notificationsFrequency": parseInt($('input[name=notifications]:checked').val())
"profile.notifications.posts": $('input[name=notifications_posts]:checked').length,
"profile.notifications.comments": $('input[name=notifications_comments]:checked').length,
"profile.notifications.replies": $('input[name=notifications_replies]:checked').length
};
var old_password = $target.find('[name=old_password]').val();

View file

@ -41,7 +41,7 @@ Template.user_item.events({
if(error){
throwError();
}else{
Meteor.call('createNotification','accountApproved', {}, user);
Meteor.call('createNotification','accountApproved', {}, user, true);
}
});
},

View file

@ -17,7 +17,6 @@ Comments.deny({
Meteor.methods({
comment: function(postId, parentCommentId, text){
console.log('parentCommentId: '+parentCommentId)
var user = Meteor.user(),
post=Posts.findOne(postId),
postUser=Meteor.users.findOne(post.userId),
@ -56,8 +55,7 @@ Meteor.methods({
comment.parent = parentCommentId;
var newCommentId=Comments.insert(comment);
console.log(comment)
console.log(newCommentId)
Posts.update(postId, {$inc: {comments: 1}});
Meteor.call('upvoteComment', newCommentId);
@ -74,19 +72,21 @@ Meteor.methods({
properties.parentAuthorId = parentComment.userId;
properties.parentAuthorName = getDisplayName(parentUser);
// reply notification
// do not notify users of their own actions (i.e. they're replying to themselves)
if(parentUser._id != user._id)
Meteor.call('createNotification','newReply', properties, parentUser, user);
Meteor.call('createNotification','newReply', properties, parentUser, user, getUserSetting('notifications.replies', false, parentUser));
// 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)
Meteor.call('createNotification','newComment', properties, postUser, user);
Meteor.call('createNotification','newComment', properties, postUser, user, getUserSetting('notifications.comments', false, postUser));
}else{
// root comment
// don't notify users of their own comments
if(postUser._id != user._id)
Meteor.call('createNotification','newComment', properties, postUser, Meteor.user());
Meteor.call('createNotification','newComment', properties, postUser, Meteor.user(), getUserSetting('notifications.comments', false, postUser));
}
}
return properties;

View file

@ -83,8 +83,8 @@ Meteor.methods({
var postAuthor = Meteor.users.findOne(post.userId);
Meteor.call('upvotePost', postId,postAuthor);
if(getSetting('newPostsNotifications')){
// notify admin of new posts
if(getSetting('emailNotifications', false)){
// notify users of new posts
var properties = {
postAuthorName : getDisplayName(postAuthor),
postAuthorId : post.userId,
@ -93,7 +93,7 @@ Meteor.methods({
}
var notification = getNotification('newPost', properties);
// call a server method because we do not have access to admin users' info on the client
Meteor.call('notifyAdmins', notification, Meteor.user(), function(error, result){
Meteor.call('notifyUsers', notification, Meteor.user(), function(error, result){
//run asynchronously
});
}

View file

@ -76,4 +76,22 @@ numberOfItemsInPast24Hours = function(user, collection){
}
});
return items.count();
}
getUserSetting = function(setting, defaultValue, user){
var user = (typeof user == 'undefined') ? Meteor.user() : user;
var defaultValue = (typeof defaultValue == "undefined") ? null: defaultValue;
var settingValue = getProperty(user.profile, setting);
return (settingValue == null) ? defaultValue : settingValue;
}
getProperty = function(object, property){
// recursive function to get nested properties
var array = property.split('.');
if(array.length > 1){
var parent = array.shift();
// if our property is not at this level, call function again one level deeper if we can go deeper, else return null
return (typeof object[parent] == "undefined") ? null : getProperty(object[parent], array.join('.'))
}else{
// else return property
return object[array[0]];
}
}

View file

@ -1,8 +1,9 @@
sendEmail = function(to, subject, text, html){
// TO-DO: limit who can send emails
var from = getSetting('defaultEmail') || 'noreply@example.com';
// TODO: limit who can send emails
// TODO: fix this error: Error: getaddrinfo ENOTFOUND
var from = getSetting('defaultEmail', 'noreply@example.com');
var siteName = getSetting('title');
var subject = '['+siteName+'] '+subject

View file

@ -3,11 +3,12 @@ getUnsubscribeLink = function(user){
};
Meteor.methods({
createNotification: function(event, properties, userToNotify, userDoingAction){
createNotification: function(event, properties, userToNotify, userDoingAction, sendEmail){
// console.log('adding new notification for:'+getDisplayName(userToNotify)+', for event:'+event);
// console.log(userToNotify);
// console.log(userDoingAction);
// console.log(properties);
// console.log(sendEmail);
var notification= {
timestamp: new Date().getTime(),
userId: userToNotify._id,
@ -19,7 +20,7 @@ Meteor.methods({
// send the notification if notifications are activated,
// the notificationsFrequency is set to 1, or if it's undefined (legacy compatibility)
if(userToNotify.profile && (userToNotify.profile.notificationsFrequency === 1 || typeof userToNotify.profile.notificationsFrequency === 'undefined')){
if(sendEmail){
Meteor.call('sendNotificationEmail', userToNotify, newNotificationId);
}
},
@ -45,11 +46,11 @@ Meteor.methods({
}
return false;
},
notifyAdmins : function(notification, currentUser){
// send a notification to every site admin
_.each(adminUsers(), function(user, index, list){
if(user._id !== currentUser._id){
// don't send admins notifications for their own posts
notifyUsers : function(notification, currentUser){
// send a notification to every user according to their notifications settings
_.each(Meteor.users.find().fetch(), function(user, index, list){
if(user._id !== currentUser._id && getUserSetting('notifications.posts', false, user)){
// don't send users notifications for their own posts
sendEmail(getEmail(user), notification.subject, notification.text, notification.html);
}
});