4660 Commits

Author SHA1 Message Date
Elliot DeNolf
766b67f0be chore(release): v3.14.0 [skip ci] 2025-01-03 08:34:41 -05:00
Sasha
4e57054bb7 fix: ensure scheduled publish restriction (#10317) 2025-01-03 08:26:21 -05:00
Jacob Fletcher
b14935ce28 fix(ui): unable to find user field schemas when updating password (#10305)
When updating password within the account view, the server console
throws an error because it is unable to find the remaining user fields
when building form state. This was because the field schema map sets
these fields within its own `_users.auth` key, separate from the other
fields. When the form submits, it uses this key as the schema path,
which may not contain all user fields, even though it sends full
document data through the request.
2025-01-02 17:54:49 -05:00
Sasha
2e58a4ad27 fix: ensure loggingLevels is respected (#10308)
Issue https://github.com/payloadcms/payload/issues/10272

Adds `logError` utility that can be used across the codebase for logging
errors
2025-01-02 21:42:08 +00:00
Paul
d9e0cd360b fix: 'oldValue' must be a string error when viewing version diffs in postgres (#10313)
Fixes https://github.com/payloadcms/payload/issues/10068

We were accidentally not catching that in postgres IDs return as strings
but the react diff viewer expects a string
2025-01-02 21:25:51 +00:00
Jacob Fletcher
abb51b98eb fix(ui): properly instantiates abort controllers (#10309)
Fixes #10296. When an async `useEffect` runs twice or more before
resolving, we use the Abort Controller API to cancel previous events.
This works by instantiating a new ref on each run, and if a previous ref
was detected, it will be aborted and a new instance will be set up for
the next run. However, while the logic was aborting previous instances
as expected, it was failing to instantiate a new one.
2025-01-02 15:08:38 -05:00
Tristan
38f34551a2 feat: add Estonian language support (#10169)
Adding Estonian language support for the Payload CMS.

---------

Co-authored-by: Dan Ribbens <dan.ribbens@gmail.com>
2025-01-02 19:41:47 +00:00
Jacob Fletcher
7928ecaee7 fix: safely executes form state conditions, validations, and default values (#10275)
Whenever form state fails, like when field conditions, validations, or
default value functions throw errors, blocks and array rows are stuck
within an infinite loading state. Examples of this might be when
accessing properties of undefined within these functions, etc. Although
these errors are logged to the server console, the UI is be misleading,
where the user often waits for the request to resolve rather than
understanding that an underlying API error has occurred. Now, we safely
execute these functions within a `try...catch` block and handle their
failures accordingly. On the client, form state will resolve as expected
using the default return values for these functions.
2025-01-02 14:12:28 -05:00
Said Akhrarov
2ae7d8e5d4 fix(ui): gracefully handle deletions in collection with upload hasMany (#9426)
### What?
This PR aims to prevent a runtime error by allowing deletions in media
collections and preventing them from impacting workflows while using
`hasMany` upload fields.

### Why?
To prevent runtime issues during common tasks.

### How?
By treating deleted media documents as empty placeholders instead of
undefined objects.

Fixes #9328

Before:

[Dashboard-before--Payload.webm](https://github.com/user-attachments/assets/32cbfe1d-2569-43bc-be05-abd2d9913b9b)

After:

[Dashboard-after--Payload.webm](https://github.com/user-attachments/assets/b5cb67b8-21de-403c-879c-680e49fd380c)

Notes:
- There is room for improvement here: allow selection of existing media
in upload collection instead of forcing user to upload new. Workaround
is to remove the row and choose existing as usual.
- New uploads chosen will always replace the first instance of undefined
placeholder due to the simple check. If you have 3 deleted entries and
open the drawer on the second one, then it will populate the first one
anyway. This can be improved but will require more laborious code
changes.
- Noticed an issue where deleted non-hasMany upload fields do not
re-render after a file is uploaded. It only shows the previous deleted
doc, ie id: "untitled - ID: ...". Re-renders correctly when choosing
from existing. This is unrelated to this PR. I will investigate further.
- I'm realizing this actually diverges from what `db-postgres` does, as
deleted entries in a `hasMany` upload gets removed from the field in the
initial deletion probably due to cascading the deletion...
2025-01-02 18:55:24 +00:00
Jacob Fletcher
d38ca839cb fix(next): returns proper verb tenses from update and delete routes (#10307)
When hitting the delete or updates routes and no docs were effected, the
API returns success messages with improper verb tenses, i.e. `Deleted 0
Post successfully`.
2025-01-02 13:30:52 -05:00
Sondre Ørland
c65802233c chore(translations): adjust Norwegian translation of events (#10300)
`Hendelse` makes more sense in the context of the new scheduled publish
feature.
2025-01-02 17:30:16 +00:00
Germán Jabloñski
018c1933b0 fix(richtext-lexical): allow any priority of FOCUS_COMMAND (#10128)
This revert patch behavior on indent in Firefox, in order to fix #10049
2025-01-02 17:16:18 +00:00
Patrik
bd7f70545a fix(ui): disable save button until the upload file is uploaded / ready (#10083)
### What?

Previously, while uploading a file - if the uploading process took a bit
of time, users could still save the document prior to the upload fully
completing.

### Why?

During the uploading process - the save button should be disabled until
the upload is complete to prevent premature saving of an upload
document.

### How?

Now, we keep track of the state of the upload in a provider and disable
the save button until the file is fully uploaded.
2025-01-02 09:35:53 -05:00
Elliot DeNolf
b0ebd92a1e chore(release): v3.13.0 [skip ci] 2025-01-01 23:15:48 -05:00
James Mikrut
f3f36d8010 fix(ui): checkboxes as first field were crashing WhereBuilder (#10290)
Fixes an issue where if a checkbox field was in the first position of a
collection, and you tried to filter on it via the List view, the page
would crash.
2024-12-31 23:55:43 +00:00
Alessio Gravili
ee3c2cc16f fix(richtext-lexical): empty lines were incorrectly stripped from mdx blocks if doNotTrimChildren was set to true (#10287)
This caused empty lines to disappear from code blocks
2024-12-31 21:58:46 +00:00
Elliot DeNolf
c3eb272d3c fix(cpa): do not overwrite custom.scss file on update (#10285)
No longer overwrite an existing `custom.scss` file if using
`create-payload-app` to update an existing project.

Fixes #9983
2024-12-31 12:04:42 -05:00
Jacob Fletcher
be87ba0ecd docs: adds useListQuery to list of React hooks and updates useDocumentInfo (#10186)
The `useListQuery` was currently undocumented and the `useDocumentInfo`
hook was out of date.
2024-12-31 16:31:23 +00:00
Elliot DeNolf
c4b31c079f fix(plugin-cloud-storage): actually deprecate adapters (#9640)
In v2, plugin-cloud-storage exported some adapters that were marked for
deprecation. These were replaced by standalone `@payloadcms/storage-*`
packages. More detail located in [this section of the migration
guide](https://github.com/payloadcms/payload/blob/main/docs/migration-guide/overview.mdx#payloadcmsplugin-cloud-storage).

Unfortunately, these exports were not removed prior to releasing 3.0.
2024-12-31 09:14:56 -05:00
Alessio Gravili
07e86c0f20 fix(richtext-lexical): throw toast error when attempting to create upload node without any upload collections enabled (#10277)
Fixes https://github.com/payloadcms/payload/issues/9136
2024-12-31 07:30:32 +00:00
Alessio Gravili
182eaa3433 feat(richtext-lexical): ability to override default placeholder (#10278)
![CleanShot 2024-12-30 at 23 28
01@2x](https://github.com/user-attachments/assets/0bab3a2a-bded-440f-9bfe-cb8bf5b74e2a)

![CleanShot 2024-12-30 at 23 28
08@2x](https://github.com/user-attachments/assets/589b7be0-f662-4c4a-b66b-66f9b88ee7c6)
2024-12-31 07:09:03 +00:00
Alessio Gravili
35df899547 fix(richtext-lexical): various issues for lexical sub-fields due to incorrectly generated client field schema map (#10276)
Fixes https://github.com/payloadcms/payload/issues/9905,
https://github.com/payloadcms/payload/issues/9660

Single lexical fields were represented file in the schema map (`path =>
field`). In the client schema map however, they were incorrectly
represented like this: `path => { fields: [field] } `
2024-12-31 06:33:43 +00:00
Gerard Du Pre
5188a9b2a0 feat(translations): add Catalan translations (#10260)
### What?
Translated payload to Catalan
### Why?
I needed to have payload in Catalan
### How?
By following the
[readme](https://github.com/payloadcms/payload/blob/main/packages/translations/README.md)

---------

Co-authored-by: Alessio Gravili <alessio@gravili.de>
2024-12-31 04:37:54 +00:00
Jesper We
c5b1cd600b chore(translations): fine-tune some Swedish texts (#10224)
### What?

Fix some minor nits with Swedish translations

### Why?

För att ge ett mer professionellt intryck.
2024-12-30 19:35:10 -07:00
Said Akhrarov
cdaebcc79c fix(plugin-search): respect custom api route in reindexButton (#10258)
<!--

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 with `plugin-search` where the ReindexButton was
not directing the reindex call to the correct endpoint location if the
user defined a custom config api route.

### Why?
To allow collection reindexing even when the default base api path gets
overriden with a user-provided one.

### How?
By threading the custom route to the ReindexButton component that calls
the reindex endpoint.

Fixes #10245

Notes:
- I think the `basePath` check/manipulation might be better in the RSC
instead of the client

Edit: @JessChowdhury Didn't see you were assigned until after! Felt bad
about this since it's my bad, wanted to take some ownership over the bug
here, my mistake!
2024-12-31 00:08:58 +00:00
James Mikrut
6dac4c5777 fix(ui): relationship edit drawers now respect current locale (#10262)
Fixes #9979
2024-12-30 23:46:00 +00:00
Jacob Fletcher
f5a955d906 fix(ui): properly filters fields from list view columns and conditions (#10246)
Fixes #10234. Some fields, such as focal point fields for upload enabled
collections, were rendering in the condition selector despite being
hidden from the column selector. This was because the logic for the
column selector was filtering fields without labels, but the same was
not being done for the filter conditions. This, however, is not a good
way to filter these fields as it requires this specific logic to be
written in multiple places. Instead, they need to explicitly check for
`hidden` and `disabled` in addition to `disableListFilter` and
`disableListColumn`. The actual filtering logic has been improved across
the two instances as well, removing multiple duplicative loops.

This change has also exposed a underlying issue with the way columns
were handled within the table columns provider. When row selections were
enabled, the selector columns were present in column state. This caused
problems when interacting with column indices, such as when reordering
columns. Instead of needing to manually filter these out every time we
need to work with column state, they no longer appear there in the first
place. Instead, we inject the row selectors directly into the table
itself, completely isolating these row selectors from the column state.
2024-12-30 23:39:48 +00:00
Alessio Gravili
885e96636d fix(richtext-lexical): formatted link markdown conversion not working (#10269)
Fixes https://github.com/payloadcms/payload/issues/8279

Ports over https://github.com/facebook/lexical/pull/7004
2024-12-30 22:48:03 +00:00
James Mikrut
7a59e7da46 feat: adds more control over how to disable graphql for collections /… (#10265)
Adds more control over how you can disable GraphQL queries / mutations
for collections and globals.

For example, you might want to disable all GraphQL queries and mutations
for a given collection, but you still have relationship fields that
relate to that collection, therefore depend on the types being
generated.

Now, instead of passing `graphQL: false` (which completely disables
everything, including types, which would break relationship fields) you
can now specify `graphQL.disableQueries: true` and
`graphQL.disableMutations: true`to keep the types, but disable just the
queries / mutations.

Closes #9893
2024-12-30 22:20:31 +00:00
Dan Ribbens
039b489cb8 fix(ui): disableListColumn on first field breaks filter condition selection (#10267)
What?
This PR fixes an issue with the WhereBuilder where if the first field in
a collection had disableListFilter enabled, the select in that fields
Condition would be rendered disabled, making it impossible to query docs
in list view.

Why?
To allow users to query their documents while still being able to set
disableListFilter on fields regardless of where they are in the
collection hierarchy.

How?
By setting the intitial field selection to the first
`admin.listDisabledColumn: false` field when clicking the Add Condition
button in the WhereBuilder and Condition components.

Fixes https://github.com/payloadcms/payload/issues/10110
2024-12-30 16:44:20 -05:00
Violet Rosenzweig
16c6abeee4 fix(graphql): Change config from raw path to file: url (#9311)
### What?

On windows, the `payload-graphql generate:schema` command fails.

### Why?

Because the config it's trying to load is `c:\path\to\config.js`, which
node interprets as `\path\to\config.js` on the `c:` protocol.

### How?

By changing it to use a file URL, as in `file:\\\c:\path\to\config.js`.
The change is the same as what the main `payload` cli does:
https://github.com/payloadcms/payload/blob/main/packages/payload/src/bin/index.ts#L54

Fixes #9309

Co-authored-by: Violet Rosenzweig <rosenzweigv@leoncountyfl.gov>
2024-12-30 16:43:58 -05:00
James Mikrut
5d6064a419 fix(translations): adds missing max validations keys to client (#10266)
Fixes #9836
2024-12-30 16:13:06 -05:00
Anders Semb Hermansen
eb69885a89 fix: close db connections after running jobs from command line. (#9994)
### What?

Exit process after `payload jobs:run` without cron is executed

### Why?

I would expect the `payload jobs:run` command to exit normally after
execution. With mongodb this is not the case as database connections are
open so the node process itself will not exit.

### How?

Execute `payload.db.destroy` to close all db connections after queue is
execution is done.

Fixes: #9851
2024-12-30 15:03:29 -05:00
James Mikrut
8671e856ed fix(ui): removes useless verified checkbox on user create (#10252)
Removes the useless `_verified` checkbox from user creation. We can't
make it functional from the admin UI, because if we respected the
incoming `_verified` property from a user creation, then any user could
auto-verify themselves via REST / GraphQL APIs.

Fixes #10158
2024-12-30 19:58:01 +00:00
James Mikrut
ef7242cd85 fix(ui): autosave wasnt firing on first change (#10256)
Fixes #10111
2024-12-30 17:04:17 +00:00
Alessio Gravili
c01b4bfb79 fix(richtext-lexical): ensure markdown normalization does not merge escaped code block lines (#10230) 2024-12-30 01:52:12 +00:00
Elliot DeNolf
2111a860f7 chore(cpa): remove success message outline (#10233)
The usage of clack's `note` on the success message (contains long urls)
would often wrap on terminals that did not have a very wide window
and/or do not support [terminal
hyperlinks](https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda)

This swaps the usage of `note` for more plain log output that does not
have an outline and eliminates the possibility for this issue.

Before:
<img width="726" alt="CleanShot 2024-12-29 at 02 54 18"
src="https://github.com/user-attachments/assets/4fcb028c-58f0-4102-9268-53aca8124111"
/>


After:
<img width="716" alt="CleanShot 2024-12-29 at 02 54 39"
src="https://github.com/user-attachments/assets/30615fa8-5f2c-43f5-a6a5-9f0b9cc415fb"
/>
2024-12-29 07:52:28 -05:00
Alessio Gravili
68a5f5ca2f feat(ui): expose onMount to CodeField (#10223)
This is useful for modifying the monaco instance, e.g. to add external
types to the editor:

```tsx
<CodeField
        autoComplete={autoComplete}
        field={props}
        forceRender={forceRender}
        key={key}
        onMount={(editor, monaco) => {
          console.log('editor mounted')
          monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
            allowNonTsExtensions: true,
            moduleResolution: monaco.languages.typescript.ModuleResolutionKind.NodeJs,
            paths: {
              payload: ['file:///node_modules/payload/index.d.ts'],
            },
            target: monaco.languages.typescript.ScriptTarget.ESNext,
            typeRoots: ['node_modules/@types', 'node_modules/payload'],
          })
          const run = async () => {
            const types = await fetch('https://unpkg.com/payload@latest/dist/index.d.ts')
            const typesText = await types.text()
            monaco.languages.typescript.typescriptDefaults.addExtraLib(
              typesText,
              'file:///node_modules/payload/index.d.ts',
            )
          }
          void run()
        }}
        path={path}
        permissions={permissions}
        readOnly={readOnly}
        renderedBlocks={renderedBlocks}
        schemaPath={schemaPath}
        validate={validate}
      />
```
2024-12-28 19:09:51 +00:00
Elliot DeNolf
fabe5411f4 chore(release): v3.12.0 [skip ci] 2024-12-28 12:02:39 -05:00
Alessio Gravili
67db04c660 fix(richtext-lexical): newlines in mdx props were stripped, even though objects inside props may expect there to be newlines (#10215) 2024-12-28 04:53:44 +00:00
Alessio Gravili
181fc410bf feat(richtext-lexical): multiline string support for objects in MDX parser (#10208) 2024-12-27 23:14:55 +00:00
James Mikrut
37d1f2d04b feat: scheduled publish / unpublish (#10203)
Adds a feature to allow editors to schedule publish / unpublish events
in the future. Must be enabled by setting
`versions.drafts.schedulePublish: true` in your Collection / Global
configs.


https://github.com/user-attachments/assets/ca1d7a8b-946a-4eac-b911-c2177dbe3b1c

Todo:

- [x] Translate new i18n keys
- [x] Wire up locale-specific scheduled publish / unpublish actions
2024-12-27 16:52:18 -05:00
Alessio Gravili
a46609ef6b feat(richtext-lexical): more lenient MDX JSON object parser that allows unquoted property keys (#10205)
Previously, the following MDX could not be parsed by lexical:

```tsx
<RestExamples
  data={[
    {
      operation: "Find"
    }
]}
```

Instead, it had to be converted into valid JSON:

```tsx
<RestExamples
  data={[
    {
      "operation": "Find"
    }
]}
```

This PR permits using the first example, as it swaps out JSON.parse with
them ore lenient [json5](https://www.npmjs.com/package/json5) package
parser
2024-12-27 21:41:15 +00:00
James Mikrut
cf8c0ae959 feat: adds req to filterOptions args (#10204)
Adds `req` to `filterOptions` arguments.
2024-12-27 21:38:14 +00:00
Jacob Fletcher
fad4ee6282 fix(ui): pagination resets perPage (#10199)
When using various controls within the List View, those selections are
sometimes not persisted. This is especially evident when selecting
`perPage` from the List View, where the URL and UI would reflect this
selection, but the controls would be stale. Similarly, after changing
`perPage` then navigating to another page through the pagination
controls, `perPage` would reset back to the original value. Same with
the sort controls, where sorting by a particular column would not be
reflected in the UI. This was because although we modify the URL search
params and fire off a new query with those changes, we were not updating
local component state.
2024-12-27 19:32:36 +00:00
Sasha
6b4842d44d feat(cpa): create project from example using --example CLI arg (#10172)
Adds the ability to create a project using an existing in the Payload
repo example through `create-payload-app`:

For example:
`pnpx create-payload-app --example custom-server` - creates a project
from the
[custom-server](https://github.com/payloadcms/payload/tree/main/examples/custom-server)
example.

This is much easier and faster then downloading the whole repo and
copying the example to another folder.
Note that we don't configure the payload config with the storage / DB
adapter there because examples can be very specific.
2024-12-27 20:16:34 +02:00
Elliot DeNolf
7e0975f970 feat: export defaultLoggerOptions (#10133)
Make `defaultLoggerOptions` available. Useful if you need to only tweak
the defaults for your logger.
2024-12-27 10:57:34 -05:00
Sasha
98666eb016 perf(db-postgres): do not push database schema if not changed (#10155)
Based on https://github.com/payloadcms/payload/pull/10154

If the actual database schema is not changed (no new columns, enums,
indexes, tables) - skip calling Drizzle push. This, potentially can
significantly reduce overhead on reloads in development mode especially
when using remote databases.

If for whatever reason you need to preserve the current behavior you can
use `PAYLOAD_FORCE_DRIZZLE_PUSH=true` env flag.
2024-12-27 10:12:01 -05:00
Sasha
374b79d218 fix(db-postgres): prevent indexes from changing name on HMR (#10154)
As we didn't reset our `adapter.indexes` state, on every HMR reload we
incremented every single index name with the `buildIndexName`:

466f109152/packages/drizzle/src/utilities/buildIndexName.ts (L3-L24)

I found this while debugging our internal SQL schema:

Before reload:

```ts
 "payload_preferences": {
    "name": "payload_preferences",
    "columns": {
      "id": {
        "name": "id",
        "type": "serial",
        "primaryKey": true
      },
      "key": {
        "name": "key",
        "type": "varchar"
      },
      "value": {
        "name": "value",
        "type": "jsonb"
      },
      "updatedAt": {
        "name": "updated_at",
        "type": "timestamp",
        "defaultNow": true,
        "mode": "string",
        "notNull": true,
        "precision": 3,
        "withTimezone": true
      },
      "createdAt": {
        "name": "created_at",
        "type": "timestamp",
        "defaultNow": true,
        "mode": "string",
        "notNull": true,
        "precision": 3,
        "withTimezone": true
      }
    },
    "foreignKeys": {},
    "indexes": {
      "payload_preferences_key_idx": {
        "name": "payload_preferences_key_idx",
        "on": "key"
      },
      "payload_preferences_updated_at_idx": {
        "name": "payload_preferences_updated_at_idx",
        "on": "updatedAt"
      },
      "payload_preferences_created_at_idx": {
        "name": "payload_preferences_created_at_idx",
        "on": "createdAt"
      }
    }
  },
```

After:
```ts

"payload_preferences": {
    "name": "payload_preferences",
    "columns": {
      "id": {
        "name": "id",
        "type": "serial",
        "primaryKey": true
      },
      "key": {
        "name": "key",
        "type": "varchar"
      },
      "value": {
        "name": "value",
        "type": "jsonb"
      },
      "updatedAt": {
        "name": "updated_at",
        "type": "timestamp",
        "defaultNow": true,
        "mode": "string",
        "notNull": true,
        "precision": 3,
        "withTimezone": true
      },
      "createdAt": {
        "name": "created_at",
        "type": "timestamp",
        "defaultNow": true,
        "mode": "string",
        "notNull": true,
        "precision": 3,
        "withTimezone": true
      }
    },
    "foreignKeys": {},
    "indexes": {
      "payload_preferences_key_1_idx": {
        "name": "payload_preferences_key_1_idx",
        "on": "key"
      },
      "payload_preferences_updated_at_1_idx": {
        "name": "payload_preferences_updated_at_1_idx",
        "on": "updatedAt"
      },
      "payload_preferences_created_at_1_idx": {
        "name": "payload_preferences_created_at_1_idx",
        "on": "createdAt"
      }
    }
  },
```
Which isn't really great for dev performance and can potentially cause
errors
2024-12-27 10:04:48 -05:00
Sasha
eff75f9613 fix: deep querying, handle getLocalizedPaths for blocks (#10187)
Fixes https://github.com/payloadcms/payload/issues/10126

Properly handles the `getLocalizedPaths` function for blocks.

Previously, using collection with this config:
```
{
  slug: 'deep-nested',
  fields: [
    {
      type: 'tabs',
      tabs: [
        {
          name: 'content',
          fields: [
            {
              type: 'blocks',
              name: 'blocks',
              blocks: [
                {
                  slug: 'testBlock',
                  fields: [
                    {
                      type: 'tabs',
                      tabs: [
                        {
                          name: 'meta',
                          fields: [
                            {
                              type: 'relationship',
                              relationTo: 'movies',
                              name: 'movie',
                            },
                          ],
                        },
                      ],
                    },
                  ],
                },
              ],
            },
          ],
        },
      ],
    },
  ],
},

```
The following query didn't work in MongoDB:
```ts
const result = await payload.find({
  collection: 'deep-nested',
  where: {
    'content.blocks.meta.movie': {
      equals: movie.id,
    },
  },
})
```
2024-12-27 09:46:09 -05:00