Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Create Page “cards” #254

Merged
merged 13 commits into from
Oct 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions homepage/_pages/en/cards.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
unique_slug: cards
name: Cards
layout_list:
- type: layout_headline
title: Card Introduction
- type: layout_cards
card_type: project
title: Project Card | Open Government
card_tags:
- open gov
- type: layout_cards
title: Project Card | Open Data
card_type: project
card_tags:
- open data
- type: layout_cards
title: Project Card | Open Source
card_type: project
card_tags:
- open source
- type: layout_cards
title: Job Card
card_type: job
- type: layout_cards
title: Event Card
card_type: event
---
28 changes: 28 additions & 0 deletions homepage/_pages/zh-tw/cards.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
---
unique_slug: cards
name: 卡片頁
layout_list:
- type: layout_headline
title: 卡片介紹
- type: layout_cards
card_type: project
title: 專案卡 | 開放政府專案
card_tags:
- open gov
- type: layout_cards
title: 專案卡 | 開放資料專案
card_type: project
card_tags:
- open data
- type: layout_cards
title: 專案卡 | 開放原始碼專案
card_type: project
card_tags:
- open source
- type: layout_cards
title: 人力卡
card_type: job
- type: layout_cards
title: 事件卡
card_type: event
---
35 changes: 35 additions & 0 deletions homepage/src/components/cards.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ParseMarkdownAndHtml } from './parseMarkdownAndHtml';

const Cards = ({ id, title, cards }) => {
return (
<div className="section" id={id}>
<div className="container">
<div className="section-head">
<h2>{title}</h2>
</div>
<div className="row">
{cards.map((card) => (
<Card key={card.data.id} card={card} />
))}
</div>
</div>
</div>
);
};

const Card = ({ card }) => (
<div className="col-md-4 mb-3" id={card.data.id}>
<div className="section-main">
<h3>{card.data.title}</h3>
<div>
<img src={card.data.image} alt={card.data.title} />
<strong>{card.data.description}</strong>
<ParseMarkdownAndHtml markdown={true}>
{card.content}
</ParseMarkdownAndHtml>
</div>
</div>
</div>
);

export default Cards;
87 changes: 18 additions & 69 deletions homepage/src/layouts/contentMapper.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,76 +4,25 @@ import ThreeColumns from '../components/threeColumns';
import ImageAndText from '../components/imageAndText';
import Section from '../components/section';
import Headline from '../components/headline';
import Cards from '../components/cards';
import { componentTypes } from '../lib/componentMapper';

const contentMapper = (layout) => {
switch (layout.type) {
case 'layout_banner':
return (
<Banner
key={layout.title}
id={layout.id}
title={layout.title}
subtitle={layout.subtitle}
heroImage={layout.hero_image}
highlights={layout.highlights}
/>
);
case 'layout_section':
if (layout.columns?.length === 2) {
return (
<TwoColumns
key={layout.title}
id={layout.id}
title={layout.title}
columns={layout.columns}
markdown={true}
/>
);
} else if (layout.columns?.length === 3) {
return (
<ThreeColumns
key={layout.title}
id={layout.id}
title={layout.title}
columns={layout.columns}
markdown={true}
/>
);
} else {
return (
<Section
key={layout.title}
id={layout.id}
title={layout.title}
subtitle={layout.columns?.[0]?.title}
image={layout.columns?.[0]?.image}
content={layout.columns?.[0]?.text}
markdown={true}
/>
);
}
case 'layout_image_text':
return (
<ImageAndText
key={layout.title}
id={layout.id}
image={layout.image}
title={layout.title}
subtitle={layout.subtitle}
content={layout.text}
highlights={layout.highlights}
markdown={true}
/>
);
case 'layout_headline':
return (
<Headline
key={layout.title}
id={layout.id}
title={layout.title}
subtitle={layout.subtitle}
/>
);
const contentMapper = (component) => {
switch (component.type) {
case componentTypes.Banner:
return <Banner key={component.id} {...component.props} />;
case componentTypes.Headline:
return <Headline key={component.id} {...component.props} />;
case componentTypes.ImageAndText:
return <ImageAndText key={component.id} {...component.props} />;
case componentTypes.OneColumn:
return <Section key={component.id} {...component.props} />;
case componentTypes.TwoColumns:
return <TwoColumns key={component.id} {...component.props} />;
case componentTypes.ThreeColumns:
return <ThreeColumns key={component.id} {...component.props} />;
case componentTypes.Cards:
return <Cards key={component.id} {...component.props} />;
default:
return null;
}
Expand Down
121 changes: 121 additions & 0 deletions homepage/src/lib/componentMapper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
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',
Cards: 'Cards',
};

export const componentMapper = (layout, cards = []) => {
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;
}
}
case 'layout_cards': {
let filteredCards = cards;
// filter cards by card_type
if (layout.card_type) {
filteredCards = cards.filter(
(card) => layout.card_type === card.data.type,
);
}
// filter cards by card_tags
if (layout.card_tags && layout.card_tags.length > 0) {
filteredCards = filteredCards.filter((card) =>
layout.card_tags.every((tag) => card.data.tags?.includes(tag)),
);
}

type = componentTypes.Cards;
props = {
id: titleToAnchorId(layout.title),
title: layout.title,
cards: filteredCards,
};
break;
}
}

