Commit Graph

28 Commits

Author SHA1 Message Date
Said Akhrarov
cd546b3125 feat(ui): add support for disabling join field row types (#12738)
### What?
This PR adds a new `admin.disableRowTypes` config to `'join'` fields
which hides the `"Type"` column from the relationship table.

### Why?
While the collection type column _can be_ helpful for providing
information, it's not always necessary and can sometimes be redundant
when the field only has a singular relationTo. Hiding it can be helpful
by removing visual noise and providing editors the data directly.

### How?
By threading `admin.disableRowTypes` directly to the `getTableState`
function of the `RelationshipTable` component.

**With row types** (via `admin.disableRowTypes: false | undefined` OR
default for polymorphic):

![image](https://github.com/user-attachments/assets/22b55477-cf56-4b0e-a845-e6f2b39efe3b)

**Without row types** (default for monomorphic):

![image](https://github.com/user-attachments/assets/3a2bb0ba-2d5e-4299-8689-249b2d3fefe2)
2025-10-03 11:10:10 +01:00
Jacob Fletcher
61ee8fadca fix(ui): autosave-enabled document drawers close unexpectedly within the join field (#13298)
Fixes #12975.

When editing autosave-enabled documents through the join field, the
document drawer closes unexpectedly on every autosave interval, making
it nearly impossible to use.

This is because as of #12842, the underlying relationship table
re-renders on every autosave event, remounting the drawer each time. The
fix is to lift the drawer out of table's rendering tree and into the
join field itself. This way all rows share the same drawer, whose
rendering lifecycle has been completely decoupled from the table's
state.

Note: this is very similar to how relationship fields achieve similar
functionality.

This PR also adds jsdocs to the `useDocumentDrawer` hook and strengthens
its types.

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1210906078627353
2025-07-29 11:49:15 -04:00
Jarrod Flesch
19a3367972 fix(ui): monomorphic joins tables not fetching draft documents (#13139)
Monomorphic join fields were not using the `draft` argument when
fetching documents to display in the table. This change makes the join
field treatment of drafts consistent with the `relationship` type
fields.

Added e2e test to cover.
2025-07-11 14:26:48 +00: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
Sasha
2b40e0f21f feat: polymorphic join querying by fields that don't exist in every collection (#12648)
This PR makes it possible to do polymorphic join querying by fields that
don't exist in all collections specified in `field.collection`, for
example:
```
const result = await payload.find({
  collection: 'payload-folders',
  joins: {
    documentsAndFolders: {
      where: {
        and: [
          {
            relationTo: {
              in: ['folderPoly1', 'folderPoly2'],
            },
          },
          {
            folderPoly2Title: { // this field exists only in the folderPoly2 collection, before it'd throw a query error.
              equals: 'Poly 2 Title',
            },
          },
        ],
      },
    },
  },
})
```

---------

Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
2025-06-03 00:48:07 +03:00
Sasha
7aa3c5ea6b fix: cannot define a join field when the target relationship is nested to a second or higher tab (#12041)
Fixes https://github.com/payloadcms/payload/issues/11720
2025-04-10 15:36:03 +03:00
Sasha
e5690fcab9 fix(graphql): respect draft: true when querying joins (#11869)
The same as https://github.com/payloadcms/payload/pull/11763 but also
for GraphQL. The previous fix was working only for the Local API and
REST API due to a different method for querying joins in GraphQL.
2025-04-01 14:41:47 -04:00
Said Akhrarov
077fb3ab30 fix(ui): respect locale in buildTableState (#11147)
### What?
This PR fixes an issue where the `join` field table was not respecting
the locale selected in the admin ui localizer.

This also introduces an e2e test to the existing suite to catch this
issue.

### Why?
To properly render `join` field table data according to chosen and
configured locales.

### How?
Threading `req.locale` through to the `payload.find` call in
`buildTableState`.

Fixes #11134

Before:

[Editing---Category--join-locales-before-Payload.webm](https://github.com/user-attachments/assets/d77b71bb-f849-4be2-aa96-26dbfedb52d4)

After:

[Editing---Category--join-locales-after-Payload.webm](https://github.com/user-attachments/assets/0d1f7351-adf4-4bad-ac82-0fee67f8b66a)
2025-02-14 12:23:49 -05:00
Dan Ribbens
dd28959916 fix: join field does not show validation error (#11170)
### What?

Assuming you have a hook in your collection that is looking for certain
conditions to be met related to the join field. The way you would
prevent it is to throw a `new ValidationError()` with errors containing
the path of the field. Previously, the error message for the field would
not show in the admin UI at all.

### Why?

Users need to be able to see any custom error messages for joins field
in the UI so they can address the issue.

### How?

Adds an error class and display the FieldError in the Join field in the
UI component.
2025-02-13 23:09:04 -05:00
Sasha
2f66bdc2dc fix(ui): create-first-user crashes when users collection has join field (#10871)
Fixes https://github.com/payloadcms/payload/issues/10870
Now we hide join fields from the `/create-first-user` view since they're
not meaningful there.
2025-01-29 19:52:22 +02:00
Sasha
25a70ab455 fix: join field with the target relationship inside localized array (#10621)
Fixes https://github.com/payloadcms/payload/issues/10356
2025-01-21 02:18:26 +02:00
Sasha
a0d8131649 fix(db-postgres): joins to self collection (#10182)
### What?
With Postgres, before join to self like:
```ts
import type { CollectionConfig } from 'payload'

export const SelfJoins: CollectionConfig = {
  slug: 'self-joins',
  fields: [
    {
      name: 'rel',
      type: 'relationship',
      relationTo: 'self-joins',
    },
    {
      name: 'joins',
      type: 'join',
      on: 'rel',
      collection: 'self-joins',
    },
  ],
}
```
wasn't possible, even though it's a valid usage.

### How?
Now, to differentiate parent `self_joins` and children `self_joins` we
do additional alias for the nested select -
`"4d3cf2b6_1adf_46a8_b6d2_3e1c3809d737"`:
```sql
select 
  "id", 
  "rel_id", 
  "updated_at", 
  "created_at", 
  (
    select 
      coalesce(
        json_agg(
          json_build_object('id', "joins_alias".id)
        ), 
        '[]' :: json
      ) 
    from 
      (
        select 
          "created_at", 
          "rel_id", 
          "id" 
        from 
          "self_joins" "4d3cf2b6_1adf_46a8_b6d2_3e1c3809d737" 
        where 
          "4d3cf2b6_1adf_46a8_b6d2_3e1c3809d737"."rel_id" = "self_joins"."id" 
        order by 
          "4d3cf2b6_1adf_46a8_b6d2_3e1c3809d737"."created_at" desc 
        limit 
          $1
      ) "joins_alias"
  ) as "joins_alias" 
from 
  "self_joins" 
where 
  "self_joins"."id" = $2 
order by 
  "self_joins"."created_at" desc 
limit 
  $3

```

Fixes https://github.com/payloadcms/payload/issues/10144

-->
2024-12-26 20:47:49 +02:00
Dan Ribbens
d03658de01 feat: join field with polymorphic relationships (#9990)
### What?
The join field had a limitation imposed that prevents it from targeting
polymorphic relationship fields. With this change we can support any
relationship fields.

### Why?
Improves the functionality of join field.

### How?
Extended the database adapters and removed the config sanitization that
would throw an error when polymorphic relationships were used.

Fixes #
2024-12-19 22:34:52 +00:00
Sasha
1d46b6d738 fix(ui): join field "add new" calculate initial drawer data with relationship inside blocks (#10057)
We merged https://github.com/payloadcms/payload/pull/9773 that adds
support for join field with relationships inside arrays, it just happens
that now it's also true for relationships inside blocks, added a test
case with blocks.
This just corrects initial data drawer calculation with the "add new"
button if we encounter a blocks field in join's `on`.
2024-12-19 08:45:22 +02:00
Dan Ribbens
b0b2fc6c47 feat: join field support relationships inside arrays (#9773)
### What?

Allow the join field to have a configuration `on` relationships inside
of an array, ie `on: 'myArray.myRelationship'`.

### Why?

This is a more powerful and expressive way to use the join field and not
be limited by usage of array data. For example, if you have a roles
array for multinant sites, you could add a join field on the sites to
show who the admins are.

### How?

This fixes the traverseFields function to allow the configuration to
pass sanitization. In addition, the function for querying the drizzle
tables needed to be ehanced.

Additional changes from https://github.com/payloadcms/payload/pull/9995:

- Significantly improves traverseFields and the 'join' case with a raw
query injection pattern, right now it's internal but we could expose it
at some point, for example for querying vectors.
- Fixes potential issues with not passed locale to traverseFields (it
was undefined always)
- Adds an empty array fallback for joins with localized relationships

Fixes #
https://github.com/payloadcms/payload/discussions/9643

---------

Co-authored-by: Because789 <thomas@because789.ch>
Co-authored-by: Sasha <64744993+r1tsuu@users.noreply.github.com>
2024-12-17 13:14:43 -05:00
Dan Ribbens
2ec4d0c2ef feat: join field admin.defaultColumns (#9982)
Add the ability to specify which columns should appear in the
relationship table of a join fields

The new property is in the Join field `admin.defaultColumns` and can be
set to an array of strings containing the field names in the desired
order.
2024-12-15 03:31:31 +00:00
Dan Ribbens
67179a7fb8 fix: join field description, custom components and loading state (#9703)
- [fix: join field shows loading when creating a
document](9f7a2e7936)
- [fix: join field
descriptions](90e8cdb464)
- [feat(ui): adds before & after inputs to join
field](19d43329ad)

---------

Co-authored-by: Patrik <patrik@payloadcms.com>
2024-12-03 15:58:42 -05:00
Jacob Fletcher
5d18a5288e fix: overrides entity visibility within drawers (#9546)
When using the `admin.hidden: true` property on a collection, it
rightfully removes all navigation and routing for that particular
collection. However, this also affects the expected behavior of hidden
entities when they are rendered within a drawer, such as the document
drawer or list drawer. For example, when creating a new _admin.hidden_
document through the relationship or join field, the drawer should still
render the view, despite the underlying route for that view being
disabled. This change was a result of the introduction of on-demand
server components in #8364, where we now make a server roundtrip to
render the view in its entirety, which include the logic that redirects
these hidden entities.

Now, we pass a new `overrideEntityVisibility` argument through the
server function that, when true, skips this step. This way documents can
continue to respect `admin.hidden` while also having the ability to
override on a case-by-case basis throughout the UI.
2024-11-26 18:22:04 -05:00
Sasha
d499de1e0f fix(db-postgres): joins with versions and hasMany relationship (#9370)
Fixes errors when having joins with versions +drafts on `hasMany: true`
relationships.
Removes `joinQuery` overhead if we don't need it for the current
operation. Right now, in all adapters we support joins only for `find`,
`findOne`, and `queryDrafts`.


Fixes https://github.com/payloadcms/payload/issues/9369
2024-11-21 10:42:05 -05:00
Dan Ribbens
93a55d1075 feat: add join field config where property (#8973)
### What?

Makes it possible to filter join documents using a `where` added
directly in the config.


### Why?

It makes the join field more powerful for adding contextual meaning to
the documents being returned. For example, maybe you have a
`requiresAction` field that you set and you can have a join that
automatically filters the documents to those that need attention.

### How?

In the database adapter, we merge the requested `where` to the `where`
defined on the field.
On the frontend the results are filtered using the `filterOptions`
property in the component.

Fixes
https://github.com/payloadcms/payload/discussions/8936
https://github.com/payloadcms/payload/discussions/8937

---------

Co-authored-by: Sasha <64744993+r1tsuu@users.noreply.github.com>
2024-11-06 10:06:25 -05:00
Sasha
f4041ce6e2 fix(db-mongodb): joins with singular collection name (#8933)
### What?
Properly specifies `$lookup.from` when the collection name is singular.

### Why?
MongoDB can pluralize the collection name and so can be different for
singular ones.

### How?
Uses the collection name from the driver directly
`adapter.collections[slug].collection.name` instead of just `slug`.
2024-10-30 12:06:03 -04:00
Dan Ribbens
f0edbb79f9 feat: join field defaultLimit and defaultSort (#8908)
### What?

Allow specifying the defaultSort and defaultLimit to use for populating
a join field

### Why?

It is much easier to set defaults rather than be forced to always call
the join query using the query pattern ("?joins[categories][limit]=0").

### How?

See docs and type changes
2024-10-28 17:52:37 -04:00
Sasha
8af00f2deb fix: join field works on collections with versions enabled (#8715)
- Fixes errors with drizzle when building the schema
https://github.com/payloadcms/payload/issues/8680
- Adds `joins` to `db.queryDrafts` to have them when doing `.find` with
`draft: true`
2024-10-22 11:05:55 -04:00
Sasha
f6acfdb1f5 fix(drizzle): hasMany joins - localized, limit and schema paths (#8633)
Fixes https://github.com/payloadcms/payload/issues/8630

- Fixes `hasMany: true` and `localized: true` on the foreign field
- Adds `limit` to the subquery instead of hardcoded `11`.
- Adds the schema path `field.on` to the subquery, without this having 2
or more relationship fields to the same collection breaks joins
- Properly checks if the field is `hasMany`
2024-10-10 12:58:30 -04:00
Dan Ribbens
1bf580fac3 feat: join field works with hasMany relationships (#8493)
Join field works on relationships and uploads having `hasMany: true`

---------

Co-authored-by: Sasha <64744993+r1tsuu@users.noreply.github.com>
2024-10-08 11:40:34 -04:00
Dan Ribbens
27b1629927 fix(db-postgres, db-sqlite): joins relation name (#8491)
A join field on a relationship with a camelCase name would cause an
error from drizzle due to the relation name not matching.
2024-09-30 16:47:21 -04:00
Dan Ribbens
3f375cc6ee feat: join field on upload fields (#8379)
This PR makes it possible to use the new `join` field in connection with
an `upload` field. Previously `join` was reserved only for
relationships.
2024-09-30 13:12:30 -04:00
Dan Ribbens
6ef2bdea15 feat!: join field (#7518)
## Description

- Adds a new "join" field type to Payload and is supported by all database adapters
- The UI uses a table view for the new field
- `db-mongodb` changes relationships to be stored as ObjectIDs instead of strings (for now querying works using both types internally to the DB so no data migration should be necessary unless you're querying directly, see breaking changes for details
- Adds a reusable traverseFields utility to Payload to make it easier to work with nested fields, used internally and for plugin maintainers

```ts
export const Categories: CollectionConfig = {
    slug: 'categories',
    fields: [
        {
            name: 'relatedPosts',
            type: 'join',
            collection: 'posts',
            on: 'category',
        }
    ]
}
```

BREAKING CHANGES:
All mongodb relationship and upload values will be stored as MongoDB ObjectIDs instead of strings going forward. If you have existing data and you are querying data directly, outside of Payload's APIs, you get different results. For example, a `contains` query will no longer works given a partial ID of a relationship since the ObjectID requires the whole identifier to work. 

---------

Co-authored-by: Jacob Fletcher <jacobsfletch@gmail.com>
Co-authored-by: James <james@trbl.design>
2024-09-20 11:10:16 -04:00