From c37f8a7202925bec2d9a27961ea10f125c259c91 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gr=C3=A9goire=20Aubert?= Date: Thu, 30 Nov 2017 16:05:46 +0100 Subject: [PATCH] SONAR-10151 Refactor Quality Gates modals to Typescript --- .../src/main/js/api/quality-gates.ts | 33 +++-- .../components/CopyQualityGateForm.tsx | 134 ++++++++++++++++++ .../components/CreateQualityGateForm.tsx | 127 +++++++++++++++++ .../components/DeleteQualityGateForm.tsx | 106 ++++++++++++++ .../apps/quality-gates/components/Details.js | 57 +------- .../{DetailsHeader.js => DetailsHeader.tsx} | 75 ++++++++-- .../js/apps/quality-gates/components/List.js | 2 +- .../quality-gates/components/ListHeader.js | 42 ------ .../quality-gates/components/ListHeader.tsx | 65 +++++++++ .../components/QualityGatesApp.js | 16 +-- .../components/RenameQualityGateForm.tsx | 125 ++++++++++++++++ .../templates/quality-gate-form.hbs | 20 --- .../templates/quality-gates-delete.hbs | 17 --- .../js/apps/quality-gates/views/copy-view.js | 53 ------- .../apps/quality-gates/views/create-view.js | 52 ------- .../apps/quality-gates/views/delete-view.js | 52 ------- .../quality-gates/views/gate-projects-view.js | 15 +- .../apps/quality-gates/views/rename-view.js | 53 ------- 18 files changed, 667 insertions(+), 377 deletions(-) create mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/CopyQualityGateForm.tsx create mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/CreateQualityGateForm.tsx create mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/DeleteQualityGateForm.tsx rename server/sonar-web/src/main/js/apps/quality-gates/components/{DetailsHeader.js => DetailsHeader.tsx} (52%) delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.js create mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.tsx create mode 100644 server/sonar-web/src/main/js/apps/quality-gates/components/RenameQualityGateForm.tsx delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/templates/quality-gate-form.hbs delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/templates/quality-gates-delete.hbs delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/views/copy-view.js delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/views/create-view.js delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/views/delete-view.js delete mode 100644 server/sonar-web/src/main/js/apps/quality-gates/views/rename-view.js diff --git a/server/sonar-web/src/main/js/api/quality-gates.ts b/server/sonar-web/src/main/js/api/quality-gates.ts index d2402fcdb46..90b03cbe338 100644 --- a/server/sonar-web/src/main/js/api/quality-gates.ts +++ b/server/sonar-web/src/main/js/api/quality-gates.ts @@ -52,31 +52,42 @@ export function fetchQualityGates(): Promise<{ return getJSON('/api/qualitygates/list').catch(throwGlobalError); } -export function fetchQualityGate(id: string): Promise { +export function fetchQualityGate(id: number): Promise { return getJSON('/api/qualitygates/show', { id }).catch(throwGlobalError); } -export function createQualityGate(name: string): Promise { - return postJSON('/api/qualitygates/create', { name }); +export function createQualityGate(data: { + name: string; + organization?: string; +}): Promise { + return postJSON('/api/qualitygates/create', data).catch(throwGlobalError); } -export function deleteQualityGate(id: string): Promise { +export function deleteQualityGate(id: number): Promise { return post('/api/qualitygates/destroy', { id }); } -export function renameQualityGate(id: string, name: string): Promise { - return post('/api/qualitygates/rename', { id, name }); +export function renameQualityGate(data: { + id: number; + name: string; + organization?: string; +}): Promise { + return post('/api/qualitygates/rename', data).catch(throwGlobalError); } -export function copyQualityGate(id: string, name: string): Promise { - return postJSON('/api/qualitygates/copy', { id, name }); +export function copyQualityGate(data: { + id: number; + name: string; + organization?: string; +}): Promise { + return postJSON('/api/qualitygates/copy', data).catch(throwGlobalError); } -export function setQualityGateAsDefault(id: string): Promise { +export function setQualityGateAsDefault(id: number): Promise { return post('/api/qualitygates/set_as_default', { id }).catch(throwGlobalError); } -export function createCondition(gateId: string, condition: RequestData): Promise { +export function createCondition(gateId: number, condition: RequestData): Promise { return postJSON('/api/qualitygates/create_condition', { ...condition, gateId }); } @@ -84,7 +95,7 @@ export function updateCondition(condition: RequestData): Promise { return postJSON('/api/qualitygates/update_condition', condition); } -export function deleteCondition(id: string): Promise { +export function deleteCondition(id: number): Promise { return post('/api/qualitygates/delete_condition', { id }); } diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/CopyQualityGateForm.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/CopyQualityGateForm.tsx new file mode 100644 index 00000000000..ceeb416cc63 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/CopyQualityGateForm.tsx @@ -0,0 +1,134 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 * as PropTypes from 'prop-types'; +import Modal from '../../../components/controls/Modal'; +import { copyQualityGate, QualityGate } from '../../../api/quality-gates'; +import { getQualityGateUrl } from '../../../helpers/urls'; +import { translate } from '../../../helpers/l10n'; + +interface Props { + qualityGate: QualityGate; + onCopy: (newQualityGate: QualityGate) => void; + onClose: () => void; + organization?: string; +} + +interface State { + loading: boolean; + name: string; +} + +export default class CopyQualityGateForm extends React.PureComponent { + mounted: boolean; + + static contextTypes = { + router: PropTypes.object + }; + + constructor(props: Props) { + super(props); + this.state = { loading: false, name: props.qualityGate.name }; + } + + componentDidMount() { + this.mounted = true; + } + + componentWillUnmount() { + this.mounted = false; + } + + handleCancelClick = (event: React.SyntheticEvent) => { + event.preventDefault(); + this.props.onClose(); + }; + + handleNameChange = (event: React.SyntheticEvent) => { + this.setState({ name: event.currentTarget.value }); + }; + + handleFormSubmit = (event: React.SyntheticEvent) => { + event.preventDefault(); + const { qualityGate, organization } = this.props; + const { name } = this.state; + if (name) { + this.setState({ loading: true }); + copyQualityGate({ id: qualityGate.id, name, organization }).then( + qualityGate => { + this.props.onCopy(qualityGate); + this.props.onClose(); + this.context.router.push( + getQualityGateUrl(String(qualityGate.id), this.props.organization) + ); + }, + () => { + if (this.mounted) { + this.setState({ loading: false }); + } + } + ); + } + }; + + render() { + const { qualityGate } = this.props; + const { loading, name } = this.state; + const header = translate('quality_gates.copy'); + const submitDisabled = loading || !name || (qualityGate && qualityGate.name === name); + + return ( + +
+
+

{header}

+
+
+
+ + +
+
+
+ {loading && } + + + {translate('cancel')} + +
+ +
+ ); + } +} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/CreateQualityGateForm.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/CreateQualityGateForm.tsx new file mode 100644 index 00000000000..1171c189e4a --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/CreateQualityGateForm.tsx @@ -0,0 +1,127 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 * as PropTypes from 'prop-types'; +import Modal from '../../../components/controls/Modal'; +import { createQualityGate, QualityGate } from '../../../api/quality-gates'; +import { translate } from '../../../helpers/l10n'; +import { getQualityGateUrl } from '../../../helpers/urls'; + +interface Props { + onCreate: (qualityGate: QualityGate) => void; + onClose: () => void; + organization?: string; +} + +interface State { + loading: boolean; + name: string; +} + +export default class CreateQualityGateForm extends React.PureComponent { + mounted: boolean; + + static contextTypes = { + router: PropTypes.object + }; + + state = { loading: false, name: '' }; + + componentDidMount() { + this.mounted = true; + } + + componentWillUnmount() { + this.mounted = false; + } + + handleCancelClick = (event: React.SyntheticEvent) => { + event.preventDefault(); + this.props.onClose(); + }; + + handleNameChange = (event: React.SyntheticEvent) => { + this.setState({ name: event.currentTarget.value }); + }; + + handleFormSubmit = (event: React.SyntheticEvent) => { + event.preventDefault(); + const { organization } = this.props; + const { name } = this.state; + if (name) { + this.setState({ loading: true }); + createQualityGate({ name, organization }).then( + qualityGate => { + this.props.onCreate(qualityGate); + this.context.router.push(getQualityGateUrl(String(qualityGate.id), organization)); + this.props.onClose(); + }, + () => { + if (this.mounted) { + this.setState({ loading: false }); + } + } + ); + } + }; + + render() { + const { loading, name } = this.state; + const header = translate('quality_gates.rename'); + const submitDisabled = loading || !name; + + return ( + +
+
+

{header}

+
+
+
+ + +
+
+
+ {loading && } + + + {translate('cancel')} + +
+ +
+ ); + } +} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/DeleteQualityGateForm.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/DeleteQualityGateForm.tsx new file mode 100644 index 00000000000..ab80d7e9df9 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/DeleteQualityGateForm.tsx @@ -0,0 +1,106 @@ +import {} from '../../overview/qualityGate/QualityGate'; +/* + * SonarQube + * Copyright (C) 2009-2017 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 * as PropTypes from 'prop-types'; +import Modal from '../../../components/controls/Modal'; +import { getQualityGatesUrl } from '../../../helpers/urls'; +import { deleteQualityGate, QualityGate } from '../../../api/quality-gates'; +import { translate, translateWithParameters } from '../../../helpers/l10n'; + +interface Props { + onClose: () => void; + onDelete: (qualityGate: QualityGate) => void; + organization?: string; + qualityGate: QualityGate; +} + +interface State { + loading: boolean; +} + +export default class DeleteQualityGateForm extends React.PureComponent { + mounted: boolean; + + static contextTypes = { + router: PropTypes.object + }; + + state: State = { loading: false }; + + componentDidMount() { + this.mounted = true; + } + + componentWillUnmount() { + this.mounted = false; + } + + handleCancelClick = (event: React.SyntheticEvent) => { + event.preventDefault(); + this.props.onClose(); + }; + + handleFormSubmit = (event: React.SyntheticEvent) => { + event.preventDefault(); + const { organization, qualityGate } = this.props; + this.setState({ loading: true }); + deleteQualityGate(qualityGate.id).then( + () => { + this.props.onDelete(qualityGate); + this.context.router.replace(getQualityGatesUrl(organization)); + }, + () => { + if (this.mounted) { + this.setState({ loading: false }); + } + } + ); + }; + + render() { + const { qualityGate } = this.props; + const header = translate('quality_gates.delete'); + + return ( + +
+
+

{header}

+
+
+

+ {translateWithParameters('quality_gates.delete.confirm.message', qualityGate.name)} +

+
+
+ {this.state.loading && } + + + {translate('cancel')} + +
+ +
+ ); + } +} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Details.js b/server/sonar-web/src/main/js/apps/quality-gates/components/Details.js index 2d3a5ad3beb..b6ff64b5c87 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/Details.js +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Details.js @@ -23,10 +23,6 @@ import Helmet from 'react-helmet'; import { fetchQualityGate, setQualityGateAsDefault } from '../../../api/quality-gates'; import DetailsHeader from './DetailsHeader'; import DetailsContent from './DetailsContent'; -import RenameView from '../views/rename-view'; -import CopyView from '../views/copy-view'; -import DeleteView from '../views/delete-view'; -import { getQualityGatesUrl, getQualityGateUrl } from '../../../helpers/urls'; export default class Details extends React.PureComponent { static contextTypes = { @@ -50,49 +46,8 @@ export default class Details extends React.PureComponent { () => {} ); - handleRenameClick = () => { - const { qualityGate, onRename } = this.props; - new RenameView({ - qualityGate, - onRename: (qualityGate, newName) => { - onRename(qualityGate, newName); - } - }).render(); - }; - - handleCopyClick = () => { - const { qualityGate, onCopy, organization } = this.props; - const { router } = this.context; - new CopyView({ - qualityGate, - onCopy: newQualityGate => { - onCopy(newQualityGate); - router.push(getQualityGateUrl(newQualityGate.id, organization && organization.key)); - } - }).render(); - }; - - handleSetAsDefaultClick = () => { - const { qualityGate, onSetAsDefault } = this.props; - if (!qualityGate.isDefault) { - setQualityGateAsDefault(qualityGate.id).then(() => onSetAsDefault(qualityGate), () => {}); - } - }; - - handleDeleteClick = () => { - const { qualityGate, onDelete, organization } = this.props; - const { router } = this.context; - new DeleteView({ - qualityGate, - onDelete: qualityGate => { - onDelete(qualityGate); - router.replace(getQualityGatesUrl(organization && organization.key)); - } - }).render(); - }; - render() { - const { qualityGate, metrics } = this.props; + const { organization, metrics, qualityGate } = this.props; const { onAddCondition, onDeleteCondition, onSaveCondition } = this.props; if (!qualityGate) { @@ -104,11 +59,11 @@ export default class Details extends React.PureComponent { { +interface Props { + qualityGate: QualityGate; + onRename: (qualityGate: QualityGate, newName: string) => void; + onCopy: (newQualityGate: QualityGate) => void; + onSetAsDefault: (qualityGate: QualityGate) => void; + onDelete: (qualityGate: QualityGate) => void; + organization?: string; +} + +interface State { + openPopup?: string; +} + +export default class DetailsHeader extends React.PureComponent { + state = { openPopup: undefined }; + + handleRenameClick = (e: React.SyntheticEvent) => { e.preventDefault(); - this.props.onRename(); + this.setState({ openPopup: 'rename' }); }; - handleCopyClick = e => { + handleCopyClick = (e: React.SyntheticEvent) => { e.preventDefault(); - this.props.onCopy(); + this.setState({ openPopup: 'copy' }); }; - handleSetAsDefaultClick = e => { + handleSetAsDefaultClick = (e: React.SyntheticEvent) => { e.preventDefault(); - this.props.onSetAsDefault(); + const { qualityGate, onSetAsDefault } = this.props; + if (!qualityGate.isDefault) { + setQualityGateAsDefault(qualityGate.id).then(() => onSetAsDefault(qualityGate), () => {}); + } }; - handleDeleteClick = e => { + handleDeleteClick = (e: React.SyntheticEvent) => { e.preventDefault(); - this.props.onDelete(); + this.setState({ openPopup: 'delete' }); }; + handleClosePopup = () => this.setState({ openPopup: undefined }); + render() { - const { qualityGate } = this.props; - const actions = qualityGate.actions || {}; + const { organization, qualityGate } = this.props; + const { openPopup } = this.state; + const actions = qualityGate.actions || ({} as any); return (
@@ -84,6 +109,32 @@ export default class DetailsHeader extends React.PureComponent { {translate('delete')} )} + {openPopup === 'rename' && ( + + )} + + {openPopup === 'copy' && ( + + )} + + {openPopup === 'delete' && ( + + )}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/List.js b/server/sonar-web/src/main/js/apps/quality-gates/components/List.js index d29633c5102..bc22c41a817 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/List.js +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/List.js @@ -29,7 +29,7 @@ export default function List({ organization, qualityGates }) { {qualityGates.map(qualityGate => ( diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.js b/server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.js deleted file mode 100644 index 2801cd954bb..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.js +++ /dev/null @@ -1,42 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 React from 'react'; -import CreateView from '../views/create-view'; -import { translate } from '../../../helpers/l10n'; - -export default function ListHeader({ canCreate, onAdd }) { - function handleAddClick(e) { - e.preventDefault(); - new CreateView({ onAdd }).render(); - } - - return ( -
-

{translate('quality_gates.page')}

- {canCreate && ( -
- -
- )} -
- ); -} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.tsx new file mode 100644 index 00000000000..d9ec9060188 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/ListHeader.tsx @@ -0,0 +1,65 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 CreateQualityGateForm from '../components/CreateQualityGateForm'; +import { QualityGate } from '../../../api/quality-gates'; +import { translate } from '../../../helpers/l10n'; +import { Organization } from '../../../app/types'; + +interface Props { + canCreate: boolean; + onAdd: (qualityGate: QualityGate) => void; + organization?: Organization; +} + +interface State { + createQualityGateOpen: boolean; +} + +export default class ListHeader extends React.PureComponent { + state = { createQualityGateOpen: false }; + + openCreateQualityGateForm = () => this.setState({ createQualityGateOpen: true }); + closeCreateQualityGateForm = () => this.setState({ createQualityGateOpen: false }); + + render() { + const { organization } = this.props; + + return ( +
+

{translate('quality_gates.page')}

+ {this.props.canCreate && ( +
+ +
+ )} + {this.state.createQualityGateOpen && ( + + )} +
+ ); + } +} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatesApp.js b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatesApp.js index 8d13fbae35e..96c3ed76f9a 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatesApp.js +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/QualityGatesApp.js @@ -56,19 +56,11 @@ export default class QualityGatesApp extends Component { updateStore({ actions, qualityGates }); if (qualityGates && qualityGates.length === 1 && !actions.create) { this.context.router.replace( - getQualityGateUrl(qualityGates[0].id, organization && organization.key) + getQualityGateUrl(String(qualityGates[0].id), organization && organization.key) ); } }); - handleAdd = qualityGate => { - const { addQualityGate, organization } = this.props; - const { router } = this.context; - - addQualityGate(qualityGate); - router.push(getQualityGateUrl(qualityGate.id, organization && organization.key)); - }; - render() { const { children, qualityGates, actions, organization } = this.props; const defaultTitle = translate('quality_gates.page'); @@ -81,7 +73,11 @@ export default class QualityGatesApp extends Component {
- + {qualityGates && }
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/RenameQualityGateForm.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/RenameQualityGateForm.tsx new file mode 100644 index 00000000000..b4a453fb678 --- /dev/null +++ b/server/sonar-web/src/main/js/apps/quality-gates/components/RenameQualityGateForm.tsx @@ -0,0 +1,125 @@ +/* + * SonarQube + * Copyright (C) 2009-2017 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 { QualityGate, renameQualityGate } from '../../../api/quality-gates'; +import { translate } from '../../../helpers/l10n'; + +interface Props { + qualityGate: QualityGate; + onRename: (qualityGate: QualityGate, newName: string) => void; + onClose: () => void; + organization?: string; +} + +interface State { + loading: boolean; + name: string; +} + +export default class RenameQualityGateForm extends React.PureComponent { + mounted: boolean; + + constructor(props: Props) { + super(props); + this.state = { loading: false, name: props.qualityGate.name }; + } + + componentDidMount() { + this.mounted = true; + } + + componentWillUnmount() { + this.mounted = false; + } + + handleCancelClick = (event: React.SyntheticEvent) => { + event.preventDefault(); + this.props.onClose(); + }; + + handleNameChange = (event: React.SyntheticEvent) => { + this.setState({ name: event.currentTarget.value }); + }; + + handleFormSubmit = (event: React.SyntheticEvent) => { + event.preventDefault(); + const { qualityGate, organization } = this.props; + const { name } = this.state; + if (name) { + this.setState({ loading: true }); + renameQualityGate({ id: qualityGate.id, name, organization }).then( + () => { + this.props.onRename(qualityGate, name); + this.props.onClose(); + }, + () => { + if (this.mounted) { + this.setState({ loading: false }); + } + } + ); + } + }; + + render() { + const { qualityGate } = this.props; + const { loading, name } = this.state; + const header = translate('quality_gates.rename'); + const submitDisabled = loading || !name || (qualityGate && qualityGate.name === name); + + return ( + +
+
+

{header}

+
+
+
+ + +
+
+
+ {loading && } + + + {translate('cancel')} + +
+ +
+ ); + } +} diff --git a/server/sonar-web/src/main/js/apps/quality-gates/templates/quality-gate-form.hbs b/server/sonar-web/src/main/js/apps/quality-gates/templates/quality-gate-form.hbs deleted file mode 100644 index bc6e623018e..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/templates/quality-gate-form.hbs +++ /dev/null @@ -1,20 +0,0 @@ -
- - - -
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/templates/quality-gates-delete.hbs b/server/sonar-web/src/main/js/apps/quality-gates/templates/quality-gates-delete.hbs deleted file mode 100644 index c146c581bae..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/templates/quality-gates-delete.hbs +++ /dev/null @@ -1,17 +0,0 @@ -
- - - -
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/views/copy-view.js b/server/sonar-web/src/main/js/apps/quality-gates/views/copy-view.js deleted file mode 100644 index a9b6da0d2f2..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/views/copy-view.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 ModalForm from '../../../components/common/modal-form'; -import Template from '../templates/quality-gate-form.hbs'; -import { copyQualityGate } from '../../../api/quality-gates'; -import { parseError } from '../../../helpers/request'; - -export default ModalForm.extend({ - template: Template, - - onFormSubmit() { - ModalForm.prototype.onFormSubmit.apply(this, arguments); - this.disableForm(); - this.sendRequest(); - }, - - sendRequest() { - const { id } = this.options.qualityGate; - const name = this.$('#quality-gate-form-name').val(); - - copyQualityGate(id, name).then( - qualityGate => { - this.destroy(); - this.options.onCopy(qualityGate); - }, - error => { - this.enableForm(); - parseError(error).then(msg => this.showErrors([{ msg }])); - } - ); - }, - - serializeData() { - return { method: 'copy', ...this.options.qualityGate }; - } -}); diff --git a/server/sonar-web/src/main/js/apps/quality-gates/views/create-view.js b/server/sonar-web/src/main/js/apps/quality-gates/views/create-view.js deleted file mode 100644 index 3580b45fcf6..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/views/create-view.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 ModalForm from '../../../components/common/modal-form'; -import Template from '../templates/quality-gate-form.hbs'; -import { createQualityGate } from '../../../api/quality-gates'; -import { parseError } from '../../../helpers/request'; - -export default ModalForm.extend({ - template: Template, - - onFormSubmit() { - ModalForm.prototype.onFormSubmit.apply(this, arguments); - this.disableForm(); - this.sendRequest(); - }, - - sendRequest() { - const name = this.$('#quality-gate-form-name').val(); - - createQualityGate(name).then( - qualityGate => { - this.destroy(); - this.options.onAdd(qualityGate); - }, - error => { - this.enableForm(); - parseError(error).then(msg => this.showErrors([{ msg }])); - } - ); - }, - - serializeData() { - return { method: 'create' }; - } -}); diff --git a/server/sonar-web/src/main/js/apps/quality-gates/views/delete-view.js b/server/sonar-web/src/main/js/apps/quality-gates/views/delete-view.js deleted file mode 100644 index 3327a6d3a10..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/views/delete-view.js +++ /dev/null @@ -1,52 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 ModalForm from '../../../components/common/modal-form'; -import Template from '../templates/quality-gates-delete.hbs'; -import { deleteQualityGate } from '../../../api/quality-gates'; -import { parseError } from '../../../helpers/request'; - -export default ModalForm.extend({ - template: Template, - - onFormSubmit() { - ModalForm.prototype.onFormSubmit.apply(this, arguments); - this.disableForm(); - this.sendRequest(); - }, - - sendRequest() { - const { id } = this.options.qualityGate; - - deleteQualityGate(id).then( - () => { - this.destroy(); - this.options.onDelete(this.options.qualityGate); - }, - error => { - this.enableForm(); - parseError(error).then(msg => this.showErrors([{ msg }])); - } - ); - }, - - serializeData() { - return this.options.qualityGate; - } -}); diff --git a/server/sonar-web/src/main/js/apps/quality-gates/views/gate-projects-view.js b/server/sonar-web/src/main/js/apps/quality-gates/views/gate-projects-view.js index 7909394dfe4..1b54745a857 100644 --- a/server/sonar-web/src/main/js/apps/quality-gates/views/gate-projects-view.js +++ b/server/sonar-web/src/main/js/apps/quality-gates/views/gate-projects-view.js @@ -25,9 +25,20 @@ import { translate } from '../../../helpers/l10n'; export default Marionette.ItemView.extend({ template: () => {}, + initialize(options) { + this.organization = options.organization; + }, + onRender() { const { qualityGate } = this.options; + const extra = { + gateId: qualityGate.id + }; + if (this.organization) { + extra.organization = this.organization.key; + } + new SelectList({ el: this.options.container, width: '100%', @@ -39,9 +50,7 @@ export default Marionette.ItemView.extend({ searchUrl: window.baseUrl + '/api/qualitygates/search?gateId=' + qualityGate.id, selectUrl: window.baseUrl + '/api/qualitygates/select', deselectUrl: window.baseUrl + '/api/qualitygates/deselect', - extra: { - gateId: qualityGate.id - }, + extra, selectParameter: 'projectId', selectParameterValue: 'id', labels: { diff --git a/server/sonar-web/src/main/js/apps/quality-gates/views/rename-view.js b/server/sonar-web/src/main/js/apps/quality-gates/views/rename-view.js deleted file mode 100644 index 2614ea6af67..00000000000 --- a/server/sonar-web/src/main/js/apps/quality-gates/views/rename-view.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2017 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 ModalForm from '../../../components/common/modal-form'; -import Template from '../templates/quality-gate-form.hbs'; -import { renameQualityGate } from '../../../api/quality-gates'; -import { parseError } from '../../../helpers/request'; - -export default ModalForm.extend({ - template: Template, - - onFormSubmit() { - ModalForm.prototype.onFormSubmit.apply(this, arguments); - this.disableForm(); - this.sendRequest(); - }, - - sendRequest() { - const { id } = this.options.qualityGate; - const name = this.$('#quality-gate-form-name').val(); - - renameQualityGate(id, name).then( - () => { - this.destroy(); - this.options.onRename(this.options.qualityGate, name); - }, - error => { - this.enableForm(); - parseError(error).then(msg => this.showErrors([{ msg }])); - } - ); - }, - - serializeData() { - return { method: 'rename', ...this.options.qualityGate }; - } -}); -- 2.39.5