Add block editing
Some checks failed
continuous-integration/drone/push Build is failing

This commit is contained in:
tobias
2024-06-23 22:23:06 +02:00
parent f9ee909e01
commit 60f7a4e4f2
32 changed files with 1061 additions and 256 deletions

6
src/utils/cn.ts Executable file
View File

@ -0,0 +1,6 @@
import { clsx, type ClassValue } from 'clsx'
import { twMerge } from 'tailwind-merge'
export default function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}

View File

@ -0,0 +1,7 @@
export default function generateBreadcrumbsUrl(docs: any, lastDoc: any) {
let prefix = ''
// You might want different prefixes for different collections.
switch (lastDoc._collection) {
}
return docs.reduce((url: any, doc: any) => `${url}/${doc.slug ?? ''}`, prefix)
}

37
src/utils/generateMeta.ts Normal file
View File

@ -0,0 +1,37 @@
import type { Metadata } from 'next'
import _get from 'lodash/get'
import deepmerge from 'deepmerge'
import { getDocument } from '@/utils/getDocument'
import normalizePath from './normalizePath'
const defaultTitle = 'Payload SaaS Starter'
const defaultDescription = 'An open-source website built with Payload and Next.js.'
const siteName = 'Payload SaaS Starter'
const defaultOpenGraph: Metadata['openGraph'] = {
type: 'website',
description: defaultDescription,
siteName,
title: defaultTitle,
}
export const generateMeta = async (path: string | string[]): Promise<Metadata> => {
const doc = await getDocument({
collection: 'pages',
path,
depth: 1,
})
const metaTitle = _get(doc, 'meta.title', null)
const title = metaTitle ?? (_get(doc, 'title', defaultTitle) as string)
const description = _get(doc, 'meta.description', defaultDescription)
const ogImage = _get(doc, 'meta.image.url', `/api/og${normalizePath(path, true)}image.jpg`)
return {
description,
openGraph: deepmerge(defaultOpenGraph, {
description,
images: ogImage ? [{ url: ogImage }] : undefined,
}),
title: { absolute: title },
}
}

View File

@ -0,0 +1,13 @@
export default function generateRandomString(
length: number,
characters: string = 'abcdefghijklmnopqrstuvwxyz0123456789',
): string {
let result = ''
const charactersLength = characters.length
for (let i = 0; i < length; i++) {
result += characters.charAt(Math.floor(Math.random() * charactersLength))
}
return result
}

80
src/utils/getDocument.ts Normal file
View File

@ -0,0 +1,80 @@
import type { Config } from 'types/payload-types'
import { unstable_cache } from 'next/cache'
import normalizePath from '@/utils/normalizePath'
import { getCurrentUser, getPayload } from '@/lib/payload'
import { draftMode } from 'next/headers'
type Collection = keyof Config['collections'] | string
type Path = string | string[]
type CacheOption = 'noDraft' | true | false
export const generateDocumentCacheKey = (collection: Collection, path?: Path): string => {
return `${collection}_path_${normalizePath(path, false)}`
}
export const generateDocumentCacheParams = (collection: Collection, path?: Path): string[] => {
return [collection, normalizePath(path)]
}
export const conditionalCache = async <T>(
fetchFunction: () => Promise<T>,
cacheKey: string,
cache: boolean | undefined,
revalidate: false | number | undefined,
): Promise<T> => {
if (!cache) {
return fetchFunction()
}
return unstable_cache(fetchFunction, [cacheKey], { revalidate, tags: [cacheKey] })()
}
interface GetDocumentParams<K extends keyof Config['collections']> {
collection: K
path?: Path
depth?: number
cache?: CacheOption
revalidate?: false | number | undefined
}
export const getDocument = async <K extends keyof Config['collections']>({
collection,
path,
depth = 0,
cache = 'noDraft',
revalidate = false,
}: GetDocumentParams<K>): Promise<Config['collections'][K] | null> => {
const { isEnabled: draft } = draftMode()
const payload = await getPayload()
const user = draft ? await getCurrentUser() : null
const normalizedPath = normalizePath(path, false)
const where = { path: { equals: normalizedPath } }
const cacheKey = generateDocumentCacheKey(collection, path)
const shouldCache = draft ? false : !!cache
return conditionalCache(
async () => {
return await payload
.find({
collection,
draft,
depth,
limit: 1,
overrideAccess: false,
user,
where,
})
.catch((error) => {
console.error('Error fetching document:', error)
return null
})
.then((result) => {
if (!result || !result.docs || result.docs.length === 0) return null
return result.docs.at(0) as Config['collections'][K] | null
})
},
cacheKey,
shouldCache,
revalidate,
)
}

View File

@ -0,0 +1,9 @@
const normalizePath = (path?: string | string[], keepTrailingSlash: boolean = false): string => {
if (!path) return '/'
if (Array.isArray(path)) path = path.join('/')
path = `/${path}/`.replace(/\/+/g, '/')
path = path !== '/' && !keepTrailingSlash ? path.replace(/\/$/, '') : path
return path
}
export default normalizePath