diff options
Diffstat (limited to 'web')
-rw-r--r-- | web/react/components/channel_notifications.jsx | 302 | ||||
-rw-r--r-- | web/react/components/create_post.jsx | 4 | ||||
-rw-r--r-- | web/react/components/edit_channel_modal.jsx | 2 | ||||
-rw-r--r-- | web/react/components/file_upload.jsx | 2 | ||||
-rw-r--r-- | web/react/components/setting_item_max.jsx | 2 | ||||
-rw-r--r-- | web/react/components/team_signup_send_invites_page.jsx | 116 | ||||
-rw-r--r-- | web/react/components/user_settings_notifications.jsx | 406 | ||||
-rw-r--r-- | web/react/utils/utils.jsx | 2 |
8 files changed, 599 insertions, 237 deletions
diff --git a/web/react/components/channel_notifications.jsx b/web/react/components/channel_notifications.jsx index 38bc91682..cd477feb7 100644 --- a/web/react/components/channel_notifications.jsx +++ b/web/react/components/channel_notifications.jsx @@ -9,159 +9,230 @@ var client = require('../utils/client.jsx'); var UserStore = require('../stores/user_store.jsx'); var ChannelStore = require('../stores/channel_store.jsx'); -module.exports = React.createClass({ - componentDidMount: function() { - ChannelStore.addChangeListener(this._onChange); +export default class ChannelNotifications extends React.Component { + constructor(props) { + super(props); + this.onListenerChange = this.onListenerChange.bind(this); + this.updateSection = this.updateSection.bind(this); + this.handleUpdate = this.handleUpdate.bind(this); + this.handleRadioClick = this.handleRadioClick.bind(this); + this.handleQuietToggle = this.handleQuietToggle.bind(this); + this.state = {notifyLevel: '', title: '', channelId: '', activeSection: ''}; + } + componentDidMount() { + ChannelStore.addChangeListener(this.onListenerChange); var self = this; - $(this.refs.modal.getDOMNode()).on('show.bs.modal', function(e) { + $(this.refs.modal.getDOMNode()).on('show.bs.modal', function showModal(e) { var button = e.relatedTarget; - var channel_id = button.getAttribute('data-channelid'); + var channelId = button.getAttribute('data-channelid'); - var notifyLevel = ChannelStore.getMember(channel_id).notify_level; + var notifyLevel = ChannelStore.getMember(channelId).notify_level; var quietMode = false; - if (notifyLevel === "quiet") quietMode = true; - self.setState({ notify_level: notifyLevel, quiet_mode: quietMode, title: button.getAttribute('data-title'), channel_id: channel_id }); + + if (notifyLevel === 'quiet') { + quietMode = true; + } + + self.setState({notifyLevel: notifyLevel, quietMode: quietMode, title: button.getAttribute('data-title'), channelId: channelId}); }); - }, - componentWillUnmount: function() { - ChannelStore.removeChangeListener(this._onChange); - }, - _onChange: function() { - if (!this.state.channel_id) return; - var notifyLevel = ChannelStore.getMember(this.state.channel_id).notify_level; + } + componentWillUnmount() { + ChannelStore.removeChangeListener(this.onListenerChange); + } + onListenerChange() { + if (!this.state.channelId) { + return; + } + + var notifyLevel = ChannelStore.getMember(this.state.channelId).notify_level; var quietMode = false; - if (notifyLevel === "quiet") quietMode = true; + if (notifyLevel === 'quiet') { + quietMode = true; + } var newState = this.state; - newState.notify_level = notifyLevel; - newState.quiet_mode = quietMode; + newState.notifyLevel = notifyLevel; + newState.quietMode = quietMode; if (!utils.areStatesEqual(this.state, newState)) { this.setState(newState); } - }, - updateSection: function(section) { - this.setState({ activeSection: section }); - }, - getInitialState: function() { - return { notify_level: "", title: "", channel_id: "", activeSection: "" }; - }, - handleUpdate: function() { - var channel_id = this.state.channel_id; - var notify_level = this.state.quiet_mode ? "quiet" : this.state.notify_level; + } + updateSection(section) { + this.setState({activeSection: section}); + } + handleUpdate() { + var channelId = this.state.channelId; + var notifyLevel = this.state.notifyLevel; + if (this.state.quietMode) { + notifyLevel = 'quiet'; + } var data = {}; - data["channel_id"] = channel_id; - data["user_id"] = UserStore.getCurrentId(); - data["notify_level"] = notify_level; + data.channel_id = channelId; + data.user_id = UserStore.getCurrentId(); + data.notify_level = notifyLevel; - if (!data["notify_level"] || data["notify_level"].length === 0) return; + if (!data.notify_level || data.notify_level.length === 0) { + return; + } client.updateNotifyLevel(data, - function(data) { - var member = ChannelStore.getMember(channel_id); - member.notify_level = notify_level; + function success() { + var member = ChannelStore.getMember(channelId); + member.notify_level = notifyLevel; ChannelStore.setChannelMember(member); - this.updateSection(""); + this.updateSection(''); }.bind(this), - function(err) { - this.setState({ server_error: err.message }); + function error(err) { + this.setState({serverError: err.message}); }.bind(this) ); - }, - handleRadioClick: function(notifyLevel) { - this.setState({ notify_level: notifyLevel, quiet_mode: false }); + } + handleRadioClick(notifyLevel) { + this.setState({notifyLevel: notifyLevel, quietMode: false}); this.refs.modal.getDOMNode().focus(); - }, - handleQuietToggle: function(quietMode) { - this.setState({ notify_level: "none", quiet_mode: quietMode }); + } + handleQuietToggle(quietMode) { + this.setState({notifyLevel: 'none', quietMode: quietMode}); this.refs.modal.getDOMNode().focus(); - }, - render: function() { - var server_error = this.state.server_error ? <div className='form-group has-error'><label className='control-label'>{ this.state.server_error }</label></div> : null; + } + render() { + var serverError = null; + if (this.state.serverError) { + serverError = <div className='form-group has-error'><label className='control-label'>{this.state.serverError}</label></div>; + } var self = this; + var describe = ''; + var inputs = []; + + var handleUpdateSection; var desktopSection; if (this.state.activeSection === 'desktop') { var notifyActive = [false, false, false]; - if (this.state.notify_level === "mention") { + if (this.state.notifyLevel === 'mention') { notifyActive[1] = true; - } else if (this.state.notify_level === "all") { + } else if (this.state.notifyLevel === 'all') { notifyActive[0] = true; } else { notifyActive[2] = true; } - var inputs = []; - inputs.push( <div> - <div className="radio"> + <div className='radio'> <label> - <input type="radio" checked={notifyActive[0]} onClick={function(){self.handleRadioClick("all")}}>For all activity</input> + <input + type='radio' + checked={notifyActive[0]} + onChange={self.handleRadioClick.bind(this, 'all')} + > + For all activity + </input> </label> <br/> </div> - <div className="radio"> + <div className='radio'> <label> - <input type="radio" checked={notifyActive[1]} onClick={function(){self.handleRadioClick("mention")}}>Only for mentions</input> + <input + type='radio' + checked={notifyActive[1]} + onChange={self.handleRadioClick.bind(this, 'mention')} + > + Only for mentions + </input> </label> <br/> </div> - <div className="radio"> + <div className='radio'> <label> - <input type="radio" checked={notifyActive[2]} onClick={function(){self.handleRadioClick("none")}}>Never</input> + <input + type='radio' + checked={notifyActive[2]} + onChange={self.handleRadioClick.bind(this, 'none')} + > + Never + </input> </label> </div> </div> ); + handleUpdateSection = function updateSection(e) { + self.updateSection(''); + self.onListenerChange(); + e.preventDefault(); + }; + desktopSection = ( <SettingItemMax - title="Send desktop notifications" + title='Send desktop notifications' inputs={inputs} submit={this.handleUpdate} - server_error={server_error} - updateSection={function(e){self.updateSection("");self._onChange();e.preventDefault();}} + server_error={serverError} + updateSection={handleUpdateSection} /> ); } else { - var describe = ""; - if (this.state.notify_level === "mention") { - describe = "Only for mentions"; - } else if (this.state.notify_level === "all") { - describe = "For all activity"; + if (this.state.notifyLevel === 'mention') { + describe = 'Only for mentions'; + } else if (this.state.notifyLevel === 'all') { + describe = 'For all activity'; } else { - describe = "Never"; + describe = 'Never'; } + handleUpdateSection = function updateSection(e) { + self.updateSection('desktop'); + e.preventDefault(); + }; + desktopSection = ( <SettingItemMin - title="Send desktop notifications" + title='Send desktop notifications' describe={describe} - updateSection={function(e){self.updateSection("desktop");e.preventDefault();}} + updateSection={handleUpdateSection} /> ); } var quietSection; if (this.state.activeSection === 'quiet') { - var quietActive = ["",""]; - if (this.state.quiet_mode) { - quietActive[0] = "active"; + var quietActive = [false, false]; + if (this.state.quietMode) { + quietActive[0] = true; } else { - quietActive[1] = "active"; + quietActive[1] = true; } - var inputs = []; - inputs.push( <div> - <div className="btn-group" data-toggle="buttons-radio"> - <button className={"btn btn-default "+quietActive[0]} onClick={function(){self.handleQuietToggle(true)}}>On</button> - <button className={"btn btn-default "+quietActive[1]} onClick={function(){self.handleQuietToggle(false)}}>Off</button> + <div className='radio'> + <label> + <input + type='radio' + checked={quietActive[0]} + onChange={self.handleQuietToggle.bind(this, true)} + > + On + </input> + </label> + <br/> + </div> + <div className='radio'> + <label> + <input + type='radio' + checked={quietActive[1]} + onChange={self.handleQuietToggle.bind(this, false)} + > + Off + </input> + </label> + <br/> </div> </div> ); @@ -173,62 +244,85 @@ module.exports = React.createClass({ </div> ); + handleUpdateSection = function updateSection(e) { + self.updateSection(''); + self.onListenerChange(); + e.preventDefault(); + }; + quietSection = ( <SettingItemMax - title="Quiet mode" + title='Quiet mode' inputs={inputs} submit={this.handleUpdate} - server_error={server_error} - updateSection={function(e){self.updateSection("");self._onChange();e.preventDefault();}} + server_error={serverError} + updateSection={handleUpdateSection} /> ); } else { - var describe = ""; - if (this.state.quiet_mode) { - describe = "On"; + if (this.state.quietMode) { + describe = 'On'; } else { - describe = "Off"; + describe = 'Off'; } + handleUpdateSection = function updateSection(e) { + self.updateSection('quiet'); + e.preventDefault(); + }; + quietSection = ( <SettingItemMin - title="Quiet mode" + title='Quiet mode' describe={describe} - updateSection={function(e){self.updateSection("quiet");e.preventDefault();}} + updateSection={handleUpdateSection} /> ); } - var self = this; return ( - <div className="modal fade" id="channel_notifications" ref="modal" tabIndex="-1" role="dialog" aria-hidden="true"> - <div className="modal-dialog settings-modal"> - <div className="modal-content"> - <div className="modal-header"> - <button type="button" className="close" data-dismiss="modal"> - <span aria-hidden="true">×</span> - <span className="sr-only">Close</span> + <div + className='modal fade' + id='channel_notifications' + ref='modal' + tabIndex='-1' + role='dialog' + aria-hidden='true' + > + <div className='modal-dialog settings-modal'> + <div className='modal-content'> + <div className='modal-header'> + <button + type='button' + className='close' + data-dismiss='modal' + > + <span aria-hidden='true'>×</span> + <span className='sr-only'>Close</span> </button> - <h4 className="modal-title">{"Notification Preferences for " + this.state.title}</h4> + <h4 className='modal-title'>{'Notification Preferences for ' + this.state.title}</h4> </div> - <div className="modal-body"> - <div className="settings-table"> - <div className="settings-content"> - <div ref="wrapper" className="user-settings"> + <div className='modal-body'> + <div className='settings-table'> + <div className='settings-content'> + <div + ref='wrapper' + className='user-settings' + > <br/> - <div className="divider-dark first"/> + <div className='divider-dark first'/> {desktopSection} - <div className="divider-light"/> + <div className='divider-light'/> {quietSection} - <div className="divider-dark"/> + <div className='divider-dark'/> </div> </div> </div> - { server_error } + {serverError} </div> </div> </div> </div> ); } -}); +} diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx index 3aa8cc39b..efaa40577 100644 --- a/web/react/components/create_post.jsx +++ b/web/react/components/create_post.jsx @@ -223,7 +223,7 @@ module.exports = React.createClass({ var previews = []; var messageText = ''; - var uploadsInProgress = 0; + var uploadsInProgress = []; if (draft && draft.previews && draft.message) { previews = draft.previews; messageText = draft.message; @@ -239,7 +239,7 @@ module.exports = React.createClass({ var draft = PostStore.getCurrentDraft(); var previews = []; var messageText = ''; - var uploadsInProgress = 0; + var uploadsInProgress = []; if (draft && draft.previews && draft.message) { previews = draft.previews; messageText = draft.message; diff --git a/web/react/components/edit_channel_modal.jsx b/web/react/components/edit_channel_modal.jsx index dcff5b89d..1a633b193 100644 --- a/web/react/components/edit_channel_modal.jsx +++ b/web/react/components/edit_channel_modal.jsx @@ -56,7 +56,7 @@ module.exports = React.createClass({ <div className="modal-content"> <div className="modal-header"> <button type="button" className="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button> - <h4 className="modal-title" ref="title">Edit {this.state.title} Description</h4> + <h4 className="modal-title" ref="title">Edit Description for {this.state.title}</h4> </div> <div className="modal-body"> <textarea className="form-control no-resize" rows="6" ref="channelDesc" maxLength="1024" value={this.state.description} onChange={this.handleUserInput}></textarea> diff --git a/web/react/components/file_upload.jsx b/web/react/components/file_upload.jsx index 7497ec330..e77982559 100644 --- a/web/react/components/file_upload.jsx +++ b/web/react/components/file_upload.jsx @@ -219,7 +219,7 @@ module.exports = React.createClass({ continue; } - var channelId = this.props.channelId || ChannelStore.getCurrentId(); + var channelId = self.props.channelId || ChannelStore.getCurrentId(); // generate a unique id that can be used by other components to refer back to this file upload var clientId = utils.generateId(); diff --git a/web/react/components/setting_item_max.jsx b/web/react/components/setting_item_max.jsx index fd95b8b32..1599041b0 100644 --- a/web/react/components/setting_item_max.jsx +++ b/web/react/components/setting_item_max.jsx @@ -20,7 +20,7 @@ module.exports = React.createClass({ <hr /> { server_error } { clientError } - { this.props.submit ? <a className="btn btn-sm btn-primary" onClick={this.props.submit}>Submit</a> : "" } + { this.props.submit ? <a className="btn btn-sm btn-primary" href="#" onClick={this.props.submit}>Submit</a> : "" } <a className="btn btn-sm theme" href="#" onClick={this.props.updateSection}>Cancel</a> </li> </ul> diff --git a/web/react/components/team_signup_send_invites_page.jsx b/web/react/components/team_signup_send_invites_page.jsx index 4bc03798b..a1e12661e 100644 --- a/web/react/components/team_signup_send_invites_page.jsx +++ b/web/react/components/team_signup_send_invites_page.jsx @@ -6,13 +6,18 @@ var utils = require('../utils/utils.jsx'); var ConfigStore = require('../stores/config_store.jsx'); var client = require('../utils/client.jsx'); -module.exports = React.createClass({ - displayName: 'TeamSignupSendInivtesPage', - propTypes: { - state: React.PropTypes.object, - updateParent: React.PropTypes.func - }, - submitBack: function(e) { +export default class TeamSignupSendInvitesPage extends React.Component { + constructor(props) { + super(props); + this.submitBack = this.submitBack.bind(this); + this.submitNext = this.submitNext.bind(this); + this.submitAddInvite = this.submitAddInvite.bind(this); + this.submitSkip = this.submitSkip.bind(this); + this.state = { + emailEnabled: !ConfigStore.getSettingAsBoolean('ByPassEmail', false) + }; + } + submitBack(e) { e.preventDefault(); if (config.AllowSignupDomainsWizard) { @@ -22,8 +27,8 @@ module.exports = React.createClass({ } this.props.updateParent(this.props.state); - }, - submitNext: function(e) { + } + submitNext(e) { e.preventDefault(); var valid = true; @@ -48,8 +53,8 @@ module.exports = React.createClass({ this.props.state.wizard = 'username'; this.props.updateParent(this.props.state); } - }, - submitAddInvite: function(e) { + } + submitAddInvite(e) { e.preventDefault(); this.props.state.wizard = 'send_invites'; if (!this.props.state.invites) { @@ -57,18 +62,19 @@ module.exports = React.createClass({ } this.props.state.invites.push(''); this.props.updateParent(this.props.state); - }, - submitSkip: function(e) { + } + submitSkip(e) { e.preventDefault(); this.props.state.wizard = 'username'; this.props.updateParent(this.props.state); - }, - getInitialState: function() { - return { - emailEnabled: !ConfigStore.getSettingAsBoolean('ByPassEmail', false) - }; - }, - render: function() { + } + componentWillMount() { + if (!this.state.emailEnabled) { + this.props.state.wizard = 'username'; + this.props.updateParent(this.props.state); + } + } + render() { client.track('signup', 'signup_team_05_send_invites'); var content = null; @@ -79,43 +85,95 @@ module.exports = React.createClass({ for (var i = 0; i < this.props.state.invites.length; i++) { if (i === 0) { - emails.push(<EmailItem focus={true} key={i} ref={'email_' + i} email={this.props.state.invites[i]} />); + emails.push( + <EmailItem + focus={true} + key={i} + ref={'email_' + i} + email={this.props.state.invites[i]} + /> + ); } else { - emails.push(<EmailItem focus={false} key={i} ref={'email_' + i} email={this.props.state.invites[i]} />); + emails.push( + <EmailItem + focus={false} + key={i} + ref={'email_' + i} + email={this.props.state.invites[i]} + /> + ); } } content = ( <div> {emails} - <div className='form-group text-right'><a href='#' onClick={this.submitAddInvite}>Add Invitation</a></div> + <div className='form-group text-right'> + <a + href='#' + onClick={this.submitAddInvite} + > + Add Invitation + </a> + </div> </div> ); bottomContent = ( - <p className='color--light'>{'if you prefer, you can invite ' + strings.Team + ' members later'}<br /> and <a href='#' onClick={this.submitSkip}>skip this step</a> for now.</p> + <p className='color--light'> + {'if you prefer, you can invite ' + strings.Team + ' members later'} + <br /> + {' and '} + <a + href='#' + onClick={this.submitSkip} + > + {'skip this step '} + </a> + {'for now.'} + </p> ); } else { content = ( - <div className='form-group color--light'>{'Email is currently disabled for your ' + strings.Team + ', and emails cannot be sent. Contact your system administrator to enable email and email invitations.'}</div> + <div className='form-group color--light'> + {'Email is currently disabled for your ' + strings.Team + ', and emails cannot be sent. Contact your system administrator to enable email and email invitations.'} + </div> ); } return ( <div> <form> - <img className='signup-team-logo' src='/static/images/logo.png' /> + <img + className='signup-team-logo' + src='/static/images/logo.png' + /> <h2>{'Invite ' + utils.toTitleCase(strings.Team) + ' Members'}</h2> {content} <div className='form-group'> - <button type='submit' className='btn-primary btn' onClick={this.submitNext}>Next<i className='glyphicon glyphicon-chevron-right'></i></button> + <button + type='submit' + className='btn-primary btn' + onClick={this.submitNext} + > + Next<i className='glyphicon glyphicon-chevron-right' /> + </button> </div> </form> {bottomContent} <div className='margin--extra'> - <a href='#' onClick={this.submitBack}>Back to previous step</a> + <a + href='#' + onClick={this.submitBack} + > + Back to previous step + </a> </div> </div> ); } -}); +} +TeamSignupSendInvitesPage.propTypes = { + state: React.PropTypes.object.isRequired, + updateParent: React.PropTypes.func.isRequired +}; diff --git a/web/react/components/user_settings_notifications.jsx b/web/react/components/user_settings_notifications.jsx index 33ae01eaa..6637bbcb5 100644 --- a/web/react/components/user_settings_notifications.jsx +++ b/web/react/components/user_settings_notifications.jsx @@ -67,16 +67,28 @@ function getNotificationsStateFromStores() { 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}; } -module.exports = React.createClass({ - displayName: 'NotificationsTab', - propTypes: { - user: React.PropTypes.object, - updateSection: React.PropTypes.func, - updateTab: React.PropTypes.func, - activeSection: React.PropTypes.string, - activeTab: React.PropTypes.string - }, - handleSubmit: function() { +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; @@ -110,66 +122,63 @@ module.exports = React.createClass({ this.setState({serverError: err.message}); }.bind(this) ); - }, - handleClose: function() { - $(this.getDOMNode()).find('.form-control').each(function clearField() { + } + handleClose() { + $(React.findDOMNode(this)).find('.form-control').each(function clearField() { this.value = ''; }); this.setState(assign({}, getNotificationsStateFromStores(), {serverError: null})); this.props.updateTab('general'); - }, - updateSection: function(section) { + } + updateSection(section) { this.setState(this.getInitialState()); this.props.updateSection(section); - }, - componentDidMount: function() { + } + componentDidMount() { UserStore.addChangeListener(this.onListenerChange); $('#user_settings').on('hidden.bs.modal', this.handleClose); - }, - componentWillUnmount: function() { + } + componentWillUnmount() { UserStore.removeChangeListener(this.onListenerChange); $('#user_settings').off('hidden.bs.modal', this.handleClose); this.props.updateSection(''); - }, - onListenerChange: function() { + } + onListenerChange() { var newState = getNotificationsStateFromStores(); if (!utils.areStatesEqual(newState, this.state)) { this.setState(newState); } - }, - getInitialState: function() { - return getNotificationsStateFromStores(); - }, - handleNotifyRadio: function(notifyLevel) { + } + handleNotifyRadio(notifyLevel) { this.setState({notifyLevel: notifyLevel}); this.refs.wrapper.getDOMNode().focus(); - }, - handleEmailRadio: function(enableEmail) { + } + handleEmailRadio(enableEmail) { this.setState({enableEmail: enableEmail}); this.refs.wrapper.getDOMNode().focus(); - }, - handleSoundRadio: function(enableSound) { + } + handleSoundRadio(enableSound) { this.setState({enableSound: enableSound}); this.refs.wrapper.getDOMNode().focus(); - }, - updateUsernameKey: function(val) { + } + updateUsernameKey(val) { this.setState({usernameKey: val}); - }, - updateMentionKey: function(val) { + } + updateMentionKey(val) { this.setState({mentionKey: val}); - }, - updateFirstNameKey: function(val) { + } + updateFirstNameKey(val) { this.setState({firstNameKey: val}); - }, - updateAllKey: function(val) { + } + updateAllKey(val) { this.setState({allKey: val}); - }, - updateChannelKey: function(val) { + } + updateChannelKey(val) { this.setState({channelKey: val}); - }, - updateCustomMentionKeys: function() { + } + updateCustomMentionKeys() { var checked = this.refs.customcheck.getDOMNode().checked; if (checked) { @@ -180,12 +189,12 @@ module.exports = React.createClass({ } else { this.setState({customKeys: '', customKeysChecked: false}); } - }, - onCustomChange: function() { + } + onCustomChange() { this.refs.customcheck.getDOMNode().checked = true; this.updateCustomMentionKeys(); - }, - render: function() { + } + render() { var serverError = null; if (this.state.serverError) { serverError = this.state.serverError; @@ -196,6 +205,7 @@ module.exports = React.createClass({ var user = this.props.user; var desktopSection; + var handleUpdateDesktopSection; if (this.props.activeSection === 'desktop') { var notifyActive = [false, false, false]; if (this.state.notifyLevel === 'mention') { @@ -206,41 +216,63 @@ module.exports = React.createClass({ notifyActive[0] = true; } - var inputs = []; + let inputs = []; inputs.push( <div> <div className='radio'> <label> - <input type='radio' checked={notifyActive[0]} onClick={function(){self.handleNotifyRadio('all')}}>For all activity</input> + <input type='radio' + checked={notifyActive[0]} + onChange={self.handleNotifyRadio.bind(this, 'all')} + > + For all activity + </input> </label> <br/> </div> <div className='radio'> <label> - <input type='radio' checked={notifyActive[1]} onClick={function(){self.handleNotifyRadio('mention')}}>Only for mentions and private messages</input> + <input + type='radio' + checked={notifyActive[1]} + onChange={self.handleNotifyRadio.bind(this, 'mention')} + > + Only for mentions and private messages + </input> </label> <br/> </div> <div className='radio'> <label> - <input type='radio' checked={notifyActive[2]} onClick={function(){self.handleNotifyRadio('none')}}>Never</input> + <input + type='radio' + checked={notifyActive[2]} + onChange={self.handleNotifyRadio.bind(this, 'none')} + > + Never + </input> </label> </div> </div> ); + handleUpdateDesktopSection = function updateDesktopSection(e) { + self.props.updateSection(''); + e.preventDefault(); + }; + desktopSection = ( <SettingItemMax title='Send desktop notifications' inputs={inputs} submit={this.handleSubmit} server_error={serverError} - updateSection={function(e){self.updateSection('');e.preventDefault();}} + updateSection={handleUpdateDesktopSection} /> ); } else { - var describe = ''; + let describe = ''; if (this.state.notifyLevel === 'mention') { describe = 'Only for mentions and private messages'; } else if (this.state.notifyLevel === 'none') { @@ -249,162 +281,278 @@ module.exports = React.createClass({ describe = 'For all activity'; } + handleUpdateDesktopSection = function updateDesktopSection() { + self.props.updateSection('desktop'); + }; + desktopSection = ( <SettingItemMin title='Send desktop notifications' describe={describe} - updateSection={function(){self.updateSection('desktop');}} + updateSection={handleUpdateDesktopSection} /> ); } var soundSection; + var handleUpdateSoundSection; if (this.props.activeSection === 'sound' && this.state.soundNeeded) { - var soundActive = ['', '']; + var soundActive = [false, false]; if (this.state.enableSound === 'false') { - soundActive[1] = 'active'; + soundActive[1] = true; } else { - soundActive[0] = 'active'; + soundActive[0] = true; } - var inputs = []; + let inputs = []; inputs.push( <div> - <div className='btn-group' data-toggle='buttons-radio'> - <button className={'btn btn-default '+soundActive[0]} onClick={function(){self.handleSoundRadio('true')}}>On</button> - <button className={'btn btn-default '+soundActive[1]} onClick={function(){self.handleSoundRadio('false')}}>Off</button> + <div className='radio'> + <label> + <input + type='radio' + checked={soundActive[0]} + onChange={self.handleSoundRadio.bind(this, 'true')} + > + On + </input> + </label> + <br/> </div> - </div> + <div className='radio'> + <label> + <input + type='radio' + checked={soundActive[1]} + onChange={self.handleSoundRadio.bind(this, 'false')} + > + Off + </input> + </label> + <br/> + </div> + </div> ); + handleUpdateSoundSection = function updateSoundSection(e) { + self.props.updateSection(''); + e.preventDefault(); + }; + soundSection = ( <SettingItemMax title='Desktop notification sounds' inputs={inputs} submit={this.handleSubmit} server_error={serverError} - updateSection={function(e){self.updateSection('');e.preventDefault();}} + updateSection={handleUpdateSoundSection} /> ); } else { - var describe = ''; + let describe = ''; if (!this.state.soundNeeded) { - describe = 'Please configure notification sounds in your browser settings' + describe = 'Please configure notification sounds in your browser settings'; } else if (this.state.enableSound === 'false') { describe = 'Off'; } else { describe = 'On'; } + handleUpdateSoundSection = function updateSoundSection() { + self.props.updateSection('sound'); + }; + soundSection = ( <SettingItemMin title='Desktop notification sounds' describe={describe} - updateSection={function(){self.updateSection('sound');}} + updateSection={handleUpdateSoundSection} disableOpen = {!this.state.soundNeeded} /> ); } var emailSection; + var handleUpdateEmailSection; if (this.props.activeSection === 'email') { - var emailActive = ['','']; + var emailActive = [false, false]; if (this.state.enableEmail === 'false') { - emailActive[1] = 'active'; + emailActive[1] = true; } else { - emailActive[0] = 'active'; + emailActive[0] = true; } - var inputs = []; + let inputs = []; inputs.push( <div> - <div className='btn-group' data-toggle='buttons-radio'> - <button className={'btn btn-default '+emailActive[0]} onClick={function(){self.handleEmailRadio('true')}}>On</button> - <button className={'btn btn-default '+emailActive[1]} onClick={function(){self.handleEmailRadio('false')}}>Off</button> + <div className='radio'> + <label> + <input + type='radio' + checked={emailActive[0]} + onChange={self.handleEmailRadio.bind(this, 'true')} + > + On + </input> + </label> + <br/> + </div> + <div className='radio'> + <label> + <input + type='radio' + checked={emailActive[1]} + onChange={self.handleEmailRadio.bind(this, 'false')} + > + Off + </input> + </label> + <br/> </div> <div><br/>{'Email notifications are sent for mentions and private messages after you have been away from ' + config.SiteName + ' for 5 minutes.'}</div> </div> ); + handleUpdateEmailSection = function updateEmailSection(e) { + self.props.updateSection(''); + e.preventDefault(); + }; + emailSection = ( <SettingItemMax title='Email notifications' inputs={inputs} submit={this.handleSubmit} server_error={serverError} - updateSection={function(e){self.updateSection('');e.preventDefault();}} + updateSection={handleUpdateEmailSection} /> ); } else { - var describe = ''; + let describe = ''; if (this.state.enableEmail === 'false') { describe = 'Off'; } else { describe = 'On'; } + handleUpdateEmailSection = function updateEmailSection() { + self.props.updateSection('email'); + }; + emailSection = ( <SettingItemMin title='Email notifications' describe={describe} - updateSection={function(){self.updateSection('email');}} + updateSection={handleUpdateEmailSection} /> ); } var keysSection; + var handleUpdateKeysSection; if (this.props.activeSection === 'keys') { - var inputs = []; + let inputs = []; + + let handleUpdateFirstNameKey; + let handleUpdateUsernameKey; + let handleUpdateMentionKey; + let handleUpdateAllKey; + let handleUpdateChannelKey; if (user.first_name) { + handleUpdateFirstNameKey = function handleFirstNameKeyChange(e) { + self.updateFirstNameKey(e.target.checked); + }; inputs.push( <div> <div className='checkbox'> <label> - <input type='checkbox' checked={this.state.firstNameKey} onChange={function(e){self.updateFirstNameKey(e.target.checked);}}>{'Your case sensitive first name "' + user.first_name + '"'}</input> + <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) { + self.updateUsernameKey(e.target.checked); + }; inputs.push( <div> <div className='checkbox'> <label> - <input type='checkbox' checked={this.state.usernameKey} onChange={function(e){self.updateUsernameKey(e.target.checked);}}>{'Your non-case sensitive username "' + user.username + '"'}</input> + <input + type='checkbox' + checked={this.state.usernameKey} + onChange={handleUpdateUsernameKey} + > + {'Your non-case sensitive username "' + user.username + '"'} + </input> </label> </div> </div> ); + handleUpdateMentionKey = function handleMentionKeyChange(e) { + self.updateMentionKey(e.target.checked); + }; inputs.push( <div> <div className='checkbox'> <label> - <input type='checkbox' checked={this.state.mentionKey} onChange={function(e){self.updateMentionKey(e.target.checked);}}>{'Your username mentioned "@' + user.username + '"'}</input> + <input + type='checkbox' + checked={this.state.mentionKey} + onChange={handleUpdateMentionKey} + > + {'Your username mentioned "@' + user.username + '"'} + </input> </label> </div> </div> ); + handleUpdateAllKey = function handleAllKeyChange(e) { + self.updateAllKey(e.target.checked); + }; inputs.push( <div> <div className='checkbox'> <label> - <input type='checkbox' checked={this.state.allKey} onChange={function(e){self.updateAllKey(e.target.checked);}}>{'Team-wide mentions "@all"'}</input> + <input + type='checkbox' + checked={this.state.allKey} + onChange={handleUpdateAllKey} + > + {'Team-wide mentions "@all"'} + </input> </label> </div> </div> ); + handleUpdateChannelKey = function handleChannelKeyChange(e) { + self.updateChannelKey(e.target.checked); + }; inputs.push( <div> <div className='checkbox'> <label> - <input type='checkbox' checked={this.state.channelKey} onChange={function(e){self.updateChannelKey(e.target.checked);}}>{'Channel-wide mentions "@channel"'}</input> + <input + type='checkbox' + checked={this.state.channelKey} + onChange={handleUpdateChannelKey} + > + {'Channel-wide mentions "@channel"'} + </input> </label> </div> </div> @@ -414,32 +562,61 @@ module.exports = React.createClass({ <div> <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> + <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} /> + <input + ref='custommentions' + className='form-control mentions-input' + type='text' + defaultValue={this.state.customKeys} + onChange={this.onCustomChange} + /> </div> ); + handleUpdateKeysSection = function updateKeysSection(e) { + self.props.updateSection(''); + e.preventDefault(); + }; keysSection = ( <SettingItemMax title='Words that trigger mentions' inputs={inputs} submit={this.handleSubmit} server_error={serverError} - updateSection={function(e){self.updateSection('');e.preventDefault();}} + updateSection={handleUpdateKeysSection} /> ); } else { - var 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(',')); - - var describe = ''; + 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] + '", '; } @@ -450,11 +627,15 @@ module.exports = React.createClass({ describe = 'No words configured'; } + handleUpdateKeysSection = function updateKeysSection() { + self.props.updateSection('keys'); + }; + keysSection = ( <SettingItemMin title='Words that trigger mentions' describe={describe} - updateSection={function(){self.updateSection('keys');}} + updateSection={handleUpdateKeysSection} /> ); } @@ -462,10 +643,26 @@ module.exports = React.createClass({ return ( <div> <div className='modal-header'> - <button type='button' className='close' data-dismiss='modal' aria-label='Close'><span aria-hidden='true'>×</span></button> - <h4 className='modal-title' ref='title'><i className='modal-back'></i>Notifications</h4> + <button + type='button' + className='close' + data-dismiss='modal' + aria-label='Close' + > + <span aria-hidden='true'>×</span> + </button> + <h4 + className='modal-title' + ref='title' + > + <i className='modal-back'></i> + Notifications + </h4> </div> - <div ref='wrapper' className='user-settings'> + <div + ref='wrapper' + className='user-settings' + > <h3 className='tab-header'>Notifications</h3> <div className='divider-dark first'/> {desktopSection} @@ -481,4 +678,17 @@ module.exports = React.createClass({ ); } -}); +} + +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 +}; diff --git a/web/react/utils/utils.jsx b/web/react/utils/utils.jsx index df7a1e697..09cd299df 100644 --- a/web/react/utils/utils.jsx +++ b/web/react/utils/utils.jsx @@ -167,7 +167,7 @@ module.exports.displayTime = function(ticks) { var ampm = 'AM'; if (hours >= 12) { - ampm = 'AM'; + ampm = 'PM'; } hours = hours % 12; |