]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-8217 Prevent saving empty values in settings
authorPascal Mugnier <pascal.mugnier@sonarsource.com>
Fri, 23 Mar 2018 10:14:46 +0000 (11:14 +0100)
committerSonarTech <sonartech@sonarsource.com>
Thu, 29 Mar 2018 18:20:46 +0000 (20:20 +0200)
server/sonar-web/src/main/js/apps/settings/components/Definition.js
server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js
server/sonar-web/src/main/js/apps/settings/store/actions.js
server/sonar-web/src/main/js/apps/settings/utils.js
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 43f52fd1a22b619f278cbc0168cffc59d0312506..8ca93ac74aef4bd51facba937a9a7550733d5a00 100644 (file)
@@ -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) && (
             <DefinitionDefaults
               isDefault={isDefault}
               onReset={this.handleReset}
@@ -203,9 +218,10 @@ class Definition extends React.PureComponent {
             />
           )}
 
-          {hasValueChanged && (
-            <DefinitionChanges onCancel={this.handleCancel} onSave={this.handleSave} />
-          )}
+          {hasValueChanged &&
+            !hasError && (
+              <DefinitionChanges onCancel={this.handleCancel} onSave={this.handleSave} />
+            )}
         </div>
       </div>
     );
@@ -223,5 +239,6 @@ export default connect(mapStateToProps, {
   saveValue,
   resetValue,
   passValidation,
-  cancelChange
+  cancelChange,
+  checkValue
 })(Definition);
index df70be22428706f8fc46b31449ff83a5d0610a5d..4c19a0a8992183c91cffeb44b0c91fc28de09fc7 100644 (file)
@@ -67,7 +67,7 @@ export default class DefinitionDefaults extends React.PureComponent {
           </div>
           <footer className="modal-foot">
             <button className="button-red">{translate('reset_verb')}</button>
-            <button type="reset" className="button-link" onClick={this.handleClose}>
+            <button className="button-link" onClick={this.handleClose} type="reset">
               {translate('cancel')}
             </button>
           </footer>
index dcbf19f63dd2707949aa39240dedac25a4ac6038..d4d1dddd806979f69dfc06081fc54939c48c3008 100644 (file)
@@ -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));
 
index f48db75aa2bc4bfaab7fff643f843a623c0d5543..ffd8107f6598a7ddd5a42c8220132d8ecd8f339d 100644 (file)
@@ -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');
   }
index 4aae3967b8f16c7e15840059a8a16221d29f41bf..b7bc5c0ac53920006e9d92c3432f001d305378d9 100644 (file)
@@ -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