From 851765a6fe56d1057786ad019bda0e0600d13112 Mon Sep 17 00:00:00 2001 From: Pascal Mugnier Date: Tue, 27 Mar 2018 15:46:41 +0200 Subject: [PATCH] SONAR-8217 Improve UI and fix issues with default values --- server/sonar-web/src/main/js/api/settings.ts | 18 ++++ .../js/apps/settings/components/Definition.js | 41 ++++------ ...itionDefaults.js => DefinitionActions.tsx} | 82 ++++++++++++------- .../settings/components/DefinitionChanges.js | 65 --------------- .../src/main/js/apps/settings/utils.js | 12 ++- 5 files changed, 93 insertions(+), 125 deletions(-) rename server/sonar-web/src/main/js/apps/settings/components/{DefinitionDefaults.js => DefinitionActions.tsx} (56%) delete mode 100644 server/sonar-web/src/main/js/apps/settings/components/DefinitionChanges.js 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 { 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 && ( @@ -190,7 +187,7 @@ class Definition extends React.PureComponent { )} {!loading && - this.props.validationMessage == null && + !hasError && this.state.success && ( @@ -207,21 +204,15 @@ class Definition extends React.PureComponent { value={effectiveValue} /> - {(!hasValueChanged || hasError) && ( - - )} - - {hasValueChanged && ( - - )} + ); 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 similarity index 56% rename from server/sonar-web/src/main/js/apps/settings/components/DefinitionDefaults.js rename to 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 { + 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 ( -
+ <> {isDefault && (
{translate('settings._default')}
)} +
+ {hasValueChanged && ( + + )} + + {canBeReset && ( + + )} + + {hasValueChanged && ( + + )} - {isExplicitlySet && ( -
- - + {isExplicitlySet && ( + {translate('default')} {': '} {getDefaultValue(setting)} -
- )} - {this.state.reseting && this.renderModal()} -
+ )} + + {this.state.reseting && this.renderModal()} +
+ ); } } 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 ( -
- {this.props.enableSave && ( - - )} - -
- ); - } -} 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) { -- 2.39.5