From 569de416820628562c4b2be43b5b3aae7500a875 Mon Sep 17 00:00:00 2001 From: Ben Liu Date: Wed, 18 Oct 2023 23:48:50 +0700 Subject: [PATCH] refactor(homepage): decouple layout to component props and rendering logic --- homepage/src/layouts/contentMapper.jsx | 84 ++++------------------ homepage/src/lib/componentMapper.js | 97 ++++++++++++++++++++++++++ homepage/src/lib/fetchPage.js | 9 +-- homepage/src/pages/index.jsx | 2 +- homepage/src/pages/resource.jsx | 2 +- 5 files changed, 116 insertions(+), 78 deletions(-) create mode 100644 homepage/src/lib/componentMapper.js diff --git a/homepage/src/layouts/contentMapper.jsx b/homepage/src/layouts/contentMapper.jsx index a1723ac8..1e4c8b08 100644 --- a/homepage/src/layouts/contentMapper.jsx +++ b/homepage/src/layouts/contentMapper.jsx @@ -4,76 +4,22 @@ import ThreeColumns from '../components/threeColumns'; import ImageAndText from '../components/imageAndText'; import Section from '../components/section'; import Headline from '../components/headline'; +import { componentTypes } from '../lib/componentMapper'; -const contentMapper = (layout) => { - switch (layout.type) { - case 'layout_banner': - return ( - - ); - case 'layout_section': - if (layout.columns?.length === 2) { - return ( - - ); - } else if (layout.columns?.length === 3) { - return ( - - ); - } else { - return ( -
- ); - } - case 'layout_image_text': - return ( - - ); - case 'layout_headline': - return ( - - ); +const contentMapper = (component) => { + switch (component.type) { + case componentTypes.Banner: + return ; + case componentTypes.Headline: + return ; + case componentTypes.ImageAndText: + return ; + case componentTypes.OneColumn: + return
; + case componentTypes.TwoColumns: + return ; + case componentTypes.ThreeColumns: + return ; default: return null; } diff --git a/homepage/src/lib/componentMapper.js b/homepage/src/lib/componentMapper.js new file mode 100644 index 00000000..d84ca318 --- /dev/null +++ b/homepage/src/lib/componentMapper.js @@ -0,0 +1,97 @@ +import { titleToAnchorId } from './titleToAnchorId'; + +const removeUndefined = (obj) => { + const newObj = {}; + Object.keys(obj).forEach((key) => { + if (obj[key] !== undefined) { + newObj[key] = obj[key]; + } + }); + return newObj; +} + +export const componentTypes = { + Banner: 'Banner', + Headline: 'Headline', + OneColumn: 'OneColumn', + TwoColumns: 'TwoColumns', + ThreeColumns: 'ThreeColumns', + ImageAndText: 'ImageAndText', +} + +export const componentMapper = (layout) => { + let type = ''; + let props = {}; + switch (layout.type) { + case 'layout_banner': { + type = componentTypes.Banner; + props = { + id: titleToAnchorId(layout.title), + title: layout.title, + subtitle: layout.subtitle, + heroImage: layout.hero_image, + highlights: layout.highlights, + }; + break; + } + case 'layout_headline': { + type = componentTypes.Headline; + props = { + id: titleToAnchorId(layout.title), + title: layout.title, + subtitle: layout.subtitle, + }; + break; + } + case 'layout_image_text': { + type = componentTypes.ImageAndText; + props = { + id: titleToAnchorId(layout.title), + title: layout.title, + subtitle: layout.subtitle, + image: layout.image, + content: layout.text, + highlights: layout.highlights, + markdown: true, + }; + break; + } + case 'layout_section': { + if (layout.columns?.length === 1) { + type = componentTypes.OneColumn; + props = { + id: titleToAnchorId(layout.title), + title: layout.title, + subtitle: layout.columns?.[0]?.title, + image: layout.columns?.[0]?.image, + content: layout.columns?.[0]?.text, + markdown: true, + }; + break; + } else if (layout.columns?.length === 2) { + type = componentTypes.TwoColumns; + props = { + id: titleToAnchorId(layout.title), + title: layout.title, + columns: layout.columns, + markdown: true, + }; + break; + } else if (layout.columns?.length === 3) { + type = componentTypes.ThreeColumns; + props = { + id: titleToAnchorId(layout.title), + title: layout.title, + columns: layout.columns, + markdown: true, + }; + break; + } + } + } + + return { + type, + props: removeUndefined(props), + }; +} diff --git a/homepage/src/lib/fetchPage.js b/homepage/src/lib/fetchPage.js index 237f0840..2a4f48f8 100644 --- a/homepage/src/lib/fetchPage.js +++ b/homepage/src/lib/fetchPage.js @@ -1,7 +1,7 @@ import fs from 'fs'; import { join } from 'path'; import matter from 'gray-matter'; -import { titleToAnchorId } from './titleToAnchorId'; +import { componentMapper } from './componentMapper'; const pagesDirectory = join(process.cwd(), '_pages'); @@ -16,12 +16,7 @@ export function fetchPage(lang, page) { const fileContent = fs.readFileSync(filePath, 'utf8'); const { data } = matter(fileContent); - const contentList = data['layout_list']?.map((layout) => { - return { - id: layout.id || titleToAnchorId(layout.title), - ...layout, - }; - }); + const contentList = data['layout_list']?.map(componentMapper); return { contentList, diff --git a/homepage/src/pages/index.jsx b/homepage/src/pages/index.jsx index f2142a43..9c6529a5 100644 --- a/homepage/src/pages/index.jsx +++ b/homepage/src/pages/index.jsx @@ -63,7 +63,7 @@ const Index = ({ headInfo, page }) => ( `, }} /> - {page.contentList.map(contentMapper)} + {page.contentList?.map(contentMapper)} ); diff --git a/homepage/src/pages/resource.jsx b/homepage/src/pages/resource.jsx index 263650b6..806e2ae5 100644 --- a/homepage/src/pages/resource.jsx +++ b/homepage/src/pages/resource.jsx @@ -19,5 +19,5 @@ export const getStaticProps = async ({ locale }) => { }; export default function Resource({ page }) { - return <>{page.contentList.map(contentMapper)}; + return <>{page.contentList?.map(contentMapper)}; }