From a5484f56ceb467e5c0a2e3f705969c1822ea8109 Mon Sep 17 00:00:00 2001 From: Pascal Mugnier Date: Wed, 23 May 2018 09:18:38 +0200 Subject: [PATCH] Fix after review --- .../components/AddConditionButton.tsx | 76 -------- .../quality-gates/components/Condition.tsx | 47 +++-- .../components/ConditionModal.tsx | 183 +++++++++--------- .../quality-gates/components/Conditions.tsx | 41 ++-- .../components/DeleteConditionModalForm.tsx | 102 ---------- .../js/components/controls/ConfirmModal.tsx | 8 +- .../js/components/controls/SimpleModal.tsx | 2 +- 7 files changed, 148 insertions(+), 311 deletions(-) delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionButton.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/DeleteConditionModalForm.tsx 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 deleted file mode 100644 index 04e4133f191..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/AddConditionButton.tsx +++ /dev/null @@ -1,76 +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. - */ -import * as React from 'react'; -import ConditionModal from './ConditionModal'; -import { Button } from '../../../components/ui/buttons'; -import { translate } from '../../../helpers/l10n'; -import { Metric, QualityGate, Condition } from '../../../app/types'; - -interface Props { - metrics: Metric[]; - organization?: string; - onAddCondition: (condition: Condition) => void; - qualityGate: QualityGate; -} - -interface State { - modal: boolean; -} - -export default class AddConditionButton extends React.PureComponent { - 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 ( - <> - - {this.state.modal && ( - - )} - - ); - } -} 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 fd05fb82324..587ce6af15f 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 @@ -21,11 +21,12 @@ import * as React from 'react'; import ConditionOperator from './ConditionOperator'; import Period from './Period'; import ConditionModal from './ConditionModal'; -import DeleteConditionModalForm from './DeleteConditionModalForm'; import { Condition as ICondition, Metric, QualityGate } from '../../../app/types'; import ActionsDropdown, { ActionsDropdownItem } from '../../../components/controls/ActionsDropdown'; -import { translate, getLocalizedMetricName } from '../../../helpers/l10n'; +import { translate, getLocalizedMetricName, translateWithParameters } from '../../../helpers/l10n'; import { formatMeasure } from '../../../helpers/measures'; +import ConfirmModal from '../../../components/controls/ConfirmModal'; +import { deleteCondition } from '../../../api/quality-gates'; interface Props { condition: ICondition; @@ -63,17 +64,30 @@ export default class Condition extends React.PureComponent { this.props.onSaveCondition(newCondition, this.props.condition); }; - handleCancelClick = () => { - this.props.onRemoveCondition(this.props.condition); + handleOpenUpdate = () => { + this.setState({ modal: true }); }; - handleOpenUpdate = () => this.setState({ modal: true }); + handleUpdateClose = () => { + this.setState({ modal: false }); + }; - handleUpdateClose = () => this.setState({ modal: false }); + handleDeleteClick = () => { + this.setState({ deleteFormOpen: true }); + }; - handleDeleteClick = () => this.setState({ deleteFormOpen: true }); + closeDeleteForm = () => { + this.setState({ deleteFormOpen: false }); + }; - closeDeleteForm = () => this.setState({ deleteFormOpen: false }); + removeCondition = (condition: ICondition) => { + if (condition.id !== undefined) { + deleteCondition({ id: condition.id, organization: this.props.organization }).then( + () => this.props.onRemoveCondition(condition), + () => {} + ); + } + }; render() { const { condition, canEdit, metric, organization, qualityGate } = this.props; @@ -123,13 +137,18 @@ export default class Condition extends React.PureComponent { /> )} {this.state.deleteFormOpen && ( - + onConfirm={this.removeCondition}> + {translateWithParameters( + 'quality_gates.delete_condition.confirm.message', + getLocalizedMetricName(this.props.metric) + )} + )} )} 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 12a557a41a5..7071337a79b 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 @@ -22,13 +22,12 @@ import AddConditionSelect from './AddConditionSelect'; import ConditionOperator from './ConditionOperator'; import ThresholdInput from './ThresholdInput'; import Period from './Period'; -import Modal from '../../../components/controls/Modal'; -import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; import { translate, getLocalizedMetricName } from '../../../helpers/l10n'; import { Metric, QualityGate, Condition } from '../../../app/types'; import { createCondition, updateCondition } from '../../../api/quality-gates'; import { isDiffMetric } from '../../../helpers/measures'; import { parseError } from '../../../helpers/request'; +import ConfirmModal from '../../../components/controls/ConfirmModal'; interface Props { condition?: Condition; @@ -52,6 +51,8 @@ interface State { } export default class ConditionModal extends React.PureComponent { + mounted = false; + constructor(props: Props) { super(props); this.state = { @@ -64,13 +65,25 @@ export default class ConditionModal extends React.PureComponent { }; } + componentDidMount() { + this.mounted = true; + } + + componentWillUnmount() { + this.mounted = false; + } + handleError = (error: any) => { - parseError(error).then( - message => { - this.setState({ errorMessage: message }); - }, - () => {} - ); + if (this.mounted) { + parseError(error).then( + message => { + this.setState({ errorMessage: message, submitting: false }); + }, + () => { + this.setState({ submitting: false }); + } + ); + } }; getUpdatedCondition = (metric: Metric) => { @@ -93,14 +106,11 @@ export default class ConditionModal extends React.PureComponent { }; handleConditionResponse = (newCondition: Condition) => { - this.setState({ errorMessage: undefined, submitting: false }); this.props.onAddCondition(newCondition); this.props.onClose(); }; - handleFormSubmit = (event: React.SyntheticEvent) => { - event.preventDefault(); - + handleFormSubmit = () => { if (this.state.metric) { const { condition, qualityGate, organization } = this.props; this.setState({ submitting: true }); @@ -130,95 +140,84 @@ export default class ConditionModal extends React.PureComponent { this.setState({ metric }); }; - handlePeriodChange = (period: boolean) => this.setState({ period }); + handlePeriodChange = (period: boolean) => { + this.setState({ period }); + }; - handleOperatorChange = (op: string) => this.setState({ op }); + handleOperatorChange = (op: string) => { + this.setState({ op }); + }; - handleWarningChange = (warning: string) => this.setState({ warning }); + handleWarningChange = (warning: string) => { + this.setState({ warning }); + }; - handleErrorChange = (error: string) => this.setState({ error }); + handleErrorChange = (error: string) => { + this.setState({ error }); + }; render() { const { header, metrics, onClose } = this.props; - const { period, op, warning, error, metric, submitting } = this.state; + const { period, op, warning, error, metric } = this.state; return ( - -
-
-

{header}

-
- -
- {this.state.errorMessage && ( -
{this.state.errorMessage}
- )} + + {this.state.errorMessage && ( +
{this.state.errorMessage}
+ )} +
+ + {metrics && ( + + )} + {this.props.metric && ( + {getLocalizedMetricName(this.props.metric)} + )} +
+ {metric && ( + <> +
+ + +
+
+ + +
+
+ + +
- - {metrics && ( - - )} - {this.props.metric && ( - {getLocalizedMetricName(this.props.metric)} - )} + +
- {metric && ( - <> -
- - -
-
- - -
-
- - -
-
- - -
- - )} -
- -
- {submitting && } - - {header} - - - {translate('cancel')} - -
- -
+ + )} + ); } } 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 1b15c245d38..0eebf3c693d 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 @@ -20,10 +20,12 @@ import * as React from 'react'; import { differenceWith, map, sortBy, uniqBy } from 'lodash'; import Condition from './Condition'; -import AddConditionButton from './AddConditionButton'; +import ConditionModal from './ConditionModal'; import DocTooltip from '../../../components/docs/DocTooltip'; import { translate, getLocalizedMetricName } from '../../../helpers/l10n'; import { Condition as ICondition, Metric, QualityGate } from '../../../app/types'; +import ModalButton from '../../../components/controls/ModalButton'; +import { Button } from '../../../components/ui/buttons'; interface Props { canEdit: boolean; @@ -36,19 +38,7 @@ interface Props { qualityGate: QualityGate; } -interface State { - error?: string; -} - -export default class Conditions extends React.PureComponent { - state: State = {}; - - componentWillUpdate(nextProps: Props) { - if (nextProps.qualityGate !== this.props.qualityGate) { - this.setState({ error: undefined }); - } - } - +export default class Conditions extends React.PureComponent { getConditionKey = (condition: ICondition, index: number) => { return condition.id ? condition.id : `new-${index}`; }; @@ -91,12 +81,21 @@ export default class Conditions extends React.PureComponent {
{canEdit && (
- + ( + + )}> + {({ onClick }) => ( + + )} +
)}
@@ -106,8 +105,6 @@ export default class Conditions extends React.PureComponent {
{translate('quality_gates.introduction')}
- {this.state.error &&
{this.state.error}
} - {uniqDuplicates.length > 0 && (

{translate('quality_gates.duplicated_conditions')}

diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/DeleteConditionModalForm.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/DeleteConditionModalForm.tsx deleted file mode 100644 index 0477d1d6420..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/DeleteConditionModalForm.tsx +++ /dev/null @@ -1,102 +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. - */ -import * as React from 'react'; -import Modal from '../../../components/controls/Modal'; -import { SubmitButton, ResetButtonLink } from '../../../components/ui/buttons'; -import { translate, translateWithParameters, getLocalizedMetricName } from '../../../helpers/l10n'; -import { Condition, Metric } from '../../../app/types'; -import { deleteCondition } from '../../../api/quality-gates'; - -interface Props { - onClose: () => void; - condition: Condition; - metric: Metric; - onDelete: (condition: Condition) => void; - organization?: string; -} - -interface State { - loading: boolean; - name: string | null; -} - -export default class DeleteConditionModalForm extends React.PureComponent { - mounted = false; - state: State = { loading: false, name: null }; - - componentDidMount() { - this.mounted = true; - } - - componentWillUnmount() { - this.mounted = false; - } - - handleFormSubmit = (event: React.SyntheticEvent) => { - event.preventDefault(); - this.setState({ loading: true }); - const { organization, condition } = this.props; - if (condition.id !== undefined) { - deleteCondition({ id: condition.id, organization }).then( - () => this.props.onDelete(condition), - () => { - if (this.mounted) { - this.setState({ loading: false }); - } - } - ); - } - }; - - render() { - const header = translate('quality_gates.delete_condition'); - - return ( - -
-
-

{header}

-
-
-
-

- {translateWithParameters( - 'quality_gates.delete_condition.confirm.message', - getLocalizedMetricName(this.props.metric) - )} -

-
-
- {this.state.loading && } - - {translate('delete')} - - - {translate('cancel')} - -
- - - ); - } -} diff --git a/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx b/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx index 631d0743d89..6456e5a790c 100644 --- a/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx +++ b/server/sonar-web/src/main/js/components/controls/ConfirmModal.tsx @@ -23,18 +23,18 @@ import DeferredSpinner from '../common/DeferredSpinner'; import { translate } from '../../helpers/l10n'; import { SubmitButton, ResetButtonLink } from '../ui/buttons'; -interface Props { +interface Props { children: React.ReactNode; confirmButtonText: string; - confirmData?: string; + confirmData?: T; confirmDisable?: boolean; header: string; isDestructive?: boolean; onClose: () => void; - onConfirm: (data?: string) => void | Promise; + onConfirm: (data?: T) => void | Promise; } -export default class ConfirmModal extends React.PureComponent { +export default class ConfirmModal extends React.PureComponent> { mounted = false; componentDidMount() { diff --git a/server/sonar-web/src/main/js/components/controls/SimpleModal.tsx b/server/sonar-web/src/main/js/components/controls/SimpleModal.tsx index e85d13031ed..98a77bce7f9 100644 --- a/server/sonar-web/src/main/js/components/controls/SimpleModal.tsx +++ b/server/sonar-web/src/main/js/components/controls/SimpleModal.tsx @@ -38,7 +38,7 @@ interface State { submitting: boolean; } -export default class SimpleModal extends React.PureComponent { +export default class SimpleModal extends React.Component { mounted = false; state: State = { submitting: false }; -- 2.39.5