FileUpload.js 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213
  1. import gql from 'graphql-tag'
  2. import { Mutation, Query } from 'react-apollo'
  3. import { useState } from 'react'
  4. import { endpoint } from '../config'
  5. const DO_LOCAL = gql`
  6. {
  7. doLocal @client
  8. }
  9. `
  10. const UPLOAD_FILE = gql`
  11. mutation UPLOAD_FILE(
  12. $files: [Upload!]!
  13. $name: String!
  14. $description: String!
  15. ) {
  16. uploadFiles(files: $files, name: $name, description: $description) {
  17. id
  18. path
  19. name
  20. description
  21. filename
  22. mimetype
  23. size
  24. }
  25. }
  26. `
  27. const TestForm = props => {
  28. const [state, setState] = useState({ files: null, name: '', description: '' })
  29. function updateState (event) {
  30. const { name, type, files, value } = event.target
  31. setState({ ...state, [name]: type === 'file' ? files : value })
  32. }
  33. return (
  34. <Mutation mutation={UPLOAD_FILE} variables={state}>
  35. {(uploadFiles, { data, error, loading }) => (
  36. <form
  37. onSubmit={async event => {
  38. console.log(state)
  39. event.preventDefault()
  40. const res = await uploadFiles()
  41. console.log(res)
  42. }}
  43. >
  44. <input
  45. type='file'
  46. multiple
  47. required
  48. name='files'
  49. onChange={updateState}
  50. />
  51. <input
  52. type='text'
  53. name='name'
  54. value={state.name}
  55. onChange={updateState}
  56. />
  57. <textarea
  58. name='description'
  59. value={state.description}
  60. onChange={updateState}
  61. />
  62. <button>Send</button>
  63. <Query query={DO_LOCAL}>
  64. {({ data, client }) => (
  65. <>
  66. <button
  67. type='button'
  68. onClick={event => {
  69. client.writeData({ data: { doLocal: !data.doLocal } })
  70. }}
  71. >
  72. Do Local
  73. </button>
  74. <button disabled={data.doLocal}>Uh-Oh!</button>
  75. </>
  76. )}
  77. </Query>
  78. </form>
  79. )}
  80. </Mutation>
  81. )
  82. }
  83. const FileFormFields = props => {
  84. const [state, setState] = useState({ ...FileState })
  85. const updateState = async event => {
  86. const { name, type, value, files } = event.target
  87. await setState({
  88. ...state,
  89. [name]: type === 'file' ? files[0] : value
  90. })
  91. props.onChange(event, state)
  92. }
  93. return (
  94. <fieldset>
  95. <label htmlFor='file'>File</label>
  96. <input
  97. type='file'
  98. multiple
  99. required
  100. name='file'
  101. id='file'
  102. onChange={updateState}
  103. />
  104. <label htmlFor='name'>File name</label>
  105. <input
  106. type='text'
  107. name='name'
  108. id='name'
  109. placeholder='File name'
  110. value={state.name}
  111. onChange={updateState}
  112. />
  113. <label htmlFor='description'>File description</label>
  114. <textarea
  115. name='description'
  116. id='description'
  117. placeholder='File description'
  118. value={state.description}
  119. onChange={updateState}
  120. />
  121. </fieldset>
  122. )
  123. }
  124. const FileFields = {
  125. id: null,
  126. path: '',
  127. name: '',
  128. description: '',
  129. filename: '',
  130. mimetype: '',
  131. size: '',
  132. file: null
  133. }
  134. async function uploadFile (file) {
  135. const body = new FormData()
  136. body.append('file', file)
  137. const res = await fetch(`${endpoint}/upload`, { method: 'POST', body })
  138. return res.json()
  139. }
  140. class FileUpload extends React.Component {
  141. state = {
  142. ...FileState
  143. }
  144. upload = async event => {
  145. event.preventDefault()
  146. if (!this.state.file) {
  147. alert('Please select file first.')
  148. return
  149. }
  150. this.setState({ uploading: true })
  151. const data = new FormData()
  152. data.append('file', this.state.file)
  153. data.append('description', this.state.description)
  154. const res = await fetch(`${endpoint}/upload`, {
  155. method: 'POST',
  156. body: data
  157. })
  158. const { error, file } = await res.json()
  159. if (error) {
  160. console.error(error)
  161. alert('Upload error.')
  162. this.setState({ uploading: false })
  163. }
  164. this.setState({ path: `${endpoint}/${file.path}`, uploading: false })
  165. }
  166. selectFile = event => {
  167. const { validity, files } = event.target
  168. this.setState({ file: files[0] })
  169. }
  170. handleChange = event => {
  171. this.setState({ [event.target.name]: event.target.value })
  172. }
  173. render () {
  174. return (
  175. <form>
  176. <fieldset>
  177. <input type='file' name='file' id='file' onChange={this.selectFile} />
  178. <textarea
  179. name='description'
  180. id='description'
  181. placeholder='Description'
  182. value={this.state.description}
  183. onChange={this.handleChange}
  184. />
  185. <img src={this.state.path} alt={this.state.name} />
  186. <button onClick={this.upload} disabled={this.state.uploading}>
  187. Save
  188. </button>
  189. </fieldset>
  190. </form>
  191. )
  192. }
  193. }
  194. export default FileUpload
  195. export { FileFields, FileFormFields }