Commit Graph

13746 Commits

Author SHA1 Message Date
Alessio Gravili
fafaa04e1a fix(drizzle): ensure updateOne does not create new document if where query has no results (#12991)
Previously, `db.updateOne` calls with `where` queries that lead to no
results would create new rows on drizzle. Essentially, `db.updateOne`
behaved like `db.upsertOne` on drizzle
2025-07-02 13:56:59 -07:00
Germán Jabloñski
babcd599da fix(ui): save nested richtext inside inlineBlock (#12773)
Removing the `setTimeout` not only doesn't break any tests, but it also
fixes the linked issue.

The long comment above the if statement was added in
https://github.com/payloadcms/payload/pull/5460 and explains why the if
statement is necessary GIVEN the existence of the `setTimeout`, but the
`setTimeout` was introduced [earlier because the button apparently
didn't work](https://github.com/payloadcms/payload/issues/1414).

It seems to work now without the `setTimeout`, because otherwise the
tests wouldn't even pass. I also tested it manually, and it works fine.


Fixes #12687
2025-07-02 19:43:48 +00:00
Jessica Rynkar
ac19b78968 style(richtext-lexical): ensure error state is shown at small-break (#12827)
### What?
Shows error state (red left border) on small screens.

### Why?
The current error state disappears at small-break screen width.

### How?
Updates small-break error state to match the desktop error state for the
Lexical field.

##### Reported by client.
2025-07-02 12:16:50 -07:00
Jacob Fletcher
b40c581a27 fix(ui): autosave infinite loop within document drawer (#13007)
Required for #13005.

Opening an autosave-enabled document within a drawer triggers an
infinite loop when the root document is also autosave-enabled.

This was for two reasons:

1. Autosave would run and change the `updatedAt` timestamp. This would
trigger another run of autosave, and so on. The timestamp is now removed
before comparison to ensure that sequential autosave runs are skipped.

2. The `dequal()` call was not being given the `.current` property off
the ref object. This meant that is was never evaluate to `true` and
therefore never skip unnecessary autosaves to begin with.

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1210697235723932
2025-07-02 15:11:38 -04:00
Patrik
335af1b8c9 fix(plugin-import-export): preview table to include all selected columns regardless of populated data (#12985)
### What?

Ensure the export preview table includes all field keys as columns, even
if those fields are not populated in any of the returned documents.

### Why?

Previously, if none of the documents in the preview result had a value
for a given field, that column would be missing entirely from the
preview table.

### How?

- Introduced a `getFlattenedFieldKeys` utility that recursively extracts
all missing flattened field accessors from the collection’s config that
are undefined

- Updates the preview UI logic to build columns from all flattened keys,
not just the first document
2025-07-02 09:28:21 -07:00
Alessio Gravili
583a733334 feat(drizzle): support half-precision, binary, and sparse vectors column types (#12491)
Adds support for `halfvec` and `sparsevec` and `bit` (binary vector)
column types. This is required for supporting indexing of embeddings >
2000 dimensions on postgres using the pg-vector extension.
2025-07-02 19:24:53 +03:00
Jessica Rynkar
6e5ddc8873 fix(examples): only allow super admins to create users with super admin role (#13015)
### What?

This PR updates the `create` access control on the `users` collection in
the `multi-tenant` example to prevent unauthorized creation of
`super-admin` users.

### Why?

Previously, any authenticated user could create a new user and assign
them the `super-admin` role — even if they didn’t have that role
themselves. This bypassed role-based restrictions and introduced a
security vulnerability, allowing users to escalate their own privileges
by working around role restrictions during user creation.

### How?

The `create` access function now checks whether the current user has the
`super-admin` role before allowing the creation of another
`super-admin`. If not, the request is denied.


**Fixes:** `CMS2-Q225-01`
2025-07-02 15:42:55 +01:00
Jarrod Flesch
9ba740e472 fix(ui): field bulk upload showing stale data (#13006) 2025-07-02 10:11:51 -04:00
Jessica Rynkar
50029532aa fix(examples): checks requested tenant matches user tenant permissions (#13012)
### What

This PR updates the `create` access control functions in the
`multi-tenant` example to ensure that any `tenant` specified in a create
request matches a tenant the user has admin access to.

### Why

Previously, while the admin panel UI restricted the tenant selection, it
was still possible to bypass this by making a request directly to the
API with a different `tenant`. This allowed users to create documents
under tenants they shouldn't have access to.

### How

The `access` functions on the `users` and `pages` collections now
explicitly check whether the tenant(s) in the request are included in
the user's tenant permissions. If not, access is denied by returning
`false`.

**Fixes: CMS2-Q225-03**
2025-07-02 14:30:47 +01:00
Jacob Fletcher
c80b6e92c4 fix(ui): prevent document drawer from remounting on save (#13005)
Supersedes #12992. Partially closes #12975.

Right now autosave-enabled documents opened within a drawer will
unnecessarily remount on every autosave interval, causing loss of input
focus, etc. This makes it nearly impossible to edit these documents,
especially if the interval is very short.

But the same is true for non-autosave documents when "manually" saving,
e.g. pressing the "save draft" or "publish changes" buttons. This has
gone largely unnoticed, however, as the user has already lost focus of
the form to interact with these controls, and they somewhat expect this
behavior or at least accept it.

Now, the form remains mounted across autosave events and the user's
cursor never loses focus. Much better.

Before:


https://github.com/user-attachments/assets/a159cdc0-21e8-45f6-a14d-6256e53bc3df

After:


https://github.com/user-attachments/assets/cd697439-1cd3-4033-8330-a5642f7810e8

Related: #12842

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1210689077645986
2025-07-02 09:07:08 -04:00
Jarrod Flesch
a9580e05ac fix: disable graphql introspection queries when disableIntrospectionInProduction is true (#12982) 2025-07-02 08:33:20 -04:00
Jarrod Flesch
57d00ad2e9 test: reduce queue test amount (#13008) 2025-07-01 15:55:16 -04:00
Jarrod Flesch
a9ad7c771e fix(ui): bulk upload redirecting to relationship documents when added (#13001)
Fixes https://github.com/payloadcms/payload/issues/12786
2025-07-01 15:23:11 -04:00
Patrik
7a40a9fc06 fix(ui): skip disabled fields when adding OR filter conditions in list view (#13004)
### What?

Fixes a bug where adding an additional OR filter condition in the list
view selects a field with `admin.disableListFilter: true`, causing all
filter fields to appear disabled.

### Why?

When the first field in a collection has `disableListFilter` set to
`true`, adding a second OR condition defaults to using that field. This
leads to a broken filter UI where no valid fields are selectable.

### How?

Replaces the hardcoded usage of `reducedFields[0]` with a call to
`reducedFields.find(...) `that skips fields with `disableListFilter:
true`, consistent with the logic already used when adding the first
filter condition.

Fixes #12993
2025-07-01 11:35:48 -07:00
Patrik
b1ae749311 fix(ui): render preview sizes button when adjustments are disabled but image sizes are defined (#12999)
### What?

The "Preview Sizes" button in the file upload UI was not showing up if:
- `crop` and `focalPoint` were both `false`
- No `customUploadActions` were provided
- But image sizes were configured

### Why?

This happened because `UploadActions` wasn’t rendered at all unless
adjustments or custom actions were present.

### How?

Update the conditional in `StaticFileDetails` to also render
`UploadActions` when:
- `hasImageSizes` is `true` and the document has a `filename`

Fixes #12832
2025-07-01 07:44:48 -07:00
Jacob Fletcher
3f30a2e300 fix(ui): block rows unexpectedly collapse and array rows not collapsed on init (#12987) 2025-06-30 21:12:26 -04:00
Jarrod Flesch
c07187d804 test: fix multi-tenant flakes (#12983) 2025-06-30 17:18:41 -04:00
Sasha
0e8ac0bad5 fix(db-postgres): joins with hasMany: true relationships nested to an array (#12980)
Fixes https://github.com/payloadcms/payload/issues/12679
2025-06-30 21:25:29 +03:00
Alessio Gravili
463c9754c7 templates: fix pnpm 10 ignored build scripts warning (#12974)
When using pnpm 10 to install any of our templates, the following
warning is thrown:

![Screenshot 2025-06-29 at 13 23
28@2x](https://github.com/user-attachments/assets/450630f1-0455-48a0-96e9-516110b6146c)

> Warning: Ignored build scripts: esbuild, unrs-resolver. Run "pnpm
approve-builds" to pick which dependencies should be allowed to run
scripts.

This PR fixes this by adding those packages to `onlyBuiltDependencies`
2025-06-29 15:17:34 -07:00
Alessio Gravili
4458f74cef ci: template errors not being caught due. fix: error due to updated generated-types User type (#12973)
This PR consists of two separate changes. One change cannot pass CI
without the other, so both are included in this single PR.


## CI - ensure types are generated

Our website template is currently failing to build due to a type error.
This error was introduced by a change in our generated types.

Our CI did not catch this issue because it wasn't generating types /
import map before attempting to build the templates. This PR updates the
CI to generate types first.

It also updates some CI step names for improved clarity.

## Fix: type error

![Screenshot 2025-06-29 at 12 53
49@2x](https://github.com/user-attachments/assets/962f1513-bc6c-4e12-9b74-9b891c49900b)


This fixes the type error by ensuring we consistently use the _same_
generated `TypedUser` object within payload, instead of `BaseUser`.
Previously, we sometimes used the generated-types user and sometimes the
base user, which was causing type conflicts depending on what the
generated user type was.

It also deprecates the `User` type (which was essentially just
`BaseUser`), as consumers should use `TypedUser` instead. `TypedUser`
will automatically fall back to `BaseUser` if no generated types exists,
but will accept passing it a generated-types User.

Without this change, additional properties added to the user via
generated-types may cause the user object to not be accepted by
functions that only accept a `User` instead of a `TypedUser`, which is
what failed here.

## Templates: re-generate templates to update generated types

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1210668927737258
2025-06-29 14:27:50 -07:00
Jacob Fletcher
cfc7adcbc5 fix: strict custom view paths (#12968) 2025-06-29 14:20:54 -04:00
Jarrod Flesch
16f5538e12 fix(plugin-multi-tenant): unnecessary modal appearing (#12854)
Fixes #12826 

Leave without saving was being triggered when no changes were made to
the tenant. This should only happen if the value in form state differs
from that of the selected tenant, i.e. after changing tenants.

Adds tenant selector syncing so the selector updates when a tenant is
added or the name is edited.

Also adds E2E for most multi-tenant admin functionality. 

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1210562742356842
2025-06-27 16:30:13 -04:00
Said Akhrarov
9f6030641a fix: appropriately throw unverified email error (#12933)
<!--

Thank you for the PR! Please go through the checklist below and make
sure you've completed all the steps.

Please review the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository if you haven't already.

The following items will ensure that your PR is handled as smoothly as
possible:

- PR Title must follow conventional commits format. For example, `feat:
my new feature`, `fix(plugin-seo): my fix`.
- Minimal description explained as if explained to someone not
immediately familiar with the code.
- Provide before/after screenshots or code diffs if applicable.
- Link any related issues/discussions from GitHub or Discord.
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Fixes #

-->
### What?
This PR addresses an issue where the order of operations/conditions for
throwing an unverified email error were incorrect.

### Why?
To properly throw an unverified email error under the correct
conditions.

### How?
Pushing this error to be thrown later in the operation.
2025-06-27 19:26:37 +00:00
Jacob Fletcher
f2213e5c5c feat: mount live preview to document root (#12860)
Mounts live preview to `../:id` instead `../:id/preview`.

This is a huge win for both UX and a maintainability standpoint.

Here are just a few of those wins:

1. If you edit a document, _then_ decide you want to preview those
changes, you are currently presented with the `LeaveWithoutSaving` modal
and are forced to either save your edits or clear them. This is because
you are being navigated to an entirely new page with it's own form
context. Instead, you should be able to freely navigate back and forth
between the two.
2. If you are an editor who most often uses Live Preview, or you are
editing a collection that typically requires it, you likely want it to
automatically enter live preview mode when you open a document.
Currently, the user has to navigate to the document _first_, then use
the live preview tab. Instead, you should be able to set a preference
and avoid this extra step.
3. Since the inception of Live Preview, we've been maintaining largely
the same code across the default edit view and the live preview view,
which often became out of sync and inconsistent—but they're essentially
doing the same thing. While we could abstract a lot of this out, it is
no longer necessary if the two views are combined into one.

This change does also include some small modifications to UI. The "Live
Preview" tab no longer exists, and instead has been replaced with a
button placed next to the document controls (subject to change).

Before:


https://github.com/user-attachments/assets/48518b02-87ba-4750-ba7b-b21b5c75240a

After:


https://github.com/user-attachments/assets/a8ec8657-a6d6-4ee1-b9a7-3c1173bcfa96
2025-06-27 11:58:00 -04:00
Jessica Rynkar
6f6d305f9d fix(ui): prevent error if rows is undefined in mergeServerFormState (#12962)
### What? 
Adds optional chaining when accessing `rows` in `mergeServerFormState`
to prevent error crashing the UI.

### Why? 
When an array field is populated in a `beforeChange` hook and was
previously empty, it crashes `mergeServerFormState.ts` on this line
because no `rows` exist:

```ts 
const indexInCurrentState = currentState[path].rows.findIndex
``` 

The line after this checks `if (indexInCurrentState > -1)` so returning
undefined here will not affect the subsequent code.

### How? 
Added optional chaining to the access of `rows`, which prevents the
error being thrown.

Fixes #12944
2025-06-27 15:57:48 +00:00
Paul
c902f14cb3 fix(db-mongodb): add ability to disable fallback sort and no longer adds a fallback for unique fields (#12961)
You can now disable fallback sort in the mongodb adapter by passing
`disableFallbackSort: true` in the options.

We also no longer add fallback sort to sorts on unique fields by default
now.

This came out of a discussion in this issue
https://github.com/payloadcms/payload/issues/12690
and the linked PR https://github.com/payloadcms/payload/pull/12888

Closes https://github.com/payloadcms/payload/issues/12690
2025-06-27 13:45:30 +00:00
Elliot DeNolf
c66e5ca823 chore(release): v3.44.0 [skip ci] v3.44.0 2025-06-27 09:23:04 -04:00
James Mikrut
26d709dda6 feat: auth sessions (#12483)
Adds full session functionality into Payload's existing local
authentication strategy.

It's enabled by default, because this is a more secure pattern that we
should enforce. However, we have provided an opt-out pattern for those
that want to stick to stateless JWT authentication by passing
`collectionConfig.auth.useSessions: false`.

Todo:

- [x] @jessrynkar to update the Next.js server functions for refresh and
logout to support these new features
- [x] @jessrynkar resolve build errors

---------

Co-authored-by: Elliot DeNolf <denolfe@gmail.com>
Co-authored-by: Jessica Chowdhury <jessica@trbl.design>
Co-authored-by: Jarrod Flesch <30633324+JarrodMFlesch@users.noreply.github.com>
Co-authored-by: Sasha <64744993+r1tsuu@users.noreply.github.com>
2025-06-27 09:13:52 -04:00
Jacob Fletcher
c8b72141e4 feat: collection-level preferences (#12909)
Needed for #12860.

The new live preview pattern requires collection-level preferences, a
pattern that does not yet exist.

Instead of creating a new record for these types of preferences, we can
simply reuse `<collectionSlug>-list` under a more general key:
`collection-<slug>`. This way other relevant properties can be attached
in the future that might not specifically apply to the list view.

This will also match the conventions already estalished by
document-level preferences in `collection-<slug>-<id>` and
`global-<slug>`.

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1210628212784050
2025-06-27 09:08:47 -04:00
Elliot DeNolf
1db06195c2 ci: bring back CODEOWNERS file for reviews, approval not required [skip ci] 2025-06-27 09:00:52 -04:00
Roman
6a935d4d4d examples: fix broken navigation to post in localization example (#12810)
This pull request updates the `Card` component in the localization
example to support localized URLs. The most significant changes include
importing a new hook for locale management and modifying the URL
generation logic to include the locale.

Localization updates:

*
[`examples/localization/src/components/Card/index.tsx`](diffhunk://#diff-619212c47638e7ff51284c62740ba188c87f008d481442b7f4951e2c150a2415R5):
Imported `useLocale` from `next-intl` to manage locale-based
functionality.
*
[`examples/localization/src/components/Card/index.tsx`](diffhunk://#diff-619212c47638e7ff51284c62740ba188c87f008d481442b7f4951e2c150a2415R20):
Added a `locale` constant using the `useLocale` hook to retrieve the
current locale.
*
[`examples/localization/src/components/Card/index.tsx`](diffhunk://#diff-619212c47638e7ff51284c62740ba188c87f008d481442b7f4951e2c150a2415L28-R30):
Updated the `href` generation logic to include the locale in the URL
structure, ensuring localized navigation.
2025-06-27 11:11:16 +00:00
Jesper We
c3c1614fa6 fix(ui): usePreventLeave should not show alert for exceptions (#12722)
When using 3rd party custom components in an edit form there exists a
possibility that a non-navigational click event will propagate through
to payload.

In this case the `findClosestAnchor` function in `usePreventLeave` may
find an anchor without href, resulting in the `newUrlObj = new
URL(newUrl)` in `isAnchorOfCurrentUrl` throwing the exception:

> TypeError: URL constructor:  is not a valid URL.

As a result a native alert is shown to the user, with no real
explanation as to what is going on. This is not a good experience.

I suggest moving it to a console log which is less "in your face" for
users who do not know what to do about it anyway.

I discovered this while using a data grid component with a context menu.
Clicking on menu items (which are `<a>` tags without href in this
component) triggers the error.

(Another on-liner fix would ofc be to not attempt to create an URL
object if there is no href `if (anchor?.href) {`, but I opted for this
version since using `alert()` in production code is not a preferred
practice anyway)

<!--

Thank you for the PR! Please go through the checklist below and make
sure you've completed all the steps.

Please review the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository if you haven't already.

The following items will ensure that your PR is handled as smoothly as
possible:

- PR Title must follow conventional commits format. For example, `feat:
my new feature`, `fix(plugin-seo): my fix`.
- Minimal description explained as if explained to someone not
immediately familiar with the code.
- Provide before/after screenshots or code diffs if applicable.
- Link any related issues/discussions from GitHub or Discord.
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Fixes #

-->
2025-06-27 07:00:04 -04:00
ThijsAtFreave
e7695502e3 fix: richTextField supports beforeInput/afterInput, but these were missing from types.ts (#12889)
Add `afterInput` and `beforeInput` to `admin.components` of
RichTextField type. These props are supported but missing from types.
2025-06-27 06:50:04 -04:00
Sam Wheeler
0e9865c564 fix(ui): vertically align table headers to the middle (#12699)
This fixes a small ui bug where the items in the table header were not
vertically aligned when they don't contain the SortColumn component. The
SortColumn component handles vertical alignment with a nested flexbox.
The PR adds vertical-align: middle directly to the th element so that
the text in the header is vertically aligned even when there isn't a
nested flexbox

Before:
<img width="719" alt="Screenshot 2025-06-05 at 10 24 19 AM"
src="https://github.com/user-attachments/assets/3962517e-3b22-452a-af04-8397549c4ed9"
/>

After:
<img width="719" alt="Screenshot 2025-06-05 at 10 30 39 AM"
src="https://github.com/user-attachments/assets/0c5a0847-8ee2-4439-981e-f3538908e920"
/>
2025-06-27 06:43:41 -04:00
Chandler Gonzales
e5e0ec86c5 docs: remove group from list of default field validations (#12921)
### What?

Removes group from the list of default field validations in the docs

### Why?

It doesn't exist in the code:
886c07e918/packages/payload/src/fields/validations.ts
2025-06-27 06:34:22 -04:00
Jessica Rynkar
c76d83985d fix(plugin-multi-tenant): updates tenant selector upon tenant creation (#12936)
### What?
Updates the tenant selector displayed in the sidebar when a new tenant
is created.

### Why?
Currently when using the multi-tenant plugin and creating a new tenant
doc, the tenant selector dropdown does not display the new tenant as an
option until the page gets refreshed.

### How?
Extends the `WatchTenantCollection` helper to check if the tenant `id`
from the current doc exists, if the tenant is new it manually calls
`updateTenants`. The `updateTenants` function previously only adjusted
the title on existing tenants, this has been updated to add a new tenant
as an option when it doesn't exist.

#### Reported by client
2025-06-27 06:26:05 -04:00
Said Akhrarov
a1822d21d0 fix(ui): properly render create new button in polymorphic joins (#12930)
<!--

Thank you for the PR! Please go through the checklist below and make
sure you've completed all the steps.

Please review the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository if you haven't already.

The following items will ensure that your PR is handled as smoothly as
possible:

- PR Title must follow conventional commits format. For example, `feat:
my new feature`, `fix(plugin-seo): my fix`.
- Minimal description explained as if explained to someone not
immediately familiar with the code.
- Provide before/after screenshots or code diffs if applicable.
- Link any related issues/discussions from GitHub or Discord.
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Fixes #

-->
### What?
This PR fixes an issue where the bottom "Create new ..." button would
cause a runtime error due to not accounting for a polymorphic join
setup.

### Why?
To prevent a runtime error and allow users the ability to add new
documents to the join as expected even in a polymorphic setup.

### How?
Creation of a new `AddNewButton` which handles all of the add new button
instances in the `RelationshipTable` component.

Addresses
https://github.com/payloadcms/payload/issues/12913#issuecomment-3001475438

Before:


[join-polymorphic-runtime-error--Payload.webm](https://github.com/user-attachments/assets/fad3a1ba-c51c-4731-84cc-c27adbaac1d9)


After:

[polymorphic-after-Editing---Multiple-Collections-Parent---Payload
(1).webm](https://github.com/user-attachments/assets/e3baf902-1b2b-4f19-8b6d-838edd6fef80)
2025-06-27 05:47:36 -04:00
Dani Calero 🚀
4b9566f8b8 fix(ui): render DateTime label as <label> instead of <span> (#12949)
## What / Why
Date & Time fields were rendering their field label as a `<span>` while
every other field type uses a proper `<label>` with a matching
`htmlFor`.

Because the element was a span it broke styles and made 'field-label'
have different styles from the rest of 'field-label's.

**Root cause:** DateTimeField failed to pass its `path` (or an explicit
`htmlFor`) to `FieldLabel`. When `FieldLabel` receives no `htmlFor`, it
intentionally downgrades to a `<span>`.

## Screenshots

### Before

![image](https://github.com/user-attachments/assets/edecfce7-0326-4f3e-af76-d7b37158343a)
*DateTime label rendered as `<span>`, causing style inconsistencies*

### After  

![image](https://github.com/user-attachments/assets/d9fb06c2-1ca0-4f8d-803d-15c6c6355d1e)
*DateTime label now rendered as proper `<label>` element*

## Changes introduced
- `packages/ui/src/fields/DateTime/index.tsx`
  - Added `path={path}` prop to `FieldLabel` component

## Behavior after the fix
- Date-time labels are now real `<label>` elements with `for="field-…"`
- Visual alignment now matches every other field type  

## How to test manually
1. Run `pnpm dev fields`
2. Inspect the DateTime field markup – label is now `<label>` 
3. Observe that vertical spacing matches other types of fields
2025-06-27 05:34:28 -04:00
Sasha
54afaf9529 fix(db-mongodb): strip deleted from the config blocks from the result (#12869)
If you (using the MongoDB adapter) delete a block from the payload
config, but still have some data with that block in the DB, you'd
receive in the admin panel an error like:
```
Block with type "cta" was found in block data, but no block with that type is defined in the config for field with schema path pages.blocks
```

Now, we remove those "unknown" blocks at the DB adapter level.

Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
2025-06-27 05:30:48 -04:00
Patrik
3830d710a4 feat(plugin-import-export): preview displays CSV and JSON data accurately (#12948)
### What

This PR updates the import-export plugin's `<Preview />` component to
render table columns and rows using the same logic as the CSV export.

Key changes:
- Adds a new `/api/preview-data` custom REST endpoint that:
  - Accepts filters (`fields`, `where`, `sort`, `draft`, `limit`)
- Uses `getCustomFieldFunctions` and `flattenObject` to transform
documents
  - Returns deeply flattened rows identical to the CSV export
- Refactors the <Preview /> component to:
- POST preview config to the new endpoint instead of querying the
collection directly
- Match column ordering and flattening logic with the `createExport`
function
- Ensures consistency across CSV downloads and in-admin previews
-Adds JSON preview

This ensures preview results now exactly match exported CSV content,
including support for custom field transformers and polymorphic fields.

---------

Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
2025-06-27 05:10:28 -04:00
Dave Ryan
2da6d924de fix: validate "null" value for point field as true when its not required (#12908)
### What?

This PR solves an issue with validation of the `point` field in Payload
CMS. If the value is `null` and the field is not required, the
validation will return `true` before trying to examine the contents of
the field

### Why?

If the point field is given a value, and saved, it is then impossible to
successfully "unset" the point field, either through the CMS UI or
through a hook like `beforeChange`. Trying to do so will throw this
error:

```
[17:09:41] ERROR: Cannot read properties of null (reading '0')
    err: {
      "type": "TypeError",
      "message": "Cannot read properties of null (reading '0')",
      "stack":
          TypeError: Cannot read properties of null (reading '0')
              at point (webpack-internal:///(rsc)/./node_modules/.pnpm/payload@3.43.0_graphql@16.10.0_typescript@5.7.3/node_modules/payload/dist/fields/validations.js:622:40)
```

because a value of `null` will not be changed to the default value of
`['','']`, which in any case does not pass MongoDB validation either.

```
[17:22:49] ERROR: Cast to [Number] failed for value "[ NaN, NaN ]" (type string) at path "location.coordinates.0" because of "CastError"
    err: {
      "type": "CastError",
      "message": "Cast to [Number] failed for value \"[ NaN, NaN ]\" (type string) at path \"location.coordinates.0\" because of \"CastError\"",
      "stack":
          CastError: Cast to [Number] failed for value "[ NaN, NaN ]" (type string) at path "location.coordinates.0" because of "CastError"
              at SchemaArray.cast (webpack-internal:///(rsc)/./node_modules/.pnpm/mongoose@8.15.1_@aws-sdk+credential-providers@3.778.0/node_modules/mongoose/lib/schema/array.js:414:15)
```


### How?

This adds a check to the top of the `point` validation function and
returns early before trying to examine the contents of the point field

---------

Co-authored-by: Dave Ryan <dmr@Daves-MacBook-Pro.local>
2025-06-27 07:49:47 +00:00
Jarrod Flesch
86e48ae70b test: bulk edit flaky selectors (#12950)
https://github.com/payloadcms/payload/pull/12861 introduced some flaky
test selectors. Specifically bulk editing values and then looking for
the previous values in the table rows.

This PR fixes the flakes and fixes eslint errors in `findTableRow` and
`findTableCell` helper funcitons.
2025-06-26 22:40:19 -04:00
Kendell
7ebac630f7 test: adds test for skipSafeFetch allowList (#12954)
Adds missing test in PR: #12927
2025-06-26 17:14:49 -04:00
Ondřej Závodný
7472798808 fix(live-preview): client-side live preview cannot populate more than 10 relationships at once (#12929)
### What?

Set the `limit` query param on API requests called within the
`useLivePreview` hook.

### Why?

We are heavily relying on the block system in our pages and we reuse the
media collection in a lot of the block types. When the page has more
than 10 images, the API request doesn't fetch all of them for live
preview due to the default 10 item `limit`. This PR allows the preview
page to override this `limit` so that all the items get correctly
fetched.

### Our current workaround

Set the `depth` param of `useLivePreview` hook like this:

```
useLivePreview({
  // ...
  depth: '1000&limit=1000',
})
```

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1210643905956939

---------

Co-authored-by: Jacob Fletcher <jacobsfletch@gmail.com>
2025-06-26 16:36:49 -04:00
Said Akhrarov
605c993bb7 fix(drizzle): skip column if undefined in findMany (#12902)
<!--

Thank you for the PR! Please go through the checklist below and make
sure you've completed all the steps.

Please review the
[CONTRIBUTING.md](https://github.com/payloadcms/payload/blob/main/CONTRIBUTING.md)
document in this repository if you haven't already.

The following items will ensure that your PR is handled as smoothly as
possible:

- PR Title must follow conventional commits format. For example, `feat:
my new feature`, `fix(plugin-seo): my fix`.
- Minimal description explained as if explained to someone not
immediately familiar with the code.
- Provide before/after screenshots or code diffs if applicable.
- Link any related issues/discussions from GitHub or Discord.
- Add review comments if necessary to explain to the reviewer the logic
behind a change

### What?

### Why?

### How?

Fixes #

-->
### What?
This PR fixes an issue where sorting on a traditional virtual field with
`virtual: true` while using a drizzle-based db adapter would cause a
runtime error.

### Why?
To skip attempting to sort virtual fields which are not linked to a
relationship/upload and prevent a runtime error from surfacing.

### How?
Skipping the deletion of the property from the `selectFields` object if
the column is false-y.

Fixes #12886

Before:


[sort-virtualfield-drizzle-error.mp4](https://private-user-images.githubusercontent.com/78685728/457602747-b8661e47-a1a8-4453-b2ec-b7e7199b9846.mp4?jwt=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJnaXRodWIuY29tIiwiYXVkIjoicmF3LmdpdGh1YnVzZXJjb250ZW50LmNvbSIsImtleSI6ImtleTUiLCJleHAiOjE3NTA2OTU0NzksIm5iZiI6MTc1MDY5NTE3OSwicGF0aCI6Ii83ODY4NTcyOC80NTc2MDI3NDctYjg2NjFlNDctYTFhOC00NDUzLWIyZWMtYjdlNzE5OWI5ODQ2Lm1wND9YLUFtei1BbGdvcml0aG09QVdTNC1ITUFDLVNIQTI1NiZYLUFtei1DcmVkZW50aWFsPUFLSUFWQ09EWUxTQTUzUFFLNFpBJTJGMjAyNTA2MjMlMkZ1cy1lYXN0LTElMkZzMyUyRmF3czRfcmVxdWVzdCZYLUFtei1EYXRlPTIwMjUwNjIzVDE2MTI1OVomWC1BbXotRXhwaXJlcz0zMDAmWC1BbXotU2lnbmF0dXJlPTE3NmMzOWI5YjNiNzEwYzk3ZWUyNDllYTBjMzZkNzkzMjhjNzc5YzJhNDlkOTBiNDk5MDFhMTdmNDA4NjJhZWQmWC1BbXotU2lnbmVkSGVhZGVycz1ob3N0In0.N1GJsiI_gZ8M54VHCAmiPEhcJGqRw3Ucy-VeM5R7UFE)

After: 


[virtualfields-sort-Posts---Payload.webm](https://github.com/user-attachments/assets/f5a15d98-4a40-4817-bc6a-415f3ec27484)

<details>

<summary>Collection config used above</summary>

```ts
export const PostsCollection: CollectionConfig = {
  slug: postsSlug,
  admin: {
    useAsTitle: 'title',
    defaultColumns: ['title', 'exampleField'],
  },
  fields: [
    {
      name: 'title',
      type: 'text',
    },
    {
      name: 'exampleField',
      type: 'text',
      virtual: true,
      admin: {
        readOnly: true,
      },
      hooks: {
        afterRead: [({ data }) => data?.title],
      },
    },
    {
      type: 'relationship',
      name: 'category',
      relationTo: 'categories',
    },
    {
      name: 'categoryTitle',
      type: 'text',
      virtual: 'category.title',
    },
  ],
}
```

</details>

---------

Co-authored-by: Sasha <64744993+r1tsuu@users.noreply.github.com>
2025-06-26 19:52:29 +00:00
Kendell
a7ad573a0e fix: get external resource blocked (#12927)
## Fix
- Use `[Config].upload.skipSafeFetch` to allow specific external urls
- Use `[Config].upload.pasteURL.allowList` to allow specific external
urls

Documentation: [Uploading files from remote
urls](https://payloadcms.com/docs/upload/overview#uploading-files-from-remote-urls)

Fixes: https://github.com/payloadcms/payload/issues/12876
Mentioned: https://github.com/payloadcms/payload/issues/7037,
https://github.com/payloadcms/payload/issues/12934
Source PR: https://github.com/payloadcms/payload/pull/12622
Issue Trace:
1. [`allowList`
Added](8b7f2ddbf4 (diff-92acf7b8d30e447a791e37820136bcbf23c42f0358daca0fdea4e7b77f7d4bc9)
)

2. [`allowList`
Removed](648c168f86 (diff-92acf7b8d30e447a791e37820136bcbf23c42f0358daca0fdea4e7b77f7d4bc9))
2025-06-26 15:24:39 -04:00
Jarrod Flesch
d62d9b4b8e fix(ui): bulk upload losing state when adding additional files (#12946)
Fixes an issue where adding additional upload files would clear the
state of the originally uploaded files.
2025-06-26 15:23:38 -04:00
Jacob Fletcher
67fa5a0b3b fix(live-preview): foreign postMessage events reset client-side state (#12925)
Needed for #12860.

If the admin panel broadcasts foreign postMessage events, i.e. those
without the `payload-live-preview` signature, client-side live preview
subscriptions will reset back to initial state.

This is because we dispatch two postMessage events in the admin panel,
one for client-side live preview to catch (`payload-live-preview`), and
the other for server-side live preview (`payload-document-event`). This
was not previously noticeable because both events would only get called
simultaneously on initial render, where initial state is already the
expected result.

Now that Live Preview can be freely toggled on and off, both events are
frequently dispatched and very obviously disregard the current working
state.

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1210628466702818
2025-06-26 14:05:21 -04:00
Jacob Fletcher
bcb10b52b3 fix: restore missing properties to live preview client config (#12904)
Needed for #12860.

The client config unnecessarily omits the `livePreview.collections` and
`livePreview.globals` properties. This is because the root live preview
config extends the type with these two additional properties without
sharing it elsewhere. To led to the client sanitization function
overlooking these additional properties, as there was no type indication
that they exist.

The `collections` and `globals` properties are now appended to the
client config as expected, and the root live preview is standardized
behind the `RootLivePreviewConfig` type to ensure no properties are
lost.

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1210628466702823
2025-06-26 14:05:10 -04:00
Paul
87c7952558 feat(templates): added int and e2e tests to blank and website templates (#12866)
This PR adds int tests with vitest and e2e tests with playwright
directly into our templates.

The following are also updated:
- bumps core turbo to 2.5.4 in monorepo
- blank and website templates moved up to be part of the monorepo
workspace
- this means we now have thes templates filtered out in pnpm commands in
package.json
- they will now by default use workspace packages which we can use for
manual testing and int and e2e tests
  - note that turbo doesnt work with these for dev in monorepo context
- CPA script will fetch latest version and then replace `workspace:*` or
the pinned version in the package.json before installation
- blank template no longer uses _template as a base, this is to simplify
management for workspace
- updated the generate template variations script
2025-06-26 13:55:28 -04:00