From 8fdadf99370e485e6a0c33d3b3cfbe0732a7ce20 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Gr=C3=A9goire=20Aubert?= Date: Fri, 27 Apr 2018 17:11:12 +0200 Subject: [PATCH] SONAR-10274 Better page title handling for SonarCloud --- .../src/main/js/app/components/App.tsx | 10 +- .../js/app/components/AppContextContainer.tsx | 76 ++ .../app/components/DefaultHelmetContainer.js | 40 - .../main/js/app/components/GlobalLoading.tsx | 12 +- .../app/components/LocalizationContainer.tsx | 4 +- .../js/app/components/SimpleContainer.tsx | 64 +- .../src/main/js/app/utils/startReactApp.js | 157 ++-- .../js/apps/maintenance/components/App.tsx | 284 +++---- .../__tests__/__snapshots__/App-test.tsx.snap | 708 ++++++++++-------- .../resources/org/sonar/l10n/core.properties | 1 + 10 files changed, 723 insertions(+), 633 deletions(-) create mode 100644 server/sonar-web/src/main/js/app/components/AppContextContainer.tsx delete mode 100644 server/sonar-web/src/main/js/app/components/DefaultHelmetContainer.js diff --git a/server/sonar-web/src/main/js/app/components/App.tsx b/server/sonar-web/src/main/js/app/components/App.tsx index 4c5a266afde..7390182e2fd 100644 --- a/server/sonar-web/src/main/js/app/components/App.tsx +++ b/server/sonar-web/src/main/js/app/components/App.tsx @@ -18,8 +18,9 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import { connect } from 'react-redux'; import * as PropTypes from 'prop-types'; +import { connect } from 'react-redux'; +import Helmet from 'react-helmet'; import GlobalLoading from './GlobalLoading'; import { CurrentUser } from '../types'; import { fetchCurrentUser } from '../../store/users/actions'; @@ -117,7 +118,12 @@ class App extends React.PureComponent { if (this.state.loading) { return ; } - return this.props.children; + return ( + <> + + {this.props.children} + + ); } } diff --git a/server/sonar-web/src/main/js/app/components/AppContextContainer.tsx b/server/sonar-web/src/main/js/app/components/AppContextContainer.tsx new file mode 100644 index 00000000000..0ab3e78ccc4 --- /dev/null +++ b/server/sonar-web/src/main/js/app/components/AppContextContainer.tsx @@ -0,0 +1,76 @@ +/* + * 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 * as PropTypes from 'prop-types'; +import Helmet from 'react-helmet'; +import GlobalLoading from './GlobalLoading'; +import { tryGetGlobalNavigation } from '../../api/nav'; + +interface Props { + children?: React.ReactNode; +} + +interface State { + loading: boolean; + onSonarCloud: boolean; +} + +export default class AppContextContainer extends React.PureComponent { + mounted = false; + static childContextTypes = { onSonarCloud: PropTypes.bool }; + state: State = { loading: true, onSonarCloud: false }; + + getChildContext() { + return { onSonarCloud: this.state.onSonarCloud }; + } + + componentDidMount() { + this.mounted = true; + tryGetGlobalNavigation().then( + appState => { + if (this.mounted) { + this.setState({ + loading: false, + onSonarCloud: Boolean( + appState.settings && appState.settings['sonar.sonarcloud.enabled'] === 'true' + ) + }); + } + }, + () => {} + ); + } + + componentWillUnmount() { + this.mounted = false; + } + + render() { + if (this.state.loading) { + return ; + } + return ( + <> + + {this.props.children} + + ); + } +} diff --git a/server/sonar-web/src/main/js/app/components/DefaultHelmetContainer.js b/server/sonar-web/src/main/js/app/components/DefaultHelmetContainer.js deleted file mode 100644 index cfd72fd1485..00000000000 --- a/server/sonar-web/src/main/js/app/components/DefaultHelmetContainer.js +++ /dev/null @@ -1,40 +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 React from 'react'; -import { connect } from 'react-redux'; -import Helmet from 'react-helmet'; -import { getGlobalSettingValue } from '../../store/rootReducer'; - -function DefaultHelmetContainer({ children, onSonarCloud }) { - return ( -
- - {children} -
- ); -} - -const mapStateToProps = state => ({ - onSonarCloud: getGlobalSettingValue(state, 'sonar.sonarcloud.enabled') -}); - -export default connect(mapStateToProps)(DefaultHelmetContainer); diff --git a/server/sonar-web/src/main/js/app/components/GlobalLoading.tsx b/server/sonar-web/src/main/js/app/components/GlobalLoading.tsx index 1c0f433d014..ec873fb3a2e 100644 --- a/server/sonar-web/src/main/js/app/components/GlobalLoading.tsx +++ b/server/sonar-web/src/main/js/app/components/GlobalLoading.tsx @@ -18,12 +18,16 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; +import Helmet from 'react-helmet'; export default function GlobalLoading() { return ( -
- - Loading... -
+ <> + +
+ + Loading... +
+ ); } diff --git a/server/sonar-web/src/main/js/app/components/LocalizationContainer.tsx b/server/sonar-web/src/main/js/app/components/LocalizationContainer.tsx index dc6cea9cf58..aea9b8490ac 100644 --- a/server/sonar-web/src/main/js/app/components/LocalizationContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/LocalizationContainer.tsx @@ -72,8 +72,8 @@ export default class LocalizationContainer extends React.PureComponent + defaultLocale={this.state.lang || DEFAULT_LANGUAGE} + locale={this.state.lang || DEFAULT_LANGUAGE}> {this.props.children} ); diff --git a/server/sonar-web/src/main/js/app/components/SimpleContainer.tsx b/server/sonar-web/src/main/js/app/components/SimpleContainer.tsx index 728d654579f..800bbee9c22 100644 --- a/server/sonar-web/src/main/js/app/components/SimpleContainer.tsx +++ b/server/sonar-web/src/main/js/app/components/SimpleContainer.tsx @@ -18,11 +18,8 @@ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ import * as React from 'react'; -import * as PropTypes from 'prop-types'; -import GlobalLoading from './GlobalLoading'; import GlobalFooterContainer from './GlobalFooterContainer'; import * as theme from '../theme'; -import { tryGetGlobalNavigation } from '../../api/nav'; import NavBar from '../../components/nav/NavBar'; interface Props { @@ -30,57 +27,14 @@ interface Props { hideLoggedInInfo?: boolean; } -interface State { - loading: boolean; - onSonarCloud: boolean; -} - -export default class SimpleContainer extends React.PureComponent { - mounted = false; - - static childContextTypes = { - onSonarCloud: PropTypes.bool - }; - - state: State = { loading: true, onSonarCloud: false }; - - getChildContext() { - return { onSonarCloud: this.state.onSonarCloud }; - } - - componentDidMount() { - this.mounted = true; - tryGetGlobalNavigation().then( - appState => { - if (this.mounted) { - this.setState({ - loading: false, - onSonarCloud: Boolean( - appState.settings && appState.settings['sonar.sonarcloud.enabled'] === 'true' - ) - }); - } - }, - () => {} - ); - } - - componentWillUnmount() { - this.mounted = false; - } - - render() { - if (this.state.loading) { - return ; - } - return ( -
-
- - {this.props.children} -
- +export default function SimpleContainer({ children, hideLoggedInInfo }: Props) { + return ( +
+
+ + {children}
- ); - } + +
+ ); } diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.js b/server/sonar-web/src/main/js/app/utils/startReactApp.js index 98968f52f68..023bee3da4b 100644 --- a/server/sonar-web/src/main/js/app/utils/startReactApp.js +++ b/server/sonar-web/src/main/js/app/utils/startReactApp.js @@ -17,13 +17,14 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ +/* eslint-disable react/jsx-sort-props */ import React from 'react'; import { render } from 'react-dom'; import { Router, Route, IndexRoute, Redirect } from 'react-router'; import { Provider } from 'react-redux'; import getStore from './getStore'; import getHistory from './getHistory'; -import DefaultHelmetContainer from '../components/DefaultHelmetContainer'; +import AppContextContainer from '../components/AppContextContainer'; import LocalizationContainer from '../components/LocalizationContainer'; import MigrationContainer from '../components/MigrationContainer'; import App from '../components/App'; @@ -148,99 +149,95 @@ const startReactApp = () => { - - - - {maintenanceRoutes} - {setupRoutes} - + + + {maintenanceRoutes} + {setupRoutes} + - + + + - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + import('../components/ComponentContainer').then(i => i.default) + }> + + + + + - - - - - - - - + + - import('../components/ComponentContainer').then(i => i.default) - }> - - - - - - - - - - - - - - - - - - - {projectAdminRoutes} - - - + path="project/quality_profiles" + childRoutes={projectQualityProfilesRoutes} + /> + + - - - - - - - - - - - - + + + + + + {projectAdminRoutes} - - + + + + + + + + + + + + + + + + + diff --git a/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx b/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx index 8f19a13856e..4777ab4372c 100644 --- a/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx +++ b/server/sonar-web/src/main/js/apps/maintenance/components/App.tsx @@ -19,6 +19,7 @@ */ import * as React from 'react'; import * as classNames from 'classnames'; +import Helmet from 'react-helmet'; import { getMigrationStatus, getSystemStatus, migrateDatabase } from '../../../api/system'; import DateFromNow from '../../../components/intl/DateFromNow'; import TimeFormatter from '../../../components/intl/TimeFormatter'; @@ -129,156 +130,163 @@ export default class App extends React.PureComponent { const { state, status } = this.state; return ( -
-
- {status === 'OFFLINE' && ( - <> -

- {translate('maintenance.sonarqube_is_offline')} -

-

- {translate('maintenance.sonarqube_is_offline.text')} -

-

- {translate('maintenance.try_again')} -

- - )} + <> + +
+
+ {status === 'OFFLINE' && ( + <> +

+ {translate('maintenance.sonarqube_is_offline')} +

+

+ {translate('maintenance.sonarqube_is_offline.text')} +

+

+ {translate('maintenance.try_again')} +

+ + )} + + {status === 'UP' && ( + <> +

{translate('maintenance.sonarqube_is_up')}

+

+ {translate('maintenance.all_systems_opetational')} +

+

+ {translate('layout.home')} +

+ + )} - {status === 'UP' && ( - <> -

{translate('maintenance.sonarqube_is_up')}

-

- {translate('maintenance.all_systems_opetational')} -

-

- {translate('layout.home')} -

- - )} + {status === 'STARTING' && ( + <> +

+ {translate('maintenance.sonarqube_is_starting')} +

+

+ +

+ + )} - {status === 'STARTING' && ( - <> -

- {translate('maintenance.sonarqube_is_starting')} -

-

- -

- - )} + {status === 'DOWN' && ( + <> +

+ {translate('maintenance.sonarqube_is_down')} +

+

+ {translate('maintenance.sonarqube_is_down.text')} +

+

+ {translate('maintenance.try_again')} +

+ + )} - {status === 'DOWN' && ( - <> -

- {translate('maintenance.sonarqube_is_down')} -

-

{translate('maintenance.sonarqube_is_down.text')}

-

- {translate('maintenance.try_again')} -

- - )} + {(status === 'DB_MIGRATION_NEEDED' || status === 'DB_MIGRATION_RUNNING') && ( + <> +

+ {translate('maintenance.sonarqube_is_under_maintenance')} +

+

+

+ + )} - {(status === 'DB_MIGRATION_NEEDED' || status === 'DB_MIGRATION_RUNNING') && ( - <> -

- {translate('maintenance.sonarqube_is_under_maintenance')} -

-

-

- - )} + {state === 'NO_MIGRATION' && ( + <> +

+ {translate('maintenance.database_is_up_to_date')} +

+

+ {translate('layout.home')} +

+ + )} - {state === 'NO_MIGRATION' && ( - <> -

- {translate('maintenance.database_is_up_to_date')} -

-

- {translate('layout.home')} -

- - )} + {state === 'MIGRATION_REQUIRED' && ( + <> +

{translate('maintenance.upgrade_database')}

+

{translate('maintenance.upgrade_database.1')}

+

{translate('maintenance.upgrade_database.2')}

+

{translate('maintenance.upgrade_database.3')}

+
+ +
+ + )} - {state === 'MIGRATION_REQUIRED' && ( - <> -

{translate('maintenance.upgrade_database')}

-

{translate('maintenance.upgrade_database.1')}

-

{translate('maintenance.upgrade_database.2')}

-

{translate('maintenance.upgrade_database.3')}

-
- -
- - )} + {state === 'NOT_SUPPORTED' && ( + <> +

+ {translate('maintenance.migration_not_supported')} +

+

{translate('maintenance.migration_not_supported.text')}

+ + )} - {state === 'NOT_SUPPORTED' && ( - <> -

- {translate('maintenance.migration_not_supported')} -

-

{translate('maintenance.migration_not_supported.text')}

- - )} + {state === 'MIGRATION_RUNNING' && ( + <> +

{translate('maintenance.database_migration')}

+ {this.state.message && ( +

{this.state.message}

+ )} + {this.state.startedAt && ( +

+ {translate('background_tasks.table.started')}{' '} + +
+ + + +

+ )} +

+ +

+ + )} - {state === 'MIGRATION_RUNNING' && ( - <> -

{translate('maintenance.database_migration')}

- {this.state.message && ( -

{this.state.message}

- )} - {this.state.startedAt && ( + {state === 'MIGRATION_SUCCEEDED' && ( + <> +

+ {translate('maintenance.database_is_up_to_date')} +

- {translate('background_tasks.table.started')}{' '} - -
- - - + {translate('layout.home')}

- )} -

- -

- - )} - - {state === 'MIGRATION_SUCCEEDED' && ( - <> -

- {translate('maintenance.database_is_up_to_date')} -

-

- {translate('layout.home')} -

- - )} + + )} - {state === 'MIGRATION_FAILED' && ( - <> -

- {translate('maintenance.upgrade_failed')} -

-

{translate('maintenance.upgrade_failed.text')}

- - )} + {state === 'MIGRATION_FAILED' && ( + <> +

+ {translate('maintenance.upgrade_failed')} +

+

{translate('maintenance.upgrade_failed.text')}

+ + )} +
-
+ ); } } diff --git a/server/sonar-web/src/main/js/apps/maintenance/components/__tests__/__snapshots__/App-test.tsx.snap b/server/sonar-web/src/main/js/apps/maintenance/components/__tests__/__snapshots__/App-test.tsx.snap index d054e906e8c..9168d061485 100644 --- a/server/sonar-web/src/main/js/apps/maintenance/components/__tests__/__snapshots__/App-test.tsx.snap +++ b/server/sonar-web/src/main/js/apps/maintenance/components/__tests__/__snapshots__/App-test.tsx.snap @@ -1,398 +1,482 @@ // Jest Snapshot v1, https://goo.gl/fbAQLP exports[`Maintenance Page should render DB_MIGRATION_NEEDED status 1`] = ` -
+ +
- -

