0
Fork 0
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:
Charles Zhao 2023-08-20 02:05:29 -05:00 committed by GitHub
parent 4a532a358d
commit 5b1039267f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 70 additions and 54 deletions

View file

@ -55,6 +55,14 @@
margin-top: _.unit(6);
}
.notFound {
width: 100%;
svg {
margin-top: 10%;
}
}
.actionBar {
position: absolute;
inset: auto 0 0 0;

View file

@ -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

View file

@ -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}>