From dae20275be42c48a93268390b081bc2c1b426731 Mon Sep 17 00:00:00 2001 From: Sergey Yarkov Date: Fri, 3 Jul 2020 14:38:27 +0300 Subject: [PATCH] article page --- gatsby-browser.js | 2 + gatsby-config.js | 53 +++++++- gatsby-node.js | 34 ++++++ package-lock.json | 107 +++++++++++++++- package.json | 4 +- src/components/Article/Article.js | 74 ++++++++++++ src/components/Article/Article.scss | 114 ++++++++++++++++++ .../Articles/MoreArticles/MoreArticles.js | 18 +++ .../Articles/MoreArticles/MoreArticles.scss | 19 +++ src/images/facebook-icon__large.svg | 1 + src/images/twitter-icon__large.svg | 1 + src/images/vk-icon.svg | 1 + src/templates/articleTemplate.js | 48 ++++++++ static/admin/config.yml | 2 + 14 files changed, 467 insertions(+), 11 deletions(-) create mode 100644 gatsby-node.js create mode 100644 src/components/Article/Article.js create mode 100644 src/components/Article/Article.scss create mode 100644 src/components/Articles/MoreArticles/MoreArticles.js create mode 100644 src/components/Articles/MoreArticles/MoreArticles.scss create mode 100644 src/images/facebook-icon__large.svg create mode 100644 src/images/twitter-icon__large.svg create mode 100644 src/images/vk-icon.svg create mode 100644 src/templates/articleTemplate.js diff --git a/gatsby-browser.js b/gatsby-browser.js index a00d155..f8a9ecf 100644 --- a/gatsby-browser.js +++ b/gatsby-browser.js @@ -1,5 +1,7 @@ import React from "react" import './src/styles/global.scss' +import 'prismjs/themes/prism-tomorrow.css' +import 'prismjs/plugins/line-numbers/prism-line-numbers.css' import { ThemeProvider } from "./src/context/ThemeContext" export const wrapRootElement = ({ element }) => ( diff --git a/gatsby-config.js b/gatsby-config.js index 1b411ef..857ee34 100644 --- a/gatsby-config.js +++ b/gatsby-config.js @@ -31,10 +31,43 @@ module.exports = { ] }, plugins: [ - 'gatsby-plugin-netlify-cms', - 'gatsby-plugin-react-helmet', - 'gatsby-plugin-sass', - 'gatsby-transformer-remark', + { + resolve: `gatsby-transformer-remark`, + options: { + plugins: [ + { + resolve: `gatsby-remark-prismjs`, + options: { + classPrefix: "language-", + inlineCodeMarker: null, + aliases: {}, + showLineNumbers: false, + noInlineHighlight: false, + languageExtensions: [ + { + language: "superscript", + extend: "javascript", + definition: { + superscript_types: /(SuperType)/, + }, + insertBefore: { + function: { + superscript_keywords: /(superif|superelse)/, + }, + }, + }, + ], + prompt: { + user: "root", + host: "localhost", + global: false, + }, + escapeEntities: {}, + }, + }, + ], + }, + }, { resolve: 'gatsby-plugin-react-svg', options: { @@ -42,6 +75,16 @@ module.exports = { include: /images/ } } - } + }, + { + resolve: 'gatsby-source-filesystem', + options: { + name: 'content', + path: `${__dirname}/content` + } + }, + 'gatsby-plugin-netlify-cms', + 'gatsby-plugin-react-helmet', + 'gatsby-plugin-sass' ], } diff --git a/gatsby-node.js b/gatsby-node.js new file mode 100644 index 0000000..09cac3d --- /dev/null +++ b/gatsby-node.js @@ -0,0 +1,34 @@ +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 + }, + }); + }); + + }) +} \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 0d276b4..ee13c76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -3877,6 +3877,17 @@ "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" }, + "clipboard": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/clipboard/-/clipboard-2.0.6.tgz", + "integrity": "sha512-g5zbiixBRk/wyKakSwCKd7vQXDjFnAMGHoEyBogG/bw9kTD9GvdAvaoRR1ALcEzt3pVKxZR0pViekPMIS0QyGg==", + "optional": true, + "requires": { + "good-listener": "^1.2.2", + "select": "^1.1.2", + "tiny-emitter": "^2.0.0" + } + }, "clipboardy": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz", @@ -5026,6 +5037,12 @@ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "delegate": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/delegate/-/delegate-3.2.0.tgz", + "integrity": "sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==", + "optional": true + }, "delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -7598,10 +7615,38 @@ } } }, + "gatsby-remark-prismjs": { + "version": "3.5.9", + "resolved": "https://registry.npmjs.org/gatsby-remark-prismjs/-/gatsby-remark-prismjs-3.5.9.tgz", + "integrity": "sha512-Nmc5DayvCJQZ+z8Z44fH3aEvDXsb7daY/cEDW02uecwl0xz4g3B7KGEPfI+EDXWCOoB3X5BzYAk/nMKI0UUt1A==", + "requires": { + "@babel/runtime": "^7.10.3", + "parse-numeric-range": "^0.0.2", + "unist-util-visit": "^1.4.1" + }, + "dependencies": { + "unist-util-visit": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-1.4.1.tgz", + "integrity": "sha512-AvGNk7Bb//EmJZyhtRUnNMEpId/AZ5Ph/KUpTI09WHQuDZHKovQ1oEv3mfmKpWKtoMzyMC4GLBm1Zy5k12fjIw==", + "requires": { + "unist-util-visit-parents": "^2.0.0" + } + }, + "unist-util-visit-parents": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-2.1.2.tgz", + "integrity": "sha512-DyN5vD4NE3aSeB+PXYNKxzGsfocxp6asDc2XXE3b0ekO2BaRUpBicbbUygfSvYfUz1IkmjFR1YF7dPklraMZ2g==", + "requires": { + "unist-util-is": "^3.0.0" + } + } + } + }, "gatsby-source-filesystem": { - "version": "2.3.14", - "resolved": "https://registry.npmjs.org/gatsby-source-filesystem/-/gatsby-source-filesystem-2.3.14.tgz", - "integrity": "sha512-AUnSikwa8+bW0DFWOV1Dq8ZUNxCnEGmx7uxxutLTolHSMhFct2cpxwaXX5ITtjqb9KgfcQ+y0EbKhzXLWpmOzg==", + "version": "2.3.18", + "resolved": "https://registry.npmjs.org/gatsby-source-filesystem/-/gatsby-source-filesystem-2.3.18.tgz", + "integrity": "sha512-HcPhm8yIYrpSVCVOiCzE8dGOKfv78Dvw8p86COE/EbvqRyXQ7x2N+v5dZSluSejtoXck0vISa2kJCGPTGzcsbw==", "requires": { "@babel/runtime": "^7.10.3", "better-queue": "^3.8.10", @@ -7609,7 +7654,7 @@ "chokidar": "3.4.0", "file-type": "^12.4.2", "fs-extra": "^8.1.0", - "gatsby-core-utils": "^1.3.8", + "gatsby-core-utils": "^1.3.11", "got": "^9.6.0", "md5-file": "^3.2.3", "mime": "^2.4.6", @@ -7617,9 +7662,22 @@ "progress": "^2.0.3", "read-chunk": "^3.2.0", "valid-url": "^1.0.9", - "xstate": "^4.10.0" + "xstate": "^4.11.0" }, "dependencies": { + "gatsby-core-utils": { + "version": "1.3.11", + "resolved": "https://registry.npmjs.org/gatsby-core-utils/-/gatsby-core-utils-1.3.11.tgz", + "integrity": "sha512-eaplfOveXLl1RCWja7QIke560jUKLprvCXZ446YgQ8vAYB0fXVz3u6AOf7XUmEV9F9PIkNjmfevd1oUPy9qISw==", + "requires": { + "ci-info": "2.0.0", + "configstore": "^5.0.1", + "fs-extra": "^8.1.0", + "node-object-hash": "^2.0.0", + "proper-lockfile": "^4.1.1", + "xdg-basedir": "^4.0.0" + } + }, "got": { "version": "9.6.0", "resolved": "https://registry.npmjs.org/got/-/got-9.6.0.tgz", @@ -7637,6 +7695,11 @@ "to-readable-stream": "^1.0.0", "url-parse-lax": "^3.0.0" } + }, + "xstate": { + "version": "4.11.0", + "resolved": "https://registry.npmjs.org/xstate/-/xstate-4.11.0.tgz", + "integrity": "sha512-v+S3jF2YrM2tFOit8o7+4N3FuFd9IIGcIKHyfHeeNjMlmNmwuiv/IbY9uw7ECifx7H/A9aGLcxPSr0jdjTGDww==" } } }, @@ -8220,6 +8283,15 @@ "minimatch": "~3.0.2" } }, + "good-listener": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/good-listener/-/good-listener-1.2.2.tgz", + "integrity": "sha1-1TswzfkxPf+33JoNR3CWqm0UXFA=", + "optional": true, + "requires": { + "delegate": "^3.1.2" + } + }, "got": { "version": "8.3.2", "resolved": "https://registry.npmjs.org/got/-/got-8.3.2.tgz", @@ -12818,6 +12890,11 @@ "unist-util-visit-children": "^1.0.0" } }, + "parse-numeric-range": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/parse-numeric-range/-/parse-numeric-range-0.0.2.tgz", + "integrity": "sha1-tPCdQTx6282Yf26SM8e0shDJOOQ=" + }, "parse-passwd": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", @@ -13747,6 +13824,14 @@ } } }, + "prismjs": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.20.0.tgz", + "integrity": "sha512-AEDjSrVNkynnw6A+B1DsFkd6AVdTnp+/WoUixFRULlCLZVRZlVQMVWio/16jv7G1FscUxQxOQhWwApgbnxr6kQ==", + "requires": { + "clipboard": "^2.0.0" + } + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -15943,6 +16028,12 @@ } } }, + "select": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/select/-/select-1.1.2.tgz", + "integrity": "sha1-DnNQrN7ICxEIUoeG7B1EGNEbOW0=", + "optional": true + }, "select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -17519,6 +17610,12 @@ "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz", "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q=" }, + "tiny-emitter": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz", + "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==", + "optional": true + }, "tiny-invariant": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.1.0.tgz", diff --git a/package.json b/package.json index 5d444a5..384c658 100644 --- a/package.json +++ b/package.json @@ -21,10 +21,12 @@ "gatsby-plugin-react-helmet": "^3.3.8", "gatsby-plugin-react-svg": "^3.0.0", "gatsby-plugin-sass": "^2.3.7", - "gatsby-source-filesystem": "^2.3.14", + "gatsby-remark-prismjs": "^3.5.9", + "gatsby-source-filesystem": "^2.3.18", "gatsby-transformer-remark": "^2.8.23", "netlify-cms-app": "^2.12.16", "node-sass": "^4.14.1", + "prismjs": "^1.20.0", "prop-types": "^15.7.2", "react": "^16.12.0", "react-dom": "^16.12.0", diff --git a/src/components/Article/Article.js b/src/components/Article/Article.js new file mode 100644 index 0000000..c44f4a0 --- /dev/null +++ b/src/components/Article/Article.js @@ -0,0 +1,74 @@ +import React from 'react'; +import { Link } from 'gatsby' +import './Article.scss' + +import ViewsIcon from '../../images/views-icon.svg' +import VkIcon from '../../images/vk-icon.svg' +import TwitterIcon from '../../images/twitter-icon__large.svg' +import FacebookIcon from '../../images/facebook-icon__large.svg' + +const Article = ({ data: { title, description, category, tags, time }, html }) => { + return ( +
+
+
+
+ ~ {time} мин +
+
+ + 4252 +
+
+
+

{title}

+
+
+ {category} +
+
+ Поделиться: +
+ + + + + + + + + +
+
+
+

+ {description} +

+
+
+ {tags.map((tag, i) =>
+ {tag} +
)} +
+
+ article +
+
+
+
+
+ Смотреть еще в категории {category} +
+
+
+

Комментарии

+
+
+
+
+
+
+ ) +} + +export default Article \ No newline at end of file diff --git a/src/components/Article/Article.scss b/src/components/Article/Article.scss new file mode 100644 index 0000000..ce0c7e3 --- /dev/null +++ b/src/components/Article/Article.scss @@ -0,0 +1,114 @@ +@import '../../styles/variables.scss'; + +.article { + & article { + & .article-info { + display: flex; + margin-bottom: 10px; + font-size: 14px; + &__views { + display: flex; + align-items: center; + margin-left: 15px; + & svg { + margin-right: 7px; + } + } + } + & .article-heading { + margin-bottom: 5px; + & h1 { + font-size: 40px; + font-weight: 700; + line-height: 48px; + color: $black-clr; + } + } + & .article-category { + margin-bottom: 10px; + & a { + font-size: 16px; + } + } + & .article-share { + display: flex; + margin-bottom: 15px; + &__social{ + margin-left: 15px; + & a { + text-decoration: none; + margin-right: 5px; + } + & a:nth-child(3) { + margin-right: 0; + } + } + } + & .article-description { + margin-bottom: 20px; + & p { + font-size: 17px; + color: $black-clr; + } + } + & .article-tags { + display: flex; + margin-bottom: 20px; + } + & .article-image { + & img { + height: auto; + max-width: 100%; + border-radius: 7px; + } + margin-bottom: 25px; + } + & .article-more { + margin: 15px 0; + } + & .article-comments { + margin: 25px 0; + } + } +} + +.dark { + & .article { + & article { + & .article-share { + &__social { + & a { + & svg { + & .vk-icon, .twitter-icon, .facebook-icon { + fill: $white-clr; + } + } + } + } + } + & .article-info, & .article-share { + color: $white-clr; + } + & .article-more { + color: $white-clr; + } + & p, h1, h2, h3, h4, h5, h6, ul, ol { + color: $white-clr; + } + & blockquote { + background: #2A2A2A; + color: $white-clr; + } + } + } +} + +@media (min-width: 768px) and (max-width: 1023px) { + .article { + article { + & .article-image { + padding: 0 5rem; + } + } + } +} \ No newline at end of file diff --git a/src/components/Articles/MoreArticles/MoreArticles.js b/src/components/Articles/MoreArticles/MoreArticles.js new file mode 100644 index 0000000..cfea4c9 --- /dev/null +++ b/src/components/Articles/MoreArticles/MoreArticles.js @@ -0,0 +1,18 @@ +import React from 'react'; +import ArticleCard from '../ArticleCard/ArticleCard' +import './MoreArticles.scss' + +const MoreArticles = () => { + return ( +
+
+

Вам также может понравится...

+
+
+ {[1,2,3,4].map(e => )} +
+
+ ) +} + +export default MoreArticles \ No newline at end of file diff --git a/src/components/Articles/MoreArticles/MoreArticles.scss b/src/components/Articles/MoreArticles/MoreArticles.scss new file mode 100644 index 0000000..f78f2aa --- /dev/null +++ b/src/components/Articles/MoreArticles/MoreArticles.scss @@ -0,0 +1,19 @@ +@import '../../../styles/variables.scss'; + +.more-articles { + margin-top: 40px; + & .more-articles__heading { + margin-bottom: 35px; + } + & .more-articles__content { + display: flex; + justify-content: space-between; + flex-wrap: wrap; + } +} + +.dark { + & .more-articles__heading { + color: $white-clr; + } +} \ No newline at end of file diff --git a/src/images/facebook-icon__large.svg b/src/images/facebook-icon__large.svg new file mode 100644 index 0000000..11bb596 --- /dev/null +++ b/src/images/facebook-icon__large.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/images/twitter-icon__large.svg b/src/images/twitter-icon__large.svg new file mode 100644 index 0000000..8133a8b --- /dev/null +++ b/src/images/twitter-icon__large.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/images/vk-icon.svg b/src/images/vk-icon.svg new file mode 100644 index 0000000..8098be6 --- /dev/null +++ b/src/images/vk-icon.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/src/templates/articleTemplate.js b/src/templates/articleTemplate.js new file mode 100644 index 0000000..1cfbf9b --- /dev/null +++ b/src/templates/articleTemplate.js @@ -0,0 +1,48 @@ +import React from 'react' +import Layout from '../components/Layout/Layout' +import Article from '../components/Article/Article' +import Offers from '../components/Offers/Offers' +import MoreArticles from '../components/Articles/MoreArticles/MoreArticles' +import Newsletter from '../components/Newsletter/Newsletter' +import { graphql } from "gatsby" + +export default function Template ({ data }) { + const { markdownRemark } = data + const { frontmatter, html } = markdownRemark + console.log(markdownRemark.frontmatter) + return ( + +
+
+
+
+
+ + +
+
+ +
+
+
+
+
+ ) +} + +export const pageQuery = graphql` + query Article($slug: String!) { + markdownRemark(frontmatter: {slug: {eq: $slug}}) { + html + frontmatter { + slug + title + time + tags + description + date + category + } + } + } +` \ No newline at end of file diff --git a/static/admin/config.yml b/static/admin/config.yml index c13db86..af29df5 100644 --- a/static/admin/config.yml +++ b/static/admin/config.yml @@ -11,6 +11,8 @@ collections: slug: "{{year}}-{{month}}-{{day}}-{{slug}}" fields: - {label: "Template Key", name: "templateKey", widget: "hidden", default: "article"} + - {label: "Slug", name: "slug", widget: "string"} + - {label: "Время чтения", name: "time", widget: "string"} - {label: "Заголовок", name: "title", widget: "string"} - {label: "Категория", name: "category", widget: "relation", collection: "categories", valueField: "title", searchFields: ["title"]} - {label: "Дата публикации", name: "date", widget: "datetime"}