Skip to content

Commit

Permalink
Merge branch 'feature/improved-file-input' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
Harley Alexander committed Mar 26, 2020
2 parents 08c42d8 + 7324b13 commit 2d47e4d
Show file tree
Hide file tree
Showing 35 changed files with 1,123 additions and 1,103 deletions.
93 changes: 59 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,26 +25,29 @@ _Screenshot of the example app in this package, using `Auth`, GraphQL `API` and
- [Post editors](#post-editors)
- [Filter and sort media by name](#filter-and-sort-media-by-name)
- [Authentication and Sign in with `Auth`](#signin-with-auth)
- [`<RaAmplifyAuthProvider />`](#raamplifyauthprovider)
- [`<AmplifyAuthProvider />`](#amplifyauthprovider-)
- [`useAuth`](#useauth)
- [`useAuthProvider`](#useauthprovider)
- [`useUser`](#useuser)
- [Federated sign in](#federated-sign-in)
- [Permissions](#permissions)
- [Image Upload with `Storage`](#image-upload)
- [Required schema](#required-schema)
- [`<S3Input />`](#s3input)
- [`<S3ImageField />`](#s3imagefield)
- [`<S3ImageInput />` and `<S3FileInput />`](#s3imageinput--and-s3fileinput-)
- [`<S3ImageField />` and `<S3FileField />`](#s3imagefield--and-s3filefield-)
- [`<S3Input />` and `<S3Field />`](#s3input--and-s3field-)
- [`protected`, `private` files](#protected-private-files)
- [Pagination using `nextToken`](#pagination-using-nexttoken)

## Whats missing and needs help?

- REST API support
- Filtering, sorting of get & list
- Multiple image/file upload
- Recursively updating connections
- Your knowledge and ideas
- Proper typescript typing
- Jest tests
- handling many to many connections
- Filtering, sorting of get & list
- Search with `@searchable` directive
- REST API support

[Check out some `good first issues`](https://github.com/mayteio/ra-aws-amplify/issues?q=is%3Aissue+is%3Aopen+label%3A%22good+first+issue%22) to start!

Expand Down Expand Up @@ -79,7 +82,7 @@ type Post @model {
// App.js
import React, { useEffect, useState } from 'react';
import { Admin, Resource, ListGuesser } from 'react-admin';
import { useDataProvider } from 'ra-aws-amplify';
import { useAmplifyDataProvider } from 'ra-aws-amplify';

// grab your amplify generated code
import config from './aws-exports';
Expand All @@ -88,7 +91,7 @@ import * as queries from './graphql/queries';
import * as mutations from './graphql/mutations';

function App() {
const dataProvider = useDataProvider({ config, schema, queries, mutations });
const dataProvider = useAmplifyDataProvider({ config, schema, queries, mutations });

return
<Admin dataProvider={dataProvider}>
Expand All @@ -100,18 +103,20 @@ function App() {
export default App;
```

## `useDataProvider`
## `useAmplifyDataProvider`

`useDataProvider` is a hook that generates a dataProvider to pass into the `<Admin />` component from `react-admin`. It's smart enough to pick up what kind of authentication you're using for your API (based on the config you pass) as well as hook up the generated queries and mutations from running `amplify push`.
`useAmplifyDataProvider` is a hook that generates a dataProvider to pass into the `<Admin />` component from `react-admin`. It's smart enough to pick up what kind of authentication you're using for your API (based on the config you pass) as well as hook up the generated queries and mutations from running `amplify push`.

```js
import { AUTH_TYPE } from 'aws-appsync';
import { useAmplifyDataProvider } from 'react-admin';

import config from './aws-exports';
import schema from './graphql/schema.json';
import * as queries from './graphql/queries';
import * as mutations from './graphql/mutations';
import { AUTH_TYPE } from 'aws-appsync';

const dataProvider = useDataProvider({
const dataProvider = useAmplifyDataProvider({
// required
config, // generated aws-exports.js
schema, // generated json schema.json
Expand All @@ -129,7 +134,7 @@ No problem. When you `import * as queries from './graphql/queries';` it just ret
```js
// customQueries.js
export const customQueries = {
'listPosts': `
listPosts: `
query CustomListPostQuery {
listPosts {
items {
Expand All @@ -138,12 +143,19 @@ export const customQueries = {
}
}
}
`
}
`,
};

// App.js
import { customQueries } from './customQuieres';
const dataProvider = useDataProvider({ queries: customQueries, ... })
import * as queries from './graphql/queries';
import { customQueries } from './customQueries';

const dataProvider = useAmplifyDataProvider({
queries: {
...queries,
...customQueries,
},
});
```

## DynamoDB Access Patterns with `react-admin`
Expand Down Expand Up @@ -291,27 +303,27 @@ Coming soon...

This package exposes a few tools for handling authentication out of the box with `@aws-amplify/Auth`:

- [`<RaAmplifyAuthProvider />`](#raamplifyauthprovider)
- [`<AmplifyAuthProvider />`](#amplifyauthprovider-)
- [`useAuth`](#useauth)
- [`useAuthProvider`](#useauthprovider)
- [`useUser`](#useuser)
- [Federated sign in](#federated-sign-in)
- [Permissions](#permissions)

### `<RaAmplifyAuthProvider />`
### `<AmplifyAuthProvider />`

Wrap your app in this provider so `Auth` is available at all contexts, with an abstracted API so it's easier to refactor to another provider if DynamoDB drives you nuts 😉.

```js
// index.tsx
import ReactDOM from 'react-dom';
import { RaAmplifyAuthProvider } from 'ra-aws-amplify';
import { AmplifyAuthProvider } from 'ra-aws-amplify';
import { App } from './App';

ReactDOM.render(
<RaAmplifyAuthProvider>
<AmplifyAuthProvider>
<App />
</RaAmplifyAuthProvider>,
</AmplifyAuthProvider>,
document.getElementById('root')
);
```
Expand Down Expand Up @@ -417,11 +429,12 @@ Use this in conjunction with the [Pre Token Generation Lambda Trigger](https://d

## Image Upload with `Storage`

This package exposes `<S3Input />` and `<S3ImageField />` components to help you deal with image & file upload.
This package exposes a handful of input and field components to help you deal with image & file upload via aws-amplify's `Storage` package.

- [Required schema](#required-schema)
- [`<S3Input />`](#s3input)
- [`<S3ImageField />`](#s3imagefield)
- [`<S3ImageInput />` and `<S3FileInput />`](#s3imageinput--and-s3fileinput-)
- [`<S3ImageField />` and `<S3FileField />`](#s3imagefield--and-s3filefield-)
- [`<S3Input />` and `<S3Field />`](#s3input--and-s3field-)
- [`protected`, `private` files](#protected-private-files)

### Required Schema
Expand All @@ -434,52 +447,60 @@ type Post @model {
title: String!
content: String
featureImage: S3Object
files: [S3Object!]
}

type S3Object {
key: String!
identityId: String
level: String
type: String!
}
```

### `<S3Input />`
### `<S3ImageInput />` and `<S3FileInput />`

You can then use `<S3Input />`, for example your `<CreatePost />` might look something like the following:
You can then use `<S3ImageInput />` and `<S3FileInput />` to upload files. Your `<CreatePost />` might look something like the following:

```js
// CreatePost.js
import React from 'react';
import { Create, SimpleForm, TextInput } from 'react-admin';
import { S3Input } from 'ra-aws-amplify';
import { S3ImageInput, S3FileInput } from 'ra-aws-amplify';

export const CreateApp: React.FC = props => {
return (
<Create {...props}>
<SimpleForm>
<TextInput source="title" />
<TextInput source="content" multiline />
<S3Input source="featureImage" accept="image/*" multiple={false} />
<S3ImageInput source="featureImage" accept="image/*" multiple={false} />
<S3FileInput source="files" multiple={true} />
</SimpleForm>
</Create>
);
};
```

### `<S3ImageField />`
### `<S3ImageField />` and `<S3FileField />`

If you want to use the Image in your `<List />` component, you can use `<S3ImageField />` passing, in this example, the `featureImage` field as the source:
If you want to use the image and files in your `<List />` component, you can use the `<S3ImageField />` and `<S3FileField />` to display them:

```js
import React from 'react';
import { List, Datagrid, TextField } from 'react-admin';
import { S3ImageField } from 'ra-aws-amplify';
import { List, Datagrid, TextField, SingleFieldList } from 'react-admin';
import { S3ImageField, S3FileField } from 'ra-aws-amplify';

export const ListPosts = props => {
return (
<List {...props}>
<Datagrid rowClick="edit">
<S3ImageField source="featureImage" />
<ArrayField source="files">
<SingleFieldList>
<S3FileField />
</SingleFieldList>
</ArrayField>
<TextField source="title" />
<TextField source="content" />
</Datagrid>
Expand All @@ -488,6 +509,10 @@ export const ListPosts = props => {
};
```

### `<S3Input />` and `<S3Field />`

The logic for handling `Storage` upload & retrieval is actually abstracted into these two components. They both use `React.cloneElement` to pass the props down to either `S3ImageField` or `S3FileField`. The responsibility of, for example, S3ImageField is just to display whatever URL is passed down to it.

### `protected`, `private` files

You can pass in the `level` option as a prop to `<S3Input level={...} />` (one of `public`, `protected`, and `private`) and that will get passed on to `Storage`. If you do this, it's important to either use the `authProvider` from this package, or in your custom `authProvider` pass the `identityId` into `getPermissions`:
Expand Down
2 changes: 2 additions & 0 deletions example/amplify/backend/api/raawsamplify/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ type Post
content: String
image: Media @connection
comments: [Comment] @connection(keyName: "byPost", fields: ["id"])
files: [S3Object!]
}

type Comment
Expand Down Expand Up @@ -46,4 +47,5 @@ type S3Object {
key: String!
identityId: String
level: String
type: String
}
3 changes: 2 additions & 1 deletion example/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"main": "index.js",
"license": "MIT",
"scripts": {
"start": "webpack-dev-server --open"
"start": "webpack-dev-server --open",
"schema": "aws appsync get-introspection-schema --api-id=eshgyezy4rahzabv6hx4exkbhq --format=JSON src/graphql/schema.json --profile=personal"
},
"dependencies": {
"react-app-polyfill": "^1.0.0"
Expand Down
5 changes: 5 additions & 0 deletions example/public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>React App</title>
<style type="text/css">
body {
margin: 0;
}
</style>
</head>

<body>
Expand Down
Loading

0 comments on commit 2d47e4d

Please sign in to comment.