Skip to content

Commit

Permalink
[v1][www] Paginate blog index page (#7646)
Browse files Browse the repository at this point in the history
* v1-pagination
* Fix things for Gatsby v1
  * `pathContext` instead of `pageContext`
  * import `navigateTo` instead of `navigate`, `Link` from `gatsby-link` instead of `gatsby`
  • Loading branch information
calcsam authored and fk committed Aug 26, 2018
1 parent 0f6dde0 commit c199b6b
Show file tree
Hide file tree
Showing 4 changed files with 164 additions and 10 deletions.
18 changes: 18 additions & 0 deletions www/gatsby-node.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ exports.createPages = ({ graphql, boundActionCreators }) => {
return new Promise((resolve, reject) => {
const docsTemplate = path.resolve(`src/templates/template-docs-markdown.js`)
const blogPostTemplate = path.resolve(`src/templates/template-blog-post.js`)
const blogListTemplate = path.resolve(`src/templates/template-blog-list.js`)
const tagTemplate = path.resolve(`src/templates/tags.js`)
const contributorPageTemplate = path.resolve(
`src/templates/template-contributor-page.js`
Expand Down Expand Up @@ -141,6 +142,23 @@ exports.createPages = ({ graphql, boundActionCreators }) => {
})
})

// Create blog-list pages.
const postsPerPage = 8
const numPages = Math.ceil(blogPosts.length / postsPerPage)

Array.from({ length: numPages }).forEach((_, i) => {
createPage({
path: i === 0 ? `/blog` : `/blog/${i + 1}`,
component: slash(blogListTemplate),
context: {
limit: postsPerPage,
skip: i * postsPerPage,
numPages,
currentPage: i + 1,
},
})
})

const tagLists = blogPosts
.filter(post => _.get(post, `node.frontmatter.tags`))
.map(post => _.get(post, `node.frontmatter.tags`))
Expand Down
16 changes: 16 additions & 0 deletions www/src/components/pagination/PaginationLink.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import React from "react"
import Link from "gatsby-link"
import { colors } from "../../utils/presets"

const PaginationLink = ({ to, children, ...props }) => {
if (to) {
return (
<Link to={to} {...props}>
{children}
</Link>
)
}
return <span css={{ color: colors.gray.calm }}>{children}</span>
}

export default PaginationLink
118 changes: 118 additions & 0 deletions www/src/components/pagination/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
import React from "react"
import { navigateTo } from "gatsby-link"
import ArrowForwardIcon from "react-icons/lib/md/arrow-forward"
import ArrowBackIcon from "react-icons/lib/md/arrow-back"
import PaginationLink from "./PaginationLink"
import presets, { colors } from "../../utils/presets"
import { options, rhythm } from "../../utils/typography"

class Pagination extends React.Component {
changePage = e => {
navigateTo(`/blog/${e.target.value}`)
}
render() {
const { numPages, currentPage } = this.props.context
const isFirst = currentPage === 1
const isLast = currentPage === numPages
const prevPageNum =
currentPage - 1 === 1 ? `` : (currentPage - 1).toString()
const nextPageNum = (currentPage + 1).toString()
const prevPageLink = isFirst ? null : `/blog/${prevPageNum}`
const nextPageLink = isLast ? null : `/blog/${nextPageNum}`

const prevNextLinkStyles = {
"&&": {
boxShadow: `none`,
borderBottom: 0,
fontFamily: options.headerFontFamily.join(`,`),
fontWeight: `bold`,
color: colors.gatsby,
},
}

return (
<div
css={{
display: `flex`,
justifyContent: `space-between`,
margin: `${rhythm(1)} 0`,
flexDirection: `column`,
[presets.Tablet]: {
flexDirection: `row`,
},
}}
>
<div
css={{
display: `flex`,
margin: `0`,
padding: `0`,
justifyContent: `space-between`,
alignItems: `center`,
marginBottom: rhythm(1 / 2),
[presets.Tablet]: {
width: `15rem`,
marginBottom: 0,
},
}}
>
<PaginationLink to={prevPageLink} css={prevNextLinkStyles}>
<ArrowBackIcon style={{ verticalAlign: `sub` }} />
Newer posts
</PaginationLink>
<PaginationLink to={nextPageLink} css={prevNextLinkStyles}>
Older posts
<ArrowForwardIcon style={{ verticalAlign: `sub` }} />
</PaginationLink>
</div>
<div
css={{
display: `flex`,
alignItems: `center`,
justifyContent: `flex-end`,
fontFamily: options.headerFontFamily.join(`,`),
}}
>
<span>Showing page &nbsp;</span>
<select
value={currentPage === 1 ? `` : currentPage.toString()}
onChange={this.changePage}
css={{
appearance: `none`,
border: `none`,
padding: `0.5ch 2ch 0.5ch 0.5ch`,
color: `rebeccapurple`,
fontWeight: `bold`,
}}
>
{Array.from({ length: numPages }, (_, i) => (
<option
value={`${i === 0 ? `` : i + 1}`}
key={`pagination-number${i + 1}`}
>
{i + 1}
</option>
))}
</select>
<svg
width="10"
height="5"
viewBox="0 0 10 5"
css={{
position: `relative`,
right: `1.5ch`,
fill: `rebeccapurple`,
pointerEvents: `none`,
}}
>
<path d="M0 0l5 4.998L10 0z" fillRule="evenodd" />
</svg>
<span>of &nbsp;</span>
<span>{numPages}</span>
</div>
</div>
)
}
}

export default Pagination
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import React from "react"
import Helmet from "react-helmet"

import Container from "../../components/container"
import BlogPostPreviewItem from "../../components/blog-post-preview-item"
import EmailCaptureForm from "../../components/email-capture-form"
import Container from "../components/container"
import BlogPostPreviewItem from "../components/blog-post-preview-item"
import Pagination from "../components/pagination"
import EmailCaptureForm from "../components/email-capture-form"

import presets, { colors } from "../../utils/presets"
import { rhythm, scale, options } from "../../utils/typography"
import logo from "../../monogram.svg"
import presets, { colors } from "../utils/presets"
import { rhythm, options } from "../utils/typography"
import logo from "../monogram.svg"

class BlogPostsIndex extends React.Component {
render() {
Expand Down Expand Up @@ -88,12 +89,11 @@ class BlogPostsIndex extends React.Component {
transition: `transform 50ms`,
},
},
[presets.Desktop]: {},
[presets.Hd]: {},
}}
/>
))}
<EmailCaptureForm signupMessage="Enjoying our blog? Receive the next post in your inbox!" />
<Pagination context={this.props.pathContext} />
<EmailCaptureForm signupMessage="Enjoying our blog? Receive the next post in your inbox!" />
</Container>
</div>
)
Expand All @@ -103,13 +103,15 @@ class BlogPostsIndex extends React.Component {
export default BlogPostsIndex

export const pageQuery = graphql`
query BlogPostsIndexQuery {
query blogListQuery($skip: Int!, $limit: Int!) {
allMarkdownRemark(
sort: { order: DESC, fields: [frontmatter___date] }
filter: {
frontmatter: { draft: { ne: true } }
fileAbsolutePath: { regex: "/docs.blog/" }
}
limit: $limit
skip: $skip
) {
edges {
node {
Expand Down

0 comments on commit c199b6b

Please sign in to comment.