feat: manage blog detail fallback copy via payload

This commit is contained in:
syntaxbullet
2026-06-22 12:43:34 +02:00
parent 4a751317b0
commit e12d814040
4 changed files with 58 additions and 9 deletions

View File

@@ -166,6 +166,21 @@ export const Posts: CollectionConfig<'posts'> = {
{ name: 'url', type: 'text', defaultValue: blogDetailContent.heroBackLink.url }, { name: 'url', type: 'text', defaultValue: blogDetailContent.heroBackLink.url },
], ],
}, },
{
name: 'fallbackArticle',
label: 'Missing article field fallbacks',
type: 'group',
fields: [
{ name: 'title', type: 'text', defaultValue: blogDetailContent.fallbackArticle.title },
{ name: 'category', type: 'text', defaultValue: blogDetailContent.fallbackArticle.category },
{ name: 'date', type: 'text', defaultValue: blogDetailContent.fallbackArticle.date },
{ name: 'authorName', type: 'text', defaultValue: blogDetailContent.fallbackArticle.authorName },
{ name: 'authorRole', type: 'text', defaultValue: blogDetailContent.fallbackArticle.authorRole },
{ name: 'readTime', type: 'text', defaultValue: blogDetailContent.fallbackArticle.readTime },
{ name: 'excerpt', type: 'textarea', defaultValue: blogDetailContent.fallbackArticle.excerpt },
{ name: 'tag', type: 'text', defaultValue: blogDetailContent.fallbackArticle.tag },
],
},
{ {
name: 'categoryColors', name: 'categoryColors',
label: 'Category colors JSON', label: 'Category colors JSON',

View File

@@ -2156,6 +2156,16 @@ export interface Post {
label?: string | null; label?: string | null;
url?: string | null; url?: string | null;
}; };
fallbackArticle?: {
title?: string | null;
category?: string | null;
date?: string | null;
authorName?: string | null;
authorRole?: string | null;
readTime?: string | null;
excerpt?: string | null;
tag?: string | null;
};
categoryColors?: categoryColors?:
| { | {
[k: string]: unknown; [k: string]: unknown;
@@ -5025,6 +5035,18 @@ export interface PostsSelect<T extends boolean = true> {
label?: T; label?: T;
url?: T; url?: T;
}; };
fallbackArticle?:
| T
| {
title?: T;
category?: T;
date?: T;
authorName?: T;
authorRole?: T;
readTime?: T;
excerpt?: T;
tag?: T;
};
categoryColors?: T; categoryColors?: T;
metaCopy?: metaCopy?:
| T | T

View File

@@ -9,6 +9,16 @@ export const blogDetailContent = {
label: 'Newsroom', label: 'Newsroom',
url: '/presse', url: '/presse',
}, },
fallbackArticle: {
title: 'Presse',
category: 'Presse',
date: 'Aktuell',
authorName: 'BMP Redaktion',
authorRole: 'Presse',
readTime: '1 min',
excerpt: 'Dieser Pressebeitrag wird aus Payload CMS geladen.',
tag: 'Presse',
},
categoryColors: { categoryColors: {
Innovation: '#2563EB', Innovation: '#2563EB',
Engagement: '#16A34A', Engagement: '#16A34A',

View File

@@ -35,6 +35,7 @@ const getDetailPage = (value: unknown): BlogDetailCms => {
...detail, ...detail,
notFound: { ...blogDetailContent.notFound, ...detail.notFound }, notFound: { ...blogDetailContent.notFound, ...detail.notFound },
heroBackLink: { ...blogDetailContent.heroBackLink, ...detail.heroBackLink }, heroBackLink: { ...blogDetailContent.heroBackLink, ...detail.heroBackLink },
fallbackArticle: { ...blogDetailContent.fallbackArticle, ...detail.fallbackArticle },
categoryColors: colorMap(detail.categoryColors), categoryColors: colorMap(detail.categoryColors),
metaCopy: { ...blogDetailContent.meta, ...(detail.metaCopy || detail.meta) }, metaCopy: { ...blogDetailContent.meta, ...(detail.metaCopy || detail.meta) },
sidebarCta: { ...blogDetailContent.sidebarCta, ...detail.sidebarCta }, sidebarCta: { ...blogDetailContent.sidebarCta, ...detail.sidebarCta },
@@ -48,23 +49,24 @@ export default function BlogDetail() {
const route = useCmsRoute(); const route = useCmsRoute();
const cmsArticle = route?.collection === 'posts' ? route.doc : undefined; const cmsArticle = route?.collection === 'posts' ? route.doc : undefined;
const cmsDetail = getDetailPage(cmsArticle?.detailPage); const cmsDetail = getDetailPage(cmsArticle?.detailPage);
const fallbackArticle = cmsDetail.fallbackArticle || blogDetailContent.fallbackArticle;
const articleFallbackImage = mediaUrl(cmsDetail.fallbackImage, `/images/${blogDetailContent.fallbackImageFilename}`); const articleFallbackImage = mediaUrl(cmsDetail.fallbackImage, `/images/${blogDetailContent.fallbackImageFilename}`);
const article = (slug ? getArticleBySlug(slug) : undefined) || (cmsArticle ? { const article = (slug ? getArticleBySlug(slug) : undefined) || (cmsArticle ? {
slug: String(cmsArticle.slug || slug), slug: String(cmsArticle.slug || slug),
title: String(cmsArticle.title || 'Presse'), title: String(cmsArticle.title || fallbackArticle.title || blogDetailContent.fallbackArticle.title),
cat: String(cmsArticle.cat || 'Presse'), cat: String(cmsArticle.cat || fallbackArticle.category || blogDetailContent.fallbackArticle.category),
date: String(cmsArticle.date || 'Aktuell'), date: String(cmsArticle.date || fallbackArticle.date || blogDetailContent.fallbackArticle.date),
author: String(cmsArticle.authorName || 'BMP Redaktion'), author: String(cmsArticle.authorName || fallbackArticle.authorName || blogDetailContent.fallbackArticle.authorName),
authorRole: String(cmsArticle.authorRole || 'Presse'), authorRole: String(cmsArticle.authorRole || fallbackArticle.authorRole || blogDetailContent.fallbackArticle.authorRole),
readTime: String(cmsArticle.readTime || '1 min'), readTime: String(cmsArticle.readTime || fallbackArticle.readTime || blogDetailContent.fallbackArticle.readTime),
img: docImageUrl(cmsArticle, articleFallbackImage, 'heroImage'), img: docImageUrl(cmsArticle, articleFallbackImage, 'heroImage'),
excerpt: String(cmsArticle.excerpt || cmsArticle.meta?.description || 'Dieser Pressebeitrag wird aus Payload CMS geladen.'), excerpt: String(cmsArticle.excerpt || cmsArticle.meta?.description || fallbackArticle.excerpt || blogDetailContent.fallbackArticle.excerpt),
sections: Array.isArray(cmsArticle.sections) && cmsArticle.sections.length > 0 ? cmsArticle.sections as BlogSection[] : [{ body: String(cmsArticle.excerpt || cmsArticle.meta?.description || 'Dieser Pressebeitrag wird aus Payload CMS geladen.') }], sections: Array.isArray(cmsArticle.sections) && cmsArticle.sections.length > 0 ? cmsArticle.sections as BlogSection[] : [{ body: String(cmsArticle.excerpt || cmsArticle.meta?.description || fallbackArticle.excerpt || blogDetailContent.fallbackArticle.excerpt) }],
tags: Array.isArray(cmsArticle.tags) tags: Array.isArray(cmsArticle.tags)
? cmsArticle.tags ? cmsArticle.tags
.map((item: { tag?: string }) => item.tag) .map((item: { tag?: string }) => item.tag)
.filter((tag): tag is string => Boolean(tag)) .filter((tag): tag is string => Boolean(tag))
: ['Presse'], : [String(fallbackArticle.tag || blogDetailContent.fallbackArticle.tag)],
relatedSlugs: Array.isArray(cmsArticle.relatedSlugs) relatedSlugs: Array.isArray(cmsArticle.relatedSlugs)
? cmsArticle.relatedSlugs ? cmsArticle.relatedSlugs
.map((item: { slug?: string }) => item.slug) .map((item: { slug?: string }) => item.slug)