diff --git a/modules/hudozka-api/src/core/Article.ts b/modules/hudozka-api/src/core/Article.ts index 6b868781..6a248dff 100644 --- a/modules/hudozka-api/src/core/Article.ts +++ b/modules/hudozka-api/src/core/Article.ts @@ -1,6 +1,5 @@ import Data from './Data' import Image from './Image' -import Config from './Config' import { find, findOne, total } from '../lib/store' import { Tag } from './Tag' @@ -101,13 +100,6 @@ const previewFromImage = (imgs = []) => imgs.length ? imgs[0] : null -async function resolveDefaultPreview() { - const config = await Config.findConfig() - if (!config) return null - - return Image.findByFile(config.articleCardDefaultPreview) -} - async function processArticle(article) { let preview = null const previewId = article.preview @@ -116,8 +108,6 @@ async function processArticle(article) { if (previewId) { preview = await Image.findById(previewId) - } else { - preview = await resolveDefaultPreview() } return new Article({ diff --git a/modules/hudozka-api/src/core/Config.ts b/modules/hudozka-api/src/core/Config.ts deleted file mode 100644 index 086d6c23..00000000 --- a/modules/hudozka-api/src/core/Config.ts +++ /dev/null @@ -1,40 +0,0 @@ -import Data from './Data' -import { findOne } from '../lib/store' - -const store = () => Data.getStore('Settings') - -export default class Config { - static async findConfig() { - const config = await Config.findById('settings') - return config || new Config({} as any) - } - - static async findById(id: string) { - const data = await findOne(store(), { id }) - if (!data) return null - - return new Config(data) - } - - public hash: any - public file: any - public server: any - public articlesPerPage: any - public articleCardDefaultPreview: any - public collectiveImage: any - public redirect: any - - constructor({ hash, file, ...data }) { - this.hash = hash - this.file = file - this.server = data.server - this.articlesPerPage = data.articlesPerPage || 5 - this.articleCardDefaultPreview = data.articleCardDefaultPreview - this.collectiveImage = data.collectiveImage - - const redirect = data.redirect || {} - this.redirect = new Map(Object - .entries(redirect) - ) - } -} diff --git a/modules/hudozka-api/src/core/Page.ts b/modules/hudozka-api/src/core/Page.ts index f35e1fa7..90ca78e0 100644 --- a/modules/hudozka-api/src/core/Page.ts +++ b/modules/hudozka-api/src/core/Page.ts @@ -1,7 +1,6 @@ import Data from './Data' import { find as storeFind, findOne, total } from '../lib/store' import Image from './Image' -import Config from './Config' const store = () => Data.getStore('Page') @@ -80,13 +79,6 @@ const previewFromImage = (imgs = []) => imgs.length ? imgs[0] : null -async function resolveDefaultPreview() { - const config = await Config.findConfig() - if (!config) return null - - return Image.findByFile(config.articleCardDefaultPreview) -} - async function processPage(article) { let preview = null const previewId = article.preview @@ -95,8 +87,6 @@ async function processPage(article) { if (previewId) { preview = await Image.findById(previewId) - } else { - preview = await resolveDefaultPreview() } return new Page({ diff --git a/modules/hudozka-api/src/factory/article.ts b/modules/hudozka-api/src/factory/article.ts index 0afe3140..b4cfd83c 100644 --- a/modules/hudozka-api/src/factory/article.ts +++ b/modules/hudozka-api/src/factory/article.ts @@ -2,8 +2,10 @@ import Article from '../core/Article' import { encodeImage } from './image' export function encodeArticle(article: Article) { + const preview = article.preview ? encodeImage(article.preview) : null + return { ...article, - preview: encodeImage(article.preview), + preview, } } \ No newline at end of file diff --git a/modules/hudozka-api/src/factory/page.ts b/modules/hudozka-api/src/factory/page.ts index 5a3f2805..003887ae 100644 --- a/modules/hudozka-api/src/factory/page.ts +++ b/modules/hudozka-api/src/factory/page.ts @@ -3,13 +3,15 @@ import Page from '../core/Page' import { Breadcrumb } from '../types' export function encodePage(page: Page, breadcrumb: Breadcrumb) { + const preview = page.preview ? encodeImage(page.preview) : null + return { id: page.id, title: page.title, url: page.url, data: page.data, description: page.description, - preview: encodeImage(page.preview), + preview, tokens: page.tokens, breadcrumb, } diff --git a/next.config.js b/next.config.js index 87b1671d..f5bbe0fd 100644 --- a/next.config.js +++ b/next.config.js @@ -5,6 +5,7 @@ module.exports = withCss(withSass({ exportTrailingSlash: true, env: { APP_ARTICLES_PAGE_SIZE: 24, + APP_CARD_DEFAULT_IMAGE: 'https://art.shlisselburg.org/static/img/main.jpg', }, webpack(config) { config.resolve.modules.push(__dirname) diff --git a/src/components/ArticleGrid/index.tsx b/src/components/ArticleGrid/index.tsx index 2758ff68..3d345adc 100644 --- a/src/components/ArticleGrid/index.tsx +++ b/src/components/ArticleGrid/index.tsx @@ -1,4 +1,4 @@ -import { IArticle } from 'src/types' +import { IArticle, ImageDefinition } from 'src/types' import { Pager } from '../Pager' import { CardGrid } from '../CardGrid' import { Card, CardLayout } from '../Card' @@ -6,6 +6,45 @@ import { Date } from './Date' import { Block } from '../Block' import { Spacer } from '../Spacer' +export interface IResizeImage { + w: number + h: number +} + +export function resizeImage(src: string, options: IResizeImage): string { + return `https://images.weserv.nl/?url=${src}&w=${options.w}&h=${options.h}&n=-1` +} + +function getImage(image?: ImageDefinition) { + if (!image) { + const defaultSrc = process.env.APP_CARD_DEFAULT_IMAGE + const src = resizeImage(defaultSrc, { w: 400, h: 400 }) + const set = [ + { + density: 2, + href: resizeImage(defaultSrc, { w: 800, h: 800 }), + } + ] + const srcSet = set + .map(({ href, density }) => `${href} ${density}x`) + .join(' ') + + return { + src, + srcSet, + } + } + + const preview = image.artifacts.medium + const src = preview.src + const srcSet = preview.set.map(({ url, density }) => `${url} ${density}x`).join(' ') + + return { + src, + srcSet, + } +} + export type ArticleGridProps = { articles: IArticle[] nextPage: number | null @@ -29,9 +68,7 @@ export const ArticleGrid: React.FC = ({ articles, nextPage, pr {articles.map((article, i) => { const gridColumn = article.featured ? 'span 2' : 'auto' const layout: CardLayout = article.featured ? 'featured' : 'simple' - const preview = article.preview.artifacts.medium - const src = preview.src - const srcSet = preview.set.map(({ url, density }) => `${url} ${density}x`).join(' ') + const { src, srcSet } = getImage(article.preview) const content = !article.featured ? (