FileUpload.js 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165
  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($files: [Upload!]!, $name: String!, $description: String!) {
  12. uploadFiles(files: $files, name: $name, description: $description) {
  13. id
  14. path
  15. name
  16. description
  17. filename
  18. mimetype
  19. size
  20. }
  21. }
  22. `
  23. const TestForm = props => {
  24. const [state, setState] = useState({ files: null, name: '', description: '' })
  25. function updateState(event) {
  26. const { name, type, files, value } = event.target
  27. setState({ ...state, [name]: type === 'file' ? files : value })
  28. }
  29. return (
  30. <Mutation mutation={UPLOAD_FILE} variables={state}>
  31. {(uploadFiles, { data, error, loading }) => (
  32. <form onSubmit={async event => {
  33. console.log(state)
  34. event.preventDefault()
  35. const res = await uploadFiles()
  36. console.log(res)
  37. }}>
  38. <input type='file' multiple required name='files' onChange={updateState} />
  39. <input type='text' name='name' value={state.name} onChange={updateState} />
  40. <textarea name='description' value={state.description} onChange={updateState} />
  41. <button>Send</button>
  42. <Query query={DO_LOCAL}>
  43. {({ data, client }) => (
  44. <>
  45. <button type='button' onClick={
  46. event => { client.writeData({ data: { doLocal: !data.doLocal } }) }
  47. }>Do Local</button>
  48. <button disabled={data.doLocal}>Uh-Oh!</button>
  49. </>
  50. )}
  51. </Query>
  52. </form>
  53. )}
  54. </Mutation>
  55. )
  56. }
  57. const FileFormFields = props => {
  58. const [state, setState] = useState({ ...FileState })
  59. const updateState = async event => {
  60. const { name, type, value, files } = event.target
  61. await setState({
  62. ...state,
  63. [name]: type === 'file' ? files[0] : value
  64. })
  65. console.log(state)
  66. props.onChange(event, state)
  67. }
  68. return (
  69. < fieldset >
  70. <label htmlFor='file'>File</label>
  71. <input type='file' multiple required name='file' id='file' onChange={updateState} />
  72. <label htmlFor='name'>File name</label>
  73. <input type='text' name='name' id='name' placeholder='File name' value={state.name} onChange={updateState} />
  74. <label htmlFor='description'>File description</label>
  75. <textarea name='description' id='description' placeholder='File description' value={state.description} onChange={updateState} />
  76. </fieldset >
  77. )
  78. }
  79. const FileFields = {
  80. id: null,
  81. path: '',
  82. name: '',
  83. description: '',
  84. filename: '',
  85. mimetype: '',
  86. size: '',
  87. file: null
  88. }
  89. async function uploadFile(file) {
  90. const body = new FormData()
  91. body.append('file', file)
  92. const res = await fetch(`${endpoint}/upload`, { method: 'POST', body })
  93. return res.json()
  94. }
  95. class FileUpload extends React.Component {
  96. state = {
  97. ...FileState
  98. }
  99. upload = async event => {
  100. event.preventDefault()
  101. if (!this.state.file) {
  102. alert('Please select file first.')
  103. return
  104. }
  105. this.setState({ uploading: true })
  106. const data = new FormData()
  107. data.append('file', this.state.file)
  108. data.append('description', this.state.description)
  109. const res = await fetch(`${endpoint}/upload`, {
  110. method: 'POST',
  111. body: data
  112. })
  113. const { error, file } = await res.json()
  114. if (error) {
  115. console.error(error)
  116. alert('Upload error.')
  117. this.setState({ uploading: false })
  118. }
  119. this.setState({ path: `${endpoint}/${file.path}`, uploading: false })
  120. }
  121. selectFile = event => {
  122. const { validity, files } = event.target
  123. this.setState({ file: files[0] })
  124. }
  125. handleChange = event => {
  126. this.setState({ [event.target.name]: event.target.value })
  127. }
  128. render() {
  129. return (
  130. <form>
  131. <fieldset>
  132. <input type='file' name='file' id='file'
  133. onChange={this.selectFile}
  134. />
  135. <textarea name="description" id="description" placeholder="Description"
  136. value={this.state.description}
  137. onChange={this.handleChange}
  138. ></textarea>
  139. <img src={this.state.path} alt={this.state.name} />
  140. <button onClick={this.upload} disabled={this.state.uploading}>Save</button>
  141. </fieldset>
  142. </form>
  143. )
  144. }
  145. }
  146. export default FileUpload
  147. export { FileFields, FileFormFields }