Last active
June 23, 2025 14:41
-
-
Save pro-laico/2887985e10e1b91721d53320d712774d to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import type { CollectionConfig } from 'payload' | |
import { authenticated } from '../../access/authenticated' | |
import { authenticatedOrPublished } from '../../access/authenticatedOrPublished' | |
import { slugField } from '@/fields/slug' | |
import { populatePublishedAt } from '../../hooks/populatePublishedAt' | |
import { generatePreviewPath } from '../../utilities/generatePreviewPath' | |
import { revalidateDelete, revalidatePage } from './hooks/revalidatePage' | |
import { populateHref } from '@/hooks/populateHref' | |
import { createBreadcrumbsField, createParentField } from '@payloadcms/plugin-nested-docs' | |
import { | |
MetaDescriptionField, | |
MetaImageField, | |
MetaTitleField, | |
OverviewField, | |
PreviewField, | |
} from '@payloadcms/plugin-seo/fields' | |
import Blocks from '@/blocks' | |
import { ClassNameField } from '@/proLaico/styles/fields/ClassName' | |
export const Pages: CollectionConfig<'pages'> = { | |
slug: 'pages', | |
access: { | |
create: authenticated, | |
delete: authenticated, | |
read: authenticatedOrPublished, | |
update: authenticated, | |
}, | |
// This config controls what's populated by default when a page is referenced | |
// https://payloadcms.com/docs/queries/select#defaultpopulate-collection-config-property | |
// Type safe if the collection slug generic is passed to `CollectionConfig` - `CollectionConfig<'pages'> | |
defaultPopulate: { | |
title: true, | |
slug: true, | |
href: true, | |
}, | |
admin: { | |
defaultColumns: ['title', 'slug', 'href', 'updatedAt'], | |
livePreview: { | |
url: ({ data, req }) => { | |
const path = generatePreviewPath({ | |
slug: typeof data?.slug === 'string' ? data.slug : '', | |
path: typeof data?.href === 'string' ? data.href : '', | |
collection: 'pages', | |
req, | |
}) | |
return path | |
}, | |
}, | |
preview: (data, { req }) => | |
generatePreviewPath({ | |
slug: typeof data?.slug === 'string' ? data.slug : '', | |
path: typeof data?.href === 'string' ? data.href : '', | |
collection: 'pages', | |
req, | |
}), | |
useAsTitle: 'title', | |
}, | |
fields: [ | |
{ | |
name: 'title', | |
type: 'text', | |
required: true, | |
}, | |
{ | |
type: 'tabs', | |
tabs: [ | |
{ | |
label: 'Children', | |
fields: [ | |
{ | |
name: 'children-gen-1', | |
type: 'blocks', | |
blocks: [...Blocks], | |
required: true, | |
admin: { | |
initCollapsed: true, | |
}, | |
}, | |
], | |
}, | |
{ | |
name: 'meta', | |
label: 'SEO', | |
fields: [ | |
OverviewField({ | |
titlePath: 'meta.title', | |
descriptionPath: 'meta.description', | |
imagePath: 'meta.image', | |
}), | |
MetaTitleField({ | |
hasGenerateFn: true, | |
}), | |
MetaImageField({ | |
relationTo: 'media', | |
}), | |
MetaDescriptionField({}), | |
PreviewField({ | |
// if the `generateUrl` function is configured | |
hasGenerateFn: true, | |
// field paths to match the target field for data | |
titlePath: 'meta.title', | |
descriptionPath: 'meta.description', | |
}), | |
], | |
}, | |
{ | |
label: 'Styles', | |
fields: [ | |
ClassNameField({ | |
namePrefix: 'main', | |
}), | |
], | |
}, | |
{ | |
label: 'Settings', | |
fields: [ | |
{ | |
name: 'noIndex', | |
type: 'checkbox', | |
defaultValue: false, | |
}, | |
], | |
}, | |
], | |
}, | |
{ | |
name: 'publishedAt', | |
type: 'date', | |
admin: { | |
position: 'sidebar', | |
}, | |
}, | |
...slugField(), | |
{ | |
name: 'href', | |
type: 'text', | |
admin: { | |
position: 'sidebar', | |
}, | |
}, | |
createParentField('pages', { | |
name: 'parent', | |
label: 'Parent', | |
admin: { | |
position: 'sidebar', | |
}, | |
}), | |
createBreadcrumbsField('pages', { | |
name: 'breadcrumbs', | |
label: 'Breadcrumbs', | |
admin: { | |
initCollapsed: true, | |
position: 'sidebar', | |
}, | |
}), | |
], | |
hooks: { | |
afterChange: [revalidatePage], | |
beforeChange: [populatePublishedAt, populateHref], | |
afterDelete: [revalidateDelete], | |
}, | |
versions: { | |
drafts: { | |
autosave: { | |
interval: 100, // We set this interval for optimal live preview | |
}, | |
schedulePublish: true, | |
}, | |
maxPerDoc: 50, | |
}, | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const queryPageByHref = cache(async ({ href }: { href: string }) => { | |
const { isEnabled: draft } = await draftMode() | |
const payload = await getPayload({ config: configPromise }) | |
const result = await payload.find({ | |
collection: 'pages', | |
limit: 1, | |
draft, | |
pagination: false, | |
overrideAccess: draft, | |
where: { | |
href: { | |
equals: href, | |
}, | |
}, | |
}) | |
return result.docs?.[0] || null | |
}) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
muxVideoPlugin({ | |
enabled: true, | |
adminThumbnail: 'image', | |
initSettings: { | |
tokenId: process.env.MUX_TOKEN_ID || '', | |
tokenSecret: process.env.MUX_TOKEN_SECRET || '', | |
webhookSecret: process.env.MUX_WEBHOOK_SIGNING_SECRET || '', | |
}, | |
uploadSettings: { | |
cors_origin: process.env.NEXT_PUBLIC_SERVER_URL || 'http://localhost:3000', | |
}, | |
}), |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use server' | |
import React from 'react' | |
import type { VideoBlock as VideoBlockProps } from '@/payload-types' | |
import postHogPropertyApplicator from '@/proLaico/tracking/utilities/propertyApplicator' | |
import MuxVideo from '../../components/muxVideo' | |
import { getPayload } from 'payload' | |
import configPromise from '@/payload.config' | |
const muxVideoQuery = async ({ id }: { id: string }) => { | |
const payload = await getPayload({ config: configPromise }) | |
const result = await payload.findByID({ | |
collection: 'mux-video', | |
id: id, | |
}) | |
return result || null | |
} | |
export const VideoBlock: React.FC<VideoBlockProps> = async (props) => { | |
let video = null | |
if (typeof props.video.video === 'string') { | |
video = await muxVideoQuery({ id: props.video.video }) | |
} else if (typeof props.video.video === 'object') { | |
video = props.video.video | |
} | |
if (!video) { | |
console.warn('No video found.') | |
return <div className="sr-only">No video found.</div> | |
} | |
return ( | |
<div | |
{...(props?.postHogProperty && postHogPropertyApplicator(props?.postHogProperty))} | |
{...(props.ClassName && { className: props.ClassName })} | |
> | |
<MuxVideo video={props} muxVideo={video} /> | |
</div> | |
) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use client' | |
import { VideoBlock as VideoBlockProps, MuxVideo as MuxVideoProps } from '@/payload-types' | |
import dynamic from 'next/dynamic' | |
const MuxPlayer = dynamic(() => import('@mux/mux-player-react'), { ssr: false }) | |
function MuxVideo({ video, muxVideo }: { video: VideoBlockProps; muxVideo: MuxVideoProps }) { | |
return ( | |
<MuxPlayer | |
// Using playback id | |
playbackId={muxVideo.playbackOptions![0].playbackId!} | |
// Or use the playback URL | |
src={muxVideo.playbackOptions![0].playbackUrl!} | |
// Poster | |
poster={muxVideo.playbackOptions![0].posterUrl!} | |
/> | |
) | |
} | |
export default MuxVideo |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { ClassNameField } from '@/proLaico/styles/fields/ClassName' | |
import { deepMerge, GroupField } from 'payload' | |
type VideoField = (options?: { overrides?: Partial<GroupField> }) => GroupField | |
export const VideoField: VideoField = ({ overrides = {} } = {}) => { | |
const groupField: GroupField = { | |
name: 'video', | |
label: 'Video', | |
type: 'group', | |
fields: [ | |
{ | |
name: 'video', | |
label: 'Preview Video', | |
type: 'relationship', | |
relationTo: 'mux-video', | |
required: true, | |
}, | |
ClassNameField(), | |
], | |
} | |
return deepMerge(groupField, overrides) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment