From 8b1c450599a1ee106660d3825941ea890a051c04 Mon Sep 17 00:00:00 2001 From: Pascal Mugnier Date: Fri, 23 Mar 2018 11:14:46 +0100 Subject: [PATCH] SONAR-8217 Prevent saving empty values in settings --- .../js/apps/settings/components/Definition.js | 33 ++++++++++++++----- .../settings/components/DefinitionDefaults.js | 2 +- .../main/js/apps/settings/store/actions.js | 18 ++++++++++ .../src/main/js/apps/settings/utils.js | 4 +++ .../resources/org/sonar/l10n/core.properties | 1 + 5 files changed, 49 insertions(+), 9 deletions(-) diff --git a/server/sonar-web/src/main/js/apps/settings/components/Definition.js b/server/sonar-web/src/main/js/apps/settings/components/Definition.js index 43f52fd1a22..8ca93ac74ae 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/Definition.js +++ b/server/sonar-web/src/main/js/apps/settings/components/Definition.js @@ -34,7 +34,7 @@ import { import AlertErrorIcon from '../../../components/icons-components/AlertErrorIcon'; import AlertSuccessIcon from '../../../components/icons-components/AlertSuccessIcon'; import { translateWithParameters, translate } from '../../../helpers/l10n'; -import { resetValue, saveValue } from '../store/actions'; +import { resetValue, saveValue, checkValue } from '../store/actions'; import { passValidation } from '../store/settingsPage/validationMessages/actions'; import { cancelChange, changeValue } from '../store/settingsPage/changedValues/actions'; import { TYPE_PASSWORD } from '../constants'; @@ -63,7 +63,8 @@ class Definition extends React.PureComponent { }; state = { - success: false + success: false, + hasError: false }; componentDidMount() { @@ -85,6 +86,8 @@ class Definition extends React.PureComponent { this.props.changeValue(this.props.setting.definition.key, value); if (this.props.setting.definition.type === TYPE_PASSWORD) { this.handleSave(); + } else { + this.handleCheck(); } }; @@ -94,7 +97,8 @@ class Definition extends React.PureComponent { return this.props .resetValue(definition.key, componentKey) .then(() => { - this.safeSetState({ success: true }); + this.props.changeValue(definition.key, definition.defaultValue); + this.safeSetState({ success: true, hasError: false }); this.timeout = setTimeout(() => this.safeSetState({ success: false }), 3000); }) .catch(() => { @@ -108,6 +112,16 @@ class Definition extends React.PureComponent { this.props.passValidation(this.props.setting.definition.key); }; + handleCheck = () => { + this.safeSetState({ success: false }); + const componentKey = this.props.component ? this.props.component.key : null; + if (this.props.checkValue(this.props.setting.definition.key, componentKey)) { + this.safeSetState({ hasError: false }); + } else { + this.safeSetState({ hasError: true }); + } + }; + handleSave = () => { if (this.props.changedValue != null) { this.safeSetState({ success: false }); @@ -126,6 +140,7 @@ class Definition extends React.PureComponent { render() { const { setting, changedValue, loading } = this.props; + const { hasError } = this.state; const { definition } = setting; const propertyName = getPropertyName(definition); @@ -195,7 +210,7 @@ class Definition extends React.PureComponent { value={effectiveValue} /> - {!hasValueChanged && ( + {(!hasValueChanged || hasError) && ( )} - {hasValueChanged && ( - - )} + {hasValueChanged && + !hasError && ( + + )} ); @@ -223,5 +239,6 @@ export default connect(mapStateToProps, { saveValue, resetValue, passValidation, - cancelChange + cancelChange, + checkValue })(Definition); diff --git a/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js b/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js index df70be22428..4c19a0a8992 100644 --- a/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js +++ b/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js @@ -67,7 +67,7 @@ export default class DefinitionDefaults extends React.PureComponent { diff --git a/server/sonar-web/src/main/js/apps/settings/store/actions.js b/server/sonar-web/src/main/js/apps/settings/store/actions.js index dcbf19f63dd..d4d1dddd806 100644 --- a/server/sonar-web/src/main/js/apps/settings/store/actions.js +++ b/server/sonar-web/src/main/js/apps/settings/store/actions.js @@ -59,6 +59,24 @@ export const fetchValues = (keys, component) => dispatch => () => {} ); +export const checkValue = (key, componentKey) => (dispatch, getState) => { + const state = getState(); + const definition = getSettingsAppDefinition(state, key); + const value = getSettingsAppChangedValue(state, key); + + if (isEmptyValue(definition, value)) { + if (definition.defaultValue === undefined) { + dispatch(failValidation(key, translate('settings.state.value_cant_be_empty_no_default'))); + } else { + dispatch(failValidation(key, translate('settings.state.value_cant_be_empty'))); + } + return false; + } + + dispatch(passValidation(key)); + return true; +}; + export const saveValue = (key, componentKey) => (dispatch, getState) => { dispatch(startLoading(key)); diff --git a/server/sonar-web/src/main/js/apps/settings/utils.js b/server/sonar-web/src/main/js/apps/settings/utils.js index f48db75aa2b..ffd8107f659 100644 --- a/server/sonar-web/src/main/js/apps/settings/utils.js +++ b/server/sonar-web/src/main/js/apps/settings/utils.js @@ -117,6 +117,10 @@ function getParentValue(setting) { export function getDefaultValue(setting) { const parentValue = getParentValue(setting); + if (parentValue === undefined) { + return setting.value; + } + if (parentValue == null) { return translate('settings.default.no_value'); } diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 4aae3967b8f..b7bc5c0ac53 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -788,6 +788,7 @@ settings.state.saving=Saving... settings.state.saved=Saved! settings.state.validation_failed=Validation failed. {0} settings.state.value_cant_be_empty=Provide a value or use "Reset" to set the value to the default one. +settings.state.value_cant_be_empty_no_default=Provide a value. settings._default=(default) settings.boolean.true=True settings.boolean.false=False -- 2.39.5