Files
mattermost/web/react/components/user_settings/user_settings_notifications.jsx

704 lines
25 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// 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 = 'default';
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(
<div key='userNotificationLevelOption'>
<div className='radio'>
<label>
<input type='radio'
checked={notifyActive[0]}
onChange={this.handleNotifyRadio.bind(this, 'all')}
>
For all activity
</input>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
checked={notifyActive[1]}
onChange={this.handleNotifyRadio.bind(this, 'mention')}
>
Only for mentions and direct messages
</input>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
checked={notifyActive[2]}
onChange={this.handleNotifyRadio.bind(this, 'none')}
>
Never
</input>
</label>
</div>
</div>
);
handleUpdateDesktopSection = function updateDesktopSection(e) {
this.props.updateSection('');
e.preventDefault();
}.bind(this);
const extraInfo = <span>{'Desktop notifications are available on Firefox, Safari, and Chrome.'}</span>;
desktopSection = (
<SettingItemMax
title='Send desktop notifications'
extraInfo={extraInfo}
inputs={inputs}
submit={this.handleSubmit}
server_error={serverError}
updateSection={handleUpdateDesktopSection}
/>
);
} else {
let describe = '';
if (this.state.notifyLevel === 'mention') {
describe = 'Only for mentions and direct messages';
} else if (this.state.notifyLevel === 'none') {
describe = 'Never';
} else {
describe = 'For all activity';
}
handleUpdateDesktopSection = function updateDesktopSection() {
this.props.updateSection('desktop');
}.bind(this);
desktopSection = (
<SettingItemMin
title='Send desktop notifications'
describe={describe}
updateSection={handleUpdateDesktopSection}
/>
);
}
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(
<div key='userNotificationSoundOptions'>
<div className='radio'>
<label>
<input
type='radio'
checked={soundActive[0]}
onChange={this.handleSoundRadio.bind(this, 'true')}
>
On
</input>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
checked={soundActive[1]}
onChange={this.handleSoundRadio.bind(this, 'false')}
>
Off
</input>
</label>
<br/>
</div>
</div>
);
handleUpdateSoundSection = function updateSoundSection(e) {
this.props.updateSection('');
e.preventDefault();
}.bind(this);
const extraInfo = <span>{'Desktop notification sounds are available on Firefox, Safari, Chrome, Internet Explorer, and Edge.'}</span>;
soundSection = (
<SettingItemMax
title='Desktop notification sounds'
extraInfo={extraInfo}
inputs={inputs}
submit={this.handleSubmit}
server_error={serverError}
updateSection={handleUpdateSoundSection}
/>
);
} 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 = (
<SettingItemMin
title='Desktop notification sounds'
describe={describe}
updateSection={handleUpdateSoundSection}
disableOpen = {!this.state.soundNeeded}
/>
);
}
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(
<div key='userNotificationEmailOptions'>
<div className='radio'>
<label>
<input
type='radio'
checked={emailActive[0]}
onChange={this.handleEmailRadio.bind(this, 'true')}
>
On
</input>
</label>
<br/>
</div>
<div className='radio'>
<label>
<input
type='radio'
checked={emailActive[1]}
onChange={this.handleEmailRadio.bind(this, 'false')}
>
Off
</input>
</label>
<br/>
</div>
<div><br/>{'Email notifications are sent for mentions and direct messages after youve been offline for more than 60 seconds or away from ' + global.window.config.SiteName + ' for more than 5 minutes.'}</div>
</div>
);
handleUpdateEmailSection = function updateEmailSection(e) {
this.props.updateSection('');
e.preventDefault();
}.bind(this);
emailSection = (
<SettingItemMax
title='Email notifications'
inputs={inputs}
submit={this.handleSubmit}
server_error={serverError}
updateSection={handleUpdateEmailSection}
/>
);
} else {
let describe = '';
if (this.state.enableEmail === 'false') {
describe = 'Off';
} else {
describe = 'On';
}
handleUpdateEmailSection = function updateEmailSection() {
this.props.updateSection('email');
}.bind(this);
emailSection = (
<SettingItemMin
title='Email notifications'
describe={describe}
updateSection={handleUpdateEmailSection}
/>
);
}
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(
<div key='userNotificationFirstNameOption'>
<div className='checkbox'>
<label>
<input
type='checkbox'
checked={this.state.firstNameKey}
onChange={handleUpdateFirstNameKey}
>
{'Your case sensitive first name "' + user.first_name + '"'}
</input>
</label>
</div>
</div>
);
}
handleUpdateUsernameKey = function handleUsernameKeyChange(e) {
this.updateUsernameKey(e.target.checked);
}.bind(this);
inputs.push(
<div key='userNotificationUsernameOption'>
<div className='checkbox'>
<label>
<input
type='checkbox'
checked={this.state.usernameKey}
onChange={handleUpdateUsernameKey}
>
{'Your non-case sensitive username "' + user.username + '"'}
</input>
</label>
</div>
</div>
);
handleUpdateMentionKey = function handleMentionKeyChange(e) {
this.updateMentionKey(e.target.checked);
}.bind(this);
inputs.push(
<div key='userNotificationMentionOption'>
<div className='checkbox'>
<label>
<input
type='checkbox'
checked={this.state.mentionKey}
onChange={handleUpdateMentionKey}
>
{'Your username mentioned "@' + user.username + '"'}
</input>
</label>
</div>
</div>
);
handleUpdateAllKey = function handleAllKeyChange(e) {
this.updateAllKey(e.target.checked);
}.bind(this);
inputs.push(
<div key='userNotificationAllOption'>
<div className='checkbox'>
<label>
<input
type='checkbox'
checked={this.state.allKey}
onChange={handleUpdateAllKey}
>
{'Team-wide mentions "@all"'}
</input>
</label>
</div>
</div>
);
handleUpdateChannelKey = function handleChannelKeyChange(e) {
this.updateChannelKey(e.target.checked);
}.bind(this);
inputs.push(
<div key='userNotificationChannelOption'>
<div className='checkbox'>
<label>
<input
type='checkbox'
checked={this.state.channelKey}
onChange={handleUpdateChannelKey}
>
{'Channel-wide mentions "@channel"'}
</input>
</label>
</div>
</div>
);
inputs.push(
<div key='userNotificationCustomOption'>
<div className='checkbox'>
<label>
<input
ref='customcheck'
type='checkbox'
checked={this.state.customKeysChecked}
onChange={this.updateCustomMentionKeys}
>
{'Other non-case sensitive words, separated by commas:'}
</input>
</label>
</div>
<input
ref='custommentions'
className='form-control mentions-input'
type='text'
defaultValue={this.state.customKeys}
onChange={this.onCustomChange}
/>
</div>
);
handleUpdateKeysSection = function updateKeysSection(e) {
this.props.updateSection('');
e.preventDefault();
}.bind(this);
keysSection = (
<SettingItemMax
title='Words that trigger mentions'
inputs={inputs}
submit={this.handleSubmit}
server_error={serverError}
updateSection={handleUpdateKeysSection}
/>
);
} 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 = (
<SettingItemMin
title='Words that trigger mentions'
describe={describe}
updateSection={handleUpdateKeysSection}
/>
);
}
return (
<div>
<div className='modal-header'>
<button
type='button'
className='close'
data-dismiss='modal'
aria-label='Close'
>
<span aria-hidden='true'>&times;</span>
</button>
<h4
className='modal-title'
ref='title'
>
<i className='modal-back'></i>
Notifications
</h4>
</div>
<div
ref='wrapper'
className='user-settings'
>
<h3 className='tab-header'>Notifications</h3>
<div className='divider-dark first'/>
{desktopSection}
<div className='divider-light'/>
{soundSection}
<div className='divider-light'/>
{emailSection}
<div className='divider-light'/>
{keysSection}
<div className='divider-dark'/>
</div>
</div>
);
}
}
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
};