fix(templates): website bug fixes for slug generation and form builder and adds support for strictNullChecks: true (#7877)
This commit is contained in:
@@ -18,16 +18,16 @@
|
||||
"start": "cross-env NODE_OPTIONS=--no-deprecation next start"
|
||||
},
|
||||
"dependencies": {
|
||||
"@payloadcms/db-mongodb": "3.0.0-beta.84",
|
||||
"@payloadcms/live-preview-react": "3.0.0-beta.84",
|
||||
"@payloadcms/next": "3.0.0-beta.84",
|
||||
"@payloadcms/plugin-cloud": "3.0.0-beta.84",
|
||||
"@payloadcms/plugin-form-builder": "3.0.0-beta.84",
|
||||
"@payloadcms/plugin-nested-docs": "3.0.0-beta.84",
|
||||
"@payloadcms/plugin-redirects": "3.0.0-beta.84",
|
||||
"@payloadcms/plugin-seo": "3.0.0-beta.84",
|
||||
"@payloadcms/richtext-lexical": "3.0.0-beta.84",
|
||||
"@payloadcms/ui": "3.0.0-beta.84",
|
||||
"@payloadcms/db-mongodb": "3.0.0-beta.91",
|
||||
"@payloadcms/live-preview-react": "3.0.0-beta.91",
|
||||
"@payloadcms/next": "3.0.0-beta.91",
|
||||
"@payloadcms/plugin-cloud": "3.0.0-beta.91",
|
||||
"@payloadcms/plugin-form-builder": "3.0.0-beta.91",
|
||||
"@payloadcms/plugin-nested-docs": "3.0.0-beta.91",
|
||||
"@payloadcms/plugin-redirects": "3.0.0-beta.91",
|
||||
"@payloadcms/plugin-seo": "3.0.0-beta.91",
|
||||
"@payloadcms/richtext-lexical": "3.0.0-beta.91",
|
||||
"@payloadcms/ui": "3.0.0-beta.91",
|
||||
"@radix-ui/react-checkbox": "^1.0.4",
|
||||
"@radix-ui/react-label": "^2.0.2",
|
||||
"@radix-ui/react-select": "^2.0.0",
|
||||
@@ -41,7 +41,7 @@
|
||||
"lexical": "0.17.0",
|
||||
"lucide-react": "^0.378.0",
|
||||
"next": "15.0.0-canary.104",
|
||||
"payload": "3.0.0-beta.84",
|
||||
"payload": "3.0.0-beta.91",
|
||||
"payload-admin-bar": "^1.0.6",
|
||||
"prism-react-renderer": "^2.3.1",
|
||||
"react": "19.0.0-rc-06d0b89e-20240801",
|
||||
@@ -56,6 +56,7 @@
|
||||
"@payloadcms/eslint-config": "^1.1.1",
|
||||
"@tailwindcss/typography": "^0.5.13",
|
||||
"@types/escape-html": "^1.0.2",
|
||||
"@types/jsonwebtoken": "^9.0.6",
|
||||
"@types/node": "18.11.3",
|
||||
"@types/react": "npm:types-react@19.0.0-rc.0",
|
||||
"@types/react-dom": "npm:types-react-dom@19.0.0-rc.0",
|
||||
|
||||
10230
templates/website/pnpm-lock.yaml
generated
Normal file
10230
templates/website/pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
@@ -50,16 +50,22 @@ export default async function Post({ params: { slug = '' } }) {
|
||||
/>
|
||||
</div>
|
||||
|
||||
{post.relatedPosts && post.relatedPosts.length > 0 && (
|
||||
<RelatedPosts
|
||||
className="mt-12"
|
||||
docs={post.relatedPosts.filter((post) => typeof post === 'object')}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
</article>
|
||||
)
|
||||
}
|
||||
|
||||
export async function generateMetadata({ params: { slug } }): Promise<Metadata> {
|
||||
export async function generateMetadata({
|
||||
params: { slug },
|
||||
}: {
|
||||
params: { slug: string }
|
||||
}): Promise<Metadata> {
|
||||
const post = await queryPostBySlug({ slug })
|
||||
|
||||
return generateMeta({ doc: post })
|
||||
|
||||
@@ -39,7 +39,9 @@ export default async function Page() {
|
||||
<CollectionArchive posts={posts.docs} />
|
||||
|
||||
<div className="container">
|
||||
{posts.totalPages > 1 && <Pagination page={posts.page} totalPages={posts.totalPages} />}
|
||||
{posts.totalPages > 1 && posts.page && (
|
||||
<Pagination page={posts.page} totalPages={posts.totalPages} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -40,7 +40,9 @@ export default async function Page({ params: { pageNumber = 2 } }) {
|
||||
<CollectionArchive posts={posts.docs} />
|
||||
|
||||
<div className="container">
|
||||
{posts.totalPages > 1 && <Pagination page={posts.page} totalPages={posts.totalPages} />}
|
||||
{posts.totalPages > 1 && posts.page && (
|
||||
<Pagination page={posts.page} totalPages={posts.totalPages} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
@@ -60,7 +62,7 @@ export async function generateStaticParams() {
|
||||
limit: 10,
|
||||
})
|
||||
|
||||
const pages = []
|
||||
const pages: number[] = []
|
||||
|
||||
for (let i = 1; i <= posts.totalPages; i++) {
|
||||
pages.push(i)
|
||||
|
||||
@@ -19,24 +19,23 @@ import { default as default_17 } from 'src/payload/components/BeforeDashboard'
|
||||
import { default as default_18 } from 'src/payload/components/BeforeLogin'
|
||||
|
||||
export const importMap = {
|
||||
'@payloadcms/richtext-lexical/client#RichTextCell': RichTextCell_0,
|
||||
'@payloadcms/richtext-lexical/client#RichTextField': RichTextField_1,
|
||||
'@payloadcms/richtext-lexical/generateComponentMap#getGenerateComponentMap':
|
||||
getGenerateComponentMap_2,
|
||||
'@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient': InlineToolbarFeatureClient_3,
|
||||
'@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient': FixedToolbarFeatureClient_4,
|
||||
'@payloadcms/richtext-lexical/client#HeadingFeatureClient': HeadingFeatureClient_5,
|
||||
'@payloadcms/richtext-lexical/client#UnderlineFeatureClient': UnderlineFeatureClient_6,
|
||||
'@payloadcms/richtext-lexical/client#BoldFeatureClient': BoldFeatureClient_7,
|
||||
'@payloadcms/richtext-lexical/client#ItalicFeatureClient': ItalicFeatureClient_8,
|
||||
'@payloadcms/richtext-lexical/client#LinkFeatureClient': LinkFeatureClient_9,
|
||||
'@payloadcms/plugin-seo/client#OverviewComponent': OverviewComponent_10,
|
||||
'@payloadcms/plugin-seo/client#MetaTitleComponent': MetaTitleComponent_11,
|
||||
'@payloadcms/plugin-seo/client#MetaImageComponent': MetaImageComponent_12,
|
||||
'@payloadcms/plugin-seo/client#MetaDescriptionComponent': MetaDescriptionComponent_13,
|
||||
'@payloadcms/plugin-seo/client#PreviewComponent': PreviewComponent_14,
|
||||
'@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient': HorizontalRuleFeatureClient_15,
|
||||
'@payloadcms/richtext-lexical/client#BlocksFeatureClient': BlocksFeatureClient_16,
|
||||
'/payload/components/BeforeDashboard#default': default_17,
|
||||
'/payload/components/BeforeLogin#default': default_18,
|
||||
"@payloadcms/richtext-lexical/client#RichTextCell": RichTextCell_0,
|
||||
"@payloadcms/richtext-lexical/client#RichTextField": RichTextField_1,
|
||||
"@payloadcms/richtext-lexical/generateComponentMap#getGenerateComponentMap": getGenerateComponentMap_2,
|
||||
"@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient": InlineToolbarFeatureClient_3,
|
||||
"@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient": FixedToolbarFeatureClient_4,
|
||||
"@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_5,
|
||||
"@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_6,
|
||||
"@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_7,
|
||||
"@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_8,
|
||||
"@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_9,
|
||||
"@payloadcms/plugin-seo/client#OverviewComponent": OverviewComponent_10,
|
||||
"@payloadcms/plugin-seo/client#MetaTitleComponent": MetaTitleComponent_11,
|
||||
"@payloadcms/plugin-seo/client#MetaImageComponent": MetaImageComponent_12,
|
||||
"@payloadcms/plugin-seo/client#MetaDescriptionComponent": MetaDescriptionComponent_13,
|
||||
"@payloadcms/plugin-seo/client#PreviewComponent": PreviewComponent_14,
|
||||
"@payloadcms/richtext-lexical/client#HorizontalRuleFeatureClient": HorizontalRuleFeatureClient_15,
|
||||
"@payloadcms/richtext-lexical/client#BlocksFeatureClient": BlocksFeatureClient_16,
|
||||
"/payload/components/BeforeDashboard#default": default_17,
|
||||
"/payload/components/BeforeLogin#default": default_18
|
||||
}
|
||||
|
||||
@@ -14,14 +14,16 @@ export const ArchiveBlock: React.FC<
|
||||
id?: string
|
||||
}
|
||||
> = async (props) => {
|
||||
const { id, categories, introContent, limit = 3, populateBy, selectedDocs } = props
|
||||
const { id, categories, introContent, limit: limitFromProps, populateBy, selectedDocs } = props
|
||||
|
||||
const limit = limitFromProps || 3
|
||||
|
||||
let posts: Post[] = []
|
||||
|
||||
if (populateBy === 'collection') {
|
||||
const payload = await getPayloadHMR({ config: configPromise })
|
||||
|
||||
const flattenedCategories = categories.map((category) => {
|
||||
const flattenedCategories = categories?.map((category) => {
|
||||
if (typeof category === 'object') return category.id
|
||||
else return category
|
||||
})
|
||||
@@ -43,9 +45,13 @@ export const ArchiveBlock: React.FC<
|
||||
|
||||
posts = fetchedPosts.docs
|
||||
} else {
|
||||
posts = selectedDocs.map((post) => {
|
||||
if (selectedDocs?.length) {
|
||||
const filteredSelectedPosts = selectedDocs.map((post) => {
|
||||
if (typeof post.value === 'object') return post.value
|
||||
})
|
||||
}) as Post[]
|
||||
|
||||
posts = filteredSelectedPosts
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
|
||||
@@ -16,7 +16,7 @@ export const CallToActionBlock: React.FC<
|
||||
<div className="container">
|
||||
<div className="bg-card rounded border-border border p-4 flex flex-col gap-8 md:flex-row md:justify-between md:items-center">
|
||||
<div className="max-w-[48rem] flex items-center">
|
||||
<RichText className="" content={richText} enableGutter={false} />
|
||||
{richText && <RichText className="mb-0" content={richText} enableGutter={false} />}
|
||||
</div>
|
||||
<div className="flex flex-col gap-8">
|
||||
{(links || []).map(({ link }, i) => {
|
||||
|
||||
@@ -7,7 +7,7 @@ type Props = {
|
||||
language?: string
|
||||
}
|
||||
|
||||
export const Code: React.FC<Props> = ({ code, language }) => {
|
||||
export const Code: React.FC<Props> = ({ code, language = '' }) => {
|
||||
return (
|
||||
<Highlight code={code} language={language} theme={themes.vsDark}>
|
||||
{({ getLineProps, getTokenProps, tokens }) => (
|
||||
|
||||
@@ -32,12 +32,13 @@ export const ContentBlock: React.FC<
|
||||
|
||||
return (
|
||||
<div
|
||||
className={cn(`col-span-4 lg:col-span-${colsSpanClasses[size]}`, {
|
||||
className={cn(`col-span-4 lg:col-span-${colsSpanClasses[size!]}`, {
|
||||
'md:col-span-2': size !== 'full',
|
||||
})}
|
||||
key={index}
|
||||
>
|
||||
<RichText content={richText} enableGutter={false} />
|
||||
{richText && <RichText content={richText} enableGutter={false} />}
|
||||
|
||||
{enableLink && <CMSLink {...link} />}
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import type { CheckboxField } from '@payloadcms/plugin-form-builder/types'
|
||||
import type { FieldErrorsImpl, FieldValues, UseFormRegister } from 'react-hook-form'
|
||||
|
||||
import { useFormContext } from 'react-hook-form'
|
||||
|
||||
import { Checkbox as CheckboxUi } from '@/components/ui/checkbox'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import React from 'react'
|
||||
@@ -20,13 +22,19 @@ export const Checkbox: React.FC<
|
||||
setValue: any
|
||||
}
|
||||
> = ({ name, defaultValue, errors, label, register, required: requiredFromProps, width }) => {
|
||||
const props = register(name, { required: requiredFromProps })
|
||||
const { setValue } = useFormContext()
|
||||
|
||||
return (
|
||||
<Width width={width}>
|
||||
<div className="flex items-center gap-2">
|
||||
<CheckboxUi
|
||||
defaultChecked={defaultValue}
|
||||
id={name}
|
||||
{...register(name, { required: requiredFromProps })}
|
||||
{...props}
|
||||
onCheckedChange={(checked) => {
|
||||
setValue(props.name, checked)
|
||||
}}
|
||||
/>
|
||||
<Label htmlFor={name}>{label}</Label>
|
||||
</div>
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
import type { MessageField } from '@payloadcms/plugin-form-builder/types'
|
||||
|
||||
import RichText from '@/components/RichText'
|
||||
import React from 'react'
|
||||
|
||||
import { Width } from '../Width'
|
||||
|
||||
export const Message: React.FC<MessageField> = ({ message }) => {
|
||||
export const Message: React.FC = ({ message }: { message: Record<string, any> }) => {
|
||||
return (
|
||||
<Width className="my-12" width="100">
|
||||
<RichText content={message} />
|
||||
{message && <RichText content={message} />}
|
||||
</Width>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@ export const buildInitialFormState = (fields: FormFieldBlock[]) => {
|
||||
if (field.blockType === 'checkbox') {
|
||||
return {
|
||||
...initialSchema,
|
||||
[field.name]: false,
|
||||
[field.name]: field.defaultValue,
|
||||
}
|
||||
}
|
||||
if (field.blockType === 'country') {
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { Form as FormType } from '@payloadcms/plugin-form-builder/types'
|
||||
|
||||
import { useRouter } from 'next/navigation'
|
||||
import React, { useCallback, useState } from 'react'
|
||||
import { useForm } from 'react-hook-form'
|
||||
import { useForm, FormProvider } from 'react-hook-form'
|
||||
import RichText from 'src/app/components/RichText'
|
||||
import { Button } from 'src/app/components/ui/button'
|
||||
|
||||
@@ -48,10 +48,8 @@ export const FormBlock: React.FC<
|
||||
const {
|
||||
control,
|
||||
formState: { errors },
|
||||
getValues,
|
||||
handleSubmit,
|
||||
register,
|
||||
setValue,
|
||||
} = formMethods
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
@@ -128,6 +126,7 @@ export const FormBlock: React.FC<
|
||||
|
||||
return (
|
||||
<div className="container max-w-[48rem] pb-20">
|
||||
<FormProvider {...formMethods}>
|
||||
{enableIntro && introContent && !hasSubmitted && (
|
||||
<RichText className="mb-8" content={introContent} enableGutter={false} />
|
||||
)}
|
||||
@@ -166,6 +165,7 @@ export const FormBlock: React.FC<
|
||||
</Button>
|
||||
</form>
|
||||
)}
|
||||
</FormProvider>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ interface HeaderClientProps {
|
||||
|
||||
export const HeaderClient: React.FC<HeaderClientProps> = ({ header }) => {
|
||||
/* Storing the value in a useState to avoid hydration errors */
|
||||
const [theme, setTheme] = useState(null)
|
||||
const [theme, setTheme] = useState<string | null>(null)
|
||||
const { headerTheme, setHeaderTheme } = useHeaderTheme()
|
||||
const pathname = usePathname()
|
||||
|
||||
@@ -25,7 +25,7 @@ export const HeaderClient: React.FC<HeaderClientProps> = ({ header }) => {
|
||||
}, [pathname])
|
||||
|
||||
useEffect(() => {
|
||||
if (headerTheme !== theme) setTheme(headerTheme)
|
||||
if (headerTheme && headerTheme !== theme) setTheme(headerTheme)
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
}, [headerTheme])
|
||||
|
||||
|
||||
@@ -9,15 +9,15 @@ type CMSLinkType = {
|
||||
appearance?: 'inline' | ButtonProps['variant']
|
||||
children?: React.ReactNode
|
||||
className?: string
|
||||
label?: string
|
||||
newTab?: boolean
|
||||
label?: string | null
|
||||
newTab?: boolean | null
|
||||
reference?: {
|
||||
relationTo: 'pages' | 'posts'
|
||||
value: Page | Post | string | number
|
||||
}
|
||||
size?: ButtonProps['size']
|
||||
type?: 'custom' | 'reference'
|
||||
url?: string
|
||||
} | null
|
||||
size?: ButtonProps['size'] | null
|
||||
type?: 'custom' | 'reference' | null
|
||||
url?: string | null
|
||||
}
|
||||
|
||||
export const CMSLink: React.FC<CMSLinkType> = (props) => {
|
||||
@@ -48,7 +48,7 @@ export const CMSLink: React.FC<CMSLinkType> = (props) => {
|
||||
/* Ensure we don't break any styles set by richText */
|
||||
if (appearance === 'inline') {
|
||||
return (
|
||||
<Link className={cn(className)} href={href || url} {...newTabProps}>
|
||||
<Link className={cn(className)} href={href || url || ''} {...newTabProps}>
|
||||
{label && label}
|
||||
{children && children}
|
||||
</Link>
|
||||
@@ -57,7 +57,7 @@ export const CMSLink: React.FC<CMSLinkType> = (props) => {
|
||||
|
||||
return (
|
||||
<Button asChild className={className} size={size} variant={appearance}>
|
||||
<Link className={cn(className)} href={href || url} {...newTabProps}>
|
||||
<Link className={cn(className)} href={href || url || ''} {...newTabProps}>
|
||||
{label && label}
|
||||
{children && children}
|
||||
</Link>
|
||||
|
||||
@@ -6,6 +6,6 @@ import React from 'react'
|
||||
export const LivePreviewListener: React.FC = () => {
|
||||
const router = useRouter()
|
||||
return (
|
||||
<PayloadLivePreview refresh={router.refresh} serverURL={process.env.NEXT_PUBLIC_SERVER_URL} />
|
||||
<PayloadLivePreview refresh={router.refresh} serverURL={process.env.NEXT_PUBLIC_SERVER_URL!} />
|
||||
)
|
||||
}
|
||||
|
||||
@@ -41,8 +41,8 @@ export const ImageMedia: React.FC<MediaProps> = (props) => {
|
||||
width: fullWidth,
|
||||
} = resource
|
||||
|
||||
width = fullWidth
|
||||
height = fullHeight
|
||||
width = fullWidth!
|
||||
height = fullHeight!
|
||||
alt = altFromResource
|
||||
|
||||
src = `${process.env.NEXT_PUBLIC_SERVER_URL}${url}`
|
||||
|
||||
@@ -19,7 +19,7 @@ export const HighImpactHero: React.FC<Page['hero']> = ({ links, media, richText
|
||||
<div className="relative -mt-[10.4rem] flex items-end text-white" data-theme="dark">
|
||||
<div className="container mb-8 z-10 relative">
|
||||
<div className="max-w-[34rem]">
|
||||
<RichText className="mb-6" content={richText} enableGutter={false} />
|
||||
{richText && <RichText className="mb-6" content={richText} enableGutter={false} />}
|
||||
{Array.isArray(links) && links.length > 0 && (
|
||||
<ul className="flex gap-4">
|
||||
{links.map(({ link }, i) => {
|
||||
@@ -34,7 +34,7 @@ export const HighImpactHero: React.FC<Page['hero']> = ({ links, media, richText
|
||||
</div>
|
||||
</div>
|
||||
<div className="min-h-[80vh] select-none">
|
||||
{typeof media === 'object' && (
|
||||
{media && typeof media === 'object' && (
|
||||
<React.Fragment>
|
||||
<Media fill imgClassName="-z-10 object-cover" priority resource={media} />
|
||||
<div className="absolute pointer-events-none left-0 bottom-0 w-full h-1/2 bg-gradient-to-t from-black to-transparent" />
|
||||
|
||||
@@ -18,7 +18,7 @@ export const LowImpactHero: React.FC<LowImpactHeroType> = ({ children, richText
|
||||
return (
|
||||
<div className="container mt-16">
|
||||
<div className="max-w-[48rem]">
|
||||
{children || <RichText content={richText} enableGutter={false} />}
|
||||
{children || (richText && <RichText content={richText} enableGutter={false} />)}
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -10,7 +10,8 @@ export const MediumImpactHero: React.FC<Page['hero']> = ({ links, media, richTex
|
||||
return (
|
||||
<div className="">
|
||||
<div className="container mb-8">
|
||||
<RichText className="mb-6" content={richText} enableGutter={false} />
|
||||
{richText && <RichText className="mb-6" content={richText} enableGutter={false} />}
|
||||
|
||||
{Array.isArray(links) && links.length > 0 && (
|
||||
<ul className="flex gap-4">
|
||||
{links.map(({ link }, i) => {
|
||||
@@ -24,7 +25,7 @@ export const MediumImpactHero: React.FC<Page['hero']> = ({ links, media, richTex
|
||||
)}
|
||||
</div>
|
||||
<div className="container ">
|
||||
{typeof media === 'object' && (
|
||||
{media && typeof media === 'object' && (
|
||||
<div>
|
||||
<Media
|
||||
className="-mx-4 md:-mx-8 2xl:-mx-16"
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import jwt from 'jsonwebtoken'
|
||||
import { draftMode } from 'next/headers'
|
||||
import { redirect } from 'next/navigation'
|
||||
import { getPayloadHMR } from '@payloadcms/next/utilities'
|
||||
import configPromise from '@payload-config'
|
||||
|
||||
const payloadToken = 'payload-token'
|
||||
|
||||
@@ -13,6 +15,7 @@ export async function GET(
|
||||
}
|
||||
},
|
||||
): Promise<Response> {
|
||||
const payload = await getPayloadHMR({ config: configPromise })
|
||||
const token = req.cookies.get(payloadToken)?.value
|
||||
const { searchParams } = new URL(req.url)
|
||||
const path = searchParams.get('path')
|
||||
@@ -25,8 +28,9 @@ export async function GET(
|
||||
new Response('You are not allowed to preview this page', { status: 403 })
|
||||
}
|
||||
|
||||
const user = jwt.decode(token, process.env.PAYLOAD_SECRET)
|
||||
const user = jwt.verify(token, payload.config.secret)
|
||||
|
||||
// You can add additional checks here to see if the user is allowed to preview this page
|
||||
if (!user) {
|
||||
draftMode().disable()
|
||||
return new Response('You are not allowed to preview this page', { status: 403 })
|
||||
|
||||
@@ -19,7 +19,7 @@ const initialContext: ContextType = {
|
||||
const HeaderThemeContext = createContext(initialContext)
|
||||
|
||||
export const HeaderThemeProvider = ({ children }: { children: React.ReactNode }) => {
|
||||
const [headerTheme, setThemeState] = useState<Theme | undefined>(
|
||||
const [headerTheme, setThemeState] = useState<Theme | undefined | null>(
|
||||
canUseDOM ? (document.documentElement.getAttribute('data-theme') as Theme) : undefined,
|
||||
)
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ export const generateMeta = async (args: { doc: Page | Post }): Promise<Metadata
|
||||
return {
|
||||
description: doc?.meta?.description,
|
||||
openGraph: mergeOpenGraph({
|
||||
description: doc?.meta?.description,
|
||||
description: doc?.meta?.description || '',
|
||||
images: ogImage
|
||||
? [
|
||||
{
|
||||
|
||||
@@ -34,8 +34,9 @@ export const getMeUser = async (args?: {
|
||||
redirect(nullUserRedirect)
|
||||
}
|
||||
|
||||
// Token will exist here because if it doesn't the user will be redirected
|
||||
return {
|
||||
token,
|
||||
token: token!,
|
||||
user,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,10 +6,10 @@ import { useCallback, useEffect, useRef } from 'react'
|
||||
|
||||
type UseClickableCardType<T extends HTMLElement> = {
|
||||
card: {
|
||||
ref: RefObject<T>
|
||||
ref: RefObject<T | null>
|
||||
}
|
||||
link: {
|
||||
ref: RefObject<HTMLAnchorElement>
|
||||
ref: RefObject<HTMLAnchorElement | null>
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ export interface Page {
|
||||
id?: string | null;
|
||||
}[]
|
||||
| null;
|
||||
media?: string | Media | null;
|
||||
media?: (string | null) | Media;
|
||||
};
|
||||
layout: (
|
||||
| {
|
||||
@@ -231,7 +231,7 @@ export interface Page {
|
||||
)[];
|
||||
meta?: {
|
||||
title?: string | null;
|
||||
image?: string | Media | null;
|
||||
image?: (string | null) | Media;
|
||||
description?: string | null;
|
||||
};
|
||||
publishedAt?: string | null;
|
||||
@@ -319,7 +319,7 @@ export interface Post {
|
||||
categories?: (string | Category)[] | null;
|
||||
meta?: {
|
||||
title?: string | null;
|
||||
image?: string | Media | null;
|
||||
image?: (string | null) | Media;
|
||||
description?: string | null;
|
||||
};
|
||||
publishedAt?: string | null;
|
||||
|
||||
@@ -41,8 +41,8 @@ const generateTitle: GenerateTitle<Post | Page> = ({ doc }) => {
|
||||
|
||||
const generateURL: GenerateURL<Post | Page> = ({ doc }) => {
|
||||
return doc?.slug
|
||||
? `${process.env.NEXT_PUBLIC_SERVER_URL}/${doc.slug}`
|
||||
: process.env.NEXT_PUBLIC_SERVER_URL
|
||||
? `${process.env.NEXT_PUBLIC_SERVER_URL!}/${doc.slug}`
|
||||
: process.env.NEXT_PUBLIC_SERVER_URL!
|
||||
}
|
||||
|
||||
export default buildConfig({
|
||||
@@ -116,7 +116,7 @@ export default buildConfig({
|
||||
}),
|
||||
// database-adapter-config-start
|
||||
db: mongooseAdapter({
|
||||
url: process.env.DATABASE_URI,
|
||||
url: process.env.DATABASE_URI!,
|
||||
}),
|
||||
// database-adapter-config-end
|
||||
collections: [Pages, Posts, Media, Categories, Users],
|
||||
@@ -190,7 +190,7 @@ export default buildConfig({
|
||||
}),
|
||||
payloadCloudPlugin(), // storage-adapter-placeholder
|
||||
],
|
||||
secret: process.env.PAYLOAD_SECRET,
|
||||
secret: process.env.PAYLOAD_SECRET!,
|
||||
sharp,
|
||||
typescript: {
|
||||
outputFile: path.resolve(dirname, 'payload-types.ts'),
|
||||
|
||||
@@ -5,7 +5,5 @@ import type { User } from '../../payload-types'
|
||||
type isAuthenticated = (args: AccessArgs<User>) => boolean
|
||||
|
||||
export const authenticated: isAuthenticated = ({ req: { user } }) => {
|
||||
if (user) {
|
||||
return true
|
||||
}
|
||||
return Boolean(user)
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { CollectionAfterReadHook } from 'payload'
|
||||
import { User } from 'src/payload-types'
|
||||
|
||||
// The `user` collection has access control locked so that users are not publicly accessible
|
||||
// This means that we need to populate the authors manually here to protect user privacy
|
||||
@@ -6,7 +7,7 @@ import type { CollectionAfterReadHook } from 'payload'
|
||||
// So we use an alternative `populatedAuthors` field to populate the user data, hidden from the admin UI
|
||||
export const populateAuthors: CollectionAfterReadHook = async ({ doc, req, req: { payload } }) => {
|
||||
if (doc?.authors) {
|
||||
const authorDocs = []
|
||||
const authorDocs: User[] = []
|
||||
|
||||
for (const author of doc.authors) {
|
||||
const authorDoc = await payload.findByID({
|
||||
|
||||
@@ -13,8 +13,8 @@ const formatSlug =
|
||||
return format(value)
|
||||
}
|
||||
|
||||
if (operation === 'create') {
|
||||
const fallbackData = data?.[fallback] || originalDoc?.[fallback]
|
||||
if (operation === 'create' || !data?.slug) {
|
||||
const fallbackData = data?.[fallback] || data?.[fallback]
|
||||
|
||||
if (fallbackData && typeof fallbackData === 'string') {
|
||||
return format(fallbackData)
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"allowJs": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": false,
|
||||
"strictNullChecks": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"noEmit": true,
|
||||
"incremental": true,
|
||||
|
||||
Reference in New Issue
Block a user