From cb48215bc470779a5d666446387593bd25282aaa Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Sat, 4 Jul 2020 20:31:24 +0300 Subject: [PATCH] added category page --- gatsby-node.esm.js | 60 +++++++++++ gatsby-node.js | 41 +------ package-lock.json | 5 + package.json | 1 + src/components/Article/Article.js | 5 +- .../Articles/ArticleCard/ArticleCard.js | 3 +- src/helpers/slugify.js | 67 ++++++++++++ src/pages/index.js | 2 +- src/templates/categoryTemplate.js | 100 ++++++++++++++++++ static/admin/config.yml | 4 +- 10 files changed, 243 insertions(+), 45 deletions(-) create mode 100644 gatsby-node.esm.js create mode 100644 src/helpers/slugify.js create mode 100644 src/templates/categoryTemplate.js diff --git a/gatsby-node.esm.js b/gatsby-node.esm.js new file mode 100644 index 0000000..3300502 --- /dev/null +++ b/gatsby-node.esm.js @@ -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); +}; diff --git a/gatsby-node.js b/gatsby-node.js index 47a7474..20728a7 100644 --- a/gatsby-node.js +++ b/gatsby-node.js @@ -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); -}; \ No newline at end of file +require = require('esm')(module) +module.exports = require('./gatsby-node.esm.js') \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 29bac13..c3ca23a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -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", diff --git a/package.json b/package.json index dc85f95..b97071d 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/src/components/Article/Article.js b/src/components/Article/Article.js index 6a4f4ec..9be7388 100644 --- a/src/components/Article/Article.js +++ b/src/components/Article/Article.js @@ -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

{title}

- {category} + {category}
Поделиться: @@ -68,7 +69,7 @@ const Article = ({ data: { title, image, description, category, tags, time, date
- Смотреть еще в категории {category} + Смотреть еще в категории {category}
diff --git a/src/components/Articles/ArticleCard/ArticleCard.js b/src/components/Articles/ArticleCard/ArticleCard.js index a9d2eb6..0700119 100644 --- a/src/components/Articles/ArticleCard/ArticleCard.js +++ b/src/components/Articles/ArticleCard/ArticleCard.js @@ -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 }

{title}

- {category} + {category}
    diff --git a/src/helpers/slugify.js b/src/helpers/slugify.js new file mode 100644 index 0000000..f198d55 --- /dev/null +++ b/src/helpers/slugify.js @@ -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 \ No newline at end of file diff --git a/src/pages/index.js b/src/pages/index.js index e625367..3393afc 100644 --- a/src/pages/index.js +++ b/src/pages/index.js @@ -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 { diff --git a/src/templates/categoryTemplate.js b/src/templates/categoryTemplate.js new file mode 100644 index 0000000..9409f75 --- /dev/null +++ b/src/templates/categoryTemplate.js @@ -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 ( + + +
    +
    +
    +
    +
    +
    +

    Статьи

    +
    +
    +
    + Все +
    +
    + Javascript +
    +
    + GraphQL +
    +
    + Reactjs +
    +
    + SEO оптимизация +
    +
    + Web разработка +
    +
    + pet-проекты +
    +
    + Nodejs +
    +
    + ООП +
    +
    + Новости +
    +
    +
    + + 278 +
    +
    +
    +
    +
    +
    + + +
    +
    + +
    +
    +
    +
    +
    + ) +} + +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 diff --git a/static/admin/config.yml b/static/admin/config.yml index e7c187e..4a76c02 100644 --- a/static/admin/config.yml +++ b/static/admin/config.yml @@ -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"}