aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web
diff options
context:
space:
mode:
authorPascal Mugnier <pascal.mugnier@sonarsource.com>2018-03-27 15:46:41 +0200
committerSonarTech <sonartech@sonarsource.com>2018-03-29 20:20:46 +0200
commit851765a6fe56d1057786ad019bda0e0600d13112 (patch)
treeb47f0d5e23ba2da45a49830b069bada3bb911d8f /server/sonar-web
parentb28f54a5076dfd1696b52abe347fbe2e1722940f (diff)
downloadsonarqube-851765a6fe56d1057786ad019bda0e0600d13112.tar.gz
sonarqube-851765a6fe56d1057786ad019bda0e0600d13112.zip
SONAR-8217 Improve UI and fix issues with default values
Diffstat (limited to 'server/sonar-web')
-rw-r--r--server/sonar-web/src/main/js/api/settings.ts18
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/Definition.js41
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/DefinitionActions.tsx (renamed from server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js)82
-rw-r--r--server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js65
-rw-r--r--server/sonar-web/src/main/js/apps/settings/utils.js12
5 files changed, 93 insertions, 125 deletions
diff --git a/server/sonar-web/src/main/js/api/settings.ts b/server/sonar-web/src/main/js/api/settings.ts
index 46c0ec67cf8..6df408faa6b 100644
--- a/server/sonar-web/src/main/js/api/settings.ts
+++ b/server/sonar-web/src/main/js/api/settings.ts
@@ -23,6 +23,24 @@ import { TYPE_PROPERTY_SET } from '../apps/settings/constants';
import { BranchParameters } from '../app/types';
import throwGlobalError from '../app/utils/throwGlobalError';
+interface DefinitionField {
+ description: string;
+ key: string;
+ name: string;
+ options: string[];
+}
+
+export interface Definition {
+ category: string;
+ description: string;
+ fields: DefinitionField[];
+ key: string;
+ name: string;
+ options: string[];
+ subCategory: string;
+ type: string;
+}
+
export function getDefinitions(component?: string): Promise<any> {
return getJSON('/api/settings/list_definitions', { component }).then(r => r.definitions);
}
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 31169d527cb..b1a1f32503b 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
@@ -23,8 +23,7 @@ import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import classNames from 'classnames';
import Input from './inputs/Input';
-import DefinitionDefaults from './DefinitionDefaults';
-import DefinitionChanges from './DefinitionChanges';
+import DefinitionActions from './DefinitionActions';
import {
getPropertyName,
getPropertyDescription,
@@ -63,8 +62,7 @@ class Definition extends React.PureComponent {
};
state = {
- success: false,
- hasError: false
+ success: false
};
componentDidMount() {
@@ -98,7 +96,7 @@ class Definition extends React.PureComponent {
.resetValue(definition.key, componentKey)
.then(() => {
this.props.cancelChange(definition.key, componentKey);
- this.safeSetState({ success: true, hasError: false });
+ this.safeSetState({ success: true });
this.timeout = setTimeout(() => this.safeSetState({ success: false }), 3000);
})
.catch(() => {
@@ -114,8 +112,7 @@ class Definition extends React.PureComponent {
handleCheck = () => {
const componentKey = this.props.component ? this.props.component.key : null;
- const hasError = !this.props.checkValue(this.props.setting.definition.key, componentKey);
- this.safeSetState({ hasError });
+ this.props.checkValue(this.props.setting.definition.key, componentKey);
};
handleSave = () => {
@@ -136,9 +133,9 @@ class Definition extends React.PureComponent {
render() {
const { setting, changedValue, loading } = this.props;
- const { hasError } = this.state;
const { definition } = setting;
const propertyName = getPropertyName(definition);
+ const hasError = this.props.validationMessage != null;
const hasValueChanged = changedValue != null;
@@ -177,7 +174,7 @@ class Definition extends React.PureComponent {
)}
{!loading &&
- this.props.validationMessage != null && (
+ hasError && (
<span className="text-danger">
<AlertErrorIcon className="spacer-right" />
<span>
@@ -190,7 +187,7 @@ class Definition extends React.PureComponent {
)}
{!loading &&
- this.props.validationMessage == null &&
+ !hasError &&
this.state.success && (
<span className="text-success">
<AlertSuccessIcon className="spacer-right" />
@@ -207,21 +204,15 @@ class Definition extends React.PureComponent {
value={effectiveValue}
/>
- {(!hasValueChanged || hasError) && (
- <DefinitionDefaults
- isDefault={isDefault}
- onReset={this.handleReset}
- setting={setting}
- />
- )}
-
- {hasValueChanged && (
- <DefinitionChanges
- enableSave={!hasError}
- onCancel={this.handleCancel}
- onSave={this.handleSave}
- />
- )}
+ <DefinitionActions
+ changedValue={changedValue}
+ hasError={hasError}
+ isDefault={isDefault}
+ onCancel={this.handleCancel}
+ onReset={this.handleReset}
+ onSave={this.handleSave}
+ setting={setting}
+ />
</div>
</div>
);
diff --git a/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js b/server/sonar-web/src/main/js/apps/settings/components/DefinitionActions.tsx
index 4c19a0a8992..c5a4e796164 100644
--- a/server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js
+++ b/server/sonar-web/src/main/js/apps/settings/components/DefinitionActions.tsx
@@ -17,39 +17,38 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-// @flow
-import React from 'react';
-import { getSettingValue, isEmptyValue, getDefaultValue } from '../utils';
+import * as React from 'react';
import Modal from '../../../components/controls/Modal';
+import { isEmptyValue, getDefaultValue, getSettingValue } from '../utils';
import { translate } from '../../../helpers/l10n';
+import { Button } from '../../../components/ui/buttons';
+import { SettingValue, Definition } from '../../../api/settings';
-/*::
type Props = {
- isDefault: boolean,
- onReset: () => void,
- setting: Object
+ changedValue: string;
+ hasError: boolean;
+ isDefault: boolean;
+ onCancel: () => void;
+ onReset: () => void;
+ onSave: () => void;
+ setting: SettingValue & { definition: Definition };
+ valueChanged: boolean;
};
-*/
-/*::
+
type State = { reseting: boolean };
-*/
-export default class DefinitionDefaults extends React.PureComponent {
- /*:: props: Props; */
- state /*: State*/ = { reseting: false };
+export default class DefinitionActions extends React.PureComponent<Props, State> {
+ state: State = { reseting: false };
handleClose = () => {
this.setState({ reseting: false });
};
- handleReset = (e /*: Event & {target: HTMLElement} */) => {
- e.preventDefault();
- e.target.blur();
+ handleReset = () => {
this.setState({ reseting: true });
};
- handleSubmit = (event /*: Event */) => {
- event.preventDefault();
+ handleSubmit = () => {
this.props.onReset();
this.handleClose();
};
@@ -77,31 +76,52 @@ export default class DefinitionDefaults extends React.PureComponent {
}
render() {
- const { setting, isDefault } = this.props;
- const { definition } = setting;
-
- const isExplicitlySet = !isDefault && !isEmptyValue(definition, getSettingValue(setting));
+ const { setting, isDefault, changedValue } = this.props;
+ const hasValueChanged = changedValue != null;
+ const canBeReset = !isDefault && isEmptyValue(setting.definition, changedValue);
+ const isExplicitlySet =
+ !isDefault && !isEmptyValue(setting.definition, getSettingValue(setting));
return (
- <div>
+ <>
{isDefault && (
<div className="spacer-top note" style={{ lineHeight: '24px' }}>
{translate('settings._default')}
</div>
)}
+ <div className="settings-definition-changes nowrap">
+ {hasValueChanged && (
+ <Button
+ className="spacer-right button-success"
+ disabled={this.props.hasError}
+ onClick={this.props.onSave}>
+ {translate('save')}
+ </Button>
+ )}
+
+ {canBeReset && (
+ <Button className="spacer-right" onClick={this.handleReset}>
+ {translate('reset_verb')}
+ </Button>
+ )}
+
+ {hasValueChanged && (
+ <Button className="spacer-right button-link" onClick={this.props.onCancel}>
+ {translate('cancel')}
+ </Button>
+ )}
- {isExplicitlySet && (
- <div className="spacer-top nowrap">
- <button onClick={this.handleReset}>{translate('reset_verb')}</button>
- <span className="spacer-left note">
+ {isExplicitlySet && (
+ <span className="note">
{translate('default')}
{': '}
{getDefaultValue(setting)}
</span>
- </div>
- )}
- {this.state.reseting && this.renderModal()}
- </div>
+ )}
+
+ {this.state.reseting && this.renderModal()}
+ </div>
+ </>
);
}
}
diff --git a/server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js b/server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js
deleted file mode 100644
index a3eb663af9b..00000000000
--- a/server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2018 SonarSource SA
- * mailto:info AT sonarsource DOT com
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-// @flow
-import React from 'react';
-import PropTypes from 'prop-types';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {
- enableSave: boolean
-};
-*/
-
-export default class DefinitionChanges extends React.PureComponent {
- static propTypes = {
- onSave: PropTypes.func.isRequired,
- onCancel: PropTypes.func.isRequired
- };
-
- handleSaveClick(e /*: Object */) {
- e.preventDefault();
- e.target.blur();
- this.props.onSave();
- }
-
- handleCancelChange(e /*: Object */) {
- e.preventDefault();
- e.target.blur();
- this.props.onCancel();
- }
-
- render() {
- return (
- <div className="settings-definition-changes">
- {this.props.enableSave && (
- <button className="js-save-changes button-success" onClick={e => this.handleSaveClick(e)}>
- {translate('save')}
- </button>
- )}
- <button
- className="js-cancel-changes big-spacer-left button-link"
- onClick={e => this.handleCancelChange(e)}>
- {translate('cancel')}
- </button>
- </div>
- );
- }
-}
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 b7aa3a8e34a..b05eac7f43e 100644
--- a/server/sonar-web/src/main/js/apps/settings/utils.js
+++ b/server/sonar-web/src/main/js/apps/settings/utils.js
@@ -115,12 +115,16 @@ function getParentValue(setting) {
* @returns {string}
*/
export function getDefaultValue(setting) {
- const parentValue = getParentValue(setting);
+ let parentValue = getParentValue(setting);
if (parentValue == null) {
- return setting.definition.defaultValue
- ? setting.definition.defaultValue
- : translate('settings.default.no_value');
+ if (setting.definition.defaultValue) {
+ return setting.definition.defaultValue;
+ }
+ parentValue = getSettingValue(setting);
+ if (parentValue == null) {
+ return translate('settings.default.no_value');
+ }
}
if (setting.definition.multiValues) {