diff options
author | Pascal Mugnier <pascal.mugnier@sonarsource.com> | 2018-05-09 07:27:30 +0200 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2018-05-24 20:20:46 +0200 |
commit | 562b9dacb912c64a4c048c03bdc9a7e2505a4bbe (patch) | |
tree | 68b4ca9c4179cca4504b5955f47dec28a495948e | |
parent | fbe1259e4abbbbe7416489819b79113ab953d864 (diff) | |
download | sonarqube-562b9dacb912c64a4c048c03bdc9a7e2505a4bbe.tar.gz sonarqube-562b9dacb912c64a4c048c03bdc9a7e2505a4bbe.zip |
Fix SONAR-10640
5 files changed, 240 insertions, 8 deletions
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionButton.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionButton.tsx new file mode 100644 index 00000000000..48943131904 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionButton.tsx @@ -0,0 +1,70 @@ +/* + * 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. + */ +import * as React from 'react'; +import ConditionModal from './ConditionModal'; +import { Button } from '../../../components/ui/buttons'; +import { translate } from '../../../helpers/l10n'; +import { Metric } from '../../../app/types'; + +interface Props { + metrics: Metric[]; +} + +interface State { + modal: boolean; +} + +export default class AddConditionButton extends React.PureComponent<Props, State> { + mounted = false; + state: State = { modal: false }; + + componentDidMount() { + this.mounted = true; + } + + componentWillUnmount() { + this.mounted = false; + } + + handleClick = () => { + this.setState({ modal: true }); + }; + + handleModalClose = () => { + if (this.mounted) { + this.setState({ modal: false }); + } + }; + + render() { + return ( + <> + <Button onClick={this.handleClick}>{translate('quality_gates.add_condition')}</Button> + {this.state.modal && ( + <ConditionModal + header={translate('quality_gates.add_condition')} + metrics={this.props.metrics} + onClose={this.handleModalClose} + /> + )} + </> + ); + } +} 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/AddConditionSelect.tsx index ef67bfd1554..8539232bb3f 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/AddConditionSelect.tsx @@ -67,14 +67,12 @@ export default class AddConditionSelect extends React.PureComponent<Props> { }); return ( - <div className="big-spacer-top panel bg-muted"> - <Select - className="text-middle input-large" - onChange={this.handleChange} - options={optionsWithDomains} - placeholder={translate('quality_gates.add_condition')} - /> - </div> + <Select + className="text-middle input-large" + onChange={this.handleChange} + options={optionsWithDomains} + placeholder={translate('quality_gates.add_condition')} + /> ); } } 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 new file mode 100644 index 00000000000..f0c27021af4 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionModal.tsx @@ -0,0 +1,97 @@ +/* + * 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. + */ +import * as React from 'react'; +import AddConditionSelect from './AddConditionSelect'; +import ConditionOperator from './ConditionOperator'; +import Modal from '../../../components/controls/Modal'; +import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; +import { translate } from '../../../helpers/l10n'; +import { Metric } from '../../../app/types'; + +interface Props { + metrics: Metric[]; + header: string; + onClose: () => void; +} + +interface State { + metric: string; + submitting: boolean; +} + +export default class ConditionModal extends React.PureComponent<Props, State> { + state = { metric: '', submitting: false }; + + handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => { + event.preventDefault(); + this.setState({ submitting: true }); + }; + + handleChooseType = (metric: string) => { + this.setState({ metric }); + }; + + render() { + const { header, metrics, onClose } = this.props; + const { submitting } = this.state; + return ( + <Modal contentLabel={header} onRequestClose={onClose}> + <form onSubmit={this.handleFormSubmit}> + <div className="modal-head"> + <h2>{header}</h2> + </div> + + <div className="modal-body"> + <div className="modal-field"> + <label htmlFor="create-user-login"> + {translate('quality_gates.conditions.metric')} + </label> + <AddConditionSelect metrics={metrics} onAddCondition={this.handleChooseType} /> + </div> + <div className="modal-field"> + <label htmlFor="create-user-login"> + {translate('quality_gates.conditions.metric')} + </label> + <ConditionOperator + canEdit={true} + condition={} + metric={this.state.metric} + onOperatorChange={() => {}} + /> + </div> + </div> + + <div className="modal-foot"> + {submitting && <i className="spinner spacer-right" />} + <SubmitButton disabled={submitting} id="coding-rules-custom-rule-creation-reactivate"> + {header} + </SubmitButton> + <ResetButtonLink + disabled={submitting} + id="coding-rules-custom-rule-creation-cancel" + onClick={onClose}> + {translate('cancel')} + </ResetButtonLink> + </div> + </form> + </Modal> + ); + } +} 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 new file mode 100644 index 00000000000..55c8d3c54d1 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/ConditionOperator.tsx @@ -0,0 +1,63 @@ +/* + * 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. + */ +import * as React from 'react'; +import Select from '../../../components/controls/Select'; +import { Condition as ICondition, Metric } from '../../../app/types'; +import { translate } from '../../../helpers/l10n'; + +interface Props { + condition: ICondition; + canEdit: boolean; + metric: Metric; + onOperatorChange: ({ value }: any) => void; +} + +export default function ConditionOperator({ condition, canEdit, metric, onOperatorChange }: Props) { + if (!canEdit && condition.op) { + return metric.type === 'RATING' ? ( + <span className="note">{translate('quality_gates.operator', condition.op, 'rating')}</span> + ) : ( + <span className="note">{translate('quality_gates.operator', condition.op)}</span> + ); + } + + if (metric.type === 'RATING') { + return <span className="note">{translate('quality_gates.operator.GT.rating')}</span>; + } + + const operators = ['LT', 'GT', 'EQ', 'NE']; + const operatorOptions = operators.map(op => { + const label = translate('quality_gates.operator', op); + return { label, value: op }; + }); + + return ( + <Select + autofocus={true} + className="input-medium" + clearable={false} + name="operator" + onChange={onOperatorChange} + options={operatorOptions} + searchable={false} + value={condition.op} + /> + ); +} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx index 0df36b5110f..07a9f8cc600 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Conditions.tsx @@ -21,6 +21,7 @@ import * as React from 'react'; import { differenceWith, map, sortBy, uniqBy } from 'lodash'; import AddConditionSelect from './AddConditionSelect'; import Condition from './Condition'; +import AddConditionButton from './AddConditionButton'; import DocTooltip from '../../../components/docs/DocTooltip'; import { translate, getLocalizedMetricName } from '../../../helpers/l10n'; import { Condition as ICondition, Metric, QualityGate } from '../../../app/types'; @@ -103,6 +104,9 @@ export default class Conditions extends React.PureComponent<Props, State> { return ( <div className="quality-gate-section" id="quality-gate-conditions"> + <div className="pull-right"> + <AddConditionButton metrics={availableMetrics} /> + </div> <header className="display-flex-center spacer-bottom"> <h3>{translate('quality_gates.conditions')}</h3> <DocTooltip className="spacer-left" doc="quality-gates/quality-gate-conditions" /> |