Skip to content

Commit

Permalink
feat(web): Organization page with "standalone" theme - Level 1 sitemap (
Browse files Browse the repository at this point in the history
#17068)

* Level 1 sitemap

* Reduce include depth

* Add seo title

* Error validate when fetching parent subpages

* Add explicit entryId field

* Reverse conditional

* Add translation fallbacks

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
  • Loading branch information
RunarVestmann and kodiakhq[bot] authored Nov 28, 2024
1 parent a40be29 commit 7f80869
Show file tree
Hide file tree
Showing 9 changed files with 372 additions and 8 deletions.
7 changes: 5 additions & 2 deletions apps/web/components/LanguageToggler/LanguageToggler.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -188,8 +188,11 @@ export const LanguageToggler = ({
<DialogPrompt
baseId={dialogId}
initialVisibility={true}
title={gn('switchToEnglishModalTitle')}
description={gn('switchToEnglishModalText')}
title={gn('switchToEnglishModalTitle', 'Translation not available')}
description={gn(
'switchToEnglishModalText',
'The page you are viewing does not have an English translation yet',
)}
ariaLabel="Confirm switching to english"
disclosureElement={Disclosure}
onConfirm={() => {
Expand Down
35 changes: 30 additions & 5 deletions apps/web/pages/s/[...slugs]/index.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { type FC } from 'react'

import {
import type {
Query,
QueryGetOrganizationPageArgs,
} from '@island.is/web/graphql/schema'
Expand Down Expand Up @@ -31,6 +31,9 @@ import PublishedMaterial, {
import StandaloneHome, {
type StandaloneHomeProps,
} from '@island.is/web/screens/Organization/Standalone/Home'
import StandaloneLevel1Sitemap, {
type StandaloneLevel1SitemapProps,
} from '@island.is/web/screens/Organization/Standalone/Level1Sitemap'
import StandaloneParentSubpage, {
StandaloneParentSubpageProps,
} from '@island.is/web/screens/Organization/Standalone/ParentSubpage'
Expand All @@ -46,6 +49,7 @@ enum PageType {
FRONTPAGE = 'frontpage',
STANDALONE_FRONTPAGE = 'standalone-frontpage',
STANDALONE_PARENT_SUBPAGE = 'standalone-parent-subpage',
STANDALONE_LEVEL1_SITEMAP = 'standalone-level1-sitemap',
SUBPAGE = 'subpage',
ALL_NEWS = 'news',
PUBLISHED_MATERIAL = 'published-material',
Expand All @@ -62,6 +66,9 @@ const pageMap: Record<PageType, FC<any>> = {
[PageType.STANDALONE_PARENT_SUBPAGE]: (props) => (
<StandaloneParentSubpage {...props} />
),
[PageType.STANDALONE_LEVEL1_SITEMAP]: (props) => (
<StandaloneLevel1Sitemap {...props} />
),
[PageType.SUBPAGE]: (props) => <SubPage {...props} />,
[PageType.ALL_NEWS]: (props) => <OrganizationNewsList {...props} />,
[PageType.PUBLISHED_MATERIAL]: (props) => <PublishedMaterial {...props} />,
Expand Down Expand Up @@ -90,6 +97,10 @@ interface Props {
type: PageType.STANDALONE_PARENT_SUBPAGE
props: StandaloneParentSubpageProps
}
| {
type: PageType.STANDALONE_LEVEL1_SITEMAP
props: StandaloneLevel1SitemapProps
}
| {
type: PageType.SUBPAGE
props: {
Expand Down Expand Up @@ -164,10 +175,10 @@ Component.getProps = async (context) => {

const modifiedContext = { ...context, organizationPage }

const STANDALONE_THEME = 'standalone'
const isStandaloneTheme = organizationPage.theme === 'standalone'

if (slugs.length === 1) {
if (organizationPage.theme === STANDALONE_THEME) {
if (isStandaloneTheme) {
return {
page: {
type: PageType.STANDALONE_FRONTPAGE,
Expand Down Expand Up @@ -237,7 +248,21 @@ Component.getProps = async (context) => {
}
}

if (organizationPage.theme === STANDALONE_THEME) {
if (
isStandaloneTheme &&
organizationPage.topLevelNavigation?.links.some(
(link) => slugs[1] === link.href.split('/').pop(),
)
) {
return {
page: {
type: PageType.STANDALONE_LEVEL1_SITEMAP,
props: await StandaloneLevel1Sitemap.getProps(modifiedContext),
},
}
}

if (isStandaloneTheme) {
return {
page: {
type: PageType.STANDALONE_PARENT_SUBPAGE,
Expand Down Expand Up @@ -291,7 +316,7 @@ Component.getProps = async (context) => {
}
}

if (organizationPage.theme === STANDALONE_THEME) {
if (isStandaloneTheme) {
return {
page: {
type: PageType.STANDALONE_PARENT_SUBPAGE,
Expand Down
161 changes: 161 additions & 0 deletions apps/web/screens/Organization/Standalone/Level1Sitemap.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import {
CategoryCard,
GridColumn,
GridContainer,
GridRow,
Stack,
} from '@island.is/island-ui/core'
import { Text } from '@island.is/island-ui/core'
import type { SpanType } from '@island.is/island-ui/core/types'
import {
ContentLanguage,
OrganizationPage,
Query,
QueryGetOrganizationPageArgs,
QueryGetOrganizationPageStandaloneSitemapLevel1Args,
} from '@island.is/web/graphql/schema'
import useContentfulId from '@island.is/web/hooks/useContentfulId'
import { StandaloneLayout } from '@island.is/web/layouts/organization/standalone'
import type { Screen, ScreenContext } from '@island.is/web/types'
import { CustomNextError } from '@island.is/web/units/errors'

import {
GET_ORGANIZATION_PAGE_QUERY,
GET_ORGANIZATION_PAGE_STANDALONE_SITEMAP_LEVEL1_QUERY,
} from '../../queries'

const GRID_COLUMN_SPAN: SpanType = ['1/1', '1/1', '1/1', '1/2', '1/3']

const LanguageToggleSetup = (props: { ids: string[] }) => {
useContentfulId(...props.ids)
return null
}

type StandaloneLevel1SitemapScreenContext = ScreenContext & {
organizationPage?: Query['getOrganizationPage']
}

export interface StandaloneLevel1SitemapProps {
organizationPage: OrganizationPage
categoryTitle: string
items: {
label: string
href: string
description?: string | null
}[]
}

const StandaloneLevel1Sitemap: Screen<
StandaloneLevel1SitemapProps,
StandaloneLevel1SitemapScreenContext
> = ({ organizationPage, categoryTitle, items }) => {
return (
<StandaloneLayout
organizationPage={organizationPage}
seo={{
title: `${categoryTitle} | ${organizationPage.title}`,
}}
>
<LanguageToggleSetup ids={[organizationPage.id]} />
<GridContainer>
<GridRow>
<GridColumn span={['9/9', '9/9', '7/9']} offset={['0', '0', '1/9']}>
<Stack space={3}>
<Text variant="h1" as="h1">
{categoryTitle}
</Text>
<GridRow rowGap={3}>
{items.map(({ label, description, href }, index) => (
<GridColumn span={GRID_COLUMN_SPAN} key={index}>
<CategoryCard
heading={label}
headingAs="h2"
headingVariant="h3"
text={description ?? ''}
href={href}
/>
</GridColumn>
))}
</GridRow>
</Stack>
</GridColumn>
</GridRow>
</GridContainer>
</StandaloneLayout>
)
}

StandaloneLevel1Sitemap.getProps = async ({
apolloClient,
locale,
query,
organizationPage,
}) => {
const [organizationPageSlug, categorySlug] = (query.slugs ?? []) as string[]

const [
{
data: { getOrganizationPage },
},
{
data: { getOrganizationPageStandaloneSitemapLevel1 },
},
] = await Promise.all([
!organizationPage
? apolloClient.query<Query, QueryGetOrganizationPageArgs>({
query: GET_ORGANIZATION_PAGE_QUERY,
variables: {
input: {
slug: organizationPageSlug,
lang: locale as ContentLanguage,
},
},
})
: {
data: { getOrganizationPage: organizationPage },
},
apolloClient.query<
Query,
QueryGetOrganizationPageStandaloneSitemapLevel1Args
>({
query: GET_ORGANIZATION_PAGE_STANDALONE_SITEMAP_LEVEL1_QUERY,
variables: {
input: {
organizationPageSlug,
categorySlug,
lang: locale as ContentLanguage,
},
},
}),
])

if (!getOrganizationPage) {
throw new CustomNextError(404, 'Organization page was not found')
}

if (!getOrganizationPageStandaloneSitemapLevel1) {
throw new CustomNextError(
404,
'Organization page standalone level 1 sitemap was not found',
)
}

const categoryTitle = organizationPage?.topLevelNavigation?.links.find(
(link) => categorySlug === link.href.split('/').pop(),
)?.label

if (!categoryTitle) {
throw new CustomNextError(
404,
'Organization page standalone level 1 category was not found',
)
}

return {
organizationPage: getOrganizationPage,
categoryTitle,
items: getOrganizationPageStandaloneSitemapLevel1.childLinks,
}
}

export default StandaloneLevel1Sitemap
7 changes: 6 additions & 1 deletion apps/web/screens/Organization/Standalone/ParentSubpage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,12 @@ const StandaloneParentSubpage: Screen<
const { linkResolver } = useLinkResolver()

return (
<StandaloneLayout organizationPage={organizationPage}>
<StandaloneLayout
organizationPage={organizationPage}
seo={{
title: `${subpage.title} | ${organizationPage.title}`,
}}
>
<LanguageToggleSetup
ids={[organizationPage.id, parentSubpage.id, subpage.id]}
/>
Expand Down
14 changes: 14 additions & 0 deletions apps/web/screens/queries/Organization.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -431,3 +431,17 @@ export const GET_ORGANIZATION_PARENT_SUBPAGE_QUERY = gql`
}
}
`

export const GET_ORGANIZATION_PAGE_STANDALONE_SITEMAP_LEVEL1_QUERY = gql`
query GetOrganizationPageStandaloneSitemapLevel1Query(
$input: GetOrganizationPageStandaloneSitemapLevel1Input!
) {
getOrganizationPageStandaloneSitemapLevel1(input: $input) {
childLinks {
label
href
description
}
}
}
`
Loading

0 comments on commit 7f80869

Please sign in to comment.