- maintenance.sonarqube_is_under_maintenance -

-

+ +

+ maintenance.sonarqube_is_under_maintenance +

+

-

+

- + /> + +

-
+ `; exports[`Maintenance Page should render DB_MIGRATION_RUNNING status 1`] = ` -
+ +
- -

- maintenance.sonarqube_is_under_maintenance -

-

+ +

+ maintenance.sonarqube_is_under_maintenance +

+

-

+

- + /> + +

-
+ `; exports[`Maintenance Page should render DOWN status 1`] = ` -
+ +
- + `; exports[`Maintenance Page should render OFFLINE status 1`] = ` -
+ +
- -

- maintenance.sonarqube_is_offline -

-

- maintenance.sonarqube_is_offline.text -

-

- + +

- maintenance.try_again - -

- + maintenance.sonarqube_is_offline +

+

+ maintenance.sonarqube_is_offline.text +

+

+ + maintenance.try_again + +

+
+
- + `; exports[`Maintenance Page should render STARTING status 1`] = ` -
+ +
- -

- maintenance.sonarqube_is_starting -

-

- -

-
+
+ +

+ maintenance.sonarqube_is_starting +

+

+ +

+
+
-
+ `; exports[`Maintenance Page should render UP status 1`] = ` -
+ +
- -

