Skip to content

Commit

Permalink
Defaults example (keystonejs#5814)
Browse files Browse the repository at this point in the history
  • Loading branch information
timleslie authored May 28, 2021
1 parent 60326d9 commit 28ca49c
Show file tree
Hide file tree
Showing 13 changed files with 684 additions and 4 deletions.
5 changes: 5 additions & 0 deletions .changeset/ninety-pears-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@keystone-next/example-default-values': major
---

Initial version of the `default-values` example.
12 changes: 11 additions & 1 deletion .github/workflows/tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,17 @@ jobs:
DATABASE_URL: 'file:./test.db'
strategy:
matrix:
test: ['auth.test.ts', 'basic.test.ts', 'blog.test.ts', 'json.test.ts', 'roles.test.ts', 'task-manager.test.ts', 'with-auth.test.ts']
test:
[
'auth.test.ts',
'basic.test.ts',
'blog.test.ts',
'default-values.test.ts',
'json.test.ts',
'roles.test.ts',
'task-manager.test.ts',
'with-auth.test.ts',
]
fail-fast: false
steps:
- name: Checkout Repo
Expand Down
4 changes: 2 additions & 2 deletions examples/NEW-EXAMPLES.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ There are three types of example project:
### Feature Example steps

1. Decide which base project to use. This is up to you, and will depend on what feature you're trying to demonstrate and where it makes most contextual sense to add it.
2. Create a new project directory: `cd examples; cp -R todo <example-name>`.
2. Create a new project directory: `cd examples; cp -R task-manager <example-name>`.
3. Add to git; `git add <example-name>`
4. Edit `package.json` for the new project. You'll need to update `name`, set `version` to `0.0.0`, and edit the `repository` link.
5. Edit `CHANGELOG.md` for the new project. Clear out everything except the top level heading. Update top level heading to match the package name
6. Edit `README.md` for the new project. Document what you expect to be showing off here. This will help act as a spec. We will loop back to this once we’re done to make sure it makes sense, but writing it up front helps frame the work.
7. Make sure your base example runs. `cd <example-name>; yarn dev`.
8. Add a changeset with the initial major version of the example. `cd ../..; yarn changeset - major “Initial version of the <example-name> example”`
8. Add a changeset with the initial major version of the example. `cd ../..; yarn changeset - major “Initial version of the <example-name> example.`
9. [Draw the rest of the owl](https://knowyourmeme.com/memes/how-to-draw-an-owl). Write and test your example, making sure that it's clearly commented.
10. Add a smoke test to ensure your example is executed on CI.
11. Update the `examples/README.md` with a link to your new example.
Expand Down
1 change: 1 addition & 0 deletions examples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ You can use these projects to learn about, and experiment with specific features

- [`withAuth()`](./with-auth): Adding password based authentication to your Keystone application.
- [`JSON field`](./json): Using a JSON field in your Keystone application.
- [`defaultValue`](./default-values): Using `defaultValue` to set default values on fields in your data schema.

## Running examples

Expand Down
1 change: 1 addition & 0 deletions examples/default-values/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# @keystone-next/example-default-values
79 changes: 79 additions & 0 deletions examples/default-values/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
## Feature Example - Default Values

This project demonstrates how to use default values for fields.
It builds on the [Task Manager](../task-manager) starter project.

## Instructions

To run this project, clone the Keystone repository locally then navigate to this directory and run:

```shell
yarn 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.

## Features

This project demonstrates how to use default values for fields.
Default values are set using the [`defaultValue`](https://next.keystonejs.com/apis/fields#scalar-types) argument on fields.
They are applied by Keystone when an object is created and no value is supplied for the field.
There are two types of default values in Keystone; `static`, and `dynamic`.

### Static

`Static` default values are set using a fixed value as the `defaultValue` argument.
We use a static default to set the `isComplete` state to `false` when a new task is created.

```typescript
isComplete: checkbox({ defaultValue: false }),
```

### Dynamic

`Dynamic` default values are set using a function as `defaultValue` argument.
This function is evaluated when the item is created.
The function recieves two arguments, `originalInput` and `context`.

We use `originalInput`, which contains the input passed to the GraphQL create mutation, to set the priority of the task.

```typescript
priority: select({
dataType: 'enum',
options: [
{ label: 'Low', value: 'low' },
{ label: 'Medium', value: 'medium' },
{ label: 'High', value: 'high' },
],
// Dynamic default: Use the label field to determine the priority
defaultValue: ({ originalInput }) => {
if (originalInput.label && originalInput.label.toLowerCase().includes('urgent')) {
return 'high';
} else {
return 'low';
}
},
}),
```

We use [`context`](https://next.keystonejs.com/apis/context) along with the [list items API](https://next.keystonejs.com/apis/list-items) to set the default assignee of a task to be a user named `"Anonymous"`.

```typescript
assignedTo: relationship({
ref: 'Person.tasks',
many: false,
// Dynamic default: Find an anonymous user and assign the task to them
defaultValue: async ({ context }) => {
const anonymous = await context.lists.Person.findMany({
where: { name: 'Anonymous' },
});
if (anonymous.length > 0) {
return { connect: { id: anonymous[0].id } };
}
// If we don't have an anonymous user return undefined so as not to apply any default
},
}),
```
10 changes: 10 additions & 0 deletions examples/default-values/keystone.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import { config } from '@keystone-next/keystone/schema';
import { lists } from './schema';

export default config({
db: {
provider: 'sqlite',
url: process.env.DATABASE_URL || 'file:./keystone-example.db',
},
lists,
});
22 changes: 22 additions & 0 deletions examples/default-values/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "@keystone-next/example-default-values",
"version": "0.0.0",
"private": true,
"license": "MIT",
"scripts": {
"dev": "keystone-next dev",
"start": "keystone-next start",
"build": "keystone-next build"
},
"dependencies": {
"@keystone-next/fields": "^9.0.0",
"@keystone-next/keystone": "^18.0.0"
},
"devDependencies": {
"typescript": "^4.2.4"
},
"engines": {
"node": "^12.20 || >= 14.13"
},
"repository": "https://github.com/keystonejs/keystone/tree/master/examples/default-values"
}
Loading

0 comments on commit 28ca49c

Please sign in to comment.