Merge pull request #87 from tmshv/upd/card-blur

card images blur
This commit is contained in:
tmshv authored and GitHub committed 2021-09-22 15:20:42 +03:00
commit b778f61e92
8 files changed
+79 -60

No files matched your search

+3 -2
View File
@@ -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
+1 -1
View File
@@ -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
View File
@@ -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())
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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
View File
@@ -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 = {