aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-12-10 17:47:01 +0100
committerSonarTech <sonartech@sonarsource.com>2019-01-08 20:21:06 +0100
commitbbdfc6267f94b82a7c1c072e0e400b3bee87610e (patch)
treef22d39b3a2912108e7c593a65d891dcc76c12a9d /server/sonar-web/src/main/js
parentf085494e7c0a846c4e293cd4cc07ccc87bbf9b82 (diff)
downloadsonarqube-bbdfc6267f94b82a7c1c072e0e400b3bee87610e.tar.gz
sonarqube-bbdfc6267f94b82a7c1c072e0e400b3bee87610e.zip
SONAR-11572 limit operators of quality gate conditions in UI
Diffstat (limited to 'server/sonar-web/src/main/js')
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/Condition.tsx17
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/ConditionModal.tsx38
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/ConditionOperator.tsx64
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/MetricSelect.tsx (renamed from server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionSelect.tsx)8
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/utils.ts10
5 files changed, 74 insertions, 63 deletions
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Condition.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/Condition.tsx
index 6b775c72712..9d7762977d5 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/Condition.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Condition.tsx
@@ -18,7 +18,6 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import ConditionOperator from './ConditionOperator';
import ConditionModal from './ConditionModal';
import ActionsDropdown, { ActionsDropdownItem } from '../../../components/controls/ActionsDropdown';
import { translate, getLocalizedMetricName, translateWithParameters } from '../../../helpers/l10n';
@@ -77,6 +76,18 @@ export default class Condition extends React.PureComponent<Props, State> {
);
};
+ renderOperator() {
+ // TODO can operator be missing?
+ const { op = 'GT' } = this.props.condition;
+ return (
+ <span className="note">
+ {this.props.metric.type === 'RATING'
+ ? translate('quality_gates.operator', op, 'rating')
+ : translate('quality_gates.operator', op)}
+ </span>
+ );
+ }
+
render() {
const { condition, canEdit, metric, organization, qualityGate } = this.props;
return (
@@ -88,9 +99,7 @@ export default class Condition extends React.PureComponent<Props, State> {
)}
</td>
- <td className="thin text-middle nowrap">
- <ConditionOperator canEdit={false} metric={metric} op={condition.op} />
- </td>
+ <td className="thin text-middle nowrap">{this.renderOperator()}</td>
<td className="thin text-middle nowrap">{formatMeasure(condition.error, metric.type)}</td>
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionModal.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionModal.tsx
index e480bd53c91..e2778fe943f 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionModal.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionModal.tsx
@@ -18,13 +18,14 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import AddConditionSelect from './AddConditionSelect';
+import MetricSelect from './MetricSelect';
import ConditionOperator from './ConditionOperator';
import ThresholdInput from './ThresholdInput';
import { translate, getLocalizedMetricName } from '../../../helpers/l10n';
import { createCondition, updateCondition } from '../../../api/quality-gates';
import ConfirmModal from '../../../components/controls/ConfirmModal';
import { Alert } from '../../../components/ui/Alert';
+import { getPossibleOperators } from '../utils';
interface Props {
condition?: T.Condition;
@@ -64,31 +65,29 @@ export default class ConditionModal extends React.PureComponent<Props, State> {
this.mounted = false;
}
- getUpdatedCondition = (metric: T.Metric) => {
- return {
- metric: metric.key,
- op: metric.type === 'RATING' ? 'GT' : this.state.op,
- error: this.state.error
- };
- };
+ getSinglePossibleOperator(metric: T.Metric) {
+ const operators = getPossibleOperators(metric);
+ return Array.isArray(operators) ? undefined : operators;
+ }
handleFormSubmit = () => {
if (this.state.metric) {
const { condition, qualityGate, organization } = this.props;
- const newCondition = this.getUpdatedCondition(this.state.metric);
- let submitPromise: Promise<T.Condition>;
- if (condition) {
- submitPromise = updateCondition({ organization, id: condition.id, ...newCondition });
- } else {
- submitPromise = createCondition({ gateId: qualityGate.id, organization, ...newCondition });
- }
+ const newCondition: T.Omit<T.Condition, 'id'> = {
+ metric: this.state.metric.key,
+ op: this.getSinglePossibleOperator(this.state.metric) || this.state.op,
+ error: this.state.error
+ };
+ const submitPromise = condition
+ ? updateCondition({ organization, id: condition.id, ...newCondition })
+ : createCondition({ gateId: qualityGate.id, organization, ...newCondition });
return submitPromise.then(this.props.onAddCondition);
}
return Promise.reject();
};
- handleChooseType = (metric: T.Metric) => {
- this.setState({ metric });
+ handleMetricChange = (metric: T.Metric) => {
+ this.setState({ metric, op: undefined, error: '' });
};
handleOperatorChange = (op: string) => {
@@ -112,9 +111,7 @@ export default class ConditionModal extends React.PureComponent<Props, State> {
{this.state.errorMessage && <Alert variant="error">{this.state.errorMessage}</Alert>}
<div className="modal-field">
<label htmlFor="create-user-login">{translate('quality_gates.conditions.metric')}</label>
- {metrics && (
- <AddConditionSelect metrics={metrics} onAddCondition={this.handleChooseType} />
- )}
+ {metrics && <MetricSelect metrics={metrics} onMetricChange={this.handleMetricChange} />}
{this.props.metric && (
<span className="note">{getLocalizedMetricName(this.props.metric)}</span>
)}
@@ -124,7 +121,6 @@ export default class ConditionModal extends React.PureComponent<Props, State> {
<div className="modal-field">
<label>{translate('quality_gates.conditions.operator')}</label>
<ConditionOperator
- canEdit={true}
metric={metric}
onOperatorChange={this.handleOperatorChange}
op={op}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionOperator.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionOperator.tsx
index 13ef8d24e46..ba7b8aca6c4 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionOperator.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionOperator.tsx
@@ -20,52 +20,48 @@
import * as React from 'react';
import Select from '../../../components/controls/Select';
import { translate } from '../../../helpers/l10n';
+import { getPossibleOperators } from '../utils';
interface Props {
op?: string;
- canEdit: boolean;
metric: T.Metric;
- onOperatorChange?: (op: string) => void;
+ onOperatorChange: (op: string) => void;
}
export default class ConditionOperator extends React.PureComponent<Props> {
handleChange = ({ value }: { label: string; value: string }) => {
- if (this.props.onOperatorChange) {
- this.props.onOperatorChange(value);
- }
+ this.props.onOperatorChange(value);
};
- render() {
- const { canEdit, metric, op } = this.props;
- if (!canEdit && op) {
- return metric.type === 'RATING' ? (
- <span className="note">{translate('quality_gates.operator', op, 'rating')}</span>
- ) : (
- <span className="note">{translate('quality_gates.operator', op)}</span>
- );
- }
+ getLabel(op: string, metric: T.Metric) {
+ return metric.type === 'RATING'
+ ? translate('quality_gates.operator', op, 'rating')
+ : translate('quality_gates.operator', op);
+ }
- if (metric.type === 'RATING') {
- return <span className="note">{translate('quality_gates.operator.GT.rating')}</span>;
- }
+ render() {
+ const operators = getPossibleOperators(this.props.metric);
- const operators = ['LT', 'GT', 'EQ', 'NE'];
- const operatorOptions = operators.map(op => {
- const label = translate('quality_gates.operator', op);
- return { label, value: op };
- });
+ if (Array.isArray(operators)) {
+ const operatorOptions = operators.map(op => {
+ const label = this.getLabel(op, this.props.metric);
+ return { label, value: op };
+ });
- return (
- <Select
- autoFocus={true}
- className="input-medium"
- clearable={false}
- name="operator"
- onChange={this.handleChange}
- options={operatorOptions}
- searchable={false}
- value={op}
- />
- );
+ return (
+ <Select
+ autoFocus={true}
+ className="input-medium"
+ clearable={false}
+ name="operator"
+ onChange={this.handleChange}
+ options={operatorOptions}
+ searchable={false}
+ value={this.props.op}
+ />
+ );
+ } else {
+ return <span className="note">{this.getLabel(operators, this.props.metric)}</span>;
+ }
}
}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionSelect.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/MetricSelect.tsx
index 47c852cb378..60331a83d63 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionSelect.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/MetricSelect.tsx
@@ -24,7 +24,7 @@ import { translate, getLocalizedMetricName, getLocalizedMetricDomain } from '../
interface Props {
metrics: T.Metric[];
- onAddCondition: (metric: T.Metric) => void;
+ onMetricChange: (metric: T.Metric) => void;
}
interface State {
@@ -38,12 +38,12 @@ interface Option {
value: number;
}
-export default class AddConditionSelect extends React.PureComponent<Props, State> {
+export default class MetricSelect extends React.PureComponent<Props, State> {
state = { value: -1 };
handleChange = ({ value }: Option) => {
this.setState({ value });
- this.props.onAddCondition(this.props.metrics[value]);
+ this.props.onMetricChange(this.props.metrics[value]);
};
render() {
@@ -77,7 +77,7 @@ export default class AddConditionSelect extends React.PureComponent<Props, State
className="text-middle input-large"
onChange={this.handleChange}
options={optionsWithDomains}
- placeholder={translate('quality_gates.add_condition')}
+ placeholder={translate('search.search_for_metrics')}
value={this.state.value}
/>
);
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/utils.ts b/server/sonar-web/src/main/js/apps/quality-gates/utils.ts
index 08a3a01ff8c..8c76e632ee8 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/utils.ts
+++ b/server/sonar-web/src/main/js/apps/quality-gates/utils.ts
@@ -46,3 +46,13 @@ export function replaceCondition(
});
return { ...qualityGate, conditions };
}
+
+export function getPossibleOperators(metric: T.Metric) {
+ if (metric.direction === 1) {
+ return 'LT';
+ } else if (metric.direction === -1) {
+ return 'GT';
+ } else {
+ return ['LT', 'GT'];
+ }
+}