import { translate } from '../../helpers/l10n';
import { Extension } from '../types';
import { PluginPendingResult } from '../../api/plugins';
+import handleRequiredAuthorization from '../utils/handleRequiredAuthorization';
interface Props {
appState: {
componentDidMount() {
if (!this.context.canAdmin) {
- // workaround cyclic dependencies
- import('../utils/handleRequiredAuthorization').then(handleRequredAuthorization =>
- handleRequredAuthorization.default()
- );
+ handleRequiredAuthorization();
} else {
this.fetchNavigationSettings();
this.props.fetchEditions(this.props.editionsUrl, this.props.appState.version);
import webhooksRoutes from '../../apps/webhooks/routes';
import { maintenanceRoutes, setupRoutes } from '../../apps/maintenance/routes';
import { globalPermissionsRoutes, projectPermissionsRoutes } from '../../apps/permissions/routes';
+import { lazyLoad } from '../../components/lazyLoad';
function handleUpdate() {
const { action } = this.state.location;
<Route path="profiles" childRoutes={qualityProfilesRoutes} />
<Route path="web_api" childRoutes={webAPIRoutes} />
- <Route
- getComponent={() =>
- import('../components/ComponentContainer').then(i => i.default)
- }>
+ <Route component={lazyLoad(() => import('../components/ComponentContainer'))}>
<Route path="code" childRoutes={codeRoutes} />
<Route path="component_measures" childRoutes={componentMeasuresRoutes} />
<Route path="dashboard" childRoutes={overviewRoutes} />
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/AboutApp').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/AboutApp')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps, RouteComponent } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/Account').then(i => callback(null, i.default));
- },
+ component: lazyLoad(() => import('./components/Account')),
childRoutes: [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./profile/Profile').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./profile/Profile')) }
},
{
path: 'security',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/Security').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./components/Security'))
},
{
path: 'projects',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./projects/ProjectsContainer').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./projects/ProjectsContainer'))
},
{
path: 'notifications',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./notifications/Notifications').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./notifications/Notifications'))
},
{
path: 'organizations',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./organizations/UserOrganizations').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./organizations/UserOrganizations'))
}
]
}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/BackgroundTasksApp').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/BackgroundTasksApp')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/App').then(i => callback(null, { component: (i as any).default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/App')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, RouteComponent, RedirectFunction } from 'react-router';
+import { RouterState, RedirectFunction } from 'react-router';
import { parseQuery, serializeQuery } from './query';
+import { lazyLoad } from '../../components/lazyLoad';
import { RawQuery } from '../../helpers/query';
function parseHash(hash: string): RawQuery {
replace({ pathname: nextState.location.pathname, query: normalizedQuery });
}
},
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/App').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./components/App'))
}
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps, RedirectFunction } from 'react-router';
+import { RouterState, RedirectFunction } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/AppContainer').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/AppContainer')) }
},
{
path: 'domain/:domainName',
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, RouteComponent } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- indexRoute: {
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/App').then(i => callback(null, i.default));
- }
- }
+ indexRoute: { component: lazyLoad(() => import('./components/App')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/App').then(i => callback(null, { component: (i as any).default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/App')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/App').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/App')) }
}
];
import { Helmet } from 'react-helmet';
import Header from './Header';
import List from './List';
+import forSingleOrganization from '../../organizations/forSingleOrganization';
import Suggestions from '../../../app/components/embed-docs-modal/Suggestions';
import { searchUsersGroups, deleteGroup, updateGroup, createGroup } from '../../../api/user_groups';
import { Group, Paging } from '../../../app/types';
query: string;
}
-export default class App extends React.PureComponent<Props, State> {
- mounted = false;
- state: State = { loading: true, query: '' };
+export default forSingleOrganization(
+ class App extends React.PureComponent<Props, State> {
+ mounted = false;
+ state: State = { loading: true, query: '' };
- componentDidMount() {
- this.mounted = true;
- this.fetchGroups();
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
+ componentDidMount() {
+ this.mounted = true;
+ this.fetchGroups();
+ }
- get organization() {
- return this.props.organization && this.props.organization.key;
- }
+ componentWillUnmount() {
+ this.mounted = false;
+ }
- makeFetchGroupsRequest = (data?: { p?: number; q?: string }) => {
- this.setState({ loading: true });
- return searchUsersGroups({
- organization: this.organization,
- q: this.state.query,
- ...data
- });
- };
-
- stopLoading = () => {
- if (this.mounted) {
- this.setState({ loading: false });
+ get organization() {
+ return this.props.organization && this.props.organization.key;
}
- };
- fetchGroups = (data?: { p?: number; q?: string }) => {
- this.makeFetchGroupsRequest(data).then(({ groups, paging }) => {
+ makeFetchGroupsRequest = (data?: { p?: number; q?: string }) => {
+ this.setState({ loading: true });
+ return searchUsersGroups({
+ organization: this.organization,
+ q: this.state.query,
+ ...data
+ });
+ };
+
+ stopLoading = () => {
if (this.mounted) {
- this.setState({ groups, loading: false, paging });
+ this.setState({ loading: false });
}
- }, this.stopLoading);
- };
+ };
- fetchMoreGroups = () => {
- const { paging } = this.state;
- if (paging && paging.total > paging.pageIndex * paging.pageSize) {
- this.makeFetchGroupsRequest({ p: paging.pageIndex + 1 }).then(({ groups, paging }) => {
+ fetchGroups = (data?: { p?: number; q?: string }) => {
+ this.makeFetchGroupsRequest(data).then(({ groups, paging }) => {
if (this.mounted) {
- this.setState(({ groups: existingGroups = [] }) => ({
- groups: [...existingGroups, ...groups],
- loading: false,
- paging
- }));
+ this.setState({ groups, loading: false, paging });
}
}, this.stopLoading);
- }
- };
+ };
+
+ fetchMoreGroups = () => {
+ const { paging } = this.state;
+ if (paging && paging.total > paging.pageIndex * paging.pageSize) {
+ this.makeFetchGroupsRequest({ p: paging.pageIndex + 1 }).then(({ groups, paging }) => {
+ if (this.mounted) {
+ this.setState(({ groups: existingGroups = [] }) => ({
+ groups: [...existingGroups, ...groups],
+ loading: false,
+ paging
+ }));
+ }
+ }, this.stopLoading);
+ }
+ };
- search = (query: string) => {
- this.fetchGroups({ q: query });
- this.setState({ query });
- };
+ search = (query: string) => {
+ this.fetchGroups({ q: query });
+ this.setState({ query });
+ };
- refresh = () => {
- this.fetchGroups({ q: this.state.query });
- };
+ refresh = () => {
+ this.fetchGroups({ q: this.state.query });
+ };
- handleCreate = (data: { description: string; name: string }) => {
- return createGroup({ ...data, organization: this.organization }).then(group => {
- if (this.mounted) {
- this.setState(({ groups = [] }: State) => ({
- groups: [...groups, group]
- }));
- }
- });
- };
+ handleCreate = (data: { description: string; name: string }) => {
+ return createGroup({ ...data, organization: this.organization }).then(group => {
+ if (this.mounted) {
+ this.setState(({ groups = [] }: State) => ({
+ groups: [...groups, group]
+ }));
+ }
+ });
+ };
- handleDelete = (name: string) => {
- return deleteGroup({ name, organization: this.organization }).then(() => {
- if (this.mounted) {
- this.setState(({ groups = [] }: State) => ({
- groups: groups.filter(group => group.name !== name)
- }));
- }
- });
- };
+ handleDelete = (name: string) => {
+ return deleteGroup({ name, organization: this.organization }).then(() => {
+ if (this.mounted) {
+ this.setState(({ groups = [] }: State) => ({
+ groups: groups.filter(group => group.name !== name)
+ }));
+ }
+ });
+ };
- handleEdit = (data: { description?: string; id: number; name?: string }) => {
- return updateGroup(data).then(() => {
- if (this.mounted) {
- this.setState(({ groups = [] }: State) => ({
- groups: groups.map(group => (group.id === data.id ? { ...group, ...data } : group))
- }));
- }
- });
- };
-
- render() {
- const { groups, loading, paging, query } = this.state;
-
- const showAnyone =
- this.props.organization === undefined && 'anyone'.includes(query.toLowerCase());
-
- return (
- <>
- <Suggestions suggestions="user_groups" />
- <Helmet title={translate('user_groups.page')} />
- <div className="page page-limited" id="groups-page">
- <Header loading={loading} onCreate={this.handleCreate} />
-
- <SearchBox
- className="big-spacer-bottom"
- id="groups-search"
- minLength={2}
- onChange={this.search}
- placeholder={translate('search.search_by_name')}
- value={query}
- />
-
- {groups !== undefined && (
- <List
- groups={groups}
- onDelete={this.handleDelete}
- onEdit={this.handleEdit}
- onEditMembers={this.refresh}
- organization={this.organization}
- showAnyone={showAnyone}
+ handleEdit = (data: { description?: string; id: number; name?: string }) => {
+ return updateGroup(data).then(() => {
+ if (this.mounted) {
+ this.setState(({ groups = [] }: State) => ({
+ groups: groups.map(group => (group.id === data.id ? { ...group, ...data } : group))
+ }));
+ }
+ });
+ };
+
+ render() {
+ const { groups, loading, paging, query } = this.state;
+
+ const showAnyone =
+ this.props.organization === undefined && 'anyone'.includes(query.toLowerCase());
+
+ return (
+ <>
+ <Suggestions suggestions="user_groups" />
+ <Helmet title={translate('user_groups.page')} />
+ <div className="page page-limited" id="groups-page">
+ <Header loading={loading} onCreate={this.handleCreate} />
+
+ <SearchBox
+ className="big-spacer-bottom"
+ id="groups-search"
+ minLength={2}
+ onChange={this.search}
+ placeholder={translate('search.search_by_name')}
+ value={query}
/>
- )}
-
- {groups !== undefined &&
- paging !== undefined && (
- <div id="groups-list-footer">
- <ListFooter
- count={showAnyone ? groups.length + 1 : groups.length}
- loadMore={this.fetchMoreGroups}
- ready={!loading}
- total={showAnyone ? paging.total + 1 : paging.total}
- />
- </div>
+
+ {groups !== undefined && (
+ <List
+ groups={groups}
+ onDelete={this.handleDelete}
+ onEdit={this.handleEdit}
+ onEditMembers={this.refresh}
+ organization={this.organization}
+ showAnyone={showAnyone}
+ />
)}
- </div>
- </>
- );
+
+ {groups !== undefined &&
+ paging !== undefined && (
+ <div id="groups-list-footer">
+ <ListFooter
+ count={showAnyone ? groups.length + 1 : groups.length}
+ loadMore={this.fetchMoreGroups}
+ ready={!loading}
+ total={showAnyone ? paging.total + 1 : paging.total}
+ />
+ </div>
+ )}
+ </div>
+ </>
+ );
+ }
}
-}
+);
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- Promise.all([
- import('./components/App').then(i => i.default),
- import('../organizations/forSingleOrganization').then(i => i.default)
- ]).then(([App, forSingleOrganization]) =>
- callback(null, { component: forSingleOrganization(App) })
- );
- }
+ indexRoute: { component: lazyLoad(() => import('./components/App')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./AppContainer').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./AppContainer')) }
}
];
+++ /dev/null
-/*
- * 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.
- */
-// @flow
-import React from 'react';
-import { connect } from 'react-redux';
-import { withRouter } from 'react-router';
-import { areThereCustomOrganizations } from '../../store/rootReducer';
-
-const forSingleOrganization = (ComposedComponent /*: Object */) => {
- class X extends React.PureComponent {
- static displayName = `forSingleOrganization(${ComposedComponent.displayName})}`;
-
- render() {
- const { customOrganizations, router, ...other } = this.props;
-
- if (customOrganizations) {
- router.replace('/not_found');
- return null;
- }
-
- return <ComposedComponent {...other} />;
- }
- }
-
- const mapStateToProps = state => ({
- customOrganizations: areThereCustomOrganizations(state)
- });
-
- return connect(mapStateToProps)(withRouter(X));
-};
-
-export default forSingleOrganization;
--- /dev/null
+/*
+ * 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 { connect } from 'react-redux';
+import { withRouter, WithRouterProps } from 'react-router';
+import { areThereCustomOrganizations } from '../../store/rootReducer';
+
+type ReactComponent<P> = React.ComponentClass<P> | React.StatelessComponent<P>;
+
+export default function forSingleOrganization<P>(ComposedComponent: ReactComponent<P>) {
+ interface StateProps {
+ customOrganizations: boolean | undefined;
+ }
+
+ class ForSingleOrganization extends React.Component<StateProps & WithRouterProps> {
+ static displayName = `forSingleOrganization(${ComposedComponent.displayName})}`;
+
+ render() {
+ const { customOrganizations, router, ...other } = this.props;
+
+ if (!other.params.organizationKey && customOrganizations) {
+ router.replace('/not_found');
+ return null;
+ }
+
+ return <ComposedComponent {...other} />;
+ }
+ }
+
+ const mapStateToProps = (state: any) => ({
+ customOrganizations: areThereCustomOrganizations(state)
+ });
+
+ return connect(mapStateToProps)(withRouter(ForSingleOrganization));
+}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/App').then(i => callback(null, { component: (i as any).default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/App')) }
}
];
*/
import { connect } from 'react-redux';
import App from './App';
+import forSingleOrganization from '../../organizations/forSingleOrganization';
import { getAppState } from '../../../store/rootReducer';
import { getRootQualifiers } from '../../../store/appState/duck';
topQualifiers: getRootQualifiers(getAppState(state)).filter(q => q !== 'APP')
});
-export default connect(mapStateToProps)(App);
+export default forSingleOrganization(connect(mapStateToProps)(App));
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- Promise.all([
- import('./components/AppContainer').then(i => i.default),
- import('../organizations/forSingleOrganization').then(i => i.default)
- ]).then(([AppContainer, forSingleOrganization]) =>
- callback(null, { component: forSingleOrganization(AppContainer) })
- );
- }
+ indexRoute: { component: lazyLoad(() => import('./components/AppContainer')) }
}
];
import Suggestions from '../../../../app/components/embed-docs-modal/Suggestions';
import { translate } from '../../../../helpers/l10n';
import { Organization } from '../../../../app/types';
+import forSingleOrganization from '../../../organizations/forSingleOrganization';
import '../../styles.css';
interface Props {
organization?: Organization;
}
-export default function App({ organization }: Props) {
+function App({ organization }: Props) {
return (
<div className="page page-limited">
<Suggestions suggestions="global_permissions" />
</div>
);
}
+
+export default forSingleOrganization(App);
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
export const globalPermissionsRoutes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- Promise.all([
- import('./global/components/App').then(i => i.default),
- import('../organizations/forSingleOrganization').then(i => i.default)
- ]).then(([App, forSingleOrganization]) =>
- callback(null, { component: forSingleOrganization(App) })
- );
- }
+ indexRoute: { component: lazyLoad(() => import('./global/components/App')) }
}
];
export const projectPermissionsRoutes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./project/components/AppContainer').then(i =>
- callback(null, { component: i.default })
- );
- }
+ indexRoute: { component: lazyLoad(() => import('./project/components/AppContainer')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/App').then(i => callback(null, { component: (i as any).default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/App')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/ProjectActivityAppContainer').then(i =>
- callback(null, { component: (i as any).default })
- );
+ indexRoute: {
+ component: lazyLoad(() => import('./components/ProjectActivityAppContainer') as any)
}
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/AppContainer').then(i =>
- callback(null, { component: (i as any).default })
- );
- }
+ indexRoute: { component: lazyLoad(() => import('./components/AppContainer')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./App').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./App')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./App').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./App')) }
}
];
import * as React from 'react';
import { connect } from 'react-redux';
import App from './App';
-import { Organization } from '../../app/types';
+import forSingleOrganization from '../organizations/forSingleOrganization';
+import { Organization, LoggedInUser } from '../../app/types';
import { onFail } from '../../store/rootActions';
import { getAppState, getOrganizationByKey, getCurrentUser } from '../../store/rootReducer';
import { receiveOrganizations } from '../../store/organizations/duck';
import { changeProjectVisibility } from '../../api/organizations';
import { fetchOrganization } from '../../apps/organizations/actions';
-interface Props {
- appState: {
- defaultOrganization: string;
- qualifiers: string[];
- };
- currentUser: { login: string };
+interface StateProps {
+ appState: { defaultOrganization: string; qualifiers: string[] };
+ currentUser: LoggedInUser;
+ organization?: Organization;
+}
+
+interface DispatchProps {
fetchOrganization: (organization: string) => void;
onVisibilityChange: (organization: Organization, visibility: string) => void;
+}
+
+interface OwnProps {
onRequestFail: (error: any) => void;
- organization?: Organization;
}
-class AppContainer extends React.PureComponent<Props> {
+class AppContainer extends React.PureComponent<OwnProps & StateProps & DispatchProps> {
componentDidMount() {
// if there is no organization, that means we are in the global scope
// let's fetch defails for the default organization in this case
}
}
-const mapStateToProps = (state: any, ownProps: Props) => ({
+const mapStateToProps = (state: any, ownProps: any) => ({
appState: getAppState(state),
- currentUser: getCurrentUser(state),
+ currentUser: getCurrentUser(state) as LoggedInUser,
organization:
ownProps.organization || getOrganizationByKey(state, getAppState(state).defaultOrganization)
});
dispatch(onVisibilityChange(organization, visibility))
});
-export default connect<any, any, any>(mapStateToProps, mapDispatchToProps)(AppContainer);
+export default forSingleOrganization(
+ connect<StateProps, DispatchProps, OwnProps>(mapStateToProps, mapDispatchToProps)(AppContainer)
+);
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- Promise.all([
- import('./AppContainer').then(i => i.default),
- import('../organizations/forSingleOrganization').then(i => i.default)
- ]).then(([AppContainer, forSingleOrganization]) =>
- callback(null, { component: forSingleOrganization(AppContainer) })
- );
- }
+ indexRoute: { component: lazyLoad(() => import('./AppContainer')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps, RouteComponent } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/QualityGatesApp').then(i => callback(null, i.default));
- },
+ component: lazyLoad(() => import('./components/QualityGatesApp')),
childRoutes: [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/Intro').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/Intro')) }
},
{
path: 'show/:id',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/DetailsApp').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./components/DetailsApp'))
}
]
}
import { searchQualityProfiles, getExporters, Actions } from '../../../api/quality-profiles';
import Suggestions from '../../../app/components/embed-docs-modal/Suggestions';
import { sortProfiles } from '../utils';
-import { translate } from '../../../helpers/l10n';
+import { Exporter, Profile } from '../types';
import OrganizationHelmet from '../../../components/common/OrganizationHelmet';
+import { translate } from '../../../helpers/l10n';
+import { Languages } from '../../../store/languages/reducer';
import '../styles.css';
-import { Exporter, Profile } from '../types';
interface Props {
children: React.ReactElement<any>;
- languages: Array<{}>;
+ languages: Languages;
onRequestFail: (reasong: any) => void;
organization: { name: string; key: string } | null;
}
*/
import { connect } from 'react-redux';
import App from './App';
-import { getLanguages, getCurrentUser, getOrganizationByKey } from '../../../store/rootReducer';
+import forSingleOrganization from '../../organizations/forSingleOrganization';
+import { getLanguages, getOrganizationByKey } from '../../../store/rootReducer';
import { onFail } from '../../../store/rootActions';
+import { Languages } from '../../../store/languages/reducer';
+
+interface StateProps {
+ languages: Languages;
+ organization: { name: string; key: string } | null;
+}
+
+interface DispatchProps {
+ onRequestFail: (reasong: any) => void;
+}
const mapStateToProps = (state: any, ownProps: any) => ({
- currentUser: getCurrentUser(state),
languages: getLanguages(state),
organization: ownProps.params.organizationKey
? getOrganizationByKey(state, ownProps.params.organizationKey)
onRequestFail: (error: any) => onFail(dispatch)(error)
});
-export default connect(mapStateToProps, mapDispatchToProps)(App as any);
+export default forSingleOrganization(
+ connect<StateProps, DispatchProps>(mapStateToProps, mapDispatchToProps)(App)
+);
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps, RouteComponent, withRouter } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getComponent(state: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/AppContainer')
- .then(i => i.default)
- .then(AppContainer => {
- if (state.params.organizationKey) {
- callback(null, AppContainer);
- } else {
- import('../organizations/forSingleOrganization')
- .then(i => i.default)
- .then(forSingleOrganization => callback(null, forSingleOrganization(AppContainer)));
- }
- });
- },
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./home/HomeContainer').then(i => callback(null, { component: i.default }));
- },
+ component: lazyLoad(() => import('./components/AppContainer')),
+ indexRoute: { component: lazyLoad(() => import('./home/HomeContainer')) },
childRoutes: [
{
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/ProfileContainer').then(i => callback(null, withRouter(i.default)));
- },
+ component: lazyLoad(() => import('./components/ProfileContainer')),
childRoutes: [
{
path: 'show',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./details/ProfileDetails').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./details/ProfileDetails'))
},
{
path: 'changelog',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./changelog/ChangelogContainer').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./changelog/ChangelogContainer'))
},
{
path: 'compare',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./compare/ComparisonContainer').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./compare/ComparisonContainer'))
}
]
}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, RouteComponent } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
path: 'new',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/LoginContainer').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./components/LoginContainer'))
},
{
path: 'logout',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/Logout').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./components/Logout'))
},
{
path: 'unauthorized',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/Unauthorized').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./components/Unauthorized'))
},
{
path: 'email_already_exists',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/EmailAlreadyExists').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./components/EmailAlreadyExists'))
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, RouteComponent, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/AppContainer').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/AppContainer')) }
},
{
path: 'encryption',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./encryption/EncryptionAppContainer').then(i => callback(null, i.default));
- }
+ component: lazyLoad(() => import('./encryption/EncryptionAppContainer'))
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/App').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/App')) }
}
];
+++ /dev/null
-/*
- * 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.
- */
-// @flow
-import React from 'react';
-import Modal from '../../../components/controls/Modal';
-import { translate } from '../../../helpers/l10n';
-
-/*::
-type Props = {|
- onFinish: () => void
-|};
-*/
-
-/*::
-type State = {
- OnboardingContainer?: Object
-};
-*/
-
-export default class OnboardingModal extends React.PureComponent {
- /*:: mounted: boolean; */
- /*:: props: Props; */
- state /*: State */ = {};
-
- componentDidMount() {
- this.mounted = true;
- import('./OnboardingContainer').then(i => this.receiveComponent(i.default));
- }
-
- componentWillUnmount() {
- this.mounted = false;
- }
-
- receiveComponent = (OnboardingContainer /*: Object */) => {
- if (this.mounted) {
- this.setState({ OnboardingContainer });
- }
- };
-
- render() {
- const { OnboardingContainer } = this.state;
-
- return (
- <Modal contentLabel={translate('tutorials.onboarding')} large={true}>
- {OnboardingContainer != null && <OnboardingContainer onFinish={this.props.onFinish} />}
- </Modal>
- );
- }
-}
--- /dev/null
+/*
+ * 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 Modal from '../../../components/controls/Modal';
+import { translate } from '../../../helpers/l10n';
+import { lazyLoad } from '../../../components/lazyLoad';
+
+interface Props {
+ onFinish: () => void;
+}
+
+const OnboardingContainer = lazyLoad(() => import('./OnboardingContainer'));
+
+export default function OnboardingModal({ onFinish }: Props) {
+ return (
+ <Modal contentLabel={translate('tutorials.onboarding')} large={true}>
+ <OnboardingContainer onFinish={onFinish} />
+ </Modal>
+ );
+}
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./UsersAppContainer').then(i => callback(null, { component: i.default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./UsersAppContainer')) }
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, RouteComponent, IndexRouteProps } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- getIndexRoute(_: RouterState, callback: (err: any, route: IndexRouteProps) => any) {
- import('./components/WebApiApp').then(i => callback(null, { component: (i as any).default }));
- }
+ indexRoute: { component: lazyLoad(() => import('./components/WebApiApp')) }
},
{
path: '**',
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/WebApiApp').then(i => callback(null, (i as any).default));
- }
+ component: lazyLoad(() => import('./components/WebApiApp'))
}
];
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
-import { RouterState, RouteComponent } from 'react-router';
+import { lazyLoad } from '../../components/lazyLoad';
const routes = [
{
- indexRoute: {
- getComponent(_: RouterState, callback: (err: any, component: RouteComponent) => any) {
- import('./components/App').then(i => callback(null, i.default));
- }
- }
+ indexRoute: { component: lazyLoad(() => import('./components/App')) }
}
];
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
import * as React from 'react';
+import { translate } from '../helpers/l10n';
+import { get, save } from '../helpers/storage';
type ReactComponent<P> = React.ComponentClass<P> | React.StatelessComponent<P>;
(): Promise<{ default: ReactComponent<P> }>;
}
+export const LAST_FAILED_CHUNK_STORAGE_KEY = 'sonarqube.last_failed_chunk';
+
export function lazyLoad<P>(loader: Loader<P>) {
+ interface ImportError {
+ request?: string;
+ }
+
interface State {
Component?: ReactComponent<P>;
+ error?: ImportError;
}
// use `React.Component`, not `React.PureComponent` to always re-render
componentDidMount() {
this.mounted = true;
- loader().then(i => this.receiveComponent(i.default), () => {});
+ loader().then(i => this.receiveComponent(i.default), this.failToReceiveComponent);
}
componentWillUnmount() {
receiveComponent = (Component: ReactComponent<P>) => {
if (this.mounted) {
- this.setState({ Component });
+ this.setState({ Component, error: undefined });
+ }
+ };
+
+ failToReceiveComponent = (error?: ImportError) => {
+ const lastFailedChunk = get(LAST_FAILED_CHUNK_STORAGE_KEY);
+ if (error && error.request === lastFailedChunk) {
+ // BOOM!
+ // this is the second time we try to load the same file
+ // usually that means the file does not exist on the server
+ // so we should not try to reload the page to not fall into infinite reloading
+ // just show the error message
+ if (this.mounted) {
+ this.setState({ Component: undefined, error });
+ }
+ } else {
+ if (error && error.request) {
+ save(LAST_FAILED_CHUNK_STORAGE_KEY, error.request);
+ }
+ window.location.reload();
}
};
render() {
- const { Component } = this.state;
+ const { Component, error } = this.state;
+
+ if (error && error.request) {
+ return <div className="alert alert-danger">{translate('default_error_message')}</div>;
+ }
if (!Component) {
return null;