1
0
mirror of https://github.com/kremalicious/blog.git synced 2025-01-05 03:15:07 +01:00

improved pagination

This commit is contained in:
Matthias Kretschmann 2018-09-29 20:43:10 +02:00
parent 6e655b6a6d
commit 7006b168bf
Signed by: m
GPG Key ID: 606EEEF3C479A91F
6 changed files with 124 additions and 87 deletions

View File

@ -2,7 +2,6 @@ const path = require('path')
const fs = require('fs') const fs = require('fs')
const yaml = require('js-yaml') const yaml = require('js-yaml')
const { createFilePath } = require('gatsby-source-filesystem') const { createFilePath } = require('gatsby-source-filesystem')
const { paginate } = require('gatsby-awesome-pagination')
const fastExif = require('fast-exif') const fastExif = require('fast-exif')
const Fraction = require('fraction.js') const Fraction = require('fraction.js')
const dms2dec = require('dms2dec') const dms2dec = require('dms2dec')
@ -172,12 +171,13 @@ exports.createPages = ({ graphql, actions }) => {
} }
const posts = result.data.allMarkdownRemark.edges const posts = result.data.allMarkdownRemark.edges
const numPages = Math.ceil(posts.length / itemsPerPage)
// Generate posts & posts index // Generate posts & posts index
generateContent(createPage, posts) generateContent(createPage, posts, numPages)
// Generate Tag Pages // Generate Tag Pages
generateTagPages(createPage, posts) generateTagPages(createPage, posts, numPages)
// create manual redirects // create manual redirects
redirects.forEach(({ f, t }) => { redirects.forEach(({ f, t }) => {
@ -196,7 +196,7 @@ exports.createPages = ({ graphql, actions }) => {
const postsTemplate = path.resolve('src/templates/Posts.jsx') 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') const postTemplate = path.resolve('src/templates/Post.jsx')
// Create Post pages // Create Post pages
@ -210,69 +210,49 @@ const generateContent = (createPage, posts) => {
}) })
}) })
// Create paginated front page // Create paginated Blog index pages
paginate({ Array.from({ length: numPages }).forEach((_, i) => {
createPage, createPage({
items: posts, path: i === 0 ? '/' : `/page/${i + 1}`,
itemsPerPage: itemsPerPage, component: postsTemplate,
pathPrefix: '/', context: {
component: postsTemplate limit: itemsPerPage,
skip: i * itemsPerPage,
numPages,
currentPageNumber: i + 1,
prevPage: i - 1,
nextPage: i + 2
}
})
}) })
} }
const generateTagPages = (createPage, posts) => { const generateTagPages = (createPage, posts) => {
const tagSet = new Set() const tagList = arrayReducer(posts, 'tags')
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)
tagList.forEach(tag => { tagList.forEach(tag => {
if (tag === 'goodies') return if (tag === 'goodies') return
// Create tag pages // Create tag pages
createPage({ createPage({
path: `/tag/${tag}/`, path: `/tags/${tag}/`,
component: postsTemplate, component: postsTemplate,
context: { tag } 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) { // https://www.adamjberkowitz.com/tags-and-categories-in-gatsby-js/
// return array const arrayReducer = (postsArray, type) => {
// .slice(0) return (postsArray = postsArray
// .slice((page_number - 1) * page_size, page_number * page_size) .map(({ node }) => {
// } return node.frontmatter[type]
})
.reduce((a, b) => {
return a.concat(b)
}, [])
.filter((type, index, array) => {
return array.indexOf(type) === index
})
.sort())
}

View File

@ -28,7 +28,6 @@
"fast-exif": "^1.0.1", "fast-exif": "^1.0.1",
"fraction.js": "^4.0.9", "fraction.js": "^4.0.9",
"gatsby": "^2.0.12", "gatsby": "^2.0.12",
"gatsby-awesome-pagination": "^0.3.1",
"gatsby-image": "^2.0.12", "gatsby-image": "^2.0.12",
"gatsby-plugin-catch-links": "^2.0.3", "gatsby-plugin-catch-links": "^2.0.3",
"gatsby-plugin-favicon": "^3.1.4", "gatsby-plugin-favicon": "^3.1.4",

View File

@ -3,25 +3,61 @@ import PropTypes from 'prop-types'
import { Link } from 'gatsby' import { Link } from 'gatsby'
import styles from './Pagination.module.scss' import styles from './Pagination.module.scss'
const Pagination = ({ pageContext }) => { const PageNumber = ({ i, current }) => (
const { previousPagePath, nextPagePath } = pageContext <Link
className={current ? styles.current : styles.number}
to={i === 0 ? '' : `/page/${i + 1}`}
>
{i + 1}
</Link>
)
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 ( return (
<div className={styles.pagination}> <Link to={link} rel={rel} title={title}>
{nextPagePath ? ( {prevPagePath ? '←' : '→'}
<Link className={styles.paginationLink} to={nextPagePath}> </Link>
&laquo; Older Posts
</Link>
) : null}
{previousPagePath ? (
<Link className={styles.paginationLink} to={previousPagePath}>
Newer Posts &raquo;
</Link>
) : null}
</div>
) )
} }
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 ? (
<div className={styles.pagination}>
<div>{!isFirst && <PrevNext prevPagePath={prevPagePath} />}</div>
<div>
{Array.from({ length: numPages }, (_, i) => (
<PageNumber
key={`pagination-number${i + 1}`}
i={i}
current={currentPageNumber === i + 1}
/>
))}
</div>
<div>{!isLast && <PrevNext nextPagePath={nextPagePath} />}</div>
</div>
) : null
}
Pagination.propTypes = { Pagination.propTypes = {
pageContext: PropTypes.object.isRequired pageContext: PropTypes.object.isRequired
} }

View File

@ -3,18 +3,41 @@
.pagination { .pagination {
display: flex; display: flex;
margin-top: $spacer * 2; margin-top: $spacer * 2;
margin-bottom: $spacer * 2; margin-bottom: $spacer;
} justify-content: center;
.paginationLink { > div {
flex: 1 1 50%; &:first-child {
display: block; margin-right: $spacer;
}
&:last-child { &:last-child {
text-align: right; margin-left: $spacer;
} text-align: right;
}
&:only-child {
text-align: left;
} }
} }
.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;
}

View File

@ -202,7 +202,6 @@ picture {
height: auto; height: auto;
margin: 0 auto; margin: 0 auto;
display: block; display: block;
border-radius: $border-radius;
} }
img { img {
@ -323,14 +322,14 @@ cite {
blockquote, blockquote,
blockquote > p { blockquote > p {
font-style: italic; font-style: italic;
color: $brand-grey; color: $brand-grey-light;
} }
// stylelint-enable no-descending-specificity // stylelint-enable no-descending-specificity
blockquote { blockquote {
margin: 0 0 $spacer; margin: 0 0 $spacer;
position: relative; position: relative;
padding-left: $spacer * 1.5; padding-left: $spacer * 1.25;
// quotation marks // quotation marks
&::before { &::before {

View File

@ -15,7 +15,7 @@ import styles from './Posts.module.scss'
const Posts = ({ data, location, pageContext }) => { const Posts = ({ data, location, pageContext }) => {
const edges = data.allMarkdownRemark.edges const edges = data.allMarkdownRemark.edges
const { tag, previousPagePath, humanPageNumber, numberOfPages } = pageContext const { tag, currentPageNumber, numPages } = pageContext
const PostsList = edges.map(({ node }) => { const PostsList = edges.map(({ node }) => {
const { type, linkurl, title, image } = node.frontmatter const { type, linkurl, title, image } = node.frontmatter
@ -58,11 +58,11 @@ const Posts = ({ data, location, pageContext }) => {
<Layout location={location}> <Layout location={location}>
<SEO /> <SEO />
{location.pathname === '/' && <Featured />} {location.pathname === '/' && <Featured />}
{tag && <h1 className={styles.archiveTitle}>{tag}</h1>} {tag && <h1 className={styles.archiveTitle}>#{tag}</h1>}
{previousPagePath && ( {currentPageNumber > 1 && (
<h1 <h1
className={styles.archiveTitle} className={styles.archiveTitle}
>{`Page ${humanPageNumber} / ${numberOfPages}`}</h1> >{`Page ${currentPageNumber} / ${numPages}`}</h1>
)} )}
{PostsList} {PostsList}
<Pagination pageContext={pageContext} /> <Pagination pageContext={pageContext} />