From 98186e5018bbc604796d4f9762c93f4f75e2913f Mon Sep 17 00:00:00 2001 From: JoramWilander Date: Mon, 21 Sep 2015 14:22:23 -0400 Subject: Implement incoming webhooks. --- .../user_settings/user_settings_notifications.jsx | 697 +++++++++++++++++++++ 1 file changed, 697 insertions(+) create mode 100644 web/react/components/user_settings/user_settings_notifications.jsx (limited to 'web/react/components/user_settings/user_settings_notifications.jsx') diff --git a/web/react/components/user_settings/user_settings_notifications.jsx b/web/react/components/user_settings/user_settings_notifications.jsx new file mode 100644 index 000000000..fde4970ce --- /dev/null +++ b/web/react/components/user_settings/user_settings_notifications.jsx @@ -0,0 +1,697 @@ +// Copyright (c) 2015 Spinpunch, Inc. All Rights Reserved. +// See License.txt for license information. + +var UserStore = require('../../stores/user_store.jsx'); +var SettingItemMin = require('../setting_item_min.jsx'); +var SettingItemMax = require('../setting_item_max.jsx'); +var client = require('../../utils/client.jsx'); +var AsyncClient = require('../../utils/async_client.jsx'); +var utils = require('../../utils/utils.jsx'); +var assign = require('object-assign'); + +function getNotificationsStateFromStores() { + var user = UserStore.getCurrentUser(); + var soundNeeded = !utils.isBrowserFirefox(); + + var sound = 'true'; + if (user.notify_props && user.notify_props.desktop_sound) { + sound = user.notify_props.desktop_sound; + } + var desktop = 'all'; + if (user.notify_props && user.notify_props.desktop) { + desktop = user.notify_props.desktop; + } + var email = 'true'; + if (user.notify_props && user.notify_props.email) { + email = user.notify_props.email; + } + + var usernameKey = false; + var mentionKey = false; + var customKeys = ''; + var firstNameKey = false; + var allKey = false; + var channelKey = false; + + if (user.notify_props) { + if (user.notify_props.mention_keys) { + var keys = user.notify_props.mention_keys.split(','); + + if (keys.indexOf(user.username) !== -1) { + usernameKey = true; + keys.splice(keys.indexOf(user.username), 1); + } else { + usernameKey = false; + } + + if (keys.indexOf('@' + user.username) !== -1) { + mentionKey = true; + keys.splice(keys.indexOf('@' + user.username), 1); + } else { + mentionKey = false; + } + + customKeys = keys.join(','); + } + + if (user.notify_props.first_name) { + firstNameKey = user.notify_props.first_name === 'true'; + } + + if (user.notify_props.all) { + allKey = user.notify_props.all === 'true'; + } + + if (user.notify_props.channel) { + channelKey = user.notify_props.channel === 'true'; + } + } + + return {notifyLevel: desktop, enableEmail: email, soundNeeded: soundNeeded, enableSound: sound, + usernameKey: usernameKey, mentionKey: mentionKey, customKeys: customKeys, customKeysChecked: customKeys.length > 0, + firstNameKey: firstNameKey, allKey: allKey, channelKey: channelKey}; +} + +export default class NotificationsTab extends React.Component { + constructor(props) { + super(props); + + this.handleSubmit = this.handleSubmit.bind(this); + this.handleClose = this.handleClose.bind(this); + this.updateSection = this.updateSection.bind(this); + this.onListenerChange = this.onListenerChange.bind(this); + this.handleNotifyRadio = this.handleNotifyRadio.bind(this); + this.handleEmailRadio = this.handleEmailRadio.bind(this); + this.handleSoundRadio = this.handleSoundRadio.bind(this); + this.updateUsernameKey = this.updateUsernameKey.bind(this); + this.updateMentionKey = this.updateMentionKey.bind(this); + this.updateFirstNameKey = this.updateFirstNameKey.bind(this); + this.updateAllKey = this.updateAllKey.bind(this); + this.updateChannelKey = this.updateChannelKey.bind(this); + this.updateCustomMentionKeys = this.updateCustomMentionKeys.bind(this); + this.onCustomChange = this.onCustomChange.bind(this); + + this.state = getNotificationsStateFromStores(); + } + handleSubmit() { + var data = {}; + data.user_id = this.props.user.id; + data.email = this.state.enableEmail; + data.desktop_sound = this.state.enableSound; + data.desktop = this.state.notifyLevel; + + var mentionKeys = []; + if (this.state.usernameKey) { + mentionKeys.push(this.props.user.username); + } + if (this.state.mentionKey) { + mentionKeys.push('@' + this.props.user.username); + } + + var stringKeys = mentionKeys.join(','); + if (this.state.customKeys.length > 0 && this.state.customKeysChecked) { + stringKeys += ',' + this.state.customKeys; + } + + data.mention_keys = stringKeys; + data.first_name = this.state.firstNameKey.toString(); + data.all = this.state.allKey.toString(); + data.channel = this.state.channelKey.toString(); + + client.updateUserNotifyProps(data, + function success() { + this.props.updateSection(''); + AsyncClient.getMe(); + }.bind(this), + function failure(err) { + this.setState({serverError: err.message}); + }.bind(this) + ); + } + handleClose() { + $(React.findDOMNode(this)).find('.form-control').each(function clearField() { + this.value = ''; + }); + + this.setState(assign({}, getNotificationsStateFromStores(), {serverError: null})); + + this.props.updateTab('general'); + } + updateSection(section) { + this.setState(getNotificationsStateFromStores()); + this.props.updateSection(section); + } + componentDidMount() { + UserStore.addChangeListener(this.onListenerChange); + $('#user_settings').on('hidden.bs.modal', this.handleClose); + } + componentWillUnmount() { + UserStore.removeChangeListener(this.onListenerChange); + $('#user_settings').off('hidden.bs.modal', this.handleClose); + this.props.updateSection(''); + } + onListenerChange() { + var newState = getNotificationsStateFromStores(); + if (!utils.areStatesEqual(newState, this.state)) { + this.setState(newState); + } + } + handleNotifyRadio(notifyLevel) { + this.setState({notifyLevel: notifyLevel}); + React.findDOMNode(this.refs.wrapper).focus(); + } + handleEmailRadio(enableEmail) { + this.setState({enableEmail: enableEmail}); + React.findDOMNode(this.refs.wrapper).focus(); + } + handleSoundRadio(enableSound) { + this.setState({enableSound: enableSound}); + React.findDOMNode(this.refs.wrapper).focus(); + } + updateUsernameKey(val) { + this.setState({usernameKey: val}); + } + updateMentionKey(val) { + this.setState({mentionKey: val}); + } + updateFirstNameKey(val) { + this.setState({firstNameKey: val}); + } + updateAllKey(val) { + this.setState({allKey: val}); + } + updateChannelKey(val) { + this.setState({channelKey: val}); + } + updateCustomMentionKeys() { + var checked = React.findDOMNode(this.refs.customcheck).checked; + + if (checked) { + var text = React.findDOMNode(this.refs.custommentions).value; + + // remove all spaces and split string into individual keys + this.setState({customKeys: text.replace(/ /g, ''), customKeysChecked: true}); + } else { + this.setState({customKeys: '', customKeysChecked: false}); + } + } + onCustomChange() { + React.findDOMNode(this.refs.customcheck).checked = true; + this.updateCustomMentionKeys(); + } + render() { + var serverError = null; + if (this.state.serverError) { + serverError = this.state.serverError; + } + + var user = this.props.user; + + var desktopSection; + var handleUpdateDesktopSection; + if (this.props.activeSection === 'desktop') { + var notifyActive = [false, false, false]; + if (this.state.notifyLevel === 'mention') { + notifyActive[1] = true; + } else if (this.state.notifyLevel === 'none') { + notifyActive[2] = true; + } else { + notifyActive[0] = true; + } + + let inputs = []; + + inputs.push( +
+
+ +
+
+
+ +
+
+
+ +
+
+ ); + + handleUpdateDesktopSection = function updateDesktopSection(e) { + this.props.updateSection(''); + e.preventDefault(); + }.bind(this); + + desktopSection = ( + + ); + } else { + let describe = ''; + if (this.state.notifyLevel === 'mention') { + describe = 'Only for mentions and private messages'; + } else if (this.state.notifyLevel === 'none') { + describe = 'Never'; + } else { + describe = 'For all activity'; + } + + handleUpdateDesktopSection = function updateDesktopSection() { + this.props.updateSection('desktop'); + }.bind(this); + + desktopSection = ( + + ); + } + + var soundSection; + var handleUpdateSoundSection; + if (this.props.activeSection === 'sound' && this.state.soundNeeded) { + var soundActive = [false, false]; + if (this.state.enableSound === 'false') { + soundActive[1] = true; + } else { + soundActive[0] = true; + } + + let inputs = []; + + inputs.push( +
+
+ +
+
+
+ +
+
+
+ ); + + handleUpdateSoundSection = function updateSoundSection(e) { + this.props.updateSection(''); + e.preventDefault(); + }.bind(this); + + soundSection = ( + + ); + } else { + let describe = ''; + if (!this.state.soundNeeded) { + describe = 'Please configure notification sounds in your browser settings'; + } else if (this.state.enableSound === 'false') { + describe = 'Off'; + } else { + describe = 'On'; + } + + handleUpdateSoundSection = function updateSoundSection() { + this.props.updateSection('sound'); + }.bind(this); + + soundSection = ( + + ); + } + + var emailSection; + var handleUpdateEmailSection; + if (this.props.activeSection === 'email') { + var emailActive = [false, false]; + if (this.state.enableEmail === 'false') { + emailActive[1] = true; + } else { + emailActive[0] = true; + } + + let inputs = []; + + inputs.push( +
+
+ +
+
+
+ +
+
+

{'Email notifications are sent for mentions and private messages after you have been away from ' + global.window.config.SiteName + ' for 5 minutes.'}
+
+ ); + + handleUpdateEmailSection = function updateEmailSection(e) { + this.props.updateSection(''); + e.preventDefault(); + }.bind(this); + + emailSection = ( + + ); + } else { + let describe = ''; + if (this.state.enableEmail === 'false') { + describe = 'Off'; + } else { + describe = 'On'; + } + + handleUpdateEmailSection = function updateEmailSection() { + this.props.updateSection('email'); + }.bind(this); + + emailSection = ( + + ); + } + + var keysSection; + var handleUpdateKeysSection; + if (this.props.activeSection === 'keys') { + let inputs = []; + + let handleUpdateFirstNameKey; + let handleUpdateUsernameKey; + let handleUpdateMentionKey; + let handleUpdateAllKey; + let handleUpdateChannelKey; + + if (user.first_name) { + handleUpdateFirstNameKey = function handleFirstNameKeyChange(e) { + this.updateFirstNameKey(e.target.checked); + }.bind(this); + inputs.push( +
+
+ +
+
+ ); + } + + handleUpdateUsernameKey = function handleUsernameKeyChange(e) { + this.updateUsernameKey(e.target.checked); + }.bind(this); + inputs.push( +
+
+ +
+
+ ); + + handleUpdateMentionKey = function handleMentionKeyChange(e) { + this.updateMentionKey(e.target.checked); + }.bind(this); + inputs.push( +
+
+ +
+
+ ); + + handleUpdateAllKey = function handleAllKeyChange(e) { + this.updateAllKey(e.target.checked); + }.bind(this); + inputs.push( +
+
+ +
+
+ ); + + handleUpdateChannelKey = function handleChannelKeyChange(e) { + this.updateChannelKey(e.target.checked); + }.bind(this); + inputs.push( +
+
+ +
+
+ ); + + inputs.push( +
+
+ +
+ +
+ ); + + handleUpdateKeysSection = function updateKeysSection(e) { + this.props.updateSection(''); + e.preventDefault(); + }.bind(this); + keysSection = ( + + ); + } else { + let keys = []; + if (this.state.firstNameKey) { + keys.push(user.first_name); + } + if (this.state.usernameKey) { + keys.push(user.username); + } + if (this.state.mentionKey) { + keys.push('@' + user.username); + } + if (this.state.allKey) { + keys.push('@all'); + } + if (this.state.channelKey) { + keys.push('@channel'); + } + if (this.state.customKeys.length > 0) { + keys = keys.concat(this.state.customKeys.split(',')); + } + + let describe = ''; + for (var i = 0; i < keys.length; i++) { + describe += '"' + keys[i] + '", '; + } + + if (describe.length > 0) { + describe = describe.substring(0, describe.length - 2); + } else { + describe = 'No words configured'; + } + + handleUpdateKeysSection = function updateKeysSection() { + this.props.updateSection('keys'); + }.bind(this); + + keysSection = ( + + ); + } + + return ( +
+
+ +

+ + Notifications +

+
+
+

Notifications

+
+ {desktopSection} +
+ {soundSection} +
+ {emailSection} +
+ {keysSection} +
+
+
+ + ); + } +} + +NotificationsTab.defaultProps = { + user: null, + activeSection: '', + activeTab: '' +}; +NotificationsTab.propTypes = { + user: React.PropTypes.object, + updateSection: React.PropTypes.func, + updateTab: React.PropTypes.func, + activeSection: React.PropTypes.string, + activeTab: React.PropTypes.string +}; -- cgit v1.2.3-1-g7c22