diff options
Diffstat (limited to 'web/react/components/user_settings')
8 files changed, 189 insertions, 77 deletions
diff --git a/web/react/components/user_settings/code_theme_chooser.jsx b/web/react/components/user_settings/code_theme_chooser.jsx deleted file mode 100644 index eef4b24ba..000000000 --- a/web/react/components/user_settings/code_theme_chooser.jsx +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. -// See License.txt for license information. - -var Constants = require('../../utils/constants.jsx'); - -export default class CodeThemeChooser extends React.Component { - constructor(props) { - super(props); - this.state = {}; - } - render() { - const theme = this.props.theme; - - const premadeThemes = []; - for (const k in Constants.CODE_THEMES) { - if (Constants.CODE_THEMES.hasOwnProperty(k)) { - let activeClass = ''; - if (k === theme.codeTheme) { - activeClass = 'active'; - } - - premadeThemes.push( - <div - className='col-xs-6 col-sm-3 premade-themes' - key={'premade-theme-key' + k} - > - <div - className={activeClass} - onClick={() => this.props.updateTheme(k)} - > - <label> - <img - className='img-responsive' - src={'/static/images/themes/code_themes/' + k + '.png'} - /> - <div className='theme-label'>{Constants.CODE_THEMES[k]}</div> - </label> - </div> - </div> - ); - } - } - - return ( - <div className='row'> - {premadeThemes} - </div> - ); - } -} - -CodeThemeChooser.propTypes = { - theme: React.PropTypes.object.isRequired, - updateTheme: React.PropTypes.func.isRequired -}; diff --git a/web/react/components/user_settings/manage_outgoing_hooks.jsx b/web/react/components/user_settings/manage_outgoing_hooks.jsx index 6e9b2205d..4c56db0a1 100644 --- a/web/react/components/user_settings/manage_outgoing_hooks.jsx +++ b/web/react/components/user_settings/manage_outgoing_hooks.jsx @@ -236,6 +236,7 @@ export default class ManageOutgoingHooks extends React.Component { return ( <div key='addOutgoingHook'> <label className='control-label'>{'Add a new outgoing webhook'}</label> + <div className='padding-top divider-light'></div> <div className='padding-top'> <div> <label className='control-label'>{'Channel'}</label> diff --git a/web/react/components/user_settings/user_settings.jsx b/web/react/components/user_settings/user_settings.jsx index 15bf961d6..546e26ca3 100644 --- a/web/react/components/user_settings/user_settings.jsx +++ b/web/react/components/user_settings/user_settings.jsx @@ -10,6 +10,7 @@ var AppearanceTab = require('./user_settings_appearance.jsx'); var DeveloperTab = require('./user_settings_developer.jsx'); var IntegrationsTab = require('./user_settings_integrations.jsx'); var DisplayTab = require('./user_settings_display.jsx'); +var AdvancedTab = require('./user_settings_advanced.jsx'); export default class UserSettings extends React.Component { constructor(props) { @@ -110,6 +111,17 @@ export default class UserSettings extends React.Component { /> </div> ); + } else if (this.props.activeTab === 'advanced') { + return ( + <div> + <AdvancedTab + user={this.state.user} + activeSection={this.props.activeSection} + updateSection={this.props.updateSection} + updateTab={this.props.updateTab} + /> + </div> + ); } return <div/>; diff --git a/web/react/components/user_settings/user_settings_advanced.jsx b/web/react/components/user_settings/user_settings_advanced.jsx new file mode 100644 index 000000000..910444735 --- /dev/null +++ b/web/react/components/user_settings/user_settings_advanced.jsx @@ -0,0 +1,169 @@ +// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +const Client = require('../../utils/client.jsx'); +const SettingItemMin = require('../setting_item_min.jsx'); +const SettingItemMax = require('../setting_item_max.jsx'); +const Constants = require('../../utils/constants.jsx'); +const PreferenceStore = require('../../stores/preference_store.jsx'); + +export default class AdvancedSettingsDisplay extends React.Component { + constructor(props) { + super(props); + + this.updateSection = this.updateSection.bind(this); + this.updateSetting = this.updateSetting.bind(this); + this.handleClose = this.handleClose.bind(this); + this.setupInitialState = this.setupInitialState.bind(this); + + this.state = this.setupInitialState(); + } + + setupInitialState() { + const sendOnCtrlEnter = PreferenceStore.getPreference( + Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, + 'send_on_ctrl_enter', + {value: 'false'} + ).value; + + return { + settings: {send_on_ctrl_enter: sendOnCtrlEnter} + }; + } + + updateSetting(setting, value) { + const settings = this.state.settings; + settings[setting] = value; + this.setState(settings); + } + + handleSubmit(setting) { + const preference = PreferenceStore.setPreference( + Constants.Preferences.CATEGORY_ADVANCED_SETTINGS, + setting, + this.state.settings[setting] + ); + + Client.savePreferences([preference], + () => { + PreferenceStore.emitChange(); + this.updateSection(''); + }, + (err) => { + this.setState({serverError: err.message}); + } + ); + } + + updateSection(section) { + this.props.updateSection(section); + } + + handleClose() { + this.updateSection(''); + } + + componentDidMount() { + $('#user_settings').on('hidden.bs.modal', this.handleClose); + } + + componentWillUnmount() { + $('#user_settings').off('hidden.bs.modal', this.handleClose); + } + + render() { + const serverError = this.state.serverError || null; + let ctrlSendSection; + + if (this.props.activeSection === 'advancedCtrlSend') { + const ctrlSendActive = [ + this.state.settings.send_on_ctrl_enter === 'true', + this.state.settings.send_on_ctrl_enter === 'false' + ]; + + const inputs = [ + <div key='ctrlSendSetting'> + <div className='radio'> + <label> + <input + type='radio' + checked={ctrlSendActive[0]} + onChange={this.updateSetting.bind(this, 'send_on_ctrl_enter', 'true')} + /> + {'On'} + </label> + <br/> + </div> + <div className='radio'> + <label> + <input + type='radio' + checked={ctrlSendActive[1]} + onChange={this.updateSetting.bind(this, 'send_on_ctrl_enter', 'false')} + /> + {'Off'} + </label> + <br/> + </div> + <div><br/>{'If enabled \'Enter\' inserts a new line and \'Ctrl + Enter\' submits the message.'}</div> + </div> + ]; + + ctrlSendSection = ( + <SettingItemMax + title='Send messages on Ctrl + Enter' + inputs={inputs} + submit={() => this.handleSubmit('send_on_ctrl_enter')} + server_error={serverError} + updateSection={(e) => { + this.updateSection(''); + e.preventDefault(); + }} + /> + ); + } else { + ctrlSendSection = ( + <SettingItemMin + title='Send messages on Ctrl + Enter' + describe={this.state.settings.send_on_ctrl_enter === 'true' ? 'On' : 'Off'} + updateSection={() => this.props.updateSection('advancedCtrlSend')} + /> + ); + } + + 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> + {'Advanced Settings'} + </h4> + </div> + <div className='user-settings'> + <h3 className='tab-header'>{'Advanced Settings'}</h3> + <div className='divider-dark first'/> + {ctrlSendSection} + <div className='divider-dark'/> + </div> + </div> + ); + } +} + +AdvancedSettingsDisplay.propTypes = { + user: React.PropTypes.object, + updateSection: React.PropTypes.func, + updateTab: React.PropTypes.func, + activeSection: React.PropTypes.string +}; diff --git a/web/react/components/user_settings/user_settings_appearance.jsx b/web/react/components/user_settings/user_settings_appearance.jsx index e94894a1d..8c62a189d 100644 --- a/web/react/components/user_settings/user_settings_appearance.jsx +++ b/web/react/components/user_settings/user_settings_appearance.jsx @@ -7,7 +7,6 @@ var Utils = require('../../utils/utils.jsx'); const CustomThemeChooser = require('./custom_theme_chooser.jsx'); const PremadeThemeChooser = require('./premade_theme_chooser.jsx'); -const CodeThemeChooser = require('./code_theme_chooser.jsx'); const AppDispatcher = require('../../dispatcher/app_dispatcher.jsx'); const Constants = require('../../utils/constants.jsx'); const ActionTypes = Constants.ActionTypes; @@ -19,14 +18,12 @@ export default class UserSettingsAppearance extends React.Component { this.onChange = this.onChange.bind(this); this.submitTheme = this.submitTheme.bind(this); this.updateTheme = this.updateTheme.bind(this); - this.updateCodeTheme = this.updateCodeTheme.bind(this); this.handleClose = this.handleClose.bind(this); this.handleImportModal = this.handleImportModal.bind(this); this.state = this.getStateFromStores(); this.originalTheme = this.state.theme; - this.originalCodeTheme = this.state.theme.codeTheme; } componentDidMount() { UserStore.addChangeListener(this.onChange); @@ -61,10 +58,6 @@ export default class UserSettingsAppearance extends React.Component { type = 'custom'; } - if (!theme.codeTheme) { - theme.codeTheme = Constants.DEFAULT_CODE_THEME; - } - return {theme, type}; } onChange() { @@ -100,13 +93,6 @@ export default class UserSettingsAppearance extends React.Component { ); } updateTheme(theme) { - theme.codeTheme = this.state.theme.codeTheme; - this.setState({theme}); - Utils.applyTheme(theme); - } - updateCodeTheme(codeTheme) { - var theme = this.state.theme; - theme.codeTheme = codeTheme; this.setState({theme}); Utils.applyTheme(theme); } @@ -116,7 +102,6 @@ export default class UserSettingsAppearance extends React.Component { handleClose() { const state = this.getStateFromStores(); state.serverError = null; - state.theme.codeTheme = this.originalCodeTheme; Utils.applyTheme(state.theme); @@ -185,13 +170,7 @@ export default class UserSettingsAppearance extends React.Component { </div> {custom} <hr /> - <strong className='radio'>{'Code Theme'}</strong> - <CodeThemeChooser - theme={this.state.theme} - updateTheme={this.updateCodeTheme} - /> - <hr /> - {serverError} + {serverError} <a className='btn btn-sm btn-primary' href='#' diff --git a/web/react/components/user_settings/user_settings_general.jsx b/web/react/components/user_settings/user_settings_general.jsx index 1c8ce3c79..3adac197a 100644 --- a/web/react/components/user_settings/user_settings_general.jsx +++ b/web/react/components/user_settings/user_settings_general.jsx @@ -570,6 +570,7 @@ export default class UserSettingsGeneralTab extends React.Component { /> ); } + return ( <div> <div className='modal-header'> diff --git a/web/react/components/user_settings/user_settings_integrations.jsx b/web/react/components/user_settings/user_settings_integrations.jsx index 4b1e5e532..9bee74343 100644 --- a/web/react/components/user_settings/user_settings_integrations.jsx +++ b/web/react/components/user_settings/user_settings_integrations.jsx @@ -43,6 +43,7 @@ export default class UserSettingsIntegrationsTab extends React.Component { incomingHooksSection = ( <SettingItemMax title='Incoming Webhooks' + width='medium' inputs={inputs} updateSection={(e) => { this.updateSection(''); @@ -54,6 +55,7 @@ export default class UserSettingsIntegrationsTab extends React.Component { incomingHooksSection = ( <SettingItemMin title='Incoming Webhooks' + width='medium' describe='Manage your incoming webhooks (Developer feature)' updateSection={() => { this.updateSection('incoming-hooks'); @@ -72,6 +74,7 @@ export default class UserSettingsIntegrationsTab extends React.Component { outgoingHooksSection = ( <SettingItemMax title='Outgoing Webhooks' + width='medium' inputs={inputs} updateSection={(e) => { this.updateSection(''); @@ -83,6 +86,7 @@ export default class UserSettingsIntegrationsTab extends React.Component { outgoingHooksSection = ( <SettingItemMin title='Outgoing Webhooks' + width='medium' describe='Manage your outgoing webhooks' updateSection={() => { this.updateSection('outgoing-hooks'); diff --git a/web/react/components/user_settings/user_settings_modal.jsx b/web/react/components/user_settings/user_settings_modal.jsx index 5449ae91e..18dd490e7 100644 --- a/web/react/components/user_settings/user_settings_modal.jsx +++ b/web/react/components/user_settings/user_settings_modal.jsx @@ -43,6 +43,7 @@ export default class UserSettingsModal extends React.Component { tabs.push({name: 'integrations', uiName: 'Integrations', icon: 'glyphicon glyphicon-transfer'}); } tabs.push({name: 'display', uiName: 'Display', icon: 'glyphicon glyphicon-eye-open'}); + tabs.push({name: 'advanced', uiName: 'Advanced', icon: 'glyphicon glyphicon-list-alt'}); return ( <div |