mirror of
https://github.com/logto-io/logto.git
synced 2025-04-07 23:01:25 -05:00
refactor(console): AppEndpointsProvider
-> AppDataProvider
(#4117)
This commit is contained in:
parent
99aa43216f
commit
736e99fd63
11 changed files with 39 additions and 32 deletions
|
@ -22,7 +22,7 @@ import ErrorBoundary from './containers/ErrorBoundary';
|
|||
import LogtoErrorBoundary from './containers/LogtoErrorBoundary';
|
||||
import TenantAppContainer from './containers/TenantAppContainer';
|
||||
import AppConfirmModalProvider from './contexts/AppConfirmModalProvider';
|
||||
import AppEndpointsProvider from './contexts/AppEndpointsProvider';
|
||||
import AppDataProvider from './contexts/AppDataProvider';
|
||||
import { AppThemeProvider } from './contexts/AppThemeProvider';
|
||||
import TenantsProvider, { TenantsContext } from './contexts/TenantsProvider';
|
||||
import initI18n from './i18n/init';
|
||||
|
@ -83,11 +83,11 @@ function Content() {
|
|||
* if it's Cloud, render the tenant app container only when a tenant ID is available (in a tenant context).
|
||||
*/}
|
||||
{!isCloud || currentTenantId ? (
|
||||
<AppEndpointsProvider>
|
||||
<AppDataProvider>
|
||||
<AppConfirmModalProvider>
|
||||
<TenantAppContainer />
|
||||
</AppConfirmModalProvider>
|
||||
</AppEndpointsProvider>
|
||||
</AppDataProvider>
|
||||
) : (
|
||||
<CloudApp />
|
||||
)}
|
||||
|
|
|
@ -5,7 +5,7 @@ import { useContext } from 'react';
|
|||
import { Controller, useFormContext } from 'react-hook-form';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { AppEndpointsContext } from '@/contexts/AppEndpointsProvider';
|
||||
import { AppDataContext } from '@/contexts/AppDataProvider';
|
||||
import CodeEditor from '@/ds-components/CodeEditor';
|
||||
import CopyToClipboard from '@/ds-components/CopyToClipboard';
|
||||
import DynamicT from '@/ds-components/DynamicT';
|
||||
|
@ -31,7 +31,7 @@ function ConfigForm({ formItems, className, connectorId, connectorType }: Props)
|
|||
control,
|
||||
formState: { errors },
|
||||
} = useFormContext<ConnectorFormType>();
|
||||
const { userEndpoint } = useContext(AppEndpointsContext);
|
||||
const { userEndpoint } = useContext(AppDataContext);
|
||||
const { data: customDomain } = useCustomDomain();
|
||||
const callbackUri = new URL(`/callback/${connectorId}`, userEndpoint).toString();
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ import { useContext } from 'react';
|
|||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import ExternalLinkIcon from '@/assets/icons/external-link.svg';
|
||||
import { AppEndpointsContext } from '@/contexts/AppEndpointsProvider';
|
||||
import { AppDataContext } from '@/contexts/AppDataProvider';
|
||||
import type { Props as ButtonProps, ButtonType } from '@/ds-components/Button';
|
||||
import Button from '@/ds-components/Button';
|
||||
import { Tooltip } from '@/ds-components/Tip';
|
||||
|
@ -20,7 +20,7 @@ type Props = {
|
|||
|
||||
function LivePreviewButton({ size, type, isDisabled }: Props) {
|
||||
const { configs, updateConfigs } = useConfigs();
|
||||
const { userEndpoint } = useContext(AppEndpointsContext);
|
||||
const { userEndpoint } = useContext(AppDataContext);
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
return (
|
||||
|
|
|
@ -9,7 +9,7 @@ import { useTranslation } from 'react-i18next';
|
|||
import useSWR from 'swr';
|
||||
|
||||
import PhoneInfo from '@/assets/images/phone-info.svg';
|
||||
import { AppEndpointsContext } from '@/contexts/AppEndpointsProvider';
|
||||
import { AppDataContext } from '@/contexts/AppDataProvider';
|
||||
import type { RequestError } from '@/hooks/use-api';
|
||||
import useUiLanguages from '@/hooks/use-ui-languages';
|
||||
|
||||
|
@ -29,7 +29,7 @@ function SignInExperiencePreview({ platform, mode, language = 'en', signInExperi
|
|||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
|
||||
const { customPhrases } = useUiLanguages();
|
||||
const { userEndpoint } = useContext(AppEndpointsContext);
|
||||
const { userEndpoint } = useContext(AppDataContext);
|
||||
const previewRef = useRef<HTMLIFrameElement>(null);
|
||||
const { data: allConnectors } = useSWR<ConnectorResponse[], RequestError>('api/connectors');
|
||||
const [iframeLoaded, setIframeLoaded] = useState(false);
|
||||
|
|
|
@ -5,7 +5,8 @@ import { RouterProvider, createBrowserRouter } from 'react-router-dom';
|
|||
import AppLoading from '@/components/AppLoading';
|
||||
import { getBasename } from '@/consts';
|
||||
import { isCloud } from '@/consts/env';
|
||||
import { AppEndpointsContext } from '@/contexts/AppEndpointsProvider';
|
||||
import { AppDataContext } from '@/contexts/AppDataProvider';
|
||||
import useMeCustomData from '@/hooks/use-me-custom-data';
|
||||
import useTrackUserId from '@/hooks/use-track-user-id';
|
||||
import { OnboardingRoutes } from '@/onboarding';
|
||||
import useUserOnboardingData from '@/onboarding/hooks/use-user-onboarding-data';
|
||||
|
@ -13,8 +14,9 @@ import { ConsoleRoutes } from '@/pages/ConsoleRoutes';
|
|||
|
||||
/** @deprecated Remove this layer. */
|
||||
function TenantAppContainer() {
|
||||
const { userEndpoint } = useContext(AppEndpointsContext);
|
||||
const { isOnboarding, isLoaded } = useUserOnboardingData();
|
||||
const { userEndpoint } = useContext(AppDataContext);
|
||||
const { isLoaded } = useMeCustomData();
|
||||
const { isOnboarding } = useUserOnboardingData();
|
||||
const { isAuthenticated } = useLogto();
|
||||
|
||||
const router = useMemo(
|
||||
|
|
|
@ -10,7 +10,7 @@ type Props = {
|
|||
children: ReactNode;
|
||||
};
|
||||
|
||||
type AppEndpoints = {
|
||||
type AppData = {
|
||||
/**
|
||||
* The Logto endpoint for the current tenant.
|
||||
*
|
||||
|
@ -19,12 +19,19 @@ type AppEndpoints = {
|
|||
userEndpoint?: URL;
|
||||
};
|
||||
|
||||
export const AppEndpointsContext = createContext<AppEndpoints>({});
|
||||
export const AppDataContext = createContext<AppData>({});
|
||||
|
||||
function AppEndpointsProvider({ children }: Props) {
|
||||
const [endpoints, setEndpoints] = useState<AppEndpoints>({});
|
||||
/** The context provider for the global app data. */
|
||||
function AppDataProvider({ children }: Props) {
|
||||
const [userEndpoint, setUserEndpoint] = useState<URL>();
|
||||
const { currentTenantId } = useContext(TenantsContext);
|
||||
const memorizedContext = useMemo(() => endpoints, [endpoints]);
|
||||
const memorizedContext = useMemo(
|
||||
() =>
|
||||
({
|
||||
userEndpoint,
|
||||
} satisfies AppData),
|
||||
[userEndpoint]
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
const getEndpoint = async () => {
|
||||
|
@ -35,15 +42,13 @@ function AppEndpointsProvider({ children }: Props) {
|
|||
const { user } = await ky
|
||||
.get(new URL(`api/.well-known/endpoints/${currentTenantId}`, adminTenantEndpoint))
|
||||
.json<{ user: string }>();
|
||||
setEndpoints({ userEndpoint: new URL(user) });
|
||||
setUserEndpoint(new URL(user));
|
||||
};
|
||||
|
||||
void getEndpoint();
|
||||
}, [currentTenantId]);
|
||||
|
||||
return (
|
||||
<AppEndpointsContext.Provider value={memorizedContext}>{children}</AppEndpointsContext.Provider>
|
||||
);
|
||||
return <AppDataContext.Provider value={memorizedContext}>{children}</AppDataContext.Provider>;
|
||||
}
|
||||
|
||||
export default AppEndpointsProvider;
|
||||
export default AppDataProvider;
|
|
@ -7,7 +7,7 @@ import { toast } from 'react-hot-toast';
|
|||
import { useTranslation } from 'react-i18next';
|
||||
|
||||
import { getBasename, getManagementApi, requestTimeout } from '@/consts';
|
||||
import { AppEndpointsContext } from '@/contexts/AppEndpointsProvider';
|
||||
import { AppDataContext } from '@/contexts/AppDataProvider';
|
||||
import { TenantsContext } from '@/contexts/TenantsProvider';
|
||||
|
||||
import { useConfirmModal } from './use-confirm-modal';
|
||||
|
@ -106,7 +106,7 @@ export const useStaticApi = ({
|
|||
};
|
||||
|
||||
const useApi = (props: Omit<StaticApiProps, 'prefixUrl'> = {}) => {
|
||||
const { userEndpoint } = useContext(AppEndpointsContext);
|
||||
const { userEndpoint } = useContext(AppDataContext);
|
||||
|
||||
return useStaticApi({ ...props, prefixUrl: userEndpoint });
|
||||
};
|
||||
|
|
|
@ -12,7 +12,7 @@ import { Trans, useTranslation } from 'react-i18next';
|
|||
|
||||
import FormCard from '@/components/FormCard';
|
||||
import { openIdProviderConfigPath } from '@/consts/oidc';
|
||||
import { AppEndpointsContext } from '@/contexts/AppEndpointsProvider';
|
||||
import { AppDataContext } from '@/contexts/AppDataProvider';
|
||||
import CopyToClipboard from '@/ds-components/CopyToClipboard';
|
||||
import DynamicT from '@/ds-components/DynamicT';
|
||||
import FormField from '@/ds-components/FormField';
|
||||
|
@ -30,7 +30,7 @@ type Props = {
|
|||
};
|
||||
|
||||
function AdvancedSettings({ applicationType, oidcConfig }: Props) {
|
||||
const { userEndpoint } = useContext(AppEndpointsContext);
|
||||
const { userEndpoint } = useContext(AppDataContext);
|
||||
const {
|
||||
register,
|
||||
formState: { errors },
|
||||
|
|
|
@ -6,7 +6,7 @@ import type { MDXProps } from 'mdx/types';
|
|||
import type { LazyExoticComponent } from 'react';
|
||||
import { useEffect, useContext, cloneElement, lazy, Suspense, useState } from 'react';
|
||||
|
||||
import { AppEndpointsContext } from '@/contexts/AppEndpointsProvider';
|
||||
import { AppDataContext } from '@/contexts/AppDataProvider';
|
||||
import CodeEditor from '@/ds-components/CodeEditor';
|
||||
import TextLink from '@/ds-components/TextLink';
|
||||
import useCustomDomain from '@/hooks/use-custom-domain';
|
||||
|
@ -56,7 +56,7 @@ function Guide({ app, isCompact, onClose }: Props) {
|
|||
const sdks = app && applicationTypeAndSdkTypeMappings[app.type];
|
||||
const [selectedSdk, setSelectedSdk] = useState<Optional<SupportedSdk>>();
|
||||
const [activeStepIndex, setActiveStepIndex] = useState(-1);
|
||||
const { userEndpoint } = useContext(AppEndpointsContext);
|
||||
const { userEndpoint } = useContext(AppDataContext);
|
||||
const { data: customDomain } = useCustomDomain();
|
||||
const isCustomDomainActive = customDomain?.status === DomainStatus.Active;
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@ import PasswordlessDark from '@/assets/icons/passwordless-dark.svg';
|
|||
import Passwordless from '@/assets/icons/passwordless.svg';
|
||||
import { discordLink } from '@/consts';
|
||||
import { ConnectorsTabs } from '@/consts/page-tabs';
|
||||
import { AppEndpointsContext } from '@/contexts/AppEndpointsProvider';
|
||||
import { AppDataContext } from '@/contexts/AppDataProvider';
|
||||
import useConfigs from '@/hooks/use-configs';
|
||||
import useDocumentationUrl from '@/hooks/use-documentation-url';
|
||||
import useTheme from '@/hooks/use-theme';
|
||||
|
@ -40,7 +40,7 @@ type GetStartedMetadata = {
|
|||
|
||||
const useGetStartedMetadata = () => {
|
||||
const { configs, updateConfigs } = useConfigs();
|
||||
const { userEndpoint } = useContext(AppEndpointsContext);
|
||||
const { userEndpoint } = useContext(AppDataContext);
|
||||
const theme = useTheme();
|
||||
const isLightMode = theme === Theme.Light;
|
||||
const navigate = useNavigate();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { useContext } from 'react';
|
||||
|
||||
import { AppEndpointsContext } from '@/contexts/AppEndpointsProvider';
|
||||
import { AppDataContext } from '@/contexts/AppDataProvider';
|
||||
import CopyToClipboard from '@/ds-components/CopyToClipboard';
|
||||
import DynamicT from '@/ds-components/DynamicT';
|
||||
import Tag from '@/ds-components/Tag';
|
||||
|
@ -8,7 +8,7 @@ import Tag from '@/ds-components/Tag';
|
|||
import * as styles from './index.module.scss';
|
||||
|
||||
function DefaultDomain() {
|
||||
const { userEndpoint } = useContext(AppEndpointsContext);
|
||||
const { userEndpoint } = useContext(AppDataContext);
|
||||
|
||||
if (!userEndpoint) {
|
||||
return null;
|
||||
|
|
Loading…
Add table
Reference in a new issue