0
Fork 0
mirror of https://github.com/logto-io/logto.git synced 2025-01-06 20:40:08 -05:00
logto/packages/console/src/App.tsx

159 lines
4.9 KiB
TypeScript
Raw Permalink Normal View History

import { UserScope } from '@logto/core-kit';
import { LogtoProvider, Prompt, useLogto } from '@logto/react';
import {
adminConsoleApplicationId,
defaultTenantId,
PredefinedScope,
TenantScope,
} from '@logto/schemas';
import { conditionalArray } from '@silverhand/essentials';
import { useContext, useMemo } from 'react';
import { Helmet } from 'react-helmet';
import { createBrowserRouter, RouterProvider } from 'react-router-dom';
import 'overlayscrollbars/overlayscrollbars.css';
2022-02-27 21:35:14 -05:00
import './scss/normalized.scss';
import './scss/overlayscrollbars.scss';
// eslint-disable-next-line import/no-unassigned-import
import '@fontsource/roboto-mono';
2023-03-01 10:46:30 -05:00
import CloudAppRoutes from '@/cloud/AppRoutes';
import AppLoading from '@/components/AppLoading';
import { isCloud } from '@/consts/env';
import { cloudApi, getManagementApi, meApi } from '@/consts/resources';
import { ConsoleRoutes } from '@/containers/ConsoleRoutes';
import { GlobalScripts } from './components/Conversion';
import { adminTenantEndpoint, mainTitle } from './consts';
import ErrorBoundary from './containers/ErrorBoundary';
import LogtoErrorBoundary from './containers/LogtoErrorBoundary';
import AppConfirmModalProvider from './contexts/AppConfirmModalProvider';
import AppDataProvider, { AppDataContext } from './contexts/AppDataProvider';
import { AppThemeProvider } from './contexts/AppThemeProvider';
import TenantsProvider, { TenantsContext } from './contexts/TenantsProvider';
import Toast from './ds-components/Toast';
import useCurrentUser from './hooks/use-current-user';
import initI18n from './i18n/init';
2022-02-28 09:18:01 -05:00
void initI18n();
/**
* The main entry of the project. It provides two fundamental context providers:
*
* - `RouterProvider`: the sole router provider of the project.
* - `TenantsProvider`: manages the tenants data, requires the `RouterProvider` to
* get the current tenant ID from the URL.
*/
function App() {
const router = createBrowserRouter([
{
path: '*',
element: (
<TenantsProvider>
<Providers />
</TenantsProvider>
),
},
]);
return <RouterProvider router={router} />;
}
export default App;
/**
* This component serves as a container for all the providers and boundary components.
*
* Since `TenantsContext` requires the `TenantsProvider` to be mounted, and the initialization
* of `LogtoProvider` requires the `TenantsContext` to be available, we have to put them into
* different components.
*/
function Providers() {
const { currentTenantId } = useContext(TenantsContext);
2023-02-10 00:06:52 -05:00
// For Cloud, we use Management API proxy for accessing tenant data.
// For OSS, we directly call the tenant API with the default tenant API resource.
const resources = useMemo(
() =>
isCloud
? [cloudApi.indicator, meApi.indicator]
: [getManagementApi(defaultTenantId).indicator, meApi.indicator],
[]
);
const scopes = useMemo(
() => [
UserScope.Email,
UserScope.Identities,
UserScope.CustomData,
UserScope.Organizations,
UserScope.OrganizationRoles,
PredefinedScope.All,
...conditionalArray(
isCloud && [
...Object.values(TenantScope),
cloudApi.scopes.CreateTenant,
cloudApi.scopes.ManageTenantSelf,
]
),
],
[]
);
2022-02-27 21:35:14 -05:00
return (
<LogtoProvider
unstable_enableCache
config={{
2023-03-06 23:38:26 -05:00
endpoint: adminTenantEndpoint.href,
appId: adminConsoleApplicationId,
resources,
scopes,
prompt: [Prompt.Login, Prompt.Consent],
}}
>
<AppThemeProvider>
2024-04-17 08:38:30 -05:00
<Helmet titleTemplate={`%s - ${mainTitle}`} defaultTitle={mainTitle} />
<Toast />
2024-04-17 08:38:30 -05:00
<ErrorBoundary>
<LogtoErrorBoundary>
{/**
* If it's not Cloud (OSS), render the tenant app container directly since only default tenant is available;
* if it's Cloud, render the tenant app container only when a tenant ID is available (in a tenant context).
*/}
{!isCloud || currentTenantId ? (
<AppDataProvider>
<AppConfirmModalProvider>
<AppRoutes />
</AppConfirmModalProvider>
</AppDataProvider>
) : (
<CloudAppRoutes />
)}
</LogtoErrorBoundary>
</ErrorBoundary>
</AppThemeProvider>
</LogtoProvider>
2022-02-27 21:35:14 -05:00
);
}
/** Renders different routes based on the user's onboarding status. */
function AppRoutes() {
const { tenantEndpoint } = useContext(AppDataContext);
const { isLoaded } = useCurrentUser();
const { isAuthenticated } = useLogto();
// Authenticated user should load onboarding data before rendering the app.
// This looks weird and it will be refactored soon by merging the onboarding
// routes with the console routes.
if (!tenantEndpoint || (isCloud && isAuthenticated && !isLoaded)) {
return <AppLoading />;
}
return (
<>
<GlobalScripts />
2024-05-28 03:09:08 -05:00
<ConsoleRoutes />
</>
);
}