From e2420c2a63239d4e52d44c42c411948b9fdb7458 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Mon, 3 Apr 2017 12:37:32 -0600 Subject: [PATCH 01/22] Add multiple file upload component --- client/components/multi-uploader.js | 31 +++++++++++++++++++++++++++++ client/pages/index.js | 17 +++++++++++++--- 2 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 client/components/multi-uploader.js diff --git a/client/components/multi-uploader.js b/client/components/multi-uploader.js new file mode 100644 index 0000000..517ed04 --- /dev/null +++ b/client/components/multi-uploader.js @@ -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 + } +} + +export default graphql(gql` + mutation multiUpload ($files: [Upload!]) { + multiUpload (files: $files) { + name + type + size + path + } + } +`)(MultiUploader) diff --git a/client/pages/index.js b/client/pages/index.js index 26ad181..adbb4e3 100644 --- a/client/pages/index.js +++ b/client/pages/index.js @@ -1,6 +1,7 @@ import Head from 'next/head' import withData from '../helpers/with-data' import SingleUploader from '../components/single-uploader' +import MultiUploader from '../components/multi-uploader' export default withData(props => (
@@ -13,10 +14,20 @@ export default withData(props => ( body { margin: 2em; } + section { + height: 50vh; + } `} -

Apollo upload example

-

Select an image to upload and view the response in the console.

- +
+

Apollo upload example (single file)

+

Select an image to upload and view the response in the console.

+ +
+
+

Apollo upload example (multiple files)

+

Select multiple images to upload and view the response in the console.

+ +
)) From 54b686fda302727dc5172edee810c15307690ffc Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Mon, 3 Apr 2017 12:39:30 -0600 Subject: [PATCH 02/22] Add mutation/resolver for multi file upload --- api/resolvers.js | 4 ++++ api/schema.graphql | 1 + 2 files changed, 5 insertions(+) diff --git a/api/resolvers.js b/api/resolvers.js index 4de7971..9d64b08 100644 --- a/api/resolvers.js +++ b/api/resolvers.js @@ -8,6 +8,10 @@ export default { singleUpload (root, {file}) { console.log('Uploaded file:', file) return file + }, + multiUpload (root, {files}) { + console.log('Uploaded files:', files) + return files } } } diff --git a/api/schema.graphql b/api/schema.graphql index 2a2a100..6abdeeb 100644 --- a/api/schema.graphql +++ b/api/schema.graphql @@ -19,4 +19,5 @@ type Query { type Mutation { singleUpload (file: Upload!): File! + multiUpload (files: [Upload!]): [File!] } From 14be2c24339259539cfc4f98ab13ec20f7d55e68 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Mon, 3 Apr 2017 20:16:27 -0600 Subject: [PATCH 03/22] Add rethinkdb --- api/config.js | 5 +++++ api/package.json | 1 + api/resolvers.js | 25 +++++++++++++++++++------ api/rethinkdb.js | 10 ++++++++++ 4 files changed, 35 insertions(+), 6 deletions(-) create mode 100644 api/rethinkdb.js diff --git a/api/config.js b/api/config.js index 8d45014..f1398b9 100644 --- a/api/config.js +++ b/api/config.js @@ -2,3 +2,8 @@ import path from 'path' export const distPath = path.resolve(__dirname, 'dist') export const apiEndpoint = '/graphql' +export const rethinkdb = { + host: 'localhost', + port: 28015, + db: 'test' +} diff --git a/api/package.json b/api/package.json index 211041e..86ddda9 100644 --- a/api/package.json +++ b/api/package.json @@ -16,6 +16,7 @@ "koa-bodyparser": "^4.2.0", "koa-compress": "^2.0.0", "koa-router": "^7.1.1", + "rethinkdbdash": "^2.3.28", "source-map-support": "^0.4.14", "webpack": "^2.3.2", "zoo": "^0.1.9" diff --git a/api/resolvers.js b/api/resolvers.js index 9d64b08..b25f3c1 100644 --- a/api/resolvers.js +++ b/api/resolvers.js @@ -1,3 +1,12 @@ +import getRethinkDB from './rethinkdb' + +const getNewVal = (result) => { + if (result.changes.length === 1) { + return result.changes[0].new_val + } + return result.changes.map((file) => file.new_val) +} + export default { Query: { ignore () { @@ -5,13 +14,17 @@ export default { } }, Mutation: { - singleUpload (root, {file}) { - console.log('Uploaded file:', file) - return file + async singleUpload (_, {file}) { + const db = getRethinkDB() + const result = await db.table('uploads') + .insert(file, {returnChanges: true}) + return getNewVal(result) }, - multiUpload (root, {files}) { - console.log('Uploaded files:', files) - return files + async multiUpload (_, {files}) { + const db = getRethinkDB() + const result = await db.table('uploads') + .insert(files, {returnChanges: true}) + return getNewVal(result) } } } diff --git a/api/rethinkdb.js b/api/rethinkdb.js new file mode 100644 index 0000000..43a9c86 --- /dev/null +++ b/api/rethinkdb.js @@ -0,0 +1,10 @@ +import rethinkdbdash from 'rethinkdbdash' +import {rethinkdb} from './config' + +let driver +export default () => { + if (!driver) { + driver = rethinkdbdash(rethinkdb) + } + return driver +} From 0dd7f4a9b4d3f99141a85b9a8244e543de8dad54 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Mon, 3 Apr 2017 20:36:08 -0600 Subject: [PATCH 04/22] Add query for all uploads --- api/resolvers.js | 5 +++-- api/schema.graphql | 3 +-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/resolvers.js b/api/resolvers.js index b25f3c1..ef087e8 100644 --- a/api/resolvers.js +++ b/api/resolvers.js @@ -9,8 +9,9 @@ const getNewVal = (result) => { export default { Query: { - ignore () { - return null + async allUploads () { + const db = getRethinkDB() + return await db.table('uploads') } }, Mutation: { diff --git a/api/schema.graphql b/api/schema.graphql index 6abdeeb..b58727d 100644 --- a/api/schema.graphql +++ b/api/schema.graphql @@ -13,8 +13,7 @@ input Upload { } type Query { - # GraphQL will not work without defining a query. - ignore: Boolean + allUploads: [File] } type Mutation { From 347ea10af1be122a2613f0b18cf7365dd89e256c Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Mon, 3 Apr 2017 21:01:25 -0600 Subject: [PATCH 05/22] Adjust section height to prevent scrolling --- client/pages/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/pages/index.js b/client/pages/index.js index adbb4e3..8e9d022 100644 --- a/client/pages/index.js +++ b/client/pages/index.js @@ -15,7 +15,7 @@ export default withData(props => ( margin: 2em; } section { - height: 50vh; + height: calc(50vh - 4em); } `} From 02993f3cb9b256798be3486e6a05c6b2c7677cd9 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Mon, 3 Apr 2017 21:35:37 -0600 Subject: [PATCH 06/22] Add multi-uploader component --- {client => app}/components/multi-uploader.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename {client => app}/components/multi-uploader.js (100%) diff --git a/client/components/multi-uploader.js b/app/components/multi-uploader.js similarity index 100% rename from client/components/multi-uploader.js rename to app/components/multi-uploader.js From 4a3227c5091fc1897edd5a7279b696475830f206 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Mon, 3 Apr 2017 21:38:07 -0600 Subject: [PATCH 07/22] Change api to app in app readme --- app/readme.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/readme.md b/app/readme.md index 19caebb..ee06ba1 100644 --- a/app/readme.md +++ b/app/readme.md @@ -5,7 +5,7 @@ An example web application using [Next.js](https://github.com/zeit/next.js), [Re ## Setup 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. For development run `npm run dev`. From c3b885bf66b968ef916a757ce40d14db1c2638a7 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 10:06:07 -0600 Subject: [PATCH 08/22] Add h2 headers for upload components --- app/pages/index.js | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/app/pages/index.js b/app/pages/index.js index 8e9d022..bc59533 100644 --- a/app/pages/index.js +++ b/app/pages/index.js @@ -15,17 +15,18 @@ export default withData(props => ( margin: 2em; } section { - height: calc(50vh - 4em); + padding-top: 3em; } `} +

Apollo upload example

-

Apollo upload example (single file)

+

Single file upload

Select an image to upload and view the response in the console.

-

Apollo upload example (multiple files)

+

Multiple file upload

Select multiple images to upload and view the response in the console.

From 9721b4bac06d72dcfe5752813cd4e938c2906b62 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 10:06:50 -0600 Subject: [PATCH 09/22] Remove rethinkdb config obj --- api/config.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/api/config.js b/api/config.js index f1398b9..8d45014 100644 --- a/api/config.js +++ b/api/config.js @@ -2,8 +2,3 @@ import path from 'path' export const distPath = path.resolve(__dirname, 'dist') export const apiEndpoint = '/graphql' -export const rethinkdb = { - host: 'localhost', - port: 28015, - db: 'test' -} From 5361bf1ad59e9eae13fa0cb42dd0576384776cc0 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 10:07:26 -0600 Subject: [PATCH 10/22] Remove async/await --- api/resolvers.js | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/api/resolvers.js b/api/resolvers.js index ef087e8..5c9b5d2 100644 --- a/api/resolvers.js +++ b/api/resolvers.js @@ -9,21 +9,21 @@ const getNewVal = (result) => { export default { Query: { - async allUploads () { + allUploads () { const db = getRethinkDB() - return await db.table('uploads') + return db.table('uploads') } }, Mutation: { - async singleUpload (_, {file}) { + singleUpload (_, {file}) { const db = getRethinkDB() - const result = await db.table('uploads') + const result = db.table('uploads') .insert(file, {returnChanges: true}) return getNewVal(result) }, - async multiUpload (_, {files}) { + multiUpload (_, {files}) { const db = getRethinkDB() - const result = await db.table('uploads') + const result = db.table('uploads') .insert(files, {returnChanges: true}) return getNewVal(result) } From f5416cd2189944e3af26ddc12039193f048f5e30 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 10:08:21 -0600 Subject: [PATCH 11/22] Add db info from process --- api/rethinkdb.js | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/api/rethinkdb.js b/api/rethinkdb.js index 43a9c86..a1c2544 100644 --- a/api/rethinkdb.js +++ b/api/rethinkdb.js @@ -1,10 +1,13 @@ import rethinkdbdash from 'rethinkdbdash' -import {rethinkdb} from './config' let driver export default () => { if (!driver) { - driver = rethinkdbdash(rethinkdb) + driver = rethinkdbdash({ + host: process.env.DB_HOST, + port: process.env.DB_PORT, + db: process.env.DB_NAME + }) } return driver } From 786f6cb41fc833d162d715ed36a3ea6ec91e3da8 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 10:09:02 -0600 Subject: [PATCH 12/22] Update mutation to expect arrays --- api/schema.graphql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/schema.graphql b/api/schema.graphql index b58727d..deab78d 100644 --- a/api/schema.graphql +++ b/api/schema.graphql @@ -18,5 +18,5 @@ type Query { type Mutation { singleUpload (file: Upload!): File! - multiUpload (files: [Upload!]): [File!] + multiUpload (files: [Upload!]!): [File!]! } From cb246d01d418a671fabaf1c23efed6b16e34ebda Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 10:23:28 -0600 Subject: [PATCH 13/22] Add promises to resolvers --- api/resolvers.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/api/resolvers.js b/api/resolvers.js index 5c9b5d2..7d15fcd 100644 --- a/api/resolvers.js +++ b/api/resolvers.js @@ -17,15 +17,15 @@ export default { Mutation: { singleUpload (_, {file}) { const db = getRethinkDB() - const result = db.table('uploads') + return db.table('uploads') .insert(file, {returnChanges: true}) - return getNewVal(result) + .then((result) => getNewVal(result)) }, multiUpload (_, {files}) { const db = getRethinkDB() - const result = db.table('uploads') + return db.table('uploads') .insert(files, {returnChanges: true}) - return getNewVal(result) + .then((result) => getNewVal(result)) } } } From 3f174429846dd8d68d09678c4f8b98596b81b9be Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 10:24:15 -0600 Subject: [PATCH 14/22] Update gql mutation to expect arrays --- app/components/multi-uploader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/components/multi-uploader.js b/app/components/multi-uploader.js index 517ed04..de9b45b 100644 --- a/app/components/multi-uploader.js +++ b/app/components/multi-uploader.js @@ -20,7 +20,7 @@ class MultiUploader extends Component { } export default graphql(gql` - mutation multiUpload ($files: [Upload!]) { + mutation multiUpload ($files: [Upload!]!) { multiUpload (files: $files) { name type From e0303e63637e75bcb596301c4defec7c32eafec9 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 12:03:34 -0600 Subject: [PATCH 15/22] Return results for uploads query --- api/resolvers.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/api/resolvers.js b/api/resolvers.js index 7d15fcd..e5daf7a 100644 --- a/api/resolvers.js +++ b/api/resolvers.js @@ -12,20 +12,21 @@ export default { allUploads () { const db = getRethinkDB() return db.table('uploads') + .then((result) => result) } }, Mutation: { singleUpload (_, {file}) { const db = getRethinkDB() return db.table('uploads') - .insert(file, {returnChanges: true}) - .then((result) => getNewVal(result)) + .insert(file, {returnChanges: true}) + .then((result) => getNewVal(result)) }, multiUpload (_, {files}) { const db = getRethinkDB() return db.table('uploads') - .insert(files, {returnChanges: true}) - .then((result) => getNewVal(result)) + .insert(files, {returnChanges: true}) + .then((result) => getNewVal(result)) } } } From 70e48c49afb5a4e755ec654881edcc7a5022dcba Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 12:04:40 -0600 Subject: [PATCH 16/22] Add id to file type for react key --- api/schema.graphql | 1 + 1 file changed, 1 insertion(+) diff --git a/api/schema.graphql b/api/schema.graphql index deab78d..e9919b6 100644 --- a/api/schema.graphql +++ b/api/schema.graphql @@ -1,4 +1,5 @@ type File { + id: String! name: String! type: String! size: Int! From 824af6db76a5ef089931638ddf9cc69319c0e249 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 12:05:48 -0600 Subject: [PATCH 17/22] Add upload-list component --- app/components/upload-list.js | 23 +++++++++++++++++++++++ app/pages/index.js | 4 ++++ 2 files changed, 27 insertions(+) create mode 100644 app/components/upload-list.js diff --git a/app/components/upload-list.js b/app/components/upload-list.js new file mode 100644 index 0000000..8ec04c2 --- /dev/null +++ b/app/components/upload-list.js @@ -0,0 +1,23 @@ +import {graphql, gql} from 'react-apollo' + +const UploadList = ({data: {allUploads, loading}}) => { + return ( +
    + {allUploads.map((file) => { + return
  • {file.name}
  • + })} +
+ ) +} + +export default graphql(gql` + query allUploads { + allUploads { + id + name + type + size + path + } + } +`)(UploadList) diff --git a/app/pages/index.js b/app/pages/index.js index bc59533..5876c16 100644 --- a/app/pages/index.js +++ b/app/pages/index.js @@ -2,6 +2,7 @@ import Head from 'next/head' import withData from '../helpers/with-data' import SingleUploader from '../components/single-uploader' import MultiUploader from '../components/multi-uploader' +import UploadList from '../components/upload-list' export default withData(props => (
@@ -30,5 +31,8 @@ export default withData(props => (

Select multiple images to upload and view the response in the console.

+
+ +
)) From 4c68f46d0800753b8fab20ea66eb9c75110cfbe6 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 23:23:08 -0600 Subject: [PATCH 18/22] Replace rethinkdb with lowdb --- api/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/package.json b/api/package.json index 70177b1..cf79592 100644 --- a/api/package.json +++ b/api/package.json @@ -16,7 +16,7 @@ "koa-bodyparser": "^4.2.0", "koa-compress": "^2.0.0", "koa-router": "^7.1.1", - "rethinkdbdash": "^2.3.28", + "lowdb": "^0.16.0", "source-map-support": "^0.4.14", "webpack": "^2.3.3", "zoo": "^0.1.9" From de4fdc0632acf039a6b51f318b89789232e2ab81 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 23:24:01 -0600 Subject: [PATCH 19/22] Remove id and use iterator as key --- app/components/upload-list.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/components/upload-list.js b/app/components/upload-list.js index 8ec04c2..c25ec41 100644 --- a/app/components/upload-list.js +++ b/app/components/upload-list.js @@ -3,8 +3,8 @@ import {graphql, gql} from 'react-apollo' const UploadList = ({data: {allUploads, loading}}) => { return (
    - {allUploads.map((file) => { - return
  • {file.name}
  • + {allUploads.map((file, i) => { + return
  • {file.name}
  • })}
) @@ -13,7 +13,6 @@ const UploadList = ({data: {allUploads, loading}}) => { export default graphql(gql` query allUploads { allUploads { - id name type size From c09266640345edfe165d9de3b9bd97ba8d8c8329 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 23:26:51 -0600 Subject: [PATCH 20/22] Add lowdb --- api/db.json | 1 + api/resolvers.js | 39 +++++++++++++++++++++------------------ api/rethinkdb.js | 13 ------------- 3 files changed, 22 insertions(+), 31 deletions(-) create mode 100644 api/db.json delete mode 100644 api/rethinkdb.js diff --git a/api/db.json b/api/db.json new file mode 100644 index 0000000..a192a06 --- /dev/null +++ b/api/db.json @@ -0,0 +1 @@ +{"uploads":[{"name":"IMG_0599.JPG","type":"image/jpeg","size":343845,"path":"/tmp/uploads/upload_7b8d12d21774c726904d6272f6176d57"},{"name":"IMG_0599.JPG","type":"image/jpeg","size":343845,"path":"/tmp/uploads/upload_e39a69250284e0113b276e3dcf87dbb4"},{"name":"kalen-emsley-99660.jpg","type":"image/jpeg","size":14036175,"path":"/tmp/uploads/upload_fe22084971ed01e6849cd7fa253ccf4b"}]} \ No newline at end of file diff --git a/api/resolvers.js b/api/resolvers.js index e5daf7a..d335296 100644 --- a/api/resolvers.js +++ b/api/resolvers.js @@ -1,32 +1,35 @@ -import getRethinkDB from './rethinkdb' +import low from 'lowdb' +import fileAsync from 'lowdb/lib/storages/file-async' -const getNewVal = (result) => { - if (result.changes.length === 1) { - return result.changes[0].new_val - } - return result.changes.map((file) => file.new_val) +// 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 { Query: { allUploads () { - const db = getRethinkDB() - return db.table('uploads') - .then((result) => result) + return db.get('uploads').value() } }, Mutation: { singleUpload (_, {file}) { - const db = getRethinkDB() - return db.table('uploads') - .insert(file, {returnChanges: true}) - .then((result) => getNewVal(result)) + return saveFile(file) }, multiUpload (_, {files}) { - const db = getRethinkDB() - return db.table('uploads') - .insert(files, {returnChanges: true}) - .then((result) => getNewVal(result)) + return Promise.all(files.map((file) => { + return saveFile(file) + })).then((results) => results) } } } diff --git a/api/rethinkdb.js b/api/rethinkdb.js deleted file mode 100644 index a1c2544..0000000 --- a/api/rethinkdb.js +++ /dev/null @@ -1,13 +0,0 @@ -import rethinkdbdash from 'rethinkdbdash' - -let driver -export default () => { - if (!driver) { - driver = rethinkdbdash({ - host: process.env.DB_HOST, - port: process.env.DB_PORT, - db: process.env.DB_NAME - }) - } - return driver -} From c00ff4192653a8fe70551d572efc0247475dbcf8 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Tue, 4 Apr 2017 23:27:06 -0600 Subject: [PATCH 21/22] Remove id from file type --- api/schema.graphql | 1 - 1 file changed, 1 deletion(-) diff --git a/api/schema.graphql b/api/schema.graphql index e9919b6..deab78d 100644 --- a/api/schema.graphql +++ b/api/schema.graphql @@ -1,5 +1,4 @@ type File { - id: String! name: String! type: String! size: Int! From fd18389be4dc09069d2099d6d1d98525966f1553 Mon Sep 17 00:00:00 2001 From: Michael Merrill Date: Thu, 6 Apr 2017 08:16:58 -0600 Subject: [PATCH 22/22] Remove and ignore db.json file --- .gitignore | 1 + api/db.json | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) delete mode 100644 api/db.json diff --git a/.gitignore b/.gitignore index ba8e7fa..840014a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ node_modules yarn.lock .env .DS_Store +db.json diff --git a/api/db.json b/api/db.json deleted file mode 100644 index a192a06..0000000 --- a/api/db.json +++ /dev/null @@ -1 +0,0 @@ -{"uploads":[{"name":"IMG_0599.JPG","type":"image/jpeg","size":343845,"path":"/tmp/uploads/upload_7b8d12d21774c726904d6272f6176d57"},{"name":"IMG_0599.JPG","type":"image/jpeg","size":343845,"path":"/tmp/uploads/upload_e39a69250284e0113b276e3dcf87dbb4"},{"name":"kalen-emsley-99660.jpg","type":"image/jpeg","size":14036175,"path":"/tmp/uploads/upload_fe22084971ed01e6849cd7fa253ccf4b"}]} \ No newline at end of file