diff --git a/scm-ui-components/packages/ui-components/src/config/Configuration.js b/scm-ui-components/packages/ui-components/src/config/Configuration.js index 07b68f39a6..0eb6f6ffc2 100644 --- a/scm-ui-components/packages/ui-components/src/config/Configuration.js +++ b/scm-ui-components/packages/ui-components/src/config/Configuration.js @@ -2,12 +2,7 @@ import React from "react"; import { translate } from "react-i18next"; import type { Links } from "@scm-manager/ui-types"; -import { - apiClient, - SubmitButton, - Loading, - ErrorNotification -} from "../"; +import { apiClient, SubmitButton, Loading, ErrorNotification } from "../"; type RenderProps = { readOnly: boolean, @@ -20,10 +15,10 @@ type Props = { render: (props: RenderProps) => any, // ??? // context props - t: (string) => string + t: string => string }; -type ConfigurationType = { +type ConfigurationType = { _links: Links } & Object; @@ -32,6 +27,7 @@ type State = { fetching: boolean, modifying: boolean, contentType?: string, + configChanged: boolean, configuration?: ConfigurationType, modifiedConfiguration?: ConfigurationType, @@ -43,12 +39,12 @@ type State = { * synchronizing the configuration with the backend. */ class Configuration extends React.Component { - constructor(props: Props) { super(props); this.state = { fetching: true, modifying: false, + configChanged: false, valid: false }; } @@ -56,7 +52,8 @@ class Configuration extends React.Component { componentDidMount() { const { link } = this.props; - apiClient.get(link) + apiClient + .get(link) .then(this.captureContentType) .then(response => response.json()) .then(this.loadConfig) @@ -119,19 +116,39 @@ class Configuration extends React.Component { this.setState({ modifying: true }); - const {modifiedConfiguration} = this.state; + const { modifiedConfiguration } = this.state; - apiClient.put(this.getModificationUrl(), modifiedConfiguration, this.getContentType()) - .then(() => this.setState({ modifying: false })) + apiClient + .put( + this.getModificationUrl(), + modifiedConfiguration, + this.getContentType() + ) + .then(() => this.setState({ modifying: false, configChanged: true, valid: false })) .catch(this.handleError); }; + renderConfigChangedNotification = () => { + if (this.state.configChanged) { + return ( +
+
+ ); + } + return null; + }; + render() { const { t } = this.props; const { fetching, error, configuration, modifying, valid } = this.state; if (error) { - return ; + return ; } else if (fetching || !configuration) { return ; } else { @@ -144,19 +161,21 @@ class Configuration extends React.Component { }; return ( -
- { this.props.render(renderProps) } -
- - + <> + {this.renderConfigChangedNotification()} +
+ {this.props.render(renderProps)} +
+ + + ); } } - } export default translate("config")(Configuration); diff --git a/scm-ui/public/locales/en/config.json b/scm-ui/public/locales/en/config.json index de02006e79..1a33da8c8b 100644 --- a/scm-ui/public/locales/en/config.json +++ b/scm-ui/public/locales/en/config.json @@ -10,6 +10,7 @@ }, "config-form": { "submit": "Submit", + "submit-success-notification": "Configuration changed successfully!", "no-permission-notification": "Please note: You do not have the permission to edit the config!" }, "proxy-settings": { diff --git a/scm-ui/src/config/components/form/ConfigForm.js b/scm-ui/src/config/components/form/ConfigForm.js index f5bd6531b5..dc3f20c95d 100644 --- a/scm-ui/src/config/components/form/ConfigForm.js +++ b/scm-ui/src/config/components/form/ConfigForm.js @@ -23,7 +23,8 @@ type State = { error: { loginAttemptLimitTimeout: boolean, loginAttemptLimit: boolean - } + }, + changed: boolean }; class ConfigForm extends React.Component { @@ -59,7 +60,8 @@ class ConfigForm extends React.Component { error: { loginAttemptLimitTimeout: false, loginAttemptLimit: false - } + }, + changed: false }; } @@ -75,6 +77,9 @@ class ConfigForm extends React.Component { submit = (event: Event) => { event.preventDefault(); + this.setState({ + changed: false + }); this.props.submitForm(this.state.config); }; @@ -156,7 +161,9 @@ class ConfigForm extends React.Component { ); @@ -172,7 +179,8 @@ class ConfigForm extends React.Component { error: { ...this.state.error, [name]: !isValid - } + }, + changed: true }); }; diff --git a/scm-ui/src/config/containers/GlobalConfig.js b/scm-ui/src/config/containers/GlobalConfig.js index 6046aa4a09..71be3fdd7f 100644 --- a/scm-ui/src/config/containers/GlobalConfig.js +++ b/scm-ui/src/config/containers/GlobalConfig.js @@ -34,7 +34,19 @@ type Props = { t: string => string }; -class GlobalConfig extends React.Component { +type State = { + configChanged: boolean +}; + +class GlobalConfig extends React.Component { + constructor(props: Props) { + super(props); + + this.state = { + configChanged: false + }; + } + componentDidMount() { this.props.configReset(); this.props.fetchConfig(this.props.configLink); @@ -42,6 +54,22 @@ class GlobalConfig extends React.Component { modifyConfig = (config: Config) => { this.props.modifyConfig(config); + this.setState({ configChanged: true }); + }; + + renderConfigChangedNotification = () => { + if (this.state.configChanged) { + return ( +
+
+ ); + } + return null; }; render() { @@ -64,6 +92,7 @@ class GlobalConfig extends React.Component { return (
+ {this.renderConfigChangedNotification()} <ConfigForm submitForm={config => this.modifyConfig(config)} config={config}