Skip to content

Commit

Permalink
feat: Separate resource fragments (#53)
Browse files Browse the repository at this point in the history
fixes #40
  • Loading branch information
sMteX committed Feb 15, 2021
1 parent c8fd1ea commit 564fc6f
Show file tree
Hide file tree
Showing 4 changed files with 409 additions and 24 deletions.
110 changes: 90 additions & 20 deletions packages/dataprovider/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ Data provider for [react admin](https://github.com/marmelab/react-admin)

`yarn add @ra-data-prisma/dataprovider`

make sure you backend api is compatible by using the other package in this repo [backend](../backend/README.md)
Make sure your backend API is compatible by using the other package in this repo [backend](../backend/README.md)

Add the dataprovider to your react-admin app:

```
```jsx
import React, { Component } from "react"

import { Admin, Resource, Datagrid, TextField, Login } from "react-admin"
Expand Down Expand Up @@ -48,7 +47,6 @@ const AdminApp = () => {
}

export default AdminApp
```

## Features
Expand All @@ -69,7 +67,7 @@ this dataprovider supports all filtering and searching and adds some convenience
- available comparisons (default comparison is the one which would be used if omitted):
- ints, floats and datetimes - `gt`, `gte`, `lt`, `lte`, `equals` (default = `equals`)
- strings - `gt`, `gte`, `lt`, `lte`, `equals`, `contains`, `startsWith`, `endsWith` (default = `contains`)
- _case insensitive_: prisma currently does not support case insensitive queries ([but its on the way](https://github.com/prisma/prisma-client-js/issues/690)), so we currently emulate it query for multiple variations of the search term: as-is, fully lowercase, first letter uppercase. This does work in many cases (searching for terms and names), it fails in some. When prisma supports case insensitive querying, we will adopt that
- _case insensitive_: If your Prisma version supports it (>= 2.8.0), we automatically query strings as case insensitive. If your Prisma version doesn't support it, we emulate it with query for multiple variations of the search term: as-is, fully lowercase, first letter uppercase. This does work in many cases (searching for terms and names), but fails in some.
- _q_ query. `q` is a convention in react-admin for general search. We implement this client side. A query on `q` will search all string fields and int fields on a resource. It additionaly splits multiple search terms and does an AND search
- if you need more sophisticated search, you can use normal nexus-prisma graphql queries. You can even mix it with `q` and the intelligent short notation
Expand All @@ -81,15 +79,13 @@ If you have relations, you can use `ReferenceArrayField/Input` or `Referenceinpu
_show a list of cities with the country_
```
```jsx
export const CityList = (props) => (
<List {...props}>
<Datagrid>
<TextField source="id" />
<TextField source="name" />
<TextField source="name" />
<ReferenceField
label="Country"
source="country"
reference="Country"
Expand All @@ -105,8 +101,7 @@ export const CityList = (props) => (
_show all user roles in the user list_
```
```jsx
export const UserList = (props) => (
<List {...props} >
<Datagrid>
Expand All @@ -130,7 +125,7 @@ export const UserList = (props) => (
_edit the roles for a user_
```
```jsx
export const UserEdit = (props) => (
<Edit title={<UserTitle />} {...props} undoable={false}>
<SimpleForm variant="outlined">
Expand All @@ -152,19 +147,19 @@ export const UserEdit = (props) => (
### Virtual Resources / Views (_experimental_)
Lists currently load all fields on a certain type, but linked resources get sanitized to just load the id.
Lists currently load all fields on a certain type, but linked resources get sanitized to **just load the id**.
But sometimes you need to load specific nested fields from a certain resource, for example for an export.
Unfortunatly, react-admin has no mechanism to describe what to fetch exactly (see also https://github.com/marmelab/react-admin/issues/4751)
To fix this, you can specify a `ResourceView` to do that:
```
```ts
// real world example
buildGraphQLProvider({
clientOptions: { uri: "/api/graphql" } as any,
resourceViews: {
AllParticipantsToInvoice: {
ParticipantsToInvoice: {
resource: "ChallengeParticipation",
fragment: gql`
fragment Billing on ChallengeParticipation {
Expand Down Expand Up @@ -196,11 +191,86 @@ buildGraphQLProvider({
},
},
})
```

Now you have a new virtual resource `AllParticipantsToInvoice` that can be used to display a List. (notice: update/create/delete is currently not specified, so use it read-only ).

it will have exactly this data.
You can also have separate fragments for "one" record and for "many" records (e.g. different views for detail of a resource and for their list):
```ts
// real world example
buildGraphQLProvider({
clientOptions: { uri: "/api/graphql" } as any,
resourceViews: {
ParticipantsToInvoice: {
resource: "ChallengeParticipation",
fragment: {
one: gql`
fragment OneBilling on ChallengeParticipation {
challenge {
title
}
user {
email
firstname
lastname
school {
name
address
city {
name
zipCode
canton {
id
}
}
}
}
teamsCount
teams {
name
}
}
`,
many: gql`
fragment ManyBillings on ChallengeParticipation {
challenge {
title
}
user {
email
firstname
lastname
school {
name
address
}
}
teams {
name
}
}
`,
}
},
},
})
```
Now you have a new virtual resource `ParticipantsToInvoice` that can be used to display a List or for one record. (notice: update/create/delete is currently not specified, so use it read-only) and it will have exactly this data.
There are two ways you can use this new virtual resource. If you want to use it with React-Admin's query hooks (`useQuery, useGetList, useGetOne`), you need to add this as a new `<Resource>`:
```jsx
<Admin>
// ...
<Resource name="ParticipantsToInvoice" />
</Admin>
```
These hooks rely on Redux store and will throw an error if the resource isn't defined.
However, if you directly use data provider calls, you can use it with defined `<Resource>` but also _without_ as it directly calls data provider.
```ts
const dataProvider = useDataProvider()
const { data } = await dataProvider.getList('ParticipantsToInvoice', {
pagination: { page: 1, perPage: 10 },
sort: { field: 'id', order: 'ASC' },
filter: {}
}),
```
It's currently also possible to override an existing resource, altough this is not battle tested.
Loading

0 comments on commit 564fc6f

Please sign in to comment.