added category page

This commit is contained in:
Sergey Yarkov 2020-07-04 20:31:24 +03:00
parent 8abf87d842
commit cb48215bc4
10 changed files with 243 additions and 45 deletions

60
gatsby-node.esm.js Normal file
View File

@ -0,0 +1,60 @@
import slugify from './src/helpers/slugify'
import { fmImagesToRelative } from 'gatsby-remark-relative-images'
import path from 'path'
exports.createPages = async ({ actions, graphql }) => {
const { createPage } = actions
const articleTemplate = path.resolve('src/templates/articleTemplate.js')
const categoryTemplate = path.resolve('src/templates/categoryTemplate.js')
const result = await graphql(
`
{
allMarkdownRemark {
edges {
node {
frontmatter {
templateKey
slug
title
}
}
}
}
}
`
)
if (result.errors) {
throw result.errors
}
const all = result.data.allMarkdownRemark.edges
const articles = all.filter(article => article.node.frontmatter.templateKey === 'article')
const categories = all.filter(category => category.node.frontmatter.templateKey === 'category')
articles.forEach(({ node }) => {
createPage({
path: `article/${node.frontmatter.slug}`,
component: articleTemplate,
context: {
slug: node.frontmatter.slug
},
});
});
categories.forEach(({ node }) => {
createPage({
path: `category/${slugify(node.frontmatter.title)}`,
component: categoryTemplate,
context: {
title: node.frontmatter.title
},
});
})
}
exports.onCreateNode = ({ node }) => {
fmImagesToRelative(node);
};

View File

@ -1,39 +1,2 @@
const { fmImagesToRelative } = require('gatsby-remark-relative-images');
const path = require('path')
exports.createPages = ({ actions, graphql }) => {
const { createPage } = actions
const articleTemplate = path.resolve('src/templates/articleTemplate.js')
return graphql(`
{
allMarkdownRemark(filter: {frontmatter: {templateKey: {eq: "article"}}}) {
edges {
node {
frontmatter {
slug
}
}
}
}
}
`).then(result => {
if (result.errors) {
return Promise.reject(result.errors);
}
result.data.allMarkdownRemark.edges.forEach(({ node }) => {
createPage({
path: `article/${node.frontmatter.slug}`,
component: articleTemplate,
context: {
slug: node.frontmatter.slug
},
});
});
})
}
exports.onCreateNode = ({ node }) => {
fmImagesToRelative(node);
};
require = require('esm')(module)
module.exports = require('./gatsby-node.esm.js')

5
package-lock.json generated
View File

@ -7314,6 +7314,11 @@
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
"integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ=="
},
"esm": {
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
"integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA=="
},
"espree": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",

View File

