You can currently extend Payload's type generation if you provide
additional JSON schema definitions yourself.
But, Payload has helpful functions like `fieldsToJSONSchema` which would
be nice to easily re-use.
The only issue is that the `fieldsToJSONSchema` requires arguments which
are difficult to access from the context of plugins, etc. They should
really be provided at runtime to the `config.typescript.schema`
functions.
This PR does exactly that. Adds more args to the `schema` extension
point to make utility functions easier to re-use.
### What?
When using `throw new APIResponse("Custom error message", 500, null,
true)` the error message is being replaced with the standard "Something
went wrong" message.
### Why?
We are not checking if the 4th argument (`isPublic`) is false before
masquerading the error message.
### How?
Adds a check for `!err.isPublic` before adjusting the outgoing message.
Fixes#10878. The Search Plugin displays a link within the search
results collection that points to the underlying document that is
related to that result. The href used, however, was not accounting for
any `basePath` provided to the `next.config.js`, leading to a 404 if
using a custom base path. The fix is to use the `Link` component from
`next/link` instead of an anchor tag directly. This will automatically
inject the the base path into the href before rendering it.
This PR also brings back the `CopyToClipboard` component. This makes it
easy for the user to copy the href instead of navigating to it.
---------
Co-authored-by: Jacob Fletcher <jacobsfletch@gmail.com>
There were a number of areas within the Search Plugin where typings
could have been improved, namely:
- The `customProps` sent to the `ReindexButton`. This now uses the
`satisfies` keyword to ensure type strictness.
- The `collectionLabels` prop sent to the `ReindexButtonClient`
component. This is now standardized behind a new
`ResolvedCollectionLabels` type to closely reflect `CollectionLabels`.
This was also converted from unnecessarily invoking a function to being
a basic object.
- The `locale` type sent through `SyncDocArgs`. This now uses
`Locale['code']` from Payload.
Continuation of #10632. The `apiBasePath` property in the Search Plugin
config is unnecessary. This plugin reads directly from the Payload
config for this property. Exposing it to the plugin's config was likely
a mistake during sanitization before passing it through to the remaining
files. This property was added to resolve the types, but as result,
exposed it to the config unnecessarily. This PR marks this property with
the deprecated flag to prevent breaking changes.
Previously, the lexical link drawer did not display any fields if the
`create` permission was false, even though the `update` permission was
true.
The issue was a faulty permission check in `RenderFields` that did not
check the top-level permission operation keys for truthiness. It only
checked if the `permissions` variable itself was `true`, or if the
sub-fields had `create` / `update` permissions set to `true`.
This fixes#10631.
Originally the api basepath for the reindex button is resolved during
plugin initialization. Looks like this happens before payload overrides
the config with the `basePath `from the next config.
I've changed it so that it uses the `useConfig` hook, and manually
tested that it works.

