From 22e304d1624d9f67003156b64505e0b445b88315 Mon Sep 17 00:00:00 2001 From: runarvestmann Date: Mon, 3 Jun 2024 15:03:15 +0000 Subject: [PATCH] Add project subpage layout to generic list item page --- .../hooks/useLinkResolver/useLinkResolver.ts | 4 + .../[subSlug]/[genericListItemSlug]/index.ts | 4 +- .../[subSlug]/[genericListItemSlug]/index.ts | 12 -- .../[subSlug]/[genericListItemSlug]/index.tsx | 124 ++++++++++++++++++ apps/web/screens/Project/Project.tsx | 19 ++- .../ProjectWrapper/ProjectWrapper.tsx | 1 + 6 files changed, 147 insertions(+), 17 deletions(-) delete mode 100644 apps/web/pages/v/[slug]/[subSlug]/[genericListItemSlug]/index.ts create mode 100644 apps/web/pages/v/[slug]/[subSlug]/[genericListItemSlug]/index.tsx diff --git a/apps/web/hooks/useLinkResolver/useLinkResolver.ts b/apps/web/hooks/useLinkResolver/useLinkResolver.ts index 529826e6674f..338bbb0a8bb4 100644 --- a/apps/web/hooks/useLinkResolver/useLinkResolver.ts +++ b/apps/web/hooks/useLinkResolver/useLinkResolver.ts @@ -43,6 +43,10 @@ export const routesTemplate = { is: '/s/[organization]/[slug]/[listItemSlug]', en: '/en/o/[organization]/[slug]/[listItemSlug]', }, + projectsubpagelistitem: { + is: '/v/[project]/[slug]/[listItemSlug]', + en: '/en/p/[project]/[slug]/[listItemSlug]', + }, aboutsubpage: { is: '/s/stafraent-island/[slug]', en: '', diff --git a/apps/web/pages/en/p/[slug]/[subSlug]/[genericListItemSlug]/index.ts b/apps/web/pages/en/p/[slug]/[subSlug]/[genericListItemSlug]/index.ts index fed923d3a5a9..a0af49de48f0 100644 --- a/apps/web/pages/en/p/[slug]/[subSlug]/[genericListItemSlug]/index.ts +++ b/apps/web/pages/en/p/[slug]/[subSlug]/[genericListItemSlug]/index.ts @@ -1,11 +1,11 @@ import withApollo from '@island.is/web/graphql/withApollo' import { withLocale } from '@island.is/web/i18n' -import GenericListItem from '@island.is/web/screens/GenericList/GenericListItem' +import { Component } from '@island.is/web/pages/v/[slug]/[subSlug]/[genericListItemSlug]' import { getServerSidePropsWrapper } from '@island.is/web/utils/getServerSidePropsWrapper' // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore make web strict -const Screen = withApollo(withLocale('en')(GenericListItem)) +const Screen = withApollo(withLocale('en')(Component)) export default Screen diff --git a/apps/web/pages/v/[slug]/[subSlug]/[genericListItemSlug]/index.ts b/apps/web/pages/v/[slug]/[subSlug]/[genericListItemSlug]/index.ts deleted file mode 100644 index a8e4bdf665b5..000000000000 --- a/apps/web/pages/v/[slug]/[subSlug]/[genericListItemSlug]/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -import withApollo from '@island.is/web/graphql/withApollo' -import { withLocale } from '@island.is/web/i18n' -import GenericListItem from '@island.is/web/screens/GenericList/GenericListItem' -import { getServerSidePropsWrapper } from '@island.is/web/utils/getServerSidePropsWrapper' - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore make web strict -const Screen = withApollo(withLocale('is')(GenericListItem)) - -export default Screen - -export const getServerSideProps = getServerSidePropsWrapper(Screen) diff --git a/apps/web/pages/v/[slug]/[subSlug]/[genericListItemSlug]/index.tsx b/apps/web/pages/v/[slug]/[subSlug]/[genericListItemSlug]/index.tsx new file mode 100644 index 000000000000..f6438099f4fe --- /dev/null +++ b/apps/web/pages/v/[slug]/[subSlug]/[genericListItemSlug]/index.tsx @@ -0,0 +1,124 @@ +import { useMemo } from 'react' +import { useRouter } from 'next/router' + +import { ProjectPage } from '@island.is/web/graphql/schema' +import withApollo from '@island.is/web/graphql/withApollo' +import { useLinkResolver } from '@island.is/web/hooks' +import { useI18n, withLocale } from '@island.is/web/i18n' +import { LayoutProps } from '@island.is/web/layouts/main' +import type { GenericListItemPageProps } from '@island.is/web/screens/GenericList/GenericListItem' +import GenericListItemPage from '@island.is/web/screens/GenericList/GenericListItem' +import SubPageLayout, { + type PageProps, +} from '@island.is/web/screens/Project/Project' +import type { Screen as ScreenType } from '@island.is/web/types' +import { CustomNextError } from '@island.is/web/units/errors' +import { getServerSidePropsWrapper } from '@island.is/web/utils/getServerSidePropsWrapper' + +interface ComponentProps { + parentProps: { + layoutProps: LayoutProps + componentProps: PageProps + } + genericListItemProps: GenericListItemPageProps +} + +export const Component: ScreenType = ({ + parentProps, + genericListItemProps, +}) => { + const { activeLocale } = useI18n() + const router = useRouter() + const { linkResolver } = useLinkResolver() + const backLinkUrl = useMemo(() => { + const pathname = new URL(router.asPath, 'https://island.is').pathname + return pathname.slice(0, pathname.lastIndexOf('/')) + }, [router.asPath]) + + const projectPage = parentProps.componentProps.projectPage as ProjectPage + const subpage = projectPage.projectSubpages.find( + (subpage) => subpage.slug === router.query.subSlug, + ) + + return ( + { + if (subpage.slug === router.query.subSlug) { + return { + ...subpage, + bottomSlices: [], + slices: [], + content: genericListItemProps.item.content, + title: genericListItemProps.item.title, + showTableOfContents: false, + } + } + return subpage + }) ?? [], + }, + }} + /> + ) +} + +Component.getProps = async (ctx) => { + const [parentProps, genericListItemProps] = await Promise.all([ + SubPageLayout.getProps?.(ctx), + GenericListItemPage.getProps?.(ctx), + ]) + + if (!parentProps) { + throw new CustomNextError( + 404, + 'Could not fetch subpage layout for generic list item', + ) + } + if (!genericListItemProps) { + throw new CustomNextError(404, 'Could not fetch generic list item props') + } + + return { + parentProps, + genericListItemProps, + } +} + +// eslint-disable-next-line @typescript-eslint/ban-ts-comment +// @ts-ignore make web strict +const Screen = withApollo(withLocale('is')(Component)) + +export default Screen + +export const getServerSideProps = getServerSidePropsWrapper(Screen) diff --git a/apps/web/screens/Project/Project.tsx b/apps/web/screens/Project/Project.tsx index cc5ca0380ccc..6f9ee35504db 100644 --- a/apps/web/screens/Project/Project.tsx +++ b/apps/web/screens/Project/Project.tsx @@ -46,7 +46,7 @@ import { ProjectFooter } from './components/ProjectFooter' import { ProjectWrapper } from './components/ProjectWrapper' import { getThemeConfig } from './utils' -interface PageProps { +export interface PageProps { projectPage: Query['getProjectPage'] namespace: Record projectNamespace: Record @@ -54,6 +54,9 @@ interface PageProps { stepOptionsFromNamespace: { data: Record[]; slug: string }[] stepperNamespace: Record locale: Locale + backLink?: { url: string; text: string } + customContentfulIds?: (string | undefined)[] + customBreadcrumbItems?: BreadCrumbItem[] } const ProjectPage: Screen = ({ projectPage, @@ -62,6 +65,9 @@ const ProjectPage: Screen = ({ stepperNamespace, stepOptionsFromNamespace, locale, + backLink, + customContentfulIds, + customBreadcrumbItems, }) => { const n = useNamespace(namespace) const p = useNamespace(projectNamespace) @@ -77,7 +83,11 @@ const ProjectPage: Screen = ({ [router.query.subSlug, projectPage?.projectSubpages], ) - useContentfulId(projectPage?.id, subpage?.id) + const contentfulIds = customContentfulIds + ? customContentfulIds + : [projectPage?.id, subpage?.id] + + useContentfulId(...contentfulIds) const baseRouterPath = router.asPath.split('?')[0].split('#')[0] @@ -116,7 +126,9 @@ const ProjectPage: Screen = ({ } }, [renderSlicesAsTabs, subpage, router.asPath]) - const breadCrumbs: BreadCrumbItem[] = !subpage + const breadCrumbs: BreadCrumbItem[] = customBreadcrumbItems + ? customBreadcrumbItems + : !subpage ? [] : [ { @@ -157,6 +169,7 @@ const ProjectPage: Screen = ({ breadcrumbItems={breadCrumbs} sidebarNavigationTitle={navigationTitle} withSidebar={projectPage?.sidebar} + backLink={backLink} > {!subpage && shouldDisplayWebReader && (