mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-15 01:16:22 +02:00
Refactor/lazy load (#2842)
Currently our bundle size is clocking in at: 1,798.28 kB │ gzip: 558.42 kB After the changes: 1,299.32 kB │ gzip: 403.26 kB
This commit is contained in:
parent
ce815e5f29
commit
0dcf28a0f0
@ -66,3 +66,7 @@ Whenever there are changes to the backend API, the client should be regenerated:
|
|||||||
This script assumes that you have a running instance of the enterprise backend at `http://localhost:4242`.
|
This script assumes that you have a running instance of the enterprise backend at `http://localhost:4242`.
|
||||||
The new OpenAPI client will be generated from the runtime schema of this instance.
|
The new OpenAPI client will be generated from the runtime schema of this instance.
|
||||||
The target URL can be changed by setting the `UNLEASH_OPENAPI_URL` env var.
|
The target URL can be changed by setting the `UNLEASH_OPENAPI_URL` env var.
|
||||||
|
|
||||||
|
## Analyzing bundle size
|
||||||
|
|
||||||
|
`npx vite-bundle-visualizer` in the root of the frontend directory
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
"start": "vite",
|
"start": "vite",
|
||||||
"start:prod": "vite build && vite preview",
|
"start:prod": "vite build && vite preview",
|
||||||
"start:sandbox": "UNLEASH_API=https://sandbox.getunleash.io/ospro yarn run start",
|
"start:sandbox": "UNLEASH_API=https://sandbox.getunleash.io/ospro yarn run start",
|
||||||
"start:enterprise": "UNLEASH_API=https://unleash4.herokuapp.com yarn run start",
|
"start:enterprise": "UNLEASH_API=https://unleash.herokuapp.com yarn run start",
|
||||||
"start:demo": "UNLEASH_BASE_PATH=/demo/ yarn start",
|
"start:demo": "UNLEASH_BASE_PATH=/demo/ yarn start",
|
||||||
"test": "tsc && vitest run",
|
"test": "tsc && vitest run",
|
||||||
"test:snapshot": "yarn test -u",
|
"test:snapshot": "yarn test -u",
|
||||||
|
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 113 KiB |
52
frontend/src/component/admin/Admin.tsx
Normal file
52
frontend/src/component/admin/Admin.tsx
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
import { Routes, Route } from 'react-router-dom';
|
||||||
|
import { ApiPage } from './api';
|
||||||
|
import { CreateApiToken } from './apiToken/CreateApiToken/CreateApiToken';
|
||||||
|
import { AuthSettings } from './auth/AuthSettings';
|
||||||
|
import { Billing } from './billing/Billing';
|
||||||
|
import FlaggedBillingRedirect from './billing/FlaggedBillingRedirect/FlaggedBillingRedirect';
|
||||||
|
import { CorsAdmin } from './cors';
|
||||||
|
import { CreateGroup } from './groups/CreateGroup/CreateGroup';
|
||||||
|
import { EditGroup } from './groups/EditGroup/EditGroup';
|
||||||
|
import { Group } from './groups/Group/Group';
|
||||||
|
import { GroupsAdmin } from './groups/GroupsAdmin';
|
||||||
|
import { InstanceAdmin } from './instance-admin/InstanceAdmin';
|
||||||
|
import { MaintenanceAdmin } from './maintenance';
|
||||||
|
import AdminMenu from './menu/AdminMenu';
|
||||||
|
import { Network } from './network/Network';
|
||||||
|
import CreateProjectRole from './projectRoles/CreateProjectRole/CreateProjectRole';
|
||||||
|
import EditProjectRole from './projectRoles/EditProjectRole/EditProjectRole';
|
||||||
|
import ProjectRoles from './projectRoles/ProjectRoles/ProjectRoles';
|
||||||
|
import { ServiceAccounts } from './serviceAccounts/ServiceAccounts';
|
||||||
|
import CreateUser from './users/CreateUser/CreateUser';
|
||||||
|
import EditUser from './users/EditUser/EditUser';
|
||||||
|
import { InviteLink } from './users/InviteLink/InviteLink';
|
||||||
|
import UsersAdmin from './users/UsersAdmin';
|
||||||
|
|
||||||
|
export const Admin = () => (
|
||||||
|
<>
|
||||||
|
<AdminMenu />
|
||||||
|
<Routes>
|
||||||
|
<Route path="users" element={<UsersAdmin />} />
|
||||||
|
<Route path="create-project-role" element={<CreateProjectRole />} />
|
||||||
|
<Route path="roles/:id/edit" element={<EditProjectRole />} />
|
||||||
|
<Route path="api" element={<ApiPage />} />
|
||||||
|
<Route path="api/create-token" element={<CreateApiToken />} />
|
||||||
|
<Route path="users/:id/edit" element={<EditUser />} />
|
||||||
|
<Route path="service-accounts" element={<ServiceAccounts />} />
|
||||||
|
<Route path="create-user" element={<CreateUser />} />
|
||||||
|
<Route path="invite-link" element={<InviteLink />} />
|
||||||
|
<Route path="groups" element={<GroupsAdmin />} />
|
||||||
|
<Route path="groups/create-group" element={<CreateGroup />} />
|
||||||
|
<Route path="groups/:groupId/edit" element={<EditGroup />} />
|
||||||
|
<Route path="groups/:groupId" element={<Group />} />
|
||||||
|
<Route path="roles" element={<ProjectRoles />} />
|
||||||
|
<Route path="instance" element={<InstanceAdmin />} />
|
||||||
|
<Route path="network/*" element={<Network />} />
|
||||||
|
<Route path="maintenance" element={<MaintenanceAdmin />} />
|
||||||
|
<Route path="cors" element={<CorsAdmin />} />
|
||||||
|
<Route path="auth" element={<AuthSettings />} />
|
||||||
|
<Route path="admin-invoices" element={<FlaggedBillingRedirect />} />
|
||||||
|
<Route path="billing" element={<Billing />} />
|
||||||
|
</Routes>
|
||||||
|
</>
|
||||||
|
);
|
3
frontend/src/component/admin/AdminRedirect.tsx
Normal file
3
frontend/src/component/admin/AdminRedirect.tsx
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { Navigate } from 'react-router-dom';
|
||||||
|
|
||||||
|
export const AdminRedirect = () => <Navigate to="/admin/users" replace />;
|
3
frontend/src/component/admin/LazyAdmin.tsx
Normal file
3
frontend/src/component/admin/LazyAdmin.tsx
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { lazy } from 'react';
|
||||||
|
|
||||||
|
export const LazyAdmin = lazy(() => import('./LazyAdminExport'));
|
7
frontend/src/component/admin/LazyAdminExport.tsx
Normal file
7
frontend/src/component/admin/LazyAdminExport.tsx
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
// Lazy loading only supports default export. We have an ADR
|
||||||
|
// that says we should only use named exports, because
|
||||||
|
// it makes it harder to diverge from the name of the component when
|
||||||
|
// importing it in other files.
|
||||||
|
import { Admin } from './Admin';
|
||||||
|
|
||||||
|
export default Admin;
|
@ -1,18 +1,8 @@
|
|||||||
import { useLocation } from 'react-router-dom';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
|
||||||
import { ApiTokenPage } from 'component/admin/apiToken/ApiTokenPage/ApiTokenPage';
|
import { ApiTokenPage } from 'component/admin/apiToken/ApiTokenPage/ApiTokenPage';
|
||||||
import AdminMenu from '../menu/AdminMenu';
|
|
||||||
|
|
||||||
const ApiPage = () => {
|
|
||||||
const { pathname } = useLocation();
|
|
||||||
const showAdminMenu = pathname.includes('/admin/');
|
|
||||||
|
|
||||||
|
export const ApiPage = () => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ConditionallyRender
|
|
||||||
condition={showAdminMenu}
|
|
||||||
show={<AdminMenu />}
|
|
||||||
/>
|
|
||||||
<ApiTokenPage />
|
<ApiTokenPage />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import AdminMenu from '../menu/AdminMenu';
|
|
||||||
import { Alert } from '@mui/material';
|
import { Alert } from '@mui/material';
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
@ -34,7 +33,6 @@ export const AuthSettings = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AdminMenu />
|
|
||||||
<PageContent header="Single Sign-On">
|
<PageContent header="Single Sign-On">
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={authenticationType === 'enterprise'}
|
condition={authenticationType === 'enterprise'}
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import AdminMenu from '../menu/AdminMenu';
|
|
||||||
import { PageContent } from 'component/common/PageContent/PageContent';
|
import { PageContent } from 'component/common/PageContent/PageContent';
|
||||||
import { useContext, useEffect } from 'react';
|
import { useContext, useEffect } from 'react';
|
||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||||
@ -32,7 +31,6 @@ export const Billing = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AdminMenu />
|
|
||||||
<PageContent header="Billing" isLoading={loading}>
|
<PageContent header="Billing" isLoading={loading}>
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={isBilling}
|
condition={isBilling}
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import { useLocation } from 'react-router-dom';
|
import { useLocation } from 'react-router-dom';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import AdminMenu from '../menu/AdminMenu';
|
|
||||||
import { AdminAlert } from 'component/common/AdminAlert/AdminAlert';
|
import { AdminAlert } from 'component/common/AdminAlert/AdminAlert';
|
||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||||
import AccessContext from 'contexts/AccessContext';
|
import AccessContext from 'contexts/AccessContext';
|
||||||
@ -13,16 +12,10 @@ import { CorsForm } from 'component/admin/cors/CorsForm';
|
|||||||
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
import useUiConfig from 'hooks/api/getters/useUiConfig/useUiConfig';
|
||||||
|
|
||||||
export const CorsAdmin = () => {
|
export const CorsAdmin = () => {
|
||||||
const { pathname } = useLocation();
|
|
||||||
const showAdminMenu = pathname.includes('/admin/');
|
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ConditionallyRender
|
|
||||||
condition={showAdminMenu}
|
|
||||||
show={<AdminMenu />}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={hasAccess(ADMIN)}
|
condition={hasAccess(ADMIN)}
|
||||||
show={<CorsPage />}
|
show={<CorsPage />}
|
||||||
|
@ -1,10 +1,8 @@
|
|||||||
import { GroupsList } from './GroupsList/GroupsList';
|
import { GroupsList } from './GroupsList/GroupsList';
|
||||||
import AdminMenu from '../menu/AdminMenu';
|
|
||||||
|
|
||||||
export const GroupsAdmin = () => {
|
export const GroupsAdmin = () => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AdminMenu />
|
|
||||||
<GroupsList />
|
<GroupsList />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,12 +0,0 @@
|
|||||||
import React from 'react';
|
|
||||||
import PropTypes from 'prop-types';
|
|
||||||
import { Navigate } from 'react-router-dom';
|
|
||||||
|
|
||||||
const render = () => <Navigate to="/admin/users" replace />;
|
|
||||||
|
|
||||||
render.propTypes = {
|
|
||||||
match: PropTypes.object.isRequired,
|
|
||||||
history: PropTypes.object.isRequired,
|
|
||||||
};
|
|
||||||
|
|
||||||
export default render;
|
|
@ -1,10 +1,8 @@
|
|||||||
import AdminMenu from '../menu/AdminMenu';
|
|
||||||
import { InstanceStats } from './InstanceStats/InstanceStats';
|
import { InstanceStats } from './InstanceStats/InstanceStats';
|
||||||
|
|
||||||
export const InstanceAdmin = () => {
|
export const InstanceAdmin = () => {
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AdminMenu />
|
|
||||||
<InstanceStats />
|
<InstanceStats />
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,4 @@
|
|||||||
import { useLocation } from 'react-router-dom';
|
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import AdminMenu from '../menu/AdminMenu';
|
|
||||||
import { AdminAlert } from 'component/common/AdminAlert/AdminAlert';
|
import { AdminAlert } from 'component/common/AdminAlert/AdminAlert';
|
||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||||
import AccessContext from 'contexts/AccessContext';
|
import AccessContext from 'contexts/AccessContext';
|
||||||
@ -13,16 +11,10 @@ import { MaintenanceTooltip } from './MaintenanceTooltip';
|
|||||||
import { MaintenanceToggle } from './MaintenanceToggle';
|
import { MaintenanceToggle } from './MaintenanceToggle';
|
||||||
|
|
||||||
export const MaintenanceAdmin = () => {
|
export const MaintenanceAdmin = () => {
|
||||||
const { pathname } = useLocation();
|
|
||||||
const showAdminMenu = pathname.includes('/admin/');
|
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<ConditionallyRender
|
|
||||||
condition={showAdminMenu}
|
|
||||||
show={<AdminMenu />}
|
|
||||||
/>
|
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={hasAccess(ADMIN)}
|
condition={hasAccess(ADMIN)}
|
||||||
show={<MaintenancePage />}
|
show={<MaintenancePage />}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
import { lazy } from 'react';
|
import { lazy } from 'react';
|
||||||
import AdminMenu from '../menu/AdminMenu';
|
|
||||||
import { styled, Tab, Tabs } from '@mui/material';
|
import { styled, Tab, Tabs } from '@mui/material';
|
||||||
import { Route, Routes, useLocation } from 'react-router-dom';
|
import { Route, Routes, useLocation } from 'react-router-dom';
|
||||||
import { CenteredNavLink } from '../menu/CenteredNavLink';
|
import { CenteredNavLink } from '../menu/CenteredNavLink';
|
||||||
@ -30,7 +30,6 @@ export const Network = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AdminMenu />
|
|
||||||
<StyledPageContent
|
<StyledPageContent
|
||||||
headerClass="page-header"
|
headerClass="page-header"
|
||||||
header={
|
header={
|
||||||
|
@ -2,7 +2,6 @@ import { useContext } from 'react';
|
|||||||
import AccessContext from 'contexts/AccessContext';
|
import AccessContext from 'contexts/AccessContext';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||||
import AdminMenu from 'component/admin/menu/AdminMenu';
|
|
||||||
import ProjectRoleList from './ProjectRoleList/ProjectRoleList';
|
import ProjectRoleList from './ProjectRoleList/ProjectRoleList';
|
||||||
import { AdminAlert } from 'component/common/AdminAlert/AdminAlert';
|
import { AdminAlert } from 'component/common/AdminAlert/AdminAlert';
|
||||||
|
|
||||||
@ -11,7 +10,6 @@ const ProjectRoles = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AdminMenu />
|
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={hasAccess(ADMIN)}
|
condition={hasAccess(ADMIN)}
|
||||||
show={<ProjectRoleList />}
|
show={<ProjectRoleList />}
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import AdminMenu from '../menu/AdminMenu';
|
|
||||||
import AccessContext from 'contexts/AccessContext';
|
import AccessContext from 'contexts/AccessContext';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||||
@ -11,7 +10,6 @@ export const ServiceAccounts = () => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AdminMenu />
|
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={hasAccess(ADMIN)}
|
condition={hasAccess(ADMIN)}
|
||||||
show={<ServiceAccountsTable />}
|
show={<ServiceAccountsTable />}
|
||||||
|
@ -1,18 +1,16 @@
|
|||||||
import { useContext } from 'react';
|
import { useContext } from 'react';
|
||||||
import UsersList from './UsersList/UsersList';
|
import UsersList from './UsersList/UsersList';
|
||||||
import AdminMenu from '../menu/AdminMenu';
|
|
||||||
import AccessContext from 'contexts/AccessContext';
|
import AccessContext from 'contexts/AccessContext';
|
||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||||
import { AdminAlert } from 'component/common/AdminAlert/AdminAlert';
|
import { AdminAlert } from 'component/common/AdminAlert/AdminAlert';
|
||||||
import { InviteLinkBar } from './InviteLinkBar/InviteLinkBar';
|
import { InviteLinkBar } from './InviteLinkBar/InviteLinkBar';
|
||||||
|
|
||||||
const UsersAdmin = () => {
|
export const UsersAdmin = () => {
|
||||||
const { hasAccess } = useContext(AccessContext);
|
const { hasAccess } = useContext(AccessContext);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<AdminMenu />
|
|
||||||
<InviteLinkBar />
|
<InviteLinkBar />
|
||||||
<ConditionallyRender
|
<ConditionallyRender
|
||||||
condition={hasAccess(ADMIN)}
|
condition={hasAccess(ADMIN)}
|
||||||
|
@ -1,10 +1,11 @@
|
|||||||
import { weightTypes } from '../feature/FeatureView/FeatureVariants/FeatureVariantsList/AddFeatureVariant/enums';
|
import { weightTypes } from '../feature/FeatureView/FeatureVariants/FeatureVariantsList/AddFeatureVariant/enums';
|
||||||
import { IUiConfig } from 'interfaces/uiConfig';
|
import { IUiConfig } from 'interfaces/uiConfig';
|
||||||
import { IRoute } from 'interfaces/route';
|
import { INavigationMenuItem } from 'interfaces/route';
|
||||||
import { IFeatureVariant } from 'interfaces/featureToggle';
|
import { IFeatureVariant } from 'interfaces/featureToggle';
|
||||||
import { format, isValid } from 'date-fns';
|
import { format, isValid } from 'date-fns';
|
||||||
|
|
||||||
export const filterByConfig = (config: IUiConfig) => (r: IRoute) => {
|
export const filterByConfig =
|
||||||
|
(config: IUiConfig) => (r: INavigationMenuItem) => {
|
||||||
if (r.flag) {
|
if (r.flag) {
|
||||||
// Check if the route's `flag` is enabled in IUiConfig.flags.
|
// Check if the route's `flag` is enabled in IUiConfig.flags.
|
||||||
const flags = config.flags as unknown as Record<string, boolean>;
|
const flags = config.flags as unknown as Record<string, boolean>;
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
// Lazy loading only supports default export. We have an ADR
|
||||||
|
// that says we should only use named exports, because
|
||||||
|
// it makes it harder to diverge from the name of the component when
|
||||||
|
// importing it in other files.
|
||||||
|
import { FeatureView } from './FeatureView';
|
||||||
|
|
||||||
|
export default FeatureView;
|
@ -0,0 +1,3 @@
|
|||||||
|
import { lazy } from 'react';
|
||||||
|
|
||||||
|
export const LazyFeatureView = lazy(() => import('./FeatureViewLazyExport'));
|
@ -9,7 +9,7 @@ import NavigationLink from '../NavigationLink/NavigationLink';
|
|||||||
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
import { ConditionallyRender } from 'component/common/ConditionallyRender/ConditionallyRender';
|
||||||
import { basePath } from 'utils/formatPath';
|
import { basePath } from 'utils/formatPath';
|
||||||
import { IFlags } from 'interfaces/uiConfig';
|
import { IFlags } from 'interfaces/uiConfig';
|
||||||
import { IRoute } from 'interfaces/route';
|
import { INavigationMenuItem } from 'interfaces/route';
|
||||||
import styles from './DrawerMenu.module.scss'; // FIXME: useStyle - theme
|
import styles from './DrawerMenu.module.scss'; // FIXME: useStyle - theme
|
||||||
|
|
||||||
interface IDrawerMenuProps {
|
interface IDrawerMenuProps {
|
||||||
@ -25,9 +25,9 @@ interface IDrawerMenuProps {
|
|||||||
}>;
|
}>;
|
||||||
flags?: IFlags;
|
flags?: IFlags;
|
||||||
routes: {
|
routes: {
|
||||||
mainNavRoutes: IRoute[];
|
mainNavRoutes: INavigationMenuItem[];
|
||||||
mobileRoutes: IRoute[];
|
mobileRoutes: INavigationMenuItem[];
|
||||||
adminRoutes: IRoute[];
|
adminRoutes: INavigationMenuItem[];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,12 +26,16 @@ import { flexRow, focusable } from 'themes/themeStyles';
|
|||||||
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
import { ADMIN } from 'component/providers/AccessProvider/permissions';
|
||||||
import { IPermission } from 'interfaces/user';
|
import { IPermission } from 'interfaces/user';
|
||||||
import { NavigationMenu } from './NavigationMenu/NavigationMenu';
|
import { NavigationMenu } from './NavigationMenu/NavigationMenu';
|
||||||
import { getRoutes } from 'component/menu/routes';
|
import {
|
||||||
|
getRoutes,
|
||||||
|
adminMenuRoutes,
|
||||||
|
getCondensedRoutes,
|
||||||
|
} from 'component/menu/routes';
|
||||||
import { KeyboardArrowDown } from '@mui/icons-material';
|
import { KeyboardArrowDown } from '@mui/icons-material';
|
||||||
import { filterByConfig } from 'component/common/util';
|
import { filterByConfig } from 'component/common/util';
|
||||||
import { useAuthPermissions } from 'hooks/api/getters/useAuth/useAuthPermissions';
|
import { useAuthPermissions } from 'hooks/api/getters/useAuth/useAuthPermissions';
|
||||||
import { useId } from 'hooks/useId';
|
import { useId } from 'hooks/useId';
|
||||||
import { IRoute } from 'interfaces/route';
|
import { INavigationMenuItem } from 'interfaces/route';
|
||||||
import { ThemeMode } from 'component/common/ThemeMode/ThemeMode';
|
import { ThemeMode } from 'component/common/ThemeMode/ThemeMode';
|
||||||
import { useThemeMode } from 'hooks/useThemeMode';
|
import { useThemeMode } from 'hooks/useThemeMode';
|
||||||
|
|
||||||
@ -134,14 +138,24 @@ const Header: VFC = () => {
|
|||||||
|
|
||||||
const routes = getRoutes();
|
const routes = getRoutes();
|
||||||
|
|
||||||
const filterByEnterprise = (route: IRoute): boolean => {
|
const filterByEnterprise = (route: INavigationMenuItem): boolean => {
|
||||||
return !route.menu.isEnterprise || !isOss();
|
return !route.menu.isEnterprise || !isOss();
|
||||||
};
|
};
|
||||||
|
|
||||||
const filteredMainRoutes = {
|
const filteredMainRoutes = {
|
||||||
mainNavRoutes: routes.mainNavRoutes.filter(filterByConfig(uiConfig)),
|
mainNavRoutes: getCondensedRoutes(routes.mainNavRoutes)
|
||||||
mobileRoutes: routes.mobileRoutes.filter(filterByConfig(uiConfig)),
|
.concat([
|
||||||
adminRoutes: routes.adminRoutes
|
{
|
||||||
|
path: '/admin/api',
|
||||||
|
title: 'API access',
|
||||||
|
menu: {},
|
||||||
|
},
|
||||||
|
])
|
||||||
|
.filter(filterByConfig(uiConfig)),
|
||||||
|
mobileRoutes: getCondensedRoutes(routes.mobileRoutes).filter(
|
||||||
|
filterByConfig(uiConfig)
|
||||||
|
),
|
||||||
|
adminRoutes: adminMenuRoutes
|
||||||
.filter(filterByConfig(uiConfig))
|
.filter(filterByConfig(uiConfig))
|
||||||
.filter(filterByEnterprise)
|
.filter(filterByEnterprise)
|
||||||
.map(route => ({
|
.map(route => ({
|
||||||
|
@ -11,7 +11,14 @@ exports[`returns all baseRoutes 1`] = `
|
|||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"component": [Function],
|
"component": {
|
||||||
|
"$$typeof": Symbol(react.lazy),
|
||||||
|
"_init": [Function],
|
||||||
|
"_payload": {
|
||||||
|
"_result": [Function],
|
||||||
|
"_status": -1,
|
||||||
|
},
|
||||||
|
},
|
||||||
"enterprise": true,
|
"enterprise": true,
|
||||||
"menu": {},
|
"menu": {},
|
||||||
"parent": "/projects",
|
"parent": "/projects",
|
||||||
@ -53,7 +60,14 @@ exports[`returns all baseRoutes 1`] = `
|
|||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"component": [Function],
|
"component": {
|
||||||
|
"$$typeof": Symbol(react.lazy),
|
||||||
|
"_init": [Function],
|
||||||
|
"_payload": {
|
||||||
|
"_result": [Function],
|
||||||
|
"_status": -1,
|
||||||
|
},
|
||||||
|
},
|
||||||
"menu": {},
|
"menu": {},
|
||||||
"parent": "/projects",
|
"parent": "/projects",
|
||||||
"path": "/projects/:projectId/features/:featureId/*",
|
"path": "/projects/:projectId/features/:featureId/*",
|
||||||
@ -77,7 +91,14 @@ exports[`returns all baseRoutes 1`] = `
|
|||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"component": [Function],
|
"component": {
|
||||||
|
"$$typeof": Symbol(react.lazy),
|
||||||
|
"_init": [Function],
|
||||||
|
"_payload": {
|
||||||
|
"_result": [Function],
|
||||||
|
"_status": -1,
|
||||||
|
},
|
||||||
|
},
|
||||||
"flag": "P",
|
"flag": "P",
|
||||||
"menu": {},
|
"menu": {},
|
||||||
"parent": "/projects",
|
"parent": "/projects",
|
||||||
@ -333,199 +354,6 @@ exports[`returns all baseRoutes 1`] = `
|
|||||||
"title": "Archived toggles",
|
"title": "Archived toggles",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"menu": {},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/api/create-token",
|
|
||||||
"title": "API access",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "RE",
|
|
||||||
"menu": {},
|
|
||||||
"path": "/admin/create-project-role",
|
|
||||||
"title": "Create",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "RE",
|
|
||||||
"menu": {},
|
|
||||||
"path": "/admin/roles/:id/edit",
|
|
||||||
"title": "Edit",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"menu": {
|
|
||||||
"advanced": true,
|
|
||||||
"mobile": true,
|
|
||||||
},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/api",
|
|
||||||
"title": "API access",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"menu": {
|
|
||||||
"adminSettings": true,
|
|
||||||
},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/users",
|
|
||||||
"title": "Users",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "serviceAccounts",
|
|
||||||
"menu": {
|
|
||||||
"adminSettings": true,
|
|
||||||
},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/service-accounts",
|
|
||||||
"title": "Service accounts",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"menu": {},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/create-user",
|
|
||||||
"title": "Users",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"menu": {},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/invite-link",
|
|
||||||
"title": "Invite link",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "UG",
|
|
||||||
"menu": {
|
|
||||||
"adminSettings": true,
|
|
||||||
},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/groups",
|
|
||||||
"title": "Groups",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "UG",
|
|
||||||
"menu": {},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/groups/:groupId",
|
|
||||||
"title": ":groupId",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "UG",
|
|
||||||
"menu": {},
|
|
||||||
"parent": "/admin/groups",
|
|
||||||
"path": "/admin/groups/create-group",
|
|
||||||
"title": "Create group",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "UG",
|
|
||||||
"menu": {},
|
|
||||||
"parent": "/admin/groups",
|
|
||||||
"path": "/admin/groups/:groupId/edit",
|
|
||||||
"title": "Edit group",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "RE",
|
|
||||||
"menu": {
|
|
||||||
"adminSettings": true,
|
|
||||||
},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/roles",
|
|
||||||
"title": "Project roles",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"menu": {
|
|
||||||
"adminSettings": true,
|
|
||||||
},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/auth",
|
|
||||||
"title": "Single sign-on",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"menu": {
|
|
||||||
"adminSettings": true,
|
|
||||||
},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/instance",
|
|
||||||
"title": "Instance stats",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "networkView",
|
|
||||||
"menu": {
|
|
||||||
"adminSettings": true,
|
|
||||||
},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/network/*",
|
|
||||||
"title": "Network",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "maintenance",
|
|
||||||
"menu": {
|
|
||||||
"adminSettings": true,
|
|
||||||
},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/maintenance",
|
|
||||||
"title": "Maintenance",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"flag": "embedProxyFrontend",
|
|
||||||
"menu": {
|
|
||||||
"adminSettings": true,
|
|
||||||
},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/cors",
|
|
||||||
"title": "CORS origins",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"menu": {},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin/billing",
|
|
||||||
"title": "Billing",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"component": [Function],
|
|
||||||
"menu": {
|
|
||||||
"adminSettings": true,
|
|
||||||
"isEnterprise": true,
|
|
||||||
},
|
|
||||||
"parent": "/admin",
|
|
||||||
"path": "/admin-invoices",
|
|
||||||
"title": "Billing & invoices",
|
|
||||||
"type": "protected",
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"component": [Function],
|
"component": [Function],
|
||||||
"hidden": false,
|
"hidden": false,
|
||||||
@ -534,6 +362,21 @@ exports[`returns all baseRoutes 1`] = `
|
|||||||
"title": "Admin",
|
"title": "Admin",
|
||||||
"type": "protected",
|
"type": "protected",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"component": {
|
||||||
|
"$$typeof": Symbol(react.lazy),
|
||||||
|
"_init": [Function],
|
||||||
|
"_payload": {
|
||||||
|
"_result": [Function],
|
||||||
|
"_status": -1,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
"hidden": false,
|
||||||
|
"menu": {},
|
||||||
|
"path": "/admin/*",
|
||||||
|
"title": "Admin",
|
||||||
|
"type": "protected",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"component": [Function],
|
"component": [Function],
|
||||||
"menu": {},
|
"menu": {},
|
||||||
|
@ -3,33 +3,19 @@ import { StrategyView } from 'component/strategies/StrategyView/StrategyView';
|
|||||||
import { StrategiesList } from 'component/strategies/StrategiesList/StrategiesList';
|
import { StrategiesList } from 'component/strategies/StrategiesList/StrategiesList';
|
||||||
import { TagTypeList } from 'component/tags/TagTypeList/TagTypeList';
|
import { TagTypeList } from 'component/tags/TagTypeList/TagTypeList';
|
||||||
import { AddonList } from 'component/addons/AddonList/AddonList';
|
import { AddonList } from 'component/addons/AddonList/AddonList';
|
||||||
import Admin from 'component/admin';
|
|
||||||
import AdminApi from 'component/admin/api';
|
|
||||||
import AdminUsers from 'component/admin/users/UsersAdmin';
|
|
||||||
import { GroupsAdmin } from 'component/admin/groups/GroupsAdmin';
|
|
||||||
import { AuthSettings } from 'component/admin/auth/AuthSettings';
|
|
||||||
import Login from 'component/user/Login/Login';
|
import Login from 'component/user/Login/Login';
|
||||||
import { EEA, P, RE, SE, UG } from 'component/common/flags';
|
import { EEA, P, RE, SE, UG } from 'component/common/flags';
|
||||||
import { NewUser } from 'component/user/NewUser/NewUser';
|
import { NewUser } from 'component/user/NewUser/NewUser';
|
||||||
import ResetPassword from 'component/user/ResetPassword/ResetPassword';
|
import ResetPassword from 'component/user/ResetPassword/ResetPassword';
|
||||||
import ForgottenPassword from 'component/user/ForgottenPassword/ForgottenPassword';
|
import ForgottenPassword from 'component/user/ForgottenPassword/ForgottenPassword';
|
||||||
import { ProjectListNew } from 'component/project/ProjectList/ProjectList';
|
import { ProjectListNew } from 'component/project/ProjectList/ProjectList';
|
||||||
import Project from 'component/project/Project/Project';
|
|
||||||
import RedirectArchive from 'component/archive/RedirectArchive';
|
import RedirectArchive from 'component/archive/RedirectArchive';
|
||||||
import { FeatureView } from 'component/feature/FeatureView/FeatureView';
|
|
||||||
import ProjectRoles from 'component/admin/projectRoles/ProjectRoles/ProjectRoles';
|
|
||||||
import CreateProjectRole from 'component/admin/projectRoles/CreateProjectRole/CreateProjectRole';
|
|
||||||
import EditProjectRole from 'component/admin/projectRoles/EditProjectRole/EditProjectRole';
|
|
||||||
import CreateUser from 'component/admin/users/CreateUser/CreateUser';
|
|
||||||
import EditUser from 'component/admin/users/EditUser/EditUser';
|
|
||||||
import { CreateApiToken } from 'component/admin/apiToken/CreateApiToken/CreateApiToken';
|
|
||||||
import CreateEnvironment from 'component/environments/CreateEnvironment/CreateEnvironment';
|
import CreateEnvironment from 'component/environments/CreateEnvironment/CreateEnvironment';
|
||||||
import EditEnvironment from 'component/environments/EditEnvironment/EditEnvironment';
|
import EditEnvironment from 'component/environments/EditEnvironment/EditEnvironment';
|
||||||
import { EditContext } from 'component/context/EditContext/EditContext';
|
import { EditContext } from 'component/context/EditContext/EditContext';
|
||||||
import EditTagType from 'component/tags/EditTagType/EditTagType';
|
import EditTagType from 'component/tags/EditTagType/EditTagType';
|
||||||
import CreateTagType from 'component/tags/CreateTagType/CreateTagType';
|
import CreateTagType from 'component/tags/CreateTagType/CreateTagType';
|
||||||
import EditProject from 'component/project/Project/EditProject/EditProject';
|
import EditProject from 'component/project/Project/EditProject/EditProject';
|
||||||
import CreateProject from 'component/project/Project/CreateProject/CreateProject';
|
|
||||||
import CreateFeature from 'component/feature/CreateFeature/CreateFeature';
|
import CreateFeature from 'component/feature/CreateFeature/CreateFeature';
|
||||||
import EditFeature from 'component/feature/EditFeature/EditFeature';
|
import EditFeature from 'component/feature/EditFeature/EditFeature';
|
||||||
import { ApplicationEdit } from 'component/application/ApplicationEdit/ApplicationEdit';
|
import { ApplicationEdit } from 'component/application/ApplicationEdit/ApplicationEdit';
|
||||||
@ -46,23 +32,17 @@ import { SplashPage } from 'component/splash/SplashPage/SplashPage';
|
|||||||
import { CreateUnleashContextPage } from 'component/context/CreateUnleashContext/CreateUnleashContextPage';
|
import { CreateUnleashContextPage } from 'component/context/CreateUnleashContext/CreateUnleashContextPage';
|
||||||
import { CreateSegment } from 'component/segments/CreateSegment/CreateSegment';
|
import { CreateSegment } from 'component/segments/CreateSegment/CreateSegment';
|
||||||
import { EditSegment } from 'component/segments/EditSegment/EditSegment';
|
import { EditSegment } from 'component/segments/EditSegment/EditSegment';
|
||||||
import { IRoute } from 'interfaces/route';
|
import { INavigationMenuItem, IRoute } from 'interfaces/route';
|
||||||
import { EnvironmentTable } from 'component/environments/EnvironmentTable/EnvironmentTable';
|
import { EnvironmentTable } from 'component/environments/EnvironmentTable/EnvironmentTable';
|
||||||
import { SegmentTable } from 'component/segments/SegmentTable';
|
import { SegmentTable } from 'component/segments/SegmentTable';
|
||||||
import FlaggedBillingRedirect from 'component/admin/billing/FlaggedBillingRedirect/FlaggedBillingRedirect';
|
|
||||||
import { FeaturesArchiveTable } from '../archive/FeaturesArchiveTable';
|
import { FeaturesArchiveTable } from '../archive/FeaturesArchiveTable';
|
||||||
import { Billing } from 'component/admin/billing/Billing';
|
|
||||||
import { Group } from 'component/admin/groups/Group/Group';
|
|
||||||
import { CreateGroup } from 'component/admin/groups/CreateGroup/CreateGroup';
|
|
||||||
import { EditGroup } from 'component/admin/groups/EditGroup/EditGroup';
|
|
||||||
import { LazyPlayground } from 'component/playground/Playground/LazyPlayground';
|
import { LazyPlayground } from 'component/playground/Playground/LazyPlayground';
|
||||||
import { CorsAdmin } from 'component/admin/cors';
|
|
||||||
import { InviteLink } from 'component/admin/users/InviteLink/InviteLink';
|
|
||||||
import { Profile } from 'component/user/Profile/Profile';
|
import { Profile } from 'component/user/Profile/Profile';
|
||||||
import { InstanceAdmin } from '../admin/instance-admin/InstanceAdmin';
|
import { LazyCreateProject } from 'component/project/Project/CreateProject/LazyCreateProject';
|
||||||
import { Network } from 'component/admin/network/Network';
|
import { LazyFeatureView } from 'component/feature/FeatureView/LazyFeatureView';
|
||||||
import { MaintenanceAdmin } from '../admin/maintenance';
|
import { LazyAdmin } from 'component/admin/LazyAdmin';
|
||||||
import { ServiceAccounts } from 'component/admin/serviceAccounts/ServiceAccounts';
|
import { LazyProject } from 'component/project/Project/LazyProject';
|
||||||
|
import { AdminRedirect } from 'component/admin/AdminRedirect';
|
||||||
|
|
||||||
export const routes: IRoute[] = [
|
export const routes: IRoute[] = [
|
||||||
// Splash
|
// Splash
|
||||||
@ -80,7 +60,7 @@ export const routes: IRoute[] = [
|
|||||||
path: '/projects/create',
|
path: '/projects/create',
|
||||||
parent: '/projects',
|
parent: '/projects',
|
||||||
title: 'Create',
|
title: 'Create',
|
||||||
component: CreateProject,
|
component: LazyCreateProject,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
enterprise: true,
|
enterprise: true,
|
||||||
menu: {},
|
menu: {},
|
||||||
@ -122,7 +102,7 @@ export const routes: IRoute[] = [
|
|||||||
path: '/projects/:projectId/features/:featureId/*',
|
path: '/projects/:projectId/features/:featureId/*',
|
||||||
parent: '/projects',
|
parent: '/projects',
|
||||||
title: 'FeatureView',
|
title: 'FeatureView',
|
||||||
component: FeatureView,
|
component: LazyFeatureView,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
menu: {},
|
menu: {},
|
||||||
},
|
},
|
||||||
@ -146,7 +126,7 @@ export const routes: IRoute[] = [
|
|||||||
path: '/projects/:projectId/*',
|
path: '/projects/:projectId/*',
|
||||||
parent: '/projects',
|
parent: '/projects',
|
||||||
title: ':projectId',
|
title: ':projectId',
|
||||||
component: Project,
|
component: LazyProject,
|
||||||
flag: P,
|
flag: P,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
menu: {},
|
menu: {},
|
||||||
@ -385,187 +365,19 @@ export const routes: IRoute[] = [
|
|||||||
},
|
},
|
||||||
|
|
||||||
// Admin
|
// Admin
|
||||||
{
|
|
||||||
path: '/admin/api/create-token',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'API access',
|
|
||||||
component: CreateApiToken,
|
|
||||||
type: 'protected',
|
|
||||||
menu: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/create-project-role',
|
|
||||||
title: 'Create',
|
|
||||||
component: CreateProjectRole,
|
|
||||||
type: 'protected',
|
|
||||||
menu: {},
|
|
||||||
flag: RE,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/roles/:id/edit',
|
|
||||||
title: 'Edit',
|
|
||||||
component: EditProjectRole,
|
|
||||||
type: 'protected',
|
|
||||||
menu: {},
|
|
||||||
flag: RE,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/users/:id/edit',
|
|
||||||
title: 'Edit',
|
|
||||||
component: EditUser,
|
|
||||||
type: 'protected',
|
|
||||||
menu: {},
|
|
||||||
hidden: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/api',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'API access',
|
|
||||||
component: AdminApi,
|
|
||||||
type: 'protected',
|
|
||||||
menu: { mobile: true, advanced: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/users',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Users',
|
|
||||||
component: AdminUsers,
|
|
||||||
type: 'protected',
|
|
||||||
menu: { adminSettings: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/service-accounts',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Service accounts',
|
|
||||||
component: ServiceAccounts,
|
|
||||||
type: 'protected',
|
|
||||||
menu: { adminSettings: true },
|
|
||||||
flag: 'serviceAccounts',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/create-user',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Users',
|
|
||||||
component: CreateUser,
|
|
||||||
type: 'protected',
|
|
||||||
menu: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/invite-link',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Invite link',
|
|
||||||
component: InviteLink,
|
|
||||||
type: 'protected',
|
|
||||||
menu: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/groups',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Groups',
|
|
||||||
component: GroupsAdmin,
|
|
||||||
type: 'protected',
|
|
||||||
menu: { adminSettings: true },
|
|
||||||
flag: UG,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/groups/:groupId',
|
|
||||||
parent: '/admin',
|
|
||||||
title: ':groupId',
|
|
||||||
component: Group,
|
|
||||||
type: 'protected',
|
|
||||||
menu: {},
|
|
||||||
flag: UG,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/groups/create-group',
|
|
||||||
parent: '/admin/groups',
|
|
||||||
title: 'Create group',
|
|
||||||
component: CreateGroup,
|
|
||||||
type: 'protected',
|
|
||||||
menu: {},
|
|
||||||
flag: UG,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/groups/:groupId/edit',
|
|
||||||
parent: '/admin/groups',
|
|
||||||
title: 'Edit group',
|
|
||||||
component: EditGroup,
|
|
||||||
type: 'protected',
|
|
||||||
menu: {},
|
|
||||||
flag: UG,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/roles',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Project roles',
|
|
||||||
component: ProjectRoles,
|
|
||||||
type: 'protected',
|
|
||||||
flag: RE,
|
|
||||||
menu: { adminSettings: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/auth',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Single sign-on',
|
|
||||||
component: AuthSettings,
|
|
||||||
type: 'protected',
|
|
||||||
menu: { adminSettings: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/instance',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Instance stats',
|
|
||||||
component: InstanceAdmin,
|
|
||||||
type: 'protected',
|
|
||||||
menu: { adminSettings: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/network/*',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Network',
|
|
||||||
component: Network,
|
|
||||||
type: 'protected',
|
|
||||||
menu: { adminSettings: true },
|
|
||||||
flag: 'networkView',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/maintenance',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Maintenance',
|
|
||||||
component: MaintenanceAdmin,
|
|
||||||
type: 'protected',
|
|
||||||
menu: { adminSettings: true },
|
|
||||||
flag: 'maintenance',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/cors',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'CORS origins',
|
|
||||||
component: CorsAdmin,
|
|
||||||
type: 'protected',
|
|
||||||
flag: 'embedProxyFrontend',
|
|
||||||
menu: { adminSettings: true },
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin/billing',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Billing',
|
|
||||||
component: Billing,
|
|
||||||
type: 'protected',
|
|
||||||
menu: {},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
path: '/admin-invoices',
|
|
||||||
parent: '/admin',
|
|
||||||
title: 'Billing & invoices',
|
|
||||||
component: FlaggedBillingRedirect,
|
|
||||||
type: 'protected',
|
|
||||||
menu: { adminSettings: true, isEnterprise: true },
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: '/admin',
|
path: '/admin',
|
||||||
title: 'Admin',
|
title: 'Admin',
|
||||||
component: Admin,
|
component: AdminRedirect,
|
||||||
|
hidden: false,
|
||||||
|
type: 'protected',
|
||||||
|
menu: {},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/*',
|
||||||
|
title: 'Admin',
|
||||||
|
component: LazyAdmin,
|
||||||
hidden: false,
|
hidden: false,
|
||||||
type: 'protected',
|
type: 'protected',
|
||||||
menu: {},
|
menu: {},
|
||||||
@ -620,6 +432,70 @@ export const routes: IRoute[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
export const adminMenuRoutes: INavigationMenuItem[] = [
|
||||||
|
{
|
||||||
|
path: '/history',
|
||||||
|
title: 'Event log',
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/users',
|
||||||
|
title: 'Users',
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/groups',
|
||||||
|
title: 'Groups',
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
flag: UG,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/roles',
|
||||||
|
title: 'Project roles',
|
||||||
|
flag: RE,
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/auth',
|
||||||
|
title: 'Single sign-on',
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/instance',
|
||||||
|
title: 'Instance stats',
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/service-accounts',
|
||||||
|
title: 'Service accounts',
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
flag: 'serviceAccounts',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/network/*',
|
||||||
|
title: 'Network',
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
flag: 'networkView',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/maintenance',
|
||||||
|
title: 'Maintenance',
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
flag: 'maintenance',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/cors',
|
||||||
|
title: 'CORS origins',
|
||||||
|
flag: 'embedProxyFrontend',
|
||||||
|
menu: { adminSettings: true },
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: '/admin/admin-invoices',
|
||||||
|
title: 'Billing & invoices',
|
||||||
|
menu: { adminSettings: true, isEnterprise: true },
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
export const getRoute = (path: string) =>
|
export const getRoute = (path: string) =>
|
||||||
routes.find(route => route.path === path);
|
routes.find(route => route.path === path);
|
||||||
|
|
||||||
@ -640,4 +516,17 @@ const computeRoutes = () => {
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getCondensedRoutes = (routes: IRoute[]): INavigationMenuItem[] => {
|
||||||
|
return routes.map(route => {
|
||||||
|
const condensedRoute = {
|
||||||
|
path: route.path,
|
||||||
|
flag: route.flag,
|
||||||
|
title: route.title,
|
||||||
|
menu: route.menu,
|
||||||
|
configFlag: route.configFlag,
|
||||||
|
};
|
||||||
|
return condensedRoute;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
export const getRoutes = computeRoutes();
|
export const getRoutes = computeRoutes();
|
||||||
|
@ -0,0 +1,3 @@
|
|||||||
|
import { lazy } from 'react';
|
||||||
|
|
||||||
|
export const LazyCreateProject = lazy(() => import('./CreateProject'));
|
3
frontend/src/component/project/Project/LazyProject.tsx
Normal file
3
frontend/src/component/project/Project/LazyProject.tsx
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import { lazy } from 'react';
|
||||||
|
|
||||||
|
export const LazyProject = lazy(() => import('./LazyProjectExport'));
|
@ -0,0 +1,7 @@
|
|||||||
|
// Lazy loading only supports default export. We have an ADR
|
||||||
|
// that says we should only use named exports, because
|
||||||
|
// it makes it harder to diverge from the name of the component when
|
||||||
|
// importing it in other files.
|
||||||
|
import { Project } from './Project';
|
||||||
|
|
||||||
|
export default Project;
|
@ -41,7 +41,7 @@ import { ProjectChangeRequests } from '../../changeRequest/ProjectChangeRequests
|
|||||||
import { ProjectSettings } from './ProjectSettings/ProjectSettings';
|
import { ProjectSettings } from './ProjectSettings/ProjectSettings';
|
||||||
import { useFavoriteProjectsApi } from 'hooks/api/actions/useFavoriteProjectsApi/useFavoriteProjectsApi';
|
import { useFavoriteProjectsApi } from 'hooks/api/actions/useFavoriteProjectsApi/useFavoriteProjectsApi';
|
||||||
|
|
||||||
const Project = () => {
|
export const Project = () => {
|
||||||
const projectId = useRequiredPathParam('projectId');
|
const projectId = useRequiredPathParam('projectId');
|
||||||
const params = useQueryParams();
|
const params = useQueryParams();
|
||||||
const { project, loading, refetch } = useProject(projectId);
|
const { project, loading, refetch } = useProject(projectId);
|
||||||
@ -250,5 +250,3 @@ const Project = () => {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export default Project;
|
|
||||||
|
@ -16,6 +16,14 @@ export interface IRoute {
|
|||||||
isStandalone?: boolean;
|
isStandalone?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface INavigationMenuItem {
|
||||||
|
path: string;
|
||||||
|
title: string;
|
||||||
|
menu: IRouteMenu;
|
||||||
|
flag?: keyof IFlags;
|
||||||
|
configFlag?: keyof IUiConfig;
|
||||||
|
}
|
||||||
|
|
||||||
interface IRouteMenu {
|
interface IRouteMenu {
|
||||||
mobile?: boolean;
|
mobile?: boolean;
|
||||||
advanced?: boolean;
|
advanced?: boolean;
|
||||||
|
Loading…
Reference in New Issue
Block a user