diff --git a/.codeclimate.yml b/.codeclimate.yml index 96b8651..ac97637 100644 --- a/.codeclimate.yml +++ b/.codeclimate.yml @@ -23,3 +23,5 @@ exclude_paths: - static/**/* - content/**/* - cypress/**/* +- gatsby-config.js +- gatsby-node.js diff --git a/gatsby-node.js b/gatsby-node.js index 03077aa..84c7534 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -2,19 +2,27 @@ const path = require('path'); const { createFilePath } = require('gatsby-source-filesystem'); const { paginate } = require('gatsby-awesome-pagination'); -exports.createPages = ({ graphql, actions }) => { +exports.createPages = async function ({ actions, graphql }) { const { createPage } = actions; + const itemsPerPage = 5; + /** + * Homepage + * */ const indexTemplate = path.resolve('./src/templates/index.js'); createPage({ path: '/', component: indexTemplate, }); - return graphql( + + /** + * Blog + * */ + const blogPosts = await graphql( ` - { + { allMdx( - sort: { fields: [frontmatter___date], order: DESC } + sort: { fields: [frontmatter___date], order: DESC } limit: 1000 ) { edges { @@ -29,104 +37,154 @@ exports.createPages = ({ graphql, actions }) => { } } } - `, - ) - .then((result) => { - if (result.errors) { - throw result.errors; - } - - // Create blog posts pages. - const posts = result.data.allMdx.edges; + `, + ); - const postTemplate = path.resolve('./src/templates/post.js'); - const blogTemplate = path.resolve('./src/templates/blog.js'); + const posts = blogPosts.data.allMdx.edges; + const postTemplate = path.resolve('./src/templates/post.js'); + const blogPostPromises = posts.map(async (edge, index) => { + const previous = index === posts.length - 1 ? null : posts[index + + 1].node; + const next = index === 0 ? null : posts[index - 1].node; + createPage({ + path: `/blog/${edge.node.frontmatter.slug}/`, + component: postTemplate, + context: { + slug: edge.node.frontmatter.slug, + previous, + next, + }, + }); + }); - posts.forEach((post, index) => { - const previous = index === posts.length - 1 ? null : posts[index + 1].node; - const next = index === 0 ? null : posts[index - 1].node; + await Promise.all(blogPostPromises); - createPage({ - path: `/blog/${post.node.frontmatter.slug}/`, - component: postTemplate, - context: { - slug: post.node.frontmatter.slug, - previous, - next, - }, - }); - }); + // Create a paginated blog, e.g., /, /page/2, /page/3 + const blogTemplate = path.resolve('./src/templates/blog.js'); + paginate({ + createPage, + items: posts, + itemsPerPage, + pathPrefix: ({ pageNumber }) => (pageNumber === 0 + ? '/blog' + : '/blog/page'), + component: blogTemplate, + context: { + paginate_link: '/blog', + }, + }); - // Create a paginated blog, e.g., /, /page/2, /page/3 - paginate({ - createPage, - items: posts, - itemsPerPage: 10, - pathPrefix: ({ pageNumber }) => (pageNumber === 0 ? '/blog' : '/blog/page'), - component: blogTemplate, - }); - }) - .then(() => graphql( - ` + /** + * Tag pages + pagination + * */ + const distinctTags = await graphql( + ` { allMdx { distinct(field: frontmatter___tags) } } `, - )) - .then((result) => { - if (result.errors) { - throw result.errors; + ); + const tagList = distinctTags.data.allMdx.distinct; + const tagsTemplate = path.resolve('./src/templates/tag.js'); + const tagPromises = tagList.map(async (tag) => { + await graphql( + ` + { + allMdx(filter: {frontmatter: {tags: {in: "${tag}"}}}) { + edges { + node { + id + frontmatter { + title + slug + } + body + } + } + } + } + `, + ).then((tagPosts) => { + if (tagPosts.errors) { + throw tagPosts.errors; } + const tagLower = tag.toLowerCase(); + paginate({ + createPage, + items: tagPosts.data.allMdx.edges, + itemsPerPage, + pathPrefix: ({ pageNumber }) => (pageNumber === 0 + ? `/blog/tags/${tagLower}` + : `/blog/tags/${tagLower}/page`), + component: tagsTemplate, + context: { + name: tag, + slug: tagLower, + paginate_link: `/blog/tags/${tagLower}`, + }, + }); + }); + }); - const tagsTemplate = path.resolve('./src/templates/tag.js'); - - // Create blog tag pages. - const tags = result.data.allMdx.distinct; + await Promise.all(tagPromises); - tags.forEach((tag) => { - // Todo Enter/Update graphQL - createPage({ - path: `/blog/tags/${tag}/`, - component: tagsTemplate, - context: { - name: tag, - slug: tag.toLowerCase(), - }, - }); - }); - }) - .then(() => graphql( - ` + /** + * Category pages + pagination + * */ + const distinctCategories = await graphql( + ` { allMdx { distinct(field: frontmatter___category) } } `, - )) - .then((result) => { - if (result.errors) { - throw result.errors; - } - - const categoriesTemplate = path.resolve('./src/templates/category.js'); + ); - // Create blog category pages. - const categories = result.data.allMdx.distinct; - - categories.forEach((category) => { - createPage({ - path: `/blog/categories/${category}/`, - component: categoriesTemplate, - context: { - name: category, - slug: category, - }, - }); + const categoryList = distinctCategories.data.allMdx.distinct; + const categoriesTemplate = path.resolve('./src/templates/category.js'); + const categoryPromises = categoryList.map(async (category) => { + await graphql( + ` + { + allMdx(filter: {frontmatter: {category: {eq: "${category}"}}}) { + edges { + node { + id + frontmatter { + title + slug + } + body + } + } + } + } + `, + ).then((categoryPosts) => { + if (categoryPosts.errors) { + throw categoryPosts.errors; + } + paginate({ + createPage, + items: categoryPosts.data.allMdx.edges, + itemsPerPage, + pathPrefix: ({ pageNumber }) => (pageNumber === 0 + ? `/blog/categories/${category}` + : `/blog/categories/${category}/page`), + component: categoriesTemplate, + context: { + name: category, + slug: category, + paginate_link: `/blog/categories/${category}`, + }, }); }); + }); + + await Promise.all(categoryPromises); }; exports.onCreateNode = ({ node, actions, getNode }) => { diff --git a/src/assets/styles/main.scss b/src/assets/styles/main.scss index 5344af7..c5e3dde 100644 --- a/src/assets/styles/main.scss +++ b/src/assets/styles/main.scss @@ -31,15 +31,6 @@ footer.footer { font-weight: $weight-semibold; } -.navbar { - border-top: 3px solid $primary-color; - border-bottom: 1px solid $background-grey; -} - -.navbar-end { - margin-right: 0.5rem; -} - .no-html-scroll { overflow: hidden; } diff --git a/src/components/blog/pagination.js b/src/components/blog/pagination/pagination.js similarity index 88% rename from src/components/blog/pagination.js rename to src/components/blog/pagination/pagination.js index fb8e5b2..9ca1119 100644 --- a/src/components/blog/pagination.js +++ b/src/components/blog/pagination/pagination.js @@ -1,13 +1,16 @@ import React from 'react'; import { Link } from 'gatsby'; +import './pagination.scss'; const Pagination = ({ pageContext }) => { const { previousPagePath, nextPagePath } = pageContext; + const defaultLink = pageContext.paginate_link; + const pageLink = `${defaultLink}/page`; // A sweet helper function to create pagination object const createPaginationObjects = (length, page, increment = 2) => Array .from({ length }, (_, i) => ({ - link: `/blog/page/${i + increment}/`, + link: `${pageLink}/${i + increment}/`, index: i + increment, current: page === i + increment, })); @@ -16,13 +19,13 @@ const Pagination = ({ pageContext }) => { const page = pageContext.humanPageNumber; let navItems = [ { - link: '/blog/', + link: defaultLink, index: 1, - current: pages === 1, + current: page === 1, }, ]; - if (typeof pages === 'undefined') { + if (typeof pages === 'undefined' || pages === 1) { return ''; } @@ -30,7 +33,7 @@ const Pagination = ({ pageContext }) => { navItems = [ ...navItems, ...Array.from({ length: pages - 1 }, (_, i) => ({ - link: `/blog/page/${i + 2}/`, + link: `${pageLink}/${i + 2}/`, index: i + 2, current: page === i + 2, })), @@ -50,7 +53,7 @@ const Pagination = ({ pageContext }) => { index: 'starter-separator', }, { - link: `/blog/page/${pages}/`, + link: `${pageLink}/${pages}/`, index: pages, current: false, }, @@ -78,7 +81,7 @@ const Pagination = ({ pageContext }) => { index: 'finisher-separator', }, { - link: `/blog/page/${pages}/`, + link: `${pageLink}/${pages}/`, index: pages, current: false, }, @@ -87,7 +90,6 @@ const Pagination = ({ pageContext }) => { } return (
-