+++ /dev/null
-/*
- * 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<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}
- onAddCondition={this.props.onAddCondition}
- onClose={this.handleModalClose}
- organization={this.props.organization}
- qualityGate={this.props.qualityGate}
- />
- )}
- </>
- );
- }
-}
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;
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;
/>
)}
{this.state.deleteFormOpen && (
- <DeleteConditionModalForm
- condition={condition}
- metric={metric}
+ <ConfirmModal
+ confirmButtonText={translate('delete')}
+ confirmData={condition}
+ header={translate('quality_gates.delete_condition')}
+ isDestructive={true}
onClose={this.closeDeleteForm}
- onDelete={this.props.onRemoveCondition}
- organization={organization}
- />
+ onConfirm={this.removeCondition}>
+ {translateWithParameters(
+ 'quality_gates.delete_condition.confirm.message',
+ getLocalizedMetricName(this.props.metric)
+ )}
+ </ConfirmModal>
)}
</td>
)}
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;
}
export default class ConditionModal extends React.PureComponent<Props, State> {
+ mounted = false;
+
constructor(props: Props) {
super(props);
this.state = {
};
}
+ 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) => {
};
handleConditionResponse = (newCondition: Condition) => {
- this.setState({ errorMessage: undefined, submitting: false });
this.props.onAddCondition(newCondition);
this.props.onClose();
};
- handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
- event.preventDefault();
-
+ handleFormSubmit = () => {
if (this.state.metric) {
const { condition, qualityGate, organization } = this.props;
this.setState({ submitting: true });
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 (
- <Modal contentLabel={header} onRequestClose={onClose}>
- <form onSubmit={this.handleFormSubmit}>
- <div className="modal-head">
- <h2>{header}</h2>
- </div>
-
- <div className="modal-body">
- {this.state.errorMessage && (
- <div className="alert alert-danger">{this.state.errorMessage}</div>
- )}
+ <ConfirmModal
+ confirmButtonText={header}
+ header={header}
+ onClose={onClose}
+ onConfirm={this.handleFormSubmit}>
+ {this.state.errorMessage && (
+ <div className="alert alert-warning modal-alert">{this.state.errorMessage}</div>
+ )}
+ <div className="modal-field">
+ <label htmlFor="create-user-login">{translate('quality_gates.conditions.metric')}</label>
+ {metrics && (
+ <AddConditionSelect metrics={metrics} onAddCondition={this.handleChooseType} />
+ )}
+ {this.props.metric && (
+ <span className="note">{getLocalizedMetricName(this.props.metric)}</span>
+ )}
+ </div>
+ {metric && (
+ <>
+ <div className="modal-field">
+ <label>{translate('quality_gates.conditions.leak')}</label>
+ <Period
+ canEdit={true}
+ metric={metric}
+ onPeriodChange={this.handlePeriodChange}
+ period={period}
+ />
+ </div>
+ <div className="modal-field">
+ <label>{translate('quality_gates.conditions.operator')}</label>
+ <ConditionOperator
+ canEdit={true}
+ metric={metric}
+ onOperatorChange={this.handleOperatorChange}
+ op={op}
+ />
+ </div>
+ <div className="modal-field">
+ <label>{translate('quality_gates.conditions.warning')}</label>
+ <ThresholdInput
+ metric={metric}
+ name="warning"
+ onChange={this.handleWarningChange}
+ value={warning}
+ />
+ </div>
<div className="modal-field">
- <label htmlFor="create-user-login">
- {translate('quality_gates.conditions.metric')}
- </label>
- {metrics && (
- <AddConditionSelect metrics={metrics} onAddCondition={this.handleChooseType} />
- )}
- {this.props.metric && (
- <span className="note">{getLocalizedMetricName(this.props.metric)}</span>
- )}
+ <label>{translate('quality_gates.conditions.error')}</label>
+ <ThresholdInput
+ metric={metric}
+ name="error"
+ onChange={this.handleErrorChange}
+ value={error}
+ />
</div>
- {metric && (
- <>
- <div className="modal-field">
- <label>{translate('quality_gates.conditions.leak')}</label>
- <Period
- canEdit={true}
- metric={metric}
- onPeriodChange={this.handlePeriodChange}
- period={period}
- />
- </div>
- <div className="modal-field">
- <label>{translate('quality_gates.conditions.operator')}</label>
- <ConditionOperator
- canEdit={true}
- metric={metric}
- onOperatorChange={this.handleOperatorChange}
- op={op}
- />
- </div>
- <div className="modal-field">
- <label>{translate('quality_gates.conditions.warning')}</label>
- <ThresholdInput
- metric={metric}
- name="warning"
- onChange={this.handleWarningChange}
- value={warning}
- />
- </div>
- <div className="modal-field">
- <label>{translate('quality_gates.conditions.error')}</label>
- <ThresholdInput
- metric={metric}
- name="error"
- onChange={this.handleErrorChange}
- value={error}
- />
- </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>
+ </>
+ )}
+ </ConfirmModal>
);
}
}
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;
qualityGate: QualityGate;
}
-interface State {
- error?: string;
-}
-
-export default class Conditions extends React.PureComponent<Props, State> {
- state: State = {};
-
- componentWillUpdate(nextProps: Props) {
- if (nextProps.qualityGate !== this.props.qualityGate) {
- this.setState({ error: undefined });
- }
- }
-
+export default class Conditions extends React.PureComponent<Props> {
getConditionKey = (condition: ICondition, index: number) => {
return condition.id ? condition.id : `new-${index}`;
};
<div className="quality-gate-section" id="quality-gate-conditions">
{canEdit && (
<div className="pull-right">
- <AddConditionButton
- metrics={availableMetrics}
- onAddCondition={this.props.onAddCondition}
- organization={organization}
- qualityGate={qualityGate}
- />
+ <ModalButton
+ modal={({ onClose }) => (
+ <ConditionModal
+ header={translate('quality_gates.add_condition')}
+ metrics={availableMetrics}
+ onAddCondition={this.props.onAddCondition}
+ onClose={onClose}
+ organization={this.props.organization}
+ qualityGate={this.props.qualityGate}
+ />
+ )}>
+ {({ onClick }) => (
+ <Button onClick={onClick}>{translate('quality_gates.add_condition')}</Button>
+ )}
+ </ModalButton>
</div>
)}
<header className="display-flex-center spacer-bottom">
<div className="big-spacer-bottom">{translate('quality_gates.introduction')}</div>
- {this.state.error && <div className="alert alert-danger">{this.state.error}</div>}
-
{uniqDuplicates.length > 0 && (
<div className="alert alert-warning">
<p>{translate('quality_gates.duplicated_conditions')}</p>
+++ /dev/null
-/*
- * 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<Props, State> {
- mounted = false;
- state: State = { loading: false, name: null };
-
- componentDidMount() {
- this.mounted = true;
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- handleFormSubmit = (event: React.SyntheticEvent<HTMLFormElement>) => {
- 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 (
- <Modal contentLabel={header} onRequestClose={this.props.onClose}>
- <form id="delete-condition-form" onSubmit={this.handleFormSubmit}>
- <div className="modal-head">
- <h2>{header}</h2>
- </div>
- <div className="modal-body">
- <div className="js-modal-messages" />
- <p>
- {translateWithParameters(
- 'quality_gates.delete_condition.confirm.message',
- getLocalizedMetricName(this.props.metric)
- )}
- </p>
- </div>
- <div className="modal-foot">
- {this.state.loading && <i className="spinner spacer-right" />}
- <SubmitButton
- className="button-red"
- disabled={this.state.loading}
- id="delete-profile-submit">
- {translate('delete')}
- </SubmitButton>
- <ResetButtonLink id="delete-profile-cancel" onClick={this.props.onClose}>
- {translate('cancel')}
- </ResetButtonLink>
- </div>
- </form>
- </Modal>
- );
- }
-}
import { translate } from '../../helpers/l10n';
import { SubmitButton, ResetButtonLink } from '../ui/buttons';
-interface Props {
+interface Props<T> {
children: React.ReactNode;
confirmButtonText: string;
- confirmData?: string;
+ confirmData?: T;
confirmDisable?: boolean;
header: string;
isDestructive?: boolean;
onClose: () => void;
- onConfirm: (data?: string) => void | Promise<void>;
+ onConfirm: (data?: T) => void | Promise<void>;
}
-export default class ConfirmModal extends React.PureComponent<Props> {
+export default class ConfirmModal<T = string> extends React.PureComponent<Props<T>> {
mounted = false;
componentDidMount() {
submitting: boolean;
}
-export default class SimpleModal extends React.PureComponent<Props, State> {
+export default class SimpleModal extends React.Component<Props, State> {
mounted = false;
state: State = { submitting: false };