From cd2390e6fc6812ad175a3cfac9e46e145e2b60ea Mon Sep 17 00:00:00 2001 From: jl Date: Tue, 21 Jul 2026 22:01:51 +0800 Subject: [PATCH 1/3] chore: udpate dockerfile to skip prepare scripts --- docker/local/Dockerfile | 2 +- src/app/(payload)/admin/importMap.js | 50 ++++++----------- .../durianpy-website/HomepageConfig.ts | 55 +++++++++++++++++++ src/payload-types.ts | 38 ++++++++++++- src/payload.config.ts | 2 + 5 files changed, 111 insertions(+), 36 deletions(-) create mode 100644 src/globals/durianpy-website/HomepageConfig.ts diff --git a/docker/local/Dockerfile b/docker/local/Dockerfile index d34aa3b..9415e89 100644 --- a/docker/local/Dockerfile +++ b/docker/local/Dockerfile @@ -10,7 +10,7 @@ USER node COPY --chown=node:node package.json package-lock.json ./ -RUN npm install --legacy-peer-deps +RUN npm install --legacy-peer-deps --ignore-scripts COPY --chown=node:node . . diff --git a/src/app/(payload)/admin/importMap.js b/src/app/(payload)/admin/importMap.js index 2ed42a6..f30b09e 100644 --- a/src/app/(payload)/admin/importMap.js +++ b/src/app/(payload)/admin/importMap.js @@ -15,39 +15,25 @@ import { HeadingFeatureClient as HeadingFeatureClient_e70f5e05f09f93e00b997edb1e import { FolderTypeField as FolderTypeField_2b8867833a34864a02ddf429b0728a40 } from '@payloadcms/next/client' import { default as default_1a7510af427896d367a49dbf838d2de6 } from '@/components/BeforeDashboard' import { default as default_8a7ab0eb7ab5c511aba12e68480bfe5e } from '@/components/BeforeLogin' -import { S3ClientUploadHandler as S3ClientUploadHandler_f97aa6c64367fa259c5bc0567239ef24 } from '@payloadcms/storage-s3/client' import { CollectionCards as CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } from '@payloadcms/next/rsc' export const importMap = { - '@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell': - RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e, - '@payloadcms/richtext-lexical/rsc#RscEntryLexicalField': - RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e, - '@payloadcms/richtext-lexical/rsc#LexicalDiffComponent': - LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e, - '@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient': - InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - '@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient': - FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - '@payloadcms/richtext-lexical/client#ParagraphFeatureClient': - ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - '@payloadcms/richtext-lexical/client#UnderlineFeatureClient': - UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - '@payloadcms/richtext-lexical/client#BoldFeatureClient': - BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - '@payloadcms/richtext-lexical/client#ItalicFeatureClient': - ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - '@payloadcms/richtext-lexical/client#LinkFeatureClient': - LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - '@payloadcms/next/rsc#FolderTableCell': FolderTableCell_f9c02e79a4aed9a3924487c0cd4cafb1, - '@payloadcms/next/rsc#FolderField': FolderField_f9c02e79a4aed9a3924487c0cd4cafb1, - '@payloadcms/next/client#SlugField': SlugField_2b8867833a34864a02ddf429b0728a40, - '@payloadcms/richtext-lexical/client#HeadingFeatureClient': - HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, - '@payloadcms/next/client#FolderTypeField': FolderTypeField_2b8867833a34864a02ddf429b0728a40, - '@/components/BeforeDashboard#default': default_1a7510af427896d367a49dbf838d2de6, - '@/components/BeforeLogin#default': default_8a7ab0eb7ab5c511aba12e68480bfe5e, - '@payloadcms/storage-s3/client#S3ClientUploadHandler': - S3ClientUploadHandler_f97aa6c64367fa259c5bc0567239ef24, - '@payloadcms/next/rsc#CollectionCards': CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1, + "@payloadcms/richtext-lexical/rsc#RscEntryLexicalCell": RscEntryLexicalCell_44fe37237e0ebf4470c9990d8cb7b07e, + "@payloadcms/richtext-lexical/rsc#RscEntryLexicalField": RscEntryLexicalField_44fe37237e0ebf4470c9990d8cb7b07e, + "@payloadcms/richtext-lexical/rsc#LexicalDiffComponent": LexicalDiffComponent_44fe37237e0ebf4470c9990d8cb7b07e, + "@payloadcms/richtext-lexical/client#InlineToolbarFeatureClient": InlineToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#FixedToolbarFeatureClient": FixedToolbarFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#ParagraphFeatureClient": ParagraphFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#UnderlineFeatureClient": UnderlineFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#BoldFeatureClient": BoldFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#ItalicFeatureClient": ItalicFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/richtext-lexical/client#LinkFeatureClient": LinkFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/next/rsc#FolderTableCell": FolderTableCell_f9c02e79a4aed9a3924487c0cd4cafb1, + "@payloadcms/next/rsc#FolderField": FolderField_f9c02e79a4aed9a3924487c0cd4cafb1, + "@payloadcms/next/client#SlugField": SlugField_2b8867833a34864a02ddf429b0728a40, + "@payloadcms/richtext-lexical/client#HeadingFeatureClient": HeadingFeatureClient_e70f5e05f09f93e00b997edb1ef0c864, + "@payloadcms/next/client#FolderTypeField": FolderTypeField_2b8867833a34864a02ddf429b0728a40, + "@/components/BeforeDashboard#default": default_1a7510af427896d367a49dbf838d2de6, + "@/components/BeforeLogin#default": default_8a7ab0eb7ab5c511aba12e68480bfe5e, + "@payloadcms/next/rsc#CollectionCards": CollectionCards_f9c02e79a4aed9a3924487c0cd4cafb1 } diff --git a/src/globals/durianpy-website/HomepageConfig.ts b/src/globals/durianpy-website/HomepageConfig.ts new file mode 100644 index 0000000..0d2a111 --- /dev/null +++ b/src/globals/durianpy-website/HomepageConfig.ts @@ -0,0 +1,55 @@ +import { checkCollectionAccess } from '@/access/checkCollectionAccess' +import { getCollectionGroupLabel } from '@/constants/collections' +import { GlobalConfig } from 'payload' + +// We will let VS Code import these automatically! +// 1. Click on getCollectionGroupLabel below, press Ctrl + . (or Cmd + .), and click "Update import" or "Add import" +// 2. Click on checkCollectionAccess below, press Ctrl + . (or Cmd + .), and click "Add import" + +export const HomepageConfig: GlobalConfig = { + slug: 'homepage-config', + admin: { + group: getCollectionGroupLabel('durianpy-website'), + }, + access: { + read: () => true, + // We explicitly type args as 'any' to satisfy TS, and removed the invalid 'admin' access rule! + update: (args: any) => checkCollectionAccess(args, 'homepage-config' as any, 'update'), + }, + versions: { + // Globals use 'max' instead of 'maxPerDoc' + max: 50, + drafts: { + autosave: { + showSaveDraftButton: true, + }, + schedulePublish: true, + }, + }, + fields: [ + { + name: 'heroImageDesktop', + type: 'upload', + relationTo: 'media', + required: true, + label: 'Hero Image (Desktop)', + }, + { + name: 'heroImageMobile', + type: 'upload', + relationTo: 'media', + required: true, + label: 'Hero Image (Mobile)', + }, + { + name: 'heroTitle', + type: 'text', + label: 'Hero Title', + }, + { + name: 'heroSubtitle', + type: 'text', + label: 'Hero Subtitle', + }, + ], +} diff --git a/src/payload-types.ts b/src/payload-types.ts index 0a66d77..3a67024 100644 --- a/src/payload-types.ts +++ b/src/payload-types.ts @@ -103,8 +103,12 @@ export interface Config { defaultIDType: string; }; fallbackLocale: null; - globals: {}; - globalsSelect: {}; + globals: { + 'homepage-config': HomepageConfig; + }; + globalsSelect: { + 'homepage-config': HomepageConfigSelect | HomepageConfigSelect; + }; locale: null; widgets: { collections: CollectionsWidget; @@ -1095,6 +1099,34 @@ export interface PayloadMigrationsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "homepage-config". + */ +export interface HomepageConfig { + id: string; + heroImageDesktop: string | Media; + heroImageMobile: string | Media; + heroTitle?: string | null; + heroSubtitle?: string | null; + _status?: ('draft' | 'published') | null; + updatedAt?: string | null; + createdAt?: string | null; +} +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "homepage-config_select". + */ +export interface HomepageConfigSelect { + heroImageDesktop?: T; + heroImageMobile?: T; + heroTitle?: T; + heroSubtitle?: T; + _status?: T; + updatedAt?: T; + createdAt?: T; + globalType?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "collections_widget". @@ -1117,7 +1149,7 @@ export interface TaskSchedulePublish { relationTo: 'sample'; value: string | Sample; } | null; - global?: string | null; + global?: 'homepage-config' | null; user?: (string | null) | User; }; output?: unknown; diff --git a/src/payload.config.ts b/src/payload.config.ts index 261a467..05820b3 100644 --- a/src/payload.config.ts +++ b/src/payload.config.ts @@ -14,6 +14,7 @@ import { plugins } from './plugins' import { defaultLexical } from '@/fields/defaultLexical' import { getServerSideURL, getServerSideOrigin } from './utilities/getURL' import { Sample } from './collections/durianpy-website/sample-website-collection.index' +import { HomepageConfig } from './globals/durianpy-website/HomepageConfig' const filename = fileURLToPath(import.meta.url) const dirname = path.dirname(filename) @@ -94,6 +95,7 @@ export default buildConfig({ }), }), collections: [Media, Categories, Users, Sample], + globals: [HomepageConfig], cors: [getServerSideOrigin()].filter(Boolean).map((url) => { try { const { origin } = new URL(url!) From f571fe169cb6da85ea556fe92c07e6e4f9dbe69f Mon Sep 17 00:00:00 2001 From: jpornillos Date: Fri, 31 Jul 2026 11:23:30 +0000 Subject: [PATCH 2/3] fix(cms): address PR review comments and enable drafts for HomepageConfig --- src/constants/globals.ts | 12 ++++++++ .../durianpy-website/HomepageConfig.ts | 30 ++++++++----------- 2 files changed, 25 insertions(+), 17 deletions(-) create mode 100644 src/constants/globals.ts diff --git a/src/constants/globals.ts b/src/constants/globals.ts new file mode 100644 index 0000000..ea52fae --- /dev/null +++ b/src/constants/globals.ts @@ -0,0 +1,12 @@ +export const GLOBALS = { + DURIANPY_WEBSITE_HOMEPAGE_CONFIG: 'durianpy-website-homepage-config', +} as const + +export type GlobalSlug = (typeof GLOBALS)[keyof typeof GLOBALS] + +export const GLOBAL_LABELS: Record = { + [GLOBALS.DURIANPY_WEBSITE_HOMEPAGE_CONFIG]: { + singular: 'Homepage Config', + plural: 'Homepage Configs', + }, +} diff --git a/src/globals/durianpy-website/HomepageConfig.ts b/src/globals/durianpy-website/HomepageConfig.ts index 0d2a111..6381fe7 100644 --- a/src/globals/durianpy-website/HomepageConfig.ts +++ b/src/globals/durianpy-website/HomepageConfig.ts @@ -1,31 +1,27 @@ +import { GlobalConfig, AccessArgs } from 'payload' import { checkCollectionAccess } from '@/access/checkCollectionAccess' import { getCollectionGroupLabel } from '@/constants/collections' -import { GlobalConfig } from 'payload' +import { GLOBALS, GLOBAL_LABELS } from '@/constants/globals' -// We will let VS Code import these automatically! -// 1. Click on getCollectionGroupLabel below, press Ctrl + . (or Cmd + .), and click "Update import" or "Add import" -// 2. Click on checkCollectionAccess below, press Ctrl + . (or Cmd + .), and click "Add import" +type AccessType = 'create' | 'read' | 'update' | 'delete' + +const checkHomepageConfigAccess = (accessType?: AccessType) => (access: AccessArgs) => + checkCollectionAccess(access, GLOBALS.DURIANPY_WEBSITE_HOMEPAGE_CONFIG as any, accessType) export const HomepageConfig: GlobalConfig = { - slug: 'homepage-config', + slug: GLOBALS.DURIANPY_WEBSITE_HOMEPAGE_CONFIG, + label: GLOBAL_LABELS[GLOBALS.DURIANPY_WEBSITE_HOMEPAGE_CONFIG].singular, admin: { group: getCollectionGroupLabel('durianpy-website'), }, + versions: { + drafts: true, // <-- This instantly enables staging and publishing! + }, access: { read: () => true, - // We explicitly type args as 'any' to satisfy TS, and removed the invalid 'admin' access rule! - update: (args: any) => checkCollectionAccess(args, 'homepage-config' as any, 'update'), - }, - versions: { - // Globals use 'max' instead of 'maxPerDoc' - max: 50, - drafts: { - autosave: { - showSaveDraftButton: true, - }, - schedulePublish: true, - }, + update: checkHomepageConfigAccess('update'), }, + fields: [ { name: 'heroImageDesktop', From 427b7ff22a5e71235c8d5ac0d11f0a7cca68be9c Mon Sep 17 00:00:00 2001 From: jpornillos Date: Fri, 31 Jul 2026 11:40:43 +0000 Subject: [PATCH 3/3] chore: remove inline comment --- src/globals/durianpy-website/HomepageConfig.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/globals/durianpy-website/HomepageConfig.ts b/src/globals/durianpy-website/HomepageConfig.ts index 6381fe7..75cb219 100644 --- a/src/globals/durianpy-website/HomepageConfig.ts +++ b/src/globals/durianpy-website/HomepageConfig.ts @@ -15,7 +15,7 @@ export const HomepageConfig: GlobalConfig = { group: getCollectionGroupLabel('durianpy-website'), }, versions: { - drafts: true, // <-- This instantly enables staging and publishing! + drafts: true, }, access: { read: () => true,