aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-web/src/main/js/apps/quality-gates
diff options
context:
space:
mode:
authorStas Vilchik <stas.vilchik@sonarsource.com>2018-12-11 09:42:41 +0100
committerSonarTech <sonartech@sonarsource.com>2019-01-08 20:21:06 +0100
commite3b080e7a3e1eaf19f52f1f900cc341f0b989896 (patch)
treed1b78affbcf65a344bc8080c8db72f9927f5def5 /server/sonar-web/src/main/js/apps/quality-gates
parentbbdfc6267f94b82a7c1c072e0e400b3bee87610e (diff)
downloadsonarqube-e3b080e7a3e1eaf19f52f1f900cc341f0b989896.tar.gz
sonarqube-e3b080e7a3e1eaf19f52f1f900cc341f0b989896.zip
always open default quality gate
Diffstat (limited to 'server/sonar-web/src/main/js/apps/quality-gates')
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx60
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx53
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/Intro.tsx55
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Intro-test.tsx40
-rw-r--r--server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Intro-test.tsx.snap22
5 files changed, 55 insertions, 175 deletions
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx
index a1ad8e3ac30..3b7d6bff1bc 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/App.tsx
@@ -21,7 +21,6 @@ import * as React from 'react';
import { WithRouterProps } from 'react-router';
import Helmet from 'react-helmet';
import Details from './Details';
-import Intro from './Intro';
import List from './List';
import ListHeader from './ListHeader';
import DeferredSpinner from '../../../components/common/DeferredSpinner';
@@ -60,6 +59,12 @@ class App extends React.PureComponent<Props, State> {
addSideBarClass();
}
+ componentDidUpdate(prevProps: Props) {
+ if (prevProps.params.id !== undefined && this.props.params.id === undefined) {
+ this.openDefault(this.state.qualityGates);
+ }
+ }
+
componentWillUnmount() {
this.mounted = false;
removeWhitePageClass();
@@ -73,10 +78,8 @@ class App extends React.PureComponent<Props, State> {
if (this.mounted) {
this.setState({ canCreate: actions.create, loading: false, qualityGates });
- if (qualityGates && qualityGates.length === 1 && !actions.create) {
- this.props.router.replace(
- getQualityGateUrl(String(qualityGates[0].id), organization && organization.key)
- );
+ if (!this.props.params.id) {
+ this.openDefault(qualityGates);
}
}
},
@@ -88,6 +91,14 @@ class App extends React.PureComponent<Props, State> {
);
};
+ openDefault(qualityGates: T.QualityGate[]) {
+ const defaultQualityGate = qualityGates.find(gate => Boolean(gate.isDefault))!;
+ const { organization } = this.props;
+ this.props.router.replace(
+ getQualityGateUrl(String(defaultQualityGate.id), organization && organization.key)
+ );
+ }
+
handleSetDefault = (qualityGate: T.QualityGate) => {
this.setState(({ qualityGates }) => {
return {
@@ -101,31 +112,8 @@ class App extends React.PureComponent<Props, State> {
});
};
- renderContent() {
- const { id } = this.props.params;
- const organizationKey = this.props.organization && this.props.organization.key;
- if (id !== undefined) {
- return (
- <Details
- id={id}
- onSetDefault={this.handleSetDefault}
- organization={organizationKey}
- qualityGates={this.state.qualityGates}
- refreshQualityGates={this.fetchQualityGates}
- />
- );
- } else {
- return (
- <Intro
- organization={organizationKey}
- qualityGates={this.state.qualityGates}
- router={this.props.router}
- />
- );
- }
- }
-
render() {
+ const { id } = this.props.params;
const { canCreate, qualityGates } = this.state;
const defaultTitle = translate('quality_gates.page');
const organization = this.props.organization && this.props.organization.key;
@@ -146,16 +134,24 @@ class App extends React.PureComponent<Props, State> {
organization={organization}
refreshQualityGates={this.fetchQualityGates}
/>
- {qualityGates.length > 0 && (
+ <DeferredSpinner loading={this.state.loading}>
<List organization={organization} qualityGates={qualityGates} />
- )}
+ </DeferredSpinner>
</div>
</div>
</div>
)}
</ScreenPositionHelper>
- <DeferredSpinner loading={this.state.loading}>{this.renderContent()}</DeferredSpinner>
+ {id !== undefined && (
+ <Details
+ id={id}
+ onSetDefault={this.handleSetDefault}
+ organization={organization}
+ qualityGates={this.state.qualityGates}
+ refreshQualityGates={this.fetchQualityGates}
+ />
+ )}
</div>
</>
);
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx
index cd58b7fec43..fb9a7580e8c 100644
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx
+++ b/server/sonar-web/src/main/js/apps/quality-gates/components/Details.tsx
@@ -26,6 +26,7 @@ import { getMetrics, Store } from '../../../store/rootReducer';
import { fetchMetrics } from '../../../store/rootActions';
import { fetchQualityGate } from '../../../api/quality-gates';
import { checkIfDefault, addCondition, replaceCondition, deleteCondition } from '../utils';
+import DeferredSpinner from '../../../components/common/DeferredSpinner';
interface OwnProps {
id: string;
@@ -130,34 +131,34 @@ export class Details extends React.PureComponent<Props, State> {
render() {
const { organization, metrics, refreshQualityGates } = this.props;
- const { qualityGate } = this.state;
-
- if (!qualityGate) {
- return null;
- }
+ const { loading, qualityGate } = this.state;
return (
- <>
- <Helmet title={qualityGate.name} />
- <div className="layout-page-main">
- <DetailsHeader
- onSetDefault={this.handleSetDefault}
- organization={organization}
- qualityGate={qualityGate}
- refreshItem={this.fetchDetails}
- refreshList={refreshQualityGates}
- />
- <DetailsContent
- isDefault={checkIfDefault(qualityGate, this.props.qualityGates)}
- metrics={metrics}
- onAddCondition={this.handleAddCondition}
- onRemoveCondition={this.handleRemoveCondition}
- onSaveCondition={this.handleSaveCondition}
- organization={organization}
- qualityGate={qualityGate}
- />
- </div>
- </>
+ <div className="layout-page-main">
+ <DeferredSpinner loading={loading} timeout={200}>
+ {qualityGate && (
+ <>
+ <Helmet title={qualityGate.name} />
+ <DetailsHeader
+ onSetDefault={this.handleSetDefault}
+ organization={organization}
+ qualityGate={qualityGate}
+ refreshItem={this.fetchDetails}
+ refreshList={refreshQualityGates}
+ />
+ <DetailsContent
+ isDefault={checkIfDefault(qualityGate, this.props.qualityGates)}
+ metrics={metrics}
+ onAddCondition={this.handleAddCondition}
+ onRemoveCondition={this.handleRemoveCondition}
+ onSaveCondition={this.handleSaveCondition}
+ organization={organization}
+ qualityGate={qualityGate}
+ />
+ </>
+ )}
+ </DeferredSpinner>
+ </div>
);
}
}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/Intro.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/Intro.tsx
deleted file mode 100644
index 3443f67118e..00000000000
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/Intro.tsx
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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 { InjectedRouter } from 'react-router';
-import { translate } from '../../../helpers/l10n';
-import { getQualityGateUrl } from '../../../helpers/urls';
-
-interface Props {
- organization?: string;
- qualityGates: T.QualityGate[];
- router: InjectedRouter;
-}
-
-export default class Intro extends React.PureComponent<Props> {
- componentDidMount() {
- const defaultQualityGate = this.props.qualityGates.find(qualityGate =>
- Boolean(qualityGate.isDefault)
- );
- if (defaultQualityGate) {
- this.props.router.replace(
- getQualityGateUrl(String(defaultQualityGate.id), this.props.organization)
- );
- }
- }
-
- render() {
- return (
- <div className="layout-page-main">
- <div className="layout-page-main-inner">
- <div className="search-navigator-intro markdown">
- <p>{translate('quality_gates.intro.1')}</p>
- <p>{translate('quality_gates.intro.2')}</p>
- </div>
- </div>
- </div>
- );
- }
-}
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Intro-test.tsx b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Intro-test.tsx
deleted file mode 100644
index c2320622d9d..00000000000
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/Intro-test.tsx
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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 { shallow } from 'enzyme';
-import Intro from '../Intro';
-
-it('should redirect to detail of default quality gate', () => {
- const replace = jest.fn();
- shallow(
- <Intro
- organization="foo"
- qualityGates={[{ id: 1, name: 'Bar', isDefault: true }]}
- router={{ replace } as any}
- />
- );
- expect(replace).toHaveBeenCalledWith({ pathname: '/organizations/foo/quality_gates/show/1' });
-});
-
-it('should display the intro', () => {
- expect(
- shallow(<Intro organization="foo" qualityGates={[]} router={{} as any} />)
- ).toMatchSnapshot();
-});
diff --git a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Intro-test.tsx.snap b/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Intro-test.tsx.snap
deleted file mode 100644
index ba1263977b9..00000000000
--- a/server/sonar-web/src/main/js/apps/quality-gates/components/__tests__/__snapshots__/Intro-test.tsx.snap
+++ /dev/null
@@ -1,22 +0,0 @@
-// Jest Snapshot v1, https://goo.gl/fbAQLP
-
-exports[`should display the intro 1`] = `
-<div
- className="layout-page-main"
->
- <div
- className="layout-page-main-inner"
- >
- <div
- className="search-navigator-intro markdown"
- >
- <p>
- quality_gates.intro.1
- </p>
- <p>
- quality_gates.intro.2
- </p>
- </div>
- </div>
-</div>
-`;