From f07571d79de1c00529136cd74c075ddfc4784b41 Mon Sep 17 00:00:00 2001 From: enahum Date: Mon, 27 Feb 2017 17:55:12 -0300 Subject: PLT-3193 Add channel notification preferences for push notifications (#5512) * PLT-3193 Add channel notification preferences for push and email notifications * Fixing UI * Removing email as preferences from the UI for now * move to action * fix client test --- webapp/actions/channel_actions.jsx | 8 +- webapp/components/channel_notifications_modal.jsx | 262 ++++++++++++++++++--- .../user_settings/email_notification_setting.jsx | 26 +- webapp/i18n/en.json | 2 + webapp/utils/constants.jsx | 5 +- 5 files changed, 254 insertions(+), 49 deletions(-) diff --git a/webapp/actions/channel_actions.jsx b/webapp/actions/channel_actions.jsx index 5f41d127d..582de54cc 100644 --- a/webapp/actions/channel_actions.jsx +++ b/webapp/actions/channel_actions.jsx @@ -316,9 +316,13 @@ export function autocompleteChannels(term, success, error) { ); } -export function updateChannelNotifyProps(data, success, error) { - Client.updateChannelNotifyProps(data, +export function updateChannelNotifyProps(data, options, success, error) { + Client.updateChannelNotifyProps(Object.assign({}, data, options), () => { + const member = ChannelStore.getMyMember(data.channel_id); + member.notify_props = Object.assign(member.notify_props, options); + ChannelStore.storeMyChannelMember(member); + if (success) { success(); } diff --git a/webapp/components/channel_notifications_modal.jsx b/webapp/components/channel_notifications_modal.jsx index 58ab9143f..e78755fe3 100644 --- a/webapp/components/channel_notifications_modal.jsx +++ b/webapp/components/channel_notifications_modal.jsx @@ -4,8 +4,6 @@ import SettingItemMin from 'components/setting_item_min.jsx'; import SettingItemMax from 'components/setting_item_max.jsx'; -import ChannelStore from 'stores/channel_store.jsx'; - import $ from 'jquery'; import React from 'react'; import {Modal} from 'react-bootstrap'; @@ -20,19 +18,24 @@ export default class ChannelNotificationsModal extends React.Component { this.updateSection = this.updateSection.bind(this); this.onHide = this.onHide.bind(this); - this.handleSubmitNotifyLevel = this.handleSubmitNotifyLevel.bind(this); - this.handleUpdateNotifyLevel = this.handleUpdateNotifyLevel.bind(this); - this.createNotifyLevelSection = this.createNotifyLevelSection.bind(this); + this.handleSubmitDesktopNotifyLevel = this.handleSubmitDesktopNotifyLevel.bind(this); + this.handleUpdateDesktopNotifyLevel = this.handleUpdateDesktopNotifyLevel.bind(this); + this.createDesktopNotifyLevelSection = this.createDesktopNotifyLevelSection.bind(this); this.handleSubmitMarkUnreadLevel = this.handleSubmitMarkUnreadLevel.bind(this); this.handleUpdateMarkUnreadLevel = this.handleUpdateMarkUnreadLevel.bind(this); this.createMarkUnreadLevelSection = this.createMarkUnreadLevelSection.bind(this); + this.handleSubmitPushNotificationLevel = this.handleSubmitPushNotificationLevel.bind(this); + this.handleUpdatePushNotificationLevel = this.handleUpdatePushNotificationLevel.bind(this); + this.createPushNotificationLevelSection = this.createPushNotificationLevelSection.bind(this); + this.state = { activeSection: '', show: true, notifyLevel: props.channelMember.notify_props.desktop, - unreadLevel: props.channelMember.notify_props.mark_unread + unreadLevel: props.channelMember.notify_props.mark_unread, + pushLevel: props.channelMember.notify_props.push || 'default' }; } @@ -47,7 +50,7 @@ export default class ChannelNotificationsModal extends React.Component { this.setState({show: false}); } - handleSubmitNotifyLevel() { + handleSubmitDesktopNotifyLevel() { const channelId = this.props.channel.id; const notifyLevel = this.state.notifyLevel; const currentUserId = this.props.currentUser.id; @@ -57,19 +60,14 @@ export default class ChannelNotificationsModal extends React.Component { return; } + const options = {desktop: notifyLevel}; const data = { channel_id: channelId, - user_id: currentUserId, - desktop: notifyLevel + user_id: currentUserId }; - updateChannelNotifyProps(data, + updateChannelNotifyProps(data, options, () => { - // YUCK - var member = ChannelStore.getMyMember(channelId); - member.notify_props.desktop = notifyLevel; - ChannelStore.storeMyChannelMember(member); - this.updateSection(''); }, (err) => { @@ -78,11 +76,11 @@ export default class ChannelNotificationsModal extends React.Component { ); } - handleUpdateNotifyLevel(notifyLevel) { + handleUpdateDesktopNotifyLevel(notifyLevel) { this.setState({notifyLevel}); } - createNotifyLevelSection(serverError) { + createDesktopNotifyLevelSection(serverError) { // Get glabal user setting for notifications const globalNotifyLevel = this.props.currentUser.notify_props ? this.props.currentUser.notify_props.desktop : 'all'; let globalNotifyLevelName; @@ -140,7 +138,7 @@ export default class ChannelNotificationsModal extends React.Component { type='radio' name='desktopNotificationLevel' checked={notifyActive[0]} - onChange={this.handleUpdateNotifyLevel.bind(this, 'default')} + onChange={this.handleUpdateDesktopNotifyLevel.bind(this, 'default')} /> @@ -170,7 +168,7 @@ export default class ChannelNotificationsModal extends React.Component { type='radio' name='desktopNotificationLevel' checked={notifyActive[2]} - onChange={this.handleUpdateNotifyLevel.bind(this, 'mention')} + onChange={this.handleUpdateDesktopNotifyLevel.bind(this, 'mention')} /> @@ -182,7 +180,7 @@ export default class ChannelNotificationsModal extends React.Component { type='radio' name='desktopNotificationLevel' checked={notifyActive[3]} - onChange={this.handleUpdateNotifyLevel.bind(this, 'none')} + onChange={this.handleUpdateDesktopNotifyLevel.bind(this, 'none')} /> @@ -208,7 +206,7 @@ export default class ChannelNotificationsModal extends React.Component { { - // Yuck... - var member = ChannelStore.getMyMember(channelId); - member.notify_props.mark_unread = markUnreadLevel; - ChannelStore.storeMyChannelMember(member); this.updateSection(''); }, (err) => { @@ -375,8 +369,213 @@ export default class ChannelNotificationsModal extends React.Component { return content; } + handleSubmitPushNotificationLevel() { + const channelId = this.props.channel.id; + const notifyLevel = this.state.pushLevel; + const currentUserId = this.props.currentUser.id; + + if (this.props.channelMember.notify_props.push === notifyLevel) { + this.updateSection(''); + return; + } + + const options = {push: notifyLevel}; + const data = { + channel_id: channelId, + user_id: currentUserId + }; + + updateChannelNotifyProps(data, options, + () => { + this.updateSection(''); + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + } + + handleUpdatePushNotificationLevel(pushLevel) { + this.setState({pushLevel}); + } + + createPushNotificationLevelSection(serverError) { + if (global.mm_config.SendPushNotifications === 'false') { + return null; + } + + // Get glabal user setting for notifications + const globalNotifyLevel = this.props.currentUser.notify_props ? this.props.currentUser.notify_props.push : 'all'; + let globalNotifyLevelName; + if (globalNotifyLevel === 'all') { + globalNotifyLevelName = ( + + ); + } else if (globalNotifyLevel === 'mention') { + globalNotifyLevelName = ( + + ); + } else { + globalNotifyLevelName = ( + + ); + } + + const sendPushNotifications = ( + + ); + + const notificationLevel = this.state.pushLevel; + + let content; + if (this.state.activeSection === 'push') { + const notifyActive = [false, false, false, false]; + if (notificationLevel === 'default') { + notifyActive[0] = true; + } else if (notificationLevel === 'all') { + notifyActive[1] = true; + } else if (notificationLevel === 'mention') { + notifyActive[2] = true; + } else { + notifyActive[3] = true; + } + + const inputs = []; + + inputs.push( +
+
+ +
+
+
+ +
+
+
+ +
+
+
+ +
+
+ ); + + const handleUpdateSection = function updateSection(e) { + this.updateSection(''); + e.preventDefault(); + }.bind(this); + + const extraInfo = ( + + + + ); + + content = ( + + ); + } else { + let describe; + if (notificationLevel === 'default') { + describe = ( + + ); + } else if (notificationLevel === 'mention') { + describe = (); + } else if (notificationLevel === 'all') { + describe = (); + } else { + describe = (); + } + + content = ( + { + this.updateSection('push'); + }} + /> + ); + } + + return ( +
+
+ {content} +
+ ); + } + render() { - var serverError = null; + let serverError = null; if (this.state.serverError) { serverError =
; } @@ -406,7 +605,8 @@ export default class ChannelNotificationsModal extends React.Component { >
- {this.createNotifyLevelSection(serverError)} + {this.createDesktopNotifyLevelSection(serverError)} + {this.createPushNotificationLevelSection(serverError)}
{this.createMarkUnreadLevelSection(serverError)}
diff --git a/webapp/components/user_settings/email_notification_setting.jsx b/webapp/components/user_settings/email_notification_setting.jsx index a8319de29..457512507 100644 --- a/webapp/components/user_settings/email_notification_setting.jsx +++ b/webapp/components/user_settings/email_notification_setting.jsx @@ -13,10 +13,6 @@ import SettingItemMax from 'components/setting_item_max.jsx'; import {Preferences} from 'utils/constants.jsx'; -const INTERVAL_IMMEDIATE = 30; // "immediate" is a 30 second interval -const INTERVAL_FIFTEEN_MINUTES = 15 * 60; -const INTERVAL_HOUR = 60 * 60; - export default class EmailNotificationSetting extends React.Component { static propTypes = { activeSection: React.PropTypes.string.isRequired, @@ -36,7 +32,7 @@ export default class EmailNotificationSetting extends React.Component { this.collapse = this.collapse.bind(this); this.state = { - emailInterval: PreferenceStore.getInt(Preferences.CATEGORY_NOTIFICATIONS, Preferences.EMAIL_INTERVAL, INTERVAL_IMMEDIATE) + emailInterval: PreferenceStore.getInt(Preferences.CATEGORY_NOTIFICATIONS, Preferences.EMAIL_INTERVAL, Preferences.INTERVAL_IMMEDIATE) }; } @@ -66,7 +62,7 @@ export default class EmailNotificationSetting extends React.Component { if (this.props.enableEmail) { switch (this.state.emailInterval) { - case INTERVAL_IMMEDIATE: + case Preferences.INTERVAL_IMMEDIATE: description = ( ); break; - case INTERVAL_HOUR: + case Preferences.INTERVAL_HOUR: description = (
@@ -134,8 +130,8 @@ export default class EmailNotificationSetting extends React.Component {