return {
type,
props: removeUndefined(props),
};
};
17 changes: 4 additions & 13 deletions homepage/src/lib/fetchCards.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,6 @@ import fs from 'fs';
import { join } from 'path';
import matter from 'gray-matter';

import { remark } from 'remark';
import html from 'remark-html';

const cardsDirectory = join(process.cwd(), '_cards');

/**
Expand All @@ -16,24 +13,18 @@ function getCardDirectoryPath(lang) {
return join(cardsDirectory, lang);
}

export async function fetchCards(lang) {
export function fetchCards(lang) {
const cardsDirectory = getCardDirectoryPath(lang);
const filesInCards = fs.readdirSync(cardsDirectory);

const cards = filesInCards.map(async (filename) => {
const cards = filesInCards.map((filename) => {
const fullPath = join(cardsDirectory, filename);
const file = fs.readFileSync(fullPath, 'utf8');
const matterFile = matter(file);
const { data, content } = matterFile;

const processedContent = await remark().use(html).process(content);
const contentHtml = processedContent.toString();

return {
frontMatter: data,
content: contentHtml,
};
return { data, content };
});

return Promise.all(cards);
return cards;
}
5 changes: 0 additions & 5 deletions homepage/src/lib/fetchPage.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import fs from 'fs';
import { join } from 'path';
import matter from 'gray-matter';
import { titleToAnchorId } from './titleToAnchorId';

const pagesDirectory = join(process.cwd(), '_pages');

Expand All @@ -16,10 +15,6 @@ export function fetchPage(lang, page) {
const fileContent = fs.readFileSync(filePath, 'utf8');
const { data } = matter(fileContent);

data['layout_list']?.forEach((layout) => {
layout.id = layout.id || titleToAnchorId(layout.title);
});

return {
data,
};
Expand Down
6 changes: 0 additions & 6 deletions homepage/src/lib/getNavigationList.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,6 @@ export async function getPagesList(lang) {

export async function getNavigationList(lang) {
const pagesList = await getPagesList(lang);
const cardsPage = {
en: 'Cards',
'zh-tw': '卡片頁',
};

// * dynamic page navigation
const navigationList = pagesList
Expand All @@ -41,8 +37,6 @@ export async function getNavigationList(lang) {
page.path = page.path.replace('index', '');
return { link: `/${page.path}`, text: page.name };
});
// add hard coded cards page
navigationList.push({ link: `/cards`, text: cardsPage[lang] });

return navigationList;
}
7 changes: 7 additions & 0 deletions homepage/src/lib/markdownToHtml.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { remark } from 'remark';
import html from 'remark-html';

export async function markdownToHtml(markdown) {
const result = await remark().use(html).process(markdown);
return result.toString();
}
Loading
Loading