Skip to content

Commit

Permalink
Fix search filters and add support to search by relationships in the …
Browse files Browse the repository at this point in the history
…list view (#9401)

Co-authored-by: pnodet <[email protected]>
  • Loading branch information
dcousens and pnodet authored Nov 19, 2024
1 parent 147f2a3 commit 48f51be
Show file tree
Hide file tree
Showing 81 changed files with 1,173 additions and 522 deletions.
5 changes: 5 additions & 0 deletions .changeset/add-relationship-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@keystone-6/core": minor
---

Add support for searching relationship fields in the list view
5 changes: 5 additions & 0 deletions .changeset/fix-search.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@keystone-6/core": patch
---

Fix list view ignoring `.ui.listView.searchFields`
1 change: 1 addition & 0 deletions design-system/packages/fields/src/Select.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,7 @@ export function MultiSelect ({
inputId={id}
styles={composedStyles}
value={value}
filterOption={null}
onChange={value => {
if (!value) {
onChange([])
Expand Down
8 changes: 4 additions & 4 deletions docs/content/docs/config/lists.md
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ Options:

- `labelField`: Selects the field which will be used as the label column in the Admin UI.
By default looks for a field called `'label'`, then falls back to `'name'`, then `'title'`, and finally `'id'`, which is guaranteed to exist.
- `searchFields`: The fields used by the Admin UI when searching this list on the list view and in relationship fields.
- `searchFields`: The fields used by the Admin UI when searching this list on the list view and in relationship fields. Nominated fields need to support the `contains` filter.
It is always possible to search by an id and `'id'` should not be specified in this option.
By default, the `labelField` is used if it has a string `contains` filter, otherwise none.
- `description` (default: `undefined`): Sets the list description displayed in the Admin UI.
Expand All @@ -89,17 +89,17 @@ Options:
Can be either a boolean value or an async function with an argument `{ session, context }` that returns a boolean value.
- `createView`: Controls the create view page of the Admin UI.
- `defaultFieldMode` (default: `'edit'`):
Can be overridden by per-field values in the `field.ui.createView.fieldMode` config.
Can be overridden by per-field values in the `ui.createView.fieldMode` config.
See the [Fields API](../fields/overview#common-configuration) for details.
Can be one of `['edit', 'hidden']`, or an async function with an argument `{ session, context }` that returns one of `['edit', 'hidden']`.
- `itemView`: Controls the item view page of the Admin UI.
- `defaultFieldMode` (default: `'edit'`):
Can be overridden by per-field values in the `field.ui.itemView.fieldMode` config.
Can be overridden by per-field values in the `ui.itemView.fieldMode` config.
See the [Fields API](../fields/overview#common-configuration) for details.
Can be one of `['edit', 'read', 'hidden']`, or an async function with an argument `{ session, context, item }` that returns one of `['edit', 'read', 'hidden']`.
- `listView`: Controls the list view page of the Admin UI.
- `defaultFieldMode` (default: `'read'`): Controls the default mode of fields in the list view.
Can be overridden by per-field values in the `field.ui.listView.fieldMode` config.
Can be overridden by per-field values in the `ui.listView.fieldMode` config.
See the [Fields API](../fields/overview#common-configuration) for details.
Can be one of `['read', 'hidden']`, or an async function with an argument `{ session, context }` that returns one of `['read', 'hidden']`.
- `initialColumns` (default: The first three fields defined in the list). A list of field names to display in columns in the list view. By default only the label column, as determined by `labelField`, is shown.
Expand Down
8 changes: 4 additions & 4 deletions docs/content/docs/fields/relationship.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ Read our [relationships guide](../guides/relationships) for details on Keystone
- `ui` (default: `{ hideCreate: false, displayMode: 'select' }`): Configures the display mode of the field in the Admin UI.
- `hideCreate` (default: `false`). If `true`, the "Create related item" button is not shown in the item view.
- `displayMode` (default: `'select'`): Controls the mode used to display the field in the item view. The mode `'select'` displays related items in a select component, while `'cards'` displays the related items in a card layout. Each display mode supports further configuration.
- `ui.displayMode === 'select'` options:
- `displayMode === 'select'` options:
- `labelField`: The field path from the related list to use for item labels in the select. Defaults to the `labelField` configured on the related list.
- `searchFields`: The fields used by the UI to search for this item, in context of this relationship field. Defaults to `searchFields` configured on the related list.
- `ui.displayMode === 'cards'` options:
- `searchFields`: The fields used by the Admin UI when searching by this relationship on the list view and in relationship fields. Nominated fields need to support the `contains` filter.
- `displayMode === 'cards'` options:
- `cardFields`: A list of field paths from the related list to render in the card component. Defaults to `'id'` and the `labelField` configured on the related list.
- `linkToItem` (default `false`): If `true`, the default card component will render as a link to navigate to the related item.
- `removeMode` (default: `'disconnect'`): Controls whether the `Remove` button is present in the card. If `'disconnect'`, the button will be present. If `'none'`, the button will not be present.
Expand All @@ -27,7 +27,7 @@ Read our [relationships guide](../guides/relationships) for details on Keystone
Alternatively this can be an object with the properties:
- `labelField`: The field path from the related list to use for item labels in select. Defaults to the `labelField` configured on the related list.
- `searchFields`: The fields used by the UI to search for this item, in context of this relationship field. Defaults to `searchFields` configured on the related list.
- `ui.displayMode === 'count'` only supports `many` relationships
- `displayMode === 'count'` only supports `many` relationships

```typescript
import { config, list } from '@keystone-6/core';
Expand Down
13 changes: 7 additions & 6 deletions examples/assets-local/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -156,24 +156,25 @@ type KeystoneAdminMeta {

type KeystoneAdminUIListMeta {
key: String!
itemQueryName: String!
listQueryName: String!
hideCreate: Boolean!
hideDelete: Boolean!
path: String!
label: String!
singular: String!
plural: String!
description: String
initialColumns: [String!]!
pageSize: Int!
labelField: String!
fields: [KeystoneAdminUIFieldMeta!]!
groups: [KeystoneAdminUIFieldGroupMeta!]!
graphql: KeystoneAdminUIGraphQL!
initialColumns: [String!]!
initialSearchFields: [String!]!
initialSort: KeystoneAdminUISort
isHidden: Boolean!
isSingleton: Boolean!
hideCreate: Boolean!
hideDelete: Boolean!
isHidden: Boolean!
itemQueryName: String!
listQueryName: String!
}

type KeystoneAdminUIFieldMeta {
Expand Down
13 changes: 7 additions & 6 deletions examples/assets-s3/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -156,24 +156,25 @@ type KeystoneAdminMeta {

type KeystoneAdminUIListMeta {
key: String!
itemQueryName: String!
listQueryName: String!
hideCreate: Boolean!
hideDelete: Boolean!
path: String!
label: String!
singular: String!
plural: String!
description: String
initialColumns: [String!]!
pageSize: Int!
labelField: String!
fields: [KeystoneAdminUIFieldMeta!]!
groups: [KeystoneAdminUIFieldGroupMeta!]!
graphql: KeystoneAdminUIGraphQL!
initialColumns: [String!]!
initialSearchFields: [String!]!
initialSort: KeystoneAdminUISort
isHidden: Boolean!
isSingleton: Boolean!
hideCreate: Boolean!
hideDelete: Boolean!
isHidden: Boolean!
itemQueryName: String!
listQueryName: String!
}

type KeystoneAdminUIFieldMeta {
Expand Down
13 changes: 7 additions & 6 deletions examples/auth/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -121,24 +121,25 @@ type KeystoneAdminMeta {

type KeystoneAdminUIListMeta {
key: String!
itemQueryName: String!
listQueryName: String!
hideCreate: Boolean!
hideDelete: Boolean!
path: String!
label: String!
singular: String!
plural: String!
description: String
initialColumns: [String!]!
pageSize: Int!
labelField: String!
fields: [KeystoneAdminUIFieldMeta!]!
groups: [KeystoneAdminUIFieldGroupMeta!]!
graphql: KeystoneAdminUIGraphQL!
initialColumns: [String!]!
initialSearchFields: [String!]!
initialSort: KeystoneAdminUISort
isHidden: Boolean!
isSingleton: Boolean!
hideCreate: Boolean!
hideDelete: Boolean!
isHidden: Boolean!
itemQueryName: String!
listQueryName: String!
}

type KeystoneAdminUIFieldMeta {
Expand Down
32 changes: 32 additions & 0 deletions examples/better-list-search/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
## Base Project - Blog

This project implements a basic **Blog**, with `Posts` and `Authors`.

Use it as a starting place for learning how to use Keystone.

## Instructions

To run this project, clone the Keystone repository locally, run `pnpm install` at the root of this repository, then navigate to this directory and run:

```shell
pnpm dev
```

This will start the Admin UI at [localhost:3000](http://localhost:3000).
You can use the Admin UI to create items in your database.

You can also access a GraphQL Playground at [localhost:3000/api/graphql](http://localhost:3000/api/graphql), which allows you to directly run GraphQL queries and mutations.

Congratulations, you're now up and running with Keystone! 🚀

### Optional: add sample data

This example includes sample data. To add it to your database:

1. Ensure you’ve initialised your project with `pnpm dev` at least once.
2. Run `pnpm seed-data`. This will populate your database with sample content.
3. Run `pnpm dev` again to startup Admin UI with sample data in place.

## Try it out in CodeSandbox 🧪

You can play with this example online in a web browser using the free [codesandbox.io](https://codesandbox.io/) service. To launch this example, open the URL <https://githubbox.com/keystonejs/keystone/tree/main/examples/usecase-blog>. You can also fork this sandbox to make your own changes.
14 changes: 14 additions & 0 deletions examples/better-list-search/keystone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { config } from '@keystone-6/core'
import { lists } from './schema'
import type { TypeInfo } from '.keystone/types'

export default config<TypeInfo>({
db: {
provider: 'sqlite',
url: process.env.DATABASE_URL || 'file:./keystone-example.db',

// WARNING: this is only needed for our monorepo examples, dont do this
prismaClientPath: 'node_modules/myprisma',
},
lists,
})
23 changes: 23 additions & 0 deletions examples/better-list-search/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"name": "@keystone-6/example-better-list-search",
"version": null,
"private": true,
"license": "MIT",
"scripts": {
"dev": "keystone dev",
"start": "keystone start",
"build": "keystone build",
"postinstall": "keystone postinstall",
"seed-data": "tsx seed-data.ts"
},
"dependencies": {
"@keystone-6/core": "^6.3.1",
"@keystone-6/fields-document": "^9.1.1",
"@prisma/client": "5.19.0"
},
"devDependencies": {
"prisma": "5.19.0",
"tsx": "^4.0.0",
"typescript": "^5.5.0"
}
}
7 changes: 7 additions & 0 deletions examples/better-list-search/sandbox.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"template": "node",
"container": {
"startScript": "keystone dev",
"node": "20"
}
}
Loading

0 comments on commit 48f51be

Please sign in to comment.