diff options
author | George Goldberg <george@gberg.me> | 2017-07-04 08:00:17 +0100 |
---|---|---|
committer | Christopher Speller <crspeller@gmail.com> | 2017-07-04 00:00:17 -0700 |
commit | 0a3bb8fdb10f2ce72e5e975a35fc7d22637265f9 (patch) | |
tree | 3a3c7dfed0830d9e3a945f862c60d99f15074ca1 /webapp/components/admin_console/request_button | |
parent | f54aee1ef5466fdf11803cd75be3b7267e68540f (diff) | |
download | chat-0a3bb8fdb10f2ce72e5e975a35fc7d22637265f9.tar.gz chat-0a3bb8fdb10f2ce72e5e975a35fc7d22637265f9.tar.bz2 chat-0a3bb8fdb10f2ce72e5e975a35fc7d22637265f9.zip |
Refactor system console buttons into RequestButton component. (#6808)
Since I was going to make yet another button for the ElasticSearch test
config button, I refactored all of them to use a single common component
and tidied that component up and gave it some unit tests.
Diffstat (limited to 'webapp/components/admin_console/request_button')
-rw-r--r-- | webapp/components/admin_console/request_button/request_button.jsx | 234 |
1 files changed, 234 insertions, 0 deletions
diff --git a/webapp/components/admin_console/request_button/request_button.jsx b/webapp/components/admin_console/request_button/request_button.jsx new file mode 100644 index 000000000..4aad287d2 --- /dev/null +++ b/webapp/components/admin_console/request_button/request_button.jsx @@ -0,0 +1,234 @@ +// Copyright (c) 2016-present Mattermost, Inc. All Rights Reserved. +// See License.txt for license information. + +import React from 'react'; + +import {FormattedMessage} from 'react-intl'; +import PropTypes from 'prop-types'; + +import * as Utils from 'utils/utils.jsx'; + +/** + * A button which, when clicked, performs an action and displays + * its outcome as either success, or failure accompanied by the + * `message` property of the `err` object. + */ +export default class RequestButton extends React.Component { + static propTypes = { + + /** + * The action to be called to carry out the request. + */ + requestAction: PropTypes.func.isRequired, + + /** + * A component that displays help text for the request button. + * + * Typically, this will be a <FormattedMessage/>. + */ + helpText: PropTypes.element.isRequired, + + /** + * A component to be displayed on the button. + * + * Typically, this will be a <FormattedMessage/> + */ + buttonText: PropTypes.element.isRequired, + + /** + * True if the button form control should be disabled, otherwise false. + */ + disabled: PropTypes.bool, + + /** + * True if the config needs to be saved before running the request, otherwise false. + * + * If set to true, the action provided in the `saveConfigAction` property will be + * called before the action provided in the `requestAction` property, with the later + * only being called if the former is successful. + */ + saveNeeded: PropTypes.bool, + + /** + * Action to be called to save the config, if saveNeeded is set to true. + */ + saveConfigAction: PropTypes.func, + + /** + * True if the success message should be show when the request completes successfully, + * otherwise false. + */ + showSuccessMessage: PropTypes.bool, + + /** + * The message to show when the request completes successfully. + */ + successMessage: PropTypes.shape({ + + /** + * The i18n string ID for the success message. + */ + id: PropTypes.string.isRequired, + + /** + * The i18n default value for the success message. + */ + defaultMessage: PropTypes.string.isRequired + }), + + /** + * The message to show when the request returns an error. + */ + errorMessage: PropTypes.shape({ + + /** + * The i18n string ID for the error message. + */ + id: PropTypes.string.isRequired, + + /** + * The i18n default value for the error message. + * + * The placeholder {error} may be used to include the error message returned + * by the server in response to the failed request. + */ + defaultMessage: PropTypes.string.isRequired + }), + + /** + * True if the {error} placeholder for the `errorMessage` property should include both + * the `message` and `detailed_error` properties of the error returned from the server, + * otherwise false to include only the `message` property. + */ + includeDetailedError: PropTypes.bool + } + + static defaultProps = { + disabled: false, + saveNeeded: false, + showSuccessMessage: true, + includeDetailedError: false, + successMessage: { + id: 'admin.requestButton.requestSuccess', + defaultMessage: 'Test Successful' + }, + errorMessage: { + id: 'admin.requestButton.requestFailure', + defaultMessage: 'Test Failure: {error}' + } + } + + constructor(props) { + super(props); + + this.handleRequest = this.handleRequest.bind(this); + + this.state = { + busy: false, + fail: null, + success: false + }; + } + + handleRequest(e) { + e.preventDefault(); + + this.setState({ + busy: true, + fail: null, + success: false + }); + + const doRequest = () => { //eslint-disable-line func-style + this.props.requestAction( + () => { + this.setState({ + busy: false, + success: true + }); + }, + (err) => { + let errMsg = err.message; + if (this.props.includeDetailedError) { + errMsg += ' - ' + err.detailed_error; + } + + this.setState({ + busy: false, + fail: errMsg + }); + } + ); + }; + + if (this.props.saveNeeded) { + this.props.saveConfigAction(doRequest); + } else { + doRequest(); + } + } + + render() { + let message = null; + if (this.state.fail) { + message = ( + <div> + <div className='alert alert-warning'> + <i className='fa fa-warning'/> + <FormattedMessage + id={this.props.errorMessage.id} + defaultMessage={this.props.errorMessage.defaultMessage} + values={{ + error: this.state.fail + }} + /> + </div> + </div> + ); + } else if (this.state.success && this.props.showSuccessMessage) { + message = ( + <div> + <div className='alert alert-success'> + <i className='fa fa-success'/> + <FormattedMessage + id={this.props.successMessage.id} + defaultMessage={this.props.successMessage.defaultMessage} + /> + </div> + </div> + ); + } + + let contents = null; + if (this.state.busy) { + contents = ( + <span> + <span className='fa fa-refresh icon--rotate'/> + {Utils.localizeMessage('admin.requestButton.loading', ' Loading...')} + </span> + ); + } else { + contents = this.props.buttonText; + } + + return ( + <div className='form-group reload-config'> + <div className='col-sm-offset-4 col-sm-8'> + <div> + <button + className='btn btn-default' + onClick={this.handleRequest} + disabled={this.props.disabled} + > + {contents} + </button> + {message} + </div> + <div className='help-text'> + {this.props.helpText} + </div> + </div> + </div> + ); + } +} |