Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add 404 pages and fix styling on the 404 html template #2382

Merged
merged 9 commits into from
Sep 6, 2024
186 changes: 116 additions & 70 deletions extensions/apps/antenna/src/components/app-routes/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import BeamPage from '../pages/entry-page/beam-page';
import ReflectionPage from '../pages/entry-page/reflection-page';
import TagFeedPage from '../pages/tag-feed-page/tag-feed-page';
import EditorPage from '../pages/editor-page/editor-page';
import ErrorComponent from './error-component';
import EntrySectionLoading from '../pages/entry-page/entry-section-loading';
import routes, {
GLOBAL_ANTENNA,
Expand All @@ -24,6 +23,7 @@ import {
Outlet,
defer,
Await,
CatchBoundary,
} from '@tanstack/react-router';
import { ICreateRouter, IRouterContext } from '@akashaorg/typings/lib/ui';
import {
Expand All @@ -38,9 +38,11 @@ import {
selectReflectionNode,
} from './data-loaders';
import { mapBeamEntryData, mapReflectEntryData } from '@akashaorg/ui-awf-hooks';
import { NotFoundComponent } from './not-found-component';

const rootRoute = createRootRouteWithContext<IRouterContext>()({
component: Outlet,
notFoundComponent: () => <NotFoundComponent />,
});

const defaultRoute = createRoute({
Expand All @@ -54,22 +56,33 @@ const defaultRoute = createRoute({
const antennaRoute = createRoute({
getParentRoute: () => rootRoute,
path: routes[GLOBAL_ANTENNA],
notFoundComponent: () => <NotFoundComponent />,
component: () => {
return <GlobalAntennaPage />;
return (
<CatchBoundary getResetKey={() => 'antenna_reset'} errorComponent={NotFoundComponent}>
<GlobalAntennaPage />
</CatchBoundary>
);
},
});

const myAntennaRoute = createRoute({
getParentRoute: () => rootRoute,
path: routes[MY_ANTENNA],
notFoundComponent: () => <NotFoundComponent />,
component: () => {
return <MyAntennaPage />;
return (
<CatchBoundary getResetKey={() => 'myAntenna_reset'} errorComponent={NotFoundComponent}>
<MyAntennaPage />
</CatchBoundary>
);
},
});

const beamRoute = createRoute({
getParentRoute: () => rootRoute,
path: `${routes[BEAM]}/$beamId`,
notFoundComponent: () => <NotFoundComponent />,
loader: ({ context, params }) => ({
beam: defer(getBeamById({ apolloClient: context.apolloClient, beamId: params.beamId })),
beamStream: defer(
Expand All @@ -83,60 +96,69 @@ const beamRoute = createRoute({
const { beamId } = beamRoute.useParams();
const { beam, beamStream } = beamRoute.useLoaderData();
return (
<Suspense fallback={<EntrySectionLoading />}>
<Await promise={beamStream}>
{({ data: beamStreamData }) => (
<Await promise={beam}>
{({ data: beamById }) => {
return (
<BeamPage
beamId={beamId}
isActive={selectBeamActiveField(beamStreamData)}
beamData={mapBeamEntryData(selectBeamNode(beamById))}
beamStatus={selectBeamStatusField(beamStreamData)}
/>
);
}}
</Await>
)}
</Await>
</Suspense>
<CatchBoundary getResetKey={() => 'beamRoute_reset'} errorComponent={NotFoundComponent}>
<Suspense fallback={<EntrySectionLoading />}>
<Await promise={beamStream}>
{({ data: beamStreamData }) => (
<Await promise={beam}>
{({ data: beamById }) => {
return (
<BeamPage
beamId={beamId}
isActive={selectBeamActiveField(beamStreamData)}
beamData={mapBeamEntryData(selectBeamNode(beamById))}
beamStatus={selectBeamStatusField(beamStreamData)}
/>
);
}}
</Await>
)}
</Await>
</Suspense>
</CatchBoundary>
);
},
});

const beamReflectRoute = createRoute({
getParentRoute: () => beamRoute,
path: routes[REFLECT],
notFoundComponent: () => <NotFoundComponent />,
component: () => {
const { beamId } = beamReflectRoute.useParams();
const { beam, beamStream } = beamRoute.useLoaderData();
return (
<Suspense fallback={<EntrySectionLoading />}>
<Await promise={beamStream}>
{({ data: beamStreamData }) => (
<Await promise={beam}>
{({ data: beamById }) => {
return (
<BeamPage
beamId={beamId}
isActive={selectBeamActiveField(beamStreamData)}
beamData={mapBeamEntryData(selectBeamNode(beamById))}
beamStatus={selectBeamStatusField(beamStreamData)}
/>
);
}}
</Await>
)}
</Await>
</Suspense>
<CatchBoundary
getResetKey={() => 'beamReflectRoute_reset'}
errorComponent={NotFoundComponent}
>
<Suspense fallback={<EntrySectionLoading />}>
<Await promise={beamStream}>
{({ data: beamStreamData }) => (
<Await promise={beam}>
{({ data: beamById }) => {
return (
<BeamPage
beamId={beamId}
isActive={selectBeamActiveField(beamStreamData)}
beamData={mapBeamEntryData(selectBeamNode(beamById))}
beamStatus={selectBeamStatusField(beamStreamData)}
/>
);
}}
</Await>
)}
</Await>
</Suspense>
</CatchBoundary>
);
},
});

const reflectionsRoute = createRoute({
getParentRoute: () => rootRoute,
path: `${routes[REFLECTION]}/$reflectionId`,
notFoundComponent: () => <NotFoundComponent />,
loader: ({ context, params }) => ({
reflection: defer(
getReflectionById({
Expand All @@ -154,62 +176,83 @@ const reflectionsRoute = createRoute({
component: () => {
const { reflection, reflectionStream } = reflectionsRoute.useLoaderData();
return (
<Suspense fallback={<EntrySectionLoading />}>
<Await promise={reflectionStream}>
{({ data: reflectionStreamData }) => (
<Await promise={reflection}>
{({ data: reflectionById }) => (
<ReflectionPage
isActive={selectReflectionActiveField(reflectionStreamData)}
reflectionData={mapReflectEntryData(selectReflectionNode(reflectionById))}
/>
)}
</Await>
)}
</Await>
</Suspense>
<CatchBoundary
getResetKey={() => 'reflectionsRoute_reset'}
errorComponent={NotFoundComponent}
>
<Suspense fallback={<EntrySectionLoading />}>
<Await promise={reflectionStream}>
{({ data: reflectionStreamData }) => (
<Await promise={reflection}>
{({ data: reflectionById }) => (
<ReflectionPage
isActive={selectReflectionActiveField(reflectionStreamData)}
reflectionData={mapReflectEntryData(selectReflectionNode(reflectionById))}
/>
)}
</Await>
)}
</Await>
</Suspense>
</CatchBoundary>
);
},
});

const reflectionsReflectRoute = createRoute({
getParentRoute: () => reflectionsRoute,
path: routes[REFLECT],
notFoundComponent: () => <NotFoundComponent />,
component: () => {
const { reflection, reflectionStream } = reflectionsRoute.useLoaderData();
return (
<Suspense fallback={<EntrySectionLoading />}>
<Await promise={reflectionStream}>
{({ data: reflectionStreamData }) => (
<Await promise={reflection}>
{({ data: reflectionById }) => (
<ReflectionPage
isActive={selectReflectionActiveField(reflectionStreamData)}
reflectionData={mapReflectEntryData(selectReflectionNode(reflectionById))}
/>
)}
</Await>
)}
</Await>
</Suspense>
<CatchBoundary
getResetKey={() => 'reflectionsReflect_reset'}
errorComponent={NotFoundComponent}
>
<Suspense fallback={<EntrySectionLoading />}>
<Await promise={reflectionStream}>
{({ data: reflectionStreamData }) => (
<Await promise={reflection}>
{({ data: reflectionById }) => (
<ReflectionPage
isActive={selectReflectionActiveField(reflectionStreamData)}
reflectionData={mapReflectEntryData(selectReflectionNode(reflectionById))}
/>
)}
</Await>
)}
</Await>
</Suspense>
</CatchBoundary>
);
},
});

const tagFeedRoute = createRoute({
getParentRoute: () => rootRoute,
path: `${routes[TAGS]}/$tagName`,
notFoundComponent: () => <NotFoundComponent />,
component: () => {
const { tagName } = tagFeedRoute.useParams();
return <TagFeedPage tagName={tagName} />;
return (
<CatchBoundary getResetKey={() => 'tagFeed_reset'} errorComponent={NotFoundComponent}>
<TagFeedPage tagName={tagName} />
</CatchBoundary>
);
},
});

const editorRoute = createRoute({
getParentRoute: () => rootRoute,
path: routes[EDITOR],
notFoundComponent: () => <NotFoundComponent />,
component: () => {
return <EditorPage />;
return (
<CatchBoundary getResetKey={() => 'editor_reset'} errorComponent={NotFoundComponent}>
<EditorPage />
</CatchBoundary>
);
},
});

Expand All @@ -230,7 +273,10 @@ export const router = ({ baseRouteName, apolloClient }: ICreateRouter) =>
context: {
apolloClient,
},
// errors thrown in the route loaders are caught here.
// for a more granular errors, every loader should have an error handler
// by default we'll treat loader errors as resource/page not found
defaultErrorComponent: ({ error }) => {
return <ErrorComponent error={(error as unknown as Error).message} />;
return <NotFoundComponent error={error} />;
},
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React, { useEffect } from 'react';
import ErrorLoader from '@akashaorg/design-system-core/lib/components/ErrorLoader';
import { useTranslation } from 'react-i18next';
import { useRootComponentProps } from '@akashaorg/ui-awf-hooks';
import Button from '@akashaorg/design-system-core/lib/components/Button';

export const NotFoundComponent = (props: { error?: Error; reset?: (key: string) => void }) => {
const { t } = useTranslation();
const { getRoutingPlugin, logger, worldConfig } = useRootComponentProps();
SeverS marked this conversation as resolved.
Show resolved Hide resolved

useEffect(() => {
if (props.error) {
logger.warn(`Error in Antenna app: ${props.error}`);
}
}, [logger, props.error]);

const navigateHome = () => {
getRoutingPlugin().navigateTo({
SeverS marked this conversation as resolved.
Show resolved Hide resolved
appName: worldConfig.homepageApp,
getNavigationUrl: () => '/',
});
};

return (
<ErrorLoader
type="page-not-found"
title={`${t('Oops!')} ${t('Page not found')}`}
details={t(
'This error means that the webpage you were trying to reach does not exist on {{worldTitle}}. It may have been moved, deleted, or the URL might be incorrect.',
{ worldTitle: worldConfig.title },
)}
>
<Button label={t('Home')} variant="primary" onClick={navigateHome} />
</ErrorLoader>
);
};
Loading