292 lines
9.0 KiB
TypeScript
292 lines
9.0 KiB
TypeScript
import type { CollectionConfig } from 'payload'
|
|
|
|
import { authenticated } from '@/access/authenticated'
|
|
import { authenticatedOrPublished } from '@/access/authenticatedOrPublished'
|
|
import { populatePublishedAt } from '@/hooks/populatePublishedAt'
|
|
import { eventDetailContent } from '@/spa/eventDetailContent'
|
|
import { generatePreviewPath } from '@/utilities/generatePreviewPath'
|
|
import { slugField } from 'payload'
|
|
|
|
import { revalidateEvent, revalidateEventDelete } from './Events/hooks/revalidateEvent'
|
|
|
|
import {
|
|
MetaDescriptionField,
|
|
MetaTitleField,
|
|
OverviewField,
|
|
PreviewField,
|
|
} from '@payloadcms/plugin-seo/fields'
|
|
|
|
export const Events: CollectionConfig = {
|
|
slug: 'events',
|
|
labels: {
|
|
singular: 'Termin / Event',
|
|
plural: 'Termine & Events',
|
|
},
|
|
access: {
|
|
create: authenticated,
|
|
delete: authenticated,
|
|
read: authenticatedOrPublished,
|
|
update: authenticated,
|
|
},
|
|
admin: {
|
|
defaultColumns: ['title', 'spaPath', 'slug', 'updatedAt'],
|
|
group: 'Inhalte',
|
|
livePreview: {
|
|
url: ({ data, req }) =>
|
|
generatePreviewPath({
|
|
slug: data?.spaPath || data?.slug,
|
|
collection: 'events',
|
|
req,
|
|
}),
|
|
},
|
|
preview: (data, { req }) =>
|
|
generatePreviewPath({
|
|
slug: ((data?.spaPath as string | undefined) || (data?.slug as string)),
|
|
collection: 'events',
|
|
req,
|
|
}),
|
|
useAsTitle: 'title',
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
{
|
|
name: 'subtitle',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'image',
|
|
type: 'upload',
|
|
relationTo: 'media',
|
|
},
|
|
{
|
|
name: 'description',
|
|
type: 'textarea',
|
|
},
|
|
{
|
|
name: 'longDescription',
|
|
type: 'textarea',
|
|
},
|
|
{
|
|
name: 'date',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'time',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'location',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'venue',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'category',
|
|
type: 'text',
|
|
},
|
|
{
|
|
name: 'status',
|
|
type: 'select',
|
|
options: [
|
|
{ label: 'Geplant', value: 'geplant' },
|
|
{ label: 'Anmeldung offen', value: 'anmeldung-offen' },
|
|
{ label: 'Intern', value: 'intern' },
|
|
{ label: 'Abgeschlossen', value: 'abgeschlossen' },
|
|
],
|
|
defaultValue: 'geplant',
|
|
},
|
|
{
|
|
name: 'eckdaten',
|
|
type: 'array',
|
|
fields: [
|
|
{ name: 'label', type: 'text', required: true },
|
|
{ name: 'value', type: 'text', required: true },
|
|
],
|
|
},
|
|
{
|
|
name: 'updates',
|
|
type: 'array',
|
|
fields: [
|
|
{ name: 'timestamp', type: 'text', required: true },
|
|
{
|
|
name: 'type',
|
|
type: 'select',
|
|
options: ['ankündigung', 'erinnerung', 'update', 'highlight', 'ergebnis', 'wichtig'],
|
|
required: true,
|
|
},
|
|
{ name: 'title', type: 'text', required: true },
|
|
{ name: 'body', type: 'textarea', required: true },
|
|
],
|
|
},
|
|
{
|
|
name: 'detailPage',
|
|
label: 'Detail page chrome',
|
|
type: 'group',
|
|
admin: {
|
|
description:
|
|
'Shared labels, status/update labels, subscription copy, CTAs, and formatting copy for the Event detail route.',
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'fallbackImage',
|
|
type: 'upload',
|
|
relationTo: 'media',
|
|
label: 'Fallback hero image',
|
|
admin: {
|
|
description: `Current frontend fallback image: /images/${eventDetailContent.fallbackImageFilename}`,
|
|
},
|
|
},
|
|
{
|
|
name: 'notFound',
|
|
label: 'Not found state',
|
|
type: 'group',
|
|
fields: [
|
|
{ name: 'title', type: 'text', defaultValue: eventDetailContent.notFound.title },
|
|
{ name: 'backLabel', type: 'text', defaultValue: eventDetailContent.notFound.backLabel },
|
|
{ name: 'backUrl', type: 'text', defaultValue: eventDetailContent.notFound.backUrl },
|
|
],
|
|
},
|
|
{
|
|
name: 'dateFormat',
|
|
label: 'Date format',
|
|
type: 'group',
|
|
fields: [
|
|
{
|
|
name: 'monthNames',
|
|
type: 'json',
|
|
defaultValue: eventDetailContent.dateFormat.monthNames,
|
|
admin: { description: 'Array of 12 month names used when formatting update timestamps.' },
|
|
},
|
|
{ name: 'timeSuffix', type: 'text', defaultValue: eventDetailContent.dateFormat.timeSuffix },
|
|
],
|
|
},
|
|
{
|
|
name: 'updateStyles',
|
|
label: 'Update type labels/styles JSON',
|
|
type: 'json',
|
|
defaultValue: eventDetailContent.updateStyles,
|
|
},
|
|
{
|
|
name: 'statusStyles',
|
|
label: 'Status labels/styles JSON',
|
|
type: 'json',
|
|
defaultValue: eventDetailContent.statusStyles,
|
|
},
|
|
{
|
|
name: 'heroBackLink',
|
|
label: 'Hero back link',
|
|
type: 'group',
|
|
fields: [
|
|
{ name: 'label', type: 'text', defaultValue: eventDetailContent.heroBackLink.label },
|
|
{ name: 'url', type: 'text', defaultValue: eventDetailContent.heroBackLink.url },
|
|
],
|
|
},
|
|
{
|
|
name: 'fallbackEvent',
|
|
label: 'Missing event field fallbacks',
|
|
type: 'group',
|
|
fields: [
|
|
{ name: 'title', type: 'text', defaultValue: eventDetailContent.fallbackEvent.title },
|
|
{ name: 'date', type: 'text', defaultValue: eventDetailContent.fallbackEvent.date },
|
|
{ name: 'time', type: 'text', defaultValue: eventDetailContent.fallbackEvent.time },
|
|
{ name: 'location', type: 'text', defaultValue: eventDetailContent.fallbackEvent.location },
|
|
{ name: 'venue', type: 'text', defaultValue: eventDetailContent.fallbackEvent.venue },
|
|
{ name: 'category', type: 'text', defaultValue: eventDetailContent.fallbackEvent.category },
|
|
{ name: 'status', type: 'text', defaultValue: eventDetailContent.fallbackEvent.status },
|
|
{ name: 'longDescription', type: 'textarea', defaultValue: eventDetailContent.fallbackEvent.longDescription },
|
|
],
|
|
},
|
|
{
|
|
name: 'sections',
|
|
label: 'Section labels and CTAs',
|
|
type: 'group',
|
|
fields: [
|
|
{ name: 'aboutEyebrow', type: 'text', defaultValue: eventDetailContent.sections.aboutEyebrow },
|
|
{ name: 'factsEyebrow', type: 'text', defaultValue: eventDetailContent.sections.factsEyebrow },
|
|
{ name: 'registerLabel', type: 'text', defaultValue: eventDetailContent.sections.registerLabel },
|
|
{ name: 'registerUrl', type: 'text', defaultValue: eventDetailContent.sections.registerUrl },
|
|
{ name: 'questionLabel', type: 'text', defaultValue: eventDetailContent.sections.questionLabel },
|
|
{ name: 'questionUrl', type: 'text', defaultValue: eventDetailContent.sections.questionUrl },
|
|
],
|
|
},
|
|
{
|
|
name: 'updatesCopy',
|
|
label: 'Updates panel',
|
|
type: 'group',
|
|
fields: [
|
|
{ name: 'heading', type: 'text', defaultValue: eventDetailContent.updates.heading },
|
|
{ name: 'subscribeLabel', type: 'text', defaultValue: eventDetailContent.updates.subscribeLabel },
|
|
{ name: 'unsubscribeLabel', type: 'text', defaultValue: eventDetailContent.updates.unsubscribeLabel },
|
|
{ name: 'subscribedMessage', type: 'text', defaultValue: eventDetailContent.updates.subscribedMessage },
|
|
],
|
|
},
|
|
{
|
|
name: 'bottomCta',
|
|
label: 'Bottom CTA',
|
|
type: 'group',
|
|
fields: [
|
|
{ name: 'eyebrow', type: 'text', defaultValue: eventDetailContent.bottomCta.eyebrow },
|
|
{ name: 'heading', type: 'text', defaultValue: eventDetailContent.bottomCta.heading },
|
|
{ name: 'label', type: 'text', defaultValue: eventDetailContent.bottomCta.label },
|
|
{ name: 'url', type: 'text', defaultValue: eventDetailContent.bottomCta.url },
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'spaPath',
|
|
type: 'text',
|
|
index: true,
|
|
admin: {
|
|
description: 'Route in the legacy SPA used for previewing the current migrated event state.',
|
|
position: 'sidebar',
|
|
},
|
|
},
|
|
{
|
|
name: 'publishedAt',
|
|
type: 'date',
|
|
admin: {
|
|
position: 'sidebar',
|
|
},
|
|
},
|
|
{
|
|
name: 'meta',
|
|
type: 'group',
|
|
fields: [
|
|
OverviewField({
|
|
titlePath: 'meta.title',
|
|
descriptionPath: 'meta.description',
|
|
}),
|
|
MetaTitleField({ hasGenerateFn: true }),
|
|
MetaDescriptionField({}),
|
|
PreviewField({
|
|
hasGenerateFn: true,
|
|
titlePath: 'meta.title',
|
|
descriptionPath: 'meta.description',
|
|
}),
|
|
],
|
|
},
|
|
slugField(),
|
|
],
|
|
hooks: {
|
|
afterChange: [revalidateEvent],
|
|
afterDelete: [revalidateEventDelete],
|
|
beforeChange: [populatePublishedAt],
|
|
},
|
|
versions: {
|
|
drafts: {
|
|
autosave: {
|
|
interval: 100,
|
|
},
|
|
schedulePublish: true,
|
|
},
|
|
maxPerDoc: 50,
|
|
},
|
|
}
|