diff options
Diffstat (limited to 'webapp/components')
3 files changed, 493 insertions, 258 deletions
diff --git a/webapp/components/setting_item_min.jsx b/webapp/components/setting_item_min.jsx index 1c5fd40f3..edcc81693 100644 --- a/webapp/components/setting_item_min.jsx +++ b/webapp/components/setting_item_min.jsx @@ -33,7 +33,7 @@ export default class SettingItemMin extends React.Component { > <li className='col-sm-9 section-title'>{this.props.title}</li> {editButton} - <li className='col-sm-10 section-describe'>{this.props.describe}</li> + <li className='col-sm-12 section-describe'>{this.props.describe}</li> </ul> ); } diff --git a/webapp/components/user_settings/desktop_notification_settings.jsx b/webapp/components/user_settings/desktop_notification_settings.jsx new file mode 100644 index 000000000..e5376c7ee --- /dev/null +++ b/webapp/components/user_settings/desktop_notification_settings.jsx @@ -0,0 +1,454 @@ +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import SettingItemMin from 'components/setting_item_min.jsx'; +import SettingItemMax from 'components/setting_item_max.jsx'; + +import * as Utils from 'utils/utils.jsx'; +import * as UserAgent from 'utils/user_agent.jsx'; + +import React from 'react'; +import {FormattedMessage} from 'react-intl'; + +export default class DesktopNotificationSettings extends React.Component { + constructor(props) { + super(props); + + this.buildMaximizedSetting = this.buildMaximizedSetting.bind(this); + this.buildMinimizedSetting = this.buildMinimizedSetting.bind(this); + + this.state = {}; + } + + buildMaximizedSetting() { + let inputs = []; + let extraInfo = null; + + const activityRadio = [false, false, false]; + if (this.props.activity === 'mention') { + activityRadio[1] = true; + } else if (this.props.activity === 'none') { + activityRadio[2] = true; + } else { + activityRadio[0] = true; + } + + let soundSection; + let durationSection; + if (this.props.activity !== 'none') { + const soundRadio = [false, false]; + if (this.props.sound === 'false') { + soundRadio[1] = true; + } else { + soundRadio[0] = true; + } + + if (UserAgent.isFirefox()) { + soundSection = ( + <div> + <hr/> + <label> + <FormattedMessage + id='user.settings.notifications.desktop.sound' + defaultMessage='Notification sound' + /> + </label> + <br/> + <FormattedMessage + id='user.settings.notifications.soundConfig' + defaultMessage='Please configure notification sounds in your browser settings' + /> + </div> + ); + } else { + soundSection = ( + <div> + <hr/> + <label> + <FormattedMessage + id='user.settings.notifications.desktop.sound' + defaultMessage='Notification sound' + /> + </label> + <br/> + <div className='radio'> + <label> + <input + type='radio' + name='notificationSounds' + checked={soundRadio[0]} + onChange={() => this.props.setParentState('desktopSound', 'true')} + /> + <FormattedMessage + id='user.settings.notifications.on' + defaultMessage='On' + /> + </label> + <br/> + </div> + <div className='radio'> + <label> + <input + type='radio' + name='notificationSounds' + checked={soundRadio[1]} + onChange={() => this.props.setParentState('desktopSound', 'false')} + /> + <FormattedMessage + id='user.settings.notifications.off' + defaultMessage='Off' + /> + </label> + <br/> + </div> + <br/> + <span> + <FormattedMessage + id='user.settings.notifications.sounds_info' + defaultMessage='Notification sounds are available on IE11, Edge, Safari and Chrome.' + /> + </span> + </div> + ); + } + + const durationRadio = [false, false, false, false]; + if (this.props.duration === '3') { + durationRadio[0] = true; + } else if (this.props.duration === '10') { + durationRadio[2] = true; + } else if (this.props.duration === '0') { + durationRadio[3] = true; + } else { + durationRadio[1] = true; + } + + durationSection = ( + <div> + <hr/> + <label> + <FormattedMessage + id='user.settings.notifications.desktop.duration' + defaultMessage='Notification duration' + /> + </label> + <br/> + <div className='radio'> + <label> + <input + type='radio' + name='desktopDuration' + checked={durationRadio[0]} + onChange={() => this.props.setParentState('desktopDuration', '3')} + /> + <FormattedMessage + id='user.settings.notifications.desktop.seconds' + defaultMessage='{seconds} seconds' + values={{ + seconds: '3' + }} + /> + </label> + <br/> + </div> + <div className='radio'> + <label> + <input + type='radio' + name='desktopDuration' + checked={durationRadio[1]} + onChange={() => this.props.setParentState('desktopDuration', '5')} + /> + <FormattedMessage + id='user.settings.notifications.desktop.seconds' + defaultMessage='{seconds} seconds' + values={{ + seconds: '5' + }} + /> + </label> + <br/> + </div> + <div className='radio'> + <label> + <input + type='radio' + name='desktopDuration' + checked={durationRadio[2]} + onChange={() => this.props.setParentState('desktopDuration', '10')} + /> + <FormattedMessage + id='user.settings.notifications.desktop.seconds' + defaultMessage='{seconds} seconds' + values={{ + seconds: '10' + }} + /> + </label> + </div> + <div className='radio'> + <label> + <input + type='radio' + name='desktopDuration' + checked={durationRadio[3]} + onChange={() => this.props.setParentState('desktopDuration', '0')} + /> + <FormattedMessage + id='user.settings.notifications.desktop.unlimited' + defaultMessage='Unlimited' + /> + </label> + </div> + </div> + ); + + extraInfo = ( + <span> + <FormattedMessage + id='user.settings.notifications.desktop.durationInfo' + defaultMessage='Sets how long desktop notifications will remain on screen.' + /> + </span> + ); + } + + inputs.push( + <div key='userNotificationLevelOption'> + <label> + <FormattedMessage + id='user.settings.notifications.desktop' + defaultMessage='Send desktop notifications' + /> + </label> + <br/> + <div className='radio'> + <label> + <input + type='radio' + name='desktopNotificationLevel' + checked={activityRadio[0]} + onChange={() => this.props.setParentState('desktopActivity', 'all')} + /> + <FormattedMessage + id='user.settings.notifications.allActivity' + defaultMessage='For all activity' + /> + </label> + <br/> + </div> + <div className='radio'> + <label> + <input + type='radio' + name='desktopNotificationLevel' + checked={activityRadio[1]} + onChange={() => this.props.setParentState('desktopActivity', 'mention')} + /> + <FormattedMessage + id='user.settings.notifications.onlyMentions' + defaultMessage='Only for mentions and direct messages' + /> + </label> + <br/> + </div> + <div className='radio'> + <label> + <input + type='radio' + name='desktopNotificationLevel' + checked={activityRadio[2]} + onChange={() => this.props.setParentState('desktopActivity', 'none')} + /> + <FormattedMessage + id='user.settings.notifications.never' + defaultMessage='Never' + /> + </label> + </div> + <br/> + <span> + <FormattedMessage + id='user.settings.notifications.info' + defaultMessage='Desktop notifications are available on Firefox, Safari, and Chrome.' + /> + </span> + {soundSection} + {durationSection} + </div> + ); + + return ( + <SettingItemMax + title={Utils.localizeMessage('user.settings.notifications.desktop.title', 'Desktop notifications')} + extraInfo={extraInfo} + inputs={inputs} + submit={this.props.submit} + server_error={this.props.error} + updateSection={this.props.cancel} + /> + ); + } + + buildMinimizedSetting() { + let describe = ''; + if (this.props.activity === 'mention') { + if (UserAgent.isFirefox()) { + if (this.props.duration === '0') { + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.mentionsFirefoxForever' + defaultMessage='For mentions and direct messages, shown indefinitely' + /> + ); + } else { + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.mentionsFirefoxTimed' + defaultMessage='For mentions and direct messages, shown for {seconds} seconds' + values={{ + seconds: this.props.duration + }} + /> + ); + } + } else if (this.props.sound === 'false') { + if (this.props.duration === '0') { + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.mentionsNoSoundForever' + defaultMessage='For mentions and direct messages, without sound, shown indefinitely' + /> + ); + } else { + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.mentionsNoSoundTimed' + defaultMessage='For mentions and direct messages, without sound, shown for {seconds} seconds' + values={{ + seconds: this.props.duration + }} + /> + ); + } + } else { + if (this.props.duration === '0') { //eslint-disable-line no-lonely-if + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.mentionsSoundForever' + defaultMessage='For mentions and direct messages, with sound, shown indefinitely' + /> + ); + } else { + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.mentionsSoundTimed' + defaultMessage='For mentions and direct messages, with sound, shown for {seconds} seconds' + values={{ + seconds: this.props.duration + }} + /> + ); + } + } + } else if (this.props.activity === 'none') { + describe = ( + <FormattedMessage + id='user.settings.notifications.off' + defaultMessage='Off' + /> + ); + } else { + if (UserAgent.isFirefox()) { //eslint-disable-line no-lonely-if + if (this.props.duration === '0') { + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.allFirefoxForever' + defaultMessage='For all activity, shown indefinitely' + /> + ); + } else { + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.allFirefoxTimed' + defaultMessage='For all activity, shown for {seconds} seconds' + values={{ + seconds: this.props.duration + }} + /> + ); + } + } else if (this.props.sound === 'false') { + if (this.props.duration === '0') { + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.allNoSoundForever' + defaultMessage='For all activity, without sound, shown indefinitely' + /> + ); + } else { + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.allNoSoundTimed' + defaultMessage='For all activity, without sound, shown for {seconds} seconds' + values={{ + seconds: this.props.duration + }} + /> + ); + } + } else { + if (this.props.duration === '0') { //eslint-disable-line no-lonely-if + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.allSoundForever' + defaultMessage='For all activity, with sound, shown indefinitely' + /> + ); + } else { + describe = ( + <FormattedMessage + id='user.settings.notifications.desktop.allSoundTimed' + defaultMessage='For all activity, with sound, shown for {seconds} seconds' + values={{ + seconds: this.props.duration + }} + /> + ); + } + } + } + + const handleUpdateDesktopSection = function updateDesktopSection() { + this.props.updateSection('desktop'); + }.bind(this); + + return ( + <SettingItemMin + title={Utils.localizeMessage('user.settings.notifications.desktop.title', 'Desktop notifications')} + describe={describe} + updateSection={handleUpdateDesktopSection} + /> + ); + } + + render() { + if (this.props.active) { + return this.buildMaximizedSetting(); + } + + return this.buildMinimizedSetting(); + } +} + +DesktopNotificationSettings.propTypes = { + activity: React.PropTypes.string.isRequired, + sound: React.PropTypes.string.isRequired, + duration: React.PropTypes.string.isRequired, + updateSection: React.PropTypes.func, + setParentState: React.PropTypes.func, + submit: React.PropTypes.func, + cancel: React.PropTypes.func, + error: React.PropTypes.string, + active: React.PropTypes.bool +}; diff --git a/webapp/components/user_settings/user_settings_notifications.jsx b/webapp/components/user_settings/user_settings_notifications.jsx index b3953ec17..a18cdf041 100644 --- a/webapp/components/user_settings/user_settings_notifications.jsx +++ b/webapp/components/user_settings/user_settings_notifications.jsx @@ -4,12 +4,12 @@ import $ from 'jquery'; import SettingItemMin from 'components/setting_item_min.jsx'; import SettingItemMax from 'components/setting_item_max.jsx'; +import DesktopNotificationSettings from './desktop_notification_settings.jsx'; import UserStore from 'stores/user_store.jsx'; import Client from 'client/web_client.jsx'; import * as AsyncClient from 'utils/async_client.jsx'; -import * as UserAgent from 'utils/user_agent.jsx'; import * as Utils from 'utils/utils.jsx'; import Constants from 'utils/constants.jsx'; @@ -18,21 +18,24 @@ import {FormattedMessage} from 'react-intl'; function getNotificationsStateFromStores() { const user = UserStore.getCurrentUser(); - const soundNeeded = !UserAgent.isFirefox(); - let sound = 'true'; let desktop = 'default'; + let sound = 'true'; + let desktopDuration = '5'; let comments = 'never'; let enableEmail = 'true'; let pushActivity = 'mention'; let pushStatus = Constants.UserStatuses.ONLINE; if (user.notify_props) { + if (user.notify_props.desktop) { + desktop = user.notify_props.desktop; + } if (user.notify_props.desktop_sound) { sound = user.notify_props.desktop_sound; } - if (user.notify_props.desktop) { - desktop = user.notify_props.desktop; + if (user.notify_props.desktop_duration) { + desktopDuration = user.notify_props.desktop_duration; } if (user.notify_props.comments) { comments = user.notify_props.comments; @@ -85,12 +88,12 @@ function getNotificationsStateFromStores() { } return { - notifyLevel: desktop, + desktopActivity: desktop, + desktopDuration, enableEmail, pushActivity, pushStatus, - soundNeeded, - enableSound: sound, + desktopSound: sound, usernameKey, mentionKey, customKeys, @@ -110,16 +113,15 @@ export default class NotificationsTab extends React.Component { this.handleSubmit = this.handleSubmit.bind(this); this.handleCancel = this.handleCancel.bind(this); this.updateSection = this.updateSection.bind(this); - this.updateState = this.updateState.bind(this); + this.setStateValue = this.setStateValue.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.updateChannelKey = this.updateChannelKey.bind(this); this.updateCustomMentionKeys = this.updateCustomMentionKeys.bind(this); + this.updateState = this.updateState.bind(this); this.onCustomChange = this.onCustomChange.bind(this); this.createPushNotificationSection = this.createPushNotificationSection.bind(this); @@ -130,8 +132,9 @@ export default class NotificationsTab extends React.Component { 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; + data.desktop_sound = this.state.desktopSound; + data.desktop = this.state.desktopActivity; + data.desktop_duration = this.state.desktopDuration; data.push = this.state.pushActivity; data.push_status = this.state.pushStatus; data.comments = this.state.notifyCommentsLevel; @@ -166,12 +169,18 @@ export default class NotificationsTab extends React.Component { } handleCancel(e) { + e.preventDefault(); this.updateState(); this.props.updateSection(''); - e.preventDefault(); $('.settings-modal .modal-body').scrollTop(0).perfectScrollbar('update'); } + setStateValue(key, value) { + const data = {}; + data[key] = value; + this.setState(data); + } + updateSection(section) { this.updateState(); this.props.updateSection(section); @@ -196,11 +205,6 @@ export default class NotificationsTab extends React.Component { this.updateState(); } - handleNotifyRadio(notifyLevel) { - this.setState({notifyLevel}); - this.refs.wrapper.focus(); - } - handleNotifyCommentsRadio(notifyCommentsLevel) { this.setState({notifyCommentsLevel}); this.refs.wrapper.focus(); @@ -221,11 +225,6 @@ export default class NotificationsTab extends React.Component { this.refs.wrapper.focus(); } - handleSoundRadio(enableSound) { - this.setState({enableSound}); - this.refs.wrapper.focus(); - } - updateUsernameKey(val) { this.setState({usernameKey: val}); } @@ -261,7 +260,7 @@ export default class NotificationsTab extends React.Component { } createPushNotificationSection() { - let handleUpdateDesktopSection; + let handleUpdatePushSection; if (this.props.activeSection === 'push') { let inputs = []; let extraInfo = null; @@ -495,7 +494,7 @@ export default class NotificationsTab extends React.Component { } } - handleUpdateDesktopSection = function updateDesktopSection() { + handleUpdatePushSection = function updateDesktopSection() { this.props.updateSection('push'); }.bind(this); @@ -503,240 +502,14 @@ export default class NotificationsTab extends React.Component { <SettingItemMin title={Utils.localizeMessage('user.settings.notifications.push', 'Send mobile push notifications')} describe={describe} - updateSection={handleUpdateDesktopSection} + updateSection={handleUpdatePushSection} /> ); } render() { const 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' - name='desktopNotificationLevel' - checked={notifyActive[0]} - onChange={this.handleNotifyRadio.bind(this, 'all')} - /> - <FormattedMessage - id='user.settings.notifications.allActivity' - defaultMessage='For all activity' - /> - </label> - <br/> - </div> - <div className='radio'> - <label> - <input - type='radio' - name='desktopNotificationLevel' - checked={notifyActive[1]} - onChange={this.handleNotifyRadio.bind(this, 'mention')} - /> - <FormattedMessage - id='user.settings.notifications.onlyMentions' - defaultMessage='Only for mentions and direct messages' - /> - </label> - <br/> - </div> - <div className='radio'> - <label> - <input - type='radio' - name='desktopNotificationLevel' - checked={notifyActive[2]} - onChange={this.handleNotifyRadio.bind(this, 'none')} - /> - <FormattedMessage - id='user.settings.notifications.never' - defaultMessage='Never' - /> - </label> - </div> - </div> - ); - - const extraInfo = ( - <span> - <FormattedMessage - id='user.settings.notifications.info' - defaultMessage='Desktop notifications are available on Firefox, Safari, Chrome, Internet Explorer, and Edge.' - /> - </span> - ); - - desktopSection = ( - <SettingItemMax - title={Utils.localizeMessage('user.settings.notifications.desktop', 'Send desktop notifications')} - extraInfo={extraInfo} - inputs={inputs} - submit={this.handleSubmit} - server_error={serverError} - updateSection={this.handleCancel} - /> - ); - } else { - let describe = ''; - if (this.state.notifyLevel === 'mention') { - describe = ( - <FormattedMessage - id='user.settings.notifications.onlyMentions' - defaultMessage='Only for mentions and direct messages' - /> - ); - } else if (this.state.notifyLevel === 'none') { - describe = ( - <FormattedMessage - id='user.settings.notifications.never' - defaultMessage='Never' - /> - ); - } else { - describe = ( - <FormattedMessage - id='user.settings.notification.allActivity' - defaultMessage='For all activity' - /> - ); - } - - handleUpdateDesktopSection = function updateDesktopSection() { - this.props.updateSection('desktop'); - }.bind(this); - - desktopSection = ( - <SettingItemMin - title={Utils.localizeMessage('user.settings.notifications.desktop', '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' - name='notificationSounds' - checked={soundActive[0]} - onChange={this.handleSoundRadio.bind(this, 'true')} - /> - <FormattedMessage - id='user.settings.notifications.on' - defaultMessage='On' - /> - </label> - <br/> - </div> - <div className='radio'> - <label> - <input - type='radio' - name='notificationSounds' - checked={soundActive[1]} - onChange={this.handleSoundRadio.bind(this, 'false')} - /> - <FormattedMessage - id='user.settings.notifications.off' - defaultMessage='Off' - /> - </label> - <br/> - </div> - </div> - ); - - const extraInfo = ( - <span> - <FormattedMessage - id='user.settings.notifications.sounds_info' - defaultMessage='Desktop notifications sounds are available on Firefox, Safari, Chrome, Internet Explorer, and Edge.' - /> - </span> - ); - - soundSection = ( - <SettingItemMax - title={Utils.localizeMessage('user.settings.notifications.desktopSounds', 'Desktop notification sounds')} - extraInfo={extraInfo} - inputs={inputs} - submit={this.handleSubmit} - server_error={serverError} - updateSection={this.handleCancel} - /> - ); - } else { - let describe = ''; - if (!this.state.soundNeeded) { - describe = ( - <FormattedMessage - id='user.settings.notifications.soundConfig' - defaultMessage='Please configure notification sounds in your browser settings' - /> - ); - } else if (this.state.enableSound === 'false') { - describe = ( - <FormattedMessage - id='user.settings.notifications.off' - defaultMessage='Off' - /> - ); - } else { - describe = ( - <FormattedMessage - id='user.settings.notifications.on' - defaultMessage='On' - /> - ); - } - - handleUpdateSoundSection = function updateSoundSection() { - this.props.updateSection('sound'); - }.bind(this); - - soundSection = ( - <SettingItemMin - title={Utils.localizeMessage('user.settings.notifications.desktopSounds', 'Desktop notification sounds')} - describe={describe} - updateSection={handleUpdateSoundSection} - disableOpen={!this.state.soundNeeded} - /> - ); - } + const user = this.props.user; var keysSection; var handleUpdateKeysSection; @@ -1089,9 +862,17 @@ export default class NotificationsTab extends React.Component { /> </h3> <div className='divider-dark first'/> - {desktopSection} - <div className='divider-light'/> - {soundSection} + <DesktopNotificationSettings + activity={this.state.desktopActivity} + sound={this.state.desktopSound} + duration={this.state.desktopDuration} + updateSection={this.updateSection} + setParentState={this.setStateValue} + submit={this.handleSubmit} + cancel={this.handleCancel} + error={this.state.serverError} + active={this.props.activeSection === 'desktop'} + /> <div className='divider-light'/> <EmailNotificationSetting activeSection={this.props.activeSection} |