Add pagination

This commit is contained in:
alxshelepenok
2018-11-11 14:19:06 +03:00
parent 38090a3a0f
commit 338317803e
24 changed files with 404 additions and 48 deletions

View File

@@ -0,0 +1,37 @@
import React from 'react';
import classNames from 'classnames/bind';
import { Link } from 'gatsby';
import { PAGINATION } from '../../constants';
import styles from './Pagination.module.scss';
const cx = classNames.bind(styles);
const Pagination = ({
prevPagePath,
nextPagePath,
hasNextPage,
hasPrevPage
}) => {
const prevClassName = cx({
'pagination__prev-link': true,
'pagination__prev-link--disable': !hasPrevPage
});
const nextClassName = cx({
'pagination__next-link': true,
'pagination__next-link--disable': !hasNextPage
});
return (
<div className={styles['pagination']}>
<div className={styles['pagination__prev']}>
<Link rel="prev" to={prevPagePath} className={prevClassName}>{PAGINATION.PREV_PAGE}</Link>
</div>
<div className={styles['pagination__next']}>
<Link rel="next" to={nextPagePath} className={nextClassName}>{PAGINATION.NEXT_PAGE}</Link>
</div>
</div>
)
};
export default Pagination;

View File

@@ -0,0 +1,54 @@
@import '../../assets/scss/variables';
@import '../../assets/scss/mixins';
.pagination {
@include margin-top(2);
display: flex;
&__prev {
width: 50%;
text-align: left;
&-link {
color: $color-secondary;
font-size: 26px;
font-weight: bold;
&:hover,
&:focus {
color: $color-primary;
}
&--disable {
pointer-events: none;
color: lighten($color-gray, 20%);
}
}
}
&__next {
width: 50%;
text-align: right;
&-link {
color: $color-secondary;
font-size: 26px;
font-weight: bold;
&:hover,
&:focus {
color: $color-primary;
}
&--disable {
pointer-events: none;
color: lighten($color-gray, 20%);
}
}
}
}

View File

@@ -0,0 +1,17 @@
import React from 'react';
import renderer from 'react-test-renderer';
import Pagination from './Pagination';
describe('Pagination', () => {
const props = {
prevPagePath: '/page/1',
nextPagePath: '/page/3',
hasNextPage: true,
hasPrevPage: true
};
it('renders correctly', () => {
const tree = renderer.create(<Pagination {...props} />).toJSON();
expect(tree).toMatchSnapshot();
});
});

View File

@@ -0,0 +1,28 @@
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`Pagination renders correctly 1`] = `
<div
className="pagination"
>
<div
className="pagination__prev"
>
<Link
className="pagination__prev-link"
to="/page/1"
>
← PREV
</Link>
</div>
<div
className="pagination__next"
>
<Link
className="pagination__next-link"
to="/page/3"
>
→ NEXT
</Link>
</div>
</div>
`;

View File

@@ -0,0 +1 @@
export { default } from './Pagination';

View File

@@ -1 +1,2 @@
export { default as ICONS } from './icons';
export { default as PAGINATION } from './pagination';

View File

@@ -0,0 +1,6 @@
const PAGINATION = {
PREV_PAGE: '← PREV',
NEXT_PAGE: '→ NEXT'
};
export default PAGINATION;

View File

@@ -121,6 +121,30 @@ exports[`CategoryTemplate renders correctly 1`] = `
</Link>
</div>
</div>
<div
className="pagination"
>
<div
className="pagination__prev"
>
<Link
className="pagination__prev-link"
to="/page/1"
>
← PREV
</Link>
</div>
<div
className="pagination__next"
>
<Link
className="pagination__next-link"
to="/page/3"
>
→ NEXT
</Link>
</div>
</div>
</div>
</div>
</div>

View File

@@ -116,6 +116,30 @@ exports[`IndexTemplate renders correctly 1`] = `
</Link>
</div>
</div>
<div
className="pagination"
>
<div
className="pagination__prev"
>
<Link
className="pagination__prev-link"
to="/page/1"
>
← PREV
</Link>
</div>
<div
className="pagination__next"
>
<Link
className="pagination__next-link"
to="/page/3"
>
→ NEXT
</Link>
</div>
</div>
</div>
</div>
</div>

View File