Bumps `@faceless-ui/window-info` to v3.0.1` and
`@faceless-ui/scroll-info` to v2.0.0. This gets them both off beta
versions and includes React 19 stable in their peer deps.
The `@faceless-ui/modal` package, however, has yet to be bumped. This
package is waiting on https://github.com/faceless-ui/modal/issues/63 to
be resolved in order to fully deprecate
[`body-scroll-lock`](https://github.com/willmcpo/body-scroll-lock)
before bumping to stable.
Fixes https://github.com/payloadcms/payload/issues/10780
Previously, with enabled versions, nested select `hasMany: true` fields
weren't working with SQL database adapters. This was due to wrongly
passed `parent` to select rows data because we store arrays and blocks
in versions a bit differently, using both, `id` and `_uuid` (which
contains the normal Object ID) columns. And unlike with non versions
`_uuid` column isn't actually applicable here as it's not unique, thus
we need to save blocks/arrays first and then map their ObjectIDs to
generated by the database IDs and use them for select fields `parent`
data
As a result of #9388, the `valid` and `passesCondition` properties no
longer appear in form state. This leads to breaking logic if you were
previously relying on these properties to have explicit values. To fix
this, we simply perform the inverse on these properties before accepting
them into client side form state. In the next major release, we can
accept form state as it is received and instruct users to modify their
logic as needed.
Also comes with a small perf optimization, by keeping the old object
reference of fields if they did not change when server form state comes
back
### What?
In some cases you may want to opt out of using the default access
control that this plugin provides on the tenants collection.
### Why?
Other collections are able to opt out of this already, but the tenants
collection specifically was not configured with an opt out capability.
### How?
Adds new property to the plugin config: `useTenantsCollectionAccess`.
Setting this to `false` allows users to opt out and write their own
access control functions without the plugin merging in its own
constraints for the tenant collection.
Fixes https://github.com/payloadcms/payload/issues/10882
### What?
When using custom slugs and field names the tenancy field added to the
users would still attempt to use `tenants` and fail.
### Why?
The tenant/tenancy are hardcoded in `tenantsArrayField()`
### How?
Added the same args that are used in `tenantsField()` for the field
names and relation.
Fixes#10724
The selection is never touched in an `editor.read`, but BEFORE starting
an `editor.update` it is synced with `window.selection`. Firefox for
some reason loses the editor selection, so on the next update the
selection is null.
For reference, there was a brief discussion on the Lexical Discord
server:
https://discord.com/channels/953974421008293909/1333916489870348309
This PR moves the logic for rendering diff field components in the
version comparison view from the client to the server.
This allows us to expose more customization options to the server-side
Payload Config. For example, users can now pass their own diff
components for fields - even including RSCs.
This PR also cleans up the version view types
Implements the following from
https://github.com/payloadcms/payload/discussions/4197:
- allow for customization of diff components
- more control over versions screens in general
TODO:
- [x] Bring getFieldPaths fixes into core
- [x] Cleanup and test with scrutiny. Ensure all field types display
their diffs correctly
- [x] Review public API for overriding field types, add docs
- [x] Add e2e test for new public API
## Description
As an author reviewing the versions I have for a document , I would like
to the ability to focus only on the differences I made and not see the
entire document.
[Screencast from 2024-09-05
16-38-40.webm](https://github.com/user-attachments/assets/25d44a51-bcac-47d5-a2ec-cadae4d108d4)
A checkbox was added to the Version View allowing user to decide if
he/she wants to see only modified fields or the entire documents.
#7981 - mention this feature and also in discord
- [v] I have read and understand the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository.
## Type of change
<!-- Please delete options that are not relevant. -->
- [v] New feature (non-breaking change which adds functionality)
## Checklist:
- [ ] Existing test suite passes locally with my changes
(Actually it's stuck on S3 upload test , note related to my code)
One lat question - should we really translate text for all locales ? or
we can leave it undefined for now ?(besides english)
---------
Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
This [PR](https://github.com/payloadcms/payload/pull/9438) introduced a
bug with the publish button, an error was being thrown when localization
is false. Updated the logic breaking the publish button to safely check
whether localization exists.
### What?
Adds new feature to change the default behavior of the Publish button.
When localization is enabled, you can now choose whether to publish all
locales (default) or publish the active locale only.
<img width="401" alt="Screenshot 2024-11-22 at 12 03 20 PM"
src="https://github.com/user-attachments/assets/757383b9-3bf9-4816-8223-a907b120912e">
### Why?
Since implementing the ability to publish a specific locale, users have
reported that having this option as the default button would be
preferred in some cases.
### How?
Add `defaultLocalePublishOption` to your localization config and set it
to 'active':
```ts
localization: {
defaultLocalePublishOption: 'active',
// the rest of your localization config
},
```
---------
Co-authored-by: Anders Semb Hermansen <anders.hermansen@gmail.com>
### What?
When hitting the form-state endpoint, previousValue was undefined.
### Why?
It was not being passed through.
### How?
Sets previousValue as the initial value of the field.
Fixes https://github.com/payloadcms/payload/issues/10826
Field validations can be expensive, especially custom validations that
are async or highly complex. This can lead to slow form state response
times when generating form state for many such fields. Ideally, we only
run validations on fields whose values have changed. This is not
possible, however, because field validation functions might reference
_other_ field values with their args, and there is no good way of
detecting exactly which fields should run in this case. The next best
thing here is to only run validations _after the form has been
submitted_, and then every `onChange` event thereafter until a
successful submit has taken place. This is an elegant solution because
we currently don't _render_ field errors until submission anyway.
This change will significantly speed up form state response times, at
least until the form has been submitted. From then on, all field
validations will run regardless, just as they do now. If custom
validations continue to slow down form state response times, there is a
new `event` arg introduced in #10738 that can be used to control whether
heavy operations occur on change or on submit.
Related: #10638
Field paths within hooks are not correct.
For example, an unnamed tab containing a group field and nested text
field should have the path:
- `myGroupField.myTextField`
However, within hooks that path is formatted as:
- `_index-1.myGroupField.myTextField`
The leading index shown above should not exist, as this field is
considered top-level since it is located within an unnamed tab.
This discrepancy is only evident through the APIs themselves, such as
when creating a request with invalid data and reading the validation
errors in the response. Form state contains proper field paths, which is
ultimately why this issue was never caught. This is because within the
admin panel we merge the API response with the current form state,
obscuring the underlying issue. This becomes especially obvious in
#10580, where we no longer initialize validation errors within form
state until the form has been submitted, and instead rely solely on the
API response for the initial error state.
Here's comprehensive example of how field paths _should_ be formatted:
```
{
// ...
fields: [
{
// path: 'topLevelNamedField'
// schemaPath: 'topLevelNamedField'
// indexPath: ''
name: 'topLevelNamedField',
type: 'text',
},
{
// path: 'array'
// schemaPath: 'array'
// indexPath: ''
name: 'array',
type: 'array',
fields: [
{
// path: 'array.[n].fieldWithinArray'
// schemaPath: 'array.fieldWithinArray'
// indexPath: ''
name: 'fieldWithinArray',
type: 'text',
},
{
// path: 'array.[n].nestedArray'
// schemaPath: 'array.nestedArray'
// indexPath: ''
name: 'nestedArray',
type: 'array',
fields: [
{
// path: 'array.[n].nestedArray.[n].fieldWithinNestedArray'
// schemaPath: 'array.nestedArray.fieldWithinNestedArray'
// indexPath: ''
name: 'fieldWithinNestedArray',
type: 'text',
},
],
},
{
// path: 'array.[n]._index-2'
// schemaPath: 'array._index-2'
// indexPath: '2'
type: 'row',
fields: [
{
// path: 'array.[n].fieldWithinRowWithinArray'
// schemaPath: 'array._index-2.fieldWithinRowWithinArray'
// indexPath: ''
name: 'fieldWithinRowWithinArray',
type: 'text',
},
],
},
],
},
{
// path: '_index-2'
// schemaPath: '_index-2'
// indexPath: '2'
type: 'row',
fields: [
{
// path: 'fieldWithinRow'
// schemaPath: '_index-2.fieldWithinRow'
// indexPath: ''
name: 'fieldWithinRow',
type: 'text',
},
],
},
{
// path: '_index-3'
// schemaPath: '_index-3'
// indexPath: '3'
type: 'tabs',
tabs: [
{
// path: '_index-3-0'
// schemaPath: '_index-3-0'
// indexPath: '3-0'
label: 'Unnamed Tab',
fields: [
{
// path: 'fieldWithinUnnamedTab'
// schemaPath: '_index-3-0.fieldWithinUnnamedTab'
// indexPath: ''
name: 'fieldWithinUnnamedTab',
type: 'text',
},
{
// path: '_index-3-0-1'
// schemaPath: '_index-3-0-1'
// indexPath: '3-0-1'
type: 'tabs',
tabs: [
{
// path: '_index-3-0-1-0'
// schemaPath: '_index-3-0-1-0'
// indexPath: '3-0-1-0'
label: 'Nested Unnamed Tab',
fields: [
{
// path: 'fieldWithinNestedUnnamedTab'
// schemaPath: '_index-3-0-1-0.fieldWithinNestedUnnamedTab'
// indexPath: ''
name: 'fieldWithinNestedUnnamedTab',
type: 'text',
},
],
},
],
},
],
},
{
// path: 'namedTab'
// schemaPath: '_index-3.namedTab'
// indexPath: ''
label: 'Named Tab',
name: 'namedTab',
fields: [
{
// path: 'namedTab.fieldWithinNamedTab'
// schemaPath: '_index-3.namedTab.fieldWithinNamedTab'
// indexPath: ''
name: 'fieldWithinNamedTab',
type: 'text',
},
],
},
],
},
]
}
```
### What?
When the doc permissions were retrieved from the DB, we were coercing
them into strings even when they should not have been.
### Why?
Usage of `id.toString()`
### How?
Remove `id.toString()`. The id will be correct by this point and we
should never coerce id's like this.
Fixes https://github.com/payloadcms/payload/issues/8218
### What?
Error thrown when initiating the Estonian language (`et`) from
`@payloadcms/translations`
<img width="896" alt="Screenshot 2025-01-27 at 3 17 49 PM"
src="https://github.com/user-attachments/assets/27603c75-d713-4f11-b141-dc293d51800c"
/>
### How?
`et` needed to be added to `importDateFNSLocale`. Tested after this
change and the error is no longer present.
Fixes#10817
### What?
When the draft functionality is enabled, in the version history page,
_Restore this version_ renders an empty submenu popup.
### Why?
Restore this version button has below 2 basic scenarios:
1. restore a previously published version.
In this scenario, this button has a second option _Restore as a draft_
which is in the button submenu area, it works perfectly.
2. restore a draft version
As a draft version, there should not have a second option _Restore as a
draft_, because it is a draft version itself, so this second option and
the submenu is not required in this scenario, but actually it shows an
empty submenu which is not a good idea
### How?
Check if this version is a draft version, if yes, no need to set a
render prop to the button component, so the empty popup won't be
displayed.
Fixes#10754
Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
### What?
This PR fixes an issue for tab subfield permissions
### Why?
Permissions were not being correctly extracted when passing them down.
### How?
Properly extracts permissions when rendering fields inside the active tab.
Fixes#10720
---------
Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
### What?
Fixes bug with **plugin-nested-docs**. The plugin should update the
breadcrumb data of any child documents when the parent doc is updated,
currently only the **draft** child document is updated.
### How?
Updates the resave function to fetch draft and published child docs.
Closes issue #10066
### What?
Tenant ID is a `number` but the `beforeChange` hook shows it as a `string`.
Getting tenant ID from cookie does not work properly in PG
### Why?
A `ValidationError` is throwing when reading a pg numeric id from the cookie.
### How?
Adjust the id based on the idType on the collection.
Fixes#10740
---------
Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
Improves the logging that `routeError` throws.
Logs were sometimes being swallowed if there was a problem with the
incoming request. Now they will surface.