Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[NEW] Add admin and user setting for notifications #4339

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
b9567f1
Add setting to set default notification alert level
alexbrazier Sep 17, 2016
a37e0d9
Add user preference for notifications
alexbrazier Sep 17, 2016
ac216b9
Add user preference for mobile notifications
alexbrazier Sep 17, 2016
997ab78
Change user notification preference string
alexbrazier Sep 17, 2016
3cc4ffb
Fix linting issues
alexbrazier Sep 17, 2016
4693c2d
Merge branch 'develop' into feature/default-notifications
alexbrazier Sep 17, 2016
a82ddbd
Add setting to disable notifications for all messages in large channels
alexbrazier Sep 18, 2016
81ffe23
Optimise queries for notifications
alexbrazier Sep 18, 2016
3f0af31
Optimise mongo query for large databases
alexbrazier Sep 18, 2016
060a64c
Merge branch 'develop' into feature/default-notifications
alexbrazier Sep 19, 2016
ff797c9
Merge branch 'develop' into feature/default-notifications
alexbrazier Oct 19, 2016
80dcfef
Update admin setting notification description to make it more clear
alexbrazier Oct 19, 2016
bd4e765
Merge branch 'develop' into feature/default-notifications
alexbrazier Dec 20, 2016
ec71055
Fix issue with notifications
alexbrazier Dec 20, 2016
ba79995
Merge branch 'develop' into feature/default-notifications
alexbrazier Jan 11, 2017
5825a26
Merge branch 'develop' into feature/default-notifications
alexbrazier Jan 28, 2017
16fb575
Merge branch 'develop' into feature/default-notifications
alexbrazier Feb 9, 2017
d57c907
Change lets to consts
alexbrazier Feb 9, 2017
883ac2a
Merge branch 'develop' into feature/default-notifications
alexbrazier Mar 7, 2017
9cd748b
Merge branch 'develop' into feature/default-notifications
alexbrazier Apr 2, 2017
42f668d
Merge branch 'develop' into pr/4339-alexbrazier-feature/default-notif…
marceloschmidt May 10, 2017
02541bb
Fix linting issues
alexbrazier May 14, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 7 additions & 2 deletions packages/rocketchat-i18n/i18n/en.i18n.json
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,7 @@
"Desktop": "Desktop",
"Desktop_Notification_Test": "Desktop Notification Test",
"Desktop_Notifications": "Desktop Notifications",
"Desktop_Notifications_Default_Alert" : "Desktop Notifications Default Alert",
"Desktop_Notifications_Disabled": "Desktop Notifications are Disabled. Change your browser preferences if you need Notifications enabled.",
"Desktop_Notifications_Duration": "Desktop Notifications Duration",
"Desktop_Notifications_Duration_Description": "Seconds to display desktop notification. This may affect OS X Notification Center. Enter 0 to use default browser settings and not affect OS X Notification Center.",
Expand Down Expand Up @@ -965,7 +966,6 @@
"Max_length_is": "Max length is %s",
"Members_List": "Members List",
"Mentions": "Mentions",
"Mentions_default": "Mentions (default)",
"Message": "Message",
"Message_AllowBadWordsFilter": "Allow Message bad words filtering",
"Message_AllowDeleting": "Allow Message Deleting",
Expand Down Expand Up @@ -1029,6 +1029,7 @@
"Min_length_is": "Min length is %s",
"minutes": "minutes",
"Mobile": "Mobile",
"Mobile_Notifications_Default_Alert" : "Mobile Notifications Default Alert",
"Monday": "Monday",
"Monitor_history_for_changes_on": "Monitor history for changes on",
"More_channels": "More channels",
Expand Down Expand Up @@ -1085,9 +1086,13 @@
"Not_found_or_not_allowed": "Not Found or Not Allowed",
"Nothing": "Nothing",
"Nothing_found": "Nothing found",
"Notification_Desktop_Default_For" : "Show Desktop Notifications For",
"Notification_Mobile_Default_For" : "Push Mobile Notifications For",
"Notification_Duration": "Notification Duration",
"Notifications": "Notifications",
"Notifications_Muted_Description": "If you choose to mute everything, you won't see the room highlight in the list when there are new messages, except for mentions. Muting notifications will override notifications settings.",
"Notifications_Max_Room_Members" : "Max room members before disabling all message notifications",
"Notifications_Max_Room_Members_Description" : "Max number of members in room when notifications for all messages gets disabled. Users can still change per room setting to receive all notifications on an individual basis. (0 to disable)",
"Notify_all_in_this_room": "Notify all in this room",
"Notify_active_in_this_room": "Notify active users in this room",
"Num_Agents": "# Agents",
Expand Down Expand Up @@ -1719,4 +1724,4 @@
"your_message_optional": "your message (optional)",
"Your_password_is_wrong": "Your password is wrong!",
"Your_push_was_sent_to_s_devices": "Your push was sent to %s devices"
}
}
33 changes: 27 additions & 6 deletions packages/rocketchat-lib/server/lib/sendNotificationsOnMessage.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,20 +64,41 @@ RocketChat.callbacks.add('afterSaveMessage', function(message, room) {
settings.dontNotifyMobileUsers = [];
settings.desktopNotificationDurations = {};

const notificationPreferencesByRoom = RocketChat.models.Subscriptions.findNotificationPreferencesByRoom(room._id);
notificationPreferencesByRoom.forEach(function(subscription) {
// Don't fetch all users if room exceeds max members
const maxMembersForNotification = RocketChat.settings.get('Notifications_Max_Room_Members');
const disableAllMessageNotifications = room.usernames.length > maxMembersForNotification && maxMembersForNotification !== 0;
const subscriptions = RocketChat.models.Subscriptions.findNotificationPreferencesByRoom(room._id, disableAllMessageNotifications);
const userIds = [];
subscriptions.forEach((s) => {
userIds.push(s.u._id);
});
const userSettings = {};
RocketChat.models.Users.findUsersByIds(userIds, { fields: { 'settings.preferences.desktopNotifications': 1, 'settings.preferences.mobileNotifications': 1 } }).forEach((user) => {
userSettings[user._id] = user.settings;
});

subscriptions.forEach((subscription) => {
if (subscription.disableNotifications) {
settings.dontNotifyDesktopUsers.push(subscription.u._id);
settings.dontNotifyMobileUsers.push(subscription.u._id);
} else {
if (subscription.desktopNotifications === 'all') {
const preferences = userSettings[subscription.u._id] ? userSettings[subscription.u._id].preferences || {} : {};
const userDesktopNotificationPreference = preferences.desktopNotifications !== 'default' ? preferences.desktopNotifications : undefined;
const userMobileNotificationPreference = preferences.mobileNotifications !== 'default' ? preferences.mobileNotifications : undefined;
// Set defaults if they don't exist
const {
desktopNotifications = userDesktopNotificationPreference || RocketChat.settings.get('Desktop_Notifications_Default_Alert'),
mobilePushNotifications = userMobileNotificationPreference || RocketChat.settings.get('Mobile_Notifications_Default_Alert')
} = subscription;

if (desktopNotifications === 'all' && !disableAllMessageNotifications) {
settings.alwaysNotifyDesktopUsers.push(subscription.u._id);
} else if (subscription.desktopNotifications === 'nothing') {
} else if (desktopNotifications === 'nothing') {
settings.dontNotifyDesktopUsers.push(subscription.u._id);
}
if (subscription.mobilePushNotifications === 'all') {
if (mobilePushNotifications === 'all' && !disableAllMessageNotifications) {
settings.alwaysNotifyMobileUsers.push(subscription.u._id);
} else if (subscription.mobilePushNotifications === 'nothing') {
} else if (mobilePushNotifications === 'nothing') {
settings.dontNotifyMobileUsers.push(subscription.u._id);
}
}
Expand Down
7 changes: 7 additions & 0 deletions packages/rocketchat-lib/server/models/Users.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,13 @@ class ModelUsers extends RocketChat.models._Base

return @find query, options

findUsersByIds: (ids, options) ->
query =
_id:
$in: ids

return @find query, options

# UPDATE
addImportIds: (_id, importIds) ->
importIds = [].concat(importIds)
Expand Down
33 changes: 32 additions & 1 deletion packages/rocketchat-lib/server/startup/settings.js
Original file line number Diff line number Diff line change
Expand Up @@ -413,11 +413,42 @@ RocketChat.settings.addGroup('General', function() {
});
});
this.section('Notifications', function() {
return this.add('Desktop_Notifications_Duration', 0, {
this.add('Desktop_Notifications_Duration', 0, {
type: 'int',
'public': true,
i18nDescription: 'Desktop_Notification_Durations_Description'
});
this.add('Desktop_Notifications_Default_Alert', 'all', {
type: 'select',
values: [{
key: 'all',
i18nLabel: 'All_messages'
}, {
key: 'mentions',
i18nLabel: 'Mentions'
}, {
key: 'nothing',
i18nLabel: 'Nothing'
}],
public: true
});

this.add('Mobile_Notifications_Default_Alert', 'mentions', {
type: 'select',
values: [{
key: 'all',
i18nLabel: 'All_messages'
}, {
key: 'mentions',
i18nLabel: 'Mentions'
}, {
key: 'nothing',
i18nLabel: 'Nothing'
}],
public: true
});

return this.add('Notifications_Max_Room_Members', 100, { type: 'int', public: true, i18nDescription: 'Notifications_Max_Room_Members_Description' });
});
this.section('REST API', function() {
return this.add('API_User_Limit', 500, {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,16 @@ <h2>{{_ "Notifications"}}</h2>
<label>{{_ "Desktop"}}</label>
<div>
{{#if editing 'desktopNotifications'}}
<label><input type="radio" name="desktopNotifications" value="default" checked="{{$eq desktopNotifications 'default'}}" /> {{_ "Default"}}</label>
<label><input type="radio" name="desktopNotifications" value="all" checked="{{$eq desktopNotifications 'all'}}" /> {{_ "All_messages"}}</label>
<label><input type="radio" name="desktopNotifications" value="mentions" checked="{{$eq desktopNotifications 'mentions'}}" /> {{_ "Mentions_default"}}</label>
<label><input type="radio" name="desktopNotifications" value="mentions" checked="{{$eq desktopNotifications 'mentions'}}" /> {{_ "Mentions"}}</label>
<label><input type="radio" name="desktopNotifications" value="nothing" checked="{{$eq desktopNotifications 'nothing'}}" /> {{_ "Nothing"}}</label>
<br />
{{#if desktopNotificationDuration}}
<label>{{_ "Duration"}} ({{_ "seconds"}}) <input type="number" name="duration" min="0" value="{{desktopNotificationDuration}}"></label>
<label>{{_ "Duration"}} ({{_ "seconds"}}) <input type="number" name="duration" min="0" value="{{desktopNotificationDuration}}" class="content-background-color"></label>
{{else}}
<label>{{_ "Duration"}} ({{_ "seconds"}}) <input type="number" name="duration" min="0" value="" placeholder="{{_ "Use_User_Preferences_or_Global_Settings"}}"></label>
{{/if}}

<button type="button" class="button cancel">{{_ "Cancel"}}</button>
<button type="button" class="button primary save">{{_ "Save"}}</button>
{{else}}
Expand All @@ -68,8 +68,9 @@ <h2>{{_ "Notifications"}}</h2>
<label>{{_ "Mobile"}}</label>
<div>
{{#if editing 'mobilePushNotifications'}}
<label><input type="radio" name="mobilePushNotifications" value="default" checked="{{$eq mobilePushNotifications 'default'}}" /> {{_ "Default"}}</label>
<label><input type="radio" name="mobilePushNotifications" value="all" checked="{{$eq mobilePushNotifications 'all'}}" /> {{_ "All_messages"}}</label>
<label><input type="radio" name="mobilePushNotifications" value="mentions" checked="{{$eq mobilePushNotifications 'mentions'}}" /> {{_ "Mentions_default"}}</label>
<label><input type="radio" name="mobilePushNotifications" value="mentions" checked="{{$eq mobilePushNotifications 'mentions'}}" /> {{_ "Mentions"}}</label>
<label><input type="radio" name="mobilePushNotifications" value="nothing" checked="{{$eq mobilePushNotifications 'nothing'}}" /> {{_ "Nothing"}}</label>
<button type="button" class="button cancel">{{_ "Cancel"}}</button>
<button type="button" class="button primary save">{{_ "Save"}}</button>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Template.pushNotificationsFlexTab.helpers({
desktopNotifications: 1
}
});
return sub ? sub.desktopNotifications : '';
return sub ? sub.desktopNotifications || 'default' : 'default';
},
mobilePushNotifications() {
const sub = ChatSubscription.findOne({
Expand All @@ -53,7 +53,7 @@ Template.pushNotificationsFlexTab.helpers({
mobilePushNotifications: 1
}
});
return sub ? sub.mobilePushNotifications : '';
return sub ? sub.mobilePushNotifications || 'default' : 'default';
},
emailNotifications() {
const sub = ChatSubscription.findOne({
Expand Down Expand Up @@ -144,11 +144,7 @@ Template.pushNotificationsFlexTab.helpers({
case 'mentions':
return t('Mentions');
default:
if (field === 'emailNotifications') {
return t('Use_account_preference');
} else {
return t('Mentions');
}
return t('Use_account_preference');
}
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@ RocketChat.models.Subscriptions.updateDesktopNotificationsById = function(_id, d
_id
};

const update = {
$set: {
desktopNotifications
}
};
const update = {};

if (desktopNotifications === 'default') {
update.$unset = { desktopNotifications: 1 };
} else {
update.$set = { desktopNotifications };
}

return this.update(query, update);
};
Expand All @@ -45,11 +47,13 @@ RocketChat.models.Subscriptions.updateMobilePushNotificationsById = function(_id
_id
};

const update = {
$set: {
mobilePushNotifications
}
};
const update = {};

if (mobilePushNotifications === 'default') {
update.$unset = { mobilePushNotifications: 1 };
} else {
update.$set = { mobilePushNotifications };
}

return this.update(query, update);
};
Expand Down Expand Up @@ -146,20 +150,23 @@ RocketChat.models.Subscriptions.findDontNotifyMobileUsersByRoomId = function(roo
return this.find(query);
};

RocketChat.models.Subscriptions.findNotificationPreferencesByRoom = function(roomId) {
RocketChat.models.Subscriptions.findNotificationPreferencesByRoom = function(roomId, explicit) {
const query = {
rid: roomId,
'u._id': {$exists: true},
$or: [
'u._id': {$exists: true}
};

if (explicit) {
query.$or = [
{audioNotification: {$exists: true}},
{desktopNotifications: {$exists: true}},
{desktopNotificationDuration: {$exists: true}},
{mobilePushNotifications: {$exists: true}},
{disableNotifications: {$exists: true}}
]
};
];
}

return this.find(query);
return this.find(query, { fields: { 'u._id': 1, desktopNotificationDuration: 1, desktopNotifications: 1, mobilePushNotifications: 1 } });
};

RocketChat.models.Subscriptions.findWithSendEmailByRoomId = function(roomId) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,8 @@ Template.accountPreferences.onCreated ->
data.emailNotificationMode = $('select[name=emailNotificationMode]').val()
data.highlights = _.compact(_.map($('[name=highlights]').val().split(','), (e) -> return _.trim(e)))
data.desktopNotificationDuration = $('input[name=desktopNotificationDuration]').val()
data.desktopNotifications = $('#desktopNotifications').find('select').val()
data.mobileNotifications = $('#mobileNotifications').find('select').val()
data.unreadAlert = $('#unreadAlert').find('input:checked').val()

Meteor.call 'saveUserPreferences', data, (error, results) ->
Expand Down
22 changes: 22 additions & 0 deletions packages/rocketchat-ui-account/client/accountPreferences.html
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,28 @@ <h1>{{_ "Messages"}}</h1>
{{/if}}
</div>
</div>
<div class="input-line double-col" id="desktopNotifications">
<label>{{_ "Notification_Desktop_Default_For"}}</label>
<div>
<select class="input-monitor" name="desktopNotifications">
<option value="default" selected="{{selected 'desktopNotifications' 'default' true}}">{{_ "Default"}}</option>
<option value="all" selected="{{selected 'desktopNotifications' 'all' false}}">{{_ "All_messages"}}</option>
<option value="mentions" selected="{{selected 'desktopNotifications' 'mentions' false}}">{{_ "Mentions"}}</option>
<option value="nothing" selected="{{selected 'desktopNotifications' 'nothing' false}}">{{_ "Nothing"}}</option>
</select>
</div>
</div>
<div class="input-line double-col" id="mobileNotifications">
<label>{{_ "Notification_Mobile_Default_For"}}</label>
<div>
<select class="input-monitor" name="mobileNotifications">
<option value="default" selected="{{selected 'mobileNotifications' 'default' true}}">{{_ "Default"}}</option>
<option value="all" selected="{{selected 'mobileNotifications' 'all' false}}">{{_ "All_messages"}}</option>
<option value="mentions" selected="{{selected 'mobileNotifications' 'mentions' false}}">{{_ "Mentions"}}</option>
<option value="nothing" selected="{{selected 'mobileNotifications' 'nothing' false}}">{{_ "Nothing"}}</option>
</select>
</div>
</div>
<div class="input-line double-col" id="unreadAlert">
<label>{{_ "Unread_Tray_Icon_Alert"}}</label>
<div>
Expand Down
8 changes: 8 additions & 0 deletions server/methods/saveUserPreferences.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,14 @@ Meteor.methods({
preferences.unreadAlert = settings.unreadAlert === '1' ? true : false;
}

if (settings.desktopNotifications) {
preferences.desktopNotifications = settings.desktopNotifications;
}

if (settings.mobileNotifications) {
preferences.mobileNotifications = settings.mobileNotifications;
}

preferences.desktopNotificationDuration = settings.desktopNotificationDuration - 0;
preferences.viewMode = settings.viewMode || 0;
preferences.hideUsernames = settings.hideUsernames === '1';
Expand Down