diff --git a/content/scambox/001-hermine.mdx b/content/blog/scambox/001-hermine.mdx similarity index 87% rename from content/scambox/001-hermine.mdx rename to content/blog/scambox/001-hermine.mdx index c1f4c23..1045c7a 100644 --- a/content/scambox/001-hermine.mdx +++ b/content/blog/scambox/001-hermine.mdx @@ -1,9 +1,13 @@ --- +section: scambox +language: en title: Harry Potter and the Toaster-Investment url: harry-potter-and-the-toaster platform: telegram tags: [crypto] published: 2021-11-05 22:00:00 +author: + name: Kevin Kandlbinder --- I've recently been contacted by Hermine on Telegram with a big business opportunity, diff --git a/gatsby-config.js b/gatsby-config.js index 213c95a..1246eca 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -69,8 +69,8 @@ module.exports = { { resolve: `gatsby-source-filesystem`, options: { - path: `${__dirname}/content/scambox`, - name: `scamboxContent`, + path: `${__dirname}/content/blog`, + name: `blogContent`, }, }, "gatsby-plugin-mdx", @@ -128,8 +128,8 @@ module.exports = { interpolation: { escapeValue: false, // not needed for react as it escapes by default }, - keySeparator: false, - nsSeparator: false, + keySeparator: ".", + nsSeparator: ":", }, pages: [ { @@ -137,8 +137,14 @@ module.exports = { getLanguageFromPath: true, excludeLanguages: extConfig.languages, }, + { + matchPath: "/:lang/blog/:urlname*", + getLanguageFromPath: true, + excludeLanguages: extConfig.languages, + }, ], }, }, + `gatsby-plugin-netlify`, ], }; diff --git a/gatsby-node.js b/gatsby-node.js index 6985ce3..bc4f5ca 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -1,12 +1,12 @@ /* eslint-disable no-undef */ const path = require(`path`); const fs = require("fs"); +const { paginate } = require("gatsby-awesome-pagination"); exports.createPages = async ({ actions, graphql, reporter }) => { - const { createPage } = actions; + const { createPage, createRedirect } = actions; const projectTemplate = path.resolve(`src/templates/project.js`); - const scamboxTemplate = path.resolve(`src/templates/scamboxPost.js`); const result = await graphql(` query AllPagesQuery { @@ -17,8 +17,8 @@ exports.createPages = async ({ actions, graphql, reporter }) => { } } - scambox: allFile( - filter: { sourceInstanceName: { eq: "scamboxContent" } } + blog: allFile( + filter: { sourceInstanceName: { eq: "blogContent" } } ) { nodes { childMdx { @@ -29,6 +29,9 @@ exports.createPages = async ({ actions, graphql, reporter }) => { tags title url + section + language + published(formatString: "YYYY/MM") } } } @@ -59,24 +62,121 @@ exports.createPages = async ({ actions, graphql, reporter }) => { }); }); - result.data.scambox.nodes.forEach((node) => { + const blogListingTemplate = path.resolve(`src/templates/blogListing.js`); + const blogTemplate = path.resolve(`src/templates/blogPost.js`); + + console.log("Creating blog listing..."); + + ["en", "de"].forEach((lang) => + paginate({ + createPage, + items: result.data.blog.nodes, + itemsPerPage: 10, + pathPrefix: `/${lang}/blog`, + component: blogListingTemplate, + context: { + lang, + }, + }) + ); + + let processedSections = ["blog"]; + + result.data.blog.nodes.forEach((node) => { if (!node.childMdx) return; + if ( + !processedSections.includes( + node.childMdx.frontmatter.section ?? "blog" + ) + ) { + processedSections.push(node.childMdx.frontmatter.section); + + console.log( + "Creating section listing for " + + node.childMdx.frontmatter.section + + "..." + ); + + ["en", "de"].forEach((lang) => + paginate({ + createPage, + items: result.data.blog.nodes.filter( + (e) => + e.childMdx.frontmatter.section === + node.childMdx.frontmatter.section + ), + itemsPerPage: 10, + pathPrefix: `/${lang}/blog/${node.childMdx.frontmatter.section}`, + component: blogListingTemplate, + context: { + lang, + section: node.childMdx.frontmatter.section, + }, + }) + ); + } + // eslint-disable-next-line no-undef console.log( "Creating Page: ", - `/*/scambox/${node.childMdx.frontmatter.url}` + `/${node.childMdx.frontmatter.language}/blog/${ + node.childMdx.frontmatter.section ?? "blog" + }/${node.childMdx.frontmatter.url}` ); - //["en", "de"].forEach((lang) => { createPage({ - path: `/scambox/${node.childMdx.frontmatter.url}`, - component: scamboxTemplate, + path: `/${node.childMdx.frontmatter.language}/blog/${ + node.childMdx.frontmatter.section + ? node.childMdx.frontmatter.section + "/" + : "" + }${node.childMdx.frontmatter.published}/${ + node.childMdx.frontmatter.url + }`, + component: blogTemplate, context: { mdxId: node.childMdx.id, + lang: node.childMdx.frontmatter.language, }, }); - //}) + + ["en", "de"].forEach((lang) => { + if (lang === node.childMdx.frontmatter.language) return; + + createRedirect({ + fromPath: `/${lang}/blog/${ + node.childMdx.frontmatter.section + ? node.childMdx.frontmatter.section + "/" + : "" + }${node.childMdx.frontmatter.published}/${ + node.childMdx.frontmatter.url + }`, + toPath: `/${node.childMdx.frontmatter.language}/blog/${ + node.childMdx.frontmatter.section + ? node.childMdx.frontmatter.section + "/" + : "" + }${node.childMdx.frontmatter.published}/${ + node.childMdx.frontmatter.url + }`, + redirectInBrowser: true, + permanent: true, + }); + + if (node.childMdx.frontmatter.section === "scambox") { + createRedirect({ + fromPath: `/${lang}/scambox/${node.childMdx.frontmatter.url}`, + toPath: `/${node.childMdx.frontmatter.language}/blog/${ + node.childMdx.frontmatter.section + ? node.childMdx.frontmatter.section + "/" + : "" + }${node.childMdx.frontmatter.published}/${ + node.childMdx.frontmatter.url + }`, + redirectInBrowser: true, + permanent: true, + }); + } + }); }); }; diff --git a/locales/en/translation.json b/locales/en/translation.json index aa1c999..a604363 100644 --- a/locales/en/translation.json +++ b/locales/en/translation.json @@ -48,5 +48,31 @@ "scamboxDescription": "Take a dive with me into all of the scams I get on the daily, and maybe laugh at them a little!", "scamboxReadFull": "Read full post »", "scamboxPosted": "Posted on {{date}}", - "moreSoon": "More to come" + "moreSoon": "More to come", + "language": { + "en": { + "name": "English" + }, + "de": { + "name": "German" + } + }, + "blog": { + "title": "Blog", + "readFull": "Read full post »", + "meta": "Posted on {{date}} by {{author}}", + "page": "Page {{page}}/{{maxPage}}", + "previous": "Previous", + "next": "Next", + "section": { + "blog": { + "name": "Blog", + "description": "Read all about my exciting life!" + }, + "scambox": { + "name": "Scambox", + "description": "Take a dive with me into all of the scams I get on the daily, and maybe laugh at them a little!" + } + } + } } diff --git a/package.json b/package.json index 82f9b27..e0ab204 100644 --- a/package.json +++ b/package.json @@ -27,11 +27,13 @@ "animejs": "3.2.1", "babel-plugin-i18next-extract": "0.8.3", "gatsby": "4.1.0", + "gatsby-awesome-pagination": "^0.3.8", "gatsby-cli": "4.1.0", "gatsby-plugin-asset-path": "3.0.4", "gatsby-plugin-image": "2.1.0", "gatsby-plugin-manifest": "4.1.0", "gatsby-plugin-mdx": "3.1.0", + "gatsby-plugin-netlify": "^3.14.0", "gatsby-plugin-offline": "5.1.0", "gatsby-plugin-portal": "1.0.7", "gatsby-plugin-react-helmet": "5.1.0", diff --git a/src/components/navigation.js b/src/components/navigation.js index 358176e..67f3734 100644 --- a/src/components/navigation.js +++ b/src/components/navigation.js @@ -105,11 +105,11 @@ const Navigation = ({ isHome }) => { social - scambox + blog.title
{ social - scambox + blog.title
, diff --git a/src/pages/scambox.js b/src/pages/scambox.js deleted file mode 100644 index 889001e..0000000 --- a/src/pages/scambox.js +++ /dev/null @@ -1,87 +0,0 @@ -/* eslint-disable react/prop-types */ -import { graphql } from "gatsby"; -import { Link } from "gatsby-plugin-react-i18next"; -import React from "react"; -import { useTranslation } from "react-i18next"; - -import Layout from "../layouts/default"; - -import * as styles from "./scambox.module.scss"; - -const ScamBox = ({ data }) => { - const { t } = useTranslation(); - - return ( - -
-
-

{t("scambox")}

- -

{t("scamboxDescription")}

- -
- {data.scambox.nodes.map((post) => { - return ( - - - {post.childMdx.frontmatter.title} - - - {t("scamboxPosted", { - date: post.childMdx.frontmatter - .published, - })} - - - - {post.childMdx.excerpt}{" "} - {t("scamboxReadFull")} - - - ); - })} -
- - {t("moreSoon")} -
-
-
- ); -}; - -export const query = graphql` - query ($language: String!) { - scambox: allFile( - filter: { sourceInstanceName: { eq: "scamboxContent" } } - sort: { fields: childMdx___frontmatter___published, order: DESC } - ) { - nodes { - childMdx { - frontmatter { - platform - tags - title - url - published(formatString: "DD.MM.YYYY") - } - excerpt - } - } - } - locales: allLocale(filter: { language: { eq: $language } }) { - edges { - node { - ns - data - language - } - } - } - } -`; - -export default ScamBox; diff --git a/src/pages/scambox.module.scss b/src/pages/scambox.module.scss deleted file mode 100644 index efcaef2..0000000 --- a/src/pages/scambox.module.scss +++ /dev/null @@ -1,45 +0,0 @@ -@import "../variables"; -@import "../mixins"; - -.list { - display: flex; - flex-direction: column; - margin-top: $layoutPadding; - - .post { - text-decoration: none; - display: flex; - flex-direction: column; - color: inherit; - padding: $layoutPadding; - - border-bottom: thin dotted grey; - - .title { - color: $accentColor; - font-size: 1.5em; - text-decoration: underline dotted currentColor; - } - - .meta { - margin-bottom: 10px; - opacity: .5; - } - - .excerpt { - margin-left: 10px; - - > span { - color: $accentColor; - text-decoration: underline dotted currentColor; - } - } - } -} - -.moreSoon { - display: block; - padding: $layoutPadding; - text-align: center; - opacity: .5; -} \ No newline at end of file diff --git a/src/templates/blogListing.js b/src/templates/blogListing.js new file mode 100644 index 0000000..a6be1b2 --- /dev/null +++ b/src/templates/blogListing.js @@ -0,0 +1,187 @@ +/* eslint-disable react/prop-types */ +import { graphql, Link as Link2 } from "gatsby"; +import { StaticImage } from "gatsby-plugin-image"; +import { Link } from "gatsby-plugin-react-i18next"; +import React from "react"; +import { useTranslation } from "react-i18next"; + +import Layout from "../layouts/default"; + +import * as styles from "./blogListing.module.scss"; + +const BlogListing = ({ data, pageContext }) => { + const { t } = useTranslation(); + + const title = t(`blog.section.${pageContext.section ?? "blog"}.name`); + const description = t( + `blog.section.${pageContext.section ?? "blog"}.description` + ); + + const hasSection = typeof pageContext.section !== "undefined"; + + return ( + +
+
+ {hasSection && ( + + {t("blog.title")} / + + )} +

{title}

+ +

{description}

+ + {!hasSection && ( + <> +

Sections

+ +
+ +
+
+ +
+ + Scambox + +
+ +
+ + )} + +

Posts

+ +
+ {data.posts.nodes.map((post) => { + return ( + + + {post.childMdx.frontmatter.title} + + + {t("blog.meta", { + date: post.childMdx.frontmatter + .published, + author: post.childMdx.frontmatter + .author.name, + })} + + {post.childMdx.frontmatter.section && + !hasSection && ( + <> + {" | "} + + {t( + `blog.section.${post.childMdx.frontmatter.section}.name` + )} + + + )} + + {" | "} + {t( + `language.${post.childMdx.frontmatter.language}.name` + )} + + + + {post.childMdx.excerpt}{" "} + {t("blog.readFull")} + + + ); + })} +
+ +
+ {pageContext.pageNumber > 0 ? ( + + {t("blog.previous")} + + ) : ( + + )} + + {t("blog.page", { + page: pageContext.humanPageNumber, + maxPage: pageContext.numberOfPages, + })} + + {pageContext.humanPageNumber < + pageContext.numberOfPages ? ( + + {t("blog.next")} + + ) : ( + + )} +
+
+
+
+ ); +}; + +export const query = graphql` + query ($language: String!, $skip: Int!, $limit: Int!, $section: String) { + posts: allFile( + filter: { + sourceInstanceName: { eq: "blogContent" } + childMdx: { frontmatter: { section: { eq: $section } } } + } + sort: { fields: childMdx___frontmatter___published, order: DESC } + limit: $limit + skip: $skip + ) { + nodes { + childMdx { + frontmatter { + platform + tags + title + url + published(formatString: "DD.MM.YYYY") + urlPublished: published(formatString: "YYYY/MM") + section + language + author { + name + } + } + excerpt + } + } + } + locales: allLocale(filter: { language: { eq: $language } }) { + edges { + node { + ns + data + language + } + } + } + } +`; + +export default BlogListing; diff --git a/src/templates/blogListing.module.scss b/src/templates/blogListing.module.scss new file mode 100644 index 0000000..ebbb2bc --- /dev/null +++ b/src/templates/blogListing.module.scss @@ -0,0 +1,109 @@ +@import "../variables"; +@import "../mixins"; + +.sectionBacklink { + display: block; + margin-top: 2rem; + margin-bottom: -2rem; + font-size: .8em; + text-decoration: none; +} + +.sectionList { + @include flexList; + + .sectionCard { + @include cardGeneric; + display: flex; + flex-direction: column; + position: relative; + + .sectionImage { + width: 300px; + height: 150px; + background-position: center; + background-size: cover; + display: flex; + padding: 10px; + flex-direction: column-reverse; + text-shadow: 0 0 10px black, 0 0 10px black, 0 0 20px black; + color: white; + position: relative; + + .sectionBg { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 0; + } + + .sectionName { + font-size: 2em; + margin-top: -5px; + z-index: 100; + } + } + } +} + + +.pageSwitcher { + display: flex; + margin-top: $layoutPadding; + + >* { + width: 33%; + } + + :nth-child(2) { + text-align: center; + } + :nth-child(3) { + text-align: right; + } +} + +.list { + display: flex; + flex-direction: column; + margin-top: $layoutPadding; + + .post { + text-decoration: none; + display: flex; + flex-direction: column; + color: inherit; + padding: $layoutPadding; + + border-bottom: thin dotted grey; + + .title { + color: $accentColor; + font-size: 1.5em; + text-decoration: underline dotted currentColor; + } + + .meta { + margin-bottom: 10px; + opacity: .5; + } + + .excerpt { + margin-left: 10px; + + > span { + color: $accentColor; + text-decoration: underline dotted currentColor; + } + } + } +} + +.moreSoon { + display: block; + padding: $layoutPadding; + text-align: center; + opacity: .5; +} \ No newline at end of file diff --git a/src/templates/scamboxPost.js b/src/templates/blogPost.js similarity index 68% rename from src/templates/scamboxPost.js rename to src/templates/blogPost.js index 07ad211..2a1245a 100644 --- a/src/templates/scamboxPost.js +++ b/src/templates/blogPost.js @@ -8,14 +8,15 @@ import Utterances from "utterances-react"; import Layout from "../layouts/default"; -import * as styles from "./scamboxPost.module.scss"; +import * as styles from "./blogPost.module.scss"; +import { Link } from "gatsby-plugin-react-i18next"; -const ScamBoxPost = ({ data }) => { - const { t, i18n } = useTranslation(); +const BlogPost = ({ data }) => { + const { t } = useTranslation(); return ( @@ -28,13 +29,12 @@ const ScamBoxPost = ({ data }) => { "https://example.com/photos/4x3/photo.jpg", "https://example.com/photos/16x9/photo.jpg" ],*/ - datePublished: data.mdx.publishedIso, - dateModified: data.mdx.publishedIso, + datePublished: data.mdx.frontmatter.publishedIso, + dateModified: data.mdx.frontmatter.publishedIso, author: [ { "@type": "Person", - name: "Kevin Kandlbinder", - url: "https://kevink.dev", + name: data.mdx.frontmatter.author.name, }, ], })} @@ -47,11 +47,15 @@ const ScamBoxPost = ({ data }) => { }, { name: "article:published_time", - content: data.mdx.publishedIso, + content: data.mdx.frontmatter.publishedIso, }, { name: "article:section", - content: "Scambox", + content: t( + `blog.section.${ + data.mdx.frontmatter.section ?? "blog" + }.name` + ), }, { name: "keywords", @@ -63,17 +67,24 @@ const ScamBoxPost = ({ data }) => {

{data.mdx.frontmatter.title}

- {t("scamboxPosted", { + {t("blog.meta", { date: data.mdx.frontmatter.published, + author: data.mdx.frontmatter.author.name, })} - - {i18n.language !== "en" && ( -
- {t("scamboxNotice")} -

{t("scamboxLanguage")}

-
- )} + {data.mdx.frontmatter.section && ( + <> + {" | "} + + {t( + `blog.section.${data.mdx.frontmatter.section}.name` + )} + + + )} + {data.mdx.body} @@ -81,7 +92,7 @@ const ScamBoxPost = ({ data }) => {