From 0a3bb8fdb10f2ce72e5e975a35fc7d22637265f9 Mon Sep 17 00:00:00 2001 From: George Goldberg Date: Tue, 4 Jul 2017 08:00:17 +0100 Subject: 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. --- .../request_button/request_button.jsx | 234 +++++++++++++++++++++ 1 file changed, 234 insertions(+) create mode 100644 webapp/components/admin_console/request_button/request_button.jsx (limited to 'webapp/components/admin_console/request_button') 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 . + */ + helpText: PropTypes.element.isRequired, + + /** + * A component to be displayed on the button. + * + * Typically, this will be a + */ + 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 = ( +
+
+ + +
+
+ ); + } else if (this.state.success && this.props.showSuccessMessage) { + message = ( +
+
+ + +
+
+ ); + } + + let contents = null; + if (this.state.busy) { + contents = ( + + + {Utils.localizeMessage('admin.requestButton.loading', ' Loading...')} + + ); + } else { + contents = this.props.buttonText; + } + + return ( +
+
+
+ + {message} +
+
+ {this.props.helpText} +
+
+
+ ); + } +} -- cgit v1.2.3-1-g7c22