@ -16,6 +16,7 @@
},
"dependencies": {
"@reach/router": "^1.3.4",
"esm": "^3.2.25",
"gatsby": "^2.23.12",
"gatsby-image": "^2.4.12",
"gatsby-plugin-netlify-cms": "^4.3.9",

View File

@ -1,6 +1,7 @@
import React from 'react';
import SEO from '../SEO/SEO'
import Img from "gatsby-image"
import slugify from '../../helpers/slugify'
import { Link } from 'gatsby'
import './Article.scss'
@ -35,7 +36,7 @@ const Article = ({ data: { title, image, description, category, tags, time, date
<h1>{title}</h1>
</div>
<div className="article-category">
<Link to={`/category/${category}`}>{category}</Link>
<Link to={`/category/${slugify(category)}`}>{category}</Link>
</div>
<div className="article-share">
<span>Поделиться:</span>
@ -68,7 +69,7 @@ const Article = ({ data: { title, image, description, category, tags, time, date
<div dangerouslySetInnerHTML={{__html: html}}></div>
</div>
<div className="article-more">
<span>Смотреть еще в категории <Link to={`/category/${category}`}>{category}</Link></span>
<span>Смотреть еще в категории <Link to={`/category/${slugify(category)}`}>{category}</Link></span>
</div>
<div className="article-comments">
<div className="article-comments__heading">

View File

@ -1,4 +1,5 @@
import React from 'react';
import slugify from '../../../helpers/slugify'
import Img from "gatsby-image"
import { Link } from 'gatsby'
import './ArticleCard.scss'
@ -15,7 +16,7 @@ const ArticleCard = ({ data: { slug, title, image, category, description, tags }
<h2><Link to={`/article/${slug}`}>{title}</Link></h2>
</div>
<div className="article-card__category">
<Link to={`/category/${category}`}>{category}</Link>
<Link to={`/category/${slugify(category)}`}>{category}</Link>
</div>
<div className="article-card__tags">
<ul>

67
src/helpers/slugify.js Normal file
View File

@ -0,0 +1,67 @@
const slugify = str => {
const patterns = {
rus: /^[0-9а-яё-\s]*$/i
}
const translit = str => {
if (str.match(patterns.rus)) {
const ru = {
а: "a",
б: "b",
в: "v",
г: "g",
д: "d",
е: "e",
ё: "e",
ж: "j",
з: "z",
и: "i",
к: "k",
л: "l",
м: "m",
н: "n",
о: "o",
п: "p",
р: "r",
с: "s",
т: "t",
у: "u",
ф: "f",
х: "h",
ц: "c",
ч: "ch",
ш: "sh",
щ: "shch",
ы: "y",
э: "e",
ю: "u",
я: "ya"
},
newStr = [];
for (var i = 0; i < str.length; ++i) {
const candidate = str[i].toLowerCase()
if (ru[candidate]) {
newStr.push(ru[candidate]);
}
if (candidate === '-' || !isNaN(candidate)) {
newStr.push(candidate)
}
}
return newStr.join("");
}
return 'not rus'
}
if (str.match(patterns.rus)) {
return translit(str).split(' ').join('-').toLowerCase()
}
return str.split(' ').join('-').toLowerCase()
};
export default slugify

View File

@ -43,7 +43,7 @@ const IndexPage = ({ data: { allMarkdownRemark: edges } }) => {
export const query = graphql`
{
allMarkdownRemark(filter: {frontmatter: {templateKey: {eq: "article"}}}) {
allMarkdownRemark(filter: {frontmatter: {templateKey: {eq: "article"}}}, sort: {order: DESC, fields: frontmatter___date}) {
edges {
node {
frontmatter {

View File

@ -0,0 +1,100 @@
import React from "react"
import { Link, graphql } from 'gatsby'
import SEO from '../components/SEO/SEO'
import Layout from '../components/Layout/Layout'
import Articles from '../components/Articles/Articles'
import Offers from '../components/Offers/Offers'
import Newsletter from '../components/Newsletter/Newsletter'
const CategoryPage = ({ data: { allMarkdownRemark: edges } }) => {
return (
<Layout>
<SEO title='Категория' />
<main>
<div className="container-fluid">
<div className="row">
<div className="col-md-9 col-xs-12">
<div className="articles">
<div className="articles-heading">
<h1>Статьи</h1>
</div>
<div className="articles-categories">
<div className="tag-item">
<Link to='/'>Все</Link>
</div>
<div className="tag-item">
<Link to='/'>Javascript</Link>
</div>
<div className="tag-item">
<Link to='/'>GraphQL</Link>
</div>
<div className="tag-item">
<Link to='/'>Reactjs</Link>
</div>
<div className="tag-item">
<Link to='/'>SEO оптимизация</Link>
</div>
<div className="tag-item">
<Link to='/'>Web разработка</Link>
</div>
<div className="tag-item">
<Link to='/'>pet-проекты</Link>
</div>
<div className="tag-item">
<Link to='/'>Nodejs</Link>
</div>
<div className="tag-item">
<Link to='/'>ООП</Link>
</div>
<div className="tag-item">
<Link to='/'>Новости</Link>
</div>
</div>
<div className="articles-search">
<input placeholder="Напишите сюда чтобы отфильтровать статьи" type="text" />
<span>278</span>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-md-9 col-xs-12">
<Articles data={edges} />
<Newsletter />
</div>
<div className="col-md-3 col-xs-12">
<Offers />
</div>
</div>
</div>
</main>
</Layout>
)
}
export const pageQuery = graphql`
query articleByCategory($title: String!) {
allMarkdownRemark(filter: {frontmatter: {category: {eq: $title}}}) {
edges {
node {
frontmatter {
slug
title
image {
childImageSharp {
fluid {
...GatsbyImageSharpFluid
}
}
}
category
tags
description
}
}
}
}
}
`
export default CategoryPage

View File

@ -14,8 +14,8 @@ collections:
- {label: "Slug", name: "slug", widget: "string"}
- {label: "Время чтения", name: "time", widget: "string"}
- {label: "Заголовок", name: "title", widget: "string"}
- {labe: "Обложка", name: "image", widget: "image"}
- {label: "Категория", name: "category", widget: "relation", collection: "categories", valueField: "title", searchFields: ["title"]}
- {label: "Обложка", name: "image", widget: "image"}
- {label: "Категория", name: "category", widget: "relation", collection: "categories", valueField: "title", searchFields: ["title", "slug"]}
- {label: "Дата публикации", name: "date", widget: "datetime"}
- {label: "Описание", name: "description", widget: "text"}
- {label: "Содержание", name: "body", widget: "markdown"}