208 lines
6.8 KiB
TypeScript
208 lines
6.8 KiB
TypeScript
import type { CollectionConfig } from 'payload'
|
|
|
|
import { authenticated } from '../../access/authenticated'
|
|
import { authenticatedOrPublished } from '../../access/authenticatedOrPublished'
|
|
import { populatePublishedAt } from '../../hooks/populatePublishedAt'
|
|
import { generatePreviewPath } from '../../utilities/generatePreviewPath'
|
|
import { revalidateDelete, revalidatePage } from './hooks/revalidatePage'
|
|
|
|
import { FDHeroBlock } from '../../blocks/FDHeroBlock/config'
|
|
import { FDCtaSideImageBlock } from '../../blocks/FDCtaSideImageBlock/config'
|
|
import { FDFeatureAnnouncementBlock } from '../../blocks/FDFeatureAnnouncementBlock/config'
|
|
import { FDServicesGridBlock } from '../../blocks/FDServicesGridBlock/config'
|
|
import { FDContactBlock } from '../../blocks/FDContactBlock/config'
|
|
import { FDFaqBlock } from '../../blocks/FDFaqBlock/config'
|
|
import { FDCardGridBlock } from '../../blocks/FDCardGridBlock/config'
|
|
import { FDPricingCardBlock } from '../../blocks/FDPricingCardBlock/config'
|
|
import { FDSpacerBlock } from '../../blocks/FDSpacerBlock/config'
|
|
import { FDIconBarBlock } from '../../blocks/FDIconBarBlock/config'
|
|
import { FDUspChecklistBlock } from '../../blocks/FDUspChecklistBlock/config'
|
|
import { FDWideCardBlock } from '../../blocks/FDWideCardBlock/config'
|
|
import { FDTechPropertiesBlock } from '../../blocks/FDTechPropertiesBlock/config'
|
|
import { FDUspTableBlock } from '../../blocks/FDUspTableBlock/config'
|
|
import { FDHeaderTextImageBlock } from '../../blocks/FDHeaderTextImageBlock/config'
|
|
import { FDContactFormBlock } from '../../blocks/FDContactFormBlock/config'
|
|
import { FDTagsBlock } from '../../blocks/FDTagsBlock/config'
|
|
import { FDTextBlock } from '../../blocks/FDTextBlock/config'
|
|
import { FDLocationsGridBlock } from '../../blocks/FDLocationsGridBlock/config'
|
|
import { FDAlternateHeroBlock } from '../../blocks/FDAlternateHeroBlock/config'
|
|
import { FDStatisticsBlock } from '../../blocks/FDStatisticsBlock/config'
|
|
import { FDPartnersLogosBlock } from '../../blocks/FDPartnersLogosBlock/config'
|
|
import { FDNewsletterBlock } from '../../blocks/FDNewsletterBlock/config'
|
|
import { FDServiceChooserBlock } from '../../blocks/FDServiceChooserBlock/config'
|
|
import { FDDataTableBlock } from '../../blocks/FDDataTableBlock/config'
|
|
import { FDVpsCalculatorBlock } from '../../blocks/FDVpsCalculatorBlock/config'
|
|
import { FDCodeEmbedBlock } from '../../blocks/FDCodeEmbedBlock/config'
|
|
import { FDVideoBlock } from '../../blocks/FDVideoBlock/config'
|
|
import { FDCtaBannerBlock } from '../../blocks/FDCtaBannerBlock/config'
|
|
import { FDTestimonialBlock } from '../../blocks/FDTestimonialBlock/config'
|
|
import { FDTeamBlock } from '../../blocks/FDTeamBlock/config'
|
|
|
|
import {
|
|
MetaDescriptionField,
|
|
MetaImageField,
|
|
MetaTitleField,
|
|
OverviewField,
|
|
PreviewField,
|
|
} from '@payloadcms/plugin-seo/fields'
|
|
|
|
// ── Slug generator — handles Swedish characters ────────────────────────────
|
|
const generateSlug = (value: string): string =>
|
|
value
|
|
.toLowerCase()
|
|
.trim()
|
|
.replace(/[åä]/g, 'a')
|
|
.replace(/ö/g, 'o')
|
|
.replace(/[^a-z0-9]+/g, '-')
|
|
.replace(/^-+|-+$/g, '')
|
|
|
|
export const Pages: CollectionConfig<'pages'> = {
|
|
slug: 'pages',
|
|
access: {
|
|
create: authenticated,
|
|
delete: authenticated,
|
|
read: authenticatedOrPublished,
|
|
update: authenticated,
|
|
},
|
|
defaultPopulate: {
|
|
title: true,
|
|
slug: true,
|
|
},
|
|
admin: {
|
|
defaultColumns: ['title', 'slug', 'updatedAt'],
|
|
livePreview: {
|
|
url: ({ data, req }) =>
|
|
generatePreviewPath({
|
|
slug: data?.slug,
|
|
collection: 'pages',
|
|
req,
|
|
}),
|
|
},
|
|
preview: (data, { req }) =>
|
|
generatePreviewPath({
|
|
slug: data?.slug as string,
|
|
collection: 'pages',
|
|
req,
|
|
}),
|
|
useAsTitle: 'title',
|
|
},
|
|
fields: [
|
|
{
|
|
name: 'title',
|
|
type: 'text',
|
|
required: true,
|
|
},
|
|
{
|
|
type: 'tabs',
|
|
tabs: [
|
|
{
|
|
fields: [
|
|
{
|
|
name: 'layout',
|
|
type: 'blocks',
|
|
blocks: [
|
|
FDHeroBlock,
|
|
FDCtaSideImageBlock,
|
|
FDFeatureAnnouncementBlock,
|
|
FDServicesGridBlock,
|
|
FDContactBlock,
|
|
FDFaqBlock,
|
|
FDCardGridBlock,
|
|
FDPricingCardBlock,
|
|
FDSpacerBlock,
|
|
FDIconBarBlock,
|
|
FDUspChecklistBlock,
|
|
FDWideCardBlock,
|
|
FDTechPropertiesBlock,
|
|
FDUspTableBlock,
|
|
FDHeaderTextImageBlock,
|
|
FDContactFormBlock,
|
|
FDLocationsGridBlock,
|
|
FDAlternateHeroBlock,
|
|
FDStatisticsBlock,
|
|
FDPartnersLogosBlock,
|
|
FDNewsletterBlock,
|
|
FDServiceChooserBlock,
|
|
FDDataTableBlock,
|
|
FDVpsCalculatorBlock,
|
|
FDTagsBlock,
|
|
FDTextBlock,
|
|
FDCodeEmbedBlock,
|
|
FDVideoBlock,
|
|
FDCtaBannerBlock,
|
|
FDTestimonialBlock,
|
|
FDTeamBlock
|
|
],
|
|
required: true,
|
|
admin: {
|
|
initCollapsed: true,
|
|
},
|
|
},
|
|
],
|
|
label: 'Innehåll',
|
|
},
|
|
{
|
|
name: 'meta',
|
|
label: 'SEO',
|
|
fields: [
|
|
OverviewField({
|
|
titlePath: 'meta.title',
|
|
descriptionPath: 'meta.description',
|
|
imagePath: 'meta.image',
|
|
}),
|
|
MetaTitleField({
|
|
hasGenerateFn: true,
|
|
}),
|
|
MetaImageField({
|
|
relationTo: 'media',
|
|
}),
|
|
MetaDescriptionField({}),
|
|
PreviewField({
|
|
hasGenerateFn: true,
|
|
titlePath: 'meta.title',
|
|
descriptionPath: 'meta.description',
|
|
}),
|
|
],
|
|
},
|
|
],
|
|
},
|
|
{
|
|
name: 'publishedAt',
|
|
type: 'date',
|
|
admin: {
|
|
position: 'sidebar',
|
|
},
|
|
},
|
|
// ── Slug ──────────────────────────────────────────────────────────────
|
|
{
|
|
name: 'slug',
|
|
type: 'text',
|
|
required: true,
|
|
index: true,
|
|
admin: {
|
|
position: 'sidebar',
|
|
description: 'Genereras automatiskt från titeln.',
|
|
},
|
|
hooks: {
|
|
beforeChange: [
|
|
({ data }) => generateSlug(data?.title || ''),
|
|
],
|
|
},
|
|
}, // ← slug object closes here, then straight into ],
|
|
],
|
|
hooks: {
|
|
afterChange: [revalidatePage],
|
|
beforeChange: [populatePublishedAt],
|
|
afterDelete: [revalidateDelete],
|
|
},
|
|
versions: {
|
|
drafts: {
|
|
autosave: {
|
|
interval: 100,
|
|
},
|
|
schedulePublish: true,
|
|
},
|
|
maxPerDoc: 50,
|
|
},
|
|
}
|