diff options
Diffstat (limited to 'web/react/components')
22 files changed, 254 insertions, 202 deletions
diff --git a/web/react/components/admin_console/service_settings.jsx b/web/react/components/admin_console/service_settings.jsx index 2cc68d1ed..f232d4633 100644 --- a/web/react/components/admin_console/service_settings.jsx +++ b/web/react/components/admin_console/service_settings.jsx @@ -75,6 +75,7 @@ class ServiceSettings extends React.Component { config.ServiceSettings.EnableTesting = ReactDOM.findDOMNode(this.refs.EnableTesting).checked; config.ServiceSettings.EnableDeveloper = ReactDOM.findDOMNode(this.refs.EnableDeveloper).checked; config.ServiceSettings.EnableSecurityFixAlert = ReactDOM.findDOMNode(this.refs.EnableSecurityFixAlert).checked; + config.ServiceSettings.EnableInsecureOutgoingConnections = ReactDOM.findDOMNode(this.refs.EnableInsecureOutgoingConnections).checked; config.ServiceSettings.EnableCommands = ReactDOM.findDOMNode(this.refs.EnableCommands).checked; config.ServiceSettings.EnableOnlyAdminIntegrations = ReactDOM.findDOMNode(this.refs.EnableOnlyAdminIntegrations).checked; @@ -720,6 +721,53 @@ class ServiceSettings extends React.Component { <div className='form-group'> <label className='control-label col-sm-4' + htmlFor='EnableInsecureOutgoingConnections' + > + <FormattedMessage + id='admin.service.insecureTlsTitle' + defaultMessage='Enable Insecure Outgoing Connections: ' + /> + </label> + <div className='col-sm-8'> + <label className='radio-inline'> + <input + type='radio' + name='EnableInsecureOutgoingConnections' + value='true' + ref='EnableInsecureOutgoingConnections' + defaultChecked={this.props.config.ServiceSettings.EnableInsecureOutgoingConnections} + onChange={this.handleChange} + /> + <FormattedMessage + id='admin.service.true' + defaultMessage='true' + /> + </label> + <label className='radio-inline'> + <input + type='radio' + name='EnableInsecureOutgoingConnections' + value='false' + defaultChecked={!this.props.config.ServiceSettings.EnableInsecureOutgoingConnections} + onChange={this.handleChange} + /> + <FormattedMessage + id='admin.service.false' + defaultMessage='false' + /> + </label> + <p className='help-text'> + <FormattedMessage + id='admin.service.insecureTlsDesc' + defaultMessage='When true, any outgoing HTTPS requests will accept unverified, self-signed certificates. For example, outgoing webhooks to a server with a self-signed TLS certificate, using any domain, will be allowed. Note that this makes these connections susceptible to man-in-the-middle attacks.' + /> + </p> + </div> + </div> + + <div className='form-group'> + <label + className='control-label col-sm-4' htmlFor='SessionLengthWebInDays' > <FormattedMessage @@ -896,4 +944,4 @@ ServiceSettings.propTypes = { config: React.PropTypes.object }; -export default injectIntl(ServiceSettings);
\ No newline at end of file +export default injectIntl(ServiceSettings); diff --git a/web/react/components/channel_header.jsx b/web/react/components/channel_header.jsx index 8fc3cd63d..a827cbcc6 100644 --- a/web/react/components/channel_header.jsx +++ b/web/react/components/channel_header.jsx @@ -114,7 +114,7 @@ export default class ChannelHeader extends React.Component { } AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH_TERM, + type: ActionTypes.RECEIVED_SEARCH_TERM, term: terms, do_search: true, is_mention_search: true diff --git a/web/react/components/create_comment.jsx b/web/react/components/create_comment.jsx index 709485991..55dd8276c 100644 --- a/web/react/components/create_comment.jsx +++ b/web/react/components/create_comment.jsx @@ -152,7 +152,7 @@ class CreateComment extends React.Component { ChannelStore.setChannelMember(member); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST, + type: ActionTypes.RECEIVED_POST, post: data }); }.bind(this), @@ -216,7 +216,7 @@ class CreateComment extends React.Component { } AppDispatcher.handleViewAction({ - type: ActionTypes.RECIEVED_EDIT_POST, + type: ActionTypes.RECEIVED_EDIT_POST, refocusId: '#reply_textbox', title: this.props.intl.formatMessage(holders.commentTitle), message: lastPost.message, diff --git a/web/react/components/create_post.jsx b/web/react/components/create_post.jsx index ecabdaee6..b9fbf09b5 100644 --- a/web/react/components/create_post.jsx +++ b/web/react/components/create_post.jsx @@ -364,7 +364,7 @@ class CreatePost extends React.Component { var type = (lastPost.root_id && lastPost.root_id.length > 0) ? formatMessage(holders.comment) : formatMessage(holders.post); AppDispatcher.handleViewAction({ - type: ActionTypes.RECIEVED_EDIT_POST, + type: ActionTypes.RECEIVED_EDIT_POST, refocusId: '#post_textbox', title: type, message: lastPost.message, diff --git a/web/react/components/delete_post_modal.jsx b/web/react/components/delete_post_modal.jsx index 9d7dcb3e5..65ffa96a1 100644 --- a/web/react/components/delete_post_modal.jsx +++ b/web/react/components/delete_post_modal.jsx @@ -62,12 +62,12 @@ export default class DeletePostModal extends React.Component { var selectedPost = selectedList.posts[selectedList.order[0]]; if ((selectedPost.id === this.state.post.id && !this.state.root_id) || selectedPost.root_id === this.state.post.id) { AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH, + type: ActionTypes.RECEIVED_SEARCH, results: null }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST_SELECTED, + type: ActionTypes.RECEIVED_POST_SELECTED, results: null }); } else if (selectedPost.id === this.state.post.id && this.state.root_id) { @@ -76,12 +76,12 @@ export default class DeletePostModal extends React.Component { delete selectedList.posts[selectedPost.id]; AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST_SELECTED, + type: ActionTypes.RECEIVED_POST_SELECTED, post_list: selectedList }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH, + type: ActionTypes.RECEIVED_SEARCH, results: null }); } diff --git a/web/react/components/edit_channel_header_modal.jsx b/web/react/components/edit_channel_header_modal.jsx index 1066d123e..f6865fadd 100644 --- a/web/react/components/edit_channel_header_modal.jsx +++ b/web/react/components/edit_channel_header_modal.jsx @@ -68,7 +68,7 @@ class EditChannelHeaderModal extends React.Component { this.onHide(); AppDispatcher.handleServerAction({ - type: Constants.ActionTypes.RECIEVED_CHANNEL, + type: Constants.ActionTypes.RECEIVED_CHANNEL, channel }); }, diff --git a/web/react/components/navbar.jsx b/web/react/components/navbar.jsx index 8005678a2..e6a9fbd25 100644 --- a/web/react/components/navbar.jsx +++ b/web/react/components/navbar.jsx @@ -82,12 +82,12 @@ export default class Navbar extends React.Component { var windowWidth = $(window).outerWidth(); if (windowWidth <= 768) { AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH, + type: ActionTypes.RECEIVED_SEARCH, results: null }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST_SELECTED, + type: ActionTypes.RECEIVED_POST_SELECTED, results: null }); diff --git a/web/react/components/post.jsx b/web/react/components/post.jsx index 53fe7fb5d..3619a9f8f 100644 --- a/web/react/components/post.jsx +++ b/web/react/components/post.jsx @@ -31,12 +31,12 @@ export default class Post extends React.Component { data.posts = this.props.posts; AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST_SELECTED, + type: ActionTypes.RECEIVED_POST_SELECTED, post_list: data }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH, + type: ActionTypes.RECEIVED_SEARCH, results: null }); } @@ -59,7 +59,7 @@ export default class Post extends React.Component { ChannelStore.setChannelMember(member); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST, + type: ActionTypes.RECEIVED_POST, post: data }); }, diff --git a/web/react/components/post_deleted_modal.jsx b/web/react/components/post_deleted_modal.jsx index 218f57eb5..642befeab 100644 --- a/web/react/components/post_deleted_modal.jsx +++ b/web/react/components/post_deleted_modal.jsx @@ -24,19 +24,19 @@ export default class PostDeletedModal extends React.Component { } handleClose() { AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH, + type: ActionTypes.RECEIVED_SEARCH, results: null }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH_TERM, + type: ActionTypes.RECEIVED_SEARCH_TERM, term: null, do_search: false, is_mention_search: false }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST_SELECTED, + type: ActionTypes.RECEIVED_POST_SELECTED, results: null }); } diff --git a/web/react/components/rhs_comment.jsx b/web/react/components/rhs_comment.jsx index 1addebbe4..9c85e9940 100644 --- a/web/react/components/rhs_comment.jsx +++ b/web/react/components/rhs_comment.jsx @@ -49,7 +49,7 @@ class RhsComment extends React.Component { ChannelStore.setChannelMember(member); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST, + type: ActionTypes.RECEIVED_POST, post: data }); }, @@ -267,4 +267,4 @@ RhsComment.propTypes = { post: React.PropTypes.object }; -export default injectIntl(RhsComment);
\ No newline at end of file +export default injectIntl(RhsComment); diff --git a/web/react/components/rhs_header_post.jsx b/web/react/components/rhs_header_post.jsx index d56ba76f8..cd310df56 100644 --- a/web/react/components/rhs_header_post.jsx +++ b/web/react/components/rhs_header_post.jsx @@ -21,12 +21,12 @@ export default class RhsHeaderPost extends React.Component { e.preventDefault(); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH, + type: ActionTypes.RECEIVED_SEARCH, results: null }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST_SELECTED, + type: ActionTypes.RECEIVED_POST_SELECTED, results: null }); } @@ -34,14 +34,14 @@ export default class RhsHeaderPost extends React.Component { e.preventDefault(); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH_TERM, + type: ActionTypes.RECEIVED_SEARCH_TERM, term: this.props.fromSearch, do_search: true, is_mention_search: this.props.isMentionSearch }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST_SELECTED, + type: ActionTypes.RECEIVED_POST_SELECTED, results: null }); } diff --git a/web/react/components/search_bar.jsx b/web/react/components/search_bar.jsx index 35d7e9514..f7cb1b8f2 100644 --- a/web/react/components/search_bar.jsx +++ b/web/react/components/search_bar.jsx @@ -74,19 +74,19 @@ class SearchBar extends React.Component { e.preventDefault(); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH, + type: ActionTypes.RECEIVED_SEARCH, results: null }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH_TERM, + type: ActionTypes.RECEIVED_SEARCH_TERM, term: null, do_search: false, is_mention_search: false }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST_SELECTED, + type: ActionTypes.RECEIVED_POST_SELECTED, results: null }); } @@ -117,7 +117,7 @@ class SearchBar extends React.Component { } AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH, + type: ActionTypes.RECEIVED_SEARCH, results: data, is_mention_search: isMentionSearch }); diff --git a/web/react/components/search_results_header.jsx b/web/react/components/search_results_header.jsx index 45f56f65a..7f88eb2c7 100644 --- a/web/react/components/search_results_header.jsx +++ b/web/react/components/search_results_header.jsx @@ -19,19 +19,19 @@ export default class SearchResultsHeader extends React.Component { e.preventDefault(); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH, + type: ActionTypes.RECEIVED_SEARCH, results: null }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_SEARCH_TERM, + type: ActionTypes.RECEIVED_SEARCH_TERM, term: null, do_search: false, is_mention_search: false }); AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_POST_SELECTED, + type: ActionTypes.RECEIVED_POST_SELECTED, results: null }); } @@ -72,4 +72,4 @@ export default class SearchResultsHeader extends React.Component { SearchResultsHeader.propTypes = { isMentionSearch: React.PropTypes.bool -};
\ No newline at end of file +}; diff --git a/web/react/components/setting_item_max.jsx b/web/react/components/setting_item_max.jsx index 537055641..ac750614b 100644 --- a/web/react/components/setting_item_max.jsx +++ b/web/react/components/setting_item_max.jsx @@ -46,9 +46,14 @@ export default class SettingItemMax extends React.Component { widthClass = 'col-sm-9 col-sm-offset-3'; } + let title; + if (this.props.title) { + title = <li className='col-sm-12 section-title'>{this.props.title}</li>; + } + return ( <ul className='section-max form-horizontal'> - <li className='col-sm-12 section-title'>{this.props.title}</li> + {title} <li className={widthClass}> <ul className='setting-list'> <li className='setting-list-item'> diff --git a/web/react/components/user_settings/custom_theme_chooser.jsx b/web/react/components/user_settings/custom_theme_chooser.jsx index 9116dd938..2d88a3650 100644 --- a/web/react/components/user_settings/custom_theme_chooser.jsx +++ b/web/react/components/user_settings/custom_theme_chooser.jsx @@ -222,7 +222,7 @@ class CustomThemeChooser extends React.Component { } else { elements.push( <div - className='col-sm-4 form-group' + className='col-sm-4 form-group element' key={'custom-theme-key' + index} > <label className='custom-label'>{formatMessage(messages[element.id])}</label> @@ -265,8 +265,8 @@ class CustomThemeChooser extends React.Component { ); return ( - <div> - <div className='row form-group'> + <div className='appearance-section'> + <div className='theme-elements row form-group'> {elements} </div> <div className='row'> @@ -283,4 +283,4 @@ CustomThemeChooser.propTypes = { updateTheme: React.PropTypes.func.isRequired }; -export default injectIntl(CustomThemeChooser);
\ No newline at end of file +export default injectIntl(CustomThemeChooser); diff --git a/web/react/components/user_settings/import_theme_modal.jsx b/web/react/components/user_settings/import_theme_modal.jsx index 66bed0b0b..e9e90a936 100644 --- a/web/react/components/user_settings/import_theme_modal.jsx +++ b/web/react/components/user_settings/import_theme_modal.jsx @@ -84,7 +84,7 @@ class ImportThemeModal extends React.Component { Client.updateUser(user, (data) => { AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_ME, + type: ActionTypes.RECEIVED_ME, me: data }); @@ -212,4 +212,4 @@ ImportThemeModal.propTypes = { intl: intlShape.isRequired }; -export default injectIntl(ImportThemeModal);
\ No newline at end of file +export default injectIntl(ImportThemeModal); diff --git a/web/react/components/user_settings/manage_command_hooks.jsx b/web/react/components/user_settings/manage_command_hooks.jsx index b2fc0a4e1..d23d2957e 100644 --- a/web/react/components/user_settings/manage_command_hooks.jsx +++ b/web/react/components/user_settings/manage_command_hooks.jsx @@ -530,23 +530,19 @@ export default class ManageCommandCmds extends React.Component { /> </label> <div className='padding-top'> - <label> - <input - type='checkbox' - checked={this.state.cmd.auto_complete} - onChange={this.updateAutoComplete} - /> - <FormattedMessage - id='user.settings.cmds.auto_complete_desc_desc' - defaultMessage='A short description of what this commands does' - /> - </label> - </div> - <div className='padding-top'> - <FormattedMessage - id='user.settings.cmds.auto_complete_help' - defaultMessage='Show this command in autocomplete list.' - /> + <div className='checkbox'> + <label> + <input + type='checkbox' + checked={this.state.cmd.auto_complete} + onChange={this.updateAutoComplete} + /> + <FormattedMessage + id='user.settings.cmds.auto_complete_help' + defaultMessage=' Show this command in autocomplete list' + /> + </label> + </div> </div> </div> <div className='padding-top x2'> @@ -565,12 +561,6 @@ export default class ManageCommandCmds extends React.Component { placeholder={this.props.intl.formatMessage(holders.addAutoCompleteDescPlaceholder)} /> </div> - <div className='padding-top'> - <FormattedMessage - id='user.settings.cmds.auto_complete_desc_desc' - defaultMessage='A short description of what this commands does' - /> - </div> </div> <div className='padding-top x2'> <label className='control-label'> @@ -649,7 +639,7 @@ export default class ManageCommandCmds extends React.Component { </div> {addError} </div> - <div className='padding-top padding-bottom'> + <div className='padding-top x2 padding-bottom'> <a className={'btn btn-sm btn-primary'} href='#' diff --git a/web/react/components/user_settings/premade_theme_chooser.jsx b/web/react/components/user_settings/premade_theme_chooser.jsx index 9889bff5c..80ff8c4de 100644 --- a/web/react/components/user_settings/premade_theme_chooser.jsx +++ b/web/react/components/user_settings/premade_theme_chooser.jsx @@ -45,7 +45,7 @@ export default class PremadeThemeChooser extends React.Component { } return ( - <div className='row'> + <div className='row appearance-section'> {premadeThemes} </div> ); diff --git a/web/react/components/user_settings/user_settings.jsx b/web/react/components/user_settings/user_settings.jsx index 54d98bbde..4da51fa5f 100644 --- a/web/react/components/user_settings/user_settings.jsx +++ b/web/react/components/user_settings/user_settings.jsx @@ -6,7 +6,6 @@ import * as utils from '../../utils/utils.jsx'; import NotificationsTab from './user_settings_notifications.jsx'; import SecurityTab from './user_settings_security.jsx'; import GeneralTab from './user_settings_general.jsx'; -import AppearanceTab from './user_settings_appearance.jsx'; import DeveloperTab from './user_settings_developer.jsx'; import IntegrationsTab from './user_settings_integrations.jsx'; import DisplayTab from './user_settings_display.jsx'; @@ -85,21 +84,6 @@ export default class UserSettings extends React.Component { /> </div> ); - } else if (this.props.activeTab === 'appearance') { - return ( - <div> - <AppearanceTab - ref='activeTab' - activeSection={this.props.activeSection} - updateSection={this.props.updateSection} - updateTab={this.props.updateTab} - closeModal={this.props.closeModal} - collapseModal={this.props.collapseModal} - setEnforceFocus={this.props.setEnforceFocus} - setRequireConfirm={this.props.setRequireConfirm} - /> - </div> - ); } else if (this.props.activeTab === 'developer') { return ( <div> @@ -137,6 +121,8 @@ export default class UserSettings extends React.Component { updateTab={this.props.updateTab} closeModal={this.props.closeModal} collapseModal={this.props.collapseModal} + setEnforceFocus={this.props.setEnforceFocus} + setRequireConfirm={this.props.setRequireConfirm} /> </div> ); diff --git a/web/react/components/user_settings/user_settings_display.jsx b/web/react/components/user_settings/user_settings_display.jsx index 776bde442..4b11c06fb 100644 --- a/web/react/components/user_settings/user_settings_display.jsx +++ b/web/react/components/user_settings/user_settings_display.jsx @@ -1,15 +1,18 @@ // Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. -import {savePreferences} from '../../utils/client.jsx'; import SettingItemMin from '../setting_item_min.jsx'; import SettingItemMax from '../setting_item_max.jsx'; -import Constants from '../../utils/constants.jsx'; -const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES; -import PreferenceStore from '../../stores/preference_store.jsx'; import ManageLanguages from './manage_languages.jsx'; +import ThemeSetting from './user_settings_theme.jsx'; + +import PreferenceStore from '../../stores/preference_store.jsx'; import * as Utils from '../../utils/utils.jsx'; +import Constants from '../../utils/constants.jsx'; +const PreReleaseFeatures = Constants.PRE_RELEASE_FEATURES; + +import {savePreferences} from '../../utils/client.jsx'; import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl'; const holders = defineMessages({ @@ -452,6 +455,13 @@ class UserSettingsDisplay extends React.Component { /> </h3> <div className='divider-dark first'/> + <ThemeSetting + selected={this.props.activeSection === 'theme'} + updateSection={this.updateSection} + setRequireConfirm={this.props.setRequireConfirm} + setEnforceFocus={this.props.setEnforceFocus} + /> + <div className='divider-dark'/> {fontSection} <div className='divider-dark'/> {clockSection} @@ -472,7 +482,9 @@ UserSettingsDisplay.propTypes = { updateTab: React.PropTypes.func, activeSection: React.PropTypes.string, closeModal: React.PropTypes.func.isRequired, - collapseModal: React.PropTypes.func.isRequired + collapseModal: React.PropTypes.func.isRequired, + setRequireConfirm: React.PropTypes.func.isRequired, + setEnforceFocus: React.PropTypes.func.isRequired }; -export default injectIntl(UserSettingsDisplay);
\ No newline at end of file +export default injectIntl(UserSettingsDisplay); diff --git a/web/react/components/user_settings/user_settings_modal.jsx b/web/react/components/user_settings/user_settings_modal.jsx index 2a0a90cf5..e0b72157b 100644 --- a/web/react/components/user_settings/user_settings_modal.jsx +++ b/web/react/components/user_settings/user_settings_modal.jsx @@ -2,9 +2,13 @@ // See License.txt for license information. import ConfirmModal from '../confirm_modal.jsx'; -const Modal = ReactBootstrap.Modal; -import SettingsSidebar from '../settings_sidebar.jsx'; import UserSettings from './user_settings.jsx'; +import SettingsSidebar from '../settings_sidebar.jsx'; + +import UserStore from '../../stores/user_store.jsx'; +import * as Utils from '../../utils/utils.jsx'; + +const Modal = ReactBootstrap.Modal; import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl'; @@ -21,10 +25,6 @@ const holders = defineMessages({ id: 'user.settings.modal.notifications', defaultMessage: 'Notifications' }, - appearance: { - id: 'user.settings.modal.appearance', - defaultMessage: 'Appearance' - }, developer: { id: 'user.settings.modal.developer', defaultMessage: 'Developer' @@ -214,6 +214,12 @@ class UserSettingsModal extends React.Component { if (!skipConfirm && this.requireConfirm) { this.showConfirmModal(() => this.updateSection(section, true)); } else { + if (this.state.active_section === 'theme' && section !== 'theme') { + const user = UserStore.getCurrentUser(); + if (user.theme_props != null) { + Utils.applyTheme(user.theme_props); + } + } this.setState({active_section: section}); } } @@ -224,7 +230,6 @@ class UserSettingsModal extends React.Component { tabs.push({name: 'general', uiName: formatMessage(holders.general), icon: 'glyphicon glyphicon-cog'}); tabs.push({name: 'security', uiName: formatMessage(holders.security), icon: 'glyphicon glyphicon-lock'}); tabs.push({name: 'notifications', uiName: formatMessage(holders.notifications), icon: 'glyphicon glyphicon-exclamation-sign'}); - tabs.push({name: 'appearance', uiName: formatMessage(holders.appearance), icon: 'glyphicon glyphicon-wrench'}); if (global.window.mm_config.EnableOAuthServiceProvider === 'true') { tabs.push({name: 'developer', uiName: formatMessage(holders.developer), icon: 'glyphicon glyphicon-th'}); } @@ -294,4 +299,4 @@ UserSettingsModal.propTypes = { onModalDismissed: React.PropTypes.func.isRequired }; -export default injectIntl(UserSettingsModal);
\ No newline at end of file +export default injectIntl(UserSettingsModal); diff --git a/web/react/components/user_settings/user_settings_appearance.jsx b/web/react/components/user_settings/user_settings_theme.jsx index fb11dc81b..34c688db1 100644 --- a/web/react/components/user_settings/user_settings_appearance.jsx +++ b/web/react/components/user_settings/user_settings_theme.jsx @@ -1,8 +1,10 @@ -// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved. +// Copyright (c) 2016 Mattermost, Inc. All Rights Reserved. // See License.txt for license information. import CustomThemeChooser from './custom_theme_chooser.jsx'; import PremadeThemeChooser from './premade_theme_chooser.jsx'; +import SettingItemMin from '../setting_item_min.jsx'; +import SettingItemMax from '../setting_item_max.jsx'; import UserStore from '../../stores/user_store.jsx'; @@ -12,11 +14,22 @@ import * as Utils from '../../utils/utils.jsx'; import Constants from '../../utils/constants.jsx'; -import {FormattedMessage} from 'mm-intl'; +import {intlShape, injectIntl, defineMessages, FormattedMessage} from 'mm-intl'; const ActionTypes = Constants.ActionTypes; -export default class UserSettingsAppearance extends React.Component { +const holders = defineMessages({ + themeTitle: { + id: 'user.settings.display.theme.title', + defaultMessage: 'Theme' + }, + themeDescribe: { + id: 'user.settings.display.theme.describe', + defaultMessage: 'Open to manage your theme' + } +}); + +export default class ThemeSetting extends React.Component { constructor(props) { super(props); @@ -34,16 +47,21 @@ export default class UserSettingsAppearance extends React.Component { componentDidMount() { UserStore.addChangeListener(this.onChange); - if (this.props.activeSection === 'theme') { + if (this.props.selected) { $(ReactDOM.findDOMNode(this.refs[this.state.theme])).addClass('active-border'); } } componentDidUpdate() { - if (this.props.activeSection === 'theme') { + if (this.props.selected) { $('.color-btn').removeClass('active-border'); $(ReactDOM.findDOMNode(this.refs[this.state.theme])).addClass('active-border'); } } + componentWillReceiveProps(nextProps) { + if (!this.props.selected && nextProps.selected) { + this.resetFields(); + } + } componentWillUnmount() { UserStore.removeChangeListener(this.onChange); } @@ -89,13 +107,14 @@ export default class UserSettingsAppearance extends React.Component { Client.updateUser(user, (data) => { AppDispatcher.handleServerAction({ - type: ActionTypes.RECIEVED_ME, + type: ActionTypes.RECEIVED_ME, me: data }); this.props.setRequireConfirm(false); this.originalTheme = Object.assign({}, this.state.theme); this.scrollToTop(); + this.props.updateSection(''); }, (err) => { var state = this.getStateFromStores(); @@ -149,6 +168,8 @@ export default class UserSettingsAppearance extends React.Component { this.props.setEnforceFocus(false); } render() { + const {formatMessage} = this.props.intl; + var serverError; if (this.state.serverError) { serverError = this.state.serverError; @@ -160,136 +181,121 @@ export default class UserSettingsAppearance extends React.Component { let premade; if (displayCustom) { custom = ( - <CustomThemeChooser - theme={this.state.theme} - updateTheme={this.updateTheme} - /> + <div key='customThemeChooser'> + <br/> + <CustomThemeChooser + theme={this.state.theme} + updateTheme={this.updateTheme} + /> + </div> ); } else { premade = ( - <PremadeThemeChooser - theme={this.state.theme} - updateTheme={this.updateTheme} - /> + <div key='premadeThemeChooser'> + <br/> + <PremadeThemeChooser + theme={this.state.theme} + updateTheme={this.updateTheme} + /> + </div> ); } - const themeUI = ( - <div className='section-max appearance-section'> - <div className='col-sm-12'> - <div className='radio'> - <label> - <input type='radio' - checked={!displayCustom} - onChange={this.updateType.bind(this, 'premade')} - /> - <FormattedMessage - id='user.settings.appearance.themeColors' - defaultMessage='Theme Colors' - /> - </label> - <br/> - </div> - {premade} - <div className='radio'> - <label> - <input type='radio' - checked={displayCustom} - onChange={this.updateType.bind(this, 'custom')} - /> - <FormattedMessage - id='user.settings.appearance.customTheme' - defaultMessage='Custom Theme' - /> - </label> - <br/> - </div> - {custom} - <hr /> - {serverError} - <a - className='btn btn-sm btn-primary' - href='#' - onClick={this.submitTheme} - > - <FormattedMessage - id='user.settings.appearance.save' - defaultMessage='Save' + let themeUI; + if (this.props.selected) { + let inputs = []; + + inputs.push( + <div + className='radio' + key='premadeThemeColorLabel' + > + <label> + <input type='radio' + checked={!displayCustom} + onChange={this.updateType.bind(this, 'premade')} /> - </a> - <a - className='btn btn-sm theme' - href='#' - onClick={this.resetFields} - > <FormattedMessage - id='user.settings.appearance.cancel' - defaultMessage='Cancel' + id='user.settings.display.theme.themeColors' + defaultMessage='Theme Colors' /> - </a> + </label> + <br/> </div> - </div> - ); + ); - return ( - <div> - <div className='modal-header'> - <button - type='button' - className='close' - aria-label='Close' - onClick={this.props.closeModal} - > - <span aria-hidden='true'>{'×'}</span> - </button> - <h4 - className='modal-title' - ref='title' - > - <i - className='modal-back' - onClick={this.props.collapseModal} + inputs.push(premade); + + inputs.push( + <div + className='radio' + key='customThemeColorLabel' + > + <label> + <input type='radio' + checked={displayCustom} + onChange={this.updateType.bind(this, 'custom')} /> <FormattedMessage - id='user.settings.appearance.title' - defaultMessage='Appearance Settings' + id='user.settings.display.theme.customTheme' + defaultMessage='Custom Theme' /> - </h4> + </label> + <br/> </div> - <div className='user-settings'> - <h3 className='tab-header'> - <FormattedMessage - id='user.settings.appearance.title' - defaultMessage='Appearance Settings' - /> - </h3> - <div className='divider-dark first'/> - {themeUI} - <div className='divider-dark'/> + ); + + inputs.push(custom); + + inputs.push( + <div key='importSlackThemeButton'> <br/> <a className='theme' onClick={this.handleImportModal} > <FormattedMessage - id='user.settings.appearance.import' + id='user.settings.display.theme.import' defaultMessage='Import theme colors from Slack' /> </a> </div> - </div> - ); + ); + + themeUI = ( + <SettingItemMax + inputs={inputs} + submit={this.submitTheme} + server_error={serverError} + width='full' + updateSection={(e) => { + this.props.updateSection(''); + e.preventDefault(); + }} + /> + ); + } else { + themeUI = ( + <SettingItemMin + title={formatMessage(holders.themeTitle)} + describe={formatMessage(holders.themeDescribe)} + updateSection={() => { + this.props.updateSection('theme'); + }} + /> + ); + } + + return themeUI; } } -UserSettingsAppearance.defaultProps = { - activeSection: '' -}; -UserSettingsAppearance.propTypes = { - activeSection: React.PropTypes.string, - updateTab: React.PropTypes.func, - closeModal: React.PropTypes.func.isRequired, - collapseModal: React.PropTypes.func.isRequired, +ThemeSetting.propTypes = { + intl: intlShape.isRequired, + selected: React.PropTypes.bool.isRequired, + updateSection: React.PropTypes.func.isRequired, setRequireConfirm: React.PropTypes.func.isRequired, setEnforceFocus: React.PropTypes.func.isRequired }; + +export default injectIntl(ThemeSetting); |