]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10274 Better page title handling for SonarCloud
authorGrégoire Aubert <gregoire.aubert@sonarsource.com>
Fri, 27 Apr 2018 15:11:12 +0000 (17:11 +0200)
committerSonarTech <sonartech@sonarsource.com>
Thu, 3 May 2018 18:20:50 +0000 (20:20 +0200)
server/sonar-web/src/main/js/app/components/App.tsx
server/sonar-web/src/main/js/app/components/AppContextContainer.tsx [new file with mode: 0644]
server/sonar-web/src/main/js/app/components/DefaultHelmetContainer.js [deleted file]
server/sonar-web/src/main/js/app/components/GlobalLoading.tsx
server/sonar-web/src/main/js/app/components/LocalizationContainer.tsx
server/sonar-web/src/main/js/app/components/SimpleContainer.tsx
server/sonar-web/src/main/js/app/utils/startReactApp.js
server/sonar-web/src/main/js/apps/maintenance/components/App.tsx
server/sonar-web/src/main/js/apps/maintenance/components/__tests__/__snapshots__/App-test.tsx.snap
sonar-core/src/main/resources/org/sonar/l10n/core.properties

index 4c5a266afde707e82bb36ba5feacaa71ffd14f46..7390182e2fd6537b8259a1e62d15722edfc3b03f 100644 (file)
@@ -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<Props, State> {
     if (this.state.loading) {
       return <GlobalLoading />;
     }
-    return this.props.children;
+    return (
+      <>
+        <Helmet defaultTitle={this.state.onSonarCloud ? 'SonarCloud' : 'SonarQube'} />
+        {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 (file)
index 0000000..0ab3e78
--- /dev/null
@@ -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<Props, State> {
+  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 <GlobalLoading />;
+    }
+    return (
+      <>
+        <Helmet defaultTitle={this.state.onSonarCloud ? 'SonarCloud' : 'SonarQube'} />
+        {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 (file)
index cfd72fd..0000000
+++ /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 (
-    <div>
-      <Helmet
-        defaultTitle={onSonarCloud && onSonarCloud.value === 'true' ? 'SonarCloud' : 'SonarQube'}
-      />
-      {children}
-    </div>
-  );
-}
-
-const mapStateToProps = state => ({
-  onSonarCloud: getGlobalSettingValue(state, 'sonar.sonarcloud.enabled')
-});
-
-export default connect(mapStateToProps)(DefaultHelmetContainer);
index 1c0f433d0140ba928936eb0cc8f11418ae42f71a..ec873fb3a2e45afd643089fca093e40da223d0bc 100644 (file)
  * 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 (
-    <div className="global-loading">
-      <i className="spinner global-loading-spinner" />
-      <span className="global-loading-text">Loading...</span>
-    </div>
+    <>
+      <Helmet defaultTitle={'Loading...'} />
+      <div className="global-loading">
+        <i className="spinner global-loading-spinner" />
+        <span className="global-loading-text">Loading...</span>
+      </div>
+    </>
   );
 }
index dc6cea9cf5811dcddd733630c71a1bbbedb7cf2a..aea9b8490ac0c725aa198ea81845aa5e8af1fae5 100644 (file)
@@ -72,8 +72,8 @@ export default class LocalizationContainer extends React.PureComponent<Props, St
     }
     return (
       <IntlProvider
-        locale={this.state.lang || DEFAULT_LANGUAGE}
-        defaultLocale={this.state.lang || DEFAULT_LANGUAGE}>
+        defaultLocale={this.state.lang || DEFAULT_LANGUAGE}
+        locale={this.state.lang || DEFAULT_LANGUAGE}>
         {this.props.children}
       </IntlProvider>
     );
index 728d654579f670303bf4a0258c31891f264c383b..800bbee9c220381f3fb10b417a2b2cea8de4b167 100644 (file)
  * 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<Props, State> {
-  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 <GlobalLoading />;
-    }
-    return (
-      <div className="global-container">
-        <div className="page-wrapper" id="container">
-          <NavBar className="navbar-global" height={theme.globalNavHeightRaw} />
-          {this.props.children}
-        </div>
-        <GlobalFooterContainer hideLoggedInInfo={this.props.hideLoggedInInfo} />
+export default function SimpleContainer({ children, hideLoggedInInfo }: Props) {
+  return (
+    <div className="global-container">
+      <div className="page-wrapper" id="container">
+        <NavBar className="navbar-global" height={theme.globalNavHeightRaw} />
+        {children}
       </div>
-    );
-  }
+      <GlobalFooterContainer hideLoggedInInfo={hideLoggedInInfo} />
+    </div>
+  );
 }
index 98968f52f682444a74e180a6c5998cdae2c872f3..023bee3da4b27c525f847af3d997ef36e58c8417 100644 (file)
  * 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 = () => {
 
         <Route path="markdown/help" component={MarkdownHelp} />
 
-        <Route component={DefaultHelmetContainer}>
-          <Route component={LocalizationContainer}>
-            <Route component={SimpleContainer}>
-              <Route path="maintenance">{maintenanceRoutes}</Route>
-              <Route path="setup">{setupRoutes}</Route>
-            </Route>
+        <Route component={LocalizationContainer}>
+          <Route component={SimpleContainer}>
+            <Route path="maintenance">{maintenanceRoutes}</Route>
+            <Route path="setup">{setupRoutes}</Route>
+          </Route>
 
-            <Route component={MigrationContainer}>
+          <Route component={MigrationContainer}>
+            <Route component={AppContextContainer}>
               <Route component={SimpleSessionsContainer}>
                 <Route path="/sessions" childRoutes={sessionsRoutes} />
               </Route>
+            </Route>
 
-              <Route path="/" component={App}>
-                <IndexRoute component={Landing} />
-
-                <Route component={GlobalContainer}>
-                  <Route path="about" childRoutes={aboutRoutes} />
-                  <Route path="account" childRoutes={accountRoutes} />
-                  <Route path="coding_rules" childRoutes={codingRulesRoutes} />
-                  <Route path="component" childRoutes={componentRoutes} />
-                  <Route path="explore" component={Explore}>
-                    <Route path="issues" component={ExploreIssues} />
-                    <Route path="projects" component={ExploreProjects} />
-                  </Route>
+            <Route path="/" component={App}>
+              <IndexRoute component={Landing} />
+
+              <Route component={GlobalContainer}>
+                <Route path="about" childRoutes={aboutRoutes} />
+                <Route path="account" childRoutes={accountRoutes} />
+                <Route path="coding_rules" childRoutes={codingRulesRoutes} />
+                <Route path="component" childRoutes={componentRoutes} />
+                <Route path="explore" component={Explore}>
+                  <Route path="issues" component={ExploreIssues} />
+                  <Route path="projects" component={ExploreProjects} />
+                </Route>
+                <Route path="extension/:pluginKey/:extensionKey" component={GlobalPageExtension} />
+                <Route path="issues" component={IssuesPageSelector} />
+                <Route path="organizations" childRoutes={organizationsRoutes} />
+                <Route path="projects" childRoutes={projectsRoutes} />
+                <Route path="quality_gates" childRoutes={qualityGatesRoutes} />
+                <Route path="portfolios" component={PortfoliosPage} />
+                <Route path="profiles" childRoutes={qualityProfilesRoutes} />
+                <Route path="web_api" childRoutes={webAPIRoutes} />
+
+                <Route
+                  getComponent={() =>
+                    import('../components/ComponentContainer').then(i => i.default)
+                  }>
+                  <Route path="code" childRoutes={codeRoutes} />
+                  <Route path="component_measures" childRoutes={componentMeasuresRoutes} />
+                  <Route path="dashboard" childRoutes={overviewRoutes} />
+                  <Route path="portfolio" childRoutes={portfolioRoutes} />
+                  <Route path="project/activity" childRoutes={projectActivityRoutes} />
                   <Route
-                    path="extension/:pluginKey/:extensionKey"
-                    component={GlobalPageExtension}
+                    path="project/extension/:pluginKey/:extensionKey"
+                    component={ProjectPageExtension}
                   />
-                  <Route path="issues" component={IssuesPageSelector} />
-                  <Route path="organizations" childRoutes={organizationsRoutes} />
-                  <Route path="projects" childRoutes={projectsRoutes} />
-                  <Route path="quality_gates" childRoutes={qualityGatesRoutes} />
-                  <Route path="portfolios" component={PortfoliosPage} />
-                  <Route path="profiles" childRoutes={qualityProfilesRoutes} />
-                  <Route path="web_api" childRoutes={webAPIRoutes} />
-
+                  <Route path="project/issues" component={Issues} />
+                  <Route path="project/quality_gate" childRoutes={projectQualityGateRoutes} />
                   <Route
-                    getComponent={() =>
-                      import('../components/ComponentContainer').then(i => i.default)
-                    }>
-                    <Route path="code" childRoutes={codeRoutes} />
-                    <Route path="component_measures" childRoutes={componentMeasuresRoutes} />
-                    <Route path="dashboard" childRoutes={overviewRoutes} />
-                    <Route path="portfolio" childRoutes={portfolioRoutes} />
-                    <Route path="project/activity" childRoutes={projectActivityRoutes} />
-                    <Route
-                      path="project/extension/:pluginKey/:extensionKey"
-                      component={ProjectPageExtension}
-                    />
-                    <Route path="project/issues" component={Issues} />
-                    <Route path="project/quality_gate" childRoutes={projectQualityGateRoutes} />
-                    <Route
-                      path="project/quality_profiles"
-                      childRoutes={projectQualityProfilesRoutes}
-                    />
-                    <Route component={ProjectAdminContainer}>
-                      <Route path="custom_measures" childRoutes={customMeasuresRoutes} />
-                      <Route
-                        path="project/admin/extension/:pluginKey/:extensionKey"
-                        component={ProjectAdminPageExtension}
-                      />
-                      <Route path="project/background_tasks" childRoutes={backgroundTasksRoutes} />
-                      <Route path="project/branches" childRoutes={projectBranchesRoutes} />
-                      <Route path="project/settings" childRoutes={settingsRoutes} />
-                      <Route path="project_roles" childRoutes={projectPermissionsRoutes} />
-                      <Route path="project/webhooks" childRoutes={webhooksRoutes} />
-                    </Route>
-                    {projectAdminRoutes}
-                  </Route>
-
-                  <Route component={AdminContainer} path="admin">
+                    path="project/quality_profiles"
+                    childRoutes={projectQualityProfilesRoutes}
+                  />
+                  <Route component={ProjectAdminContainer}>
+                    <Route path="custom_measures" childRoutes={customMeasuresRoutes} />
                     <Route
-                      path="extension/:pluginKey/:extensionKey"
-                      component={GlobalAdminPageExtension}
+                      path="project/admin/extension/:pluginKey/:extensionKey"
+                      component={ProjectAdminPageExtension}
                     />
-                    <Route path="background_tasks" childRoutes={backgroundTasksRoutes} />
-                    <Route path="custom_metrics" childRoutes={customMetricsRoutes} />
-                    <Route path="groups" childRoutes={groupsRoutes} />
-                    <Route path="permission_templates" childRoutes={permissionTemplatesRoutes} />
-                    <Route path="roles/global" childRoutes={globalPermissionsRoutes} />
-                    <Route path="permissions" childRoutes={globalPermissionsRoutes} />
-                    <Route path="projects_management" childRoutes={projectsManagementRoutes} />
-                    <Route path="settings" childRoutes={settingsRoutes} />
-                    <Route path="system" childRoutes={systemRoutes} />
-                    <Route path="marketplace" childRoutes={marketplaceRoutes} />
-                    <Route path="users" childRoutes={usersRoutes} />
-                    <Route path="webhooks" childRoutes={webhooksRoutes} />
+                    <Route path="project/background_tasks" childRoutes={backgroundTasksRoutes} />
+                    <Route path="project/branches" childRoutes={projectBranchesRoutes} />
+                    <Route path="project/settings" childRoutes={settingsRoutes} />
+                    <Route path="project_roles" childRoutes={projectPermissionsRoutes} />
+                    <Route path="project/webhooks" childRoutes={webhooksRoutes} />
                   </Route>
+                  {projectAdminRoutes}
                 </Route>
 
-                <Route path="not_found" component={NotFound} />
-                <Route path="*" component={NotFound} />
+                <Route component={AdminContainer} path="admin">
+                  <Route
+                    path="extension/:pluginKey/:extensionKey"
+                    component={GlobalAdminPageExtension}
+                  />
+                  <Route path="background_tasks" childRoutes={backgroundTasksRoutes} />
+                  <Route path="custom_metrics" childRoutes={customMetricsRoutes} />
+                  <Route path="groups" childRoutes={groupsRoutes} />
+                  <Route path="permission_templates" childRoutes={permissionTemplatesRoutes} />
+                  <Route path="roles/global" childRoutes={globalPermissionsRoutes} />
+                  <Route path="permissions" childRoutes={globalPermissionsRoutes} />
+                  <Route path="projects_management" childRoutes={projectsManagementRoutes} />
+                  <Route path="settings" childRoutes={settingsRoutes} />
+                  <Route path="system" childRoutes={systemRoutes} />
+                  <Route path="marketplace" childRoutes={marketplaceRoutes} />
+                  <Route path="users" childRoutes={usersRoutes} />
+                  <Route path="webhooks" childRoutes={webhooksRoutes} />
+                </Route>
               </Route>
+              <Route path="not_found" component={NotFound} />
+              <Route path="*" component={NotFound} />
             </Route>
           </Route>
         </Route>
index 8f19a13856ec6b8d2da285b95f16b37db56ec121..4777ab4372c0d5331cc2a89b34f8972c3a56fc61 100644 (file)
@@ -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<Props, State> {
     const { state, status } = this.state;
 
     return (
-      <div className="page-wrapper-simple" id="bd">
-        <div
-          className={classNames('page-simple', { 'panel-warning': state === 'MIGRATION_REQUIRED' })}
-          id="nonav">
-          {status === 'OFFLINE' && (
-            <>
-              <h1 className="maintenance-title text-danger">
-                {translate('maintenance.sonarqube_is_offline')}
-              </h1>
-              <p className="maintenance-text">
-                {translate('maintenance.sonarqube_is_offline.text')}
-              </p>
-              <p className="maintenance-text text-center">
-                <a href={getBaseUrl() + '/'}>{translate('maintenance.try_again')}</a>
-              </p>
-            </>
-          )}
+      <>
+        <Helmet defaultTitle={translate('maintenance.page')} />
+        <div className="page-wrapper-simple" id="bd">
+          <div
+            className={classNames('page-simple', {
+              'panel-warning': state === 'MIGRATION_REQUIRED'
+            })}
+            id="nonav">
+            {status === 'OFFLINE' && (
+              <>
+                <h1 className="maintenance-title text-danger">
+                  {translate('maintenance.sonarqube_is_offline')}
+                </h1>
+                <p className="maintenance-text">
+                  {translate('maintenance.sonarqube_is_offline.text')}
+                </p>
+                <p className="maintenance-text text-center">
+                  <a href={getBaseUrl() + '/'}>{translate('maintenance.try_again')}</a>
+                </p>
+              </>
+            )}
+
+            {status === 'UP' && (
+              <>
+                <h1 className="maintenance-title">{translate('maintenance.sonarqube_is_up')}</h1>
+                <p className="maintenance-text text-center">
+                  {translate('maintenance.all_systems_opetational')}
+                </p>
+                <p className="maintenance-text text-center">
+                  <a href={getBaseUrl() + '/'}>{translate('layout.home')}</a>
+                </p>
+              </>
+            )}
 
-          {status === 'UP' && (
-            <>
-              <h1 className="maintenance-title">{translate('maintenance.sonarqube_is_up')}</h1>
-              <p className="maintenance-text text-center">
-                {translate('maintenance.all_systems_opetational')}
-              </p>
-              <p className="maintenance-text text-center">
-                <a href={getBaseUrl() + '/'}>{translate('layout.home')}</a>
-              </p>
-            </>
-          )}
+            {status === 'STARTING' && (
+              <>
+                <h1 className="maintenance-title">
+                  {translate('maintenance.sonarqube_is_starting')}
+                </h1>
+                <p className="maintenance-spinner">
+                  <i className="spinner" />
+                </p>
+              </>
+            )}
 
-          {status === 'STARTING' && (
-            <>
-              <h1 className="maintenance-title">
-                {translate('maintenance.sonarqube_is_starting')}
-              </h1>
-              <p className="maintenance-spinner">
-                <i className="spinner" />
-              </p>
-            </>
-          )}
+            {status === 'DOWN' && (
+              <>
+                <h1 className="maintenance-title text-danger">
+                  {translate('maintenance.sonarqube_is_down')}
+                </h1>
+                <p className="maintenance-text">
+                  {translate('maintenance.sonarqube_is_down.text')}
+                </p>
+                <p className="maintenance-text text-center">
+                  <a href={getBaseUrl() + '/'}>{translate('maintenance.try_again')}</a>
+                </p>
+              </>
+            )}
 
-          {status === 'DOWN' && (
-            <>
-              <h1 className="maintenance-title text-danger">
-                {translate('maintenance.sonarqube_is_down')}
-              </h1>
-              <p className="maintenance-text">{translate('maintenance.sonarqube_is_down.text')}</p>
-              <p className="maintenance-text text-center">
-                <a href={getBaseUrl() + '/'}>{translate('maintenance.try_again')}</a>
-              </p>
-            </>
-          )}
+            {(status === 'DB_MIGRATION_NEEDED' || status === 'DB_MIGRATION_RUNNING') && (
+              <>
+                <h1 className="maintenance-title">
+                  {translate('maintenance.sonarqube_is_under_maintenance')}
+                </h1>
+                <p
+                  className="maintenance-text"
+                  dangerouslySetInnerHTML={{
+                    __html: translate('maintenance.sonarqube_is_under_maintenance.1')
+                  }}
+                />
+                <p
+                  className="maintenance-text"
+                  dangerouslySetInnerHTML={{
+                    __html: translate('maintenance.sonarqube_is_under_maintenance.2')
+                  }}
+                />
+              </>
+            )}
 
-          {(status === 'DB_MIGRATION_NEEDED' || status === 'DB_MIGRATION_RUNNING') && (
-            <>
-              <h1 className="maintenance-title">
-                {translate('maintenance.sonarqube_is_under_maintenance')}
-              </h1>
-              <p
-                className="maintenance-text"
-                dangerouslySetInnerHTML={{
-                  __html: translate('maintenance.sonarqube_is_under_maintenance.1')
-                }}
-              />
-              <p
-                className="maintenance-text"
-                dangerouslySetInnerHTML={{
-                  __html: translate('maintenance.sonarqube_is_under_maintenance.2')
-                }}
-              />
-            </>
-          )}
+            {state === 'NO_MIGRATION' && (
+              <>
+                <h1 className="maintenance-title">
+                  {translate('maintenance.database_is_up_to_date')}
+                </h1>
+                <p className="maintenance-text text-center">
+                  <a href={getBaseUrl() + '/'}>{translate('layout.home')}</a>
+                </p>
+              </>
+            )}
 
-          {state === 'NO_MIGRATION' && (
-            <>
-              <h1 className="maintenance-title">
-                {translate('maintenance.database_is_up_to_date')}
-              </h1>
-              <p className="maintenance-text text-center">
-                <a href={getBaseUrl() + '/'}>{translate('layout.home')}</a>
-              </p>
-            </>
-          )}
+            {state === 'MIGRATION_REQUIRED' && (
+              <>
+                <h1 className="maintenance-title">{translate('maintenance.upgrade_database')}</h1>
+                <p className="maintenance-text">{translate('maintenance.upgrade_database.1')}</p>
+                <p className="maintenance-text">{translate('maintenance.upgrade_database.2')}</p>
+                <p className="maintenance-text">{translate('maintenance.upgrade_database.3')}</p>
+                <div className="maintenance-spinner">
+                  <Button id="start-migration" onClick={this.handleMigrateClick}>
+                    {translate('maintenance.upgrade')}
+                  </Button>
+                </div>
+              </>
+            )}
 
-          {state === 'MIGRATION_REQUIRED' && (
-            <>
-              <h1 className="maintenance-title">{translate('maintenance.upgrade_database')}</h1>
-              <p className="maintenance-text">{translate('maintenance.upgrade_database.1')}</p>
-              <p className="maintenance-text">{translate('maintenance.upgrade_database.2')}</p>
-              <p className="maintenance-text">{translate('maintenance.upgrade_database.3')}</p>
-              <div className="maintenance-spinner">
-                <Button id="start-migration" onClick={this.handleMigrateClick}>
-                  {translate('maintenance.upgrade')}
-                </Button>
-              </div>
-            </>
-          )}
+            {state === 'NOT_SUPPORTED' && (
+              <>
+                <h1 className="maintenance-title text-danger">
+                  {translate('maintenance.migration_not_supported')}
+                </h1>
+                <p>{translate('maintenance.migration_not_supported.text')}</p>
+              </>
+            )}
 
-          {state === 'NOT_SUPPORTED' && (
-            <>
-              <h1 className="maintenance-title text-danger">
-                {translate('maintenance.migration_not_supported')}
-              </h1>
-              <p>{translate('maintenance.migration_not_supported.text')}</p>
-            </>
-          )}
+            {state === 'MIGRATION_RUNNING' && (
+              <>
+                <h1 className="maintenance-title">{translate('maintenance.database_migration')}</h1>
+                {this.state.message && (
+                  <p className="maintenance-text text-center">{this.state.message}</p>
+                )}
+                {this.state.startedAt && (
+                  <p className="maintenance-text text-center">
+                    {translate('background_tasks.table.started')}{' '}
+                    <DateFromNow date={this.state.startedAt} />
+                    <br />
+                    <small className="text-muted">
+                      <TimeFormatter date={this.state.startedAt} long={true} />
+                    </small>
+                  </p>
+                )}
+                <p className="maintenance-spinner">
+                  <i className="spinner" />
+                </p>
+              </>
+            )}
 
-          {state === 'MIGRATION_RUNNING' && (
-            <>
-              <h1 className="maintenance-title">{translate('maintenance.database_migration')}</h1>
-              {this.state.message && (
-                <p className="maintenance-text text-center">{this.state.message}</p>
-              )}
-              {this.state.startedAt && (
+            {state === 'MIGRATION_SUCCEEDED' && (
+              <>
+                <h1 className="maintenance-title text-success">
+                  {translate('maintenance.database_is_up_to_date')}
+                </h1>
                 <p className="maintenance-text text-center">
-                  {translate('background_tasks.table.started')}{' '}
-                  <DateFromNow date={this.state.startedAt} />
-                  <br />
-                  <small className="text-muted">
-                    <TimeFormatter date={this.state.startedAt} long={true} />
-                  </small>
+                  <a href={getBaseUrl() + '/'}>{translate('layout.home')}</a>
                 </p>
-              )}
-              <p className="maintenance-spinner">
-                <i className="spinner" />
-              </p>
-            </>
-          )}
-
-          {state === 'MIGRATION_SUCCEEDED' && (
-            <>
-              <h1 className="maintenance-title text-success">
-                {translate('maintenance.database_is_up_to_date')}
-              </h1>
-              <p className="maintenance-text text-center">
-                <a href={getBaseUrl() + '/'}>{translate('layout.home')}</a>
-              </p>
-            </>
-          )}
+              </>
+            )}
 
-          {state === 'MIGRATION_FAILED' && (
-            <>
-              <h1 className="maintenance-title text-danger">
-                {translate('maintenance.upgrade_failed')}
-              </h1>
-              <p className="maintenance-text">{translate('maintenance.upgrade_failed.text')}</p>
-            </>
-          )}
+            {state === 'MIGRATION_FAILED' && (
+              <>
+                <h1 className="maintenance-title text-danger">
+                  {translate('maintenance.upgrade_failed')}
+                </h1>
+                <p className="maintenance-text">{translate('maintenance.upgrade_failed.text')}</p>
+              </>
+            )}
+          </div>
         </div>
-      </div>
+      </>
     );
   }
 }
index d054e906e8c8522a81079334727b4d01901a7d55..9168d061485fd158f9197948e37697d9b76615d7 100644 (file)
 // Jest Snapshot v1, https://goo.gl/fbAQLP
 
 exports[`Maintenance Page should render DB_MIGRATION_NEEDED status 1`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title"
-      >
-        maintenance.sonarqube_is_under_maintenance
-      </h1>
-      <p
-        className="maintenance-text"
-        dangerouslySetInnerHTML={
-          Object {
-            "__html": "maintenance.sonarqube_is_under_maintenance.1",
+    <div
+      className="page-simple"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title"
+        >
+          maintenance.sonarqube_is_under_maintenance
+        </h1>
+        <p
+          className="maintenance-text"
+          dangerouslySetInnerHTML={
+            Object {
+              "__html": "maintenance.sonarqube_is_under_maintenance.1",
+            }
           }
-        }
-      />
-      <p
-        className="maintenance-text"
-        dangerouslySetInnerHTML={
-          Object {
-            "__html": "maintenance.sonarqube_is_under_maintenance.2",
+        />
+        <p
+          className="maintenance-text"
+          dangerouslySetInnerHTML={
+            Object {
+              "__html": "maintenance.sonarqube_is_under_maintenance.2",
+            }
           }
-        }
-      />
-    </React.Fragment>
+        />
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
 
 exports[`Maintenance Page should render DB_MIGRATION_RUNNING status 1`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title"
-      >
-        maintenance.sonarqube_is_under_maintenance
-      </h1>
-      <p
-        className="maintenance-text"
-        dangerouslySetInnerHTML={
-          Object {
-            "__html": "maintenance.sonarqube_is_under_maintenance.1",
+    <div
+      className="page-simple"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title"
+        >
+          maintenance.sonarqube_is_under_maintenance
+        </h1>
+        <p
+          className="maintenance-text"
+          dangerouslySetInnerHTML={
+            Object {
+              "__html": "maintenance.sonarqube_is_under_maintenance.1",
+            }
           }
-        }
-      />
-      <p
-        className="maintenance-text"
-        dangerouslySetInnerHTML={
-          Object {
-            "__html": "maintenance.sonarqube_is_under_maintenance.2",
+        />
+        <p
+          className="maintenance-text"
+          dangerouslySetInnerHTML={
+            Object {
+              "__html": "maintenance.sonarqube_is_under_maintenance.2",
+            }
           }
-        }
-      />
-    </React.Fragment>
+        />
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
 
 exports[`Maintenance Page should render DOWN status 1`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title text-danger"
-      >
-        maintenance.sonarqube_is_down
-      </h1>
-      <p
-        className="maintenance-text"
-      >
-        maintenance.sonarqube_is_down.text
-      </p>
-      <p
-        className="maintenance-text text-center"
-      >
-        <a
-          href="/"
+    <div
+      className="page-simple"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title text-danger"
+        >
+          maintenance.sonarqube_is_down
+        </h1>
+        <p
+          className="maintenance-text"
+        >
+          maintenance.sonarqube_is_down.text
+        </p>
+        <p
+          className="maintenance-text text-center"
         >
-          maintenance.try_again
-        </a>
-      </p>
-    </React.Fragment>
+          <a
+            href="/"
+          >
+            maintenance.try_again
+          </a>
+        </p>
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
 
 exports[`Maintenance Page should render OFFLINE status 1`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title text-danger"
-      >
-        maintenance.sonarqube_is_offline
-      </h1>
-      <p
-        className="maintenance-text"
-      >
-        maintenance.sonarqube_is_offline.text
-      </p>
-      <p
-        className="maintenance-text text-center"
-      >
-        <a
-          href="/"
+    <div
+      className="page-simple"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title text-danger"
         >
-          maintenance.try_again
-        </a>
-      </p>
-    </React.Fragment>
+          maintenance.sonarqube_is_offline
+        </h1>
+        <p
+          className="maintenance-text"
+        >
+          maintenance.sonarqube_is_offline.text
+        </p>
+        <p
+          className="maintenance-text text-center"
+        >
+          <a
+            href="/"
+          >
+            maintenance.try_again
+          </a>
+        </p>
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
 
 exports[`Maintenance Page should render STARTING status 1`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title"
-      >
-        maintenance.sonarqube_is_starting
-      </h1>
-      <p
-        className="maintenance-spinner"
-      >
-        <i
-          className="spinner"
-        />
-      </p>
-    </React.Fragment>
+    <div
+      className="page-simple"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title"
+        >
+          maintenance.sonarqube_is_starting
+        </h1>
+        <p
+          className="maintenance-spinner"
+        >
+          <i
+            className="spinner"
+          />
+        </p>
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
 
 exports[`Maintenance Page should render UP status 1`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title"
-      >
-        maintenance.sonarqube_is_up
-      </h1>
-      <p
-        className="maintenance-text text-center"
-      >
-        maintenance.all_systems_opetational
-      </p>
-      <p
-        className="maintenance-text text-center"
-      >
-        <a
-          href="/"
+    <div
+      className="page-simple"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title"
+        >
+          maintenance.sonarqube_is_up
+        </h1>
+        <p
+          className="maintenance-text text-center"
         >
-          layout.home
-        </a>
-      </p>
-    </React.Fragment>
+          maintenance.all_systems_opetational
+        </p>
+        <p
+          className="maintenance-text text-center"
+        >
+          <a
+            href="/"
+          >
+            layout.home
+          </a>
+        </p>
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
 
 exports[`Setup Page should render MIGRATION_FAILED state 1`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title text-danger"
-      >
-        maintenance.upgrade_failed
-      </h1>
-      <p
-        className="maintenance-text"
-      >
-        maintenance.upgrade_failed.text
-      </p>
-    </React.Fragment>
+    <div
+      className="page-simple"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title text-danger"
+        >
+          maintenance.upgrade_failed
+        </h1>
+        <p
+          className="maintenance-text"
+        >
+          maintenance.upgrade_failed.text
+        </p>
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
 
 exports[`Setup Page should render MIGRATION_SUCCEEDED state 1`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title text-success"
-      >
-        maintenance.database_is_up_to_date
-      </h1>
-      <p
-        className="maintenance-text text-center"
-      >
-        <a
-          href="/"
+    <div
+      className="page-simple"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title text-success"
+        >
+          maintenance.database_is_up_to_date
+        </h1>
+        <p
+          className="maintenance-text text-center"
         >
-          layout.home
-        </a>
-      </p>
-    </React.Fragment>
+          <a
+            href="/"
+          >
+            layout.home
+          </a>
+        </p>
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
 
 exports[`Setup Page should render NO_MIGRATION state 1`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title"
-      >
-        maintenance.database_is_up_to_date
-      </h1>
-      <p
-        className="maintenance-text text-center"
-      >
-        <a
-          href="/"
+    <div
+      className="page-simple"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title"
         >
-          layout.home
-        </a>
-      </p>
-    </React.Fragment>
+          maintenance.database_is_up_to_date
+        </h1>
+        <p
+          className="maintenance-text text-center"
+        >
+          <a
+            href="/"
+          >
+            layout.home
+          </a>
+        </p>
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
 
 exports[`Setup Page should render NOT_SUPPORTED state 1`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title text-danger"
-      >
-        maintenance.migration_not_supported
-      </h1>
-      <p>
-        maintenance.migration_not_supported.text
-      </p>
-    </React.Fragment>
+    <div
+      className="page-simple"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title text-danger"
+        >
+          maintenance.migration_not_supported
+        </h1>
+        <p>
+          maintenance.migration_not_supported.text
+        </p>
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
 
 exports[`Setup Page should start migration 1`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple panel-warning"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title"
-      >
-        maintenance.upgrade_database
-      </h1>
-      <p
-        className="maintenance-text"
-      >
-        maintenance.upgrade_database.1
-      </p>
-      <p
-        className="maintenance-text"
-      >
-        maintenance.upgrade_database.2
-      </p>
-      <p
-        className="maintenance-text"
-      >
-        maintenance.upgrade_database.3
-      </p>
-      <div
-        className="maintenance-spinner"
-      >
-        <Button
-          id="start-migration"
-          onClick={[Function]}
+    <div
+      className="page-simple panel-warning"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title"
+        >
+          maintenance.upgrade_database
+        </h1>
+        <p
+          className="maintenance-text"
+        >
+          maintenance.upgrade_database.1
+        </p>
+        <p
+          className="maintenance-text"
         >
-          maintenance.upgrade
-        </Button>
-      </div>
-    </React.Fragment>
+          maintenance.upgrade_database.2
+        </p>
+        <p
+          className="maintenance-text"
+        >
+          maintenance.upgrade_database.3
+        </p>
+        <div
+          className="maintenance-spinner"
+        >
+          <Button
+            id="start-migration"
+            onClick={[Function]}
+          >
+            maintenance.upgrade
+          </Button>
+        </div>
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
 
 exports[`Setup Page should start migration 2`] = `
-<div
-  className="page-wrapper-simple"
-  id="bd"
->
+<React.Fragment>
+  <HelmetWrapper
+    defaultTitle="maintenance.page"
+    defer={true}
+    encodeSpecialCharacters={true}
+  />
   <div
-    className="page-simple"
-    id="nonav"
+    className="page-wrapper-simple"
+    id="bd"
   >
-    <React.Fragment>
-      <h1
-        className="maintenance-title"
-      >
-        maintenance.database_migration
-      </h1>
-      <p
-        className="maintenance-text text-center"
-      >
-        background_tasks.table.started
-         
-        <DateFromNow
-          date="2017-01-02T00:00:00.000Z"
-        />
-        <br />
-        <small
-          className="text-muted"
+    <div
+      className="page-simple"
+      id="nonav"
+    >
+      <React.Fragment>
+        <h1
+          className="maintenance-title"
+        >
+          maintenance.database_migration
+        </h1>
+        <p
+          className="maintenance-text text-center"
         >
-          <TimeFormatter
+          background_tasks.table.started
+           
+          <DateFromNow
             date="2017-01-02T00:00:00.000Z"
-            long={true}
           />
-        </small>
-      </p>
-      <p
-        className="maintenance-spinner"
-      >
-        <i
-          className="spinner"
-        />
-      </p>
-    </React.Fragment>
+          <br />
+          <small
+            className="text-muted"
+          >
+            <TimeFormatter
+              date="2017-01-02T00:00:00.000Z"
+              long={true}
+            />
+          </small>
+        </p>
+        <p
+          className="maintenance-spinner"
+        >
+          <i
+            className="spinner"
+          />
+        </p>
+      </React.Fragment>
+    </div>
   </div>
-</div>
+</React.Fragment>
 `;
index 8a5e326417635a66d2c6e9a6386ed0ae27fa72cd..c8f3db1dc4bb40988587cb928f9430ee2b07b1e5 100644 (file)
@@ -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