mirror of
https://github.com/sergeyyarkov/devthread.ru.git
synced 2026-10-11 10:19:13 +03:00
snippet template
This commit is contained in:
parent
8e17931305
commit
53d5030799
@ -8,6 +8,8 @@ import './src/components/Articles/Articles.scss'
|
|||||||
import './src/components/Articles/ArticleCard/ArticleCard.scss'
|
import './src/components/Articles/ArticleCard/ArticleCard.scss'
|
||||||
import './src/components/Newsletter/Newsletter.scss'
|
import './src/components/Newsletter/Newsletter.scss'
|
||||||
import './src/components/Article/Article.scss'
|
import './src/components/Article/Article.scss'
|
||||||
|
import './src/components/Snippet/Snippet.scss'
|
||||||
|
import './src/components/Snippets/Snippets.scss'
|
||||||
import './src/components/Articles/MoreArticles/MoreArticles.scss'
|
import './src/components/Articles/MoreArticles/MoreArticles.scss'
|
||||||
import './src/components/Books/Books.scss'
|
import './src/components/Books/Books.scss'
|
||||||
import './src/components/Contacts/Contacts.scss'
|
import './src/components/Contacts/Contacts.scss'
|
||||||
|
|||||||
@ -22,8 +22,8 @@ module.exports = {
|
|||||||
link: '/contacts'
|
link: '/contacts'
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'Ресурсы',
|
name: 'Сниппеты',
|
||||||
link: '/deleted'
|
link: '/snippets'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
social: {
|
social: {
|
||||||
@ -116,7 +116,7 @@ module.exports = {
|
|||||||
className: `anchor-link`,
|
className: `anchor-link`,
|
||||||
maintainCase: true,
|
maintainCase: true,
|
||||||
removeAccents: true,
|
removeAccents: true,
|
||||||
isIconAfterHeader: true,
|
isIconAfterHeader: false,
|
||||||
elements: [`h1`, `h2`, `h3`, `h4`],
|
elements: [`h1`, `h2`, `h3`, `h4`],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@ -6,6 +6,7 @@ exports.createPages = async ({ actions, graphql }) => {
|
|||||||
const { createPage } = actions
|
const { createPage } = actions
|
||||||
|
|
||||||
const articleTemplate = path.resolve('src/templates/articleTemplate.js')
|
const articleTemplate = path.resolve('src/templates/articleTemplate.js')
|
||||||
|
const snippetTemplate = path.resolve('src/templates/snippetTemplate.js')
|
||||||
const categoryTemplate = path.resolve('src/templates/categoryTemplate.js')
|
const categoryTemplate = path.resolve('src/templates/categoryTemplate.js')
|
||||||
const tagTemplate = path.resolve('src/templates/tagTemplate.js')
|
const tagTemplate = path.resolve('src/templates/tagTemplate.js')
|
||||||
|
|
||||||
@ -33,6 +34,7 @@ exports.createPages = async ({ actions, graphql }) => {
|
|||||||
|
|
||||||
const all = result.data.allMarkdownRemark.edges
|
const all = result.data.allMarkdownRemark.edges
|
||||||
const articles = all.filter(article => article.node.frontmatter.templateKey === 'article')
|
const articles = all.filter(article => article.node.frontmatter.templateKey === 'article')
|
||||||
|
const snippets = all.filter(snippet => snippet.node.frontmatter.templateKey === 'snippet')
|
||||||
const categories = all.filter(category => category.node.frontmatter.templateKey === 'category')
|
const categories = all.filter(category => category.node.frontmatter.templateKey === 'category')
|
||||||
const tags = all.filter(tag => tag.node.frontmatter.templateKey === 'tag')
|
const tags = all.filter(tag => tag.node.frontmatter.templateKey === 'tag')
|
||||||
|
|
||||||
@ -44,7 +46,17 @@ exports.createPages = async ({ actions, graphql }) => {
|
|||||||
slug: node.frontmatter.slug
|
slug: node.frontmatter.slug
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
});
|
})
|
||||||
|
|
||||||
|
snippets.forEach(({ node }) => {
|
||||||
|
createPage({
|
||||||
|
path: `snippet/${node.frontmatter.slug}`,
|
||||||
|
component: snippetTemplate,
|
||||||
|
context: {
|
||||||
|
slug: node.frontmatter.slug
|
||||||
|
},
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
categories.forEach(({ node }) => {
|
categories.forEach(({ node }) => {
|
||||||
createPage({
|
createPage({
|
||||||
|
|||||||
@ -1,6 +1,7 @@
|
|||||||
@import '../../styles/variables.scss';
|
@import '../../styles/variables.scss';
|
||||||
|
|
||||||
.about {
|
.about {
|
||||||
|
margin-bottom: 13rem;
|
||||||
& .about-heading {
|
& .about-heading {
|
||||||
margin-bottom: 45px;
|
margin-bottom: 45px;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -95,6 +95,7 @@ export default Article
|
|||||||
Article.propTypes = {
|
Article.propTypes = {
|
||||||
data: PropTypes.shape({
|
data: PropTypes.shape({
|
||||||
slug: PropTypes.string,
|
slug: PropTypes.string,
|
||||||
|
keywords: PropTypes.array,
|
||||||
title: PropTypes.string,
|
title: PropTypes.string,
|
||||||
image: PropTypes.object,
|
image: PropTypes.object,
|
||||||
description: PropTypes.string,
|
description: PropTypes.string,
|
||||||
|
|||||||
@ -2,7 +2,6 @@ import React from 'react';
|
|||||||
import PropTypes from 'prop-types'
|
import PropTypes from 'prop-types'
|
||||||
import useSiteMetadataQuery from '../../hooks/useSiteMetadataQuery'
|
import useSiteMetadataQuery from '../../hooks/useSiteMetadataQuery'
|
||||||
import ArticleCard from './ArticleCard/ArticleCard'
|
import ArticleCard from './ArticleCard/ArticleCard'
|
||||||
import Newsletter from '../Newsletter/Newsletter'
|
|
||||||
|
|
||||||
const Articles = ({ data: { edges }, limit = 6, setLimit = () => null }) => {
|
const Articles = ({ data: { edges }, limit = 6, setLimit = () => null }) => {
|
||||||
const { siteMetadata: { options: { articles: { onLoadMore } } } } = useSiteMetadataQuery()
|
const { siteMetadata: { options: { articles: { onLoadMore } } } } = useSiteMetadataQuery()
|
||||||
@ -27,7 +26,6 @@ const Articles = ({ data: { edges }, limit = 6, setLimit = () => null }) => {
|
|||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<Newsletter />
|
|
||||||
</>
|
</>
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -58,7 +58,7 @@
|
|||||||
}
|
}
|
||||||
& .articles-loadMore {
|
& .articles-loadMore {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
margin-bottom: 30px;
|
margin-bottom: 50px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,7 +25,6 @@
|
|||||||
padding: 10px;
|
padding: 10px;
|
||||||
font-family: 'Inter', sans-serif;
|
font-family: 'Inter', sans-serif;
|
||||||
font-size: 13px;
|
font-size: 13px;
|
||||||
|
|
||||||
border-radius: 5px 0px 0px 5px;
|
border-radius: 5px 0px 0px 5px;
|
||||||
}
|
}
|
||||||
& button {
|
& button {
|
||||||
|
|||||||
48
src/components/Snippet/Snippet.js
Normal file
48
src/components/Snippet/Snippet.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import PropTypes from 'prop-types'
|
||||||
|
import SEO from '../SEO/SEO'
|
||||||
|
|
||||||
|
const Snippet = ({ data: { keywords, description, title, date }, html }) => {
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<SEO title={title} titleTemplate={false} description={description} keywords={keywords.join(', ')} type='article' />
|
||||||
|
<div className="snippet">
|
||||||
|
<article>
|
||||||
|
<div className="snippet-date">
|
||||||
|
{date}
|
||||||
|
</div>
|
||||||
|
<div className="snippet-heading">
|
||||||
|
<h1>{title}</h1>
|
||||||
|
</div>
|
||||||
|
<div className="snippet-description">
|
||||||
|
<p>
|
||||||
|
{description}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div className="snippet-inner inner">
|
||||||
|
<div dangerouslySetInnerHTML={{__html: html}}></div>
|
||||||
|
</div>
|
||||||
|
<div className="snippet-comments">
|
||||||
|
<div className="snippet-comments__heading">
|
||||||
|
<h2>Комментарии</h2>
|
||||||
|
</div>
|
||||||
|
<div className="snippet-comments__content">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</article>
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Snippet
|
||||||
|
|
||||||
|
Snippet.propTypes = {
|
||||||
|
data: PropTypes.shape({
|
||||||
|
keywords: PropTypes.array,
|
||||||
|
title: PropTypes.string,
|
||||||
|
description: PropTypes.string,
|
||||||
|
date: PropTypes.string
|
||||||
|
}),
|
||||||
|
html: PropTypes.string
|
||||||
|
}
|
||||||
42
src/components/Snippet/Snippet.scss
Normal file
42
src/components/Snippet/Snippet.scss
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
@import '../../styles/variables.scss';
|
||||||
|
|
||||||
|
.snippet {
|
||||||
|
& article {
|
||||||
|
& .snippet-date {
|
||||||
|
text-align: center;
|
||||||
|
font-size: 16px;
|
||||||
|
color: #767676;
|
||||||
|
}
|
||||||
|
& .snippet-heading {
|
||||||
|
font-size: 21px;
|
||||||
|
text-align: center;
|
||||||
|
& h1 {
|
||||||
|
font-size: 40px;
|
||||||
|
}
|
||||||
|
margin-bottom: 15px;
|
||||||
|
}
|
||||||
|
& .snippet-description {
|
||||||
|
margin-bottom: 50px;
|
||||||
|
& p {
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
& .snippet-comments {
|
||||||
|
margin: 25px 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
& .snippet {
|
||||||
|
& article {
|
||||||
|
& p, h1, h2, h3, h4, h5, h6, ul, ol {
|
||||||
|
color: $white-clr;
|
||||||
|
}
|
||||||
|
& blockquote {
|
||||||
|
background: #2A2A2A;
|
||||||
|
color: $white-clr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
33
src/components/Snippets/Snippets.js
Normal file
33
src/components/Snippets/Snippets.js
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import React from 'react';
|
||||||
|
import { Link } from 'gatsby'
|
||||||
|
import useSnippetsQuery from '../../hooks/useSnippetsQuery'
|
||||||
|
|
||||||
|
const Snippets = () => {
|
||||||
|
const { snippets } = useSnippetsQuery()
|
||||||
|
return (
|
||||||
|
<div className='snippets'>
|
||||||
|
<h2>Сниппеты</h2>
|
||||||
|
{snippets.map(({ node: { frontmatter } }, i) => (
|
||||||
|
<div key={i} className='snippet-item'>
|
||||||
|
<div className="left-info">
|
||||||
|
<div className="snippet-item__date">
|
||||||
|
{frontmatter.date}
|
||||||
|
</div>
|
||||||
|
<div className="snippet-item__heading">
|
||||||
|
<Link to={`/snippet/${frontmatter.slug}`}>{frontmatter.title}</Link>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div className="right-info">
|
||||||
|
<div className="snippet-item__tags">
|
||||||
|
{frontmatter.tags.map((tag, i) => (
|
||||||
|
<div key={i} className="tag-item">{tag}</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Snippets
|
||||||
54
src/components/Snippets/Snippets.scss
Normal file
54
src/components/Snippets/Snippets.scss
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
@import '../../styles/variables.scss';
|
||||||
|
|
||||||
|
.snippets {
|
||||||
|
margin-bottom: 40px;
|
||||||
|
& h2 {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
font-size: 34px;
|
||||||
|
}
|
||||||
|
& .snippet-item {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 64px;
|
||||||
|
background: linear-gradient(92.41deg, #F5F9FF 0%, #F6F4FB 100%);
|
||||||
|
border-radius: 7px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
padding: 10px 15px;
|
||||||
|
&__date {
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
&__heading {
|
||||||
|
& a {
|
||||||
|
font-size: 16px;
|
||||||
|
font-weight: 700;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&__tags {
|
||||||
|
display: flex;
|
||||||
|
& .tag-item {
|
||||||
|
margin: 0;
|
||||||
|
margin-right: 5px;
|
||||||
|
padding: 5px 10px;
|
||||||
|
background: #EBF1FE;
|
||||||
|
color: #6ab0f3;
|
||||||
|
font-size: 14px;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dark {
|
||||||
|
& .snippets {
|
||||||
|
color: $white-clr;
|
||||||
|
& .snippet-item {
|
||||||
|
background: #2A2A2A;
|
||||||
|
& .tag-item {
|
||||||
|
color: #5183F5;
|
||||||
|
background: rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
25
src/hooks/useSnippetsQuery.js
Normal file
25
src/hooks/useSnippetsQuery.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import { useStaticQuery, graphql } from 'gatsby'
|
||||||
|
|
||||||
|
const useSnippetsQuery = () => {
|
||||||
|
const { allMarkdownRemark: { edges } } = useStaticQuery(graphql`
|
||||||
|
{
|
||||||
|
allMarkdownRemark(filter: {frontmatter: {templateKey: {eq: "snippet"}}}, sort: {order: DESC, fields: frontmatter___date}) {
|
||||||
|
edges {
|
||||||
|
node {
|
||||||
|
frontmatter {
|
||||||
|
slug
|
||||||
|
title
|
||||||
|
tags
|
||||||
|
description
|
||||||
|
date(formatString: "D MMMM YYYY", locale: "ru-RU")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)
|
||||||
|
|
||||||
|
return { snippets: edges }
|
||||||
|
}
|
||||||
|
|
||||||
|
export default useSnippetsQuery
|
||||||
@ -6,6 +6,7 @@ import useSiteMetadataQuery from '../hooks/useSiteMetadataQuery'
|
|||||||
import SEO from '../components/SEO/SEO'
|
import SEO from '../components/SEO/SEO'
|
||||||
import Layout from '../components/Layout/Layout'
|
import Layout from '../components/Layout/Layout'
|
||||||
import Articles from '../components/Articles/Articles'
|
import Articles from '../components/Articles/Articles'
|
||||||
|
import Snippets from '../components/Snippets/Snippets'
|
||||||
import Offers from '../components/Offers/Offers'
|
import Offers from '../components/Offers/Offers'
|
||||||
|
|
||||||
import ArrowNext from '../images/arrow-next.svg'
|
import ArrowNext from '../images/arrow-next.svg'
|
||||||
@ -32,6 +33,7 @@ const IndexPage = ({ data: { allMarkdownRemark: edges } }) => {
|
|||||||
<Row>
|
<Row>
|
||||||
<Col lg={9} xs={12}>
|
<Col lg={9} xs={12}>
|
||||||
<Articles data={edges} limit={limit} setLimit={setLimit} />
|
<Articles data={edges} limit={limit} setLimit={setLimit} />
|
||||||
|
<Snippets />
|
||||||
</Col>
|
</Col>
|
||||||
<Col lg={3} xs={12}>
|
<Col lg={3} xs={12}>
|
||||||
<Offers />
|
<Offers />
|
||||||
|
|||||||
@ -52,6 +52,10 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.anchor-link.before {
|
||||||
|
top: -2px!important;
|
||||||
|
}
|
||||||
|
|
||||||
.anchor {
|
.anchor {
|
||||||
display: block;
|
display: block;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|||||||
@ -53,7 +53,7 @@ const CategoryPage = ({ data: { allMarkdownRemark: edges }, pageContext: { title
|
|||||||
|
|
||||||
export const pageQuery = graphql`
|
export const pageQuery = graphql`
|
||||||
query articlesByCategory($title: String!) {
|
query articlesByCategory($title: String!) {
|
||||||
allMarkdownRemark(filter: {frontmatter: {category: {eq: $title}}}) {
|
allMarkdownRemark(filter: {frontmatter: {category: {eq: $title}, templateKey: {eq: "article"}}}) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
frontmatter {
|
frontmatter {
|
||||||
|
|||||||
39
src/templates/snippetTemplate.js
Normal file
39
src/templates/snippetTemplate.js
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
import React from 'react'
|
||||||
|
import { Main } from '../ui/ui'
|
||||||
|
import { Grid, Row, Col } from 'react-flexbox-grid'
|
||||||
|
import Snippet from '../components/Snippet/Snippet'
|
||||||
|
import Layout from '../components/Layout/Layout'
|
||||||
|
import { graphql } from "gatsby"
|
||||||
|
|
||||||
|
const snippetTemplate = ({ data: { markdownRemark: { frontmatter, html } } }) => {
|
||||||
|
return (
|
||||||
|
<Layout>
|
||||||
|
<Main>
|
||||||
|
<Grid fluid style={{ maxWidth: 900 }}>
|
||||||
|
<Row>
|
||||||
|
<Col lg={12}>
|
||||||
|
<Snippet data={frontmatter} html={html} />
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</Grid>
|
||||||
|
</Main>
|
||||||
|
</Layout>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export const pageQuery = graphql`
|
||||||
|
query Snippet($slug: String!) {
|
||||||
|
markdownRemark(frontmatter: {slug: {eq: $slug}, templateKey: {eq: "snippet"}}) {
|
||||||
|
html
|
||||||
|
frontmatter {
|
||||||
|
slug
|
||||||
|
keywords
|
||||||
|
title
|
||||||
|
description
|
||||||
|
date(formatString: "D MMMM YYYY", locale: "ru-RU")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`
|
||||||
|
|
||||||
|
export default snippetTemplate
|
||||||
@ -53,7 +53,7 @@ const TagPage = ({ data: { allMarkdownRemark: edges }, pageContext: { title } })
|
|||||||
|
|
||||||
export const pageQuery = graphql`
|
export const pageQuery = graphql`
|
||||||
query articlesByTag($title: [String!]) {
|
query articlesByTag($title: [String!]) {
|
||||||
allMarkdownRemark(filter: {frontmatter: {tags: {in: $title}}}) {
|
allMarkdownRemark(filter: {frontmatter: {tags: {in: $title}, templateKey: {eq: "article"}}}) {
|
||||||
edges {
|
edges {
|
||||||
node {
|
node {
|
||||||
frontmatter {
|
frontmatter {
|
||||||
|
|||||||
@ -22,6 +22,20 @@ collections:
|
|||||||
- {label: "Описание", name: "description", widget: "text"}
|
- {label: "Описание", name: "description", widget: "text"}
|
||||||
- {label: "Содержание", name: "body", widget: "markdown"}
|
- {label: "Содержание", name: "body", widget: "markdown"}
|
||||||
- {label: "Тэги", name: "tags", widget: "relation", multiple: true, collection: "tags", valueField: "title", searchFields: ["title"]}
|
- {label: "Тэги", name: "tags", widget: "relation", multiple: true, collection: "tags", valueField: "title", searchFields: ["title"]}
|
||||||
|
- name: 'snippets'
|
||||||
|
label: "Snippet"
|
||||||
|
folder: 'content/snippets'
|
||||||
|
create: true
|
||||||
|
slug: "{{slug}}"
|
||||||
|
fields:
|
||||||
|
- {label: "Template key", name: "templateKey", widget: "hidden", default: "snippet"}
|
||||||
|
- {label: "Slug", name: "slug", widget: "string"}
|
||||||
|
- {label: "Keywords", name: "keywords", widget: "list"}
|
||||||
|
- {label: "Название сниппета", name: "title", widget: "string"}
|
||||||
|
- {label: "Дата публикации", name: "date", widget: "datetime"}
|
||||||
|
- {label: "Тэги", name: "tags", widget: "list"}
|
||||||
|
- {label: "Описание", name: "description", widget: "text"}
|
||||||
|
- {label: "Содержание", name: "body", widget: "markdown"}
|
||||||
- name: 'categories'
|
- name: 'categories'
|
||||||
label: "Category"
|
label: "Category"
|
||||||
folder: 'content/categories'
|
folder: 'content/categories'
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user