8 files changed
+79
-60
No files matched your search
+3
-2
@@ -151,14 +151,15 @@ const Index: NextPage<Props> = props => {
|
||||
export const getStaticProps: GetStaticProps<Props> = async ctx => {
|
||||
const slug = paramsToSlug(ctx.params.slug)
|
||||
const url = `https://hudozka.tmshv.com/pages?slug=${slug}`
|
||||
const page = await apiGet(createPage)(url, null)
|
||||
const page = await apiGet(createPage) (url, () => null)
|
||||
if (!page) {
|
||||
return {
|
||||
notFound: true,
|
||||
}
|
||||
}
|
||||
|
||||
const menu = await apiGet(createMenu)('https://hudozka.tmshv.com/menu', [])
|
||||
const menu = await apiGet(createMenu)
|
||||
('https://hudozka.tmshv.com/menu', () => [])
|
||||
|
||||
const description = page.description ?? undefined
|
||||
const breadcrumbSize = page?.breadcrumb?.length ?? 0
|
||||
|
||||
@@ -46,7 +46,7 @@ export const getStaticProps = async (ctx: any) => {
|
||||
.setTitle(data.name)
|
||||
.setDescription(data.name)
|
||||
.build()
|
||||
const menu = await apiGet(createMenu)('https://hudozka.tmshv.com/menu', [])
|
||||
const menu = await apiGet(createMenu)('https://hudozka.tmshv.com/menu', () => [])
|
||||
|
||||
return {
|
||||
props: {
|
||||
|
||||
+4
-3
@@ -41,9 +41,10 @@ const Index: NextPage<Props> = props => (
|
||||
)
|
||||
|
||||
export const getStaticProps: GetStaticProps<Props> = async () => {
|
||||
const url = 'https://hudozka.tmshv.com/home'
|
||||
const items = await apiGet(createHomeCards)(url, [])
|
||||
const menu = await apiGet(createMenu)('https://hudozka.tmshv.com/menu', [])
|
||||
const items = await apiGet(createHomeCards)
|
||||
('https://hudozka.tmshv.com/home', async () => [])
|
||||
const menu = await apiGet(createMenu)
|
||||
('https://hudozka.tmshv.com/menu', () => [])
|
||||
|
||||
const title = 'Шлиссельбургская ДХШ'
|
||||
const meta = (new MetaBuilder())
|
||||
|
||||
@@ -48,6 +48,8 @@ export const PageGrid: React.FC<PageGridProps> = props => {
|
||||
objectFit={'cover'}
|
||||
src={item.cover.src}
|
||||
alt={item.cover.alt}
|
||||
placeholder={'blur'}
|
||||
blurDataURL={item.cover.blur}
|
||||
/>
|
||||
)}
|
||||
layout={layout}
|
||||
|
||||
+3
-3
@@ -1,4 +1,4 @@
|
||||
import { IMeta, ImageDefinition } from 'src/types'
|
||||
import { IMeta, Pic } from 'src/types'
|
||||
|
||||
export function meta(props: Partial<IMeta>): IMeta {
|
||||
const path = props.url || '/'
|
||||
@@ -25,7 +25,7 @@ export function meta(props: Partial<IMeta>): IMeta {
|
||||
}
|
||||
|
||||
export class MetaBuilder {
|
||||
private image: ImageDefinition
|
||||
private image: Pic
|
||||
private title: string
|
||||
private description: string
|
||||
private data: Partial<IMeta>
|
||||
@@ -45,7 +45,7 @@ export class MetaBuilder {
|
||||
return this
|
||||
}
|
||||
|
||||
setImage(param: ImageDefinition) {
|
||||
setImage(param: Pic) {
|
||||
this.image = param
|
||||
return this
|
||||
}
|
||||
|
||||
+7
-5
@@ -40,14 +40,16 @@ export function createApiUrl(path: string) {
|
||||
export type FactoryFunction<I, O> =
|
||||
| ((response: I) => O)
|
||||
| ((response: I) => Promise<O>)
|
||||
export type ApiDefaultResponse<O> = () => O
|
||||
|
||||
export function apiGet<I, O>(factory: FactoryFunction<I, O>) {
|
||||
return async (url: string, defaultResponse: O) => {
|
||||
const res = await requestGet<I>(url, null as any)
|
||||
if (!res) {
|
||||
return defaultResponse
|
||||
return async (url: string, getDefaultResponse: ApiDefaultResponse<O>) => {
|
||||
const res = await fetch(url)
|
||||
if (res.ok) {
|
||||
const data = await res.json() as I
|
||||
return factory(data)
|
||||
}
|
||||
|
||||
return factory(res)
|
||||
return getDefaultResponse()
|
||||
}
|
||||
}
|
||||
+55
-36
@@ -1,4 +1,4 @@
|
||||
import { ImageDefinition, IMenu, IPage, ITag, PageCardDto, Pic, Token } from "@/types";
|
||||
import { IMenu, IPage, ITag, PageCardDto, Pic, Token } from "@/types";
|
||||
import { asItem } from "./lib";
|
||||
import { StrapiComponentEmbed, StrapiComponent, StrapiHome, StrapiPage, StrapiPageCard, StrapiTag, StrapiMedia, StrapiMenu } from "./types";
|
||||
import { typograf, markdownToHtml } from 'src/lib/text'
|
||||
@@ -16,15 +16,6 @@ export function isYoutubeUrl(url: string): boolean {
|
||||
return /youtube\.com/.test(url)
|
||||
}
|
||||
|
||||
export function getCoverImage(media?: StrapiMedia) {
|
||||
return media ? createImageFromMedia(media) : {
|
||||
src: 'https://hudozkacdn.tmshv.com/main_fad9fdf29a.jpg',
|
||||
width: 1920,
|
||||
height: 1858,
|
||||
alt: ''
|
||||
}
|
||||
}
|
||||
|
||||
export function createEmbed(component: StrapiComponentEmbed): Token {
|
||||
if (isYoutubeUrl(component.src)) {
|
||||
return {
|
||||
@@ -51,20 +42,10 @@ export async function createPageToken(component: StrapiComponent): Promise<Token
|
||||
}
|
||||
|
||||
case 'hudozka.image': {
|
||||
const src = component.media.formats?.large?.url ?? component.media.url
|
||||
const thumb = component.media.formats?.thumbnail?.url ?? component.media.url
|
||||
const data: Pic = {
|
||||
alt: component.caption,
|
||||
const data = await createPicFromMedia(component.media, {
|
||||
alternativeText: component.caption,
|
||||
caption: component.caption,
|
||||
src,
|
||||
width: component.media.width,
|
||||
height: component.media.height,
|
||||
}
|
||||
|
||||
const blur = await encodeImageToBlurhash(thumb)
|
||||
if (blur) {
|
||||
data.blur = blur
|
||||
}
|
||||
})
|
||||
|
||||
return {
|
||||
token: 'image',
|
||||
@@ -94,12 +75,14 @@ export async function createPageToken(component: StrapiComponent): Promise<Token
|
||||
}
|
||||
|
||||
case 'hudozka.card-grid': {
|
||||
const items = await Promise.all(component.items
|
||||
.filter(Boolean)
|
||||
.map(createCardGrid)
|
||||
)
|
||||
return {
|
||||
token: 'grid',
|
||||
data: {
|
||||
items: component.items
|
||||
.filter(Boolean)
|
||||
.map(createCardGrid)
|
||||
items,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -130,12 +113,13 @@ export async function createPage(res: StrapiPage | StrapiPage[]): Promise<IPage
|
||||
return null
|
||||
}
|
||||
|
||||
const cover = getCoverImage(item.cover)
|
||||
const cover = await getCoverImage(item.cover)
|
||||
const tags: ITag[] = item.tags.map(tag => ({
|
||||
id: tag.id,
|
||||
name: tag.name,
|
||||
slug: tag.slug,
|
||||
href: `/tags/${tag.slug}`,
|
||||
count: 0,
|
||||
}))
|
||||
|
||||
const tokens = await Promise.all(item.content.map(createPageToken))
|
||||
@@ -167,17 +151,50 @@ function isCardFeatured(card: StrapiPageCard): boolean {
|
||||
return card.layout === 'big' || card.layout === 'medium'
|
||||
}
|
||||
|
||||
function createImageFromMedia(media: StrapiMedia): ImageDefinition {
|
||||
export async function getCoverImage(media?: StrapiMedia): Promise<Pic> {
|
||||
if (media) {
|
||||
return createPicFromMedia(media)
|
||||
}
|
||||
|
||||
return {
|
||||
src: media.url,
|
||||
width: media.width,
|
||||
height: media.height,
|
||||
alt: media.alternativeText ?? '',
|
||||
src: 'https://hudozkacdn.tmshv.com/main_fad9fdf29a.jpg',
|
||||
width: 1920,
|
||||
height: 1858,
|
||||
// alt: '',
|
||||
// caption: '',
|
||||
// blur: '',
|
||||
}
|
||||
}
|
||||
|
||||
export function createCardGrid(card: StrapiPageCard): PageCardDto {
|
||||
const cover = getCoverImage(card.page.cover)
|
||||
async function createPicFromMedia(media: StrapiMedia, overrides?: Partial<StrapiMedia>): Promise<Pic> {
|
||||
const src = media.formats?.large?.url ?? media.url
|
||||
const pic: Pic = {
|
||||
src,
|
||||
width: media.width,
|
||||
height: media.height,
|
||||
}
|
||||
|
||||
const alt = overrides?.alternativeText ?? media.alternativeText ?? undefined
|
||||
if (alt) {
|
||||
pic.alt = alt
|
||||
}
|
||||
|
||||
const caption = overrides?.caption ?? media.caption ?? undefined
|
||||
if (caption) {
|
||||
pic.caption = caption
|
||||
}
|
||||
|
||||
const thumb = media.formats?.thumbnail?.url ?? media.url
|
||||
const blur = await encodeImageToBlurhash(thumb)
|
||||
if (blur) {
|
||||
pic.blur = blur
|
||||
}
|
||||
|
||||
return pic
|
||||
}
|
||||
|
||||
export async function createCardGrid(card: StrapiPageCard): Promise<PageCardDto> {
|
||||
const cover = await getCoverImage(card.page.cover)
|
||||
|
||||
return {
|
||||
id: card.id,
|
||||
@@ -189,8 +206,10 @@ export function createCardGrid(card: StrapiPageCard): PageCardDto {
|
||||
}
|
||||
}
|
||||
|
||||
export function createHomeCards(data: StrapiHome): PageCardDto[] {
|
||||
return data.cards
|
||||
export async function createHomeCards(data: StrapiHome): Promise<PageCardDto[]> {
|
||||
const items = await Promise.all(data.cards
|
||||
.map(createCardGrid)
|
||||
)
|
||||
return items
|
||||
.filter(x => !!x.url)
|
||||
}
|
||||
+4
-10
@@ -14,14 +14,14 @@ export type PageCardDto = {
|
||||
title: string
|
||||
featured: boolean
|
||||
date: string | null
|
||||
cover: ImageDefinition
|
||||
cover: Pic
|
||||
}
|
||||
|
||||
export type FileDefinition = {
|
||||
url: string
|
||||
slug: string
|
||||
name: string
|
||||
cover?: ImageDefinition
|
||||
cover?: Pic
|
||||
file: {
|
||||
name: string
|
||||
size: string
|
||||
@@ -36,7 +36,7 @@ export interface IPage {
|
||||
url: string
|
||||
data: string
|
||||
date: string
|
||||
cover: ImageDefinition
|
||||
cover: Pic
|
||||
description: string
|
||||
tokens: any[]
|
||||
tags: ITag[]
|
||||
@@ -89,13 +89,7 @@ export interface ITag {
|
||||
name: string
|
||||
slug: string
|
||||
href: string
|
||||
}
|
||||
|
||||
export type ImageDefinition = {
|
||||
width: number
|
||||
height: number
|
||||
src: string
|
||||
alt?: string
|
||||
count: number
|
||||
}
|
||||
|
||||
export type Pic = {
|
||||
|
||||
Reference in new issue
Block a user