@@ -121,6 +121,30 @@ exports[`TagTemplate renders correctly 1`] = `
</Link>
</div>
</div>
<div
className="pagination"
>
<div
className="pagination__prev"
>
<Link
className="pagination__prev-link"
to="/page/1"
>
← PREV
</Link>
</div>
<div
className="pagination__next"
>
<Link
className="pagination__next-link"
to="/page/3"
>
→ NEXT
</Link>
</div>
</div>
</div>
</div>
</div>

View File

@@ -4,6 +4,7 @@ import Layout from '../components/Layout';
import Sidebar from '../components/Sidebar';
import Feed from '../components/Feed';
import Page from '../components/Page';
import Pagination from '../components/Pagination';
const CategoryTemplate = ({ data, pageContext }) => {
const {
@@ -13,24 +14,34 @@ const CategoryTemplate = ({ data, pageContext }) => {
const {
category,
page
currentPage,
prevPagePath,
nextPagePath,
hasPrevPage,
hasNextPage,
} = pageContext;
const { edges } = data.allMarkdownRemark;
const pageTitle = page > 0 ? `${category} - Page ${page} - ${siteTitle}` : `${category} - ${siteTitle}`;
const pageTitle = currentPage > 0 ? `${category} - Page ${currentPage} - ${siteTitle}` : `${category} - ${siteTitle}`;
return (
<Layout title={pageTitle} description={siteSubtitle}>
<Sidebar />
<Page title={category}>
<Feed edges={edges} />
<Pagination
prevPagePath={prevPagePath}
nextPagePath={nextPagePath}
hasPrevPage={hasPrevPage}
hasNextPage={hasNextPage}
/>
</Page>
</Layout>
);
};
export const query = graphql`
query CategoryPage($category: String, $limit: Int!, $skip: Int!) {
query CategoryPage($category: String, $postsLimit: Int!, $postsOffset: Int!) {
site {
siteMetadata {
title
@@ -38,8 +49,8 @@ export const query = graphql`
}
}
allMarkdownRemark(
limit: $limit,
skip: $skip,
limit: $postsLimit,
skip: $postsOffset,
filter: { frontmatter: { category: { eq: $category }, layout: { eq: "post" }, draft: { ne: true } } },
sort: { order: DESC, fields: [frontmatter___date] }
){

View File

@@ -56,7 +56,11 @@ describe('CategoryTemplate', () => {
},
pageContext: {
category: 'test',
page: 1
currentPage: 1,
prevPagePath: '/page/1',
nextPagePath: '/page/3',
hasNextPage: true,
hasPrevPage: true
}
};

View File

@@ -4,6 +4,7 @@ import Layout from '../components/Layout';
import Sidebar from '../components/Sidebar';
import Feed from '../components/Feed';
import Page from '../components/Page';
import Pagination from '../components/Pagination';
const IndexTemplate = ({ data, pageContext }) => {
const {
@@ -11,22 +12,35 @@ const IndexTemplate = ({ data, pageContext }) => {
subtitle: siteSubtitle
} = data.site.siteMetadata;
const { page } = pageContext;
const {
currentPage,
hasNextPage,
hasPrevPage,
prevPagePath,
nextPagePath
} = pageContext;
const { edges } = data.allMarkdownRemark;
const pageTitle = page > 0 ? `Posts - Page ${page} - ${siteTitle}` : siteTitle;
const pageTitle = currentPage > 0 ? `Posts - Page ${currentPage} - ${siteTitle}` : siteTitle;
return (
<Layout title={`${pageTitle}`} description={siteSubtitle}>
<Layout title={pageTitle} description={siteSubtitle}>
<Sidebar />
<Page>
<Feed edges={edges} />
<Pagination
prevPagePath={prevPagePath}
nextPagePath={nextPagePath}
hasPrevPage={hasPrevPage}
hasNextPage={hasNextPage}
/>
</Page>
</Layout>
);
};
export const query = graphql`
query IndexTemplate($limit: Int!, $skip: Int!) {
query IndexTemplate($postsLimit: Int!, $postsOffset: Int!) {
site {
siteMetadata {
title
@@ -34,8 +48,8 @@ export const query = graphql`
}
}
allMarkdownRemark(
limit: $limit,
skip: $skip,
limit: $postsLimit,
skip: $postsOffset,
filter: { frontmatter: { layout: { eq: "post" }, draft: { ne: true } } },
sort: { order: DESC, fields: [frontmatter___date] }
){

View File

@@ -45,7 +45,11 @@ describe('IndexTemplate', () => {
}
},
pageContext: {
page: 1
currentPage: 1,
prevPagePath: '/page/1',
nextPagePath: '/page/3',
hasNextPage: true,
hasPrevPage: true
}
};

View File

@@ -4,6 +4,7 @@ import Layout from '../components/Layout';
import Sidebar from '../components/Sidebar';
import Feed from '../components/Feed';
import Page from '../components/Page';
import Pagination from '../components/Pagination';
const TagTemplate = ({ data, pageContext }) => {
const {
@@ -12,25 +13,35 @@ const TagTemplate = ({ data, pageContext }) => {
} = data.site.siteMetadata;
const {
page,
tag
tag,
currentPage,
prevPagePath,
nextPagePath,
hasPrevPage,
hasNextPage
} = pageContext;
const { edges } = data.allMarkdownRemark;
const pageTitle = page > 0 ? `All Posts tagged as "${tag}" - Page ${page} - ${siteTitle}` : `All Posts tagged as "${tag}" - ${siteTitle}`;
const pageTitle = currentPage > 0 ? `All Posts tagged as "${tag}" - Page ${currentPage} - ${siteTitle}` : `All Posts tagged as "${tag}" - ${siteTitle}`;
return (
<Layout title={pageTitle} description={siteSubtitle}>
<Sidebar />
<Page title={tag}>
<Feed edges={edges} />
<Pagination
prevPagePath={prevPagePath}
nextPagePath={nextPagePath}
hasPrevPage={hasPrevPage}
hasNextPage={hasNextPage}
/>
</Page>
</Layout>
);
};
export const query = graphql`
query TagPage($tag: String, $limit: Int!, $skip: Int!) {
query TagPage($tag: String, $postsLimit: Int!, $postsOffset: Int!) {
site {
siteMetadata {
title
@@ -38,8 +49,8 @@ export const query = graphql`
}
}
allMarkdownRemark(
limit: $limit,
skip: $skip,
limit: $postsLimit,
skip: $postsOffset,
filter: { frontmatter: { tags: { in: [$tag] }, layout: { eq: "post" }, draft: { ne: true } } },
sort: { order: DESC, fields: [frontmatter___date] }
){

View File

@@ -56,7 +56,11 @@ describe('TagTemplate', () => {
},
pageContext: {
tag: 'test',
page: 1
currentPage: 1,
prevPagePath: '/page/1',
nextPagePath: '/page/3',
hasNextPage: true,
hasPrevPage: true
}
};