- maintenance.sonarqube_is_up -

-

- maintenance.all_systems_opetational -

-

- + +

+ maintenance.sonarqube_is_up +

+

- layout.home - -

-
+ maintenance.all_systems_opetational +

+

+ + layout.home + +

+ +
- + `; exports[`Setup Page should render MIGRATION_FAILED state 1`] = ` -
+ +
- -

- maintenance.upgrade_failed -

-

- maintenance.upgrade_failed.text -

-
+
+ +

+ maintenance.upgrade_failed +

+

+ maintenance.upgrade_failed.text +

+
+
-
+ `; exports[`Setup Page should render MIGRATION_SUCCEEDED state 1`] = ` -
+ +
- -

- maintenance.database_is_up_to_date -

-

- + +

+ maintenance.database_is_up_to_date +

+

- layout.home - -

-
+ + layout.home + +

+ +
- + `; exports[`Setup Page should render NO_MIGRATION state 1`] = ` -
+ +
- -

- maintenance.database_is_up_to_date -

-

- + +

- layout.home - -

- + maintenance.database_is_up_to_date +

+

+ + layout.home + +

+
+
- + `; exports[`Setup Page should render NOT_SUPPORTED state 1`] = ` -
+ +
- -

- maintenance.migration_not_supported -

-

- maintenance.migration_not_supported.text -

