FileUpload.js 4.3 KB

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