aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilippe Perrin <philippe.perrin@sonarsource.com>2022-07-19 10:46:34 +0200
committersonartech <sonartech@sonarsource.com>2022-07-21 20:03:05 +0000
commit35ee1a94e9adcb757b656478523edd2df315f05f (patch)
tree3b2f16e9172b2e41a9628e4146a85bd45a0a4c0c
parent54df07c9f9c1e586c2931d2ca10e7759fc1ec61b (diff)
downloadsonarqube-35ee1a94e9adcb757b656478523edd2df315f05f.tar.gz
sonarqube-35ee1a94e9adcb757b656478523edd2df315f05f.zip
[NO-JIRA] Simplify application initialization
-rw-r--r--server/sonar-web/src/main/js/api/navigation.ts (renamed from server/sonar-web/src/main/js/api/nav.ts)5
-rw-r--r--server/sonar-web/src/main/js/api/users.ts2
-rw-r--r--server/sonar-web/src/main/js/app/components/AdminContainer.tsx2
-rw-r--r--server/sonar-web/src/main/js/app/components/ComponentContainer.tsx2
-rw-r--r--server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx4
-rw-r--r--server/sonar-web/src/main/js/app/components/app-state/AppStateContext.tsx4
-rw-r--r--server/sonar-web/src/main/js/app/index.ts116
-rw-r--r--server/sonar-web/src/main/js/app/utils/startReactApp.tsx9
-rw-r--r--server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/ApplicationCreation.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/projects/components/__tests__/ApplicationCreation-test.tsx4
-rw-r--r--server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx2
-rw-r--r--server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRowActions-test.tsx4
14 files changed, 41 insertions, 119 deletions
diff --git a/server/sonar-web/src/main/js/api/nav.ts b/server/sonar-web/src/main/js/api/navigation.ts
index bca04cabf98..69111204f41 100644
--- a/server/sonar-web/src/main/js/api/nav.ts
+++ b/server/sonar-web/src/main/js/api/navigation.ts
@@ -19,6 +19,7 @@
*/
import { throwGlobalError } from '../helpers/error';
import { getJSON } from '../helpers/request';
+import { AppState } from '../types/appstate';
import { BranchParameters } from '../types/branch-like';
import { Component, Extension } from '../types/types';
@@ -40,3 +41,7 @@ export function getSettingsNavigation(): Promise<{
}> {
return getJSON('/api/navigation/settings').catch(throwGlobalError);
}
+
+export function getGlobalNavigation(): Promise<AppState> {
+ return getJSON('/api/navigation/global', undefined, true);
+}
diff --git a/server/sonar-web/src/main/js/api/users.ts b/server/sonar-web/src/main/js/api/users.ts
index e512718770e..dae13297e64 100644
--- a/server/sonar-web/src/main/js/api/users.ts
+++ b/server/sonar-web/src/main/js/api/users.ts
@@ -23,7 +23,7 @@ import { IdentityProvider, Paging } from '../types/types';
import { CurrentUser, HomePage, NoticeType, User } from '../types/users';
export function getCurrentUser(): Promise<CurrentUser> {
- return getJSON('/api/users/current');
+ return getJSON('/api/users/current', undefined, true);
}
export function dismissNotification(notice: NoticeType) {
diff --git a/server/sonar-web/src/main/js/app/components/AdminContainer.tsx b/server/sonar-web/src/main/js/app/components/AdminContainer.tsx
index de4a84124e4..0b5bcc72ab9 100644
--- a/server/sonar-web/src/main/js/app/components/AdminContainer.tsx
+++ b/server/sonar-web/src/main/js/app/components/AdminContainer.tsx
@@ -20,7 +20,7 @@
import * as React from 'react';
import { Helmet } from 'react-helmet-async';
import { Outlet } from 'react-router-dom';
-import { getSettingsNavigation } from '../../api/nav';
+import { getSettingsNavigation } from '../../api/navigation';
import { getPendingPlugins } from '../../api/plugins';
import { getSystemStatus, waitSystemUPStatus } from '../../api/system';
import handleRequiredAuthorization from '../../app/utils/handleRequiredAuthorization';
diff --git a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
index 4d6d2f3fac0..2220ec14d6c 100644
--- a/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
+++ b/server/sonar-web/src/main/js/app/components/ComponentContainer.tsx
@@ -24,7 +24,7 @@ import { getProjectAlmBinding, validateProjectAlmBinding } from '../../api/alm-s
import { getBranches, getPullRequests } from '../../api/branches';
import { getAnalysisStatus, getTasksForComponent } from '../../api/ce';
import { getComponentData } from '../../api/components';
-import { getComponentNavigation } from '../../api/nav';
+import { getComponentNavigation } from '../../api/navigation';
import { Location, Router, withRouter } from '../../components/hoc/withRouter';
import {
getBranchLikeQuery,
diff --git a/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx b/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx
index 88f82cbab52..e7822a0a90c 100644
--- a/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx
+++ b/server/sonar-web/src/main/js/app/components/__tests__/ComponentContainer-test.tsx
@@ -23,7 +23,7 @@ import { getProjectAlmBinding, validateProjectAlmBinding } from '../../../api/al
import { getBranches, getPullRequests } from '../../../api/branches';
import { getAnalysisStatus, getTasksForComponent } from '../../../api/ce';
import { getComponentData } from '../../../api/components';
-import { getComponentNavigation } from '../../../api/nav';
+import { getComponentNavigation } from '../../../api/navigation';
import { mockProjectAlmBindingConfigurationErrors } from '../../../helpers/mocks/alm-settings';
import { mockBranch, mockMainBranch, mockPullRequest } from '../../../helpers/mocks/branch-like';
import { mockComponent } from '../../../helpers/mocks/component';
@@ -65,7 +65,7 @@ jest.mock('../../../api/components', () => ({
getComponentData: jest.fn().mockResolvedValue({ component: { analysisDate: '2018-07-30' } })
}));
-jest.mock('../../../api/nav', () => ({
+jest.mock('../../../api/navigation', () => ({
getComponentNavigation: jest.fn().mockResolvedValue({
breadcrumbs: [{ key: 'portfolioKey', name: 'portfolio', qualifier: 'VW' }],
key: 'portfolioKey'
diff --git a/server/sonar-web/src/main/js/app/components/app-state/AppStateContext.tsx b/server/sonar-web/src/main/js/app/components/app-state/AppStateContext.tsx
index a8e130c84d2..d327bfb3aa1 100644
--- a/server/sonar-web/src/main/js/app/components/app-state/AppStateContext.tsx
+++ b/server/sonar-web/src/main/js/app/components/app-state/AppStateContext.tsx
@@ -21,7 +21,7 @@
import * as React from 'react';
import { AppState } from '../../../types/appstate';
-const defaultAppState = {
+export const DEFAULT_APP_STATE = {
authenticationError: false,
authorizationError: false,
edition: undefined,
@@ -30,4 +30,4 @@ const defaultAppState = {
settings: {},
version: ''
};
-export const AppStateContext = React.createContext<AppState>(defaultAppState);
+export const AppStateContext = React.createContext<AppState>(DEFAULT_APP_STATE);
diff --git a/server/sonar-web/src/main/js/app/index.ts b/server/sonar-web/src/main/js/app/index.ts
index a665c02f376..86c72242783 100644
--- a/server/sonar-web/src/main/js/app/index.ts
+++ b/server/sonar-web/src/main/js/app/index.ts
@@ -17,118 +17,30 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+import { getGlobalNavigation } from '../api/navigation';
+import { getCurrentUser } from '../api/users';
import { installExtensionsHandler, installWebAnalyticsHandler } from '../helpers/extensionsHandler';
import { loadL10nBundle } from '../helpers/l10nBundle';
-import { HttpStatus, parseJSON, request } from '../helpers/request';
import { getBaseUrl, getSystemStatus } from '../helpers/system';
-import { AppState } from '../types/appstate';
-import { L10nBundle } from '../types/l10nBundle';
-import { CurrentUser } from '../types/users';
import './styles/sonar.ts';
installWebAnalyticsHandler();
+installExtensionsHandler();
+initApplication();
-if (isMainApp()) {
- installExtensionsHandler();
-
- loadAll(loadAppState, loadUser).then(
- ([l10nBundle, user, appState, startReactApp]) => {
- startReactApp(l10nBundle.locale, appState, user);
- },
- error => {
- if (isResponse(error) && error.status === HttpStatus.Unauthorized) {
- redirectToLogin();
- } else {
- logError(error);
- }
- }
- );
-} else {
- // login, maintenance or setup pages
-
- const appStateLoader = () =>
- loadAppState().catch(() => {
- return {
- edition: undefined,
- productionDatabase: true,
- qualifiers: [],
- settings: {},
- version: ''
- };
- });
-
- loadAll(appStateLoader).then(
- ([l10nBundle, _user, appState, startReactApp]) => {
- startReactApp(l10nBundle.locale, appState);
- },
- error => {
- logError(error);
- }
- );
-}
-
-async function loadAll(
- appStateLoader: () => Promise<AppState>,
- userLoader?: () => Promise<CurrentUser | undefined>
-): Promise<
- [
- Required<L10nBundle>,
- CurrentUser | undefined,
- AppState,
- (lang: string, appState: AppState, currentUser?: CurrentUser) => void
- ]
-> {
- const [l10nBundle, user, appState] = await Promise.all([
+async function initApplication() {
+ const [l10nBundle, currentUser, appState] = await Promise.all([
loadL10nBundle(),
- userLoader ? userLoader() : undefined,
- appStateLoader()
- ]);
-
- const startReactApp = await loadApp();
-
- return [l10nBundle, user, appState, startReactApp];
-}
-
-function loadUser() {
- return request('/api/users/current')
- .submit()
- .then(checkStatus)
- .then(parseJSON);
-}
-
-function loadAppState() {
- return request('/api/navigation/global')
- .submit()
- .then(checkStatus)
- .then(parseJSON);
-}
-
-function loadApp() {
- return import(/* webpackChunkName: 'app' */ './utils/startReactApp').then(i => i.default);
-}
-
-function checkStatus(response: Response) {
- return new Promise((resolve, reject) => {
- if (response.status >= 200 && response.status < 300) {
- resolve(response);
- } else {
- reject(response);
- }
+ isMainApp() ? getCurrentUser() : undefined,
+ isMainApp() ? getGlobalNavigation() : undefined
+ ]).catch(error => {
+ // eslint-disable-next-line no-console
+ console.error('Application failed to start', error);
+ throw error;
});
-}
-
-function isResponse(error: any): error is Response {
- return typeof error.status === 'number';
-}
-
-function redirectToLogin() {
- const returnTo = window.location.pathname + window.location.search + window.location.hash;
- window.location.href = `${getBaseUrl()}/sessions/new?return_to=${encodeURIComponent(returnTo)}`;
-}
-function logError(error: any) {
- // eslint-disable-next-line no-console
- console.error('Application failed to start!', error);
+ const startReactApp = await import('./utils/startReactApp').then(i => i.default);
+ startReactApp(l10nBundle.locale, currentUser, appState);
}
function isMainApp() {
diff --git a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx
index b5387cfa9ec..3bd41cee3be 100644
--- a/server/sonar-web/src/main/js/app/utils/startReactApp.tsx
+++ b/server/sonar-web/src/main/js/app/utils/startReactApp.tsx
@@ -64,6 +64,7 @@ import { AppState } from '../../types/appstate';
import { CurrentUser } from '../../types/users';
import AdminContainer from '../components/AdminContainer';
import App from '../components/App';
+import { DEFAULT_APP_STATE } from '../components/app-state/AppStateContext';
import AppStateContextProvider from '../components/app-state/AppStateContextProvider';
import ComponentContainer from '../components/ComponentContainer';
import CurrentUserContextProvider from '../components/current-user/CurrentUserContextProvider';
@@ -223,14 +224,18 @@ function renderAdminRoutes() {
);
}
-export default function startReactApp(lang: string, appState: AppState, currentUser?: CurrentUser) {
+export default function startReactApp(
+ lang: string,
+ currentUser?: CurrentUser,
+ appState?: AppState
+) {
exportModulesAsGlobals();
const el = document.getElementById('content');
render(
<HelmetProvider>
- <AppStateContextProvider appState={appState}>
+ <AppStateContextProvider appState={appState ?? DEFAULT_APP_STATE}>
<CurrentUserContextProvider currentUser={currentUser}>
<IntlProvider defaultLocale={lang} locale={lang}>
<GlobalMessagesContainer />
diff --git a/server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx b/server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx
index 6270c9faecb..f4c18553a1e 100644
--- a/server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx
+++ b/server/sonar-web/src/main/js/apps/marketplace/EditionBoxes.tsx
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { getMarketplaceNavigation } from '../../api/nav';
+import { getMarketplaceNavigation } from '../../api/navigation';
import { getAllEditionsAbove } from '../../helpers/editions';
import { EditionKey } from '../../types/editions';
import EditionBox from './components/EditionBox';
diff --git a/server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx b/server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx
index 7bc48dbcaa8..b1568cb8b73 100644
--- a/server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx
+++ b/server/sonar-web/src/main/js/apps/marketplace/__tests__/EditionBoxes-test.tsx
@@ -22,7 +22,7 @@ import * as React from 'react';
import { EditionKey } from '../../../types/editions';
import EditionBoxes from '../EditionBoxes';
-jest.mock('../../../api/nav', () => ({
+jest.mock('../../../api/navigation', () => ({
getMarketplaceNavigation: jest.fn().mockResolvedValue({})
}));
diff --git a/server/sonar-web/src/main/js/apps/projects/components/ApplicationCreation.tsx b/server/sonar-web/src/main/js/apps/projects/components/ApplicationCreation.tsx
index f58be34596e..11bf1c33434 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/ApplicationCreation.tsx
+++ b/server/sonar-web/src/main/js/apps/projects/components/ApplicationCreation.tsx
@@ -18,7 +18,7 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
-import { getComponentNavigation } from '../../../api/nav';
+import { getComponentNavigation } from '../../../api/navigation';
import withAppStateContext from '../../../app/components/app-state/withAppStateContext';
import withCurrentUserContext from '../../../app/components/current-user/withCurrentUserContext';
import CreateApplicationForm from '../../../app/components/extensions/CreateApplicationForm';
diff --git a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ApplicationCreation-test.tsx b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ApplicationCreation-test.tsx
index ecdfa1b29fe..163991f0357 100644
--- a/server/sonar-web/src/main/js/apps/projects/components/__tests__/ApplicationCreation-test.tsx
+++ b/server/sonar-web/src/main/js/apps/projects/components/__tests__/ApplicationCreation-test.tsx
@@ -19,7 +19,7 @@
*/
import { shallow, ShallowWrapper } from 'enzyme';
import * as React from 'react';
-import { getComponentNavigation } from '../../../../api/nav';
+import { getComponentNavigation } from '../../../../api/navigation';
import CreateApplicationForm from '../../../../app/components/extensions/CreateApplicationForm';
import { Button } from '../../../../components/controls/buttons';
import { mockAppState, mockLoggedInUser, mockRouter } from '../../../../helpers/testMocks';
@@ -27,7 +27,7 @@ import { queryToSearch } from '../../../../helpers/urls';
import { ComponentQualifier } from '../../../../types/component';
import { ApplicationCreation, ApplicationCreationProps } from '../ApplicationCreation';
-jest.mock('../../../../api/nav', () => ({
+jest.mock('../../../../api/navigation', () => ({
getComponentNavigation: jest.fn().mockResolvedValue({})
}));
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx
index 6a592edf6d9..64f0274f234 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/ProjectRowActions.tsx
@@ -19,7 +19,7 @@
*/
import * as React from 'react';
import { Project } from '../../api/components';
-import { getComponentNavigation } from '../../api/nav';
+import { getComponentNavigation } from '../../api/navigation';
import ActionsDropdown, { ActionsDropdownItem } from '../../components/controls/ActionsDropdown';
import DeferredSpinner from '../../components/ui/DeferredSpinner';
import { translate } from '../../helpers/l10n';
diff --git a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRowActions-test.tsx b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRowActions-test.tsx
index 95182dc9f18..8a8b3f2e706 100644
--- a/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRowActions-test.tsx
+++ b/server/sonar-web/src/main/js/apps/projectsManagement/__tests__/ProjectRowActions-test.tsx
@@ -19,12 +19,12 @@
*/
import { shallow } from 'enzyme';
import * as React from 'react';
-import { getComponentNavigation } from '../../../api/nav';
+import { getComponentNavigation } from '../../../api/navigation';
import { mockLoggedInUser } from '../../../helpers/testMocks';
import { click, waitAndUpdate } from '../../../helpers/testUtils';
import ProjectRowActions, { Props } from '../ProjectRowActions';
-jest.mock('../../../api/nav', () => ({
+jest.mock('../../../api/navigation', () => ({
getComponentNavigation: jest.fn().mockResolvedValue({})
}));