Merge pull request #29 from tmshv/fix/opengraph-update
OpenGraph update
This commit is contained in:
11 files changed
+222
-134
No files matched your search
+14
-16
@@ -3,8 +3,8 @@ import { App } from 'src/components/App'
|
||||
import { tail } from 'lodash'
|
||||
import { Page } from 'src/components/Page'
|
||||
import { Meta } from 'src/components/Meta'
|
||||
import { meta } from 'src/lib/meta'
|
||||
import { createApiUrl, requestGet, wrapInitialProps, IResponseItems } from 'src/next-lib'
|
||||
import { MetaBuilder } from 'src/lib/meta'
|
||||
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
|
||||
import { NextPage } from 'next'
|
||||
import { IBreadcumbsPart, IMeta, IPage } from 'src/types'
|
||||
|
||||
@@ -15,11 +15,10 @@ function array<T>(value: T | T[]) {
|
||||
}
|
||||
|
||||
type Props = {
|
||||
page: any
|
||||
title: string
|
||||
content: string
|
||||
breadcrumb: IBreadcumbsPart[]
|
||||
meta: IMeta
|
||||
meta?: IMeta
|
||||
}
|
||||
|
||||
const Index: NextPage<Props> = props => (
|
||||
@@ -32,7 +31,9 @@ const Index: NextPage<Props> = props => (
|
||||
>
|
||||
<Head>
|
||||
<title>{props.title}</title>
|
||||
{/* <Meta meta={props.meta} /> */}
|
||||
{!props.meta ? null : (
|
||||
<Meta meta={props.meta} />
|
||||
)}
|
||||
</Head>
|
||||
|
||||
<Page
|
||||
@@ -54,29 +55,26 @@ export const unstable_getStaticProps = async (ctx: any) => {
|
||||
if (!page) {
|
||||
throw new Error(`Not found: ${slug}`)
|
||||
}
|
||||
const image = page.preview ? page.preview.artifacts.fb : {}
|
||||
const breadcrumbSize = page.breadcrumb?.length ?? 0
|
||||
const description = page.description ?? undefined
|
||||
const breadcrumbSize = page?.breadcrumb?.length ?? 0
|
||||
const breadcrumb = breadcrumbSize < 2 ? null : page.breadcrumb
|
||||
const meta = (new MetaBuilder())
|
||||
.setImage(page.preview)
|
||||
.setTitle(page.title)
|
||||
.setDescription(description)
|
||||
.build()
|
||||
|
||||
return {
|
||||
props: {
|
||||
page,
|
||||
content: page.data,
|
||||
title: page.title,
|
||||
meta: meta({
|
||||
title: page.title,
|
||||
image: image.src,
|
||||
imageWidth: image.width,
|
||||
imageHeight: image.height,
|
||||
}),
|
||||
meta,
|
||||
breadcrumb,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const unstable_getStaticPaths = async () => {
|
||||
console.log('call all unstable_getStaticPaths')
|
||||
|
||||
const urls = await requestGet<IResponseItems<string>>(createApiUrl(`/api/pages/urls`), null)
|
||||
if (!urls) {
|
||||
return null
|
||||
|
||||
+13
-17
@@ -1,16 +1,16 @@
|
||||
import Head from 'next/head'
|
||||
import { get } from 'lodash'
|
||||
import { App } from 'src/components/App'
|
||||
import { Article } from 'src/components/Article'
|
||||
import { Html } from 'src/components/Html'
|
||||
import { Meta } from 'src/components/Meta'
|
||||
import { meta } from 'src/lib/meta'
|
||||
import { MetaBuilder } from 'src/lib/meta'
|
||||
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
|
||||
import { NextPage } from 'next'
|
||||
import { IArticle } from 'src/types'
|
||||
import { IArticle, IMeta } from 'src/types'
|
||||
|
||||
type Props = {
|
||||
meta: any
|
||||
title: string
|
||||
meta: IMeta
|
||||
data: IArticle
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@ const Page: NextPage<Props> = props => {
|
||||
showAuthor={true}
|
||||
>
|
||||
<Head>
|
||||
<title>{props.data.title}</title>
|
||||
<title>{props.title}</title>
|
||||
<Meta meta={props.meta} />
|
||||
</Head>
|
||||
<Article
|
||||
title={props.data.title}
|
||||
title={props.title}
|
||||
date={props.data.date}
|
||||
tags={props.data.tags}
|
||||
shareable={true}
|
||||
@@ -43,31 +43,27 @@ const Page: NextPage<Props> = props => {
|
||||
}
|
||||
|
||||
export const unstable_getStaticProps = async (ctx: any) => {
|
||||
const pageUrl = '/'
|
||||
const id = ctx.params.slug
|
||||
const data = await requestGet(createApiUrl(`/api/articles/${id}`), null)
|
||||
const data = await requestGet<IArticle>(createApiUrl(`/api/articles/${id}`), null)
|
||||
if (!data) {
|
||||
return null
|
||||
}
|
||||
|
||||
const image = get(data, 'preview.artifacts.fb', {})
|
||||
const meta = (new MetaBuilder())
|
||||
.setImage(data.preview)
|
||||
.setTitle(data.title)
|
||||
.build()
|
||||
|
||||
return {
|
||||
props: {
|
||||
title: data.title,
|
||||
data,
|
||||
meta: meta({
|
||||
title: data.title,
|
||||
image: image.src,
|
||||
imageWidth: image.width,
|
||||
imageHeight: image.height,
|
||||
}),
|
||||
meta,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const unstable_getStaticPaths = async () => {
|
||||
console.log('call article unstable_getStaticPaths')
|
||||
|
||||
const urls = await requestGet<IResponseItems<string>>(createApiUrl(`/api/articles/urls`), null)
|
||||
if (!urls) {
|
||||
return null
|
||||
|
||||
+11
-15
@@ -2,17 +2,18 @@ import Head from 'next/head'
|
||||
import { range } from 'lodash'
|
||||
import { App } from 'src/components/App'
|
||||
import { ArticleGrid } from 'src/components/ArticleGrid'
|
||||
import { meta } from 'src/lib/meta'
|
||||
import { MetaBuilder } from 'src/lib/meta'
|
||||
import { Meta } from 'src/components/Meta'
|
||||
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
|
||||
import { NextPage } from 'next'
|
||||
import { IArticle } from 'src/types'
|
||||
|
||||
const pageSize = Number(process.env.APP_ARTICLES_PAGE_SIZE)
|
||||
|
||||
type Props = {
|
||||
meta: any
|
||||
title: string
|
||||
data: any //(list of article)
|
||||
data: IArticle[]
|
||||
nextPage: number
|
||||
prevPage: number
|
||||
}
|
||||
@@ -42,20 +43,19 @@ const Page: NextPage<Props> = props => {
|
||||
}
|
||||
|
||||
export const unstable_getStaticProps = async (ctx: any) => {
|
||||
// const page = parseInt(ctx.query.page)
|
||||
const page = parseInt(ctx.params.slug)
|
||||
const res = await requestGet<IResponseItems<any[]>>(
|
||||
createApiUrl(`/api/articles?page=${page}&pageSize=${pageSize}`),
|
||||
null
|
||||
)
|
||||
const res = await requestGet<IResponseItems<IArticle>>(createApiUrl(`/api/articles?page=${page}&pageSize=${pageSize}`), null)
|
||||
if (!res) {
|
||||
return null
|
||||
}
|
||||
|
||||
const data = res.items || []
|
||||
const nextPage = (res as any).nextPage
|
||||
const prevPage = (res as any).prevPage
|
||||
const data = (res.items || [])
|
||||
const nextPage = res.nextPage
|
||||
const prevPage = res.prevPage
|
||||
const title = 'События'
|
||||
const meta = (new MetaBuilder())
|
||||
.setTitle(title)
|
||||
.build()
|
||||
|
||||
return {
|
||||
props: {
|
||||
@@ -63,16 +63,12 @@ export const unstable_getStaticProps = async (ctx: any) => {
|
||||
nextPage,
|
||||
prevPage,
|
||||
title,
|
||||
meta: meta({
|
||||
title,
|
||||
})
|
||||
meta,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const unstable_getStaticPaths = async () => {
|
||||
console.log('call articles unstable_getStaticPaths')
|
||||
|
||||
const urls = await requestGet<IResponseItems<string>>(createApiUrl(`/api/articles/urls`), null)
|
||||
if (!urls) {
|
||||
return null
|
||||
|
||||
+39
-24
@@ -4,24 +4,27 @@ import { App } from 'src/components/App'
|
||||
import { Meta } from 'src/components/Meta'
|
||||
import { CollectiveImage } from 'src/components/CollectiveImage'
|
||||
import { meta } from 'src/lib/meta'
|
||||
import { IMeta, IImage } from 'src/types'
|
||||
import { IMeta, Person } from 'src/types'
|
||||
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
|
||||
import { NextPage, NextPageContext } from 'next'
|
||||
import { CardGrid } from 'src/components/CardGrid'
|
||||
import { Card } from 'src/components/Card'
|
||||
import { Block } from 'src/components/Block'
|
||||
|
||||
interface IPerson {
|
||||
url: string
|
||||
name: string
|
||||
position: string
|
||||
picture: IImage
|
||||
type CardData = {
|
||||
title: string
|
||||
caption?: string
|
||||
imageSrc: string
|
||||
imageAlt: string
|
||||
imageSrcSet: string
|
||||
href: string
|
||||
}
|
||||
|
||||
type Props = {
|
||||
title: string
|
||||
image: string
|
||||
meta: IMeta
|
||||
data: IPerson[]
|
||||
data: CardData[]
|
||||
}
|
||||
|
||||
const Page: NextPage<Props> = props => {
|
||||
@@ -52,24 +55,26 @@ const Page: NextPage<Props> = props => {
|
||||
<CardGrid style={{
|
||||
marginBottom: 'var(--size-xl)',
|
||||
}}>
|
||||
{props.data.map((item, index) => (
|
||||
{props.data.map(item => (
|
||||
<Card
|
||||
key={index}
|
||||
key={item.href}
|
||||
layout={'featured'}
|
||||
img={{
|
||||
src: item.picture.src,
|
||||
alt: item.name,
|
||||
srcSet: '',//item.name.sr,
|
||||
src: item.imageSrc,
|
||||
alt: item.imageAlt,
|
||||
srcSet: item.imageSrcSet,
|
||||
}}
|
||||
href={item.url}
|
||||
href={item.href}
|
||||
>
|
||||
<h2 style={{
|
||||
margin: '0 0 var(--size-s)',
|
||||
fontSize: '14pt',
|
||||
}}>
|
||||
{item.name[0]} {item.name[1]} {item.name[2]}
|
||||
</h2>
|
||||
{item.position}
|
||||
<Block direction={'vertical'}>
|
||||
<span>{item.title}</span>
|
||||
<span style={{
|
||||
paddingTop: 'var(--size-s)',
|
||||
fontSize: 'var(--font-size-second)',
|
||||
}}>
|
||||
{item.caption}
|
||||
</span>
|
||||
</Block>
|
||||
</Card>
|
||||
))}
|
||||
</CardGrid>
|
||||
@@ -78,14 +83,24 @@ const Page: NextPage<Props> = props => {
|
||||
}
|
||||
|
||||
export const unstable_getStaticProps = async (ctx: NextPageContext) => {
|
||||
// const pageUrl = ctx.req.url
|
||||
|
||||
const res = await requestGet<IResponseItems<IPerson>>(createApiUrl('/api/persons'), null)
|
||||
const data = res?.items || []
|
||||
const res = await requestGet<IResponseItems<Person>>(createApiUrl('/api/persons'), null)
|
||||
const title = 'Преподаватели Шлиссельбургской ДХШ'
|
||||
const imageFile = 'Images/HudozkaCollective2017.jpg'
|
||||
const resImage = await requestGet(createApiUrl(`/api/image?file=${imageFile}`), null)
|
||||
const image = get(resImage, 'artifacts.large', null)
|
||||
const data: CardData[] = (res?.items || [])
|
||||
.map(x => {
|
||||
const title = `${x.name[0]} ${x.name[1]} ${x.name[2]}`
|
||||
return {
|
||||
title,
|
||||
caption: x.position,
|
||||
href: x.url,
|
||||
imageSrc: x.picture.src,
|
||||
imageAlt: title,
|
||||
imageSrcSet: '',
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
return {
|
||||
props: {
|
||||
|
||||
+8
-9
@@ -3,7 +3,7 @@ import { App } from 'src/components/App'
|
||||
import { Meta } from 'src/components/Meta'
|
||||
import { ArticleGrid } from 'src/components/ArticleGrid'
|
||||
import { HudozkaTitle } from 'src/components/HudozkaTitle'
|
||||
import { meta } from 'src/lib/meta'
|
||||
import { meta, MetaBuilder } from 'src/lib/meta'
|
||||
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
|
||||
import { NextPage } from 'next'
|
||||
import { IArticle } from 'src/types'
|
||||
@@ -45,13 +45,15 @@ export const unstable_getStaticProps = async () => {
|
||||
const pageSize = process.env.APP_ARTICLES_PAGE_SIZE
|
||||
const res = await requestGet<IResponseItems<IArticle>>(createApiUrl(`/api/articles?page=${page}&pageSize=${pageSize}`), null)
|
||||
const articles = (res.items || [])
|
||||
.map(x => ({
|
||||
...x,
|
||||
featured: ['2019-kotiki', 'veloparking'].includes(x.id)
|
||||
}))
|
||||
const nextPage = res.nextPage
|
||||
const prevPage = res.prevPage
|
||||
const title = 'Шлиссельбургская ДХШ'
|
||||
const meta = (new MetaBuilder())
|
||||
.setTitle(title)
|
||||
.setData({
|
||||
url: '/',
|
||||
})
|
||||
.build()
|
||||
|
||||
return {
|
||||
props: {
|
||||
@@ -59,10 +61,7 @@ export const unstable_getStaticProps = async () => {
|
||||
nextPage,
|
||||
prevPage,
|
||||
title,
|
||||
meta: meta({
|
||||
title,
|
||||
url: '/',
|
||||
})
|
||||
meta,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+12
-22
@@ -2,10 +2,10 @@ import Head from 'next/head'
|
||||
import { App } from 'src/components/App'
|
||||
import { Article } from 'src/components/Article'
|
||||
import { Meta } from 'src/components/Meta'
|
||||
import { meta } from 'src/lib/meta'
|
||||
import { MetaBuilder } from 'src/lib/meta'
|
||||
import { createApiUrl, requestGet, IResponseItems } from 'src/next-lib'
|
||||
import { NextPage } from 'next'
|
||||
import { IMeta } from 'src/types'
|
||||
import { IMeta, Person } from 'src/types'
|
||||
import { Html } from 'src/components/Html'
|
||||
|
||||
interface IProps {
|
||||
@@ -47,44 +47,34 @@ const Index: NextPage<IProps> = props => {
|
||||
}
|
||||
|
||||
export const unstable_getStaticProps = async (ctx: any) => {
|
||||
console.log('call unstable_getStaticProps', ctx)
|
||||
|
||||
// const id = ctx.query.person
|
||||
// const id = ctx.params.person ?? 'va-sarzhin'
|
||||
const id = ctx.params.person //?? 'mg-timasheva'
|
||||
|
||||
const id = ctx.params.person
|
||||
if (!id) {
|
||||
throw new Error('sry')
|
||||
}
|
||||
|
||||
const person = await requestGet<any>(createApiUrl(`/api/persons/${id}`), null)
|
||||
const name = person.name || []
|
||||
const title = name.join(' ')
|
||||
const image = person.preview ? person.preview.artifacts.fb : {}
|
||||
|
||||
const person = await requestGet<Person>(createApiUrl(`/api/persons/${id}`), null)
|
||||
if (!person?.post) {
|
||||
throw new Error(`post kek ${id}`)
|
||||
}
|
||||
|
||||
const title = person.name.join(' ')
|
||||
const meta = (new MetaBuilder())
|
||||
.setImage(person.preview)
|
||||
.setTitle(title)
|
||||
.setDescription(person.position)
|
||||
.build()
|
||||
|
||||
return {
|
||||
props: {
|
||||
person,
|
||||
title,
|
||||
meta: meta({
|
||||
title,
|
||||
image: image.src,
|
||||
imageWidth: image.width,
|
||||
imageHeight: image.height,
|
||||
})
|
||||
meta,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const unstable_getStaticPaths = async () => {
|
||||
console.log('call unstable_getStaticPaths')
|
||||
|
||||
const urls = await requestGet<IResponseItems<string>>(createApiUrl(`/api/persons/urls`), null)
|
||||
// const urls = {items: ['/teacher/va-sarzhin']}
|
||||
|
||||
return {
|
||||
paths: urls.items
|
||||
|
||||
@@ -29,7 +29,9 @@ export const ArticleGrid: React.FC<ArticleGridProps> = ({ articles, nextPage, pr
|
||||
{articles.map((article, i) => {
|
||||
const gridColumn = article.featured ? 'span 2' : 'auto'
|
||||
const layout: CardLayout = article.featured ? 'featured' : 'simple'
|
||||
const srcSet = article.preview.set.map(({ url, density }) => `${url} ${density}x`).join(' ')
|
||||
const preview = article.preview.artifacts.medium
|
||||
const src = preview.src
|
||||
const srcSet = preview.set.map(({ url, density }) => `${url} ${density}x`).join(' ')
|
||||
|
||||
const content = !article.featured
|
||||
? (
|
||||
@@ -52,7 +54,7 @@ export const ArticleGrid: React.FC<ArticleGridProps> = ({ articles, nextPage, pr
|
||||
href={article.url}
|
||||
img={{
|
||||
alt: article.title,
|
||||
src: article.preview.src,
|
||||
src,
|
||||
srcSet,
|
||||
}}
|
||||
layout={layout}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
import * as React from 'react'
|
||||
import { IMeta } from '../../types'
|
||||
import { IMeta } from 'src/types'
|
||||
|
||||
export interface IMetaProps {
|
||||
export type MetaProps = {
|
||||
meta: IMeta
|
||||
}
|
||||
|
||||
export const Meta: React.FC<IMetaProps> = ({ meta }) => (
|
||||
export const Meta: React.FC<MetaProps> = ({ meta }) => (
|
||||
<>
|
||||
{/* Search Engine */}
|
||||
<meta name="description" content={meta.description} />
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
export function meta(props) {
|
||||
const path = props.url || '/'
|
||||
const url = `https://art.shlisselburg.org${path}`
|
||||
|
||||
return {
|
||||
title: 'Шлиссельбургская ДХШ',
|
||||
description: 'Сайт Шлиссельбургской художественной школы',
|
||||
image: 'https://art.shlisselburg.org/entrance.jpg',
|
||||
imageWidth: 1200,
|
||||
imageHeight: 630,
|
||||
|
||||
siteName: 'Шлиссельбургская Детская Художественная Школа',
|
||||
locale: 'ru_RU',
|
||||
type: 'website',
|
||||
domain: 'art.shlisselburg.org',
|
||||
twitterCard: 'summary_large_image',
|
||||
twitterSite: '@',
|
||||
twitterCreator: '@tmshv',
|
||||
|
||||
...props,
|
||||
url,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,76 @@
|
||||
import { IMeta, ImageDefinition } from 'src/types'
|
||||
|
||||
export function meta(props: Partial<IMeta>): IMeta {
|
||||
const path = props.url || '/'
|
||||
const url = `https://art.shlisselburg.org${path}`
|
||||
|
||||
return {
|
||||
title: 'Шлиссельбургская ДХШ',
|
||||
description: 'Сайт Шлиссельбургской художественной школы',
|
||||
image: 'https://art.shlisselburg.org/entrance.jpg',
|
||||
imageWidth: 1200,
|
||||
imageHeight: 630,
|
||||
|
||||
siteName: 'Шлиссельбургская Детская Художественная Школа',
|
||||
locale: 'ru_RU',
|
||||
type: 'website',
|
||||
domain: 'art.shlisselburg.org',
|
||||
twitterCard: 'summary_large_image',
|
||||
twitterSite: '@',
|
||||
twitterCreator: '@tmshv',
|
||||
|
||||
...props,
|
||||
url,
|
||||
}
|
||||
}
|
||||
|
||||
export class MetaBuilder {
|
||||
private image: ImageDefinition
|
||||
private title: string
|
||||
private description: string
|
||||
private data: Partial<IMeta>
|
||||
|
||||
setData(param: Partial<IMeta>) {
|
||||
this.data = param
|
||||
return this
|
||||
}
|
||||
|
||||
setTitle(param: string) {
|
||||
this.title = param
|
||||
return this
|
||||
}
|
||||
|
||||
setDescription(param: string) {
|
||||
this.description = param
|
||||
return this
|
||||
}
|
||||
|
||||
setImage(param: ImageDefinition) {
|
||||
this.image = param
|
||||
return this
|
||||
}
|
||||
|
||||
build() {
|
||||
const image = this.buildImage()
|
||||
|
||||
return meta({
|
||||
...this.data,
|
||||
...image,
|
||||
title: this.title ?? undefined,
|
||||
description: this.description ?? undefined,
|
||||
})
|
||||
}
|
||||
|
||||
private buildImage() {
|
||||
if (!this.image) {
|
||||
return null
|
||||
}
|
||||
|
||||
const artifact = this.image.artifacts.fb
|
||||
return {
|
||||
image: artifact.src,
|
||||
imageWidth: artifact.width,
|
||||
imageHeight: artifact.height,
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
-2
@@ -13,7 +13,8 @@ export interface IPage {
|
||||
title: string
|
||||
url: string
|
||||
data: string
|
||||
preview: any //IImage
|
||||
preview: ImageDefinition
|
||||
description: string
|
||||
tokens: any[]
|
||||
breadcrumb?: IBreadcumbsPart[]
|
||||
}
|
||||
@@ -65,5 +66,44 @@ export interface IArticle {
|
||||
featured: boolean
|
||||
url: string
|
||||
title: string
|
||||
preview: IImage
|
||||
preview: ImageDefinition
|
||||
}
|
||||
|
||||
export type Person = {
|
||||
id: string
|
||||
position: string
|
||||
name: [string, string, string]
|
||||
post: string
|
||||
diploma: string
|
||||
edu: string
|
||||
file: string
|
||||
hash: string
|
||||
shortName: string
|
||||
status: string
|
||||
url: string
|
||||
picture: ImageArtifact
|
||||
preview: ImageDefinition
|
||||
}
|
||||
|
||||
export type ImageArtifact = {
|
||||
width: number
|
||||
height: number
|
||||
src: string
|
||||
set: Array<{
|
||||
density: number
|
||||
url: string
|
||||
}>
|
||||
}
|
||||
|
||||
export type ImageDefinition = {
|
||||
file: string
|
||||
hash: string
|
||||
artifacts: {
|
||||
original: ImageArtifact
|
||||
large?: ImageArtifact
|
||||
big?: ImageArtifact
|
||||
medium?: ImageArtifact
|
||||
small?: ImageArtifact
|
||||
fb?: ImageArtifact
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user