Compare commits
23 Commits
fix/virtua
...
ts-strict3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e057caa886 | ||
|
|
8fee0163b5 | ||
|
|
1b17df9e0b | ||
|
|
3df1329e19 | ||
|
|
5492542c1a | ||
|
|
9948040ad2 | ||
|
|
b7ae4ee60a | ||
|
|
34ead72c85 | ||
|
|
caae5986f5 | ||
|
|
2f21d46de6 | ||
|
|
6b83086c6c | ||
|
|
5bd852c9b5 | ||
|
|
c85fb808b9 | ||
|
|
ab03f4f305 | ||
|
|
2157450805 | ||
|
|
034a26754f | ||
|
|
92380bff87 | ||
|
|
9b1dd2a8d8 | ||
|
|
9955818503 | ||
|
|
2c20051dbf | ||
|
|
d91478cd24 | ||
|
|
6dc61ae642 | ||
|
|
fdff5871f6 |
@@ -120,25 +120,25 @@ export const MyCollection: CollectionConfig = {
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `group` | Text or localization object used to group Collection and Global links in the admin navigation. Set to `false` to hide the link from the navigation while keeping its routes accessible. |
|
||||
| `hidden` | Set to true or a function, called with the current user, returning true to exclude this Collection from navigation and admin routing. |
|
||||
| `hooks` | Admin-specific hooks for this Collection. [More details](../hooks/collections). |
|
||||
| `useAsTitle` | Specify a top-level field to use for a document title throughout the Admin Panel. If no field is defined, the ID of the document is used as the title. A field with `virtual: true` cannot be used as the title. |
|
||||
| `description` | Text to display below the Collection label in the List View to give editors more information. Alternatively, you can use the `admin.components.Description` to render a React component. [More details](#custom-components). |
|
||||
| `defaultColumns` | Array of field names that correspond to which columns to show by default in this Collection's List View. |
|
||||
| `disableCopyToLocale` | Disables the "Copy to Locale" button while editing documents within this Collection. Only applicable when localization is enabled. |
|
||||
| `hideAPIURL` | Hides the "API URL" meta field while editing documents within this Collection. |
|
||||
| `enableRichTextLink` | The [Rich Text](../fields/rich-text) field features a `Link` element which allows for users to automatically reference related documents within their rich text. Set to `true` by default. |
|
||||
| `enableRichTextRelationship` | The [Rich Text](../fields/rich-text) field features a `Relationship` element which allows for users to automatically reference related documents within their rich text. Set to `true` by default. |
|
||||
| `meta` | Page metadata overrides to apply to this Collection within the Admin Panel. [More details](../admin/metadata). |
|
||||
| `preview` | Function to generate preview URLs within the Admin Panel that can point to your app. [More details](../admin/preview). |
|
||||
| `livePreview` | Enable real-time editing for instant visual feedback of your front-end application. [More details](../live-preview/overview). |
|
||||
| `components` | Swap in your own React components to be used within this Collection. [More details](#custom-components). |
|
||||
| `listSearchableFields` | Specify which fields should be searched in the List search view. [More details](#list-searchable-fields). |
|
||||
| `pagination` | Set pagination-specific options for this Collection. [More details](#pagination). |
|
||||
| `baseListFilter` | You can define a default base filter for this collection's List view, which will be merged into any filters that the user performs. |
|
||||
| Option | Description |
|
||||
| ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `group` | Text or localization object used to group Collection and Global links in the admin navigation. Set to `false` to hide the link from the navigation while keeping its routes accessible. |
|
||||
| `hidden` | Set to true or a function, called with the current user, returning true to exclude this Collection from navigation and admin routing. |
|
||||
| `hooks` | Admin-specific hooks for this Collection. [More details](../hooks/collections). |
|
||||
| `useAsTitle` | Specify a top-level field to use for a document title throughout the Admin Panel. If no field is defined, the ID of the document is used as the title. A field with `virtual: true` cannot be used as the title, unless it's linked to a relationship'. |
|
||||
| `description` | Text to display below the Collection label in the List View to give editors more information. Alternatively, you can use the `admin.components.Description` to render a React component. [More details](#custom-components). |
|
||||
| `defaultColumns` | Array of field names that correspond to which columns to show by default in this Collection's List View. |
|
||||
| `disableCopyToLocale` | Disables the "Copy to Locale" button while editing documents within this Collection. Only applicable when localization is enabled. |
|
||||
| `hideAPIURL` | Hides the "API URL" meta field while editing documents within this Collection. |
|
||||
| `enableRichTextLink` | The [Rich Text](../fields/rich-text) field features a `Link` element which allows for users to automatically reference related documents within their rich text. Set to `true` by default. |
|
||||
| `enableRichTextRelationship` | The [Rich Text](../fields/rich-text) field features a `Relationship` element which allows for users to automatically reference related documents within their rich text. Set to `true` by default. |
|
||||
| `meta` | Page metadata overrides to apply to this Collection within the Admin Panel. [More details](../admin/metadata). |
|
||||
| `preview` | Function to generate preview URLs within the Admin Panel that can point to your app. [More details](../admin/preview). |
|
||||
| `livePreview` | Enable real-time editing for instant visual feedback of your front-end application. [More details](../live-preview/overview). |
|
||||
| `components` | Swap in your own React components to be used within this Collection. [More details](#custom-components). |
|
||||
| `listSearchableFields` | Specify which fields should be searched in the List search view. [More details](#list-searchable-fields). |
|
||||
| `pagination` | Set pagination-specific options for this Collection. [More details](#pagination). |
|
||||
| `baseListFilter` | You can define a default base filter for this collection's List view, which will be merged into any filters that the user performs. |
|
||||
|
||||
### Custom Components
|
||||
|
||||
@@ -193,13 +193,13 @@ export const MyCollection: CollectionConfig = {
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `SaveButton` | Replace the default Save Button within the Edit View. [Drafts](../versions/drafts) must be disabled. [More details](../custom-components/edit-view#save-button). |
|
||||
| `SaveDraftButton` | Replace the default Save Draft Button within the Edit View. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#save-draft-button). |
|
||||
| `PublishButton` | Replace the default Publish Button within the Edit View. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publish-button). |
|
||||
| `PreviewButton` | Replace the default Preview Button within the Edit View. [Preview](../admin/preview) must be enabled. [More details](../custom-components/edit-view#preview-button). |
|
||||
| `Upload` | Replace the default Upload component within the Edit View. [Upload](../upload/overview) must be enabled. [More details](../custom-components/edit-view#upload). |
|
||||
| Option | Description |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `SaveButton` | Replace the default Save Button within the Edit View. [Drafts](../versions/drafts) must be disabled. [More details](../custom-components/edit-view#savebutton). |
|
||||
| `SaveDraftButton` | Replace the default Save Draft Button within the Edit View. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#savedraftbutton). |
|
||||
| `PublishButton` | Replace the default Publish Button within the Edit View. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publishbutton). |
|
||||
| `PreviewButton` | Replace the default Preview Button within the Edit View. [Preview](../admin/preview) must be enabled. [More details](../custom-components/edit-view#previewbutton). |
|
||||
| `Upload` | Replace the default Upload component within the Edit View. [Upload](../upload/overview) must be enabled. [More details](../custom-components/edit-view#upload). |
|
||||
|
||||
<Banner type="success">
|
||||
**Note:** For details on how to build Custom Components, see [Building Custom
|
||||
|
||||
@@ -179,12 +179,12 @@ export const MyGlobal: SanitizedGlobalConfig = {
|
||||
|
||||
The following options are available:
|
||||
|
||||
| Option | Description |
|
||||
| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `SaveButton` | Replace the default Save Button with a Custom Component. [Drafts](../versions/drafts) must be disabled. [More details](../custom-components/edit-view#save-button). |
|
||||
| `SaveDraftButton` | Replace the default Save Draft Button with a Custom Component. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#save-draft-button). |
|
||||
| `PublishButton` | Replace the default Publish Button with a Custom Component. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publish-button). |
|
||||
| `PreviewButton` | Replace the default Preview Button with a Custom Component. [Preview](../admin/preview) must be enabled. [More details](../custom-components/edit-view#preview-button). |
|
||||
| Option | Description |
|
||||
| ----------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `SaveButton` | Replace the default Save Button with a Custom Component. [Drafts](../versions/drafts) must be disabled. [More details](../custom-components/edit-view#savebutton). |
|
||||
| `SaveDraftButton` | Replace the default Save Draft Button with a Custom Component. [Drafts](../versions/drafts) must be enabled and autosave must be disabled. [More details](../custom-components/edit-view#savedraftbutton). |
|
||||
| `PublishButton` | Replace the default Publish Button with a Custom Component. [Drafts](../versions/drafts) must be enabled. [More details](../custom-components/edit-view#publishbutton). |
|
||||
| `PreviewButton` | Replace the default Preview Button with a Custom Component. [Preview](../admin/preview) must be enabled. [More details](../custom-components/edit-view#previewbutton). |
|
||||
|
||||
<Banner type="success">
|
||||
**Note:** For details on how to build Custom Components, see [Building Custom
|
||||
|
||||
@@ -298,3 +298,15 @@ Passing your migrations as shown above will tell Payload, in production only, to
|
||||
may slow down serverless cold starts on platforms such as Vercel. Generally,
|
||||
this option should only be used for long-running servers / containers.
|
||||
</Banner>
|
||||
|
||||
## Environment-Specific Configurations and Migrations
|
||||
|
||||
Your configuration may include environment-specific settings (e.g., enabling a plugin only in production). If you generate migrations without considering the environment, it can lead to discrepancies and issues. When running migrations locally, Payload uses the development environment, which might miss production-specific configurations. Similarly, running migrations in production could miss development-specific entities.
|
||||
|
||||
This is an easy oversight, so be mindful of any environment-specific logic in your config when handling migrations.
|
||||
|
||||
**Ways to address this:**
|
||||
|
||||
- Manually update your migration file after it is generated to include any environment-specific configurations.
|
||||
- Temporarily enable any required production environment variables in your local setup when generating the migration to capture the necessary updates.
|
||||
- Use separate migration files for each environment to ensure the correct migration is executed in the corresponding environment.
|
||||
|
||||
@@ -39,28 +39,28 @@ export const MyArrayField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as the heading in the [Admin Panel](../admin/overview) or an object with keys for each language. Auto-generated from name if not defined. |
|
||||
| **`fields`** \* | Array of field types to correspond to each row of the Array. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the [Admin Panel](../admin/overview) and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. |
|
||||
| **`maxRows`** | A number for the most allowed items during validation when a value is present. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide an array of row data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. If enabled, a separate, localized set of all data within this Array will be kept, so there is no need to specify each nested field as `localized`. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`labels`** | Customize the row labels appearing in the Admin dashboard. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
|
||||
| **`dbName`** | Custom table name for the field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as the heading in the [Admin Panel](../admin/overview) or an object with keys for each language. Auto-generated from name if not defined. |
|
||||
| **`fields`** \* | Array of field types to correspond to each row of the Array. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the [Admin Panel](../admin/overview) and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. |
|
||||
| **`maxRows`** | A number for the most allowed items during validation when a value is present. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide an array of row data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. If enabled, a separate, localized set of all data within this Array will be kept, so there is no need to specify each nested field as `localized`. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`labels`** | Customize the row labels appearing in the Admin dashboard. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
|
||||
| **`dbName`** | Custom table name for the field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -39,26 +39,26 @@ export const MyBlocksField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as the heading in the Admin Panel or an object with keys for each language. Auto-generated from name if not defined. |
|
||||
| **`blocks`** \* | Array of [block configs](/docs/fields/blocks#block-configs) to be made available to this field. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. |
|
||||
| **`maxRows`** | A number for the most allowed items during validation when a value is present. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API response or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide an array of block data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. If enabled, a separate, localized set of all data within this field will be kept, so there is no need to specify each nested field as `localized`. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`labels`** | Customize the block row labels appearing in the Admin dashboard. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as the heading in the Admin Panel or an object with keys for each language. Auto-generated from name if not defined. |
|
||||
| **`blocks`** \* | Array of [block configs](/docs/fields/blocks#block-configs) to be made available to this field. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. |
|
||||
| **`maxRows`** | A number for the most allowed items during validation when a value is present. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API response or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide an array of block data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. If enabled, a separate, localized set of all data within this field will be kept, so there is no need to specify each nested field as `localized`. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`labels`** | Customize the block row labels appearing in the Admin dashboard. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -28,23 +28,23 @@ export const MyCheckboxField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value, will default to false if field is also `required`. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value, will default to false if field is also `required`. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -29,26 +29,26 @@ export const MyBlocksField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
|
||||
| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
|
||||
| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. See below for [more detail](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -28,24 +28,24 @@ export const MyDateField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`timezone`** \* | Set to `true` to enable timezone selection on this field. [More details](#timezones). |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`timezone`** \* | Set to `true` to enable timezone selection on this field. [More details](#timezones). |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -28,24 +28,24 @@ export const MyEmailField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -29,25 +29,25 @@ export const MyJSONField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`jsonSchema`** | Provide a JSON schema that will be used for validation. [JSON schemas](https://json-schema.org/learn/getting-started-step-by-step) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`jsonSchema`** | Provide a JSON schema that will be used for validation. [JSON schemas](https://json-schema.org/learn/getting-started-step-by-step) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -28,29 +28,29 @@ export const MyNumberField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`min`** | Minimum value accepted. Used in the default `validation` function. |
|
||||
| **`max`** | Maximum value accepted. Used in the default `validation` function. |
|
||||
| **`hasMany`** | Makes this field an ordered array of numbers instead of just a single number. |
|
||||
| **`minRows`** | Minimum number of numbers in the numbers array, if `hasMany` is set to true. |
|
||||
| **`maxRows`** | Maximum number of numbers in the numbers array, if `hasMany` is set to true. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`min`** | Minimum value accepted. Used in the default `validation` function. |
|
||||
| **`max`** | Maximum value accepted. Used in the default `validation` function. |
|
||||
| **`hasMany`** | Makes this field an ordered array of numbers instead of just a single number. |
|
||||
| **`minRows`** | Minimum number of numbers in the numbers array, if `hasMany` is set to true. |
|
||||
| **`maxRows`** | Maximum number of numbers in the numbers array, if `hasMany` is set to true. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -32,24 +32,24 @@ export const MyPointField: Field = {
|
||||
|
||||
## Config
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Used as a field label in the Admin Panel and to name the generated GraphQL type. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. To support location queries, point index defaults to `2dsphere`, to disable the index set to `false`. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Used as a field label in the Admin Panel and to name the generated GraphQL type. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. To support location queries, point index defaults to `2dsphere`, to disable the index set to `false`. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](./overview#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -33,26 +33,26 @@ export const MyRadioField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing an `label` string and a `value` string. |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. The default value must exist within provided values in `options`. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
|
||||
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing an `label` string and a `value` string. |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. The default value must exist within provided values in `options`. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
|
||||
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -37,31 +37,31 @@ export const MyRelationshipField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`relationTo`** \* | Provide one or many collection `slug`s to be able to assign relationships to. |
|
||||
| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-relationship-options). |
|
||||
| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many relations instead of only one. |
|
||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with `hasMany`. |
|
||||
| **`maxRows`** | A number for the most allowed items during validation when a value is present. Used with `hasMany`. |
|
||||
| **`maxDepth`** | Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](/docs/queries/depth#max-depth) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`relationTo`** \* | Provide one or many collection `slug`s to be able to assign relationships to. |
|
||||
| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-relationship-options). |
|
||||
| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many relations instead of only one. |
|
||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with `hasMany`. |
|
||||
| **`maxRows`** | A number for the most allowed items during validation when a value is present. Used with `hasMany`. |
|
||||
| **`maxDepth`** | Sets a maximum population depth for this field, regardless of the remaining depth when this field is reached. [Max Depth](/docs/queries/depth#max-depth) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
@@ -376,6 +376,45 @@ non-polymorphic relationship.
|
||||
|
||||
</Banner>
|
||||
|
||||
### Linking virtual fields with relationships
|
||||
|
||||
You can link virtual fields to fields in other collections through a relationship (or upload) field, for example:
|
||||
|
||||
```ts
|
||||
{
|
||||
collections: [
|
||||
{
|
||||
slug: 'categories',
|
||||
fields: [
|
||||
{
|
||||
name: 'title',
|
||||
type: 'text',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
slug: 'posts',
|
||||
fields: [
|
||||
{
|
||||
type: 'relationship',
|
||||
name: 'category',
|
||||
relationTo: 'categories',
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
name: 'categoryTitle',
|
||||
virtual: 'category.title',
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
Here, `categoryTitle` will _always_ be populated with the corresponding value, even if the current `depth` is `0`, You can also query and sort by this field.
|
||||
The relationship must not be `hasMany: true` or polymorphic.
|
||||
The path can be deeply nested into 2 or more relationship fields, for example `post.category.title` as long as all the relationship fields meet the above requirement.
|
||||
|
||||
## Custom Components
|
||||
|
||||
### Field
|
||||
|
||||
@@ -21,23 +21,23 @@ Instead, you can invest your time and effort into learning the underlying open-s
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](./overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](./overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](../authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](./overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](../configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`editor`** | Customize or override the rich text editor. [More details](../rich-text/overview). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](./overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](./overview#validation) |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](../authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](./overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](../configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`editor`** | Customize or override the rich text editor. [More details](../rich-text/overview). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
\*_ An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -33,29 +33,29 @@ export const MySelectField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing a `label` string and a `value` string. |
|
||||
| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many selections instead of only one. |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-options) for more details. |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
|
||||
| **`dbName`** | Custom table name (if `hasMany` set to `true`) for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
|
||||
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`options`** \* | Array of options to allow the field to store. Can either be an array of strings, or an array of objects containing a `label` string and a `value` string. |
|
||||
| **`hasMany`** | Boolean when, if set to `true`, allows this field to have many selections instead of only one. |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. See the [default field admin config](/docs/fields/overview#admin-options) for more details. |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`enumName`** | Custom enum name for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
|
||||
| **`dbName`** | Custom table name (if `hasMany` set to `true`) for this field when using SQL Database Adapter ([Postgres](/docs/database/postgres)). Auto-generated from name if not defined. |
|
||||
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -43,14 +43,14 @@ export const MyTabsField: Field = {
|
||||
|
||||
Each tab must have either a `name` or `label` and the required `fields` array. You can also optionally pass a `description` to render within each individual tab.
|
||||
|
||||
| Option | Description |
|
||||
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| **`name`** | Groups field data into an object when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | The label to render on the tab itself. Required when name is undefined, defaults to name converted to words. |
|
||||
| **`fields`** \* | The fields to render within this tab. |
|
||||
| **`description`** | Optionally render a description within this tab to describe the contents of the tab itself. |
|
||||
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). (`name` must be present) |
|
||||
| **`virtual`** | Provide `true` to disable field in the database (`name` must be present). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** | Groups field data into an object when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | The label to render on the tab itself. Required when name is undefined, defaults to name converted to words. |
|
||||
| **`fields`** \* | The fields to render within this tab. |
|
||||
| **`description`** | Optionally render a description within this tab to describe the contents of the tab itself. |
|
||||
| **`interfaceName`** | Create a top level, reusable [Typescript interface](/docs/typescript/generating-types#custom-field-interfaces) & [GraphQL type](/docs/graphql/graphql-schema#custom-field-schemas). (`name` must be present) |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -28,29 +28,29 @@ export const MyTextField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
|
||||
| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`hasMany`** | Makes this field an ordered array of text instead of just a single text. |
|
||||
| **`minRows`** | Minimum number of texts in the array, if `hasMany` is set to true. |
|
||||
| **`maxRows`** | Maximum number of texts in the array, if `hasMany` is set to true. |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
|
||||
| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`hasMany`** | Makes this field an ordered array of text instead of just a single text. |
|
||||
| **`minRows`** | Minimum number of texts in the array, if `hasMany` is set to true. |
|
||||
| **`maxRows`** | Maximum number of texts in the array, if `hasMany` is set to true. |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -28,26 +28,26 @@ export const MyTextareaField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
|
||||
| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`minLength`** | Used by the default validation function to ensure values are of a minimum character length. |
|
||||
| **`maxLength`** | Used by the default validation function to ensure values are of a maximum character length. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [More details](#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -44,32 +44,32 @@ export const MyUploadField: Field = {
|
||||
|
||||
## Config Options
|
||||
|
||||
| Option | Description |
|
||||
| ---------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`relationTo`** \* | Provide a single collection `slug` to allow this field to accept a relation to. **Note: the related collection must be configured to support Uploads.** |
|
||||
| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-upload-options). |
|
||||
| **`hasMany`** | Boolean which, if set to true, allows this field to have many relations instead of only one. |
|
||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with hasMany. |
|
||||
| **`maxRows`** | A number for the most allowed items during validation when a value is present. Used with hasMany. |
|
||||
| **`maxDepth`** | Sets a number limit on iterations of related documents to populate when queried. [Depth](../queries/depth) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`displayPreview`** | Enable displaying preview of the uploaded file. Overrides related Collection's `displayPreview` option. [More](/docs/upload/overview#collection-upload-options). |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [Admin Options](./overview#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database. See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
|
||||
| Option | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **`name`** \* | To be used as the property name when stored and retrieved from the database. [More](/docs/fields/overview#field-names) |
|
||||
| **`relationTo`** \* | Provide a single collection `slug` to allow this field to accept a relation to. **Note: the related collection must be configured to support Uploads.** |
|
||||
| **`filterOptions`** | A query to filter which options appear in the UI and validate against. [More](#filtering-upload-options). |
|
||||
| **`hasMany`** | Boolean which, if set to true, allows this field to have many relations instead of only one. |
|
||||
| **`minRows`** | A number for the fewest allowed items during validation when a value is present. Used with hasMany. |
|
||||
| **`maxRows`** | A number for the most allowed items during validation when a value is present. Used with hasMany. |
|
||||
| **`maxDepth`** | Sets a number limit on iterations of related documents to populate when queried. [Depth](../queries/depth) |
|
||||
| **`label`** | Text used as a field label in the Admin Panel or an object with keys for each language. |
|
||||
| **`unique`** | Enforce that each entry in the Collection has a unique value for this field. |
|
||||
| **`validate`** | Provide a custom validation function that will be executed on both the Admin Panel and the backend. [More](/docs/fields/overview#validation) |
|
||||
| **`index`** | Build an [index](/docs/database/overview) for this field to produce faster queries. Set this field to `true` if your users will perform queries on this field's data often. |
|
||||
| **`saveToJWT`** | If this field is top-level and nested in a config supporting [Authentication](/docs/authentication/overview), include its data in the user JWT. |
|
||||
| **`hooks`** | Provide Field Hooks to control logic for this field. [More details](../hooks/fields). |
|
||||
| **`access`** | Provide Field Access Control to denote what users can see and do with this field's data. [More details](../access-control/fields). |
|
||||
| **`hidden`** | Restrict this field's visibility from all APIs entirely. Will still be saved to the database, but will not appear in any API or the Admin Panel. |
|
||||
| **`defaultValue`** | Provide data to be used for this field's default value. [More](/docs/fields/overview#default-values) |
|
||||
| **`displayPreview`** | Enable displaying preview of the uploaded file. Overrides related Collection's `displayPreview` option. [More](/docs/upload/overview#collection-upload-options). |
|
||||
| **`localized`** | Enable localization for this field. Requires [localization to be enabled](/docs/configuration/localization) in the Base config. |
|
||||
| **`required`** | Require this field to have a value. |
|
||||
| **`admin`** | Admin-specific configuration. [Admin Options](./overview#admin-options). |
|
||||
| **`custom`** | Extension point for adding custom data (e.g. for plugins) |
|
||||
| **`typescriptSchema`** | Override field type generation with providing a JSON schema |
|
||||
| **`virtual`** | Provide `true` to disable field in the database, or provide a string path to [link the field with a relationship](/docs/fields/relationship#linking-virtual-fields-with-relationships). See [Virtual Fields](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) |
|
||||
| **`graphQL`** | Custom graphQL configuration for the field. [More details](/docs/graphql/overview#field-complexity) |
|
||||
|
||||
_\* An asterisk denotes that a property is required._
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ keywords: query, documents, pagination, documentation, Content Management System
|
||||
|
||||
Documents in Payload can be easily sorted by a specific [Field](../fields/overview). When querying Documents, you can pass the name of any top-level field, and the response will sort the Documents by that field in _ascending_ order. If prefixed with a minus symbol ("-"), they will be sorted in _descending_ order. In Local API multiple fields can be specified by using an array of strings. In REST API multiple fields can be specified by separating fields with comma. The minus symbol can be in front of individual fields.
|
||||
|
||||
Because sorting is handled by the database, the field cannot be a [Virtual Field](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges). It must be stored in the database to be searchable.
|
||||
Because sorting is handled by the database, the field cannot be a [Virtual Field](https://payloadcms.com/blog/learn-how-virtual-fields-can-help-solve-common-cms-challenges) unless it's [linked with a relationship field](/docs/fields/relationship#linking-virtual-fields-with-relationships). It must be stored in the database to be searchable.
|
||||
|
||||
<Banner type="success">
|
||||
**Tip:** For performance reasons, it is recommended to enable `index: true`
|
||||
|
||||
@@ -117,7 +117,7 @@ Adding custom access control rules requires:
|
||||
2. A set of fields to conditionally render when that option is selected
|
||||
3. A function that returns the access control rules for that option
|
||||
|
||||
To do this, use the `queryPresets.constraints` property in your [Payload Config](../configuration/payload-config).
|
||||
To do this, use the `queryPresets.constraints` property in your [Payload Config](../configuration/overview).
|
||||
|
||||
```ts
|
||||
import { buildConfig } from 'payload'
|
||||
@@ -128,26 +128,28 @@ const config = buildConfig({
|
||||
// ...
|
||||
// highlight-start
|
||||
constraints: {
|
||||
read: {
|
||||
label: 'Specific Roles',
|
||||
value: 'specificRoles',
|
||||
fields: [
|
||||
{
|
||||
name: 'roles',
|
||||
type: 'select',
|
||||
hasMany: true,
|
||||
options: [
|
||||
{ label: 'Admin', value: 'admin' },
|
||||
{ label: 'User', value: 'user' },
|
||||
],
|
||||
},
|
||||
],
|
||||
access: ({ req: { user } }) => ({
|
||||
'access.read.roles': {
|
||||
in: [user?.roles],
|
||||
},
|
||||
}),
|
||||
},
|
||||
read: [
|
||||
{
|
||||
label: 'Specific Roles',
|
||||
value: 'specificRoles',
|
||||
fields: [
|
||||
{
|
||||
name: 'roles',
|
||||
type: 'select',
|
||||
hasMany: true,
|
||||
options: [
|
||||
{ label: 'Admin', value: 'admin' },
|
||||
{ label: 'User', value: 'user' },
|
||||
],
|
||||
},
|
||||
],
|
||||
access: ({ req: { user } }) => ({
|
||||
'access.read.roles': {
|
||||
in: [user?.roles],
|
||||
},
|
||||
}),
|
||||
},
|
||||
],
|
||||
// highlight-end
|
||||
},
|
||||
},
|
||||
|
||||
@@ -58,7 +58,7 @@ See the [Collections](https://payloadcms.com/docs/configuration/collections) doc
|
||||
}
|
||||
```
|
||||
|
||||
For more details on how to extend this functionality, see the [Live Preview](https://payloadcms.com/docs/live-preview) docs.
|
||||
For more details on how to extend this functionality, see the [Live Preview](https://payloadcms.com/docs/live-preview/overview) docs.
|
||||
|
||||
## Front-end
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ export const home: Partial<Page> = {
|
||||
type: 'link',
|
||||
children: [{ text: 'Live Preview' }],
|
||||
newTab: true,
|
||||
url: 'https://payloadcms.com/docs/live-preview',
|
||||
url: 'https://payloadcms.com/docs/live-preview/overview',
|
||||
},
|
||||
{
|
||||
text: ' you can edit this page in the admin panel and see the changes reflected here in real time.',
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload-monorepo",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/admin-bar",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "An admin bar for React apps using Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "create-payload-app",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-mongodb",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "The officially supported MongoDB database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -166,7 +166,7 @@ export const queryDrafts: QueryDrafts = async function queryDrafts(
|
||||
|
||||
for (let i = 0; i < result.docs.length; i++) {
|
||||
const id = result.docs[i].parent
|
||||
result.docs[i] = result.docs[i].version
|
||||
result.docs[i] = result.docs[i].version ?? {}
|
||||
result.docs[i].id = id
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-postgres",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "The officially supported Postgres database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-sqlite",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "The officially supported SQLite database adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/db-vercel-postgres",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Vercel Postgres adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/drizzle",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "A library of shared functions used by different payload database adapters",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -3,12 +3,14 @@ import type { FlattenedField, Where } from 'payload'
|
||||
|
||||
import type { DrizzleAdapter, GenericColumn } from '../types.js'
|
||||
import type { BuildQueryJoinAliases } from './buildQuery.js'
|
||||
import type { QueryContext } from './parseParams.js'
|
||||
|
||||
import { parseParams } from './parseParams.js'
|
||||
|
||||
export function buildAndOrConditions({
|
||||
adapter,
|
||||
aliasTable,
|
||||
context,
|
||||
fields,
|
||||
joins,
|
||||
locale,
|
||||
@@ -21,6 +23,7 @@ export function buildAndOrConditions({
|
||||
adapter: DrizzleAdapter
|
||||
aliasTable?: Table
|
||||
collectionSlug?: string
|
||||
context: QueryContext
|
||||
fields: FlattenedField[]
|
||||
globalSlug?: string
|
||||
joins: BuildQueryJoinAliases
|
||||
@@ -41,6 +44,7 @@ export function buildAndOrConditions({
|
||||
const result = parseParams({
|
||||
adapter,
|
||||
aliasTable,
|
||||
context,
|
||||
fields,
|
||||
joins,
|
||||
locale,
|
||||
|
||||
@@ -3,6 +3,7 @@ import type { PgTableWithColumns } from 'drizzle-orm/pg-core'
|
||||
import type { FlattenedField, Sort, Where } from 'payload'
|
||||
|
||||
import type { DrizzleAdapter, GenericColumn, GenericTable } from '../types.js'
|
||||
import type { QueryContext } from './parseParams.js'
|
||||
|
||||
import { buildOrderBy } from './buildOrderBy.js'
|
||||
import { parseParams } from './parseParams.js'
|
||||
@@ -52,24 +53,14 @@ const buildQuery = function buildQuery({
|
||||
id: adapter.tables[tableName].id,
|
||||
}
|
||||
|
||||
const orderBy = buildOrderBy({
|
||||
adapter,
|
||||
aliasTable,
|
||||
fields,
|
||||
joins,
|
||||
locale,
|
||||
parentIsLocalized,
|
||||
selectFields,
|
||||
sort,
|
||||
tableName,
|
||||
})
|
||||
|
||||
let where: SQL
|
||||
|
||||
const context: QueryContext = { sort }
|
||||
if (incomingWhere && Object.keys(incomingWhere).length > 0) {
|
||||
where = parseParams({
|
||||
adapter,
|
||||
aliasTable,
|
||||
context,
|
||||
fields,
|
||||
joins,
|
||||
locale,
|
||||
@@ -81,6 +72,18 @@ const buildQuery = function buildQuery({
|
||||
})
|
||||
}
|
||||
|
||||
const orderBy = buildOrderBy({
|
||||
adapter,
|
||||
aliasTable,
|
||||
fields,
|
||||
joins,
|
||||
locale,
|
||||
parentIsLocalized,
|
||||
selectFields,
|
||||
sort: context.sort,
|
||||
tableName,
|
||||
})
|
||||
|
||||
return {
|
||||
joins,
|
||||
orderBy,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { SQL, Table } from 'drizzle-orm'
|
||||
import type { FlattenedField, Operator, Where } from 'payload'
|
||||
import type { FlattenedField, Operator, Sort, Where } from 'payload'
|
||||
|
||||
import { and, isNotNull, isNull, ne, notInArray, or, sql } from 'drizzle-orm'
|
||||
import { PgUUID } from 'drizzle-orm/pg-core'
|
||||
@@ -14,9 +14,12 @@ import { buildAndOrConditions } from './buildAndOrConditions.js'
|
||||
import { getTableColumnFromPath } from './getTableColumnFromPath.js'
|
||||
import { sanitizeQueryValue } from './sanitizeQueryValue.js'
|
||||
|
||||
export type QueryContext = { sort: Sort }
|
||||
|
||||
type Args = {
|
||||
adapter: DrizzleAdapter
|
||||
aliasTable?: Table
|
||||
context: QueryContext
|
||||
fields: FlattenedField[]
|
||||
joins: BuildQueryJoinAliases
|
||||
locale?: string
|
||||
@@ -30,6 +33,7 @@ type Args = {
|
||||
export function parseParams({
|
||||
adapter,
|
||||
aliasTable,
|
||||
context,
|
||||
fields,
|
||||
joins,
|
||||
locale,
|
||||
@@ -57,6 +61,7 @@ export function parseParams({
|
||||
const builtConditions = buildAndOrConditions({
|
||||
adapter,
|
||||
aliasTable,
|
||||
context,
|
||||
fields,
|
||||
joins,
|
||||
locale,
|
||||
@@ -342,6 +347,7 @@ export function parseParams({
|
||||
)
|
||||
}
|
||||
if (geoConstraints.length) {
|
||||
context.sort = relationOrPath
|
||||
constraints.push(and(...geoConstraints))
|
||||
}
|
||||
break
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-nodemailer",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Payload Nodemailer Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/email-resend",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Payload Resend Email Adapter",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/graphql",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -393,19 +393,32 @@ export const fieldToSchemaMap: FieldToSchemaMap = {
|
||||
throw new Error('GraphQL with array of join.field.collection is not implemented')
|
||||
}
|
||||
|
||||
return await req.payload.find({
|
||||
const { docs } = await req.payload.find({
|
||||
collection,
|
||||
depth: 0,
|
||||
draft,
|
||||
fallbackLocale: req.fallbackLocale,
|
||||
limit,
|
||||
// Fetch one extra document to determine if there are more documents beyond the requested limit (used for hasNextPage calculation).
|
||||
limit: typeof limit === 'number' && limit > 0 ? limit + 1 : 0,
|
||||
locale: req.locale,
|
||||
overrideAccess: false,
|
||||
page,
|
||||
pagination: false,
|
||||
req,
|
||||
sort,
|
||||
where: fullWhere,
|
||||
})
|
||||
|
||||
let shouldSlice = false
|
||||
|
||||
if (typeof limit === 'number' && limit !== 0 && limit < docs.length) {
|
||||
shouldSlice = true
|
||||
}
|
||||
|
||||
return {
|
||||
docs: shouldSlice ? docs.slice(0, -1) : docs,
|
||||
hasNextPage: limit === 0 ? false : limit < docs.length,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview-react",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "The official React SDK for Payload Live Preview",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview-vue",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "The official Vue SDK for Payload Live Preview",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -30,7 +30,7 @@ export const useLivePreview = <T>(props: {
|
||||
let subscription: (event: MessageEvent) => void
|
||||
|
||||
onMounted(() => {
|
||||
subscription = subscribe({
|
||||
subscription = void subscribe({
|
||||
apiRoute,
|
||||
callback: onChange,
|
||||
depth,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/live-preview",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "The official live preview JavaScript SDK for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/next",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -140,6 +140,13 @@ export const withPayload = (nextConfig = {}, options = {}) => {
|
||||
{ module: /node_modules\/mongodb\/lib\/bson\.js/ },
|
||||
{ file: /node_modules\/mongodb\/lib\/bson\.js/ },
|
||||
],
|
||||
plugins: [
|
||||
...(incomingWebpackConfig?.plugins || []),
|
||||
// Fix cloudflare:sockets error: https://github.com/vercel/next.js/discussions/50177
|
||||
new webpackOptions.webpack.IgnorePlugin({
|
||||
resourceRegExp: /^pg-native$|^cloudflare:sockets$/,
|
||||
}),
|
||||
],
|
||||
resolve: {
|
||||
...(incomingWebpackConfig?.resolve || {}),
|
||||
alias: {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/payload-cloud",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "The official Payload Cloud plugin",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "payload",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Node, React, Headless CMS and Application Framework built on Next.js",
|
||||
"keywords": [
|
||||
"admin panel",
|
||||
|
||||
@@ -138,15 +138,17 @@ export const forgotPasswordOperation = async <TSlug extends CollectionSlug>(
|
||||
return null
|
||||
}
|
||||
|
||||
user.resetPasswordToken = token
|
||||
user.resetPasswordExpiration = new Date(
|
||||
const resetPasswordExpiration = new Date(
|
||||
Date.now() + (collectionConfig.auth?.forgotPassword?.expiration ?? expiration ?? 3600000),
|
||||
).toISOString()
|
||||
|
||||
user = await payload.update({
|
||||
id: user.id,
|
||||
collection: collectionConfig.slug,
|
||||
data: user,
|
||||
data: {
|
||||
resetPasswordExpiration,
|
||||
resetPasswordToken: token,
|
||||
},
|
||||
req,
|
||||
})
|
||||
|
||||
|
||||
@@ -85,6 +85,11 @@ export const virtualFieldPopulationPromise = async ({
|
||||
docID = currentValue
|
||||
}
|
||||
|
||||
if (segments[0] === 'id' && segments.length === 0) {
|
||||
siblingDoc[name] = docID
|
||||
return
|
||||
}
|
||||
|
||||
if (typeof docID !== 'string' && typeof docID !== 'number') {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -200,7 +200,7 @@ export const email: EmailFieldValidation = (
|
||||
* Supports multiple subdomains (e.g., user@sub.domain.example.com)
|
||||
*/
|
||||
const emailRegex =
|
||||
/^(?!.*\.\.)[\w.%+-]+@[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*\.[a-z]{2,}$/i
|
||||
/^(?!.*\.\.)[\w!#$%&'*+/=?^`{|}~-](?:[\w!#$%&'*+/=?^`{|}~.-]*[\w!#$%&'*+/=?^`{|}~-])?@[a-z0-9](?:[a-z0-9-]*[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]*[a-z0-9])?)*\.[a-z]{2,}$/i
|
||||
|
||||
if ((value && !emailRegex.test(value)) || (!value && required)) {
|
||||
return t('validation:emailAddress')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-cloud-storage",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "The official cloud storage plugin for Payload CMS",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-form-builder",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Form builder plugin for Payload CMS",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-import-export",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Import-Export plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-multi-tenant",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Multi Tenant plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-nested-docs",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "The official Nested Docs plugin for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -22,7 +22,6 @@ type ResaveArgs = {
|
||||
|
||||
const resave = async ({ collection, doc, draft, pluginConfig, req }: ResaveArgs) => {
|
||||
const parentSlug = pluginConfig?.parentFieldSlug || 'parent'
|
||||
const breadcrumbSlug = pluginConfig.breadcrumbsFieldSlug || 'breadcrumbs'
|
||||
|
||||
if (draft) {
|
||||
// If the parent is a draft, don't resave children
|
||||
|
||||
@@ -8,47 +8,39 @@ import type { Breadcrumb, NestedDocsPluginConfig } from '../types.js'
|
||||
export const resaveSelfAfterCreate =
|
||||
(pluginConfig: NestedDocsPluginConfig, collection: CollectionConfig): CollectionAfterChangeHook =>
|
||||
async ({ doc, operation, req }) => {
|
||||
if (operation !== 'create') {
|
||||
return undefined
|
||||
}
|
||||
|
||||
const { locale, payload } = req
|
||||
const breadcrumbSlug = pluginConfig.breadcrumbsFieldSlug || 'breadcrumbs'
|
||||
const breadcrumbs = doc[breadcrumbSlug] as unknown as Breadcrumb[]
|
||||
|
||||
if (operation === 'create') {
|
||||
const originalDocWithDepth0 = await payload.findByID({
|
||||
const updateAsDraft =
|
||||
typeof collection.versions === 'object' &&
|
||||
collection.versions.drafts &&
|
||||
doc._status !== 'published'
|
||||
|
||||
try {
|
||||
await payload.update({
|
||||
id: doc.id,
|
||||
collection: collection.slug,
|
||||
data: {
|
||||
[breadcrumbSlug]:
|
||||
breadcrumbs?.map((crumb, i) => ({
|
||||
...crumb,
|
||||
doc: breadcrumbs.length === i + 1 ? doc.id : crumb.doc,
|
||||
})) || [],
|
||||
},
|
||||
depth: 0,
|
||||
draft: updateAsDraft,
|
||||
locale,
|
||||
req,
|
||||
})
|
||||
|
||||
const updateAsDraft =
|
||||
typeof collection.versions === 'object' &&
|
||||
collection.versions.drafts &&
|
||||
doc._status !== 'published'
|
||||
|
||||
try {
|
||||
await payload.update({
|
||||
id: doc.id,
|
||||
collection: collection.slug,
|
||||
data: {
|
||||
...originalDocWithDepth0,
|
||||
[breadcrumbSlug]:
|
||||
breadcrumbs?.map((crumb, i) => ({
|
||||
...crumb,
|
||||
doc: breadcrumbs.length === i + 1 ? doc.id : crumb.doc,
|
||||
})) || [],
|
||||
},
|
||||
depth: 0,
|
||||
draft: updateAsDraft,
|
||||
locale,
|
||||
req,
|
||||
})
|
||||
} catch (err: unknown) {
|
||||
payload.logger.error(
|
||||
`Nested Docs plugin has had an error while adding breadcrumbs during document creation.`,
|
||||
)
|
||||
payload.logger.error(err)
|
||||
}
|
||||
} catch (err: unknown) {
|
||||
payload.logger.error(
|
||||
`Nested Docs plugin has had an error while adding breadcrumbs during document creation.`,
|
||||
)
|
||||
payload.logger.error(err)
|
||||
}
|
||||
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-redirects",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Redirects plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-search",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Search plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -124,14 +124,15 @@ export const generateReindexHandler =
|
||||
for (let i = 0; i < totalBatches; i++) {
|
||||
const { docs } = await payload.find({
|
||||
collection,
|
||||
depth: 0,
|
||||
limit: batchSize,
|
||||
locale: localeToSync,
|
||||
page: i + 1,
|
||||
...defaultLocalApiProps,
|
||||
})
|
||||
|
||||
const promises = docs.map((doc) =>
|
||||
syncDocAsSearchIndex({
|
||||
for (const doc of docs) {
|
||||
await syncDocAsSearchIndex({
|
||||
collection,
|
||||
doc,
|
||||
locale: localeToSync,
|
||||
@@ -139,12 +140,7 @@ export const generateReindexHandler =
|
||||
operation,
|
||||
pluginConfig,
|
||||
req,
|
||||
}),
|
||||
)
|
||||
|
||||
// Sequentially await promises to avoid transaction issues
|
||||
for (const promise of promises) {
|
||||
await promise
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,18 +64,17 @@ export const syncDocAsSearchIndex = async ({
|
||||
const doSync = syncDrafts || (!syncDrafts && status !== 'draft')
|
||||
|
||||
try {
|
||||
if (operation === 'create') {
|
||||
if (doSync) {
|
||||
await payload.create({
|
||||
collection: searchSlug,
|
||||
data: {
|
||||
...dataToSave,
|
||||
priority: defaultPriority,
|
||||
},
|
||||
locale: syncLocale,
|
||||
req,
|
||||
})
|
||||
}
|
||||
if (operation === 'create' && doSync) {
|
||||
await payload.create({
|
||||
collection: searchSlug,
|
||||
data: {
|
||||
...dataToSave,
|
||||
priority: defaultPriority,
|
||||
},
|
||||
depth: 0,
|
||||
locale: syncLocale,
|
||||
req,
|
||||
})
|
||||
}
|
||||
|
||||
if (operation === 'update') {
|
||||
@@ -110,6 +109,7 @@ export const syncDocAsSearchIndex = async ({
|
||||
const duplicativeDocIDs = duplicativeDocs.map(({ id }) => id)
|
||||
await payload.delete({
|
||||
collection: searchSlug,
|
||||
depth: 0,
|
||||
req,
|
||||
where: { id: { in: duplicativeDocIDs } },
|
||||
})
|
||||
@@ -134,6 +134,7 @@ export const syncDocAsSearchIndex = async ({
|
||||
...dataToSave,
|
||||
priority: foundDoc.priority || defaultPriority,
|
||||
},
|
||||
depth: 0,
|
||||
locale: syncLocale,
|
||||
req,
|
||||
})
|
||||
@@ -148,6 +149,7 @@ export const syncDocAsSearchIndex = async ({
|
||||
docs: [docWithPublish],
|
||||
} = await payload.find({
|
||||
collection,
|
||||
depth: 0,
|
||||
draft: false,
|
||||
limit: 1,
|
||||
locale: syncLocale,
|
||||
@@ -175,6 +177,7 @@ export const syncDocAsSearchIndex = async ({
|
||||
await payload.delete({
|
||||
id: searchDocID,
|
||||
collection: searchSlug,
|
||||
depth: 0,
|
||||
req,
|
||||
})
|
||||
} catch (err: unknown) {
|
||||
@@ -190,6 +193,7 @@ export const syncDocAsSearchIndex = async ({
|
||||
...dataToSave,
|
||||
priority: defaultPriority,
|
||||
},
|
||||
depth: 0,
|
||||
locale: syncLocale,
|
||||
req,
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-sentry",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Sentry plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-seo",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "SEO plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/plugin-stripe",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Stripe plugin for Payload",
|
||||
"keywords": [
|
||||
"payload",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/richtext-lexical",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "The officially supported Lexical richtext adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -284,10 +284,22 @@ export const InlineBlockComponent: React.FC<Props> = (props) => {
|
||||
)
|
||||
// cleanup effect
|
||||
useEffect(() => {
|
||||
const isStateOutOfSync = (formData: InlineBlockFields, initialState: FormState) => {
|
||||
return Object.keys(initialState).some(
|
||||
(key) => initialState[key] && formData[key] !== initialState[key].value,
|
||||
)
|
||||
}
|
||||
|
||||
return () => {
|
||||
// If the component is unmounted (either via removeInlineBlock or via lexical itself) and the form state got changed before,
|
||||
// we need to reset the initial state to force a re-fetch of the initial state when it gets mounted again (e.g. via lexical history undo).
|
||||
// Otherwise it would use an outdated initial state.
|
||||
if (initialState && isStateOutOfSync(formData, initialState)) {
|
||||
setInitialState(false)
|
||||
}
|
||||
abortAndIgnore(onChangeAbortControllerRef.current)
|
||||
}
|
||||
}, [])
|
||||
}, [formData, initialState])
|
||||
|
||||
/**
|
||||
* HANDLE FORM SUBMIT
|
||||
|
||||
@@ -56,22 +56,15 @@ export const BlocksPlugin: PluginComponent = () => {
|
||||
|
||||
if ($isRangeSelection(selection)) {
|
||||
const blockNode = $createBlockNode(payload)
|
||||
|
||||
// we need to get the focus node before inserting the block node, as $insertNodeToNearestRoot can change the focus node
|
||||
const { focus } = selection
|
||||
const focusNode = focus.getNode()
|
||||
// Insert blocks node BEFORE potentially removing focusNode, as $insertNodeToNearestRoot errors if the focusNode doesn't exist
|
||||
$insertNodeToNearestRoot(blockNode)
|
||||
|
||||
const { focus } = selection
|
||||
const focusNode = focus.getNode()
|
||||
|
||||
// First, delete currently selected node if it's an empty paragraph and if there are sufficient
|
||||
// paragraph nodes (more than 1) left in the parent node, so that we don't "trap" the user
|
||||
if (
|
||||
$isParagraphNode(focusNode) &&
|
||||
focusNode.getTextContentSize() === 0 &&
|
||||
focusNode
|
||||
.getParentOrThrow()
|
||||
.getChildren()
|
||||
.filter((node) => $isParagraphNode(node)).length > 1
|
||||
) {
|
||||
// Delete the node it it's an empty paragraph
|
||||
if ($isParagraphNode(focusNode) && !focusNode.__first) {
|
||||
focusNode.remove()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,17 +26,35 @@ export const IndentPlugin: PluginComponent<IndentFeatureProps> = ({ clientProps
|
||||
if (!editor || !disabledNodes?.length) {
|
||||
return
|
||||
}
|
||||
return editor.registerCommand(
|
||||
INDENT_CONTENT_COMMAND,
|
||||
() => {
|
||||
return $handleIndentAndOutdent((block) => {
|
||||
if (!disabledNodes.includes(block.getType())) {
|
||||
const indent = block.getIndent()
|
||||
block.setIndent(indent + 1)
|
||||
return mergeRegister(
|
||||
editor.registerCommand(
|
||||
INDENT_CONTENT_COMMAND,
|
||||
() => {
|
||||
return $handleIndentAndOutdent((block) => {
|
||||
if (!disabledNodes.includes(block.getType())) {
|
||||
const indent = block.getIndent()
|
||||
block.setIndent(indent + 1)
|
||||
}
|
||||
})
|
||||
},
|
||||
COMMAND_PRIORITY_LOW,
|
||||
),
|
||||
// If we disable indenting for certain nodes, we need to ensure that these are not indented,
|
||||
// if they get transformed from an indented state (e.g. an indented list node gets transformed into a
|
||||
// paragraph node for which indenting is disabled).
|
||||
editor.registerUpdateListener(({ dirtyElements, editorState }) => {
|
||||
editor.update(() => {
|
||||
for (const [nodeKey] of dirtyElements) {
|
||||
const node = editorState._nodeMap.get(nodeKey)
|
||||
if ($isElementNode(node) && disabledNodes.includes(node.getType())) {
|
||||
const currentIndent = node.getIndent()
|
||||
if (currentIndent > 0) {
|
||||
node.setIndent(0)
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
COMMAND_PRIORITY_LOW,
|
||||
}),
|
||||
)
|
||||
}, [editor, disabledNodes])
|
||||
|
||||
|
||||
@@ -1,14 +1,9 @@
|
||||
'use client'
|
||||
|
||||
import type { BaseSelection, ElementNode, LexicalNode } from 'lexical'
|
||||
import type { ElementNode, LexicalNode } from 'lexical'
|
||||
|
||||
import { $findMatchingParent } from '@lexical/utils'
|
||||
import {
|
||||
$isElementNode,
|
||||
$isRangeSelection,
|
||||
INDENT_CONTENT_COMMAND,
|
||||
OUTDENT_CONTENT_COMMAND,
|
||||
} from 'lexical'
|
||||
import { $isElementNode, INDENT_CONTENT_COMMAND, OUTDENT_CONTENT_COMMAND } from 'lexical'
|
||||
|
||||
import type { ToolbarGroup } from '../../toolbars/types.js'
|
||||
|
||||
@@ -25,31 +20,15 @@ const toolbarGroups = ({ disabledNodes }: IndentFeatureProps): ToolbarGroup[] =>
|
||||
ChildComponent: IndentDecreaseIcon,
|
||||
isActive: () => false,
|
||||
isEnabled: ({ selection }) => {
|
||||
const nodes = selection?.getNodes()
|
||||
if (!nodes?.length) {
|
||||
return false
|
||||
}
|
||||
let atLeastOneNodeCanOutdent = false
|
||||
const isIndentable = (node: LexicalNode): node is ElementNode =>
|
||||
$isElementNode(node) && node.canIndent()
|
||||
for (const node of nodes) {
|
||||
if (isIndentable(node)) {
|
||||
if (node.getIndent() <= 0) {
|
||||
return false
|
||||
} else {
|
||||
atLeastOneNodeCanOutdent = true
|
||||
}
|
||||
}
|
||||
const nodes = selection?.getNodes() ?? []
|
||||
|
||||
const isOutdentable = (node: LexicalNode) => {
|
||||
return isIndentable(node) && node.getIndent() > 0
|
||||
}
|
||||
|
||||
if (!atLeastOneNodeCanOutdent) {
|
||||
if (
|
||||
$pointsAncestorMatch(selection, (node) => isIndentable(node) && node.getIndent() > 0)
|
||||
) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return atLeastOneNodeCanOutdent
|
||||
return nodes.some((node) => {
|
||||
return isOutdentable(node) || Boolean($findMatchingParent(node, isOutdentable))
|
||||
})
|
||||
},
|
||||
key: 'indentDecrease',
|
||||
label: ({ i18n }) => {
|
||||
@@ -64,11 +43,18 @@ const toolbarGroups = ({ disabledNodes }: IndentFeatureProps): ToolbarGroup[] =>
|
||||
ChildComponent: IndentIncreaseIcon,
|
||||
isActive: () => false,
|
||||
isEnabled: ({ selection }) => {
|
||||
const nodes = selection?.getNodes()
|
||||
if (!nodes?.length) {
|
||||
return false
|
||||
const nodes = selection?.getNodes() ?? []
|
||||
|
||||
const isIndentableAndNotDisabled = (node: LexicalNode) => {
|
||||
return isIndentable(node) && !(disabledNodes ?? []).includes(node.getType())
|
||||
}
|
||||
return !nodes.some((node) => disabledNodes?.includes(node.getType()))
|
||||
|
||||
return nodes.some((node) => {
|
||||
return (
|
||||
isIndentableAndNotDisabled(node) ||
|
||||
Boolean($findMatchingParent(node, isIndentableAndNotDisabled))
|
||||
)
|
||||
})
|
||||
},
|
||||
key: 'indentIncrease',
|
||||
label: ({ i18n }) => {
|
||||
@@ -101,13 +87,5 @@ export const IndentFeatureClient = createClientFeature<IndentFeatureProps>(({ pr
|
||||
}
|
||||
})
|
||||
|
||||
function $pointsAncestorMatch(
|
||||
selection: BaseSelection,
|
||||
fn: (node: LexicalNode) => boolean,
|
||||
): boolean {
|
||||
return (
|
||||
$isRangeSelection(selection) &&
|
||||
(!!$findMatchingParent(selection.anchor.getNode(), fn) ||
|
||||
!!$findMatchingParent(selection.focus.getNode(), fn))
|
||||
)
|
||||
}
|
||||
const isIndentable = (node: LexicalNode): node is ElementNode =>
|
||||
$isElementNode(node) && node.canIndent()
|
||||
|
||||
@@ -53,22 +53,14 @@ export const RelationshipPlugin: PluginComponent<RelationshipFeatureProps> = ({
|
||||
|
||||
if ($isRangeSelection(selection)) {
|
||||
const relationshipNode = $createRelationshipNode(payload)
|
||||
// we need to get the focus node before inserting the block node, as $insertNodeToNearestRoot can change the focus node
|
||||
const { focus } = selection
|
||||
const focusNode = focus.getNode()
|
||||
// Insert relationship node BEFORE potentially removing focusNode, as $insertNodeToNearestRoot errors if the focusNode doesn't exist
|
||||
$insertNodeToNearestRoot(relationshipNode)
|
||||
|
||||
const { focus } = selection
|
||||
const focusNode = focus.getNode()
|
||||
|
||||
// First, delete currently selected node if it's an empty paragraph and if there are sufficient
|
||||
// paragraph nodes (more than 1) left in the parent node, so that we don't "trap" the user
|
||||
if (
|
||||
$isParagraphNode(focusNode) &&
|
||||
focusNode.getTextContentSize() === 0 &&
|
||||
focusNode
|
||||
.getParentOrThrow()
|
||||
.getChildren()
|
||||
.filter((node) => $isParagraphNode(node)).length > 1
|
||||
) {
|
||||
// Delete the node it it's an empty paragraph
|
||||
if ($isParagraphNode(focusNode) && !focusNode.__first) {
|
||||
focusNode.remove()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,18 +53,14 @@ export const UploadPlugin: PluginComponent<UploadFeaturePropsClient> = ({ client
|
||||
value: payload.value,
|
||||
},
|
||||
})
|
||||
// we need to get the focus node before inserting the block node, as $insertNodeToNearestRoot can change the focus node
|
||||
const { focus } = selection
|
||||
const focusNode = focus.getNode()
|
||||
// Insert upload node BEFORE potentially removing focusNode, as $insertNodeToNearestRoot errors if the focusNode doesn't exist
|
||||
$insertNodeToNearestRoot(uploadNode)
|
||||
|
||||
const { focus } = selection
|
||||
const focusNode = focus.getNode()
|
||||
|
||||
// Delete the node it it's an empty paragraph and it has at least one sibling, so that we don't "trap" the user
|
||||
if (
|
||||
$isParagraphNode(focusNode) &&
|
||||
!focusNode.__first &&
|
||||
(focusNode.__prev || focusNode.__next)
|
||||
) {
|
||||
// Delete the node it it's an empty paragraph
|
||||
if ($isParagraphNode(focusNode) && !focusNode.__first) {
|
||||
focusNode.remove()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,13 +4,7 @@ import { LexicalErrorBoundary } from '@lexical/react/LexicalErrorBoundary.js'
|
||||
import { HistoryPlugin } from '@lexical/react/LexicalHistoryPlugin.js'
|
||||
import { OnChangePlugin } from '@lexical/react/LexicalOnChangePlugin.js'
|
||||
import { RichTextPlugin } from '@lexical/react/LexicalRichTextPlugin.js'
|
||||
import {
|
||||
$createParagraphNode,
|
||||
$getRoot,
|
||||
BLUR_COMMAND,
|
||||
COMMAND_PRIORITY_LOW,
|
||||
FOCUS_COMMAND,
|
||||
} from 'lexical'
|
||||
import { BLUR_COMMAND, COMMAND_PRIORITY_LOW, FOCUS_COMMAND } from 'lexical'
|
||||
import * as React from 'react'
|
||||
import { useEffect, useState } from 'react'
|
||||
|
||||
@@ -24,6 +18,7 @@ import { AddBlockHandlePlugin } from './plugins/handles/AddBlockHandlePlugin/ind
|
||||
import { DraggableBlockPlugin } from './plugins/handles/DraggableBlockPlugin/index.js'
|
||||
import { InsertParagraphAtEndPlugin } from './plugins/InsertParagraphAtEnd/index.js'
|
||||
import { MarkdownShortcutPlugin } from './plugins/MarkdownShortcut/index.js'
|
||||
import { NormalizeSelectionPlugin } from './plugins/NormalizeSelection/index.js'
|
||||
import { SlashMenuPlugin } from './plugins/SlashMenu/index.js'
|
||||
import { TextPlugin } from './plugins/TextPlugin/index.js'
|
||||
import { LexicalContentEditable } from './ui/ContentEditable.js'
|
||||
@@ -112,6 +107,7 @@ export const LexicalEditor: React.FC<
|
||||
}
|
||||
ErrorBoundary={LexicalErrorBoundary}
|
||||
/>
|
||||
<NormalizeSelectionPlugin />
|
||||
<InsertParagraphAtEndPlugin />
|
||||
<DecoratorPlugin />
|
||||
<TextPlugin features={editorConfig.features} />
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
import { useLexicalComposerContext } from '@lexical/react/LexicalComposerContext'
|
||||
import { $getSelection, $isRangeSelection, RootNode } from 'lexical'
|
||||
import { useEffect } from 'react'
|
||||
|
||||
/**
|
||||
* By default, Lexical throws an error if the selection ends in deleted nodes.
|
||||
* This is very aggressive considering there are reasons why this can happen
|
||||
* outside of Payload's control (custom features or conflicting features, for example).
|
||||
* In the case of selections on nonexistent nodes, this plugin moves the selection to
|
||||
* the end of the editor and displays a warning instead of an error.
|
||||
*/
|
||||
export function NormalizeSelectionPlugin() {
|
||||
const [editor] = useLexicalComposerContext()
|
||||
|
||||
useEffect(() => {
|
||||
return editor.registerNodeTransform(RootNode, (root) => {
|
||||
const selection = $getSelection()
|
||||
if ($isRangeSelection(selection)) {
|
||||
const anchorNode = selection.anchor.getNode()
|
||||
const focusNode = selection.focus.getNode()
|
||||
if (!anchorNode.isAttached() || !focusNode.isAttached()) {
|
||||
root.selectEnd()
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'updateEditor: selection has been moved to the end of the editor because the previously selected nodes have been removed and ' +
|
||||
"selection wasn't moved to another node. Ensure selection changes after removing/replacing a selected node.",
|
||||
)
|
||||
}
|
||||
}
|
||||
return false
|
||||
})
|
||||
}, [editor])
|
||||
|
||||
return null
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/richtext-slate",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "The officially supported Slate richtext adapter for Payload",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-azure",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Payload storage adapter for Azure Blob Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-gcs",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Payload storage adapter for Google Cloud Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-s3",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Payload storage adapter for Amazon S3",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-uploadthing",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Payload storage adapter for uploadthing",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/storage-vercel-blob",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"description": "Payload storage adapter for Vercel Blob Storage",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/translations",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -2,44 +2,44 @@ import type { DefaultTranslationsObject, Language } from '../types.js'
|
||||
|
||||
export const deTranslations: DefaultTranslationsObject = {
|
||||
authentication: {
|
||||
account: 'Konto',
|
||||
account: 'Benutzerkonto',
|
||||
accountOfCurrentUser: 'Aktuelles Benutzerkonto',
|
||||
accountVerified: 'Konto erfolgreich verifiziert.',
|
||||
accountVerified: 'Benutzerkonto erfolgreich verifiziert.',
|
||||
alreadyActivated: 'Bereits aktiviert',
|
||||
alreadyLoggedIn: 'Bereits angemeldet',
|
||||
apiKey: 'API-Key',
|
||||
authenticated: 'Authentifiziert',
|
||||
backToLogin: 'Zurück zur Anmeldung',
|
||||
beginCreateFirstUser: 'Erstelle deinen ersten Benutzer um zu beginnen',
|
||||
beginCreateFirstUser: 'Erstelle deinen ersten Benutzer, um zu beginnen',
|
||||
changePassword: 'Passwort ändern',
|
||||
checkYourEmailForPasswordReset:
|
||||
'Wenn die E-Mail-Adresse mit einem Konto verknüpft ist, erhalten Sie in Kürze Anweisungen zur Zurücksetzung Ihres Passworts. Bitte überprüfen Sie Ihren Spam- oder Junk-Mail-Ordner, wenn Sie die E-Mail nicht in Ihrem Posteingang sehen.',
|
||||
'Wenn die E-Mail-Adresse mit einem Benutzerkonto verknüpft ist, erhältst du in Kürze Anweisungen zur Zurücksetzung deines Passworts. Bitte überprüfe deinen Spam-Ordner, wenn du die E-Mail nicht in deinem Posteingang siehst.',
|
||||
confirmGeneration: 'Generierung bestätigen',
|
||||
confirmPassword: 'Passwort bestätigen',
|
||||
createFirstUser: 'Ersten Benutzer erstellen',
|
||||
emailNotValid: 'Die angegebene E-Mail-Adresse ist ungültig',
|
||||
emailOrUsername: 'E-Mail oder Benutzername',
|
||||
emailSent: 'E-Mail verschickt',
|
||||
emailSent: 'E-Mail versendet',
|
||||
emailVerified: 'E-Mail erfolgreich verifiziert.',
|
||||
enableAPIKey: 'API-Key aktivieren',
|
||||
failedToUnlock: 'Konnte nicht entsperren',
|
||||
failedToUnlock: 'Entsperrung fehlgeschlagen',
|
||||
forceUnlock: 'Entsperrung erzwingen',
|
||||
forgotPassword: 'Passwort vergessen',
|
||||
forgotPasswordEmailInstructions:
|
||||
'Bitte gib deine E-Mail-Adresse an. Du wirst eine E-Mail mit Instruktionen zum Zurücksetzen deines Passworts erhalten.',
|
||||
forgotPasswordQuestion: 'Passwort vergessen?',
|
||||
forgotPasswordUsernameInstructions:
|
||||
'Bitte geben Sie unten Ihren Benutzernamen ein. Anweisungen zum Zurücksetzen Ihres Passworts werden an die mit Ihrem Benutzernamen verknüpfte E-Mail-Adresse gesendet.',
|
||||
'Bitte gib deinen Benutzernamen ein. Anweisungen zum Zurücksetzen deines Passworts werden an die mit deinem Benutzernamen verknüpfte E-Mail-Adresse gesendet.',
|
||||
generate: 'Generieren',
|
||||
generateNewAPIKey: 'Neuen API-Key generieren',
|
||||
generatingNewAPIKeyWillInvalidate:
|
||||
'Die Generierung eines neuen API-Keys wird den vorherigen Key <1>ungültig</1> machen. Bist du sicher, dass du fortfahren möchtest?',
|
||||
lockUntil: 'Sperre bis',
|
||||
'Wenn du einen neuen Key generierst, wird der vorherige <1>ungültig</1>. Bist du sicher, dass du fortfahren möchtest?',
|
||||
lockUntil: 'Sperren bis',
|
||||
logBackIn: 'Wieder anmelden',
|
||||
loggedIn:
|
||||
'Um dich mit einem anderen Benutzer anzumelden, musst du dich zuerst <0>abmelden</0>.',
|
||||
'Um dich mit einem anderen Benutzerkonto anzumelden, musst du dich zuerst <0>abmelden</0>.',
|
||||
loggedInChangePassword:
|
||||
'Um dein Passwort zu ändern, gehe in dein <0>Konto</0> und ändere dort dein Passwort.',
|
||||
'Um dein Passwort zu ändern, gehe zu deinem <0>Benutzerkonto</0> und ändere dort dein Passwort.',
|
||||
loggedOutInactivity: 'Du wurdest aufgrund von Inaktivität abgemeldet.',
|
||||
loggedOutSuccessfully: 'Du wurdest erfolgreich abgemeldet.',
|
||||
loggingOut: 'Abmelden...',
|
||||
@@ -51,19 +51,19 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
logOut: 'Abmelden',
|
||||
logout: 'Abmelden',
|
||||
logoutSuccessful: 'Abmeldung erfolgreich.',
|
||||
logoutUser: 'Benutzerabmeldung',
|
||||
logoutUser: 'Benutzer abmelden',
|
||||
newAccountCreated:
|
||||
'Ein neues Konto wurde gerade für dich auf <a href="{{serverURL}}">{{serverURL}}</a> erstellt. Bitte klicke auf den folgenden Link oder kopiere die URL in deinen Browser um deine E-Mail-Adresse zu verifizieren: <a href="{{verificationURL}}">{{verificationURL}}</a><br> Nachdem du deine E-Mail-Adresse verifiziert hast, kannst du dich erfolgreich anmelden.',
|
||||
'Ein neues Konto wurde gerade für dich auf <a href="{{serverURL}}">{{serverURL}}</a> erstellt. Bitte klicke auf den folgenden Link oder kopiere die URL in deinen Browser, um deine E-Mail-Adresse zu verifizieren: <a href="{{verificationURL}}">{{verificationURL}}</a><br> Nachdem du deine E-Mail-Adresse verifiziert hast, kannst du dich erfolgreich anmelden.',
|
||||
newAPIKeyGenerated: 'Neuer API-Key wurde generiert',
|
||||
newPassword: 'Neues Passwort',
|
||||
passed: 'Authentifizierung erfolgreich',
|
||||
passwordResetSuccessfully: 'Passwort erfolgreich zurückgesetzt.',
|
||||
resetPassword: 'Passwort zurücksetzen',
|
||||
resetPasswordExpiration: 'Passwort-Ablauf zurücksetzen',
|
||||
resetPasswordExpiration: 'Passwort-Gültigkeitsdauer zurücksetzen',
|
||||
resetPasswordToken: 'Passwort-Token zurücksetzen',
|
||||
resetYourPassword: 'Dein Passwort zurücksetzen',
|
||||
stayLoggedIn: 'Angemeldet bleiben',
|
||||
successfullyRegisteredFirstUser: 'Erster Benutzer erfolgreich registriert.',
|
||||
successfullyRegisteredFirstUser: 'Ersten Benutzer erfolgreich registriert.',
|
||||
successfullyUnlocked: 'Erfolgreich entsperrt',
|
||||
tokenRefreshSuccessful: 'Token-Aktualisierung erfolgreich.',
|
||||
unableToVerify: 'Konnte nicht verifiziert werden',
|
||||
@@ -75,15 +75,15 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
verifyUser: 'Benutzer verifizieren',
|
||||
verifyYourEmail: 'Deine E-Mail-Adresse verifizieren',
|
||||
youAreInactive:
|
||||
'Du warst seit einiger Zeit inaktiv und wirst in kurzer Zeit zu deiner eigenen Sicherheit abgemeldet. Möchtest du angemeldet bleiben?',
|
||||
'Du warst einige Zeit inaktiv und wirst in Kürze zu deiner eigenen Sicherheit abgemeldet. Möchtest du angemeldet bleiben?',
|
||||
youAreReceivingResetPassword:
|
||||
'Du erhältst diese Nachricht, weil du (oder jemand anderes) das Zurücksetzen deines Passworts für dein Benutzerkonto angefordert hat. Bitte klicke auf den folgenden Link, oder kopiere die URL in deinen Browser den Prozess abzuschließen:',
|
||||
'Du erhältst diese Nachricht, weil du (oder jemand anderes) das Zurücksetzen deines Passworts für dein Benutzerkonto angefordert hat. Bitte klicke auf den folgenden Link, oder kopiere die URL in deinen Browser, um den Prozess abzuschließen:',
|
||||
youDidNotRequestPassword:
|
||||
'Solltest du dies nicht angefordert haben, ignoriere diese E-Mail und dein Passwort bleibt unverändert.',
|
||||
},
|
||||
error: {
|
||||
accountAlreadyActivated: 'Dieses Konto wurde bereits aktiviert',
|
||||
autosaving: 'Es gab ein Problem während der automatischen Speicherung für dieses Dokument',
|
||||
accountAlreadyActivated: 'Dieses Benutzerkonto wurde bereits aktiviert',
|
||||
autosaving: 'Es gab ein Problem bei der automatischen Speicherung für dieses Dokument',
|
||||
correctInvalidFields: 'Bitte ungültige Felder korrigieren.',
|
||||
deletingFile: 'Beim Löschen der Datei ist ein Fehler aufgetreten.',
|
||||
deletingTitle:
|
||||
@@ -96,8 +96,8 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
invalidFileTypeValue: 'Ungültiger Datei-Typ: {{value}}',
|
||||
invalidRequestArgs: 'Ungültige Argumente in der Anfrage: {{args}}',
|
||||
loadingDocument: 'Es gab ein Problem, das Dokument mit der ID {{id}} zu laden.',
|
||||
localesNotSaved_one: 'Das folgende Gebietsschema konnte nicht gespeichert werden:',
|
||||
localesNotSaved_other: 'Die folgenden Gebietsschemata konnten nicht gespeichert werden:',
|
||||
localesNotSaved_one: 'Die folgende Sprache konnte nicht gespeichert werden:',
|
||||
localesNotSaved_other: 'Die folgenden Sprachen konnten nicht gespeichert werden:',
|
||||
logoutFailed: 'Abmeldung fehlgeschlagen.',
|
||||
missingEmail: 'E-Mail-Adresse fehlt.',
|
||||
missingIDOfDocument: 'ID des zu speichernden Dokuments fehlt.',
|
||||
@@ -109,23 +109,23 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
notAllowedToPerformAction: 'Du hast keine Berechtigung, diese Aktion auszuführen.',
|
||||
notFound: 'Die angeforderte Ressource wurde nicht gefunden.',
|
||||
noUser: 'Kein Benutzer',
|
||||
previewing: 'Es gab ein Problem beim Vorschauen dieses Dokuments.',
|
||||
problemUploadingFile: 'Es gab ein Problem während des Hochladens der Datei.',
|
||||
previewing: 'Bei der Vorschau dieses Dokuments ist ein Fehler aufgetreten.',
|
||||
problemUploadingFile: 'Beim Hochladen der Datei ist ein Fehler aufgetreten.',
|
||||
tokenInvalidOrExpired: 'Token ist entweder ungültig oder abgelaufen.',
|
||||
tokenNotProvided: 'Token nicht bereitgestellt.',
|
||||
unableToDeleteCount: '{{count}} von {{total}} {{label}} konnte nicht gelöscht werden.',
|
||||
tokenNotProvided: 'Kein Token vorhanden.',
|
||||
unableToDeleteCount: '{{count}} von {{total}} {{label}} konnten nicht gelöscht werden.',
|
||||
unableToReindexCollection:
|
||||
'Fehler beim Neuindizieren der Sammlung {{collection}}. Vorgang abgebrochen.',
|
||||
unableToUpdateCount: '{{count}} von {{total}} {{label}} konnte nicht aktualisiert werden.',
|
||||
unableToUpdateCount: '{{count}} von {{total}} {{label}} konnten nicht aktualisiert werden.',
|
||||
unauthorized: 'Nicht autorisiert - du musst angemeldet sein, um diese Anfrage zu stellen.',
|
||||
unauthorizedAdmin: 'Nicht autorisiert, dieser Benutzer hat keinen Zugriff auf das Admin-Panel.',
|
||||
unknown: 'Ein unbekannter Fehler ist aufgetreten.',
|
||||
unPublishingDocument: 'Es gab ein Problem, dieses Dokument auf Entwurf zu setzen.',
|
||||
unPublishingDocument: 'Bei der Aufhebung der Veröffentlichung dieses Dokuments ist ein Fehler aufgetreten.',
|
||||
unspecific: 'Ein Fehler ist aufgetreten.',
|
||||
unverifiedEmail: 'Bitte verifizieren Sie Ihre E-Mail, bevor Sie sich anmelden.',
|
||||
unverifiedEmail: 'Bitte verifiziere deine E-Mail, bevor du dich anmeldest.',
|
||||
userEmailAlreadyRegistered: 'Ein Benutzer mit der angegebenen E-Mail ist bereits registriert.',
|
||||
userLocked:
|
||||
'Dieser Benutzer ist auf Grund zu vieler unerfolgreicher Anmelde-Versuche gesperrt.',
|
||||
'Dieser Benutzer ist gesperrt, weil er zu viele fehlgeschlagene Anmeldeversuche hat.',
|
||||
usernameAlreadyRegistered:
|
||||
'Ein Benutzer mit dem angegebenen Benutzernamen ist bereits registriert.',
|
||||
usernameOrPasswordIncorrect: 'Der angegebene Benutzername oder das Passwort ist falsch.',
|
||||
@@ -134,58 +134,58 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
},
|
||||
fields: {
|
||||
addLabel: '{{label}} hinzufügen',
|
||||
addLink: 'Link Hinzufügen',
|
||||
addNew: 'Neu erstellen',
|
||||
addLink: 'Link hinzufügen',
|
||||
addNew: 'Neuen Eintrag hinzufügen',
|
||||
addNewLabel: '{{label}} erstellen',
|
||||
addRelationship: 'Verknüpfung Hinzufügen',
|
||||
addUpload: 'Hochladen Hinzufügen',
|
||||
addRelationship: 'Verknüpfung hinzufügen',
|
||||
addUpload: 'Neue Datei hochladen',
|
||||
block: 'Block',
|
||||
blocks: 'Blöcke',
|
||||
blockType: 'Block-Typ',
|
||||
chooseBetweenCustomTextOrDocument:
|
||||
'Wähle zwischen einer eigenen Text-URL oder verlinke zu einem anderen Dokument.',
|
||||
chooseDocumentToLink: 'Wähle ein Dokument zum Verlinken',
|
||||
'Wähle zwischen der Eingabe einer benutzerdefinierten URL oder verknüpfe ein anderes Dokument.',
|
||||
chooseDocumentToLink: 'Wähle ein Dokument, das du verlinken möchtest',
|
||||
chooseFromExisting: 'Aus vorhandenen auswählen',
|
||||
chooseLabel: '{{label}} auswählen',
|
||||
collapseAll: 'Alle einklappen',
|
||||
customURL: 'Eigene URL',
|
||||
editLabelData: '{{label}} bearbeiten',
|
||||
editLink: 'Bearbeite Link',
|
||||
editRelationship: 'Beziehung Hinzufügen',
|
||||
editLink: 'Link bearbeiten',
|
||||
editRelationship: 'Verknüpfung bearbeiten',
|
||||
enterURL: 'URL eingeben',
|
||||
internalLink: 'Interner Link',
|
||||
internalLink: 'Interne Verlinkung',
|
||||
itemsAndMore: '{{items}} und {{count}} mehr',
|
||||
labelRelationship: '{{label}} Verknüpfung',
|
||||
labelRelationship: '{{label}}-Verknüpfung',
|
||||
latitude: 'Breitengrad',
|
||||
linkedTo: 'Verweist auf <0>{{label}}</0>',
|
||||
linkType: 'Linktyp',
|
||||
longitude: 'Längengrad',
|
||||
newLabel: '{{label}} erstellen',
|
||||
openInNewTab: 'Öffne im neuen Tab',
|
||||
openInNewTab: 'In neuem Tab öffnen',
|
||||
passwordsDoNotMatch: 'Passwörter stimmen nicht überein.',
|
||||
relatedDocument: 'Verknüpftes Dokument',
|
||||
relationTo: 'Verknüpfung zu',
|
||||
removeRelationship: 'Beziehung Entfernen',
|
||||
removeUpload: 'Hochgeladene Datei Löschen',
|
||||
removeRelationship: 'Verknüpfung entfernen',
|
||||
removeUpload: 'Hochgeladene Datei löschen',
|
||||
saveChanges: 'Änderungen speichern',
|
||||
searchForBlock: 'Nach Block suchen',
|
||||
selectExistingLabel: '{{label}} auswählen (vorhandene)',
|
||||
selectFieldsToEdit: 'Wählen Sie die zu bearbeitenden Felder aus',
|
||||
selectFieldsToEdit: 'Wähle die zu bearbeitenden Felder aus',
|
||||
showAll: 'Alle anzeigen',
|
||||
swapRelationship: 'Beziehung Tauschen',
|
||||
swapUpload: 'Datei Austauschen',
|
||||
swapRelationship: 'Verknüpfung tauschen',
|
||||
swapUpload: 'Datei austauschen',
|
||||
textToDisplay: 'Angezeigter Text',
|
||||
toggleBlock: 'Block umschalten',
|
||||
uploadNewLabel: '{{label}} neu hochladen',
|
||||
},
|
||||
general: {
|
||||
aboutToDelete: 'Du bist dabei {{label}} <1>{{title}}</1> zu löschen. Bist du dir sicher?',
|
||||
aboutToDeleteCount_many: 'Sie sind dabei, {{count}} {{label}} zu löschen',
|
||||
aboutToDeleteCount_one: 'Sie sind dabei, {{count}} {{label}} zu löschen',
|
||||
aboutToDeleteCount_other: 'Sie sind dabei, {{count}} {{label}} zu löschen',
|
||||
addBelow: 'Darunter hinzufügen',
|
||||
aboutToDeleteCount_many: 'Du bist dabei, {{count}} {{label}} zu löschen',
|
||||
aboutToDeleteCount_one: 'Du bist dabei, {{count}} {{label}} zu löschen',
|
||||
aboutToDeleteCount_other: 'Du bist dabei, {{count}} {{label}} zu löschen',
|
||||
addBelow: 'Unterhalb hinzufügen',
|
||||
addFilter: 'Filter hinzufügen',
|
||||
adminTheme: 'Admin-Farbthema',
|
||||
adminTheme: 'Admin-Erscheinungsbild',
|
||||
all: 'Alle',
|
||||
allCollections: 'Alle Sammlungen',
|
||||
and: 'Und',
|
||||
@@ -218,23 +218,23 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
copy: 'Kopieren',
|
||||
copying: 'Kopieren',
|
||||
copyWarning:
|
||||
'Sie sind dabei, {{to}} mit {{from}} für {{label}} {{title}} zu überschreiben. Sind Sie sicher?',
|
||||
'Du bist dabei, {{to}} mit {{from}} für {{label}} {{title}} zu überschreiben. Bist du dir sicher?',
|
||||
create: 'Erstellen',
|
||||
created: 'Erstellt',
|
||||
createdAt: 'Erstellt am',
|
||||
createNew: 'Neu Erstellen',
|
||||
createNew: 'Neu erstellen',
|
||||
createNewLabel: '{{label}} neu erstellen',
|
||||
creating: 'Erstelle',
|
||||
creatingNewLabel: 'Erstelle {{label}}',
|
||||
currentlyEditing:
|
||||
'bearbeitet gerade dieses Dokument. Wenn Sie übernehmen, wird die Bearbeitung blockiert und nicht gespeicherte Änderungen können verloren gehen.',
|
||||
'bearbeitet gerade dieses Dokument. Wenn du übernimmst, wird die Bearbeitung blockiert und nicht gespeicherte Änderungen können verloren gehen.',
|
||||
custom: 'Benutzerdefiniert',
|
||||
dark: 'Dunkel',
|
||||
dashboard: 'Übersicht',
|
||||
delete: 'Löschen',
|
||||
deletedCountSuccessfully: '{{count}} {{label}} erfolgreich gelöscht.',
|
||||
deletedSuccessfully: 'Erfolgreich gelöscht.',
|
||||
deleting: 'Lösche...',
|
||||
deleting: 'Löschen...',
|
||||
depth: 'Tiefe',
|
||||
descending: 'Absteigend',
|
||||
deselectAllRows: 'Alle Zeilen abwählen',
|
||||
@@ -242,7 +242,7 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
documentLocked: 'Dokument gesperrt',
|
||||
documents: 'Dokumente',
|
||||
duplicate: 'Duplizieren',
|
||||
duplicateWithoutSaving: 'Dupliziere ohne Änderungen zu speichern',
|
||||
duplicateWithoutSaving: 'Duplizieren ohne Änderungen zu speichern',
|
||||
edit: 'Bearbeiten',
|
||||
editAll: 'Bearbeite alle',
|
||||
editedSince: 'Bearbeitet seit',
|
||||
@@ -257,20 +257,20 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
enterAValue: 'Gib einen Wert ein',
|
||||
error: 'Fehler',
|
||||
errors: 'Fehler',
|
||||
fallbackToDefaultLocale: 'Rückgriff auf das Standardgebietsschema',
|
||||
fallbackToDefaultLocale: 'Auf die Standardsprache zurückfallen',
|
||||
false: 'Falsch',
|
||||
filter: 'Filter',
|
||||
filters: 'Filter',
|
||||
filterWhere: 'Filter {{label}} wo',
|
||||
filterWhere: 'Filter {{label}}, wo',
|
||||
globals: 'Globale Dokumente',
|
||||
goBack: 'Zurück',
|
||||
isEditing: 'bearbeitet',
|
||||
isEditing: 'bearbeitet gerade',
|
||||
language: 'Sprache',
|
||||
lastModified: 'Zuletzt geändert',
|
||||
leaveAnyway: 'Trotzdem verlassen',
|
||||
leaveWithoutSaving: 'Ohne speichern verlassen',
|
||||
light: 'Hell',
|
||||
livePreview: 'Vorschau',
|
||||
livePreview: 'Live-Vorschau',
|
||||
loading: 'Lädt',
|
||||
locale: 'Sprache',
|
||||
locales: 'Sprachen',
|
||||
@@ -296,10 +296,10 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
open: 'Öffnen',
|
||||
or: 'oder',
|
||||
order: 'Reihenfolge',
|
||||
overwriteExistingData: 'Überschreiben Sie vorhandene Felddaten',
|
||||
overwriteExistingData: 'Vorhandene Eingaben überschreiben',
|
||||
pageNotFound: 'Seite nicht gefunden',
|
||||
password: 'Passwort',
|
||||
payloadSettings: 'Payload Einstellungen',
|
||||
payloadSettings: 'Payload-Einstellungen',
|
||||
perPage: 'Pro Seite: {{limit}}',
|
||||
previous: 'Vorherige',
|
||||
reindex: 'Neuindizieren',
|
||||
@@ -307,25 +307,25 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
remove: 'Entfernen',
|
||||
reset: 'Zurücksetzen',
|
||||
resetPreferences: 'Präferenzen zurücksetzen',
|
||||
resetPreferencesDescription: 'Dies setzt alle Ihre Präferenzen auf die Standardwerte zurück.',
|
||||
resetPreferencesDescription: 'Alle Präferenzen werden auf die Standardwerte zurückgesetzt.',
|
||||
resettingPreferences: 'Präferenzen werden zurückgesetzt.',
|
||||
row: 'Zeile',
|
||||
rows: 'Zeilen',
|
||||
save: 'Speichern',
|
||||
saving: 'Speichert...',
|
||||
schedulePublishFor: 'Planen Sie die Veröffentlichung für {{title}}',
|
||||
saving: 'Speichern...',
|
||||
schedulePublishFor: 'Plane die Veröffentlichung für {{title}}',
|
||||
searchBy: 'Suche nach {{label}}',
|
||||
selectAll: 'Alle auswählen {{count}} {{label}}',
|
||||
selectAllRows: 'Wählen Sie alle Zeilen aus',
|
||||
selectAll: 'Alle {{count}} {{label}} auswählen',
|
||||
selectAllRows: 'Alle Zeilen auswählen',
|
||||
selectedCount: '{{count}} {{label}} ausgewählt',
|
||||
selectLabel: 'Wählen Sie {{label}}',
|
||||
selectLabel: 'Wähle {{label}}',
|
||||
selectValue: 'Wert auswählen',
|
||||
showAllLabel: 'Zeige alle {{label}}',
|
||||
sorryNotFound: 'Entschuldige, es entspricht nichts deiner Anfrage',
|
||||
sorryNotFound: 'Es tut uns leid, aber wir haben nichts gefunden, was deiner Anfrage entspricht.',
|
||||
sort: 'Sortieren',
|
||||
sortByLabelDirection: 'Sortieren nach {{label}} {{direction}}',
|
||||
stayOnThisPage: 'Auf dieser Seite bleiben',
|
||||
submissionSuccessful: 'Einrichung erfolgreich.',
|
||||
submissionSuccessful: 'Übermittlung erfolgreich.',
|
||||
submit: 'Senden',
|
||||
submitting: 'Wird aktualisiert...',
|
||||
success: 'Erfolg',
|
||||
@@ -341,7 +341,7 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
true: 'Wahr',
|
||||
unauthorized: 'Nicht autorisiert',
|
||||
unsavedChanges:
|
||||
'Sie haben ungespeicherte Änderungen. Speichern oder verwerfen Sie diese, bevor Sie fortfahren.',
|
||||
'Du hast ungespeicherte Änderungen. Speichern oder verwerfe sie, bevor du fortfahrst.',
|
||||
unsavedChangesDuplicate:
|
||||
'Du hast ungespeicherte Änderungen, möchtest du mit dem Duplizieren fortfahren?',
|
||||
untitled: 'ohne Titel',
|
||||
@@ -350,7 +350,7 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
updatedCountSuccessfully: '{{count}} {{label}} erfolgreich aktualisiert.',
|
||||
updatedLabelSuccessfully: '{{label}} erfolgreich aktualisiert.',
|
||||
updatedSuccessfully: 'Erfolgreich aktualisiert.',
|
||||
updateForEveryone: 'Aktualisierung für alle',
|
||||
updateForEveryone: 'Für alle aktualisieren',
|
||||
updating: 'Aktualisierung',
|
||||
uploading: 'Hochladen',
|
||||
uploadingBulk: 'Hochladen von {{current}} von {{total}}',
|
||||
@@ -362,13 +362,13 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
welcome: 'Willkommen',
|
||||
},
|
||||
localization: {
|
||||
cannotCopySameLocale: 'Kann nicht in dieselbe Gebietsschema kopieren',
|
||||
cannotCopySameLocale: 'Kann nicht in dieselbe Sprache kopiert werden',
|
||||
copyFrom: 'Kopieren von',
|
||||
copyFromTo: 'Kopieren von {{from}} zu {{to}}',
|
||||
copyTo: 'Kopieren nach',
|
||||
copyToLocale: 'Kopieren in das Gebietsschema',
|
||||
localeToPublish: 'Zu veröffentlichende Lokalität',
|
||||
selectLocaleToCopy: 'Wählen Sie den Ort zum Kopieren aus',
|
||||
copyToLocale: 'Erstelle Kopie für Sprach-Variante',
|
||||
localeToPublish: 'Zu veröffentlichende Sprache',
|
||||
selectLocaleToCopy: 'Wähle den Ort zum Kopieren aus',
|
||||
},
|
||||
operators: {
|
||||
contains: 'enthält',
|
||||
@@ -390,12 +390,12 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
upload: {
|
||||
addFile: 'Datei hinzufügen',
|
||||
addFiles: 'Dateien hinzufügen',
|
||||
bulkUpload: 'Massenupload',
|
||||
bulkUpload: 'Mehrere Dateien hochladen',
|
||||
crop: 'Zuschneiden',
|
||||
cropToolDescription:
|
||||
'Ziehen Sie die Ecken des ausgewählten Bereichs, zeichnen Sie einen neuen Bereich oder passen Sie die Werte unten an.',
|
||||
dragAndDrop: 'Ziehen Sie eine Datei per Drag-and-Drop',
|
||||
dragAndDropHere: 'oder ziehe eine Datei hier',
|
||||
'Ziehe die Ecken des ausgewählten Bereichs, zeichne einen neuen Bereich oder passe die Werte unten an.',
|
||||
dragAndDrop: 'Bewege eine Datei per Drag-and-Drop',
|
||||
dragAndDropHere: 'oder lege eine Datei hier ab',
|
||||
editImage: 'Bild bearbeiten',
|
||||
fileName: 'Dateiname',
|
||||
fileSize: 'Dateigröße',
|
||||
@@ -403,7 +403,7 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
fileToUpload: 'Datei zum Hochladen',
|
||||
focalPoint: 'Brennpunkt',
|
||||
focalPointDescription:
|
||||
'Ziehen Sie den Fokuspunkt direkt auf die Vorschau oder passen Sie die Werte unten an.',
|
||||
'Setze den Fokuspunkt direkt auf der Vorschau oder passe die Werte unten an.',
|
||||
height: 'Höhe',
|
||||
lessInfo: 'Weniger Info',
|
||||
moreInfo: 'Mehr Info',
|
||||
@@ -420,12 +420,12 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
},
|
||||
validation: {
|
||||
emailAddress: 'Bitte gib eine korrekte E-Mail-Adresse an.',
|
||||
enterNumber: 'Bitte gib eine gültige Nummer an,',
|
||||
enterNumber: 'Bitte gib eine gültige Nummer an.',
|
||||
fieldHasNo: 'Dieses Feld hat kein {{label}}',
|
||||
greaterThanMax: '{{value}} ist größer als der maximal erlaubte {{label}} von {{max}}.',
|
||||
invalidInput: 'Dieses Feld hat einen inkorrekten Wert.',
|
||||
invalidSelection: 'Dieses Feld hat eine inkorrekte Auswahl.',
|
||||
invalidSelections: "'Dieses Feld enthält die folgenden inkorrekten Auswahlen:'",
|
||||
invalidSelections: 'Dieses Feld enthält die folgenden inkorrekten Auswahlmöglichkeiten:',
|
||||
lessThanMin: '{{value}} ist kleiner als der minimal erlaubte {{label}} von {{min}}.',
|
||||
limitReached: 'Limit erreicht, es können nur {{max}} Elemente hinzugefügt werden.',
|
||||
longerThanMin: 'Dieser Wert muss länger als die minimale Länge von {{minLength}} Zeichen sein.',
|
||||
@@ -433,26 +433,26 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
required: 'Pflichtfeld',
|
||||
requiresAtLeast: 'Dieses Feld muss mindestens {{count}} {{label}} enthalten.',
|
||||
requiresNoMoreThan: 'Dieses Feld kann nicht mehr als {{count}} {{label}} enthalten.',
|
||||
requiresTwoNumbers: 'Dieses Feld muss zwei Nummern enthalten.',
|
||||
requiresTwoNumbers: 'Dieses Feld muss zwei Zahlen enthalten.',
|
||||
shorterThanMax: 'Dieser Wert muss kürzer als die maximale Länge von {{maxLength}} sein.',
|
||||
timezoneRequired: 'Eine Zeitzone ist erforderlich.',
|
||||
trueOrFalse: 'Dieses Feld kann nur wahr oder falsch sein.',
|
||||
username:
|
||||
'Bitte geben Sie einen gültigen Benutzernamen ein. Dieser kann Buchstaben, Zahlen, Bindestriche, Punkte und Unterstriche enthalten.',
|
||||
validUploadID: "'Dieses Feld enthält keine valide Upload-ID.'",
|
||||
'Bitte gib einen gültigen Benutzernamen ein. Dieser kann Buchstaben, Zahlen, Bindestriche, Punkte und Unterstriche enthalten.',
|
||||
validUploadID: 'Dieses Feld enthält keine valide Upload-ID.',
|
||||
},
|
||||
version: {
|
||||
type: 'Typ',
|
||||
aboutToPublishSelection:
|
||||
'Sie sind dabei, alle {{label}} in der Auswahl zu veröffentlichen. Bist du dir sicher?',
|
||||
'Du bist dabei, alle {{label}} in der Auswahl zu veröffentlichen. Bist du dir sicher?',
|
||||
aboutToRestore: 'Du bist dabei, {{label}} auf den Stand vom {{versionDate}} zurücksetzen.',
|
||||
aboutToRestoreGlobal:
|
||||
'Du bist dabei, das Globale Dokument {{label}} auf den Stand vom {{versionDate}} zurückzusetzen.',
|
||||
aboutToRevertToPublished:
|
||||
'Du bist dabei, dieses Dokument auf den Stand des ersten Veröffentlichungsdatums zurückzusetzen - Bist du sicher?',
|
||||
aboutToUnpublish: 'Du bist dabei dieses Dokument auf Entwurf zu setzen - bist du dir sicher?',
|
||||
'Du bist dabei, dieses Dokument auf den Stand des ersten Veröffentlichungsdatums zurückzusetzen. Bist du sicher?',
|
||||
aboutToUnpublish: 'Du bist dabei dieses Dokument auf Entwurf zu setzen. Bist du dir sicher?',
|
||||
aboutToUnpublishSelection:
|
||||
'Sie sind dabei, die Veröffentlichung aller {{label}} in der Auswahl aufzuheben. Bist du dir sicher?',
|
||||
'Du bist dabei, die Veröffentlichung aller {{label}} in der Auswahl aufzuheben. Bist du dir sicher?',
|
||||
autosave: 'Automatische Speicherung',
|
||||
autosavedSuccessfully: 'Erfolgreich automatisch gespeichert.',
|
||||
autosavedVersion: 'Automatisch gespeicherte Version',
|
||||
@@ -462,8 +462,8 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
compareVersion: 'Vergleiche Version zu:',
|
||||
confirmPublish: 'Veröffentlichung bestätigen',
|
||||
confirmRevertToSaved: 'Zurücksetzen auf die letzte Speicherung bestätigen',
|
||||
confirmUnpublish: 'Setzen auf Entwurf bestätigen',
|
||||
confirmVersionRestoration: ' Wiederherstellung der Version bestätigen',
|
||||
confirmUnpublish: 'Aufhebung der Veröffentlichung bestätigen',
|
||||
confirmVersionRestoration: 'Wiederherstellung der Version bestätigen',
|
||||
currentDocumentStatus: 'Aktueller Dokumentenstatus: {{docStatus}}',
|
||||
currentDraft: 'Aktueller Entwurf',
|
||||
currentPublishedVersion: 'Aktuell veröffentlichte Version',
|
||||
@@ -475,13 +475,13 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
noRowsFound: 'Kein {{label}} gefunden',
|
||||
noRowsSelected: 'Kein {{label}} ausgewählt',
|
||||
preview: 'Vorschau',
|
||||
previouslyPublished: 'Zuvor Veröffentlicht',
|
||||
problemRestoringVersion: 'Es gab ein Problem bei der Wiederherstellung dieser Version',
|
||||
previouslyPublished: 'Zuvor veröffentlicht',
|
||||
problemRestoringVersion: 'Bei der Wiederherstellung der Version ist ein Fehler aufgetreten',
|
||||
publish: 'Veröffentlichen',
|
||||
publishAllLocales: 'Veröffentlichen Sie alle Lokalisierungen',
|
||||
publishAllLocales: 'Alle Sprachen veröffentlichen',
|
||||
publishChanges: 'Änderungen veröffentlichen',
|
||||
published: 'Veröffentlicht',
|
||||
publishIn: 'Veröffentlichen in {{locale}}',
|
||||
publishIn: 'Veröffentlichen auf {{locale}}',
|
||||
publishing: 'Veröffentlichung',
|
||||
restoreAsDraft: 'Als Entwurf wiederherstellen',
|
||||
restoredSuccessfully: 'Erfolgreich wiederhergestellt.',
|
||||
@@ -497,20 +497,20 @@ export const deTranslations: DefaultTranslationsObject = {
|
||||
showingVersionsFor: 'Versionen anzeigen für:',
|
||||
showLocales: 'Sprachen anzeigen:',
|
||||
status: 'Status',
|
||||
unpublish: 'Auf Entwurf setzen',
|
||||
unpublishing: 'Setze auf Entwurf...',
|
||||
unpublish: 'Veröffentlichung aufheben',
|
||||
unpublishing: 'Veröffentlichung aufheben...',
|
||||
version: 'Version',
|
||||
versionCount_many: '{{count}} Versionen gefunden',
|
||||
versionCount_none: 'Keine Versionen gefunden',
|
||||
versionCount_one: '{{count}} Version gefunden',
|
||||
versionCount_other: '{{count}} Versionen gefunden',
|
||||
versionCreatedOn: '{{version}} erstellt am:',
|
||||
versionID: 'Version ID',
|
||||
versionID: 'Version-ID',
|
||||
versions: 'Versionen',
|
||||
viewingVersion: 'Betrachte Version für {{entityLabel}} {{documentTitle}}',
|
||||
viewingVersionGlobal: '`Betrachte Version für das Globale Dokument {{entityLabel}}',
|
||||
viewingVersions: 'Betrachte Versionen für {{entityLabel}} {{documentTitle}}',
|
||||
viewingVersionsGlobal: '`Betrachte Versionen für das Globale Dokument {{entityLabel}}',
|
||||
viewingVersion: 'Version für {{entityLabel}} {{documentTitle}} ansehen',
|
||||
viewingVersionGlobal: 'Version für das Globale Dokument {{entityLabel}} ansehen',
|
||||
viewingVersions: 'Versionen für {{entityLabel}} {{documentTitle}} ansehen',
|
||||
viewingVersionsGlobal: 'Versionen für das Globale Dokument {{entityLabel}} ansehen',
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@payloadcms/ui",
|
||||
"version": "3.35.1",
|
||||
"version": "3.36.0",
|
||||
"homepage": "https://payloadcms.com",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -136,18 +136,38 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
|
||||
let newFilterOptions = filterOptions
|
||||
|
||||
if (value) {
|
||||
;(Array.isArray(value) ? value : [value]).forEach((val) => {
|
||||
;(Array.isArray(relationTo) ? relationTo : [relationTo]).forEach((relationTo) => {
|
||||
newFilterOptions = {
|
||||
...(filterOptions || {}),
|
||||
[relationTo]: {
|
||||
...(typeof filterOptions?.[relationTo] === 'object' ? filterOptions[relationTo] : {}),
|
||||
id: {
|
||||
not_in: [typeof val === 'object' ? val.value : val],
|
||||
},
|
||||
},
|
||||
const valuesByRelation = (Array.isArray(value) ? value : [value]).reduce((acc, val) => {
|
||||
if (typeof val === 'object' && val.relationTo) {
|
||||
if (!acc[val.relationTo]) {
|
||||
acc[val.relationTo] = []
|
||||
}
|
||||
})
|
||||
acc[val.relationTo].push(val.value)
|
||||
} else if (val) {
|
||||
const relation = Array.isArray(relationTo) ? undefined : relationTo
|
||||
if (relation) {
|
||||
if (!acc[relation]) {
|
||||
acc[relation] = []
|
||||
}
|
||||
acc[relation].push(val)
|
||||
}
|
||||
}
|
||||
return acc
|
||||
}, {})
|
||||
|
||||
;(Array.isArray(relationTo) ? relationTo : [relationTo]).forEach((relation) => {
|
||||
newFilterOptions = {
|
||||
...(newFilterOptions || {}),
|
||||
[relation]: {
|
||||
...(typeof filterOptions?.[relation] === 'object' ? filterOptions[relation] : {}),
|
||||
...(valuesByRelation[relation]
|
||||
? {
|
||||
id: {
|
||||
not_in: valuesByRelation[relation],
|
||||
},
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
@@ -174,8 +194,7 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
|
||||
|
||||
if (hasMany) {
|
||||
const withSelection = Array.isArray(value) ? value : []
|
||||
withSelection.push(formattedSelection)
|
||||
setValue(withSelection)
|
||||
setValue([...withSelection, formattedSelection])
|
||||
} else {
|
||||
setValue(formattedSelection)
|
||||
}
|
||||
@@ -252,6 +271,9 @@ const RelationshipFieldComponent: RelationshipFieldClientComponent = (props) =>
|
||||
limit: maxResultsPerRequest,
|
||||
locale,
|
||||
page: lastLoadedPageToUse,
|
||||
select: {
|
||||
[fieldToSearch]: true,
|
||||
},
|
||||
sort: fieldToSort,
|
||||
where: {
|
||||
and: [
|
||||
|
||||
@@ -183,6 +183,17 @@ function mergeData(
|
||||
return toLocaleData
|
||||
}
|
||||
|
||||
function removeIds(data: Data): Data {
|
||||
if (Array.isArray(data)) {
|
||||
return data.map(removeIds)
|
||||
}
|
||||
if (typeof data === 'object' && data !== null) {
|
||||
const { id: _id, ...rest } = data
|
||||
return Object.fromEntries(Object.entries(rest).map(([key, value]) => [key, removeIds(value)]))
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
export const copyDataFromLocaleHandler = async (args: CopyDataFromLocaleArgs) => {
|
||||
const { req } = args
|
||||
|
||||
@@ -288,7 +299,8 @@ export const copyDataFromLocale = async (args: CopyDataFromLocaleArgs) => {
|
||||
throw new Error(`Error fetching data from locale "${toLocale}"`)
|
||||
}
|
||||
|
||||
const { id, ...fromLocaleDataWithoutID } = fromLocaleData.value
|
||||
const fromLocaleDataWithoutID = removeIds(fromLocaleData.value)
|
||||
const toLocaleDataWithoutID = removeIds(toLocaleData.value)
|
||||
|
||||
return globalSlug
|
||||
? await payload.updateGlobal({
|
||||
@@ -296,8 +308,8 @@ export const copyDataFromLocale = async (args: CopyDataFromLocaleArgs) => {
|
||||
data: overrideData
|
||||
? fromLocaleDataWithoutID
|
||||
: mergeData(
|
||||
fromLocaleData.value,
|
||||
toLocaleData.value,
|
||||
fromLocaleDataWithoutID,
|
||||
toLocaleDataWithoutID,
|
||||
globals[globalSlug].config.fields,
|
||||
req,
|
||||
false,
|
||||
@@ -313,8 +325,8 @@ export const copyDataFromLocale = async (args: CopyDataFromLocaleArgs) => {
|
||||
data: overrideData
|
||||
? fromLocaleDataWithoutID
|
||||
: mergeData(
|
||||
fromLocaleData.value,
|
||||
toLocaleData.value,
|
||||
fromLocaleDataWithoutID,
|
||||
toLocaleDataWithoutID,
|
||||
collections[collectionSlug].config.fields,
|
||||
req,
|
||||
false,
|
||||
|
||||
246
payload-types.ts
Normal file
246
payload-types.ts
Normal file
@@ -0,0 +1,246 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supported timezones in IANA format.
|
||||
*
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "supportedTimezones".
|
||||
*/
|
||||
export type SupportedTimezones =
|
||||
| 'Pacific/Midway'
|
||||
| 'Pacific/Niue'
|
||||
| 'Pacific/Honolulu'
|
||||
| 'Pacific/Rarotonga'
|
||||
| 'America/Anchorage'
|
||||
| 'Pacific/Gambier'
|
||||
| 'America/Los_Angeles'
|
||||
| 'America/Tijuana'
|
||||
| 'America/Denver'
|
||||
| 'America/Phoenix'
|
||||
| 'America/Chicago'
|
||||
| 'America/Guatemala'
|
||||
| 'America/New_York'
|
||||
| 'America/Bogota'
|
||||
| 'America/Caracas'
|
||||
| 'America/Santiago'
|
||||
| 'America/Buenos_Aires'
|
||||
| 'America/Sao_Paulo'
|
||||
| 'Atlantic/South_Georgia'
|
||||
| 'Atlantic/Azores'
|
||||
| 'Atlantic/Cape_Verde'
|
||||
| 'Europe/London'
|
||||
| 'Europe/Berlin'
|
||||
| 'Africa/Lagos'
|
||||
| 'Europe/Athens'
|
||||
| 'Africa/Cairo'
|
||||
| 'Europe/Moscow'
|
||||
| 'Asia/Riyadh'
|
||||
| 'Asia/Dubai'
|
||||
| 'Asia/Baku'
|
||||
| 'Asia/Karachi'
|
||||
| 'Asia/Tashkent'
|
||||
| 'Asia/Calcutta'
|
||||
| 'Asia/Dhaka'
|
||||
| 'Asia/Almaty'
|
||||
| 'Asia/Jakarta'
|
||||
| 'Asia/Bangkok'
|
||||
| 'Asia/Shanghai'
|
||||
| 'Asia/Singapore'
|
||||
| 'Asia/Tokyo'
|
||||
| 'Asia/Seoul'
|
||||
| 'Australia/Brisbane'
|
||||
| 'Australia/Sydney'
|
||||
| 'Pacific/Guam'
|
||||
| 'Pacific/Noumea'
|
||||
| 'Pacific/Auckland'
|
||||
| 'Pacific/Fiji';
|
||||
|
||||
export interface Config {
|
||||
auth: {
|
||||
users: UserAuthOperations;
|
||||
};
|
||||
blocks: {};
|
||||
collections: {
|
||||
users: User;
|
||||
'payload-locked-documents': PayloadLockedDocument;
|
||||
'payload-preferences': PayloadPreference;
|
||||
'payload-migrations': PayloadMigration;
|
||||
};
|
||||
collectionsJoins: {};
|
||||
collectionsSelect: {
|
||||
users: UsersSelect<false> | UsersSelect<true>;
|
||||
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
||||
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
||||
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
|
||||
};
|
||||
db: {
|
||||
defaultIDType: string;
|
||||
};
|
||||
globals: {};
|
||||
globalsSelect: {};
|
||||
locale: 'en' | 'pl';
|
||||
user: User & {
|
||||
collection: 'users';
|
||||
};
|
||||
jobs: {
|
||||
tasks: unknown;
|
||||
workflows: unknown;
|
||||
};
|
||||
}
|
||||
export interface UserAuthOperations {
|
||||
forgotPassword: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
login: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
registerFirstUser: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
unlock: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
localizedField: string;
|
||||
roles: ('admin' | 'editor' | 'moderator' | 'user' | 'viewer')[];
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
email: string;
|
||||
resetPasswordToken?: string | null;
|
||||
resetPasswordExpiration?: string | null;
|
||||
salt?: string | null;
|
||||
hash?: string | null;
|
||||
loginAttempts?: number | null;
|
||||
lockUntil?: string | null;
|
||||
password?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-locked-documents".
|
||||
*/
|
||||
export interface PayloadLockedDocument {
|
||||
id: string;
|
||||
document?: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
} | null;
|
||||
globalSlug?: string | null;
|
||||
user: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
};
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-preferences".
|
||||
*/
|
||||
export interface PayloadPreference {
|
||||
id: string;
|
||||
user: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
};
|
||||
key?: string | null;
|
||||
value?:
|
||||
| {
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| unknown[]
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-migrations".
|
||||
*/
|
||||
export interface PayloadMigration {
|
||||
id: string;
|
||||
name?: string | null;
|
||||
batch?: number | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users_select".
|
||||
*/
|
||||
export interface UsersSelect<T extends boolean = true> {
|
||||
localizedField?: T;
|
||||
roles?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
email?: T;
|
||||
resetPasswordToken?: T;
|
||||
resetPasswordExpiration?: T;
|
||||
salt?: T;
|
||||
hash?: T;
|
||||
loginAttempts?: T;
|
||||
lockUntil?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-locked-documents_select".
|
||||
*/
|
||||
export interface PayloadLockedDocumentsSelect<T extends boolean = true> {
|
||||
document?: T;
|
||||
globalSlug?: T;
|
||||
user?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-preferences_select".
|
||||
*/
|
||||
export interface PayloadPreferencesSelect<T extends boolean = true> {
|
||||
user?: T;
|
||||
key?: T;
|
||||
value?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-migrations_select".
|
||||
*/
|
||||
export interface PayloadMigrationsSelect<T extends boolean = true> {
|
||||
name?: T;
|
||||
batch?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "auth".
|
||||
*/
|
||||
export interface Auth {
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
|
||||
declare module 'payload' {
|
||||
// @ts-ignore
|
||||
export interface GeneratedTypes extends Config {}
|
||||
}
|
||||
51
test/auth/forgot-password-localized/config.ts
Normal file
51
test/auth/forgot-password-localized/config.ts
Normal file
@@ -0,0 +1,51 @@
|
||||
import { fileURLToPath } from 'node:url'
|
||||
import path from 'path'
|
||||
|
||||
import { buildConfigWithDefaults } from '../../buildConfigWithDefaults.js'
|
||||
|
||||
export const collectionSlug = 'users'
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
export default buildConfigWithDefaults({
|
||||
admin: {
|
||||
user: collectionSlug,
|
||||
importMap: {
|
||||
baseDir: path.resolve(dirname),
|
||||
},
|
||||
},
|
||||
localization: {
|
||||
locales: ['en', 'pl'],
|
||||
defaultLocale: 'en',
|
||||
},
|
||||
collections: [
|
||||
{
|
||||
slug: collectionSlug,
|
||||
auth: {
|
||||
forgotPassword: {
|
||||
// Default options
|
||||
},
|
||||
},
|
||||
fields: [
|
||||
{
|
||||
name: 'localizedField',
|
||||
type: 'text',
|
||||
localized: true, // This field is localized and will require locale during validation
|
||||
required: true,
|
||||
},
|
||||
{
|
||||
name: 'roles',
|
||||
type: 'select',
|
||||
defaultValue: ['user'],
|
||||
hasMany: true,
|
||||
label: 'Role',
|
||||
options: ['admin', 'editor', 'moderator', 'user', 'viewer'],
|
||||
required: true,
|
||||
saveToJWT: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
debug: true,
|
||||
})
|
||||
78
test/auth/forgot-password-localized/int.spec.ts
Normal file
78
test/auth/forgot-password-localized/int.spec.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import type { Payload } from 'payload'
|
||||
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
import type { NextRESTClient } from '../../helpers/NextRESTClient.js'
|
||||
|
||||
import { devUser } from '../../credentials.js'
|
||||
import { initPayloadInt } from '../../helpers/initPayloadInt.js'
|
||||
import { collectionSlug } from './config.js'
|
||||
|
||||
let restClient: NextRESTClient | undefined
|
||||
let payload: Payload | undefined
|
||||
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const dirname = path.dirname(filename)
|
||||
|
||||
describe('Forgot password operation with localized fields', () => {
|
||||
beforeAll(async () => {
|
||||
;({ payload, restClient } = await initPayloadInt(dirname, 'auth/forgot-password-localized'))
|
||||
|
||||
// Register a user with additional localized field
|
||||
const res = await restClient?.POST(`/${collectionSlug}/first-register?locale=en`, {
|
||||
body: JSON.stringify({
|
||||
...devUser,
|
||||
'confirm-password': devUser.password,
|
||||
localizedField: 'English content',
|
||||
}),
|
||||
})
|
||||
|
||||
if (!res) {
|
||||
throw new Error('Failed to register user')
|
||||
}
|
||||
|
||||
const { user } = await res.json()
|
||||
|
||||
// @ts-expect-error - Localized field is not in the general Payload type, but it is in mocked collection in this case.
|
||||
await payload?.update({
|
||||
collection: collectionSlug,
|
||||
id: user.id as string,
|
||||
locale: 'pl',
|
||||
data: {
|
||||
localizedField: 'Polish content',
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
afterAll(async () => {
|
||||
if (typeof payload?.db.destroy === 'function') {
|
||||
await payload?.db.destroy()
|
||||
}
|
||||
})
|
||||
|
||||
it('should successfully process forgotPassword operation with localized fields', async () => {
|
||||
// Attempt to trigger forgotPassword operation
|
||||
const token = await payload?.forgotPassword({
|
||||
collection: collectionSlug,
|
||||
data: { email: devUser.email },
|
||||
disableEmail: true,
|
||||
})
|
||||
|
||||
// Verify token was generated successfully
|
||||
expect(token).toBeDefined()
|
||||
expect(typeof token).toBe('string')
|
||||
expect(token?.length).toBeGreaterThan(0)
|
||||
})
|
||||
|
||||
it('should not throw validation errors for localized fields', async () => {
|
||||
// We expect this not to throw an error
|
||||
await expect(
|
||||
payload?.forgotPassword({
|
||||
collection: collectionSlug,
|
||||
data: { email: devUser.email },
|
||||
disableEmail: true,
|
||||
}),
|
||||
).resolves.not.toThrow()
|
||||
})
|
||||
})
|
||||
246
test/auth/forgot-password-localized/payload-types.ts
Normal file
246
test/auth/forgot-password-localized/payload-types.ts
Normal file
@@ -0,0 +1,246 @@
|
||||
/* tslint:disable */
|
||||
/* eslint-disable */
|
||||
/**
|
||||
* This file was automatically generated by Payload.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify your source Payload config,
|
||||
* and re-run `payload generate:types` to regenerate this file.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Supported timezones in IANA format.
|
||||
*
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "supportedTimezones".
|
||||
*/
|
||||
export type SupportedTimezones =
|
||||
| 'Pacific/Midway'
|
||||
| 'Pacific/Niue'
|
||||
| 'Pacific/Honolulu'
|
||||
| 'Pacific/Rarotonga'
|
||||
| 'America/Anchorage'
|
||||
| 'Pacific/Gambier'
|
||||
| 'America/Los_Angeles'
|
||||
| 'America/Tijuana'
|
||||
| 'America/Denver'
|
||||
| 'America/Phoenix'
|
||||
| 'America/Chicago'
|
||||
| 'America/Guatemala'
|
||||
| 'America/New_York'
|
||||
| 'America/Bogota'
|
||||
| 'America/Caracas'
|
||||
| 'America/Santiago'
|
||||
| 'America/Buenos_Aires'
|
||||
| 'America/Sao_Paulo'
|
||||
| 'Atlantic/South_Georgia'
|
||||
| 'Atlantic/Azores'
|
||||
| 'Atlantic/Cape_Verde'
|
||||
| 'Europe/London'
|
||||
| 'Europe/Berlin'
|
||||
| 'Africa/Lagos'
|
||||
| 'Europe/Athens'
|
||||
| 'Africa/Cairo'
|
||||
| 'Europe/Moscow'
|
||||
| 'Asia/Riyadh'
|
||||
| 'Asia/Dubai'
|
||||
| 'Asia/Baku'
|
||||
| 'Asia/Karachi'
|
||||
| 'Asia/Tashkent'
|
||||
| 'Asia/Calcutta'
|
||||
| 'Asia/Dhaka'
|
||||
| 'Asia/Almaty'
|
||||
| 'Asia/Jakarta'
|
||||
| 'Asia/Bangkok'
|
||||
| 'Asia/Shanghai'
|
||||
| 'Asia/Singapore'
|
||||
| 'Asia/Tokyo'
|
||||
| 'Asia/Seoul'
|
||||
| 'Australia/Brisbane'
|
||||
| 'Australia/Sydney'
|
||||
| 'Pacific/Guam'
|
||||
| 'Pacific/Noumea'
|
||||
| 'Pacific/Auckland'
|
||||
| 'Pacific/Fiji';
|
||||
|
||||
export interface Config {
|
||||
auth: {
|
||||
users: UserAuthOperations;
|
||||
};
|
||||
blocks: {};
|
||||
collections: {
|
||||
users: User;
|
||||
'payload-locked-documents': PayloadLockedDocument;
|
||||
'payload-preferences': PayloadPreference;
|
||||
'payload-migrations': PayloadMigration;
|
||||
};
|
||||
collectionsJoins: {};
|
||||
collectionsSelect: {
|
||||
users: UsersSelect<false> | UsersSelect<true>;
|
||||
'payload-locked-documents': PayloadLockedDocumentsSelect<false> | PayloadLockedDocumentsSelect<true>;
|
||||
'payload-preferences': PayloadPreferencesSelect<false> | PayloadPreferencesSelect<true>;
|
||||
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
|
||||
};
|
||||
db: {
|
||||
defaultIDType: string;
|
||||
};
|
||||
globals: {};
|
||||
globalsSelect: {};
|
||||
locale: 'en' | 'pl';
|
||||
user: User & {
|
||||
collection: 'users';
|
||||
};
|
||||
jobs: {
|
||||
tasks: unknown;
|
||||
workflows: unknown;
|
||||
};
|
||||
}
|
||||
export interface UserAuthOperations {
|
||||
forgotPassword: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
login: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
registerFirstUser: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
unlock: {
|
||||
email: string;
|
||||
password: string;
|
||||
};
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users".
|
||||
*/
|
||||
export interface User {
|
||||
id: string;
|
||||
localizedField: string;
|
||||
roles: ('admin' | 'editor' | 'moderator' | 'user' | 'viewer')[];
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
email: string;
|
||||
resetPasswordToken?: string | null;
|
||||
resetPasswordExpiration?: string | null;
|
||||
salt?: string | null;
|
||||
hash?: string | null;
|
||||
loginAttempts?: number | null;
|
||||
lockUntil?: string | null;
|
||||
password?: string | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-locked-documents".
|
||||
*/
|
||||
export interface PayloadLockedDocument {
|
||||
id: string;
|
||||
document?: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
} | null;
|
||||
globalSlug?: string | null;
|
||||
user: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
};
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-preferences".
|
||||
*/
|
||||
export interface PayloadPreference {
|
||||
id: string;
|
||||
user: {
|
||||
relationTo: 'users';
|
||||
value: string | User;
|
||||
};
|
||||
key?: string | null;
|
||||
value?:
|
||||
| {
|
||||
[k: string]: unknown;
|
||||
}
|
||||
| unknown[]
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-migrations".
|
||||
*/
|
||||
export interface PayloadMigration {
|
||||
id: string;
|
||||
name?: string | null;
|
||||
batch?: number | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "users_select".
|
||||
*/
|
||||
export interface UsersSelect<T extends boolean = true> {
|
||||
localizedField?: T;
|
||||
roles?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
email?: T;
|
||||
resetPasswordToken?: T;
|
||||
resetPasswordExpiration?: T;
|
||||
salt?: T;
|
||||
hash?: T;
|
||||
loginAttempts?: T;
|
||||
lockUntil?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-locked-documents_select".
|
||||
*/
|
||||
export interface PayloadLockedDocumentsSelect<T extends boolean = true> {
|
||||
document?: T;
|
||||
globalSlug?: T;
|
||||
user?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-preferences_select".
|
||||
*/
|
||||
export interface PayloadPreferencesSelect<T extends boolean = true> {
|
||||
user?: T;
|
||||
key?: T;
|
||||
value?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "payload-migrations_select".
|
||||
*/
|
||||
export interface PayloadMigrationsSelect<T extends boolean = true> {
|
||||
name?: T;
|
||||
batch?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "auth".
|
||||
*/
|
||||
export interface Auth {
|
||||
[k: string]: unknown;
|
||||
}
|
||||
|
||||
|
||||
declare module 'payload' {
|
||||
// @ts-ignore
|
||||
export interface GeneratedTypes extends Config {}
|
||||
}
|
||||
@@ -1016,6 +1016,7 @@ describe('Auth', () => {
|
||||
expect(emailValidation('user.name+alias@example.co.uk', mockContext)).toBe(true)
|
||||
expect(emailValidation('user-name@example.org', mockContext)).toBe(true)
|
||||
expect(emailValidation('user@ex--ample.com', mockContext)).toBe(true)
|
||||
expect(emailValidation("user'payload@example.org", mockContext)).toBe(true)
|
||||
})
|
||||
|
||||
it('should not allow emails with double quotes', () => {
|
||||
@@ -1045,5 +1046,11 @@ describe('Auth', () => {
|
||||
expect(emailValidation('user@-example.com', mockContext)).toBe('validation:emailAddress')
|
||||
expect(emailValidation('user@example-.com', mockContext)).toBe('validation:emailAddress')
|
||||
})
|
||||
it('should not allow emails that start with dot', () => {
|
||||
expect(emailValidation('.user@example.com', mockContext)).toBe('validation:emailAddress')
|
||||
})
|
||||
it('should not allow emails that have a comma', () => {
|
||||
expect(emailValidation('user,name@example.com', mockContext)).toBe('validation:emailAddress')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1218,7 +1218,6 @@ describe('collections-rest', () => {
|
||||
.GET(`/${pointSlug}`, {
|
||||
query: {
|
||||
limit: 5,
|
||||
sort: 'point',
|
||||
where: {
|
||||
point: {
|
||||
// querying large enough range to include all docs
|
||||
|
||||
@@ -491,6 +491,16 @@ export default buildConfigWithDefaults({
|
||||
type: 'relationship',
|
||||
relationTo: 'posts',
|
||||
},
|
||||
{
|
||||
name: 'customID',
|
||||
type: 'relationship',
|
||||
relationTo: 'custom-ids',
|
||||
},
|
||||
{
|
||||
name: 'customIDValue',
|
||||
type: 'text',
|
||||
virtual: 'customID.id',
|
||||
},
|
||||
],
|
||||
versions: { drafts: true },
|
||||
},
|
||||
|
||||
@@ -1993,11 +1993,63 @@ describe('database', () => {
|
||||
collection: 'virtual-relations',
|
||||
depth: 0,
|
||||
where: { id: { equals: id } },
|
||||
draft: true,
|
||||
})
|
||||
expect(draft.docs[0]?.postTitle).toBe('my-title')
|
||||
})
|
||||
|
||||
it('should allow virtual field as reference to ID', async () => {
|
||||
const post = await payload.create({ collection: 'posts', data: { title: 'my-title' } })
|
||||
const { id } = await payload.create({
|
||||
collection: 'virtual-relations',
|
||||
depth: 0,
|
||||
data: { post: post.id },
|
||||
})
|
||||
|
||||
const docDepth2 = await payload.findByID({ collection: 'virtual-relations', id })
|
||||
expect(docDepth2.postID).toBe(post.id)
|
||||
const docDepth0 = await payload.findByID({ collection: 'virtual-relations', id, depth: 0 })
|
||||
expect(docDepth0.postID).toBe(post.id)
|
||||
})
|
||||
|
||||
it('should allow virtual field as reference to custom ID', async () => {
|
||||
const customID = await payload.create({ collection: 'custom-ids', data: {} })
|
||||
const { id } = await payload.create({
|
||||
collection: 'virtual-relations',
|
||||
depth: 0,
|
||||
data: { customID: customID.id },
|
||||
})
|
||||
|
||||
const docDepth2 = await payload.findByID({ collection: 'virtual-relations', id })
|
||||
expect(docDepth2.customIDValue).toBe(customID.id)
|
||||
const docDepth0 = await payload.findByID({
|
||||
collection: 'virtual-relations',
|
||||
id,
|
||||
depth: 0,
|
||||
})
|
||||
expect(docDepth0.customIDValue).toBe(customID.id)
|
||||
})
|
||||
|
||||
it('should allow deep virtual field as reference to ID', async () => {
|
||||
const category = await payload.create({
|
||||
collection: 'categories',
|
||||
data: { title: 'category-3' },
|
||||
})
|
||||
const post = await payload.create({
|
||||
collection: 'posts',
|
||||
data: { category: category.id, title: 'my-title-3' },
|
||||
})
|
||||
const { id } = await payload.create({
|
||||
collection: 'virtual-relations',
|
||||
depth: 0,
|
||||
data: { post: post.id },
|
||||
})
|
||||
|
||||
const docDepth2 = await payload.findByID({ collection: 'virtual-relations', id })
|
||||
expect(docDepth2.postCategoryID).toBe(category.id)
|
||||
const docDepth0 = await payload.findByID({ collection: 'virtual-relations', id, depth: 0 })
|
||||
expect(docDepth0.postCategoryID).toBe(category.id)
|
||||
})
|
||||
|
||||
it('should allow virtual field with reference localized', async () => {
|
||||
const post = await payload.create({
|
||||
collection: 'posts',
|
||||
@@ -2351,4 +2403,15 @@ describe('database', () => {
|
||||
|
||||
payload.db.allowAdditionalKeys = false
|
||||
})
|
||||
|
||||
it('should not crash when the version field is not selected', async () => {
|
||||
const customID = await payload.create({ collection: 'custom-ids', data: {} })
|
||||
const res = await payload.db.queryDrafts({
|
||||
collection: 'custom-ids',
|
||||
where: { parent: { equals: customID.id } },
|
||||
select: { parent: true },
|
||||
})
|
||||
|
||||
expect(res.docs[0].id).toBe(customID.id)
|
||||
})
|
||||
})
|
||||
|
||||
@@ -393,6 +393,19 @@ export interface VirtualRelation {
|
||||
| null;
|
||||
postLocalized?: string | null;
|
||||
post?: (string | null) | Post;
|
||||
customID?: (string | null) | CustomId;
|
||||
customIDValue?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
_status?: ('draft' | 'published') | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "custom-ids".
|
||||
*/
|
||||
export interface CustomId {
|
||||
id: string;
|
||||
title?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
_status?: ('draft' | 'published') | null;
|
||||
@@ -416,17 +429,6 @@ export interface FieldsPersistance {
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "custom-ids".
|
||||
*/
|
||||
export interface CustomId {
|
||||
id: string;
|
||||
title?: string | null;
|
||||
updatedAt: string;
|
||||
createdAt: string;
|
||||
_status?: ('draft' | 'published') | null;
|
||||
}
|
||||
/**
|
||||
* This interface was referenced by `Config`'s JSON-Schema
|
||||
* via the `definition` "fake-custom-ids".
|
||||
@@ -829,6 +831,8 @@ export interface VirtualRelationsSelect<T extends boolean = true> {
|
||||
postID?: T;
|
||||
postLocalized?: T;
|
||||
post?: T;
|
||||
customID?: T;
|
||||
customIDValue?: T;
|
||||
updatedAt?: T;
|
||||
createdAt?: T;
|
||||
_status?: T;
|
||||
|
||||
@@ -742,7 +742,15 @@ describe('relationship', () => {
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
|
||||
const selectedValue = relationshipField.locator('.relationship--multi-value-label__text')
|
||||
await expect(selectedValue).toBeVisible()
|
||||
await expect(selectedValue).toHaveCount(1)
|
||||
|
||||
await relationshipField.click()
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
await button.click()
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
|
||||
const selectedValues = relationshipField.locator('.relationship--multi-value-label__text')
|
||||
await expect(selectedValues).toHaveCount(2)
|
||||
})
|
||||
|
||||
test('should handle `hasMany` polymorphic relationship when `appearance: "drawer"`', async () => {
|
||||
@@ -807,6 +815,42 @@ describe('relationship', () => {
|
||||
await expect(newRows).toHaveCount(1)
|
||||
await expect(listDrawerContent.getByText('Seeded text document')).toHaveCount(0)
|
||||
})
|
||||
|
||||
test('should filter out existing values from polymorphic relationship list drawer', async () => {
|
||||
await page.goto(url.create)
|
||||
const relationshipField = page.locator('#field-polymorphicRelationshipDrawer')
|
||||
await relationshipField.click()
|
||||
const listDrawerContent = page.locator('.list-drawer').locator('.drawer__content')
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
|
||||
const relationToSelector = page.locator('.list-header__select-collection')
|
||||
await expect(relationToSelector).toBeVisible()
|
||||
|
||||
await relationToSelector.locator('.rs__control').click()
|
||||
const option = relationToSelector.locator('.rs__option').nth(1)
|
||||
await option.click()
|
||||
const rows = listDrawerContent.locator('table tbody tr')
|
||||
await expect(rows).toHaveCount(2)
|
||||
const firstRow = rows.first()
|
||||
const button = firstRow.locator('button')
|
||||
await button.click()
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
|
||||
const selectedValue = relationshipField.locator('.relationship--single-value__text')
|
||||
await expect(selectedValue).toBeVisible()
|
||||
|
||||
await relationshipField.click()
|
||||
await expect(listDrawerContent).toBeVisible()
|
||||
await expect(relationToSelector).toBeVisible()
|
||||
await relationToSelector.locator('.rs__control').click()
|
||||
await option.click()
|
||||
const newRows = listDrawerContent.locator('table tbody tr')
|
||||
await expect(newRows).toHaveCount(1)
|
||||
const newFirstRow = newRows.first()
|
||||
const newButton = newFirstRow.locator('button')
|
||||
await newButton.click()
|
||||
await expect(listDrawerContent).toBeHidden()
|
||||
})
|
||||
})
|
||||
|
||||
async function createTextFieldDoc(overrides?: Partial<TextField>): Promise<TextField> {
|
||||
|
||||
@@ -158,7 +158,7 @@ const RelationshipFields: CollectionConfig = {
|
||||
},
|
||||
{
|
||||
name: 'relationshipDrawerHasManyPolymorphic',
|
||||
relationTo: ['text-fields'],
|
||||
relationTo: ['text-fields', 'array-fields'],
|
||||
admin: {
|
||||
appearance: 'drawer',
|
||||
},
|
||||
|
||||
@@ -2,6 +2,7 @@ import { fileURLToPath } from 'node:url'
|
||||
import path from 'path'
|
||||
import { type Config } from 'payload'
|
||||
|
||||
import { LexicalFullyFeatured } from './collections/_LexicalFullyFeatured/index.js'
|
||||
import ArrayFields from './collections/Array/index.js'
|
||||
import {
|
||||
getLexicalFieldsCollection,
|
||||
@@ -26,6 +27,7 @@ const dirname = path.dirname(filename)
|
||||
export const baseConfig: Partial<Config> = {
|
||||
// ...extend config here
|
||||
collections: [
|
||||
LexicalFullyFeatured,
|
||||
getLexicalFieldsCollection({
|
||||
blocks: lexicalBlocks,
|
||||
inlineBlocks: lexicalInlineBlocks,
|
||||
@@ -42,10 +44,18 @@ export const baseConfig: Partial<Config> = {
|
||||
ArrayFields,
|
||||
],
|
||||
globals: [TabsWithRichText],
|
||||
|
||||
admin: {
|
||||
importMap: {
|
||||
baseDir: path.resolve(dirname),
|
||||
},
|
||||
components: {
|
||||
beforeDashboard: [
|
||||
{
|
||||
path: './components/CollectionsExplained.tsx#CollectionsExplained',
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
onInit: async (payload) => {
|
||||
if (process.env.SEED_IN_CONFIG_ONINIT !== 'false') {
|
||||
|
||||
@@ -302,7 +302,7 @@ describe('lexicalBlocks', () => {
|
||||
await assertLexicalDoc({
|
||||
fn: ({ lexicalWithBlocks }) => {
|
||||
const rscBlock: SerializedBlockNode = lexicalWithBlocks.root
|
||||
.children[14] as SerializedBlockNode
|
||||
.children[13] as SerializedBlockNode
|
||||
const paragraphNode: SerializedParagraphNode = lexicalWithBlocks.root
|
||||
.children[12] as SerializedParagraphNode
|
||||
|
||||
@@ -1133,9 +1133,9 @@ describe('lexicalBlocks', () => {
|
||||
).docs[0] as never
|
||||
|
||||
const richTextBlock: SerializedBlockNode = lexicalWithBlocks.root
|
||||
.children[13] as SerializedBlockNode
|
||||
.children[12] as SerializedBlockNode
|
||||
const subRichTextBlock: SerializedBlockNode = richTextBlock.fields.richTextField.root
|
||||
.children[1] as SerializedBlockNode // index 0 and 2 are paragraphs created by default around the block node when a new block is added via slash command
|
||||
.children[0] as SerializedBlockNode // index 0 and 2 are paragraphs created by default around the block node when a new block is added via slash command
|
||||
|
||||
const subSubRichTextField = subRichTextBlock.fields.subRichTextField
|
||||
const subSubUploadField = subRichTextBlock.fields.subUploadField
|
||||
@@ -1163,9 +1163,9 @@ describe('lexicalBlocks', () => {
|
||||
).docs[0] as never
|
||||
|
||||
const richTextBlock2: SerializedBlockNode = lexicalWithBlocks.root
|
||||
.children[13] as SerializedBlockNode
|
||||
.children[12] as SerializedBlockNode
|
||||
const subRichTextBlock2: SerializedBlockNode = richTextBlock2.fields.richTextField.root
|
||||
.children[1] as SerializedBlockNode // index 0 and 2 are paragraphs created by default around the block node when a new block is added via slash command
|
||||
.children[0] as SerializedBlockNode // index 0 and 2 are paragraphs created by default around the block node when a new block is added via slash command
|
||||
|
||||
const subSubRichTextField2 = subRichTextBlock2.fields.subRichTextField
|
||||
const subSubUploadField2 = subRichTextBlock2.fields.subUploadField
|
||||
@@ -1666,5 +1666,55 @@ describe('lexicalBlocks', () => {
|
||||
},
|
||||
})
|
||||
})
|
||||
|
||||
test('ensure inline blocks restore their state after undoing a removal', async () => {
|
||||
await page.goto('http://localhost:3000/admin/collections/LexicalInBlock?limit=10')
|
||||
|
||||
await page.locator('.cell-id a').first().click()
|
||||
await page.waitForURL(`**/collections/LexicalInBlock/**`)
|
||||
|
||||
// Wait for the page to be fully loaded and elements to be stable
|
||||
await page.waitForLoadState('domcontentloaded')
|
||||
|
||||
// Wait for the specific row to be visible and have its content loaded
|
||||
const row2 = page.locator('#blocks-row-2')
|
||||
await expect(row2).toBeVisible()
|
||||
|
||||
// Get initial count and ensure it's stable
|
||||
const inlineBlocks = page.locator('#blocks-row-2 .inline-block-container')
|
||||
const inlineBlockCount = await inlineBlocks.count()
|
||||
await expect(() => {
|
||||
expect(inlineBlockCount).toBeGreaterThan(0)
|
||||
}).toPass()
|
||||
|
||||
const inlineBlockElement = inlineBlocks.first()
|
||||
await inlineBlockElement.locator('.inline-block__editButton').first().click()
|
||||
|
||||
await page.locator('.drawer--is-open #field-text').fill('value1')
|
||||
await page.locator('.drawer--is-open button[type="submit"]').first().click()
|
||||
|
||||
// remove inline block
|
||||
await inlineBlockElement.click()
|
||||
await page.keyboard.press('Backspace')
|
||||
|
||||
// Check both that this specific element is removed and the total count decreased
|
||||
await expect(inlineBlocks).toHaveCount(inlineBlockCount - 1)
|
||||
|
||||
await page.keyboard.press('Escape')
|
||||
|
||||
await inlineBlockElement.click()
|
||||
|
||||
// Undo the removal using keyboard shortcut
|
||||
await page.keyboard.press('ControlOrMeta+Z')
|
||||
|
||||
// Wait for the block to be restored
|
||||
await expect(inlineBlocks).toHaveCount(inlineBlockCount)
|
||||
|
||||
// Open the drawer again
|
||||
await inlineBlockElement.locator('.inline-block__editButton').first().click()
|
||||
|
||||
// Check if the text field still contains 'value1'
|
||||
await expect(page.locator('.drawer--is-open #field-text')).toHaveValue('value1')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -728,7 +728,8 @@ describe('lexicalMain', () => {
|
||||
await expect(relationshipListDrawer).toBeVisible()
|
||||
await wait(500)
|
||||
|
||||
await expect(relationshipListDrawer.locator('.rs__single-value')).toHaveText('Lexical Field')
|
||||
await relationshipListDrawer.locator('.rs__input').first().click()
|
||||
await relationshipListDrawer.locator('.rs__menu').getByText('Lexical Field').click()
|
||||
|
||||
await relationshipListDrawer.locator('button').getByText('Rich Text').first().click()
|
||||
await expect(relationshipListDrawer).toBeHidden()
|
||||
@@ -1203,10 +1204,11 @@ describe('lexicalMain', () => {
|
||||
await expect(newUploadNode.locator('.lexical-upload__bottomRow')).toContainText('payload.png')
|
||||
|
||||
await page.keyboard.press('Enter') // floating toolbar needs to appear with enough distance to the upload node, otherwise clicking may fail
|
||||
await page.keyboard.press('Enter')
|
||||
await page.keyboard.press('ArrowLeft')
|
||||
await page.keyboard.press('ArrowLeft')
|
||||
// Select "there" by pressing shift + arrow left
|
||||
for (let i = 0; i < 4; i++) {
|
||||
for (let i = 0; i < 5; i++) {
|
||||
await page.keyboard.press('Shift+ArrowLeft')
|
||||
}
|
||||
|
||||
@@ -1258,10 +1260,10 @@ describe('lexicalMain', () => {
|
||||
const firstParagraph: SerializedParagraphNode = lexicalField.root
|
||||
.children[0] as SerializedParagraphNode
|
||||
const secondParagraph: SerializedParagraphNode = lexicalField.root
|
||||
.children[1] as SerializedParagraphNode
|
||||
const thirdParagraph: SerializedParagraphNode = lexicalField.root
|
||||
.children[2] as SerializedParagraphNode
|
||||
const uploadNode: SerializedUploadNode = lexicalField.root.children[3] as SerializedUploadNode
|
||||
const thirdParagraph: SerializedParagraphNode = lexicalField.root
|
||||
.children[3] as SerializedParagraphNode
|
||||
const uploadNode: SerializedUploadNode = lexicalField.root.children[1] as SerializedUploadNode
|
||||
|
||||
expect(firstParagraph.children).toHaveLength(2)
|
||||
expect((firstParagraph.children[0] as SerializedTextNode).text).toBe('Some ')
|
||||
@@ -1391,7 +1393,7 @@ describe('lexicalMain', () => {
|
||||
const lexicalField: SerializedEditorState = lexicalDoc.lexicalRootEditor
|
||||
|
||||
// @ts-expect-error no need to type this
|
||||
expect(lexicalField?.root?.children[1].fields.someTextRequired).toEqual('test')
|
||||
expect(lexicalField?.root?.children[0].fields.someTextRequired).toEqual('test')
|
||||
}).toPass({
|
||||
timeout: POLL_TOPASS_TIMEOUT,
|
||||
})
|
||||
|
||||
68
test/lexical/collections/_LexicalFullyFeatured/e2e.spec.ts
Normal file
68
test/lexical/collections/_LexicalFullyFeatured/e2e.spec.ts
Normal file
@@ -0,0 +1,68 @@
|
||||
import { expect, test } from '@playwright/test'
|
||||
import { AdminUrlUtil } from 'helpers/adminUrlUtil.js'
|
||||
import { reInitializeDB } from 'helpers/reInitializeDB.js'
|
||||
import { lexicalFullyFeaturedSlug } from 'lexical/slugs.js'
|
||||
import path from 'path'
|
||||
import { fileURLToPath } from 'url'
|
||||
|
||||
import { ensureCompilationIsDone } from '../../../helpers.js'
|
||||
import { initPayloadE2ENoConfig } from '../../../helpers/initPayloadE2ENoConfig.js'
|
||||
import { TEST_TIMEOUT_LONG } from '../../../playwright.config.js'
|
||||
import { LexicalHelpers } from './utils.js'
|
||||
const filename = fileURLToPath(import.meta.url)
|
||||
const currentFolder = path.dirname(filename)
|
||||
const dirname = path.resolve(currentFolder, '../../')
|
||||
|
||||
const { beforeAll, beforeEach, describe } = test
|
||||
|
||||
// Unlike the other suites, this one runs in parallel, as they run on the `lexical-fully-featured/create` URL and are "pure" tests
|
||||
test.describe.configure({ mode: 'parallel' })
|
||||
|
||||
const { serverURL } = await initPayloadE2ENoConfig({
|
||||
dirname,
|
||||
})
|
||||
|
||||
describe('Lexical Fully Featured', () => {
|
||||
beforeAll(async ({ browser }, testInfo) => {
|
||||
testInfo.setTimeout(TEST_TIMEOUT_LONG)
|
||||
process.env.SEED_IN_CONFIG_ONINIT = 'false' // Makes it so the payload config onInit seed is not run. Otherwise, the seed would be run unnecessarily twice for the initial test run - once for beforeEach and once for onInit
|
||||
const page = await browser.newPage()
|
||||
await ensureCompilationIsDone({ page, serverURL })
|
||||
await page.close()
|
||||
})
|
||||
beforeEach(async ({ page }) => {
|
||||
await reInitializeDB({
|
||||
serverURL,
|
||||
snapshotKey: 'fieldsTest',
|
||||
uploadsDir: [
|
||||
path.resolve(dirname, './collections/Upload/uploads'),
|
||||
path.resolve(dirname, './collections/Upload2/uploads2'),
|
||||
],
|
||||
})
|
||||
const url = new AdminUrlUtil(serverURL, lexicalFullyFeaturedSlug)
|
||||
const lexical = new LexicalHelpers(page)
|
||||
await page.goto(url.create)
|
||||
await lexical.editor.first().focus()
|
||||
})
|
||||
test('prevent extra paragraph when inserting decorator blocks like blocks or upload node', async ({
|
||||
page,
|
||||
}) => {
|
||||
const lexical = new LexicalHelpers(page)
|
||||
await lexical.slashCommand('block')
|
||||
await lexical.slashCommand('relationship')
|
||||
await lexical.drawer.locator('.list-drawer__header').getByText('Create New').click()
|
||||
await lexical.save('drawer')
|
||||
await expect(lexical.decorator).toHaveCount(2)
|
||||
await lexical.slashCommand('upload')
|
||||
await lexical.drawer.locator('.list-drawer__header').getByText('Create New').click()
|
||||
await lexical.drawer.getByText('Paste URL').click()
|
||||
await lexical.drawer
|
||||
.locator('.file-field__remote-file')
|
||||
.fill('https://payloadcms.com/images/universal-truth.jpg')
|
||||
await lexical.drawer.getByText('Add file').click()
|
||||
await lexical.save('drawer')
|
||||
await expect(lexical.decorator).toHaveCount(3)
|
||||
const paragraph = lexical.editor.locator('> p')
|
||||
await expect(paragraph).toHaveText('')
|
||||
})
|
||||
})
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user