Merge pull request #1 from michaelmerrill/multi-file-upload
- New multiple file upload example. - Added a database to track uploads. - Replaced the placeholder query with one that gets all the uploaded files. - New component that list all the uploaded files.
This commit is contained in:
commit
e0ed74e0f4
1
.gitignore
vendored
1
.gitignore
vendored
@ -3,3 +3,4 @@ node_modules
|
|||||||
yarn.lock
|
yarn.lock
|
||||||
.env
|
.env
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
db.json
|
||||||
|
|||||||
@ -16,6 +16,7 @@
|
|||||||
"koa-bodyparser": "^4.2.0",
|
"koa-bodyparser": "^4.2.0",
|
||||||
"koa-compress": "^2.0.0",
|
"koa-compress": "^2.0.0",
|
||||||
"koa-router": "^7.1.1",
|
"koa-router": "^7.1.1",
|
||||||
|
"lowdb": "^0.16.0",
|
||||||
"source-map-support": "^0.4.14",
|
"source-map-support": "^0.4.14",
|
||||||
"webpack": "^2.3.3",
|
"webpack": "^2.3.3",
|
||||||
"zoo": "^0.1.9"
|
"zoo": "^0.1.9"
|
||||||
|
|||||||
@ -1,13 +1,35 @@
|
|||||||
|
import low from 'lowdb'
|
||||||
|
import fileAsync from 'lowdb/lib/storages/file-async'
|
||||||
|
|
||||||
|
// Start database using file-async storage
|
||||||
|
const db = low('db.json', {
|
||||||
|
storage: fileAsync
|
||||||
|
})
|
||||||
|
|
||||||
|
db.defaults({uploads: []})
|
||||||
|
.write()
|
||||||
|
|
||||||
|
const saveFile = (file) => {
|
||||||
|
return db.get('uploads')
|
||||||
|
.push(file)
|
||||||
|
.last()
|
||||||
|
.write()
|
||||||
|
.then((result) => result)
|
||||||
|
}
|
||||||
export default {
|
export default {
|
||||||
Query: {
|
Query: {
|
||||||
ignore () {
|
allUploads () {
|
||||||
return null
|
return db.get('uploads').value()
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Mutation: {
|
Mutation: {
|
||||||
singleUpload (root, {file}) {
|
singleUpload (_, {file}) {
|
||||||
console.log('Uploaded file:', file)
|
return saveFile(file)
|
||||||
return file
|
},
|
||||||
|
multiUpload (_, {files}) {
|
||||||
|
return Promise.all(files.map((file) => {
|
||||||
|
return saveFile(file)
|
||||||
|
})).then((results) => results)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -13,10 +13,10 @@ input Upload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
# GraphQL will not work without defining a query.
|
allUploads: [File]
|
||||||
ignore: Boolean
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type Mutation {
|
type Mutation {
|
||||||
singleUpload (file: Upload!): File!
|
singleUpload (file: Upload!): File!
|
||||||
|
multiUpload (files: [Upload!]!): [File!]!
|
||||||
}
|
}
|
||||||
|
|||||||
31
app/components/multi-uploader.js
Normal file
31
app/components/multi-uploader.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
import {Component} from 'react'
|
||||||
|
import {graphql, gql} from 'react-apollo'
|
||||||
|
|
||||||
|
class MultiUploader extends Component {
|
||||||
|
handleChange = ({target}) => {
|
||||||
|
if (target.validity.valid) {
|
||||||
|
this.props
|
||||||
|
.mutate({
|
||||||
|
variables: {
|
||||||
|
files: target.files
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then(({data}) => console.log('Mutation response:', data))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
render () {
|
||||||
|
return <input type='file' accept={'image/jpeg,image/png'} multiple required onChange={this.handleChange} />
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default graphql(gql`
|
||||||
|
mutation multiUpload ($files: [Upload!]!) {
|
||||||
|
multiUpload (files: $files) {
|
||||||
|
name
|
||||||
|
type
|
||||||
|
size
|
||||||
|
path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)(MultiUploader)
|
||||||
22
app/components/upload-list.js
Normal file
22
app/components/upload-list.js
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
import {graphql, gql} from 'react-apollo'
|
||||||
|
|
||||||
|
const UploadList = ({data: {allUploads, loading}}) => {
|
||||||
|
return (
|
||||||
|
<ul>
|
||||||
|
{allUploads.map((file, i) => {
|
||||||
|
return <li key={i}>{file.name}</li>
|
||||||
|
})}
|
||||||
|
</ul>
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
export default graphql(gql`
|
||||||
|
query allUploads {
|
||||||
|
allUploads {
|
||||||
|
name
|
||||||
|
type
|
||||||
|
size
|
||||||
|
path
|
||||||
|
}
|
||||||
|
}
|
||||||
|
`)(UploadList)
|
||||||
@ -1,6 +1,8 @@
|
|||||||
import Head from 'next/head'
|
import Head from 'next/head'
|
||||||
import withData from '../helpers/with-data'
|
import withData from '../helpers/with-data'
|
||||||
import SingleUploader from '../components/single-uploader'
|
import SingleUploader from '../components/single-uploader'
|
||||||
|
import MultiUploader from '../components/multi-uploader'
|
||||||
|
import UploadList from '../components/upload-list'
|
||||||
|
|
||||||
export default withData(props => (
|
export default withData(props => (
|
||||||
<div>
|
<div>
|
||||||
@ -13,10 +15,24 @@ export default withData(props => (
|
|||||||
body {
|
body {
|
||||||
margin: 2em;
|
margin: 2em;
|
||||||
}
|
}
|
||||||
|
section {
|
||||||
|
padding-top: 3em;
|
||||||
|
}
|
||||||
`}</style>
|
`}</style>
|
||||||
</Head>
|
</Head>
|
||||||
<h1>Apollo upload example</h1>
|
<h1>Apollo upload example</h1>
|
||||||
<p>Select an image to upload and view the response in the console.</p>
|
<section>
|
||||||
<SingleUploader />
|
<h2>Single file upload</h2>
|
||||||
|
<p>Select an image to upload and view the response in the console.</p>
|
||||||
|
<SingleUploader />
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<h2>Multiple file upload</h2>
|
||||||
|
<p>Select multiple images to upload and view the response in the console.</p>
|
||||||
|
<MultiUploader />
|
||||||
|
</section>
|
||||||
|
<section>
|
||||||
|
<UploadList />
|
||||||
|
</section>
|
||||||
</div>
|
</div>
|
||||||
))
|
))
|
||||||
|
|||||||
@ -5,7 +5,7 @@ An example web application using [Next.js](https://github.com/zeit/next.js), [Re
|
|||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
1. Install the latest [Node.js](https://nodejs.org).
|
1. Install the latest [Node.js](https://nodejs.org).
|
||||||
2. Run `npm install` within the `api` directory in Terminal.
|
2. Run `npm install` within the `app` directory in Terminal.
|
||||||
3. Copy `.env.example`, rename it `.env` and customize.
|
3. Copy `.env.example`, rename it `.env` and customize.
|
||||||
|
|
||||||
For development run `npm run dev`.
|
For development run `npm run dev`.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user