@payloadcms/ui 4.0.0-canary.5 → 4.0.0-canary.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +1 -1
- package/dist/css/forms.css +6 -3
- package/dist/css/theme.css +2 -1
- package/dist/elements/AddNewRelation/index.css +1 -1
- package/dist/elements/DatePicker/index.css +1 -1
- package/dist/elements/DatePicker/index.js +1 -1
- package/dist/elements/DatePicker/index.js.map +1 -1
- package/dist/elements/DocumentFields/index.css +1 -0
- package/dist/elements/EditUpload/index.d.ts.map +1 -1
- package/dist/elements/EditUpload/index.js +4 -0
- package/dist/elements/EditUpload/index.js.map +1 -1
- package/dist/elements/Hierarchy/ColumnBrowser/Column/index.css +3 -1
- package/dist/elements/Hierarchy/ColumnBrowser/ColumnItem/index.css +1 -0
- package/dist/elements/Hierarchy/ColumnBrowser/types.d.ts +1 -1
- package/dist/elements/Hierarchy/ColumnBrowser/types.d.ts.map +1 -1
- package/dist/elements/Hierarchy/ColumnBrowser/types.js.map +1 -1
- package/dist/elements/Hierarchy/DocHeaderButton/index.js +12 -12
- package/dist/elements/Hierarchy/DocHeaderButton/index.js.map +1 -1
- package/dist/elements/Hierarchy/Field/index.client.js +14 -14
- package/dist/elements/Hierarchy/Field/index.client.js.map +1 -1
- package/dist/elements/Hierarchy/Modal/fetchAncestorPath.d.ts.map +1 -0
- package/dist/elements/Hierarchy/Modal/fetchAncestorPath.js.map +1 -0
- package/dist/elements/Hierarchy/Modal/index.css +88 -0
- package/dist/elements/Hierarchy/Modal/index.d.ts +20 -0
- package/dist/elements/Hierarchy/Modal/index.d.ts.map +1 -0
- package/dist/elements/Hierarchy/{Drawer → Modal}/index.js +105 -81
- package/dist/elements/Hierarchy/Modal/index.js.map +1 -0
- package/dist/elements/Hierarchy/{Drawer → Modal}/types.d.ts +22 -18
- package/dist/elements/Hierarchy/Modal/types.d.ts.map +1 -0
- package/dist/elements/Hierarchy/Modal/types.js.map +1 -0
- package/dist/elements/Hierarchy/Modal/useHierarchyModal.d.ts +30 -0
- package/dist/elements/Hierarchy/Modal/useHierarchyModal.d.ts.map +1 -0
- package/dist/elements/Hierarchy/{Drawer/useHierarchyDrawer.js → Modal/useHierarchyModal.js} +51 -50
- package/dist/elements/Hierarchy/Modal/useHierarchyModal.js.map +1 -0
- package/dist/elements/Hierarchy/MoveMany/index.d.ts +2 -2
- package/dist/elements/Hierarchy/MoveMany/index.d.ts.map +1 -1
- package/dist/elements/Hierarchy/MoveMany/index.js +9 -9
- package/dist/elements/Hierarchy/MoveMany/index.js.map +1 -1
- package/dist/elements/LivePreview/Toolbar/SizeInput/index.d.ts.map +1 -1
- package/dist/elements/LivePreview/Toolbar/SizeInput/index.js +1 -0
- package/dist/elements/LivePreview/Toolbar/SizeInput/index.js.map +1 -1
- package/dist/elements/LivePreview/Window/index.css +6 -0
- package/dist/elements/ReactSelect/index.css +2 -2
- package/dist/elements/ReactSelect/index.js +1 -1
- package/dist/elements/ReactSelect/index.js.map +1 -1
- package/dist/elements/RelationshipTable/index.css +1 -2
- package/dist/elements/Table/DefaultCell/fields/Hierarchy/index.js +24 -24
- package/dist/elements/Table/DefaultCell/fields/Hierarchy/index.js.map +1 -1
- package/dist/elements/Table/index.css +7 -2
- package/dist/elements/TimezonePicker/index.css +1 -1
- package/dist/exports/client/index.d.ts +3 -2
- package/dist/exports/client/index.d.ts.map +1 -1
- package/dist/exports/client/index.js +26 -26
- package/dist/exports/client/index.js.map +4 -4
- package/dist/exports/rsc/index.d.ts +2 -0
- package/dist/exports/rsc/index.d.ts.map +1 -1
- package/dist/exports/rsc/index.js +2 -0
- package/dist/exports/rsc/index.js.map +1 -1
- package/dist/fields/ConfirmPassword/index.d.ts +4 -0
- package/dist/fields/ConfirmPassword/index.d.ts.map +1 -1
- package/dist/fields/ConfirmPassword/index.js +37 -33
- package/dist/fields/ConfirmPassword/index.js.map +1 -1
- package/dist/fields/Number/Input.d.ts.map +1 -1
- package/dist/fields/Number/Input.js +29 -25
- package/dist/fields/Number/Input.js.map +1 -1
- package/dist/fields/Number/types.d.ts +4 -0
- package/dist/fields/Number/types.d.ts.map +1 -1
- package/dist/fields/Number/types.js.map +1 -1
- package/dist/fields/Password/input.d.ts.map +1 -1
- package/dist/fields/Password/input.js +33 -29
- package/dist/fields/Password/input.js.map +1 -1
- package/dist/fields/Password/types.d.ts +4 -0
- package/dist/fields/Password/types.d.ts.map +1 -1
- package/dist/fields/Password/types.js.map +1 -1
- package/dist/fields/Relationship/Input.d.ts.map +1 -1
- package/dist/fields/Relationship/Input.js +2 -0
- package/dist/fields/Relationship/Input.js.map +1 -1
- package/dist/fields/Relationship/types.d.ts +4 -0
- package/dist/fields/Relationship/types.d.ts.map +1 -1
- package/dist/fields/Relationship/types.js.map +1 -1
- package/dist/fields/Select/Input.d.ts +4 -0
- package/dist/fields/Select/Input.d.ts.map +1 -1
- package/dist/fields/Select/Input.js +44 -40
- package/dist/fields/Select/Input.js.map +1 -1
- package/dist/fields/Text/Input.d.ts.map +1 -1
- package/dist/fields/Text/Input.js +25 -21
- package/dist/fields/Text/Input.js.map +1 -1
- package/dist/fields/Text/types.d.ts +4 -0
- package/dist/fields/Text/types.d.ts.map +1 -1
- package/dist/fields/Text/types.js.map +1 -1
- package/dist/fields/Textarea/Input.d.ts.map +1 -1
- package/dist/fields/Textarea/Input.js +27 -23
- package/dist/fields/Textarea/Input.js.map +1 -1
- package/dist/fields/Textarea/index.css +1 -1
- package/dist/fields/Textarea/types.d.ts +4 -0
- package/dist/fields/Textarea/types.d.ts.map +1 -1
- package/dist/fields/Textarea/types.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/addFieldStatePromise.d.ts +1 -0
- package/dist/forms/fieldSchemasToFormState/addFieldStatePromise.d.ts.map +1 -1
- package/dist/forms/fieldSchemasToFormState/addFieldStatePromise.js +9 -1
- package/dist/forms/fieldSchemasToFormState/addFieldStatePromise.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/index.d.ts +2 -1
- package/dist/forms/fieldSchemasToFormState/index.d.ts.map +1 -1
- package/dist/forms/fieldSchemasToFormState/index.js +2 -0
- package/dist/forms/fieldSchemasToFormState/index.js.map +1 -1
- package/dist/forms/fieldSchemasToFormState/iterateFields.d.ts +2 -1
- package/dist/forms/fieldSchemasToFormState/iterateFields.d.ts.map +1 -1
- package/dist/forms/fieldSchemasToFormState/iterateFields.js +2 -0
- package/dist/forms/fieldSchemasToFormState/iterateFields.js.map +1 -1
- package/dist/styles.css +1 -1
- package/dist/utilities/buildFormState.d.ts.map +1 -1
- package/dist/utilities/buildFormState.js +1 -0
- package/dist/utilities/buildFormState.js.map +1 -1
- package/dist/utilities/formatRelativeDate.d.ts +15 -0
- package/dist/utilities/formatRelativeDate.d.ts.map +1 -0
- package/dist/utilities/formatRelativeDate.js +62 -0
- package/dist/utilities/formatRelativeDate.js.map +1 -0
- package/dist/utilities/recentlyViewed.d.ts +16 -0
- package/dist/utilities/recentlyViewed.d.ts.map +1 -0
- package/dist/utilities/recentlyViewed.js +21 -0
- package/dist/utilities/recentlyViewed.js.map +1 -0
- package/dist/utilities/recentlyViewed.spec.js +92 -0
- package/dist/utilities/recentlyViewed.spec.js.map +1 -0
- package/dist/views/Document/index.d.ts.map +1 -1
- package/dist/views/Document/index.js +9 -0
- package/dist/views/Document/index.js.map +1 -1
- package/dist/views/Document/recordRecentlyViewed.d.ts +12 -0
- package/dist/views/Document/recordRecentlyViewed.d.ts.map +1 -0
- package/dist/views/Document/recordRecentlyViewed.js +40 -0
- package/dist/views/Document/recordRecentlyViewed.js.map +1 -0
- package/dist/widgets/CollectionQuery/index.css +10 -152
- package/dist/widgets/CollectionQuery/index.d.ts +0 -1
- package/dist/widgets/CollectionQuery/index.d.ts.map +1 -1
- package/dist/widgets/CollectionQuery/index.js +40 -111
- package/dist/widgets/CollectionQuery/index.js.map +1 -1
- package/dist/widgets/RecentlyViewed/CollectionsField/index.css +14 -0
- package/dist/widgets/RecentlyViewed/CollectionsField/index.d.ts +10 -0
- package/dist/widgets/RecentlyViewed/CollectionsField/index.d.ts.map +1 -0
- package/dist/widgets/RecentlyViewed/CollectionsField/index.js +76 -0
- package/dist/widgets/RecentlyViewed/CollectionsField/index.js.map +1 -0
- package/dist/widgets/RecentlyViewed/index.d.ts +10 -0
- package/dist/widgets/RecentlyViewed/index.d.ts.map +1 -0
- package/dist/widgets/RecentlyViewed/index.js +148 -0
- package/dist/widgets/RecentlyViewed/index.js.map +1 -0
- package/dist/widgets/WidgetCard/index.css +155 -0
- package/dist/widgets/WidgetCard/index.d.ts +19 -0
- package/dist/widgets/WidgetCard/index.d.ts.map +1 -0
- package/dist/widgets/WidgetCard/index.js +49 -0
- package/dist/widgets/WidgetCard/index.js.map +1 -0
- package/package.json +4 -4
- package/dist/elements/Hierarchy/Drawer/fetchAncestorPath.d.ts.map +0 -1
- package/dist/elements/Hierarchy/Drawer/fetchAncestorPath.js.map +0 -1
- package/dist/elements/Hierarchy/Drawer/index.css +0 -90
- package/dist/elements/Hierarchy/Drawer/index.d.ts +0 -20
- package/dist/elements/Hierarchy/Drawer/index.d.ts.map +0 -1
- package/dist/elements/Hierarchy/Drawer/index.js.map +0 -1
- package/dist/elements/Hierarchy/Drawer/types.d.ts.map +0 -1
- package/dist/elements/Hierarchy/Drawer/types.js.map +0 -1
- package/dist/elements/Hierarchy/Drawer/useHierarchyDrawer.d.ts +0 -30
- package/dist/elements/Hierarchy/Drawer/useHierarchyDrawer.d.ts.map +0 -1
- package/dist/elements/Hierarchy/Drawer/useHierarchyDrawer.js.map +0 -1
- /package/dist/elements/Hierarchy/{Drawer → Modal}/fetchAncestorPath.d.ts +0 -0
- /package/dist/elements/Hierarchy/{Drawer → Modal}/fetchAncestorPath.js +0 -0
- /package/dist/elements/Hierarchy/{Drawer → Modal}/types.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildFormState.d.ts","sourceRoot":"","sources":["../../src/utilities/buildFormState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,WAAW,EACX,SAAS,EACT,cAAc,EACf,MAAM,SAAS,CAAA;AAehB,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,gBAAgB,EAAE,MAAM,CAAA;IACxB,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,KAAK,2BAA2B,GAAG;IACjC,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,MAAM,CAAC,EAAE,KAAK,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,KAAK,yBAAyB,GAAG;IAC/B,cAAc,CAAC,EAAE,KAAK,CAAA;IACtB,WAAW,CAAC,EAAE,KAAK,CAAA;IACnB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,cAAc,CAAC,EAAE,KAAK,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,GAAG,CACA;IACE,OAAO,EAAE,MAAM,CAAA;CAChB,GACD,WAAW,CACd,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,yBAAyB,GAAG,2BAA2B,CAAA;AAE1F,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAChD,kBAAkB,EAClB,OAAO,CAAC,oBAAoB,CAAC,CAwB9B,CAAA;AAED,eAAO,MAAM,cAAc,GACzB,MAAM,kBAAkB,KACvB,OAAO,CAAC,2BAA2B,
|
|
1
|
+
{"version":3,"file":"buildFormState.d.ts","sourceRoot":"","sources":["../../src/utilities/buildFormState.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,WAAW,EACX,SAAS,EACT,cAAc,EACf,MAAM,SAAS,CAAA;AAehB,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,OAAO,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,UAAU,GAAG,MAAM,GAAG,MAAM,CAAA;CACpC,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,gBAAgB,EAAE,MAAM,CAAA;IACxB,OAAO,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,KAAK,2BAA2B,GAAG;IACjC,YAAY,CAAC,EAAE,YAAY,CAAA;IAC3B,MAAM,CAAC,EAAE,KAAK,CAAA;IACd,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,CAAC,EAAE,WAAW,CAAA;IACzB,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,cAAc,CAAA;IAC/B,KAAK,EAAE,SAAS,CAAA;CACjB,CAAA;AAED,KAAK,yBAAyB,GAAG;IAC/B,cAAc,CAAC,EAAE,KAAK,CAAA;IACtB,WAAW,CAAC,EAAE,KAAK,CAAA;IACnB,UAAU,CAAC,EAAE,KAAK,CAAA;IAClB,cAAc,CAAC,EAAE,KAAK,CAAA;IACtB,KAAK,CAAC,EAAE,KAAK,CAAA;CACd,GAAG,CACA;IACE,OAAO,EAAE,MAAM,CAAA;CAChB,GACD,WAAW,CACd,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,yBAAyB,GAAG,2BAA2B,CAAA;AAE1F,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAChD,kBAAkB,EAClB,OAAO,CAAC,oBAAoB,CAAC,CAwB9B,CAAA;AAED,eAAO,MAAM,cAAc,GACzB,MAAM,kBAAkB,KACvB,OAAO,CAAC,2BAA2B,CAuNrC,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"buildFormState.js","names":["canAccessAdmin","formatErrors","UnauthorizedError","getSelectMode","reduceFieldsToValues","fieldSchemasToFormState","renderField","getClientConfig","getClientSchemaMap","getSchemaMap","handleFormStateLocking","handleLivePreview","handlePreview","handleStaleDataCheck","buildFormStateHandler","args","req","res","buildFormState","err","payload","logger","error","msg","message","id","idFromArgs","checkForStaleData","collectionSlug","data","incomingData","docPermissions","docPreferences","documentFormState","formState","globalSlug","initialBlockData","initialBlockFormState","mockRSCs","operation","originalUpdatedAt","readOnly","renderAllFields","i18n","config","returnLivePreviewURL","returnLockStatus","returnPreviewURL","widgetSlug","schemaPath","select","skipClientConfigAuth","skipValidation","updateLastEdited","selectMode","undefined","Error","schemaMap","clientSchemaMap","importMap","user","fieldOrEntityConfig","get","fields","length","type","documentData","blockData","Array","isArray","formStateResult","clientFieldSchemaMap","fieldSchemaMap","permissions","preferences","previousFormState","renderFieldFn","collections","upload","file","lockedStateResult","staleDataStateResult","lockedState","staleDataState","state","livePreviewURL","previewURL"],"sources":["../../src/utilities/buildFormState.ts"],"sourcesContent":["import type {\n BuildFormStateArgs,\n ClientConfig,\n ClientUser,\n ErrorResult,\n FormState,\n ServerFunction,\n} from 'payload'\n\nimport { canAccessAdmin, formatErrors, UnauthorizedError } from 'payload'\nimport { getSelectMode, reduceFieldsToValues } from 'payload/shared'\n\nimport { fieldSchemasToFormState } from '../forms/fieldSchemasToFormState/index.js'\nimport { renderField } from '../forms/fieldSchemasToFormState/renderField.js'\nimport { getClientConfig } from './getClientConfig.js'\nimport { getClientSchemaMap } from './getClientSchemaMap.js'\nimport { getSchemaMap } from './getSchemaMap.js'\nimport { handleFormStateLocking } from './handleFormStateLocking.js'\nimport { handleLivePreview } from './handleLivePreview.js'\nimport { handlePreview } from './handlePreview.js'\nimport { handleStaleDataCheck } from './handleStaleDataCheck.js'\n\nexport type LockedState = {\n isLocked: boolean\n lastEditedAt: string\n user?: ClientUser | number | string\n}\n\nexport type StaleDataState = {\n currentUpdatedAt: string\n isStale: boolean\n}\n\ntype BuildFormStateSuccessResult = {\n clientConfig?: ClientConfig\n errors?: never\n indexPath?: string\n livePreviewURL?: string\n lockedState?: LockedState\n previewURL?: string\n staleDataState?: StaleDataState\n state: FormState\n}\n\ntype BuildFormStateErrorResult = {\n livePreviewURL?: never\n lockedState?: never\n previewURL?: never\n staleDataState?: never\n state?: never\n} & (\n | {\n message: string\n }\n | ErrorResult\n)\n\nexport type BuildFormStateResult = BuildFormStateErrorResult | BuildFormStateSuccessResult\n\nexport const buildFormStateHandler: ServerFunction<\n BuildFormStateArgs,\n Promise<BuildFormStateResult>\n> = async (args) => {\n const { req } = args\n\n try {\n await canAccessAdmin({ req })\n const res = await buildFormState(args)\n\n return res\n } catch (err) {\n req.payload.logger.error({ err, msg: `There was an error building form state` })\n\n if (err.message === 'Could not find field schema for given path') {\n return {\n message: err.message,\n }\n }\n\n if (err.message === 'Unauthorized') {\n throw new UnauthorizedError()\n }\n\n return formatErrors(err)\n }\n}\n\nexport const buildFormState = async (\n args: BuildFormStateArgs,\n): Promise<BuildFormStateSuccessResult> => {\n const {\n id: idFromArgs,\n checkForStaleData,\n collectionSlug,\n data: incomingData,\n docPermissions,\n docPreferences,\n documentFormState,\n formState,\n globalSlug,\n initialBlockData,\n initialBlockFormState,\n mockRSCs,\n operation,\n originalUpdatedAt,\n readOnly,\n renderAllFields,\n req,\n req: {\n i18n,\n payload,\n payload: { config },\n },\n returnLivePreviewURL,\n returnLockStatus,\n returnPreviewURL,\n widgetSlug,\n schemaPath = collectionSlug || globalSlug || widgetSlug,\n select,\n skipClientConfigAuth,\n skipValidation,\n updateLastEdited,\n } = args\n\n const selectMode = select ? getSelectMode(select) : undefined\n\n if (!collectionSlug && !globalSlug && !widgetSlug) {\n throw new Error('Either collectionSlug, globalSlug, or widgetSlug must be provided')\n }\n\n const schemaMap = getSchemaMap({\n collectionSlug,\n config,\n globalSlug,\n i18n,\n widgetSlug,\n })\n\n const clientSchemaMap = getClientSchemaMap({\n collectionSlug,\n config: getClientConfig({\n config,\n i18n,\n importMap: req.payload.importMap,\n user: skipClientConfigAuth ? true : req.user,\n }),\n globalSlug,\n i18n,\n payload,\n schemaMap,\n widgetSlug,\n })\n\n const id = collectionSlug ? idFromArgs : undefined\n const fieldOrEntityConfig = schemaMap.get(schemaPath)\n\n if (!fieldOrEntityConfig) {\n throw new Error(`Could not find \"${schemaPath}\" in the fieldSchemaMap`)\n }\n\n if (\n (!('fields' in fieldOrEntityConfig) ||\n !fieldOrEntityConfig.fields ||\n !fieldOrEntityConfig.fields.length) &&\n 'type' in fieldOrEntityConfig &&\n fieldOrEntityConfig.type !== 'blocks'\n ) {\n throw new Error(\n `The field found in fieldSchemaMap for \"${schemaPath}\" does not contain any subfields.`,\n )\n }\n\n // If there is form state but no data, deduce data from that form state, e.g. on initial load\n // Otherwise, use the incoming data as the source of truth, e.g. on subsequent saves\n const data = incomingData || reduceFieldsToValues(formState, true)\n\n let documentData = undefined\n\n if (documentFormState) {\n documentData = reduceFieldsToValues(documentFormState, true)\n }\n\n let blockData = initialBlockData\n\n if (initialBlockFormState) {\n blockData = reduceFieldsToValues(initialBlockFormState, true)\n }\n\n /**\n * When building state for sub schemas we need to adjust:\n * - `fields`\n * - `parentSchemaPath`\n * - `parentPath`\n *\n * Type assertion is fine because we wrap sub schemas in an array\n * so we can safely map over them within `fieldSchemasToFormState`\n */\n const fields = Array.isArray(fieldOrEntityConfig)\n ? fieldOrEntityConfig\n : 'fields' in fieldOrEntityConfig\n ? fieldOrEntityConfig.fields\n : [fieldOrEntityConfig]\n\n // Ensure data.id is present during form state requests, where the data\n // is passed from the client as an argument, without the ID\n if (!data.id && id) {\n data.id = id\n }\n\n const formStateResult = await fieldSchemasToFormState({\n id,\n clientFieldSchemaMap: clientSchemaMap,\n collectionSlug,\n data,\n documentData,\n fields,\n fieldSchemaMap: schemaMap,\n initialBlockData: blockData,\n mockRSCs,\n operation,\n permissions: docPermissions?.fields || {},\n preferences: docPreferences || { fields: {} },\n previousFormState: formState,\n readOnly,\n renderAllFields,\n renderFieldFn: renderField,\n req,\n schemaPath,\n select,\n selectMode,\n skipValidation,\n })\n\n // Maintain form state of auth / upload fields\n if (collectionSlug && formState) {\n if (payload.collections[collectionSlug]?.config?.upload && formState.file) {\n formStateResult.file = formState.file\n }\n }\n\n let lockedStateResult: LockedState | undefined\n\n if (returnLockStatus) {\n lockedStateResult = await handleFormStateLocking({\n id,\n collectionSlug,\n globalSlug,\n req,\n updateLastEdited,\n })\n }\n\n let staleDataStateResult: StaleDataState | undefined\n\n if (checkForStaleData && originalUpdatedAt && ((collectionSlug && id) || globalSlug)) {\n staleDataStateResult = await handleStaleDataCheck({\n id,\n collectionSlug,\n globalSlug,\n originalUpdatedAt,\n req,\n })\n }\n\n const res: BuildFormStateSuccessResult = {\n lockedState: lockedStateResult,\n staleDataState: staleDataStateResult,\n state: formStateResult,\n }\n\n if (returnLivePreviewURL) {\n const { livePreviewURL } = await handleLivePreview({\n collectionSlug,\n config,\n data,\n globalSlug,\n req,\n })\n\n // Important: only set this when not undefined,\n // Otherwise it will travel through the network as `$undefined`\n if (livePreviewURL) {\n res.livePreviewURL = livePreviewURL\n }\n }\n\n if (returnPreviewURL) {\n const { previewURL } = await handlePreview({\n collectionSlug,\n config,\n data,\n globalSlug,\n req,\n })\n\n // Important: only set this when not undefined,\n // Otherwise it will travel through the network as `$undefined`\n if (previewURL) {\n res.previewURL = previewURL\n }\n }\n\n return res\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"buildFormState.js","names":["canAccessAdmin","formatErrors","UnauthorizedError","getSelectMode","reduceFieldsToValues","fieldSchemasToFormState","renderField","getClientConfig","getClientSchemaMap","getSchemaMap","handleFormStateLocking","handleLivePreview","handlePreview","handleStaleDataCheck","buildFormStateHandler","args","req","res","buildFormState","err","payload","logger","error","msg","message","id","idFromArgs","checkForStaleData","collectionSlug","data","incomingData","docPermissions","docPreferences","documentFormState","formState","globalSlug","initialBlockData","initialBlockFormState","mockRSCs","operation","originalUpdatedAt","readOnly","renderAllFields","i18n","config","returnLivePreviewURL","returnLockStatus","returnPreviewURL","widgetSlug","schemaPath","select","skipClientConfigAuth","skipValidation","updateLastEdited","selectMode","undefined","Error","schemaMap","clientSchemaMap","importMap","user","fieldOrEntityConfig","get","fields","length","type","documentData","blockData","Array","isArray","formStateResult","clientFieldSchemaMap","fieldSchemaMap","permissions","preferences","previousFormState","renderFieldFn","collections","upload","file","lockedStateResult","staleDataStateResult","lockedState","staleDataState","state","livePreviewURL","previewURL"],"sources":["../../src/utilities/buildFormState.ts"],"sourcesContent":["import type {\n BuildFormStateArgs,\n ClientConfig,\n ClientUser,\n ErrorResult,\n FormState,\n ServerFunction,\n} from 'payload'\n\nimport { canAccessAdmin, formatErrors, UnauthorizedError } from 'payload'\nimport { getSelectMode, reduceFieldsToValues } from 'payload/shared'\n\nimport { fieldSchemasToFormState } from '../forms/fieldSchemasToFormState/index.js'\nimport { renderField } from '../forms/fieldSchemasToFormState/renderField.js'\nimport { getClientConfig } from './getClientConfig.js'\nimport { getClientSchemaMap } from './getClientSchemaMap.js'\nimport { getSchemaMap } from './getSchemaMap.js'\nimport { handleFormStateLocking } from './handleFormStateLocking.js'\nimport { handleLivePreview } from './handleLivePreview.js'\nimport { handlePreview } from './handlePreview.js'\nimport { handleStaleDataCheck } from './handleStaleDataCheck.js'\n\nexport type LockedState = {\n isLocked: boolean\n lastEditedAt: string\n user?: ClientUser | number | string\n}\n\nexport type StaleDataState = {\n currentUpdatedAt: string\n isStale: boolean\n}\n\ntype BuildFormStateSuccessResult = {\n clientConfig?: ClientConfig\n errors?: never\n indexPath?: string\n livePreviewURL?: string\n lockedState?: LockedState\n previewURL?: string\n staleDataState?: StaleDataState\n state: FormState\n}\n\ntype BuildFormStateErrorResult = {\n livePreviewURL?: never\n lockedState?: never\n previewURL?: never\n staleDataState?: never\n state?: never\n} & (\n | {\n message: string\n }\n | ErrorResult\n)\n\nexport type BuildFormStateResult = BuildFormStateErrorResult | BuildFormStateSuccessResult\n\nexport const buildFormStateHandler: ServerFunction<\n BuildFormStateArgs,\n Promise<BuildFormStateResult>\n> = async (args) => {\n const { req } = args\n\n try {\n await canAccessAdmin({ req })\n const res = await buildFormState(args)\n\n return res\n } catch (err) {\n req.payload.logger.error({ err, msg: `There was an error building form state` })\n\n if (err.message === 'Could not find field schema for given path') {\n return {\n message: err.message,\n }\n }\n\n if (err.message === 'Unauthorized') {\n throw new UnauthorizedError()\n }\n\n return formatErrors(err)\n }\n}\n\nexport const buildFormState = async (\n args: BuildFormStateArgs,\n): Promise<BuildFormStateSuccessResult> => {\n const {\n id: idFromArgs,\n checkForStaleData,\n collectionSlug,\n data: incomingData,\n docPermissions,\n docPreferences,\n documentFormState,\n formState,\n globalSlug,\n initialBlockData,\n initialBlockFormState,\n mockRSCs,\n operation,\n originalUpdatedAt,\n readOnly,\n renderAllFields,\n req,\n req: {\n i18n,\n payload,\n payload: { config },\n },\n returnLivePreviewURL,\n returnLockStatus,\n returnPreviewURL,\n widgetSlug,\n schemaPath = collectionSlug || globalSlug || widgetSlug,\n select,\n skipClientConfigAuth,\n skipValidation,\n updateLastEdited,\n } = args\n\n const selectMode = select ? getSelectMode(select) : undefined\n\n if (!collectionSlug && !globalSlug && !widgetSlug) {\n throw new Error('Either collectionSlug, globalSlug, or widgetSlug must be provided')\n }\n\n const schemaMap = getSchemaMap({\n collectionSlug,\n config,\n globalSlug,\n i18n,\n widgetSlug,\n })\n\n const clientSchemaMap = getClientSchemaMap({\n collectionSlug,\n config: getClientConfig({\n config,\n i18n,\n importMap: req.payload.importMap,\n user: skipClientConfigAuth ? true : req.user,\n }),\n globalSlug,\n i18n,\n payload,\n schemaMap,\n widgetSlug,\n })\n\n const id = collectionSlug ? idFromArgs : undefined\n const fieldOrEntityConfig = schemaMap.get(schemaPath)\n\n if (!fieldOrEntityConfig) {\n throw new Error(`Could not find \"${schemaPath}\" in the fieldSchemaMap`)\n }\n\n if (\n (!('fields' in fieldOrEntityConfig) ||\n !fieldOrEntityConfig.fields ||\n !fieldOrEntityConfig.fields.length) &&\n 'type' in fieldOrEntityConfig &&\n fieldOrEntityConfig.type !== 'blocks'\n ) {\n throw new Error(\n `The field found in fieldSchemaMap for \"${schemaPath}\" does not contain any subfields.`,\n )\n }\n\n // If there is form state but no data, deduce data from that form state, e.g. on initial load\n // Otherwise, use the incoming data as the source of truth, e.g. on subsequent saves\n const data = incomingData || reduceFieldsToValues(formState, true)\n\n let documentData = undefined\n\n if (documentFormState) {\n documentData = reduceFieldsToValues(documentFormState, true)\n }\n\n let blockData = initialBlockData\n\n if (initialBlockFormState) {\n blockData = reduceFieldsToValues(initialBlockFormState, true)\n }\n\n /**\n * When building state for sub schemas we need to adjust:\n * - `fields`\n * - `parentSchemaPath`\n * - `parentPath`\n *\n * Type assertion is fine because we wrap sub schemas in an array\n * so we can safely map over them within `fieldSchemasToFormState`\n */\n const fields = Array.isArray(fieldOrEntityConfig)\n ? fieldOrEntityConfig\n : 'fields' in fieldOrEntityConfig\n ? fieldOrEntityConfig.fields\n : [fieldOrEntityConfig]\n\n // Ensure data.id is present during form state requests, where the data\n // is passed from the client as an argument, without the ID\n if (!data.id && id) {\n data.id = id\n }\n\n const formStateResult = await fieldSchemasToFormState({\n id,\n clientFieldSchemaMap: clientSchemaMap,\n collectionSlug,\n data,\n documentData,\n fields,\n fieldSchemaMap: schemaMap,\n globalSlug,\n initialBlockData: blockData,\n mockRSCs,\n operation,\n permissions: docPermissions?.fields || {},\n preferences: docPreferences || { fields: {} },\n previousFormState: formState,\n readOnly,\n renderAllFields,\n renderFieldFn: renderField,\n req,\n schemaPath,\n select,\n selectMode,\n skipValidation,\n })\n\n // Maintain form state of auth / upload fields\n if (collectionSlug && formState) {\n if (payload.collections[collectionSlug]?.config?.upload && formState.file) {\n formStateResult.file = formState.file\n }\n }\n\n let lockedStateResult: LockedState | undefined\n\n if (returnLockStatus) {\n lockedStateResult = await handleFormStateLocking({\n id,\n collectionSlug,\n globalSlug,\n req,\n updateLastEdited,\n })\n }\n\n let staleDataStateResult: StaleDataState | undefined\n\n if (checkForStaleData && originalUpdatedAt && ((collectionSlug && id) || globalSlug)) {\n staleDataStateResult = await handleStaleDataCheck({\n id,\n collectionSlug,\n globalSlug,\n originalUpdatedAt,\n req,\n })\n }\n\n const res: BuildFormStateSuccessResult = {\n lockedState: lockedStateResult,\n staleDataState: staleDataStateResult,\n state: formStateResult,\n }\n\n if (returnLivePreviewURL) {\n const { livePreviewURL } = await handleLivePreview({\n collectionSlug,\n config,\n data,\n globalSlug,\n req,\n })\n\n // Important: only set this when not undefined,\n // Otherwise it will travel through the network as `$undefined`\n if (livePreviewURL) {\n res.livePreviewURL = livePreviewURL\n }\n }\n\n if (returnPreviewURL) {\n const { previewURL } = await handlePreview({\n collectionSlug,\n config,\n data,\n globalSlug,\n req,\n })\n\n // Important: only set this when not undefined,\n // Otherwise it will travel through the network as `$undefined`\n if (previewURL) {\n res.previewURL = previewURL\n }\n }\n\n return res\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns an `Intl.RelativeTimeFormat` for the given language, falling back to English on
|
|
3
|
+
* unsupported locales. Create it once and reuse it across rows. Shared by dashboard widgets so
|
|
4
|
+
* their relative timestamps render identically.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getRelativeTimeFormat(language: string): Intl.RelativeTimeFormat;
|
|
7
|
+
/**
|
|
8
|
+
* Formats an ISO date string as a locale-aware relative time (e.g. "5m ago", "in 2d"). Returns the
|
|
9
|
+
* original value unchanged when it is not a parseable date.
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatRelativeDate({ relativeTimeFormat, value, }: {
|
|
12
|
+
relativeTimeFormat: Intl.RelativeTimeFormat;
|
|
13
|
+
value: string;
|
|
14
|
+
}): string;
|
|
15
|
+
//# sourceMappingURL=formatRelativeDate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatRelativeDate.d.ts","sourceRoot":"","sources":["../../src/utilities/formatRelativeDate.ts"],"names":[],"mappings":"AAUA;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC,kBAAkB,CAM/E;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAAC,EACjC,kBAAkB,EAClB,KAAK,GACN,EAAE;IACD,kBAAkB,EAAE,IAAI,CAAC,kBAAkB,CAAA;IAC3C,KAAK,EAAE,MAAM,CAAA;CACd,GAAG,MAAM,CAkBT"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
const relativeTimeDivisions = [{
|
|
2
|
+
amount: 60,
|
|
3
|
+
unit: 'seconds'
|
|
4
|
+
}, {
|
|
5
|
+
amount: 60,
|
|
6
|
+
unit: 'minutes'
|
|
7
|
+
}, {
|
|
8
|
+
amount: 24,
|
|
9
|
+
unit: 'hours'
|
|
10
|
+
}, {
|
|
11
|
+
amount: 7,
|
|
12
|
+
unit: 'days'
|
|
13
|
+
}, {
|
|
14
|
+
amount: 4.34524,
|
|
15
|
+
unit: 'weeks'
|
|
16
|
+
}, {
|
|
17
|
+
amount: 12,
|
|
18
|
+
unit: 'months'
|
|
19
|
+
}, {
|
|
20
|
+
amount: Number.POSITIVE_INFINITY,
|
|
21
|
+
unit: 'years'
|
|
22
|
+
}];
|
|
23
|
+
/**
|
|
24
|
+
* Returns an `Intl.RelativeTimeFormat` for the given language, falling back to English on
|
|
25
|
+
* unsupported locales. Create it once and reuse it across rows. Shared by dashboard widgets so
|
|
26
|
+
* their relative timestamps render identically.
|
|
27
|
+
*/
|
|
28
|
+
export function getRelativeTimeFormat(language) {
|
|
29
|
+
try {
|
|
30
|
+
return new Intl.RelativeTimeFormat(language, {
|
|
31
|
+
numeric: 'auto',
|
|
32
|
+
style: 'narrow'
|
|
33
|
+
});
|
|
34
|
+
} catch {
|
|
35
|
+
return new Intl.RelativeTimeFormat('en', {
|
|
36
|
+
numeric: 'auto',
|
|
37
|
+
style: 'narrow'
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Formats an ISO date string as a locale-aware relative time (e.g. "5m ago", "in 2d"). Returns the
|
|
43
|
+
* original value unchanged when it is not a parseable date.
|
|
44
|
+
*/
|
|
45
|
+
export function formatRelativeDate({
|
|
46
|
+
relativeTimeFormat,
|
|
47
|
+
value
|
|
48
|
+
}) {
|
|
49
|
+
const date = new Date(value);
|
|
50
|
+
if (Number.isNaN(date.getTime())) {
|
|
51
|
+
return value;
|
|
52
|
+
}
|
|
53
|
+
let duration = (date.getTime() - Date.now()) / 1000;
|
|
54
|
+
for (const division of relativeTimeDivisions) {
|
|
55
|
+
if (Math.abs(duration) < division.amount) {
|
|
56
|
+
return relativeTimeFormat.format(Math.round(duration), division.unit);
|
|
57
|
+
}
|
|
58
|
+
duration /= division.amount;
|
|
59
|
+
}
|
|
60
|
+
return relativeTimeFormat.format(Math.round(duration), 'years');
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=formatRelativeDate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"formatRelativeDate.js","names":["relativeTimeDivisions","amount","unit","Number","POSITIVE_INFINITY","getRelativeTimeFormat","language","Intl","RelativeTimeFormat","numeric","style","formatRelativeDate","relativeTimeFormat","value","date","Date","isNaN","getTime","duration","now","division","Math","abs","format","round"],"sources":["../../src/utilities/formatRelativeDate.ts"],"sourcesContent":["const relativeTimeDivisions: { amount: number; unit: Intl.RelativeTimeFormatUnit }[] = [\n { amount: 60, unit: 'seconds' },\n { amount: 60, unit: 'minutes' },\n { amount: 24, unit: 'hours' },\n { amount: 7, unit: 'days' },\n { amount: 4.34524, unit: 'weeks' },\n { amount: 12, unit: 'months' },\n { amount: Number.POSITIVE_INFINITY, unit: 'years' },\n]\n\n/**\n * Returns an `Intl.RelativeTimeFormat` for the given language, falling back to English on\n * unsupported locales. Create it once and reuse it across rows. Shared by dashboard widgets so\n * their relative timestamps render identically.\n */\nexport function getRelativeTimeFormat(language: string): Intl.RelativeTimeFormat {\n try {\n return new Intl.RelativeTimeFormat(language, { numeric: 'auto', style: 'narrow' })\n } catch {\n return new Intl.RelativeTimeFormat('en', { numeric: 'auto', style: 'narrow' })\n }\n}\n\n/**\n * Formats an ISO date string as a locale-aware relative time (e.g. \"5m ago\", \"in 2d\"). Returns the\n * original value unchanged when it is not a parseable date.\n */\nexport function formatRelativeDate({\n relativeTimeFormat,\n value,\n}: {\n relativeTimeFormat: Intl.RelativeTimeFormat\n value: string\n}): string {\n const date = new Date(value)\n\n if (Number.isNaN(date.getTime())) {\n return value\n }\n\n let duration = (date.getTime() - Date.now()) / 1000\n\n for (const division of relativeTimeDivisions) {\n if (Math.abs(duration) < division.amount) {\n return relativeTimeFormat.format(Math.round(duration), division.unit)\n }\n\n duration /= division.amount\n }\n\n return relativeTimeFormat.format(Math.round(duration), 'years')\n}\n"],"mappings":"AAAA,MAAMA,qBAAA,GAAiF,CACrF;EAAEC,MAAA,EAAQ;EAAIC,IAAA,EAAM;AAAU,GAC9B;EAAED,MAAA,EAAQ;EAAIC,IAAA,EAAM;AAAU,GAC9B;EAAED,MAAA,EAAQ;EAAIC,IAAA,EAAM;AAAQ,GAC5B;EAAED,MAAA,EAAQ;EAAGC,IAAA,EAAM;AAAO,GAC1B;EAAED,MAAA,EAAQ;EAASC,IAAA,EAAM;AAAQ,GACjC;EAAED,MAAA,EAAQ;EAAIC,IAAA,EAAM;AAAS,GAC7B;EAAED,MAAA,EAAQE,MAAA,CAAOC,iBAAiB;EAAEF,IAAA,EAAM;AAAQ,EACnD;AAED;;;;;AAKA,OAAO,SAASG,sBAAsBC,QAAgB;EACpD,IAAI;IACF,OAAO,IAAIC,IAAA,CAAKC,kBAAkB,CAACF,QAAA,EAAU;MAAEG,OAAA,EAAS;MAAQC,KAAA,EAAO;IAAS;EAClF,EAAE,MAAM;IACN,OAAO,IAAIH,IAAA,CAAKC,kBAAkB,CAAC,MAAM;MAAEC,OAAA,EAAS;MAAQC,KAAA,EAAO;IAAS;EAC9E;AACF;AAEA;;;;AAIA,OAAO,SAASC,mBAAmB;EACjCC,kBAAkB;EAClBC;AAAK,CAIN;EACC,MAAMC,IAAA,GAAO,IAAIC,IAAA,CAAKF,KAAA;EAEtB,IAAIV,MAAA,CAAOa,KAAK,CAACF,IAAA,CAAKG,OAAO,KAAK;IAChC,OAAOJ,KAAA;EACT;EAEA,IAAIK,QAAA,GAAW,CAACJ,IAAA,CAAKG,OAAO,KAAKF,IAAA,CAAKI,GAAG,EAAC,IAAK;EAE/C,KAAK,MAAMC,QAAA,IAAYpB,qBAAA,EAAuB;IAC5C,IAAIqB,IAAA,CAAKC,GAAG,CAACJ,QAAA,IAAYE,QAAA,CAASnB,MAAM,EAAE;MACxC,OAAOW,kBAAA,CAAmBW,MAAM,CAACF,IAAA,CAAKG,KAAK,CAACN,QAAA,GAAWE,QAAA,CAASlB,IAAI;IACtE;IAEAgB,QAAA,IAAYE,QAAA,CAASnB,MAAM;EAC7B;EAEA,OAAOW,kBAAA,CAAmBW,MAAM,CAACF,IAAA,CAAKG,KAAK,CAACN,QAAA,GAAW;AACzD","ignoreList":[]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { RecentlyViewedItem, RecentlyViewedPreferences } from 'payload';
|
|
2
|
+
/**
|
|
3
|
+
* Maximum number of documents retained in the `recently-viewed` preference. The dashboard widget
|
|
4
|
+
* typically shows fewer; the extra entries act as a buffer once excluded collections are filtered.
|
|
5
|
+
*/
|
|
6
|
+
export declare const recentlyViewedMaxItems = 20;
|
|
7
|
+
/**
|
|
8
|
+
* Returns a new preference value with `item` moved to the front, deduped by collection + id, and
|
|
9
|
+
* capped at `max`. Pure so it can be unit tested and reused as `upsertPreferences`' customMerge.
|
|
10
|
+
*/
|
|
11
|
+
export declare const addRecentlyViewedItem: ({ existing, item, max, }: {
|
|
12
|
+
existing: RecentlyViewedPreferences | undefined;
|
|
13
|
+
item: RecentlyViewedItem;
|
|
14
|
+
max?: number;
|
|
15
|
+
}) => RecentlyViewedPreferences;
|
|
16
|
+
//# sourceMappingURL=recentlyViewed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recentlyViewed.d.ts","sourceRoot":"","sources":["../../src/utilities/recentlyViewed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,SAAS,CAAA;AAE5E;;;GAGG;AACH,eAAO,MAAM,sBAAsB,KAAK,CAAA;AAKxC;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,0BAInC;IACD,QAAQ,EAAE,yBAAyB,GAAG,SAAS,CAAA;IAC/C,IAAI,EAAE,kBAAkB,CAAA;IACxB,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,KAAG,yBASH,CAAA"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maximum number of documents retained in the `recently-viewed` preference. The dashboard widget
|
|
3
|
+
* typically shows fewer; the extra entries act as a buffer once excluded collections are filtered.
|
|
4
|
+
*/export const recentlyViewedMaxItems = 20;
|
|
5
|
+
const isSameDocument = (a, b) => a.collectionSlug === b.collectionSlug && String(a.id) === String(b.id);
|
|
6
|
+
/**
|
|
7
|
+
* Returns a new preference value with `item` moved to the front, deduped by collection + id, and
|
|
8
|
+
* capped at `max`. Pure so it can be unit tested and reused as `upsertPreferences`' customMerge.
|
|
9
|
+
*/
|
|
10
|
+
export const addRecentlyViewedItem = ({
|
|
11
|
+
existing,
|
|
12
|
+
item,
|
|
13
|
+
max = recentlyViewedMaxItems
|
|
14
|
+
}) => {
|
|
15
|
+
const previousItems = Array.isArray(existing?.items) ? existing.items : [];
|
|
16
|
+
const withoutDuplicate = previousItems.filter(existingItem => !isSameDocument(existingItem, item));
|
|
17
|
+
return {
|
|
18
|
+
items: [item, ...withoutDuplicate].slice(0, max)
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
//# sourceMappingURL=recentlyViewed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recentlyViewed.js","names":["recentlyViewedMaxItems","isSameDocument","a","b","collectionSlug","String","id","addRecentlyViewedItem","existing","item","max","previousItems","Array","isArray","items","withoutDuplicate","filter","existingItem","slice"],"sources":["../../src/utilities/recentlyViewed.ts"],"sourcesContent":["import type { RecentlyViewedItem, RecentlyViewedPreferences } from 'payload'\n\n/**\n * Maximum number of documents retained in the `recently-viewed` preference. The dashboard widget\n * typically shows fewer; the extra entries act as a buffer once excluded collections are filtered.\n */\nexport const recentlyViewedMaxItems = 20\n\nconst isSameDocument = (a: RecentlyViewedItem, b: RecentlyViewedItem) =>\n a.collectionSlug === b.collectionSlug && String(a.id) === String(b.id)\n\n/**\n * Returns a new preference value with `item` moved to the front, deduped by collection + id, and\n * capped at `max`. Pure so it can be unit tested and reused as `upsertPreferences`' customMerge.\n */\nexport const addRecentlyViewedItem = ({\n existing,\n item,\n max = recentlyViewedMaxItems,\n}: {\n existing: RecentlyViewedPreferences | undefined\n item: RecentlyViewedItem\n max?: number\n}): RecentlyViewedPreferences => {\n const previousItems = Array.isArray(existing?.items) ? existing.items : []\n const withoutDuplicate = previousItems.filter(\n (existingItem) => !isSameDocument(existingItem, item),\n )\n\n return {\n items: [item, ...withoutDuplicate].slice(0, max),\n }\n}\n"],"mappings":"AAEA;;;GAIA,OAAO,MAAMA,sBAAA,GAAyB;AAEtC,MAAMC,cAAA,GAAiBA,CAACC,CAAA,EAAuBC,CAAA,KAC7CD,CAAA,CAAEE,cAAc,KAAKD,CAAA,CAAEC,cAAc,IAAIC,MAAA,CAAOH,CAAA,CAAEI,EAAE,MAAMD,MAAA,CAAOF,CAAA,CAAEG,EAAE;AAEvE;;;;AAIA,OAAO,MAAMC,qBAAA,GAAwBA,CAAC;EACpCC,QAAQ;EACRC,IAAI;EACJC,GAAA,GAAMV;AAAsB,CAK7B;EACC,MAAMW,aAAA,GAAgBC,KAAA,CAAMC,OAAO,CAACL,QAAA,EAAUM,KAAA,IAASN,QAAA,CAASM,KAAK,GAAG,EAAE;EAC1E,MAAMC,gBAAA,GAAmBJ,aAAA,CAAcK,MAAM,CAC1CC,YAAA,IAAiB,CAAChB,cAAA,CAAegB,YAAA,EAAcR,IAAA;EAGlD,OAAO;IACLK,KAAA,EAAO,CAACL,IAAA,E,GAASM,gBAAA,CAAiB,CAACG,KAAK,CAAC,GAAGR,GAAA;EAC9C;AACF","ignoreList":[]}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { addRecentlyViewedItem, recentlyViewedMaxItems } from './recentlyViewed.js';
|
|
3
|
+
const item = (collectionSlug, id, viewedAt) => ({
|
|
4
|
+
collectionSlug,
|
|
5
|
+
id,
|
|
6
|
+
viewedAt
|
|
7
|
+
});
|
|
8
|
+
describe('addRecentlyViewedItem', () => {
|
|
9
|
+
it('should create the list when there are no existing preferences', () => {
|
|
10
|
+
const next = item('posts', 1, '2026-01-01T00:00:00.000Z');
|
|
11
|
+
const result = addRecentlyViewedItem({
|
|
12
|
+
existing: undefined,
|
|
13
|
+
item: next
|
|
14
|
+
});
|
|
15
|
+
expect(result.items).toEqual([next]);
|
|
16
|
+
});
|
|
17
|
+
it('should prepend the newly viewed document', () => {
|
|
18
|
+
const existing = {
|
|
19
|
+
items: [item('posts', 1, '2026-01-01T00:00:00.000Z')]
|
|
20
|
+
};
|
|
21
|
+
const next = item('pages', 2, '2026-01-02T00:00:00.000Z');
|
|
22
|
+
const result = addRecentlyViewedItem({
|
|
23
|
+
existing,
|
|
24
|
+
item: next
|
|
25
|
+
});
|
|
26
|
+
expect(result.items.map(i => i.id)).toEqual([2, 1]);
|
|
27
|
+
});
|
|
28
|
+
it('should move an already-viewed document to the front and refresh its timestamp', () => {
|
|
29
|
+
const existing = {
|
|
30
|
+
items: [item('pages', 2, '2026-01-02T00:00:00.000Z'), item('posts', 1, '2026-01-01T00:00:00.000Z')]
|
|
31
|
+
};
|
|
32
|
+
const next = item('posts', 1, '2026-01-03T00:00:00.000Z');
|
|
33
|
+
const result = addRecentlyViewedItem({
|
|
34
|
+
existing,
|
|
35
|
+
item: next
|
|
36
|
+
});
|
|
37
|
+
expect(result.items).toEqual([next, item('pages', 2, '2026-01-02T00:00:00.000Z')]);
|
|
38
|
+
});
|
|
39
|
+
it('should treat numeric and string ids consistently when deduping', () => {
|
|
40
|
+
const existing = {
|
|
41
|
+
items: [item('posts', 1, '2026-01-01T00:00:00.000Z')]
|
|
42
|
+
};
|
|
43
|
+
const next = item('posts', '1', '2026-01-02T00:00:00.000Z');
|
|
44
|
+
const result = addRecentlyViewedItem({
|
|
45
|
+
existing,
|
|
46
|
+
item: next
|
|
47
|
+
});
|
|
48
|
+
expect(result.items).toHaveLength(1);
|
|
49
|
+
expect(result.items[0]).toEqual(next);
|
|
50
|
+
});
|
|
51
|
+
it('should not dedupe documents with the same id across different collections', () => {
|
|
52
|
+
const existing = {
|
|
53
|
+
items: [item('posts', 1, '2026-01-01T00:00:00.000Z')]
|
|
54
|
+
};
|
|
55
|
+
const next = item('pages', 1, '2026-01-02T00:00:00.000Z');
|
|
56
|
+
const result = addRecentlyViewedItem({
|
|
57
|
+
existing,
|
|
58
|
+
item: next
|
|
59
|
+
});
|
|
60
|
+
expect(result.items).toHaveLength(2);
|
|
61
|
+
});
|
|
62
|
+
it('should cap the list at the provided max', () => {
|
|
63
|
+
const existing = {
|
|
64
|
+
items: Array.from({
|
|
65
|
+
length: 5
|
|
66
|
+
}, (_, index) => item('posts', index, `2026-01-0${index + 1}T00:00:00.000Z`))
|
|
67
|
+
};
|
|
68
|
+
const next = item('pages', 99, '2026-02-01T00:00:00.000Z');
|
|
69
|
+
const result = addRecentlyViewedItem({
|
|
70
|
+
existing,
|
|
71
|
+
item: next,
|
|
72
|
+
max: 3
|
|
73
|
+
});
|
|
74
|
+
expect(result.items).toHaveLength(3);
|
|
75
|
+
expect(result.items[0]).toEqual(next);
|
|
76
|
+
});
|
|
77
|
+
it('should default the cap to recentlyViewedMaxItems', () => {
|
|
78
|
+
const existing = {
|
|
79
|
+
items: Array.from({
|
|
80
|
+
length: recentlyViewedMaxItems
|
|
81
|
+
}, (_, index) => item('posts', index, '2026-01-01T00:00:00.000Z'))
|
|
82
|
+
};
|
|
83
|
+
const next = item('pages', 99, '2026-02-01T00:00:00.000Z');
|
|
84
|
+
const result = addRecentlyViewedItem({
|
|
85
|
+
existing,
|
|
86
|
+
item: next
|
|
87
|
+
});
|
|
88
|
+
expect(result.items).toHaveLength(recentlyViewedMaxItems);
|
|
89
|
+
expect(result.items[0]).toEqual(next);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
//# sourceMappingURL=recentlyViewed.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recentlyViewed.spec.js","names":["describe","expect","it","addRecentlyViewedItem","recentlyViewedMaxItems","item","collectionSlug","id","viewedAt","next","result","existing","undefined","items","toEqual","map","i","toHaveLength","Array","from","length","_","index","max"],"sources":["../../src/utilities/recentlyViewed.spec.ts"],"sourcesContent":["import type { RecentlyViewedItem } from 'payload'\n\nimport { describe, expect, it } from 'vitest'\n\nimport { addRecentlyViewedItem, recentlyViewedMaxItems } from './recentlyViewed.js'\n\nconst item = (\n collectionSlug: string,\n id: number | string,\n viewedAt: string,\n): RecentlyViewedItem => ({\n collectionSlug,\n id,\n viewedAt,\n})\n\ndescribe('addRecentlyViewedItem', () => {\n it('should create the list when there are no existing preferences', () => {\n const next = item('posts', 1, '2026-01-01T00:00:00.000Z')\n\n const result = addRecentlyViewedItem({ existing: undefined, item: next })\n\n expect(result.items).toEqual([next])\n })\n\n it('should prepend the newly viewed document', () => {\n const existing = { items: [item('posts', 1, '2026-01-01T00:00:00.000Z')] }\n const next = item('pages', 2, '2026-01-02T00:00:00.000Z')\n\n const result = addRecentlyViewedItem({ existing, item: next })\n\n expect(result.items.map((i) => i.id)).toEqual([2, 1])\n })\n\n it('should move an already-viewed document to the front and refresh its timestamp', () => {\n const existing = {\n items: [\n item('pages', 2, '2026-01-02T00:00:00.000Z'),\n item('posts', 1, '2026-01-01T00:00:00.000Z'),\n ],\n }\n const next = item('posts', 1, '2026-01-03T00:00:00.000Z')\n\n const result = addRecentlyViewedItem({ existing, item: next })\n\n expect(result.items).toEqual([next, item('pages', 2, '2026-01-02T00:00:00.000Z')])\n })\n\n it('should treat numeric and string ids consistently when deduping', () => {\n const existing = { items: [item('posts', 1, '2026-01-01T00:00:00.000Z')] }\n const next = item('posts', '1', '2026-01-02T00:00:00.000Z')\n\n const result = addRecentlyViewedItem({ existing, item: next })\n\n expect(result.items).toHaveLength(1)\n expect(result.items[0]).toEqual(next)\n })\n\n it('should not dedupe documents with the same id across different collections', () => {\n const existing = { items: [item('posts', 1, '2026-01-01T00:00:00.000Z')] }\n const next = item('pages', 1, '2026-01-02T00:00:00.000Z')\n\n const result = addRecentlyViewedItem({ existing, item: next })\n\n expect(result.items).toHaveLength(2)\n })\n\n it('should cap the list at the provided max', () => {\n const existing = {\n items: Array.from({ length: 5 }, (_, index) =>\n item('posts', index, `2026-01-0${index + 1}T00:00:00.000Z`),\n ),\n }\n const next = item('pages', 99, '2026-02-01T00:00:00.000Z')\n\n const result = addRecentlyViewedItem({ existing, item: next, max: 3 })\n\n expect(result.items).toHaveLength(3)\n expect(result.items[0]).toEqual(next)\n })\n\n it('should default the cap to recentlyViewedMaxItems', () => {\n const existing = {\n items: Array.from({ length: recentlyViewedMaxItems }, (_, index) =>\n item('posts', index, '2026-01-01T00:00:00.000Z'),\n ),\n }\n const next = item('pages', 99, '2026-02-01T00:00:00.000Z')\n\n const result = addRecentlyViewedItem({ existing, item: next })\n\n expect(result.items).toHaveLength(recentlyViewedMaxItems)\n expect(result.items[0]).toEqual(next)\n })\n})\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/views/Document/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EAEpB,IAAI,EACJ,uBAAuB,EACvB,uBAAuB,EAEvB,iBAAiB,EACjB,gBAAgB,EAChB,gCAAgC,EACjC,MAAM,SAAS,CAAA;AAIhB,OAAO,KAAK,MAAM,OAAO,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/views/Document/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,oBAAoB,EAEpB,IAAI,EACJ,uBAAuB,EACvB,uBAAuB,EAEvB,iBAAiB,EACjB,gBAAgB,EAChB,gCAAgC,EACjC,MAAM,SAAS,CAAA;AAIhB,OAAO,KAAK,MAAM,OAAO,CAAA;AA6BzB,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAEtD,MAAM,MAAM,YAAY,GACpB,iBAAiB,GACjB,gBAAgB,CAAC,uBAAuB,CAAC,GACzC,KAAK,CAAC,EAAE,GACR,KAAK,CAAC,EAAE,CAAC,uBAAuB,CAAC,CAAA;AAErC;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GAAU,0PAgBlC;IACD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wBAAwB,CAAC,EAAE,OAAO,CAAA;IAClC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAA;IACtC,QAAQ,CAAC,mBAAmB,CAAC,EAAE,OAAO,CAAA;IACtC,QAAQ,CAAC,sBAAsB,CAAC,EAAE,OAAO,CAAA;IACzC,QAAQ,CAAC,oBAAoB,CAAC,EAAE,OAAO,CAAA;IACvC,QAAQ,CAAC,EAAE,gCAAgC,CAAA;CAC5C,GAAG,oBAAoB,KAAG,OAAO,CAAC;IACjC,IAAI,EAAE,IAAI,CAAA;IACV,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;CAC1B,CAoZA,CAAA;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,oBAAoB,+QAe7D"}
|
|
@@ -21,6 +21,7 @@ import { getPreferences } from '../../utilities/upsertPreferences.js';
|
|
|
21
21
|
import { NotFoundView } from '../NotFound/index.js';
|
|
22
22
|
import { UnauthorizedViewWithGutter } from '../Unauthorized/index.js';
|
|
23
23
|
import { getDocumentView } from './getDocumentView.js';
|
|
24
|
+
import { recordRecentlyViewed } from './recordRecentlyViewed.js';
|
|
24
25
|
import { renderDocumentSlots } from './renderDocumentSlots.js';
|
|
25
26
|
export { getDocumentView } from './getDocumentView.js';
|
|
26
27
|
/**
|
|
@@ -160,6 +161,13 @@ export const renderDocument = async ({
|
|
|
160
161
|
// get entity preferences
|
|
161
162
|
getPreferences(collectionSlug ? `collection-${collectionSlug}` : `global-${globalSlug}`, payload, req.user.id, req.user.collection)]);
|
|
162
163
|
const operation = collectionSlug && idFromArgs || globalSlug ? 'update' : 'create';
|
|
164
|
+
// Record the document as recently viewed (collections only, never on the create route or for
|
|
165
|
+
// trashed docs). Runs concurrently with the work below and never throws.
|
|
166
|
+
const recentlyViewedPromise = collectionSlug && idFromArgs && doc && !isTrashedDoc ? recordRecentlyViewed({
|
|
167
|
+
id: idFromArgs,
|
|
168
|
+
collectionSlug,
|
|
169
|
+
req
|
|
170
|
+
}) : undefined;
|
|
163
171
|
const [{
|
|
164
172
|
hasPublishedDoc,
|
|
165
173
|
mostRecentVersionIsAutosaved,
|
|
@@ -199,6 +207,7 @@ export const renderDocument = async ({
|
|
|
199
207
|
payload,
|
|
200
208
|
user
|
|
201
209
|
})]);
|
|
210
|
+
await recentlyViewedPromise;
|
|
202
211
|
const documentViewServerProps = {
|
|
203
212
|
doc,
|
|
204
213
|
hasPublishedDoc,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["isolateObjectProperty","logError","formatAdminURL","hasAutosaveEnabled","hasDraftsEnabled","React","DocumentHeader","RenderServerComponent","DocumentInfoProvider","EditDepthProvider","HydrateAuthProvider","LivePreviewProvider","buildFormState","getDocPreferences","getDocumentData","getDocumentPermissions","getHasScheduledPublish","getIsLocked","getVersions","handleLivePreview","handlePreview","isEditing","getIsEditing","getPreferences","NotFoundView","UnauthorizedViewWithGutter","getDocumentView","renderDocumentSlots","renderDocument","disableActions","documentSubViewType","drawerSlug","importMap","initialData","initPageResult","overrideEntityVisibility","params","redirectAfterCreate","redirectAfterDelete","redirectAfterDuplicate","redirectAfterRestore","searchParams","versions","viewType","collectionConfig","docID","idFromArgs","globalConfig","locale","permissions","req","i18n","payload","config","routes","admin","adminRoute","api","apiRoute","user","visibleEntities","segments","Array","isArray","collectionSlug","slug","undefined","globalSlug","id","doc","redirectURL","path","encodeURIComponent","server","redirect","Error","isTrashedDoc","Boolean","deletedAt","reqForPermissions","transactionID","reqForLockCheck","docPreferences","docPermissions","hasDeletePermission","hasPublishPermission","hasSavePermission","hasTrashPermission","currentEditor","isLocked","lastUpdateTime","entityPreferences","Promise","all","data","collection","operation","hasPublishedDoc","mostRecentVersionIsAutosaved","unpublishedVersionCount","versionCount","state","formState","hasScheduledPublish","code","fallbackLocale","readOnly","renderAllFields","schemaPath","skipValidation","documentViewServerProps","routeSegments","collections","find","visibleSlug","globals","formattedParams","URLSearchParams","append","apiQueryParams","toString","apiURL","View","showHeader","RootViewOverride","components","views","edit","root","Component","shouldAutosave","validateDraftData","drafts","validate","create","depth","draft","documentSlots","Description","clientProps","isLivePreviewEnabled","livePreviewConfig","livePreviewURL","isPreviewEnabled","previewURL","Document","_jsx","initialState","isTrashed","_jsxs","breakpoints","isLivePreviewing","value","editViewType","typeofLivePreviewURL","url","AfterHeader","serverProps","DocumentView","props","RenderedDocument","error","message","err","notFound"],"sources":["../../../src/views/Document/index.tsx"],"sourcesContent":["import type {\n AdminViewServerProps,\n CollectionPreferences,\n Data,\n DocumentViewClientProps,\n DocumentViewServerProps,\n DocumentViewServerPropsOnly,\n EditViewComponent,\n PayloadComponent,\n RenderDocumentVersionsProperties,\n} from 'payload'\n\nimport { isolateObjectProperty, logError } from 'payload'\nimport { formatAdminURL, hasAutosaveEnabled, hasDraftsEnabled } from 'payload/shared'\nimport React from 'react'\n\nimport { DocumentHeader } from '../../elements/DocumentHeader/index.js'\nimport { RenderServerComponent } from '../../elements/RenderServerComponent/index.js'\n/* eslint-disable payload/no-imports-from-exports-dir -- Server component must reference exports/client bundle for proper client boundary in prod builds */\nimport {\n DocumentInfoProvider,\n EditDepthProvider,\n HydrateAuthProvider,\n LivePreviewProvider,\n} from '../../exports/client/index.js'\n/* eslint-enable payload/no-imports-from-exports-dir */\nimport { buildFormState } from '../../utilities/buildFormState.js'\nimport { getDocPreferences } from '../../utilities/getDocPreferences.js'\nimport { getDocumentData } from '../../utilities/getDocumentData.js'\nimport { getDocumentPermissions } from '../../utilities/getDocumentPermissions.js'\nimport { getHasScheduledPublish } from '../../utilities/getHasScheduledPublish.js'\nimport { getIsLocked } from '../../utilities/getIsLocked.js'\nimport { getVersions } from '../../utilities/getVersions.js'\nimport { handleLivePreview } from '../../utilities/handleLivePreview.js'\nimport { handlePreview } from '../../utilities/handlePreview.js'\nimport { isEditing as getIsEditing } from '../../utilities/isEditing.js'\nimport { getPreferences } from '../../utilities/upsertPreferences.js'\nimport { NotFoundView } from '../NotFound/index.js'\nimport { UnauthorizedViewWithGutter } from '../Unauthorized/index.js'\nimport { getDocumentView } from './getDocumentView.js'\nimport { renderDocumentSlots } from './renderDocumentSlots.js'\n\nexport { getDocumentView } from './getDocumentView.js'\n\nexport type ViewToRender =\n | EditViewComponent\n | PayloadComponent<DocumentViewServerProps>\n | React.FC\n | React.FC<DocumentViewClientProps>\n\n/**\n * This function is responsible for rendering\n * an Edit Document view on the server for both:\n * - default document edit views\n * - on-demand edit views within drawers\n */\nexport const renderDocument = async ({\n disableActions,\n documentSubViewType,\n drawerSlug,\n importMap,\n initialData,\n initPageResult,\n overrideEntityVisibility,\n params,\n redirectAfterCreate,\n redirectAfterDelete,\n redirectAfterDuplicate,\n redirectAfterRestore,\n searchParams,\n versions,\n viewType,\n}: {\n drawerSlug?: string\n overrideEntityVisibility?: boolean\n readonly redirectAfterCreate?: boolean\n readonly redirectAfterDelete?: boolean\n readonly redirectAfterDuplicate?: boolean\n readonly redirectAfterRestore?: boolean\n versions?: RenderDocumentVersionsProperties\n} & AdminViewServerProps): Promise<{\n data: Data\n Document: React.ReactNode\n}> => {\n const {\n collectionConfig,\n docID: idFromArgs,\n globalConfig,\n locale,\n permissions,\n req,\n req: {\n i18n,\n payload,\n payload: {\n config,\n config: {\n routes: { admin: adminRoute, api: apiRoute },\n },\n },\n user,\n },\n visibleEntities,\n } = initPageResult\n\n const segments = Array.isArray(params?.segments) ? params.segments : []\n const collectionSlug = collectionConfig?.slug || undefined\n const globalSlug = globalConfig?.slug || undefined\n let isEditing = getIsEditing({ id: idFromArgs, collectionSlug, globalSlug })\n\n // Fetch the doc required for the view\n let doc =\n !idFromArgs && !globalSlug\n ? initialData || null\n : await getDocumentData({\n id: idFromArgs,\n collectionSlug,\n globalSlug,\n locale,\n payload,\n req,\n segments,\n user,\n })\n\n if (isEditing && !doc) {\n // If it's a collection document that doesn't exist, redirect to collection list\n if (collectionSlug) {\n const redirectURL = formatAdminURL({\n adminRoute,\n path: `/collections/${collectionSlug}?notFound=${encodeURIComponent(idFromArgs)}`,\n })\n req.server.redirect(redirectURL)\n } else {\n // For globals or other cases, keep the 404 behavior\n throw new Error('not-found')\n }\n }\n\n const isTrashedDoc = Boolean(doc && 'deletedAt' in doc && typeof doc?.deletedAt === 'string')\n\n // CRITICAL FIX FOR TRANSACTION RACE CONDITION:\n // When running parallel operations with Promise.all, if they share the same req object\n // and one operation calls initTransaction() which MUTATES req.transactionID, that mutation\n // is visible to all parallel operations. This causes:\n // 1. Operation A (e.g., getDocumentPermissions → docAccessOperation) calls initTransaction()\n // which sets req.transactionID = Promise, then resolves it to a UUID\n // 2. Operation B (e.g., getIsLocked) running in parallel receives the SAME req with the mutated transactionID\n // 3. Operation A (does not even know that Operation B even exists and is stil using the transactionID) commits/ends its transaction\n // 4. Operation B tries to use the now-expired session → MongoExpiredSessionError!\n //\n // Solution: Use isolateObjectProperty to create a Proxy that isolates the 'transactionID' property.\n // This allows each operation to have its own transactionID without affecting the parent req.\n // If parent req already has a transaction, preserve it (don't isolate), since this\n // issue only arises when one of the operations calls initTransaction() themselves -\n // because then, that operation will also try to commit/end the transaction itself.\n\n // If the transactionID is already set, the parallel operations will not try to\n // commit/end the transaction themselves, so we don't need to isolate the\n // transactionID property.\n const reqForPermissions = req.transactionID ? req : isolateObjectProperty(req, 'transactionID')\n const reqForLockCheck = req.transactionID ? req : isolateObjectProperty(req, 'transactionID')\n\n const [\n docPreferences,\n {\n docPermissions,\n hasDeletePermission,\n hasPublishPermission,\n hasSavePermission,\n hasTrashPermission,\n },\n { currentEditor, isLocked, lastUpdateTime },\n entityPreferences,\n ] = await Promise.all([\n // Get document preferences\n getDocPreferences({\n id: idFromArgs,\n collectionSlug,\n globalSlug,\n payload,\n user,\n }),\n\n // Get permissions - isolated transactionID prevents cross-contamination\n getDocumentPermissions({\n id: idFromArgs,\n collectionConfig,\n data: doc,\n globalConfig,\n req: reqForPermissions,\n }),\n\n // Fetch document lock state - isolated transactionID prevents cross-contamination\n getIsLocked({\n id: idFromArgs,\n collectionConfig,\n globalConfig,\n isEditing,\n req: reqForLockCheck,\n }),\n\n // get entity preferences\n getPreferences<CollectionPreferences>(\n collectionSlug ? `collection-${collectionSlug}` : `global-${globalSlug}`,\n payload,\n req.user.id,\n req.user.collection,\n ),\n ])\n\n const operation = (collectionSlug && idFromArgs) || globalSlug ? 'update' : 'create'\n\n const [\n { hasPublishedDoc, mostRecentVersionIsAutosaved, unpublishedVersionCount, versionCount },\n { state: formState },\n hasScheduledPublish,\n ] = await Promise.all([\n getVersions({\n id: idFromArgs,\n collectionConfig,\n doc,\n docPermissions,\n globalConfig,\n locale: locale?.code,\n payload,\n user,\n }),\n buildFormState({\n id: idFromArgs,\n collectionSlug,\n data: doc,\n docPermissions,\n docPreferences,\n fallbackLocale: false,\n globalSlug,\n locale: locale?.code,\n operation,\n readOnly: isTrashedDoc || isLocked,\n renderAllFields: true,\n req,\n schemaPath: collectionSlug || globalSlug,\n skipValidation: true,\n }),\n getHasScheduledPublish({\n id: idFromArgs,\n collectionConfig,\n globalConfig,\n hasPublishPermission,\n payload,\n user,\n }),\n ])\n\n const documentViewServerProps: DocumentViewServerPropsOnly = {\n doc,\n hasPublishedDoc,\n i18n,\n initPageResult,\n locale,\n params,\n payload,\n permissions,\n routeSegments: segments,\n searchParams,\n server: req.server,\n user,\n versions,\n }\n\n if (\n !overrideEntityVisibility &&\n ((collectionSlug &&\n !visibleEntities?.collections?.find((visibleSlug) => visibleSlug === collectionSlug)) ||\n (globalSlug && !visibleEntities?.globals?.find((visibleSlug) => visibleSlug === globalSlug)))\n ) {\n throw new Error('not-found')\n }\n\n const formattedParams = new URLSearchParams()\n\n if (hasDraftsEnabled(collectionConfig || globalConfig)) {\n formattedParams.append('draft', 'true')\n }\n\n if (locale?.code) {\n formattedParams.append('locale', locale.code)\n }\n\n const apiQueryParams = `?${formattedParams.toString()}`\n\n const apiURL = formatAdminURL({\n apiRoute,\n path: collectionSlug\n ? `/${collectionSlug}/${idFromArgs}${apiQueryParams}`\n : globalSlug\n ? `/${globalSlug}${apiQueryParams}`\n : '',\n })\n\n let View: ViewToRender = null\n\n let showHeader = true\n\n const RootViewOverride =\n collectionConfig?.admin?.components?.views?.edit?.root &&\n 'Component' in collectionConfig.admin.components.views.edit.root\n ? collectionConfig?.admin?.components?.views?.edit?.root?.Component\n : globalConfig?.admin?.components?.views?.edit?.root &&\n 'Component' in globalConfig.admin.components.views.edit.root\n ? globalConfig?.admin?.components?.views?.edit?.root?.Component\n : null\n\n if (RootViewOverride) {\n View = RootViewOverride\n showHeader = false\n } else {\n ;({ View } = getDocumentView({\n collectionConfig,\n config,\n docPermissions,\n globalConfig,\n routeSegments: segments,\n }))\n\n if (View === UnauthorizedViewWithGutter) {\n showHeader = false\n }\n }\n\n if (!View) {\n View = NotFoundView as React.FC<AdminViewServerProps>\n }\n\n /**\n * Handle case where autoSave is enabled and the document is being created\n * => create document and redirect\n */\n const shouldAutosave = hasSavePermission && hasAutosaveEnabled(collectionConfig || globalConfig)\n\n const validateDraftData =\n collectionConfig?.versions?.drafts && collectionConfig?.versions?.drafts?.validate\n\n let id = idFromArgs\n\n if (shouldAutosave && !validateDraftData && !idFromArgs && collectionSlug) {\n doc = await payload.create({\n collection: collectionSlug,\n data: initialData || {},\n depth: 0,\n draft: true,\n fallbackLocale: false,\n locale: locale?.code,\n req,\n user,\n })\n\n if (doc?.id) {\n id = doc.id\n isEditing = getIsEditing({ id: doc.id, collectionSlug, globalSlug })\n\n if (!drawerSlug && redirectAfterCreate !== false) {\n const redirectURL = formatAdminURL({\n adminRoute,\n path: `/collections/${collectionSlug}/${doc.id}`,\n })\n\n req.server.redirect(redirectURL)\n }\n } else {\n throw new Error('not-found')\n }\n }\n\n const documentSlots = renderDocumentSlots({\n id,\n collectionConfig,\n doc: doc as Record<string, unknown>,\n globalConfig,\n hasSavePermission,\n locale,\n permissions,\n req,\n })\n\n // Extract Description from documentSlots to pass to DocumentHeader\n const { Description } = documentSlots\n\n const clientProps: DocumentViewClientProps = {\n formState,\n ...documentSlots,\n documentSubViewType,\n viewType,\n }\n\n const { isLivePreviewEnabled, livePreviewConfig, livePreviewURL } = await handleLivePreview({\n collectionSlug,\n config,\n data: doc,\n globalSlug,\n operation,\n req,\n })\n\n const { isPreviewEnabled, previewURL } = await handlePreview({\n collectionSlug,\n config,\n data: doc,\n globalSlug,\n operation,\n req,\n })\n\n return {\n data: doc,\n Document: (\n <DocumentInfoProvider\n apiURL={apiURL}\n collectionSlug={collectionConfig?.slug}\n currentEditor={currentEditor}\n disableActions={disableActions ?? false}\n docPermissions={docPermissions}\n globalSlug={globalConfig?.slug}\n hasDeletePermission={hasDeletePermission}\n hasPublishedDoc={hasPublishedDoc}\n hasPublishPermission={hasPublishPermission}\n hasSavePermission={hasSavePermission}\n hasScheduledPublish={hasScheduledPublish}\n hasTrashPermission={hasTrashPermission}\n id={id}\n initialData={doc}\n initialState={formState}\n isEditing={isEditing}\n isLocked={isLocked}\n isTrashed={isTrashedDoc}\n key={locale?.code}\n lastUpdateTime={lastUpdateTime}\n mostRecentVersionIsAutosaved={mostRecentVersionIsAutosaved}\n redirectAfterCreate={redirectAfterCreate}\n redirectAfterDelete={redirectAfterDelete}\n redirectAfterDuplicate={redirectAfterDuplicate}\n redirectAfterRestore={redirectAfterRestore}\n unpublishedVersionCount={unpublishedVersionCount}\n versionCount={versionCount}\n >\n <LivePreviewProvider\n breakpoints={livePreviewConfig?.breakpoints}\n isLivePreviewEnabled={isLivePreviewEnabled && operation !== 'create'}\n isLivePreviewing={Boolean(\n entityPreferences?.value?.editViewType === 'live-preview' && livePreviewURL,\n )}\n isPreviewEnabled={Boolean(isPreviewEnabled)}\n previewURL={previewURL}\n typeofLivePreviewURL={typeof livePreviewConfig?.url as 'function' | 'string' | undefined}\n url={livePreviewURL}\n >\n {showHeader && !drawerSlug && (\n <DocumentHeader\n AfterHeader={Description}\n collectionConfig={collectionConfig}\n globalConfig={globalConfig}\n permissions={permissions}\n req={req}\n />\n )}\n <HydrateAuthProvider permissions={permissions} />\n <EditDepthProvider>\n {RenderServerComponent({\n clientProps,\n Component: View,\n importMap,\n serverProps: documentViewServerProps,\n })}\n </EditDepthProvider>\n </LivePreviewProvider>\n </DocumentInfoProvider>\n ),\n }\n}\n\nexport async function DocumentView(props: AdminViewServerProps) {\n try {\n const { Document: RenderedDocument } = await renderDocument(props)\n return RenderedDocument\n } catch (error) {\n if (error?.message === 'NEXT_REDIRECT') {\n throw error\n }\n\n logError({ err: error, payload: props.initPageResult.req.payload })\n\n if (error.message === 'not-found') {\n props.initPageResult.req.server.notFound()\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
1
|
+
{"version":3,"file":"index.js","names":["isolateObjectProperty","logError","formatAdminURL","hasAutosaveEnabled","hasDraftsEnabled","React","DocumentHeader","RenderServerComponent","DocumentInfoProvider","EditDepthProvider","HydrateAuthProvider","LivePreviewProvider","buildFormState","getDocPreferences","getDocumentData","getDocumentPermissions","getHasScheduledPublish","getIsLocked","getVersions","handleLivePreview","handlePreview","isEditing","getIsEditing","getPreferences","NotFoundView","UnauthorizedViewWithGutter","getDocumentView","recordRecentlyViewed","renderDocumentSlots","renderDocument","disableActions","documentSubViewType","drawerSlug","importMap","initialData","initPageResult","overrideEntityVisibility","params","redirectAfterCreate","redirectAfterDelete","redirectAfterDuplicate","redirectAfterRestore","searchParams","versions","viewType","collectionConfig","docID","idFromArgs","globalConfig","locale","permissions","req","i18n","payload","config","routes","admin","adminRoute","api","apiRoute","user","visibleEntities","segments","Array","isArray","collectionSlug","slug","undefined","globalSlug","id","doc","redirectURL","path","encodeURIComponent","server","redirect","Error","isTrashedDoc","Boolean","deletedAt","reqForPermissions","transactionID","reqForLockCheck","docPreferences","docPermissions","hasDeletePermission","hasPublishPermission","hasSavePermission","hasTrashPermission","currentEditor","isLocked","lastUpdateTime","entityPreferences","Promise","all","data","collection","operation","recentlyViewedPromise","hasPublishedDoc","mostRecentVersionIsAutosaved","unpublishedVersionCount","versionCount","state","formState","hasScheduledPublish","code","fallbackLocale","readOnly","renderAllFields","schemaPath","skipValidation","documentViewServerProps","routeSegments","collections","find","visibleSlug","globals","formattedParams","URLSearchParams","append","apiQueryParams","toString","apiURL","View","showHeader","RootViewOverride","components","views","edit","root","Component","shouldAutosave","validateDraftData","drafts","validate","create","depth","draft","documentSlots","Description","clientProps","isLivePreviewEnabled","livePreviewConfig","livePreviewURL","isPreviewEnabled","previewURL","Document","_jsx","initialState","isTrashed","_jsxs","breakpoints","isLivePreviewing","value","editViewType","typeofLivePreviewURL","url","AfterHeader","serverProps","DocumentView","props","RenderedDocument","error","message","err","notFound"],"sources":["../../../src/views/Document/index.tsx"],"sourcesContent":["import type {\n AdminViewServerProps,\n CollectionPreferences,\n Data,\n DocumentViewClientProps,\n DocumentViewServerProps,\n DocumentViewServerPropsOnly,\n EditViewComponent,\n PayloadComponent,\n RenderDocumentVersionsProperties,\n} from 'payload'\n\nimport { isolateObjectProperty, logError } from 'payload'\nimport { formatAdminURL, hasAutosaveEnabled, hasDraftsEnabled } from 'payload/shared'\nimport React from 'react'\n\nimport { DocumentHeader } from '../../elements/DocumentHeader/index.js'\nimport { RenderServerComponent } from '../../elements/RenderServerComponent/index.js'\n/* eslint-disable payload/no-imports-from-exports-dir -- Server component must reference exports/client bundle for proper client boundary in prod builds */\nimport {\n DocumentInfoProvider,\n EditDepthProvider,\n HydrateAuthProvider,\n LivePreviewProvider,\n} from '../../exports/client/index.js'\n/* eslint-enable payload/no-imports-from-exports-dir */\nimport { buildFormState } from '../../utilities/buildFormState.js'\nimport { getDocPreferences } from '../../utilities/getDocPreferences.js'\nimport { getDocumentData } from '../../utilities/getDocumentData.js'\nimport { getDocumentPermissions } from '../../utilities/getDocumentPermissions.js'\nimport { getHasScheduledPublish } from '../../utilities/getHasScheduledPublish.js'\nimport { getIsLocked } from '../../utilities/getIsLocked.js'\nimport { getVersions } from '../../utilities/getVersions.js'\nimport { handleLivePreview } from '../../utilities/handleLivePreview.js'\nimport { handlePreview } from '../../utilities/handlePreview.js'\nimport { isEditing as getIsEditing } from '../../utilities/isEditing.js'\nimport { getPreferences } from '../../utilities/upsertPreferences.js'\nimport { NotFoundView } from '../NotFound/index.js'\nimport { UnauthorizedViewWithGutter } from '../Unauthorized/index.js'\nimport { getDocumentView } from './getDocumentView.js'\nimport { recordRecentlyViewed } from './recordRecentlyViewed.js'\nimport { renderDocumentSlots } from './renderDocumentSlots.js'\n\nexport { getDocumentView } from './getDocumentView.js'\n\nexport type ViewToRender =\n | EditViewComponent\n | PayloadComponent<DocumentViewServerProps>\n | React.FC\n | React.FC<DocumentViewClientProps>\n\n/**\n * This function is responsible for rendering\n * an Edit Document view on the server for both:\n * - default document edit views\n * - on-demand edit views within drawers\n */\nexport const renderDocument = async ({\n disableActions,\n documentSubViewType,\n drawerSlug,\n importMap,\n initialData,\n initPageResult,\n overrideEntityVisibility,\n params,\n redirectAfterCreate,\n redirectAfterDelete,\n redirectAfterDuplicate,\n redirectAfterRestore,\n searchParams,\n versions,\n viewType,\n}: {\n drawerSlug?: string\n overrideEntityVisibility?: boolean\n readonly redirectAfterCreate?: boolean\n readonly redirectAfterDelete?: boolean\n readonly redirectAfterDuplicate?: boolean\n readonly redirectAfterRestore?: boolean\n versions?: RenderDocumentVersionsProperties\n} & AdminViewServerProps): Promise<{\n data: Data\n Document: React.ReactNode\n}> => {\n const {\n collectionConfig,\n docID: idFromArgs,\n globalConfig,\n locale,\n permissions,\n req,\n req: {\n i18n,\n payload,\n payload: {\n config,\n config: {\n routes: { admin: adminRoute, api: apiRoute },\n },\n },\n user,\n },\n visibleEntities,\n } = initPageResult\n\n const segments = Array.isArray(params?.segments) ? params.segments : []\n const collectionSlug = collectionConfig?.slug || undefined\n const globalSlug = globalConfig?.slug || undefined\n let isEditing = getIsEditing({ id: idFromArgs, collectionSlug, globalSlug })\n\n // Fetch the doc required for the view\n let doc =\n !idFromArgs && !globalSlug\n ? initialData || null\n : await getDocumentData({\n id: idFromArgs,\n collectionSlug,\n globalSlug,\n locale,\n payload,\n req,\n segments,\n user,\n })\n\n if (isEditing && !doc) {\n // If it's a collection document that doesn't exist, redirect to collection list\n if (collectionSlug) {\n const redirectURL = formatAdminURL({\n adminRoute,\n path: `/collections/${collectionSlug}?notFound=${encodeURIComponent(idFromArgs)}`,\n })\n req.server.redirect(redirectURL)\n } else {\n // For globals or other cases, keep the 404 behavior\n throw new Error('not-found')\n }\n }\n\n const isTrashedDoc = Boolean(doc && 'deletedAt' in doc && typeof doc?.deletedAt === 'string')\n\n // CRITICAL FIX FOR TRANSACTION RACE CONDITION:\n // When running parallel operations with Promise.all, if they share the same req object\n // and one operation calls initTransaction() which MUTATES req.transactionID, that mutation\n // is visible to all parallel operations. This causes:\n // 1. Operation A (e.g., getDocumentPermissions → docAccessOperation) calls initTransaction()\n // which sets req.transactionID = Promise, then resolves it to a UUID\n // 2. Operation B (e.g., getIsLocked) running in parallel receives the SAME req with the mutated transactionID\n // 3. Operation A (does not even know that Operation B even exists and is stil using the transactionID) commits/ends its transaction\n // 4. Operation B tries to use the now-expired session → MongoExpiredSessionError!\n //\n // Solution: Use isolateObjectProperty to create a Proxy that isolates the 'transactionID' property.\n // This allows each operation to have its own transactionID without affecting the parent req.\n // If parent req already has a transaction, preserve it (don't isolate), since this\n // issue only arises when one of the operations calls initTransaction() themselves -\n // because then, that operation will also try to commit/end the transaction itself.\n\n // If the transactionID is already set, the parallel operations will not try to\n // commit/end the transaction themselves, so we don't need to isolate the\n // transactionID property.\n const reqForPermissions = req.transactionID ? req : isolateObjectProperty(req, 'transactionID')\n const reqForLockCheck = req.transactionID ? req : isolateObjectProperty(req, 'transactionID')\n\n const [\n docPreferences,\n {\n docPermissions,\n hasDeletePermission,\n hasPublishPermission,\n hasSavePermission,\n hasTrashPermission,\n },\n { currentEditor, isLocked, lastUpdateTime },\n entityPreferences,\n ] = await Promise.all([\n // Get document preferences\n getDocPreferences({\n id: idFromArgs,\n collectionSlug,\n globalSlug,\n payload,\n user,\n }),\n\n // Get permissions - isolated transactionID prevents cross-contamination\n getDocumentPermissions({\n id: idFromArgs,\n collectionConfig,\n data: doc,\n globalConfig,\n req: reqForPermissions,\n }),\n\n // Fetch document lock state - isolated transactionID prevents cross-contamination\n getIsLocked({\n id: idFromArgs,\n collectionConfig,\n globalConfig,\n isEditing,\n req: reqForLockCheck,\n }),\n\n // get entity preferences\n getPreferences<CollectionPreferences>(\n collectionSlug ? `collection-${collectionSlug}` : `global-${globalSlug}`,\n payload,\n req.user.id,\n req.user.collection,\n ),\n ])\n\n const operation = (collectionSlug && idFromArgs) || globalSlug ? 'update' : 'create'\n\n // Record the document as recently viewed (collections only, never on the create route or for\n // trashed docs). Runs concurrently with the work below and never throws.\n const recentlyViewedPromise =\n collectionSlug && idFromArgs && doc && !isTrashedDoc\n ? recordRecentlyViewed({ id: idFromArgs, collectionSlug, req })\n : undefined\n\n const [\n { hasPublishedDoc, mostRecentVersionIsAutosaved, unpublishedVersionCount, versionCount },\n { state: formState },\n hasScheduledPublish,\n ] = await Promise.all([\n getVersions({\n id: idFromArgs,\n collectionConfig,\n doc,\n docPermissions,\n globalConfig,\n locale: locale?.code,\n payload,\n user,\n }),\n buildFormState({\n id: idFromArgs,\n collectionSlug,\n data: doc,\n docPermissions,\n docPreferences,\n fallbackLocale: false,\n globalSlug,\n locale: locale?.code,\n operation,\n readOnly: isTrashedDoc || isLocked,\n renderAllFields: true,\n req,\n schemaPath: collectionSlug || globalSlug,\n skipValidation: true,\n }),\n getHasScheduledPublish({\n id: idFromArgs,\n collectionConfig,\n globalConfig,\n hasPublishPermission,\n payload,\n user,\n }),\n ])\n\n await recentlyViewedPromise\n\n const documentViewServerProps: DocumentViewServerPropsOnly = {\n doc,\n hasPublishedDoc,\n i18n,\n initPageResult,\n locale,\n params,\n payload,\n permissions,\n routeSegments: segments,\n searchParams,\n server: req.server,\n user,\n versions,\n }\n\n if (\n !overrideEntityVisibility &&\n ((collectionSlug &&\n !visibleEntities?.collections?.find((visibleSlug) => visibleSlug === collectionSlug)) ||\n (globalSlug && !visibleEntities?.globals?.find((visibleSlug) => visibleSlug === globalSlug)))\n ) {\n throw new Error('not-found')\n }\n\n const formattedParams = new URLSearchParams()\n\n if (hasDraftsEnabled(collectionConfig || globalConfig)) {\n formattedParams.append('draft', 'true')\n }\n\n if (locale?.code) {\n formattedParams.append('locale', locale.code)\n }\n\n const apiQueryParams = `?${formattedParams.toString()}`\n\n const apiURL = formatAdminURL({\n apiRoute,\n path: collectionSlug\n ? `/${collectionSlug}/${idFromArgs}${apiQueryParams}`\n : globalSlug\n ? `/${globalSlug}${apiQueryParams}`\n : '',\n })\n\n let View: ViewToRender = null\n\n let showHeader = true\n\n const RootViewOverride =\n collectionConfig?.admin?.components?.views?.edit?.root &&\n 'Component' in collectionConfig.admin.components.views.edit.root\n ? collectionConfig?.admin?.components?.views?.edit?.root?.Component\n : globalConfig?.admin?.components?.views?.edit?.root &&\n 'Component' in globalConfig.admin.components.views.edit.root\n ? globalConfig?.admin?.components?.views?.edit?.root?.Component\n : null\n\n if (RootViewOverride) {\n View = RootViewOverride\n showHeader = false\n } else {\n ;({ View } = getDocumentView({\n collectionConfig,\n config,\n docPermissions,\n globalConfig,\n routeSegments: segments,\n }))\n\n if (View === UnauthorizedViewWithGutter) {\n showHeader = false\n }\n }\n\n if (!View) {\n View = NotFoundView as React.FC<AdminViewServerProps>\n }\n\n /**\n * Handle case where autoSave is enabled and the document is being created\n * => create document and redirect\n */\n const shouldAutosave = hasSavePermission && hasAutosaveEnabled(collectionConfig || globalConfig)\n\n const validateDraftData =\n collectionConfig?.versions?.drafts && collectionConfig?.versions?.drafts?.validate\n\n let id = idFromArgs\n\n if (shouldAutosave && !validateDraftData && !idFromArgs && collectionSlug) {\n doc = await payload.create({\n collection: collectionSlug,\n data: initialData || {},\n depth: 0,\n draft: true,\n fallbackLocale: false,\n locale: locale?.code,\n req,\n user,\n })\n\n if (doc?.id) {\n id = doc.id\n isEditing = getIsEditing({ id: doc.id, collectionSlug, globalSlug })\n\n if (!drawerSlug && redirectAfterCreate !== false) {\n const redirectURL = formatAdminURL({\n adminRoute,\n path: `/collections/${collectionSlug}/${doc.id}`,\n })\n\n req.server.redirect(redirectURL)\n }\n } else {\n throw new Error('not-found')\n }\n }\n\n const documentSlots = renderDocumentSlots({\n id,\n collectionConfig,\n doc: doc as Record<string, unknown>,\n globalConfig,\n hasSavePermission,\n locale,\n permissions,\n req,\n })\n\n // Extract Description from documentSlots to pass to DocumentHeader\n const { Description } = documentSlots\n\n const clientProps: DocumentViewClientProps = {\n formState,\n ...documentSlots,\n documentSubViewType,\n viewType,\n }\n\n const { isLivePreviewEnabled, livePreviewConfig, livePreviewURL } = await handleLivePreview({\n collectionSlug,\n config,\n data: doc,\n globalSlug,\n operation,\n req,\n })\n\n const { isPreviewEnabled, previewURL } = await handlePreview({\n collectionSlug,\n config,\n data: doc,\n globalSlug,\n operation,\n req,\n })\n\n return {\n data: doc,\n Document: (\n <DocumentInfoProvider\n apiURL={apiURL}\n collectionSlug={collectionConfig?.slug}\n currentEditor={currentEditor}\n disableActions={disableActions ?? false}\n docPermissions={docPermissions}\n globalSlug={globalConfig?.slug}\n hasDeletePermission={hasDeletePermission}\n hasPublishedDoc={hasPublishedDoc}\n hasPublishPermission={hasPublishPermission}\n hasSavePermission={hasSavePermission}\n hasScheduledPublish={hasScheduledPublish}\n hasTrashPermission={hasTrashPermission}\n id={id}\n initialData={doc}\n initialState={formState}\n isEditing={isEditing}\n isLocked={isLocked}\n isTrashed={isTrashedDoc}\n key={locale?.code}\n lastUpdateTime={lastUpdateTime}\n mostRecentVersionIsAutosaved={mostRecentVersionIsAutosaved}\n redirectAfterCreate={redirectAfterCreate}\n redirectAfterDelete={redirectAfterDelete}\n redirectAfterDuplicate={redirectAfterDuplicate}\n redirectAfterRestore={redirectAfterRestore}\n unpublishedVersionCount={unpublishedVersionCount}\n versionCount={versionCount}\n >\n <LivePreviewProvider\n breakpoints={livePreviewConfig?.breakpoints}\n isLivePreviewEnabled={isLivePreviewEnabled && operation !== 'create'}\n isLivePreviewing={Boolean(\n entityPreferences?.value?.editViewType === 'live-preview' && livePreviewURL,\n )}\n isPreviewEnabled={Boolean(isPreviewEnabled)}\n previewURL={previewURL}\n typeofLivePreviewURL={typeof livePreviewConfig?.url as 'function' | 'string' | undefined}\n url={livePreviewURL}\n >\n {showHeader && !drawerSlug && (\n <DocumentHeader\n AfterHeader={Description}\n collectionConfig={collectionConfig}\n globalConfig={globalConfig}\n permissions={permissions}\n req={req}\n />\n )}\n <HydrateAuthProvider permissions={permissions} />\n <EditDepthProvider>\n {RenderServerComponent({\n clientProps,\n Component: View,\n importMap,\n serverProps: documentViewServerProps,\n })}\n </EditDepthProvider>\n </LivePreviewProvider>\n </DocumentInfoProvider>\n ),\n }\n}\n\nexport async function DocumentView(props: AdminViewServerProps) {\n try {\n const { Document: RenderedDocument } = await renderDocument(props)\n return RenderedDocument\n } catch (error) {\n if (error?.message === 'NEXT_REDIRECT') {\n throw error\n }\n\n logError({ err: error, payload: props.initPageResult.req.payload })\n\n if (error.message === 'not-found') {\n props.initPageResult.req.server.notFound()\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PayloadRequest } from 'payload';
|
|
2
|
+
/**
|
|
3
|
+
* Records that the current user viewed a collection document, persisting it to the
|
|
4
|
+
* `recently-viewed` preference. The document is loaded with access control before this runs, so
|
|
5
|
+
* reaching here means the user can read it. Never throws: a failed write must not break the view.
|
|
6
|
+
*/
|
|
7
|
+
export declare const recordRecentlyViewed: ({ id, collectionSlug, req, }: {
|
|
8
|
+
collectionSlug: string;
|
|
9
|
+
id: number | string;
|
|
10
|
+
req: PayloadRequest;
|
|
11
|
+
}) => Promise<void>;
|
|
12
|
+
//# sourceMappingURL=recordRecentlyViewed.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recordRecentlyViewed.d.ts","sourceRoot":"","sources":["../../../src/views/Document/recordRecentlyViewed.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAA6B,MAAM,SAAS,CAAA;AAOxE;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,GAAU,8BAIxC;IACD,cAAc,EAAE,MAAM,CAAA;IACtB,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,GAAG,EAAE,cAAc,CAAA;CACpB,KAAG,OAAO,CAAC,IAAI,CAmBf,CAAA"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { PREFERENCE_KEYS } from 'payload/shared';
|
|
2
|
+
import { addRecentlyViewedItem } from '../../utilities/recentlyViewed.js';
|
|
3
|
+
import { upsertPreferences } from '../../utilities/upsertPreferences.js';
|
|
4
|
+
/**
|
|
5
|
+
* Records that the current user viewed a collection document, persisting it to the
|
|
6
|
+
* `recently-viewed` preference. The document is loaded with access control before this runs, so
|
|
7
|
+
* reaching here means the user can read it. Never throws: a failed write must not break the view.
|
|
8
|
+
*/
|
|
9
|
+
export const recordRecentlyViewed = async ({
|
|
10
|
+
id,
|
|
11
|
+
collectionSlug,
|
|
12
|
+
req
|
|
13
|
+
}) => {
|
|
14
|
+
if (!req.user) {
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
try {
|
|
18
|
+
await upsertPreferences({
|
|
19
|
+
customMerge: (existingValue, incomingValue) => addRecentlyViewedItem({
|
|
20
|
+
existing: existingValue,
|
|
21
|
+
item: incomingValue.items[0]
|
|
22
|
+
}),
|
|
23
|
+
key: PREFERENCE_KEYS.RECENTLY_VIEWED,
|
|
24
|
+
req,
|
|
25
|
+
value: {
|
|
26
|
+
items: [{
|
|
27
|
+
id,
|
|
28
|
+
collectionSlug,
|
|
29
|
+
viewedAt: new Date().toISOString()
|
|
30
|
+
}]
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
} catch (err) {
|
|
34
|
+
req.payload.logger.error({
|
|
35
|
+
err,
|
|
36
|
+
msg: `Failed to record recently viewed document "${collectionSlug}/${id}"`
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
//# sourceMappingURL=recordRecentlyViewed.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recordRecentlyViewed.js","names":["PREFERENCE_KEYS","addRecentlyViewedItem","upsertPreferences","recordRecentlyViewed","id","collectionSlug","req","user","customMerge","existingValue","incomingValue","existing","item","items","key","RECENTLY_VIEWED","value","viewedAt","Date","toISOString","err","payload","logger","error","msg"],"sources":["../../../src/views/Document/recordRecentlyViewed.ts"],"sourcesContent":["import type { PayloadRequest, RecentlyViewedPreferences } from 'payload'\n\nimport { PREFERENCE_KEYS } from 'payload/shared'\n\nimport { addRecentlyViewedItem } from '../../utilities/recentlyViewed.js'\nimport { upsertPreferences } from '../../utilities/upsertPreferences.js'\n\n/**\n * Records that the current user viewed a collection document, persisting it to the\n * `recently-viewed` preference. The document is loaded with access control before this runs, so\n * reaching here means the user can read it. Never throws: a failed write must not break the view.\n */\nexport const recordRecentlyViewed = async ({\n id,\n collectionSlug,\n req,\n}: {\n collectionSlug: string\n id: number | string\n req: PayloadRequest\n}): Promise<void> => {\n if (!req.user) {\n return\n }\n\n try {\n await upsertPreferences<RecentlyViewedPreferences>({\n customMerge: (existingValue, incomingValue) =>\n addRecentlyViewedItem({ existing: existingValue, item: incomingValue.items[0] }),\n key: PREFERENCE_KEYS.RECENTLY_VIEWED,\n req,\n value: { items: [{ id, collectionSlug, viewedAt: new Date().toISOString() }] },\n })\n } catch (err) {\n req.payload.logger.error({\n err,\n msg: `Failed to record recently viewed document \"${collectionSlug}/${id}\"`,\n })\n }\n}\n"],"mappings":"AAEA,SAASA,eAAe,QAAQ;AAEhC,SAASC,qBAAqB,QAAQ;AACtC,SAASC,iBAAiB,QAAQ;AAElC;;;;;AAKA,OAAO,MAAMC,oBAAA,GAAuB,MAAAA,CAAO;EACzCC,EAAE;EACFC,cAAc;EACdC;AAAG,CAKJ;EACC,IAAI,CAACA,GAAA,CAAIC,IAAI,EAAE;IACb;EACF;EAEA,IAAI;IACF,MAAML,iBAAA,CAA6C;MACjDM,WAAA,EAAaA,CAACC,aAAA,EAAeC,aAAA,KAC3BT,qBAAA,CAAsB;QAAEU,QAAA,EAAUF,aAAA;QAAeG,IAAA,EAAMF,aAAA,CAAcG,KAAK,CAAC;MAAG;MAChFC,GAAA,EAAKd,eAAA,CAAgBe,eAAe;MACpCT,GAAA;MACAU,KAAA,EAAO;QAAEH,KAAA,EAAO,CAAC;UAAET,EAAA;UAAIC,cAAA;UAAgBY,QAAA,EAAU,IAAIC,IAAA,GAAOC,WAAW;QAAG;MAAG;IAC/E;EACF,EAAE,OAAOC,GAAA,EAAK;IACZd,GAAA,CAAIe,OAAO,CAACC,MAAM,CAACC,KAAK,CAAC;MACvBH,GAAA;MACAI,GAAA,EAAK,8CAA8CnB,cAAA,IAAkBD,EAAA;IACvE;EACF;AACF","ignoreList":[]}
|