mirror of
https://github.com/kremalicious/blog.git
synced 2025-01-03 02:15:08 +01:00
improved pagination
This commit is contained in:
parent
6e655b6a6d
commit
7006b168bf
@ -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())
|
||||
}
|
||||
|
@ -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",
|
||||
|
@ -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 }) => (
|
||||
<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 (
|
||||
<div className={styles.pagination}>
|
||||
{nextPagePath ? (
|
||||
<Link className={styles.paginationLink} to={nextPagePath}>
|
||||
« Older Posts
|
||||
</Link>
|
||||
) : null}
|
||||
{previousPagePath ? (
|
||||
<Link className={styles.paginationLink} to={previousPagePath}>
|
||||
Newer Posts »
|
||||
</Link>
|
||||
) : null}
|
||||
</div>
|
||||
<Link to={link} rel={rel} title={title}>
|
||||
{prevPagePath ? '←' : '→'}
|
||||
</Link>
|
||||
)
|
||||
}
|
||||
|
||||
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 = {
|
||||
pageContext: PropTypes.object.isRequired
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -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 }) => {
|
||||
<Layout location={location}>
|
||||
<SEO />
|
||||
{location.pathname === '/' && <Featured />}
|
||||
{tag && <h1 className={styles.archiveTitle}>{tag}</h1>}
|
||||
{previousPagePath && (
|
||||
{tag && <h1 className={styles.archiveTitle}>#{tag}</h1>}
|
||||
{currentPageNumber > 1 && (
|
||||
<h1
|
||||
className={styles.archiveTitle}
|
||||
>{`Page ${humanPageNumber} / ${numberOfPages}`}</h1>
|
||||
>{`Page ${currentPageNumber} / ${numPages}`}</h1>
|
||||
)}
|
||||
{PostsList}
|
||||
<Pagination pageContext={pageContext} />
|
||||
|
Loading…
Reference in New Issue
Block a user