-
Notifications
You must be signed in to change notification settings - Fork 6
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #713 from MinBZK/termen-and-publications
Fix termen pages SEO and add publicaties page
- Loading branch information
Showing
21 changed files
with
836 additions
and
126 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"web": patch | ||
--- | ||
|
||
Added SEO tags for `/termen/*` pages |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"web": minor | ||
--- | ||
|
||
Added `publicaties` page |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
--- | ||
"web": minor | ||
"cms": minor | ||
--- | ||
|
||
Added `publication` content type |
58 changes: 58 additions & 0 deletions
58
apps/cms/src/api/publication/content-types/publication/schema.json
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
{ | ||
"kind": "collectionType", | ||
"collectionName": "publications", | ||
"info": { | ||
"singularName": "publication", | ||
"pluralName": "publications", | ||
"displayName": "Publication", | ||
"description": "" | ||
}, | ||
"options": { | ||
"draftAndPublish": true | ||
}, | ||
"pluginOptions": {}, | ||
"attributes": { | ||
"title": { | ||
"type": "string" | ||
}, | ||
"summary": { | ||
"type": "text" | ||
}, | ||
"content": { | ||
"type": "richtext" | ||
}, | ||
"tags": { | ||
"type": "text" | ||
}, | ||
"slug": { | ||
"type": "uid", | ||
"targetField": "title" | ||
}, | ||
"authors": { | ||
"type": "text" | ||
}, | ||
"location": { | ||
"type": "string" | ||
}, | ||
"file": { | ||
"type": "media", | ||
"multiple": false, | ||
"required": false, | ||
"allowedTypes": [ | ||
"images", | ||
"videos", | ||
"audios", | ||
"files" | ||
] | ||
}, | ||
"cite": { | ||
"type": "text" | ||
}, | ||
"originalSource": { | ||
"type": "string" | ||
}, | ||
"publicationDate": { | ||
"type": "date" | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** | ||
* publication controller | ||
*/ | ||
|
||
import { factories } from '@strapi/strapi' | ||
|
||
export default factories.createCoreController('api::publication.publication'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** | ||
* publication router | ||
*/ | ||
|
||
import { factories } from '@strapi/strapi'; | ||
|
||
export default factories.createCoreRouter('api::publication.publication'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
/** | ||
* publication service | ||
*/ | ||
|
||
import { factories } from '@strapi/strapi'; | ||
|
||
export default factories.createCoreService('api::publication.publication'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
15 changes: 15 additions & 0 deletions
15
apps/web/src/app/publicaties/[slug]/copy-cite-to-clipboard.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
'use client'; | ||
|
||
import { Button } from '@/components/button'; | ||
import { IconClipboard } from '@tabler/icons-react'; | ||
import { CopyToClipboard } from 'react-copy-to-clipboard'; | ||
|
||
interface Props { | ||
text: string; | ||
} | ||
|
||
export const CopyCiteToClipboard: React.FC<Props> = ({ text }) => ( | ||
<CopyToClipboard text={text}> | ||
<Button startIcon={<IconClipboard />}>Kopiëren naar klembord</Button> | ||
</CopyToClipboard> | ||
); |
19 changes: 19 additions & 0 deletions
19
apps/web/src/app/publicaties/[slug]/download/get-publication-file-by-slug.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { db } from '@/drizzle/db'; | ||
import { files, filesRelatedMorphs, publications } from '@/drizzle/schema'; | ||
import { and, eq } from 'drizzle-orm'; | ||
|
||
interface Args { | ||
slug: string; | ||
} | ||
|
||
export async function getPublicationFileBySlug({ slug }: Args) { | ||
const [result] = await db | ||
.select({ file: files }) | ||
.from(publications) | ||
.leftJoin(filesRelatedMorphs, eq(publications.id, filesRelatedMorphs.relatedId)) | ||
.leftJoin(files, eq(files.id, filesRelatedMorphs.fileId)) | ||
.where(and(eq(publications.slug, slug), eq(filesRelatedMorphs.relatedType, 'api::publication.publication'))) | ||
.limit(1); | ||
|
||
return result.file; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import { resolveCmsImage } from '@/common/resolve-cms-image'; | ||
import slugify from '@sindresorhus/slugify'; | ||
import { NextRequest } from 'next/server'; | ||
import { getPublicationFileBySlug } from './get-publication-file-by-slug'; | ||
|
||
export async function GET(req: NextRequest, { params }: { params: { slug: string } }) { | ||
const file = await getPublicationFileBySlug({ slug: params.slug }); | ||
|
||
const fetchResponse = await fetch(resolveCmsImage(file as any), { | ||
method: 'GET', | ||
}); | ||
|
||
const headers = new Headers(); | ||
|
||
headers.set('Content-Disposition', `attachment; filename="${slugify(params.slug)}${file?.ext}"`); | ||
headers.set('Content-Type', file?.mime || ''); | ||
|
||
return new Response(fetchResponse.body, { | ||
headers, | ||
status: fetchResponse.status, | ||
}); | ||
} |
13 changes: 13 additions & 0 deletions
13
apps/web/src/app/publicaties/[slug]/get-publication-by-slug.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
import { db } from '@/drizzle/db'; | ||
import { publications } from '@/drizzle/schema'; | ||
import { eq } from 'drizzle-orm'; | ||
|
||
interface Args { | ||
slug: string; | ||
} | ||
|
||
export async function getPublicationBySlug({ slug }: Args) { | ||
const [publication] = await db.select().from(publications).where(eq(publications.slug, slug)).limit(1); | ||
|
||
return publication; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
import { EnhanceMenuBreadcrumbs } from '@/app/menu-breadcrumbs'; | ||
import { Button } from '@/components/button'; | ||
import { Container } from '@/components/container'; | ||
import * as Dialog from '@/components/dialog'; | ||
import { Pill } from '@/components/pill'; | ||
import { RemoteMdx } from '@/components/remote-mdx'; | ||
import { Typography } from '@/components/typography'; | ||
import { IconArrowLeft, IconBlockquote, IconDownload, IconExternalLink, IconFileTypePdf } from '@tabler/icons-react'; | ||
import { format } from 'date-fns'; | ||
import Link from 'next/link'; | ||
import { CopyCiteToClipboard } from './copy-cite-to-clipboard'; | ||
import { getPublicationBySlug } from './get-publication-by-slug'; | ||
|
||
type Args = { params: { slug: string } }; | ||
|
||
export default async function PublicatiesSlugPage({ params }: Args) { | ||
const publication = await getPublicationBySlug({ slug: params.slug }); | ||
|
||
return ( | ||
<> | ||
<EnhanceMenuBreadcrumbs append={publication.title!} /> | ||
<Container component="header" className="-mt-14 bg-[#F7FBFD] py-12"> | ||
<Typography variant="h1">{publication.title}</Typography> | ||
<section className="flex flex-col gap-y-1 pb-2 pt-12"> | ||
<Typography className="!mt-0 text-lg text-primary-dark"> | ||
Gepubliceerd op: {format(publication.publicationDate!, 'dd MMMM yyyy')} | ||
</Typography> | ||
<Typography className="!mt-0 text-lg text-primary-dark">Auteurs: {publication.authors}</Typography> | ||
<Typography className="!mt-0 text-lg text-primary-dark">Locatie: {publication.location}</Typography> | ||
</section> | ||
<section> | ||
<ul className="-ml-4 flex"> | ||
<li> | ||
<Dialog.Root> | ||
<Dialog.Trigger asChild> | ||
<Button startIcon={<IconBlockquote />} variant="text"> | ||
Citeer dit artikel | ||
</Button> | ||
</Dialog.Trigger> | ||
<Dialog.Portal> | ||
<Dialog.Content> | ||
<Dialog.Title>Citeer deze publicatie</Dialog.Title> | ||
<Dialog.Description> | ||
{publication.cite} | ||
<div className="mt-4 flex justify-center"> | ||
<CopyCiteToClipboard text={publication.cite!} /> | ||
</div> | ||
</Dialog.Description> | ||
</Dialog.Content> | ||
</Dialog.Portal> | ||
</Dialog.Root> | ||
</li> | ||
<li> | ||
<Button | ||
component={Link} | ||
href={`/publicaties/${params.slug}/download`} | ||
startIcon={<IconFileTypePdf />} | ||
variant="text" | ||
> | ||
Download dit artikel | ||
</Button> | ||
</li> | ||
<li> | ||
<Button | ||
component="a" | ||
variant="text" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
startIcon={<IconExternalLink />} | ||
href={publication.originalSource!} | ||
> | ||
Originele bron | ||
</Button> | ||
</li> | ||
</ul> | ||
</section> | ||
</Container> | ||
<Container component="main" className="pt-12"> | ||
<section> | ||
<Typography variant="h2">Samenvatting</Typography> | ||
<RemoteMdx content={publication.content!} /> | ||
</section> | ||
<section> | ||
<Typography variant="h3">Trefwoorden</Typography> | ||
<ul className="mt-4 flex gap-x-6"> | ||
{publication.tags?.split(',').map((tag) => ( | ||
<Pill key={tag} component="li" label={tag} /> | ||
))} | ||
</ul> | ||
</section> | ||
</Container> | ||
<Container component="footer" className="pb-12"> | ||
<div className="mt-16 flex justify-between"> | ||
<Button component={Link} href="/publicaties" startIcon={<IconArrowLeft />}> | ||
Overzicht | ||
</Button> | ||
<Button | ||
component={Link} | ||
color="primary-light" | ||
href={`/publicaties/${params.slug}/download`} | ||
startIcon={<IconDownload />} | ||
> | ||
Download | ||
</Button> | ||
</div> | ||
</Container> | ||
</> | ||
); | ||
} | ||
|
||
export async function generateMetadata({ params }: Args) { | ||
const publication = await getPublicationBySlug({ slug: params.slug }); | ||
|
||
return { | ||
title: publication.title + ' - Regelregister van de Nederlandse Overheid', | ||
keywords: publication.tags, | ||
authors: publication.authors?.split(',').map((author) => ({ name: author.trim() })), | ||
description: publication.summary, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
import { Pill } from '@/components/pill'; | ||
import { Typography } from '@/components/typography'; | ||
import { getPublications } from './get-publications'; | ||
import Link from 'next/link'; | ||
|
||
interface Props { | ||
publication: Awaited<ReturnType<typeof getPublications>>[number]; | ||
} | ||
|
||
export const CardPublication: React.FC<Props> = ({ publication }) => { | ||
if (!publication.slug || !publication.title || !publication.summary) return null; | ||
|
||
return ( | ||
<Link href={'/publicaties/' + publication.slug} className="rounded-md border border-grey-lighter p-6"> | ||
<Typography variant="h3" className="mt-0 text-xl text-grey-dark"> | ||
{publication.title} | ||
</Typography> | ||
<Typography className="mb-4 mt-2 text-grey-dark">{publication.summary}</Typography> | ||
<div className="flex items-start gap-x-4"> | ||
{publication.tags?.split(',').map((tag) => ( | ||
<Pill key={tag} label={tag.trim()} /> | ||
))} | ||
</div> | ||
</Link> | ||
); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { db } from '@/drizzle/db'; | ||
import { publications } from '@/drizzle/schema'; | ||
import { and, desc, lte } from 'drizzle-orm'; | ||
|
||
export function getPublications() { | ||
return db | ||
.select() | ||
.from(publications) | ||
.orderBy(desc(publications.publicationDate)) | ||
.where(and(lte(publications.publishedAt, new Date().toISOString()))); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { Container } from '@/components/container'; | ||
import { RemotePage } from '@/components/remote-page'; | ||
import { Typography } from '@/components/typography'; | ||
import { Metadata } from 'next'; | ||
import { CardPublication } from './card-publication'; | ||
import { getPublications } from './get-publications'; | ||
|
||
export default async function PublicatiesPage() { | ||
const publications = await getPublications(); | ||
|
||
return ( | ||
<> | ||
<Container className="mb-16"> | ||
<Typography variant="h1">Publicaties</Typography> | ||
<RemotePage page="publicaties" /> | ||
<div className="mt-28 flex flex-col gap-y-4"> | ||
{publications.map((publication) => ( | ||
<CardPublication key={publication.id} publication={publication} /> | ||
))} | ||
</div> | ||
</Container> | ||
</> | ||
); | ||
} | ||
|
||
export const metadata: Metadata = { | ||
title: 'Regelregister van de Nederlandse Overheid - Publicaties', | ||
}; |
Oops, something went wrong.