-
+
+ +

+ maintenance.migration_not_supported +

+

+ maintenance.migration_not_supported.text +

+
+
-
+ `; exports[`Setup Page should start migration 1`] = ` -
+ +
- -

- maintenance.upgrade_database -

-

- maintenance.upgrade_database.1 -

-

- maintenance.upgrade_database.2 -

-

- maintenance.upgrade_database.3 -

-
- -
-
+ maintenance.upgrade_database.2 +

+

+ maintenance.upgrade_database.3 +

+
+ +
+ +
- + `; exports[`Setup Page should start migration 2`] = ` -
+ +
- -

- maintenance.database_migration -

-

- background_tasks.table.started - - -
- + +

+ maintenance.database_migration +

+

- - -

-

- -

-
+
+ + + +

+

+ +

+ +
- + `; diff --git a/sonar-core/src/main/resources/org/sonar/l10n/core.properties b/sonar-core/src/main/resources/org/sonar/l10n/core.properties index 8a5e3264176..c8f3db1dc4b 100644 --- a/sonar-core/src/main/resources/org/sonar/l10n/core.properties +++ b/sonar-core/src/main/resources/org/sonar/l10n/core.properties @@ -2786,6 +2786,7 @@ groups.anyone=Anyone # MAINTENANCE # #------------------------------------------------------------------------------ +maintenance.page=Maintenance maintenance.upgrade_failed=Upgrade Failed maintenance.upgrade_failed.text=Database connection cannot be established. Please check database status and JDBC settings. maintenance.migration_not_supported=Migration not supported -- 2.39.5