From 2ebf2835a9d8f0f0099ffdcc2c4d650f0b8314b8 Mon Sep 17 00:00:00 2001 From: Bohdan Kucherivayi Date: Thu, 26 Oct 2023 13:01:39 +0300 Subject: [PATCH 1/4] fix: refactor code structure --- .prettierrc | 1 + src/fields/url.ts | 1 + src/i18n.ts | 11 +++++ src/payload.config.ts | 94 +++++++++++++++++++++++++++++------------ src/types/namespace.ts | 3 -- src/utils/groups.ts | 5 +++ src/utils/validators.ts | 4 +- tsconfig.json | 3 +- 8 files changed, 91 insertions(+), 31 deletions(-) create mode 100644 src/i18n.ts delete mode 100644 src/types/namespace.ts diff --git a/.prettierrc b/.prettierrc index 0a84f4d..41c408d 100644 --- a/.prettierrc +++ b/.prettierrc @@ -10,6 +10,7 @@ "^(^types$)|(^types/(.*)$)$", "^(^assets$)|(^assets/(.*)$)$", "^(^locales$)|(^locales/(.*)$)$", + "^i18n$", "^(^components$)|(^components/(.*)$)$", "^(^collections$)|(^collections/(.*)$)$", "^(^globals$)|(^globals/(.*)$)$", diff --git a/src/fields/url.ts b/src/fields/url.ts index 5f22765..b224e1d 100644 --- a/src/fields/url.ts +++ b/src/fields/url.ts @@ -10,5 +10,6 @@ export const urlField = (data?: Partial>): TextField => ua: 'Посилання', }, validate: validateUrl, + required: false, ...data, }); diff --git a/src/i18n.ts b/src/i18n.ts new file mode 100644 index 0000000..7d33398 --- /dev/null +++ b/src/i18n.ts @@ -0,0 +1,11 @@ +export enum Namespace { + VALIDATION = 'validation', +} + +export enum Locales { + ENGLISH = 'en', + UKRAINIAN = 'uk', +} + +export const defaultLocale = Locales.ENGLISH; +export const locales = [Locales.ENGLISH, Locales.UKRAINIAN]; diff --git a/src/payload.config.ts b/src/payload.config.ts index db0a5eb..4f196bc 100644 --- a/src/payload.config.ts +++ b/src/payload.config.ts @@ -19,6 +19,8 @@ import path from 'path'; import validationEN from 'locales/en/validation'; import validationUA from 'locales/ua/validation'; +import { defaultLocale, locales } from 'i18n'; + import Logo from 'components/Logo'; import NavLogo from 'components/NavLogo'; @@ -34,8 +36,11 @@ import Authors from 'collections/blog/Authors'; import Blog from 'collections/blog/Blog'; import Tags from 'collections/blog/Tags'; import AuthorPhotos from 'collections/media/AuthorPhotos'; -import BlogMetaImages from 'collections/media/BlogMetaImages'; +import BlogAssets from 'collections/media/BlogAssets'; +import BlogCoverImages from 'collections/media/BlogCoverImages'; +import OpenGraphImages from 'collections/media/OpenGraphImages'; import PartnerLogos from 'collections/media/PartnerLogos'; +import ProjectAssets from 'collections/media/ProjectAssets'; import ProjectImages from 'collections/media/ProjectImages'; import ServiceIcons from 'collections/media/ServiceIcons'; import TeamMemberPhotos from 'collections/media/TeamMemberPhotos'; @@ -121,10 +126,12 @@ export default buildConfig({ }, bundler: webpackBundler(), webpack: (config) => { - config.resolve.modules = [...(config.resolve.modules || []), path.resolve(__dirname)]; - config.resolve.extensions = [...(config.resolve.extensions || []), '.ts', '.tsx', '.js', '.jsx', '.json']; + const newConfig = { ...config }; + + newConfig.resolve.modules = [...(config.resolve.modules || []), path.resolve(__dirname)]; + newConfig.resolve.extensions = [...(config.resolve.extensions || []), '.ts', '.tsx', '.js', '.jsx', '.json']; - return config; + return newConfig; }, // livePreview: { // url: ({ @@ -164,28 +171,32 @@ export default buildConfig({ collections: [ Admins, ContactFormLeads, - Team, - Technologies, - TechnologyLogos, - TeamMemberPhotos, - Blog, - Tags, Authors, - BlogMetaImages, AuthorPhotos, + Blog, + BlogCoverImages, + Tags, Locations, + OpenGraphImages, PartnerLogos, Partners, + Projects, + ProjectImages, + ProjectAssets, ServiceIcons, Services, - ProjectImages, - Projects, + Team, + TeamMemberPhotos, + Technologies, + TechnologyLogos, ], globals: [ AboutPage, BlogPage, ContactsPage, CookiesPolicyPage, + Footer, + GeneralInfo, HomePage, PrivacyPolicyPage, ProjectsPage, @@ -193,14 +204,12 @@ export default buildConfig({ SitemapPage, SupportUkrainePage, TermsOfUsePage, - GeneralInfo, - Navigation, Languages, - Footer, + Navigation, ], localization: { - locales: ['en', 'uk'], - defaultLocale: 'en', + locales, + defaultLocale, fallback: true, }, i18n: { @@ -247,18 +256,30 @@ export default buildConfig({ adapter: googleCloudStorageAdapter, prefix: 'media/author-photos', }, - [BlogMetaImages.slug]: { + [BlogAssets.slug]: { adapter: googleCloudStorageAdapter, - prefix: 'media/blog-meta-images', + prefix: 'media/blog-assets', }, - [PartnerLogos.slug]: { + [BlogCoverImages.slug]: { adapter: googleCloudStorageAdapter, - prefix: 'media/partner-logos', + prefix: 'media/blog-cover-images', }, [ServiceIcons.slug]: { adapter: googleCloudStorageAdapter, prefix: 'media/service-icons', }, + [PartnerLogos.slug]: { + adapter: googleCloudStorageAdapter, + prefix: 'media/partner-logos', + }, + [ProjectImages.slug]: { + adapter: googleCloudStorageAdapter, + prefix: 'media/project-images', + }, + [ProjectAssets.slug]: { + adapter: googleCloudStorageAdapter, + prefix: 'media/project-assets', + }, [TeamMemberPhotos.slug]: { adapter: googleCloudStorageAdapter, prefix: 'media/team-member-photos', @@ -271,7 +292,7 @@ export default buildConfig({ }), seo({ collections: [Blog.slug, Projects.slug], - uploadsCollection: BlogMetaImages.slug, + uploadsCollection: OpenGraphImages.slug, globals: [ AboutPage.slug, BlogPage.slug, @@ -293,13 +314,34 @@ export default buildConfig({ en: 'Canonical URL', ua: '"Канонічне" посилання', }, + required: false, localized: true, }), ], generateTitle: ({ doc }) => (doc as any)?.title || '', - generateURL: ({ doc }) => - new URL(`/[section]/${(doc as any)?.slug ? (doc as any).slug : '[slug]'}`, process.env.PAYLOAD_PUBLIC_SITE_URL) - .href, + generateURL: ({ doc, slug, locale }) => { + const document = doc as Record; + const localePrefix = locale === defaultLocale ? '' : locale; + const documentSlug = document?.slug ? slug : '[slug]'; + let section = ''; + + switch (slug) { + case Blog.slug: + section = 'blog'; + break; + + case Projects.slug: + section = 'blog'; + break; + + default: + break; + } + + const url = new URL(path.join(localePrefix, section, documentSlug), process.env.PAYLOAD_PUBLIC_SITE_URL).href; + + return url; + }, tabbedUI: true, }), blurHash({ diff --git a/src/types/namespace.ts b/src/types/namespace.ts deleted file mode 100644 index 3888bf6..0000000 --- a/src/types/namespace.ts +++ /dev/null @@ -1,3 +0,0 @@ -export enum Namespace { - VALIDATION = 'validation', -} diff --git a/src/utils/groups.ts b/src/utils/groups.ts index 140fbdb..c769077 100644 --- a/src/utils/groups.ts +++ b/src/utils/groups.ts @@ -13,6 +13,11 @@ export const blogGroup = { ua: 'Блог', }; +export const projectsGroup = { + en: 'Projects', + ua: 'Проєкти', +}; + export const pagesGroup = { en: 'Pages', ua: 'Сторінки', diff --git a/src/utils/validators.ts b/src/utils/validators.ts index 6024876..5f8fee5 100644 --- a/src/utils/validators.ts +++ b/src/utils/validators.ts @@ -1,6 +1,6 @@ import { Validate } from 'payload/types'; -import { Namespace } from 'types/namespace'; +import { Namespace } from 'i18n'; import { httpOrHttpsUrlRegEx, urlSlugRegEx } from './regex'; @@ -25,6 +25,8 @@ export const validateInteger = (value: number, options): true | string => { }; export const validateUrl = (value: string, options): true | string => { + if (!value) return true; + try { httpOrHttpsUrlRegEx.exec(value); diff --git a/tsconfig.json b/tsconfig.json index caf2cb9..b5f7707 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -36,7 +36,8 @@ "public": ["src/public"], "public/*": ["src/public/*"], "locales": ["src/locales"], - "locales/*": ["src/locales/*"] + "locales/*": ["src/locales/*"], + "i18n": ["src/i18n.ts"] } }, "include": ["src"], From a27d0d84c3325c62ad6c3789131f1e2be96aa49c Mon Sep 17 00:00:00 2001 From: Bohdan Kucherivayi Date: Thu, 26 Oct 2023 14:21:21 +0300 Subject: [PATCH 2/4] feat: add new media collections --- src/collections/Projects.ts | 22 +- src/collections/blog/Blog.ts | 103 +++++- src/collections/media/BlogAssets.ts | 22 ++ src/collections/media/BlogCoverImages.ts | 50 +++ src/collections/media/BlogMetaImages.ts | 29 -- src/collections/media/OpenGraphImages.ts | 32 ++ src/collections/media/ProjectAssets.ts | 12 +- src/collections/media/ProjectImages.ts | 4 +- src/payload-types.ts | 400 ++++++++++++++--------- 9 files changed, 455 insertions(+), 219 deletions(-) create mode 100644 src/collections/media/BlogAssets.ts create mode 100644 src/collections/media/BlogCoverImages.ts delete mode 100644 src/collections/media/BlogMetaImages.ts create mode 100644 src/collections/media/OpenGraphImages.ts diff --git a/src/collections/Projects.ts b/src/collections/Projects.ts index 8cf3ee0..9204378 100644 --- a/src/collections/Projects.ts +++ b/src/collections/Projects.ts @@ -1,9 +1,10 @@ +import payload from 'payload'; import { CollectionConfig } from 'payload/types'; import { orderField } from 'fields/order'; import { slugField } from 'fields/slug'; -import { generalGroup } from 'utils/groups'; +import { projectsGroup } from 'utils/groups'; import ProjectImages from './media/ProjectImages'; @@ -22,7 +23,7 @@ const Projects: CollectionConfig = { admin: { useAsTitle: 'preview.name', defaultColumns: ['order', 'preview.name'], - group: generalGroup, + group: projectsGroup, }, versions: { drafts: { @@ -30,6 +31,23 @@ const Projects: CollectionConfig = { }, maxPerDoc: 5, }, + endpoints: [ + { + path: '/slug/:slug', + method: 'get', + handler: async (req, res) => { + const data = await payload.find({ + collection: 'projects', + where: { slug: { equals: req.params.slug } }, + limit: 1, + }); + + if (data.docs.length) return res.status(200).send(data.docs[0]); + + res.status(404).send({ error: 'Not found' }); + }, + }, + ], fields: [ { type: 'tabs', diff --git a/src/collections/blog/Blog.ts b/src/collections/blog/Blog.ts index 41cb1b2..f246737 100644 --- a/src/collections/blog/Blog.ts +++ b/src/collections/blog/Blog.ts @@ -1,5 +1,8 @@ +import payload from 'payload'; import { CollectionConfig } from 'payload/types'; +import BlogCoverImages from 'collections/media/BlogCoverImages'; + import { richTextField } from 'fields/richText'; import { slugField } from 'fields/slug'; @@ -24,6 +27,29 @@ const Blog: CollectionConfig = { useAsTitle: 'content.title', group: blogGroup, }, + versions: { + drafts: { + autosave: true, + }, + maxPerDoc: 5, + }, + endpoints: [ + { + path: '/slug/:slug', + method: 'get', + handler: async (req, res) => { + const data = await payload.find({ + collection: 'blog-posts', + where: { slug: { equals: req.params.slug } }, + limit: 1, + }); + + if (data.docs.length) return res.status(200).send(data.docs[0]); + + res.status(404).send({ error: 'Not found' }); + }, + }, + ], fields: [ { type: 'tabs', @@ -42,32 +68,77 @@ const Blog: CollectionConfig = { en: 'Title', ua: 'Заголовок', }, + required: true, }, { - name: 'tags', + type: 'textarea', + name: 'description', label: { - en: 'Tags', - ua: 'Теги', + en: 'Description', + ua: 'Опис', }, - type: 'relationship', - relationTo: Tags.slug, - hasMany: true, required: true, }, { - name: 'author', + type: 'row', + fields: [ + { + name: 'tags', + label: { + en: 'Tags', + ua: 'Теги', + }, + type: 'relationship', + relationTo: Tags.slug, + hasMany: true, + required: true, + }, + { + name: 'author', + label: { + en: 'Author', + ua: 'Автор', + }, + type: 'relationship', + relationTo: Authors.slug, + hasMany: false, + required: true, + }, + ], + }, + { + type: 'upload', + name: 'landscape', + relationTo: BlogCoverImages.slug, label: { - en: 'Author', - ua: 'Автор', - }, - admin: { - position: 'sidebar', + en: 'Cover (shown on devices with landscape orientation)', + ua: 'Обкладинка (відображається на пристроях з альбомною орієнтацією)', }, - type: 'relationship', - relationTo: Authors.slug, - hasMany: false, - required: true, }, + // { + // type: 'group', + // name: 'cover', + // fields: [ + // { + // type: 'upload', + // name: 'landscape', + // relationTo: BlogCoverImages.slug, + // label: { + // en: 'Cover (shown on devices with landscape orientation)', + // ua: 'Обкладинка (відображається на пристроях з альбомною орієнтацією)', + // }, + // }, + // { + // type: 'upload', + // name: 'portrait', + // relationTo: BlogCoverImages.slug, + // label: { + // en: 'Cover (shown on devices with portrait orientation)', + // ua: 'Обкладинка (відображається на пристроях з портретною орієнтацією)', + // }, + // }, + // ], + // }, richTextField({ name: 'content' }), ], }, diff --git a/src/collections/media/BlogAssets.ts b/src/collections/media/BlogAssets.ts new file mode 100644 index 0000000..8f14bb0 --- /dev/null +++ b/src/collections/media/BlogAssets.ts @@ -0,0 +1,22 @@ +import { CollectionConfig } from 'payload/types'; + +import { publicUploadCollectionWithoutApiAccess } from 'utils/access'; +import { blogGroup } from 'utils/groups'; + +const BlogAssets: CollectionConfig = { + slug: 'blog-assets', + labels: { + singular: { en: 'Blog asset', ua: 'Файл блогу' }, + plural: { en: 'Blog assets', ua: 'Файли блогу' }, + }, + upload: true, + access: { + read: publicUploadCollectionWithoutApiAccess, + }, + admin: { + group: blogGroup, + }, + fields: [], +}; + +export default BlogAssets; diff --git a/src/collections/media/BlogCoverImages.ts b/src/collections/media/BlogCoverImages.ts new file mode 100644 index 0000000..167967b --- /dev/null +++ b/src/collections/media/BlogCoverImages.ts @@ -0,0 +1,50 @@ +import { CollectionConfig } from 'payload/types'; + +import { altField } from 'fields/alt'; + +import { publicUploadCollectionWithoutApiAccess } from 'utils/access'; +import { blogGroup } from 'utils/groups'; +import { defaultPhotoMimeTypes } from 'utils/mimeTypes'; + +const BlogCoverImages: CollectionConfig = { + slug: 'blog-cover-images', + labels: { + singular: { en: 'Blog cover image', ua: 'Мета фото (блог)' }, + plural: { en: 'Blog cover images', ua: 'Мета фото (блог)' }, + }, + upload: { + formatOptions: { format: 'webp', options: { lossless: true } }, + mimeTypes: defaultPhotoMimeTypes, + imageSizes: [ + { + name: '700', + width: 700, + formatOptions: { format: 'webp', options: { quality: 85 } }, + }, + { + name: '800', + width: 800, + formatOptions: { format: 'webp', options: { quality: 85 } }, + }, + { + name: '1200', + width: 1200, + formatOptions: { format: 'webp', options: { quality: 85 } }, + }, + { + name: '1600', + width: 1600, + formatOptions: { format: 'webp', options: { quality: 85 } }, + }, + ], + }, + access: { + read: publicUploadCollectionWithoutApiAccess, + }, + admin: { + group: blogGroup, + }, + fields: [altField()], +}; + +export default BlogCoverImages; diff --git a/src/collections/media/BlogMetaImages.ts b/src/collections/media/BlogMetaImages.ts deleted file mode 100644 index 97d0c70..0000000 --- a/src/collections/media/BlogMetaImages.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { CollectionConfig } from 'payload/types'; - -import { publicUploadCollectionWithoutApiAccess } from 'utils/access'; -import { mediaGroup } from 'utils/groups'; - -const BlogMetaImages: CollectionConfig = { - slug: 'blog-meta-images', - labels: { - singular: { en: 'Blog meta image', ua: 'Мета фото (блог)' }, - plural: { en: 'Blog meta images', ua: 'Мета фото (блог)' }, - }, - upload: { - resizeOptions: { - width: 1200, - height: 630, - }, - formatOptions: { format: 'webp', options: { smartSubsample: true, quality: 85 } }, - mimeTypes: ['image/webp', 'image/jpeg', 'image/png', 'image/svg+xml'], - }, - access: { - read: publicUploadCollectionWithoutApiAccess, - }, - admin: { - group: mediaGroup, - }, - fields: [], -}; - -export default BlogMetaImages; diff --git a/src/collections/media/OpenGraphImages.ts b/src/collections/media/OpenGraphImages.ts new file mode 100644 index 0000000..62d6fb8 --- /dev/null +++ b/src/collections/media/OpenGraphImages.ts @@ -0,0 +1,32 @@ +import { CollectionConfig } from 'payload/types'; + +import { publicUploadCollectionWithoutApiAccess } from 'utils/access'; +import { mediaGroup } from 'utils/groups'; + +const OpenGraphImages: CollectionConfig = { + slug: 'open-graph-images', + labels: { + singular: { en: 'Open Graph image', ua: 'Open Graph зображення' }, + plural: { en: 'Open Graph images', ua: 'Open Graph зображення' }, + }, + upload: { + resizeOptions: { + width: 1200, + }, + formatOptions: { format: 'webp', options: { quality: 80 } }, + mimeTypes: ['image/webp', 'image/jpeg', 'image/png', 'image/svg+xml'], + }, + access: { + read: publicUploadCollectionWithoutApiAccess, + }, + admin: { + description: { + en: '1200x630 preview image for the link', + ua: '1200x630 зображення попереднього перегляду посилання', + }, + group: mediaGroup, + }, + fields: [], +}; + +export default OpenGraphImages; diff --git a/src/collections/media/ProjectAssets.ts b/src/collections/media/ProjectAssets.ts index 197042d..e6a3320 100644 --- a/src/collections/media/ProjectAssets.ts +++ b/src/collections/media/ProjectAssets.ts @@ -3,22 +3,20 @@ import { CollectionConfig } from 'payload/types'; import { altField } from 'fields/alt'; import { publicUploadCollectionWithoutApiAccess } from 'utils/access'; -import { mediaGroup } from 'utils/groups'; +import { projectsGroup } from 'utils/groups'; const ProjectAssets: CollectionConfig = { slug: 'project-assets', labels: { - singular: { en: 'Project Asset', ua: 'Дані проєкту' }, - plural: { en: 'Project Assets', ua: 'Дані проєкту' }, - }, - upload: { - mimeTypes: ['image/webp', 'image/jpeg', 'image/png', 'image/svg+xml'], + singular: { en: 'Project Asset', ua: 'Файл проєкту' }, + plural: { en: 'Project Assets', ua: 'Файли проєктів' }, }, + upload: true, access: { read: publicUploadCollectionWithoutApiAccess, }, admin: { - group: mediaGroup, + group: projectsGroup, }, fields: [altField()], }; diff --git a/src/collections/media/ProjectImages.ts b/src/collections/media/ProjectImages.ts index b745f68..cdf2559 100644 --- a/src/collections/media/ProjectImages.ts +++ b/src/collections/media/ProjectImages.ts @@ -3,7 +3,7 @@ import { CollectionConfig } from 'payload/types'; import { altField } from 'fields/alt'; import { publicUploadCollectionWithoutApiAccess } from 'utils/access'; -import { mediaGroup } from 'utils/groups'; +import { projectsGroup } from 'utils/groups'; import { defaultPhotoMimeTypes } from 'utils/mimeTypes'; const ProjectImages: CollectionConfig = { @@ -50,7 +50,7 @@ const ProjectImages: CollectionConfig = { read: publicUploadCollectionWithoutApiAccess, }, admin: { - group: mediaGroup, + group: projectsGroup, description: { en: 'All project images need to be 5:4 aspect ratio', ua: 'Всі зображення повинні бути у співвідношенні сторін 5:4', diff --git a/src/payload-types.ts b/src/payload-types.ts index c956d52..350e9a5 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -10,22 +10,24 @@ export interface Config { collections: { admins: Admin; 'contact-form-leads': ContactFormLead; - team: Team; - technologies: Technology; - 'technology-logos': TechnologyLogo; - 'team-member-photos': TeamMemberPhoto; - 'blog-posts': BlogPost; - 'blog-tags': BlogTag; 'blog-authors': BlogAuthor; - 'blog-meta-images': BlogMetaImage; 'author-photos': AuthorPhoto; + 'blog-posts': BlogPost; + 'blog-cover-images': BlogCoverImage; + 'blog-tags': BlogTag; locations: Location; + 'open-graph-images': OpenGraphImage; 'partner-logos': PartnerLogo; partners: Partner; + projects: Project; + 'project-images': ProjectImage; + 'project-assets': ProjectAsset; 'service-icons': ServiceIcon; services: Service; - 'project-images': ProjectImage; - projects: Project; + team: Team; + 'team-member-photos': TeamMemberPhoto; + technologies: Technology; + 'technology-logos': TechnologyLogo; 'payload-preferences': PayloadPreference; 'payload-migrations': PayloadMigration; }; @@ -34,6 +36,8 @@ export interface Config { 'blog-page': BlogPage; 'contacts-page': ContactsPage; 'cookies-policy-page': CookiesPolicyPage; + footer: Footer; + general: General; 'home-page': HomePage; 'privacy-policy-page': PrivacyPolicyPage; 'projects-page': ProjectsPage; @@ -41,10 +45,8 @@ export interface Config { 'sitemap-page': SitemapPage; 'support-ukraine-page': SupportUkrainePage; 'terms-of-use-page': TermsOfUsePage; - general: General; - navigation: Navigation; languages: Language; - footer: Footer; + navigation: Navigation; }; } export interface Admin { @@ -78,87 +80,20 @@ export interface ContactFormLead { updatedAt: string; createdAt: string; } -export interface Team { - id: string; - slug?: string; - order: number; - photo: string | TeamMemberPhoto; - firstName: string; - lastName?: string; - title: string; - fullTitle: string; - about?: string; - links?: { - name: string; - url: string; - id?: string; - }[]; - updatedAt: string; - createdAt: string; - _status?: 'draft' | 'published'; -} -export interface TeamMemberPhoto { - id: string; - alt?: string; - prefix?: string; - updatedAt: string; - createdAt: string; - url?: string; - filename?: string; - mimeType?: string; - filesize?: number; - width?: number; - height?: number; - sizes?: { - '700'?: { - url?: string; - width?: number; - height?: number; - mimeType?: string; - filesize?: number; - filename?: string; - }; - '800'?: { - url?: string; - width?: number; - height?: number; - mimeType?: string; - filesize?: number; - filename?: string; - }; - '1200'?: { - url?: string; - width?: number; - height?: number; - mimeType?: string; - filesize?: number; - filename?: string; - }; - '1600'?: { - url?: string; - width?: number; - height?: number; - mimeType?: string; - filesize?: number; - filename?: string; - }; - }; -} -export interface Technology { +export interface BlogAuthor { id: string; slug?: string; - order: number; + photo: string | AuthorPhoto; name: string; - logo: string | TechnologyLogo; - description: string; + email: string; updatedAt: string; createdAt: string; - _status?: 'draft' | 'published'; } -export interface TechnologyLogo { +export interface AuthorPhoto { id: string; alt?: string; prefix?: string; + blurhash?: string; updatedAt: string; createdAt: string; url?: string; @@ -171,9 +106,11 @@ export interface TechnologyLogo { export interface BlogPost { id: string; content: { - title?: string; + title: string; + description: string; tags: string[] | BlogTag[]; author: string | BlogAuthor; + landscape?: string | BlogCoverImage; content?: { [k: string]: unknown; }[]; @@ -181,13 +118,14 @@ export interface BlogPost { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; slug?: string; updatedAt: string; createdAt: string; + _status?: 'draft' | 'published'; } export interface BlogTag { id: string; @@ -196,16 +134,7 @@ export interface BlogTag { updatedAt: string; createdAt: string; } -export interface BlogAuthor { - id: string; - slug?: string; - photo: string | AuthorPhoto; - name: string; - email: string; - updatedAt: string; - createdAt: string; -} -export interface AuthorPhoto { +export interface BlogCoverImage { id: string; alt?: string; prefix?: string; @@ -217,10 +146,43 @@ export interface AuthorPhoto { filesize?: number; width?: number; height?: number; + sizes?: { + '700'?: { + url?: string; + width?: number; + height?: number; + mimeType?: string; + filesize?: number; + filename?: string; + }; + '800'?: { + url?: string; + width?: number; + height?: number; + mimeType?: string; + filesize?: number; + filename?: string; + }; + '1200'?: { + url?: string; + width?: number; + height?: number; + mimeType?: string; + filesize?: number; + filename?: string; + }; + '1600'?: { + url?: string; + width?: number; + height?: number; + mimeType?: string; + filesize?: number; + filename?: string; + }; + }; } -export interface BlogMetaImage { +export interface OpenGraphImage { id: string; - prefix?: string; updatedAt: string; createdAt: string; url?: string; @@ -677,6 +639,7 @@ export interface PartnerLogo { id: string; alt?: string; prefix?: string; + blurhash?: string; updatedAt: string; createdAt: string; url?: string; @@ -697,6 +660,90 @@ export interface Partner { updatedAt: string; createdAt: string; } +export interface Project { + id: string; + preview: { + name: string; + description: string; + image: string | ProjectImage; + }; + content: { + name: string; + description: string; + }; + meta?: { + title?: string; + description?: string; + image?: string | OpenGraphImage; + keywords?: string; + canonical?: string; + }; + slug?: string; + order: number; + updatedAt: string; + createdAt: string; + _status?: 'draft' | 'published'; +} +export interface ProjectImage { + id: string; + alt?: string; + prefix?: string; + updatedAt: string; + createdAt: string; + url?: string; + filename?: string; + mimeType?: string; + filesize?: number; + width?: number; + height?: number; + sizes?: { + '700'?: { + url?: string; + width?: number; + height?: number; + mimeType?: string; + filesize?: number; + filename?: string; + }; + '800'?: { + url?: string; + width?: number; + height?: number; + mimeType?: string; + filesize?: number; + filename?: string; + }; + '1200'?: { + url?: string; + width?: number; + height?: number; + mimeType?: string; + filesize?: number; + filename?: string; + }; + '1600'?: { + url?: string; + width?: number; + height?: number; + mimeType?: string; + filesize?: number; + filename?: string; + }; + }; +} +export interface ProjectAsset { + id: string; + alt?: string; + prefix?: string; + updatedAt: string; + createdAt: string; + url?: string; + filename?: string; + mimeType?: string; + filesize?: number; + width?: number; + height?: number; +} export interface ServiceIcon { id: string; alt?: string; @@ -721,9 +768,30 @@ export interface Service { createdAt: string; _status?: 'draft' | 'published'; } -export interface ProjectImage { +export interface Team { + id: string; + slug?: string; + order: number; + photo: string | TeamMemberPhoto; + firstName: string; + lastName?: string; + title: string; + fullTitle: string; + about?: string; + links?: { + name: string; + url: string; + id?: string; + }[]; + updatedAt: string; + createdAt: string; + _status?: 'draft' | 'published'; +} +export interface TeamMemberPhoto { id: string; alt?: string; + prefix?: string; + blurhash?: string; updatedAt: string; createdAt: string; url?: string; @@ -734,6 +802,7 @@ export interface ProjectImage { height?: number; sizes?: { '700'?: { + blurhash?: string; url?: string; width?: number; height?: number; @@ -742,6 +811,7 @@ export interface ProjectImage { filename?: string; }; '800'?: { + blurhash?: string; url?: string; width?: number; height?: number; @@ -750,6 +820,7 @@ export interface ProjectImage { filename?: string; }; '1200'?: { + blurhash?: string; url?: string; width?: number; height?: number; @@ -758,6 +829,7 @@ export interface ProjectImage { filename?: string; }; '1600'?: { + blurhash?: string; url?: string; width?: number; height?: number; @@ -767,30 +839,30 @@ export interface ProjectImage { }; }; } -export interface Project { +export interface Technology { id: string; - preview: { - name: string; - description: string; - image: string | ProjectImage; - }; - content: { - name: string; - description: string; - }; - meta?: { - title?: string; - description?: string; - image?: string | BlogMetaImage; - keywords?: string; - canonical?: string; - }; slug?: string; order: number; + name: string; + logo: string | TechnologyLogo; + description: string; updatedAt: string; createdAt: string; _status?: 'draft' | 'published'; } +export interface TechnologyLogo { + id: string; + alt?: string; + prefix?: string; + updatedAt: string; + createdAt: string; + url?: string; + filename?: string; + mimeType?: string; + filesize?: number; + width?: number; + height?: number; +} export interface PayloadPreference { id: string; user: { @@ -833,7 +905,7 @@ export interface AboutPage { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; @@ -857,7 +929,7 @@ export interface BlogPage { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; @@ -881,7 +953,7 @@ export interface ContactsPage { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; @@ -905,7 +977,7 @@ export interface CookiesPolicyPage { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; @@ -913,6 +985,29 @@ export interface CookiesPolicyPage { updatedAt?: string; createdAt?: string; } +export interface Footer { + id: string; + translation?: + | { + [k: string]: unknown; + } + | unknown[] + | string + | number + | boolean + | null; + _status?: 'draft' | 'published'; + updatedAt?: string; + createdAt?: string; +} +export interface General { + id: string; + phone: string; + email: string; + _status?: 'draft' | 'published'; + updatedAt?: string; + createdAt?: string; +} export interface HomePage { id: string; content: { @@ -929,7 +1024,7 @@ export interface HomePage { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; @@ -953,7 +1048,7 @@ export interface PrivacyPolicyPage { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; @@ -977,7 +1072,7 @@ export interface ProjectsPage { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; @@ -1001,7 +1096,7 @@ export interface ScheduleMeetingPage { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; @@ -1025,7 +1120,7 @@ export interface SitemapPage { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; @@ -1049,7 +1144,7 @@ export interface SupportUkrainePage { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; @@ -1073,7 +1168,7 @@ export interface TermsOfUsePage { meta?: { title?: string; description?: string; - image?: string | BlogMetaImage; + image?: string | OpenGraphImage; keywords?: string; canonical?: string; }; @@ -1081,29 +1176,6 @@ export interface TermsOfUsePage { updatedAt?: string; createdAt?: string; } -export interface General { - id: string; - phone: string; - email: string; - _status?: 'draft' | 'published'; - updatedAt?: string; - createdAt?: string; -} -export interface Navigation { - id: string; - translation?: - | { - [k: string]: unknown; - } - | unknown[] - | string - | number - | boolean - | null; - _status?: 'draft' | 'published'; - updatedAt?: string; - createdAt?: string; -} export interface Language { id: string; translation?: @@ -1118,7 +1190,7 @@ export interface Language { updatedAt?: string; createdAt?: string; } -export interface Footer { +export interface Navigation { id: string; translation?: | { @@ -1140,22 +1212,24 @@ declare module 'payload' { collections: { 'admins': Admin 'contact-form-leads': ContactFormLead - 'team': Team - 'technologies': Technology - 'technology-logos': TechnologyLogo - 'team-member-photos': TeamMemberPhoto - 'blog-posts': BlogPost - 'blog-tags': BlogTag 'blog-authors': BlogAuthor - 'blog-meta-images': BlogMetaImage 'author-photos': AuthorPhoto + 'blog-posts': BlogPost + 'blog-cover-images': BlogCoverImage + 'blog-tags': BlogTag 'locations': Location + 'open-graph-images': OpenGraphImage 'partner-logos': PartnerLogo 'partners': Partner + 'projects': Project + 'project-images': ProjectImage + 'project-assets': ProjectAsset 'service-icons': ServiceIcon 'services': Service - 'project-images': ProjectImage - 'projects': Project + 'team': Team + 'team-member-photos': TeamMemberPhoto + 'technologies': Technology + 'technology-logos': TechnologyLogo 'payload-preferences': PayloadPreference 'payload-migrations': PayloadMigration } @@ -1164,6 +1238,8 @@ declare module 'payload' { 'blog-page': BlogPage 'contacts-page': ContactsPage 'cookies-policy-page': CookiesPolicyPage + 'footer': Footer + 'general': General 'home-page': HomePage 'privacy-policy-page': PrivacyPolicyPage 'projects-page': ProjectsPage @@ -1171,10 +1247,8 @@ declare module 'payload' { 'sitemap-page': SitemapPage 'support-ukraine-page': SupportUkrainePage 'terms-of-use-page': TermsOfUsePage - 'general': General - 'navigation': Navigation 'languages': Language - 'footer': Footer + 'navigation': Navigation } } } \ No newline at end of file From 697d6361856347a2797eabd80b97cf00dbb72d02 Mon Sep 17 00:00:00 2001 From: Bohdan Kucherivayi Date: Thu, 26 Oct 2023 14:21:37 +0300 Subject: [PATCH 3/4] 1.2.5 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index 24bc06b..3cc16dc 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@zapal/website-cms", - "version": "1.2.4", + "version": "1.2.5", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@zapal/website-cms", - "version": "1.2.4", + "version": "1.2.5", "license": "MIT", "dependencies": { "@google-cloud/storage": "6.4.1", diff --git a/package.json b/package.json index 883df07..41e97ff 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "@zapal/website-cms", "description": "Zapal's website CMS", - "version": "1.2.4", + "version": "1.2.5", "main": "dist/server.js", "license": "MIT", "scripts": { From 1317c548a68633e6d4e3a052c9bcaa97528354a6 Mon Sep 17 00:00:00 2001 From: Bohdan Kucherivayi Date: Thu, 26 Oct 2023 14:27:12 +0300 Subject: [PATCH 4/4] feat: add blurhash for blog cover images --- src/payload.config.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/payload.config.ts b/src/payload.config.ts index 4f196bc..c803b3e 100644 --- a/src/payload.config.ts +++ b/src/payload.config.ts @@ -345,7 +345,7 @@ export default buildConfig({ tabbedUI: true, }), blurHash({ - collections: [AuthorPhotos.slug, PartnerLogos.slug, TeamMemberPhotos.slug], + collections: [AuthorPhotos.slug, PartnerLogos.slug, TeamMemberPhotos.slug, BlogCoverImages.slug], }), ], });