From 7006b168bfbdc86076d71956970d87d80d729506 Mon Sep 17 00:00:00 2001 From: Matthias Kretschmann Date: Sat, 29 Sep 2018 20:43:10 +0200 Subject: [PATCH] improved pagination --- gatsby-node.js | 88 +++++++------------ package.json | 1 - src/components/molecules/Pagination.jsx | 64 +++++++++++--- .../molecules/Pagination.module.scss | 45 +++++++--- src/styles/global.scss | 5 +- src/templates/Posts.jsx | 8 +- 6 files changed, 124 insertions(+), 87 deletions(-) diff --git a/gatsby-node.js b/gatsby-node.js index 82f31a4f..ddf895c2 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -2,7 +2,6 @@ const path = require('path') const fs = require('fs') const yaml = require('js-yaml') const { createFilePath } = require('gatsby-source-filesystem') -const { paginate } = require('gatsby-awesome-pagination') const fastExif = require('fast-exif') const Fraction = require('fraction.js') const dms2dec = require('dms2dec') @@ -172,12 +171,13 @@ exports.createPages = ({ graphql, actions }) => { } const posts = result.data.allMarkdownRemark.edges + const numPages = Math.ceil(posts.length / itemsPerPage) // Generate posts & posts index - generateContent(createPage, posts) + generateContent(createPage, posts, numPages) // Generate Tag Pages - generateTagPages(createPage, posts) + generateTagPages(createPage, posts, numPages) // create manual redirects redirects.forEach(({ f, t }) => { @@ -196,7 +196,7 @@ exports.createPages = ({ graphql, actions }) => { const postsTemplate = path.resolve('src/templates/Posts.jsx') -const generateContent = (createPage, posts) => { +const generateContent = (createPage, posts, numPages) => { const postTemplate = path.resolve('src/templates/Post.jsx') // Create Post pages @@ -210,69 +210,49 @@ const generateContent = (createPage, posts) => { }) }) - // Create paginated front page - paginate({ - createPage, - items: posts, - itemsPerPage: itemsPerPage, - pathPrefix: '/', - component: postsTemplate + // Create paginated Blog index pages + Array.from({ length: numPages }).forEach((_, i) => { + createPage({ + path: i === 0 ? '/' : `/page/${i + 1}`, + component: postsTemplate, + context: { + limit: itemsPerPage, + skip: i * itemsPerPage, + numPages, + currentPageNumber: i + 1, + prevPage: i - 1, + nextPage: i + 2 + } + }) }) } const generateTagPages = (createPage, posts) => { - const tagSet = new Set() - const tagMap = new Map() - - posts.forEach(post => { - if (post.node.frontmatter.tags) { - post.node.frontmatter.tags.forEach(tag => { - tagSet.add(tag) - - const array = tagMap.has(tag) ? tagMap.get(tag) : [] - array.push(post) - tagMap.set(tag, array) - }) - } - }) - - const tagList = Array.from(tagSet) + const tagList = arrayReducer(posts, 'tags') tagList.forEach(tag => { if (tag === 'goodies') return // Create tag pages createPage({ - path: `/tag/${tag}/`, + path: `/tags/${tag}/`, component: postsTemplate, context: { tag } }) }) - - // Object.keys(posts).forEach(tagName => { - // const pageSize = 5 - // const pagesSum = Math.ceil(posts[tagName].length / pageSize) - - // for (let page = 1; page <= pagesSum; page++) { - // createPage({ - // path: - // page === 1 - // ? `/tag/${tagName.toLowerCase()}` - // : `/tag/${tagName.toLowerCase()}/page/${page}`, - // component: postsTemplate, - // context: { - // posts: paginate(posts[tagName], pageSize, page), - // tag: tagName, - // pagesSum, - // page - // } - // }) - // } - // }) } -// function paginate(array, page_size, page_number) { -// return array -// .slice(0) -// .slice((page_number - 1) * page_size, page_number * page_size) -// } +// https://www.adamjberkowitz.com/tags-and-categories-in-gatsby-js/ +const arrayReducer = (postsArray, type) => { + return (postsArray = postsArray + .map(({ node }) => { + return node.frontmatter[type] + }) + .reduce((a, b) => { + return a.concat(b) + }, []) + .filter((type, index, array) => { + return array.indexOf(type) === index + }) + .sort()) +} diff --git a/package.json b/package.json index ee4e17cd..7ed28edd 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "fast-exif": "^1.0.1", "fraction.js": "^4.0.9", "gatsby": "^2.0.12", - "gatsby-awesome-pagination": "^0.3.1", "gatsby-image": "^2.0.12", "gatsby-plugin-catch-links": "^2.0.3", "gatsby-plugin-favicon": "^3.1.4", diff --git a/src/components/molecules/Pagination.jsx b/src/components/molecules/Pagination.jsx index d128ad77..9fdcc013 100644 --- a/src/components/molecules/Pagination.jsx +++ b/src/components/molecules/Pagination.jsx @@ -3,25 +3,61 @@ import PropTypes from 'prop-types' import { Link } from 'gatsby' import styles from './Pagination.module.scss' -const Pagination = ({ pageContext }) => { - const { previousPagePath, nextPagePath } = pageContext +const PageNumber = ({ i, current }) => ( + + {i + 1} + +) + +PageNumber.propTypes = { + i: PropTypes.number.isRequired, + current: PropTypes.bool +} + +const PrevNext = ({ prevPagePath, nextPagePath }) => { + const link = prevPagePath || nextPagePath + const rel = prevPagePath ? 'prev' : 'next' + const title = prevPagePath ? 'Newer Posts' : 'Older Posts' return ( -
- {nextPagePath ? ( - - « Older Posts - - ) : null} - {previousPagePath ? ( - - Newer Posts » - - ) : null} -
+ + {prevPagePath ? '←' : '→'} + ) } +PrevNext.propTypes = { + prevPagePath: PropTypes.string, + nextPagePath: PropTypes.string +} + +const Pagination = ({ pageContext }) => { + const { currentPageNumber, numPages, prevPage, nextPage } = pageContext + const isFirst = currentPageNumber === 1 + const isLast = currentPageNumber === numPages + const prevPagePath = currentPageNumber === 2 ? '/' : `/page/${prevPage}` + const nextPagePath = `/page/${nextPage}` + + return nextPage > 1 ? ( +
+
{!isFirst && }
+
+ {Array.from({ length: numPages }, (_, i) => ( + + ))} +
+
{!isLast && }
+
+ ) : null +} + Pagination.propTypes = { pageContext: PropTypes.object.isRequired } diff --git a/src/components/molecules/Pagination.module.scss b/src/components/molecules/Pagination.module.scss index 34b76656..63da475b 100644 --- a/src/components/molecules/Pagination.module.scss +++ b/src/components/molecules/Pagination.module.scss @@ -3,18 +3,41 @@ .pagination { display: flex; margin-top: $spacer * 2; - margin-bottom: $spacer * 2; -} + margin-bottom: $spacer; + justify-content: center; -.paginationLink { - flex: 1 1 50%; - display: block; + > div { + &:first-child { + margin-right: $spacer; + } - &:last-child { - text-align: right; - } - - &:only-child { - text-align: left; + &:last-child { + margin-left: $spacer; + text-align: right; + } } } + +.number { + text-align: center; + width: 2rem; + height: 2rem; + line-height: 1.7; + display: inline-block; + border-radius: 50%; + border: 1px solid transparent; + + &:hover, + &:focus { + background: rgba(255, 255, 255, .3); + border-color: darken($brand-grey-dimmed, 5%); + } +} + +.current { + composes: number; + cursor: default; + pointer-events: none; + border: 1px solid darken($brand-grey-dimmed, 5%); + color: $brand-grey-light; +} diff --git a/src/styles/global.scss b/src/styles/global.scss index 9f5957dc..691ccb34 100644 --- a/src/styles/global.scss +++ b/src/styles/global.scss @@ -202,7 +202,6 @@ picture { height: auto; margin: 0 auto; display: block; - border-radius: $border-radius; } img { @@ -323,14 +322,14 @@ cite { blockquote, blockquote > p { font-style: italic; - color: $brand-grey; + color: $brand-grey-light; } // stylelint-enable no-descending-specificity blockquote { margin: 0 0 $spacer; position: relative; - padding-left: $spacer * 1.5; + padding-left: $spacer * 1.25; // quotation marks &::before { diff --git a/src/templates/Posts.jsx b/src/templates/Posts.jsx index 738b35dc..722c7a06 100644 --- a/src/templates/Posts.jsx +++ b/src/templates/Posts.jsx @@ -15,7 +15,7 @@ import styles from './Posts.module.scss' const Posts = ({ data, location, pageContext }) => { const edges = data.allMarkdownRemark.edges - const { tag, previousPagePath, humanPageNumber, numberOfPages } = pageContext + const { tag, currentPageNumber, numPages } = pageContext const PostsList = edges.map(({ node }) => { const { type, linkurl, title, image } = node.frontmatter @@ -58,11 +58,11 @@ const Posts = ({ data, location, pageContext }) => { {location.pathname === '/' && } - {tag &&

{tag}

} - {previousPagePath && ( + {tag &&

#{tag}

} + {currentPageNumber > 1 && (

{`Page ${humanPageNumber} / ${numberOfPages}`}

+ >{`Page ${currentPageNumber} / ${numPages}`} )} {PostsList}