From bfe138e2f47728e54a01c67a4e6ae4a33127d6c0 Mon Sep 17 00:00:00 2001 From: gestchild Date: Wed, 23 Oct 2024 16:31:00 +0100 Subject: [PATCH 1/8] add redirects --- common/next/next.config.js | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/common/next/next.config.js b/common/next/next.config.js index a041ca8419..04e92e9659 100644 --- a/common/next/next.config.js +++ b/common/next/next.config.js @@ -49,6 +49,25 @@ const createConfig = } return [...rewriteEntries]; }, + async redirects() { + return [ + { + source: '/articles/:slug', + destination: '/stories/:slug', + permanent: true, + }, + { + source: '/articles', + destination: '/search/stories', + permanent: true, + }, + { + source: '/stories/comic', + destination: '/search/stories?format=W7d_ghAAALWY3Ujc', + permanent: true, + }, + ]; + }, webpack: (config, { isServer, webpack }) => { config.plugins.push( new webpack.NormalModuleReplacementPlugin( From ee7c4a93c0d87a0240aede4302fd973b94945b48 Mon Sep 17 00:00:00 2001 From: gestchild Date: Wed, 23 Oct 2024 16:31:22 +0100 Subject: [PATCH 2/8] update linkResolver --- common/services/prismic/link-resolver.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/common/services/prismic/link-resolver.ts b/common/services/prismic/link-resolver.ts index 8cb1cd136f..fb07e0d215 100644 --- a/common/services/prismic/link-resolver.ts +++ b/common/services/prismic/link-resolver.ts @@ -18,7 +18,8 @@ type DataProps = { function linkResolver(doc: Props | DataProps): string { const { uid, type } = doc; if (!uid) return '/'; - if (type === 'webcomics') return `/articles/${uid}`; + if (type === 'articles') return `/stories/${uid}`; + if (type === 'webcomics') return `/stories/${uid}`; if (type === 'webcomic-series') return `/series/${uid}`; if ( type === 'exhibition-guides' || From b28d006c95d7b99fcb3745855dc19476ea945036 Mon Sep 17 00:00:00 2001 From: gestchild Date: Wed, 23 Oct 2024 16:31:54 +0100 Subject: [PATCH 3/8] remove unnecessary page templates --- content/webapp/pages/articles/index.tsx | 90 ----------- .../webapp/pages/stories/[contentType].tsx | 142 ------------------ 2 files changed, 232 deletions(-) delete mode 100644 content/webapp/pages/articles/index.tsx delete mode 100644 content/webapp/pages/stories/[contentType].tsx diff --git a/content/webapp/pages/articles/index.tsx b/content/webapp/pages/articles/index.tsx deleted file mode 100644 index 0c4d909487..0000000000 --- a/content/webapp/pages/articles/index.tsx +++ /dev/null @@ -1,90 +0,0 @@ -import { GetServerSideProps } from 'next'; -import { FunctionComponent } from 'react'; - -import { pageDescriptions } from '@weco/common/data/microcopy'; -import { getServerData } from '@weco/common/server-data'; -import { appError, AppErrorProps } from '@weco/common/services/app'; -import type { PaginatedResults } from '@weco/common/services/prismic/types'; -import { serialiseProps } from '@weco/common/utils/json'; -import { JsonLdObj } from '@weco/common/views/components/JsonLd/JsonLd'; -import PageLayout from '@weco/common/views/components/PageLayout/PageLayout'; -import SpacingSection from '@weco/common/views/components/styled/SpacingSection'; -import LayoutPaginatedResults from '@weco/content/components/LayoutPaginatedResults/LayoutPaginatedResults'; -import { createClient } from '@weco/content/services/prismic/fetch'; -import { fetchArticles } from '@weco/content/services/prismic/fetch/articles'; -import { - transformArticle, - transformArticleToArticleBasic, -} from '@weco/content/services/prismic/transformers/articles'; -import { articleLd } from '@weco/content/services/prismic/transformers/json-ld'; -import { transformQuery } from '@weco/content/services/prismic/transformers/paginated-results'; -import { ArticleBasic } from '@weco/content/types/articles'; -import { getPage } from '@weco/content/utils/query-params'; -import { setCacheControl } from '@weco/content/utils/setCacheControl'; - -type Props = { - articles: PaginatedResults; - jsonLd: JsonLdObj[]; -}; - -export const getServerSideProps: GetServerSideProps< - Props | AppErrorProps -> = async context => { - setCacheControl(context.res); - const page = getPage(context.query); - - if (typeof page !== 'number') { - return appError(context, 400, page.message); - } - - const client = createClient(context); - const articlesQuery = await fetchArticles(client, { page }); - - const articles = transformQuery(articlesQuery, transformArticle); - const jsonLd = articles.results.map(articleLd); - const basicArticles = { - ...articles, - results: articles.results.map(transformArticleToArticleBasic), - }; - - const serverData = await getServerData(context); - - return { - props: serialiseProps({ - articles: basicArticles, - jsonLd, - serverData, - }), - }; -}; - -const ArticlesPage: FunctionComponent = ({ - articles, - jsonLd, -}: Props) => { - // `articles` could be empty if somebody paginates off the end of the list, - // e.g. /articles?page=500 - const image = articles.results[0]?.image; - - return ( - - - - - - ); -}; - -export default ArticlesPage; diff --git a/content/webapp/pages/stories/[contentType].tsx b/content/webapp/pages/stories/[contentType].tsx deleted file mode 100644 index 208310fbfd..0000000000 --- a/content/webapp/pages/stories/[contentType].tsx +++ /dev/null @@ -1,142 +0,0 @@ -import * as prismic from '@prismicio/client'; -import { GetServerSideProps } from 'next'; -import Head from 'next/head'; -import { FunctionComponent } from 'react'; - -import { pageDescriptions } from '@weco/common/data/microcopy'; -import { getServerData } from '@weco/common/server-data'; -import { appError, AppErrorProps } from '@weco/common/services/app'; -import type { PaginatedResults } from '@weco/common/services/prismic/types'; -import { serialiseProps } from '@weco/common/utils/json'; -import { JsonLdObj } from '@weco/common/views/components/JsonLd/JsonLd'; -import PageLayout from '@weco/common/views/components/PageLayout/PageLayout'; -import SpacingSection from '@weco/common/views/components/styled/SpacingSection'; -import LayoutPaginatedResults from '@weco/content/components/LayoutPaginatedResults/LayoutPaginatedResults'; -import { ArticleFormatIds } from '@weco/content/data/content-format-ids'; -import { createClient } from '@weco/content/services/prismic/fetch'; -import { fetchSeries } from '@weco/content/services/prismic/fetch/series'; -import { articleSeriesLd } from '@weco/content/services/prismic/transformers/json-ld'; -import { transformQuery } from '@weco/content/services/prismic/transformers/paginated-results'; -import { - transformSeries, - transformSeriesToSeriesBasic, -} from '@weco/content/services/prismic/transformers/series'; -import { SeriesBasic } from '@weco/content/types/series'; -import { getPage } from '@weco/content/utils/query-params'; -import { setCacheControl } from '@weco/content/utils/setCacheControl'; - -const contentTypes = ['comic'] as const; -type ContentType = (typeof contentTypes)[number]; - -type Props = { - title: string; - contentType: ContentType; - series: PaginatedResults; - jsonLd: JsonLdObj[]; -}; - -type ContentTypeIdAndTitle = { - id: string; - title: string; -}; - -function getContentTypeId(type: ContentType): ContentTypeIdAndTitle { - switch (type) { - case 'comic': - return { - id: ArticleFormatIds.Comic, - title: 'Comics', - }; - } -} - -// eslint-disable-next-line @typescript-eslint/no-explicit-any -function isContentType(x: any): x is ContentType { - return contentTypes.includes(x); -} - -export const getServerSideProps: GetServerSideProps< - Props | AppErrorProps -> = async context => { - setCacheControl(context.res); - const page = getPage(context.query); - - if (typeof page !== 'number') { - return appError(context, 400, page.message); - } - - const { contentType } = context.query; - - if (isContentType(contentType)) { - const serverData = await getServerData(context); - const contentTypeInfo = getContentTypeId(contentType); - - const client = createClient(context); - const seriesQuery = await fetchSeries(client, { - filters: prismic.filter.at('my.series.format', contentTypeInfo.id), - page, - orderings: [ - { - field: 'document.first_publication_date', - direction: 'desc', - }, - ], - }); - const series = transformQuery(seriesQuery, transformSeries); - const basicSeries = { - ...series, - results: series.results.map(transformSeriesToSeriesBasic), - }; - - const jsonLd = series.results.map(articleSeriesLd); - - return { - props: serialiseProps({ - title: contentTypeInfo.title, - contentType, - series: basicSeries, - jsonLd, - serverData, - }), - }; - } - - return { notFound: true }; -}; - -const ArticleSeriesManyPage: FunctionComponent = ({ - title, - contentType, - series, - jsonLd, -}: Props) => { - const image = series.results[0]?.image; - - return ( - <> - {/* TODO: remove this when we're sure we've got the right route */} - - - - - - - - - - ); -}; - -export default ArticleSeriesManyPage; From e3b8d3a478042b22b33d1961e89b054bea7e1ecc Mon Sep 17 00:00:00 2001 From: gestchild Date: Wed, 23 Oct 2024 16:32:15 +0100 Subject: [PATCH 4/8] move article page template to stories --- content/webapp/pages/{articles => stories}/[articleId].tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename content/webapp/pages/{articles => stories}/[articleId].tsx (99%) diff --git a/content/webapp/pages/articles/[articleId].tsx b/content/webapp/pages/stories/[articleId].tsx similarity index 99% rename from content/webapp/pages/articles/[articleId].tsx rename to content/webapp/pages/stories/[articleId].tsx index 23611f2b12..7de1cd5eaa 100644 --- a/content/webapp/pages/articles/[articleId].tsx +++ b/content/webapp/pages/stories/[articleId].tsx @@ -332,7 +332,7 @@ const ArticlePage: FunctionComponent = ({ article, jsonLd }) => { Date: Wed, 23 Oct 2024 16:32:34 +0100 Subject: [PATCH 5/8] update links on stories landing page --- content/webapp/pages/stories/index.tsx | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/content/webapp/pages/stories/index.tsx b/content/webapp/pages/stories/index.tsx index 7819146422..2b4eec136e 100644 --- a/content/webapp/pages/stories/index.tsx +++ b/content/webapp/pages/stories/index.tsx @@ -248,7 +248,7 @@ const StoriesPage: FunctionComponent = ({ @@ -269,7 +269,9 @@ const StoriesPage: FunctionComponent = ({ items={comicSeries} itemsPerRow={3} itemsHaveTransparentBackground={true} - links={[{ text: 'More comics', url: '/stories/comic' }]} + links={[ + { text: 'More comics', url: '/stories?format=W7d_ghAAALWY3Ujc' }, + ]} /> @@ -307,7 +309,7 @@ const StoriesPage: FunctionComponent = ({ From 9071efd4928b286ea86363673724af26aedefd9d Mon Sep 17 00:00:00 2001 From: gestchild Date: Wed, 23 Oct 2024 17:20:09 +0100 Subject: [PATCH 6/8] update tests --- common/services/prismic/link-resolver.test.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/services/prismic/link-resolver.test.ts b/common/services/prismic/link-resolver.test.ts index f95a40094f..69da8771c9 100644 --- a/common/services/prismic/link-resolver.test.ts +++ b/common/services/prismic/link-resolver.test.ts @@ -7,7 +7,7 @@ import linkResolver from './link-resolver'; */ describe('webcomic edge case', () => { test.each([ - { doc: { type: 'webcomics', uid: '1' }, path: '/articles/1' }, + { doc: { type: 'webcomics', uid: '1' }, path: '/stories/1' }, { doc: { type: 'webcomic-series', uid: '1' }, path: '/series/1' }, ])('$doc resolves to $path', ({ doc, path }) => { expect(linkResolver(doc)).toBe(path); @@ -20,7 +20,7 @@ it('resolves exhibition guides to /guides/exhibitions/{id}', () => { }); test.each([ - { doc: { type: 'articles', uid: '1' }, path: '/articles/1' }, + { doc: { type: 'articles', uid: '1' }, path: '/stories/1' }, { doc: { type: 'pages', uid: '1' }, path: '/pages/1' }, { doc: { type: 'not a thing', uid: '1' }, path: '/' }, ])('$doc resolves to $path', ({ doc, path }) => { From f9b4d8630a643b2140f47773f3bff9de4bee137e Mon Sep 17 00:00:00 2001 From: gestchild Date: Thu, 24 Oct 2024 11:12:40 +0100 Subject: [PATCH 7/8] change redirect statusCode to 301 --- common/next/next.config.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/next/next.config.js b/common/next/next.config.js index 04e92e9659..20989f9d01 100644 --- a/common/next/next.config.js +++ b/common/next/next.config.js @@ -54,17 +54,17 @@ const createConfig = { source: '/articles/:slug', destination: '/stories/:slug', - permanent: true, + statusCode: 301, }, { source: '/articles', destination: '/search/stories', - permanent: true, + statusCode: 301, }, { source: '/stories/comic', destination: '/search/stories?format=W7d_ghAAALWY3Ujc', - permanent: true, + statusCode: 301, }, ]; }, From f7be6fb540d70584b024f7a819b5a0cb007eac50 Mon Sep 17 00:00:00 2001 From: gestchild Date: Tue, 29 Oct 2024 10:56:54 +0000 Subject: [PATCH 8/8] add hotjar --- content/webapp/pages/stories/[articleId].tsx | 3 +++ 1 file changed, 3 insertions(+) diff --git a/content/webapp/pages/stories/[articleId].tsx b/content/webapp/pages/stories/[articleId].tsx index 7de1cd5eaa..b72d4947fb 100644 --- a/content/webapp/pages/stories/[articleId].tsx +++ b/content/webapp/pages/stories/[articleId].tsx @@ -25,6 +25,7 @@ import ContentPage from '@weco/content/components/ContentPage/ContentPage'; import PartNumberIndicator from '@weco/content/components/PartNumberIndicator/PartNumberIndicator'; import SeriesNavigation from '@weco/content/components/SeriesNavigation/SeriesNavigation'; import { ArticleFormatIds } from '@weco/content/data/content-format-ids'; +import useHotjar from '@weco/content/hooks/useHotjar'; import { createClient } from '@weco/content/services/prismic/fetch'; import { fetchArticle, @@ -43,6 +44,7 @@ import { getHeroPicture, } from '@weco/content/utils/page-header'; import { setCacheControl } from '@weco/content/utils/setCacheControl'; + const ContentTypeWrapper = styled.div` display: flex; align-items: baseline; @@ -163,6 +165,7 @@ const HTMLDateWrapper = styled.span.attrs({ className: font('intr', 6) })` `; const ArticlePage: FunctionComponent = ({ article, jsonLd }) => { + useHotjar(true); const [listOfSeries, setListOfSeries] = useState(); useEffect(() => {