mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
fix(console): invalid guide url should show 404 not found (#4367)
This commit is contained in:
parent
4a532a358d
commit
5b1039267f
3 changed files with 70 additions and 54 deletions
|
@ -55,6 +55,14 @@
|
|||
margin-top: _.unit(6);
|
||||
}
|
||||
|
||||
.notFound {
|
||||
width: 100%;
|
||||
|
||||
svg {
|
||||
margin-top: 10%;
|
||||
}
|
||||
}
|
||||
|
||||
.actionBar {
|
||||
position: absolute;
|
||||
inset: auto 0 0 0;
|
||||
|
|
|
@ -12,6 +12,7 @@ import CodeEditor from '@/ds-components/CodeEditor';
|
|||
import TextLink from '@/ds-components/TextLink';
|
||||
import useCustomDomain from '@/hooks/use-custom-domain';
|
||||
import DetailsSummary from '@/mdx-components/DetailsSummary';
|
||||
import NotFound from '@/pages/NotFound';
|
||||
|
||||
import GuideHeader from '../GuideHeader';
|
||||
import StepsSkeleton from '../StepsSkeleton';
|
||||
|
@ -50,7 +51,7 @@ export const GuideContext = createContext<GuideContextType>({
|
|||
type Props = {
|
||||
className?: string;
|
||||
guideId: string;
|
||||
app?: ApplicationResponse;
|
||||
app: ApplicationResponse;
|
||||
isCompact?: boolean;
|
||||
onClose: () => void;
|
||||
};
|
||||
|
@ -61,28 +62,26 @@ function Guide({ className, guideId, app, isCompact, onClose }: Props) {
|
|||
const isCustomDomainActive = customDomain?.status === DomainStatus.Active;
|
||||
const guide = guides.find(({ id }) => id === guideId);
|
||||
|
||||
if (!app || !guide) {
|
||||
throw new Error('Invalid app or guide');
|
||||
}
|
||||
|
||||
const GuideComponent = guide.Component;
|
||||
const GuideComponent = guide?.Component;
|
||||
|
||||
const memorizedContext = useMemo(
|
||||
() =>
|
||||
({
|
||||
metadata: guide.metadata,
|
||||
Logo: guide.Logo,
|
||||
app,
|
||||
endpoint: tenantEndpoint?.toString() ?? '',
|
||||
alternativeEndpoint: conditional(isCustomDomainActive && tenantEndpoint?.toString()),
|
||||
redirectUris: app.oidcClientMetadata.redirectUris,
|
||||
postLogoutRedirectUris: app.oidcClientMetadata.postLogoutRedirectUris,
|
||||
isCompact: Boolean(isCompact),
|
||||
sampleUrls: {
|
||||
origin: 'http://localhost:3001/',
|
||||
callback: 'http://localhost:3001/callback',
|
||||
},
|
||||
}) satisfies GuideContextType,
|
||||
conditional(
|
||||
!!guide && {
|
||||
metadata: guide.metadata,
|
||||
Logo: guide.Logo,
|
||||
app,
|
||||
endpoint: tenantEndpoint?.toString() ?? '',
|
||||
alternativeEndpoint: conditional(isCustomDomainActive && tenantEndpoint?.toString()),
|
||||
redirectUris: app.oidcClientMetadata.redirectUris,
|
||||
postLogoutRedirectUris: app.oidcClientMetadata.postLogoutRedirectUris,
|
||||
isCompact: Boolean(isCompact),
|
||||
sampleUrls: {
|
||||
origin: 'http://localhost:3001/',
|
||||
callback: 'http://localhost:3001/callback',
|
||||
},
|
||||
}
|
||||
) satisfies GuideContextType | undefined,
|
||||
[guide, app, tenantEndpoint, isCustomDomainActive, isCompact]
|
||||
);
|
||||
|
||||
|
@ -90,39 +89,43 @@ function Guide({ className, guideId, app, isCompact, onClose }: Props) {
|
|||
<div className={classNames(styles.container, className)}>
|
||||
{!isCompact && <GuideHeader onClose={onClose} />}
|
||||
<div className={styles.content}>
|
||||
<GuideContext.Provider value={memorizedContext}>
|
||||
<MDXProvider
|
||||
components={{
|
||||
code: ({ className, children }) => {
|
||||
const [, language] = /language-(\w+)/.exec(String(className ?? '')) ?? [];
|
||||
{memorizedContext ? (
|
||||
<GuideContext.Provider value={memorizedContext}>
|
||||
<MDXProvider
|
||||
components={{
|
||||
code: ({ className, children }) => {
|
||||
const [, language] = /language-(\w+)/.exec(String(className ?? '')) ?? [];
|
||||
|
||||
return language ? (
|
||||
<CodeEditor
|
||||
isReadonly
|
||||
// We need to transform `ts` to `typescript` for prismjs, and
|
||||
// it's weird since it worked in the original Guide component.
|
||||
// To be investigated.
|
||||
language={language === 'ts' ? 'typescript' : language}
|
||||
value={String(children).trimEnd()}
|
||||
/>
|
||||
) : (
|
||||
<code>{String(children).trimEnd()}</code>
|
||||
);
|
||||
},
|
||||
a: ({ children, ...props }) => (
|
||||
<TextLink {...props} target="_blank" rel="noopener noreferrer">
|
||||
{children}
|
||||
</TextLink>
|
||||
),
|
||||
details: DetailsSummary,
|
||||
}}
|
||||
>
|
||||
<Suspense fallback={<StepsSkeleton />}>
|
||||
{tenantEndpoint && <GuideComponent {...memorizedContext} />}
|
||||
</Suspense>
|
||||
</MDXProvider>
|
||||
</GuideContext.Provider>
|
||||
{!isCompact && (
|
||||
return language ? (
|
||||
<CodeEditor
|
||||
isReadonly
|
||||
// We need to transform `ts` to `typescript` for prismjs, and
|
||||
// it's weird since it worked in the original Guide component.
|
||||
// To be investigated.
|
||||
language={language === 'ts' ? 'typescript' : language}
|
||||
value={String(children).trimEnd()}
|
||||
/>
|
||||
) : (
|
||||
<code>{String(children).trimEnd()}</code>
|
||||
);
|
||||
},
|
||||
a: ({ children, ...props }) => (
|
||||
<TextLink {...props} target="_blank" rel="noopener noreferrer">
|
||||
{children}
|
||||
</TextLink>
|
||||
),
|
||||
details: DetailsSummary,
|
||||
}}
|
||||
>
|
||||
<Suspense fallback={<StepsSkeleton />}>
|
||||
{tenantEndpoint && GuideComponent && <GuideComponent {...memorizedContext} />}
|
||||
</Suspense>
|
||||
</MDXProvider>
|
||||
</GuideContext.Provider>
|
||||
) : (
|
||||
<NotFound className={styles.notFound} />
|
||||
)}
|
||||
{!isCompact && memorizedContext && (
|
||||
<nav className={styles.actionBar}>
|
||||
<div className={styles.layout}>
|
||||
<Button
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { Theme } from '@logto/schemas';
|
||||
import classNames from 'classnames';
|
||||
import { useTranslation } from 'react-i18next';
|
||||
import { useLocation } from 'react-router-dom';
|
||||
|
||||
|
@ -10,13 +11,17 @@ import useTheme from '@/hooks/use-theme';
|
|||
|
||||
import * as styles from './index.module.scss';
|
||||
|
||||
function NotFound() {
|
||||
type Props = {
|
||||
className?: string;
|
||||
};
|
||||
|
||||
function NotFound({ className }: Props) {
|
||||
const { t } = useTranslation(undefined, { keyPrefix: 'admin_console' });
|
||||
const theme = useTheme();
|
||||
const location = useLocation();
|
||||
|
||||
return (
|
||||
<div className={styles.container}>
|
||||
<div className={classNames(styles.container, className)}>
|
||||
{/* Don't track "not found" for the root path as it will be redirected. */}
|
||||
<PageMeta titleKey="errors.page_not_found" trackPageView={location.pathname !== '/'} />
|
||||
<Card className={styles.content}>
|
||||
|
|
Loading…
Reference in a new issue