Преглед на файлове

Merge pull request #474 from transloadit/fix/remote-uploads

Fix remote uploads
Artur Paikin преди 7 години
родител
ревизия
452f8c66c5
променени са 7 файла, в които са добавени 130 реда и са изтрити 116 реда
  1. 2 0
      CHANGELOG.md
  2. 4 14
      examples/cdn-example/index.html
  3. 21 25
      src/core/Core.js
  4. 0 1
      src/plugins/Provider/view/index.js
  5. 92 74
      src/plugins/Tus.js
  6. 5 0
      src/plugins/XHRUpload.js
  7. 6 2
      website/src/docs/tus.md

+ 2 - 0
CHANGELOG.md

@@ -52,6 +52,7 @@ Ideas that will be planned and find their way into a release at one point
 - [ ] test: add tests for `npm pack`
 - [ ] test: add deepFreeze to test that state in not mutated anywhere by accident #320
 - [ ] audio: audio recording similar to Webcam #143
+- [ ] add  typescript definitions and JSDoc everywhere? https://github.com/Microsoft/TypeScript/wiki/Type-Checking-JavaScript-Files
 
 ## 1.0 Goals
 
@@ -95,6 +96,7 @@ To be released: 2018-01-26.
 - [ ] s3: rename `AWS S3` to something more general if it works with Google Cloud Storage too? See #460
 - [ ] dashboard: try adding optional whitelabel “powered by uppy.io” (@arturi, @nqst)
 - [ ] dashboard: option for Boolean metadata #454 (@arturi)
+- [ ] dashboard: use more accessible tip lib: https://github.com/ghosh/microtip
 - [ ] transloadit: add error reporting
 - [ ] importurl: new plugin that imports files from urls (@arturi, @ifedapoolarewaju)
 - [ ] core: queue preview generation #431

+ 4 - 14
examples/cdn-example/index.html

@@ -10,25 +10,15 @@
     <button id="uppyModalOpener">Open Modal</button>
     <script src="https://unpkg.com/uppy/dist/uppy.min.js"></script>
     <script>
-      const Dashboard = Uppy.Dashboard
-      const Webcam = Uppy.Webcam
-      const Tus = Uppy.Tus
-
       const uppy = Uppy.Core({debug: true, autoProceed: false})
-      .use(Uppy.Dashboard, {
-        trigger: '#uppyModalOpener',
-        target: 'body'
-      })
-      .use(Webcam, {target: Dashboard})
-      .use(Tus, {endpoint: 'https://master.tus.io/files/', resume: true})
-
-      uppy.run()
+        .use(Uppy.Dashboard, { trigger: '#uppyModalOpener' })
+        .use(Uppy.Webcam, {target: Uppy.Dashboard})
+        .use(Uppy.Tus, { endpoint: 'https://master.tus.io/files/' })
+        .run()
 
       uppy.on('success', (fileCount) => {
         console.log(`${fileCount} files uploaded`)
       })
-
-      document.querySelector('#uppyModalOpener').click()
     </script>
   </body>
 </html>

+ 21 - 25
src/core/Core.js

@@ -9,9 +9,11 @@ const DefaultStore = require('../store/DefaultStore')
 // const deepFreeze = require('deep-freeze-strict')
 
 /**
- * Main Uppy core
+ * Uppy Core module.
+ * Manages plugins, state updates, acts as an event bus,
+ * adds/removes files and metadata.
  *
- * @param {object} opts general options, like locales, to show modal or not to show
+ * @param {object} opts — Uppy options
  */
 class Uppy {
   constructor (opts) {
@@ -69,7 +71,6 @@ class Uppy {
     this.getPlugin = this.getPlugin.bind(this)
     this.setFileMeta = this.setFileMeta.bind(this)
     this.setFileState = this.setFileState.bind(this)
-    // this._initSocket = this._initSocket.bind(this)
     this.log = this.log.bind(this)
     this.info = this.info.bind(this)
     this.hideInfo = this.hideInfo.bind(this)
@@ -77,6 +78,7 @@ class Uppy {
     this.removeFile = this.removeFile.bind(this)
     this.pauseResume = this.pauseResume.bind(this)
     this._calculateProgress = this._calculateProgress.bind(this)
+    this.updateOnlineStatus = this.updateOnlineStatus.bind(this)
     this.resetProgress = this.resetProgress.bind(this)
 
     this.pauseAll = this.pauseAll.bind(this)
@@ -86,7 +88,6 @@ class Uppy {
     this.retryUpload = this.retryUpload.bind(this)
     this.upload = this.upload.bind(this)
 
-    // this.bus = this.emitter = ee()
     this.emitter = ee()
     this.on = this.emitter.on.bind(this.emitter)
     this.off = this.emitter.off.bind(this.emitter)
@@ -128,7 +129,8 @@ class Uppy {
   }
 
   /**
-   * Iterate on all plugins and run `update` on them. Called each time state changes
+   * Iterate on all plugins and run `update` on them.
+   * Called each time state changes.
    *
    */
   updateAll (state) {
@@ -147,19 +149,21 @@ class Uppy {
   }
 
   /**
-   * Returns current state
+   * Returns current state.
    */
   getState () {
     return this.store.getState()
   }
 
-  // Back compat.
+  /**
+  * Back compat for when this.state is used instead of this.getState().
+  */
   get state () {
     return this.getState()
   }
 
   /**
-  * Shorthand to set state for a specific file
+  * Shorthand to set state for a specific file.
   */
   setFileState (fileID, state) {
     this.setState({
@@ -268,7 +272,7 @@ class Uppy {
   }
 
   /**
-  * Check if minNumberOfFiles restriction is reached before uploading
+  * Check if minNumberOfFiles restriction is reached before uploading.
   *
   * @return {boolean}
   * @private
@@ -284,7 +288,7 @@ class Uppy {
 
   /**
   * Check if file passes a set of restrictions set in options: maxFileSize,
-  * maxNumberOfFiles and allowedFileTypes
+  * maxNumberOfFiles and allowedFileTypes.
   *
   * @param {object} file object to check
   * @return {boolean}
@@ -429,7 +433,7 @@ class Uppy {
     })
 
     removeUploads.forEach((uploadID) => {
-      this.removeUpload(uploadID)
+      this._removeUpload(uploadID)
     })
 
     this._calculateTotalProgress()
@@ -773,7 +777,7 @@ class Uppy {
   }
 
   /**
-   * Registers a plugin with Core
+   * Registers a plugin with Core.
    *
    * @param {Class} Plugin object
    * @param {Object} options object that will be passed to Plugin later
@@ -817,7 +821,7 @@ class Uppy {
   }
 
   /**
-   * Find one Plugin by name
+   * Find one Plugin by name.
    *
    * @param string name description
    */
@@ -834,7 +838,7 @@ class Uppy {
   }
 
   /**
-   * Iterate through all `use`d plugins
+   * Iterate through all `use`d plugins.
    *
    * @param function method description
    */
@@ -877,7 +881,7 @@ class Uppy {
 
   /**
   * Set info message in `state.info`, so that UI plugins like `Informer`
-  * can display the message
+  * can display the message.
   *
   * @param {string} msg Message to be displayed by the informer
   */
@@ -950,16 +954,8 @@ class Uppy {
     }
   }
 
-  // _initSocket (opts) {
-  //   if (!this.socket) {
-  //     this.socket = new UppySocket(opts)
-  //   }
-
-  //   return this.socket
-  // }
-
   /**
-   * Initializes actions, installs all plugins (by iterating on them and calling `install`), sets options
+   * Initializes actions.
    *
    */
   run () {
@@ -1111,7 +1107,7 @@ class Uppy {
       Object.keys(this.getState().files).forEach((fileID) => {
         const file = this.getFile(fileID)
 
-        if (!file.progress.uploadStarted || file.isRemote) {
+        if (!file.progress.uploadStarted) {
           waitingFileIDs.push(file.id)
         }
       })

+ 0 - 1
src/plugins/Provider/view/index.js

@@ -426,7 +426,6 @@ module.exports = class View {
    * for all of them, depending on current file state.
    */
   toggleCheckbox (e, file) {
-    console.log(e, e.shiftKey)
     e.stopPropagation()
     e.preventDefault()
     let { folders, files, filterInput } = this.plugin.getPluginState()

+ 92 - 74
src/plugins/Tus.js

@@ -116,8 +116,6 @@ module.exports = class Tus extends Plugin {
    * @returns {Promise}
    */
   upload (file, current, total) {
-    this.uppy.log(`uploading ${current} of ${total}`)
-
     this.resetUploaderReferences(file.id)
 
     // Create a new tus upload
@@ -208,93 +206,109 @@ module.exports = class Tus extends Plugin {
     return new Promise((resolve, reject) => {
       this.uppy.log(file.remote.url)
       if (file.serverToken) {
-        this.connectToServerSocket(file)
-      } else {
-        let endpoint = this.opts.endpoint
-        if (file.tus && file.tus.endpoint) {
-          endpoint = file.tus.endpoint
+        return this.connectToServerSocket(file)
+          .then(() => resolve())
+          .catch(reject)
+      }
+
+      let endpoint = this.opts.endpoint
+      if (file.tus && file.tus.endpoint) {
+        endpoint = file.tus.endpoint
+      }
+
+      this.uppy.emit('upload-started', file.id)
+
+      fetch(file.remote.url, {
+        method: 'post',
+        credentials: 'include',
+        headers: {
+          'Accept': 'application/json',
+          'Content-Type': 'application/json'
+        },
+        body: JSON.stringify(Object.assign({}, file.remote.body, {
+          endpoint,
+          protocol: 'tus',
+          size: file.data.size,
+          metadata: file.meta
+        }))
+      })
+      .then((res) => {
+        if (res.status < 200 || res.status > 300) {
+          return reject(res.statusText)
         }
 
-        this.uppy.emit('upload-started', file.id)
-
-        fetch(file.remote.url, {
-          method: 'post',
-          credentials: 'include',
-          headers: {
-            'Accept': 'application/json',
-            'Content-Type': 'application/json'
-          },
-          body: JSON.stringify(Object.assign({}, file.remote.body, {
-            endpoint,
-            protocol: 'tus',
-            size: file.data.size,
-            metadata: file.meta
-          }))
-        })
-        .then((res) => {
-          if (res.status < 200 || res.status > 300) {
-            return reject(res.statusText)
-          }
-
-          res.json().then((data) => {
-            const token = data.token
-            this.uppy.setFileState(file.id, { serverToken: token })
-            file = this.getFile(file.id)
-            this.connectToServerSocket(file)
-            resolve()
-          })
+        return res.json().then((data) => {
+          this.uppy.setFileState(file.id, { serverToken: data.token })
+          file = this.getFile(file.id)
+          return file
         })
-      }
+      })
+      .then((file) => {
+        return this.connectToServerSocket(file)
+      })
+      .then(() => {
+        resolve()
+      })
+      .catch((err) => {
+        reject(new Error(err))
+      })
     })
   }
 
   connectToServerSocket (file) {
-    const token = file.serverToken
-    const host = getSocketHost(file.remote.host)
-    const socket = new UppySocket({ target: `${host}/api/${token}` })
-    this.uploaderSockets[file.id] = socket
-    this.uploaderEvents[file.id] = createEventTracker(this.uppy)
+    return new Promise((resolve, reject) => {
+      const token = file.serverToken
+      const host = getSocketHost(file.remote.host)
+      const socket = new UppySocket({ target: `${host}/api/${token}` })
+      this.uploaderSockets[file.id] = socket
+      this.uploaderEvents[file.id] = createEventTracker(this.uppy)
 
-    this.onFileRemove(file.id, () => socket.send('pause', {}))
+      this.onFileRemove(file.id, () => {
+        socket.send('pause', {})
+        resolve(`upload ${file.id} was removed`)
+      })
 
-    this.onPause(file.id, (isPaused) => {
-      isPaused ? socket.send('pause', {}) : socket.send('resume', {})
-    })
+      this.onPause(file.id, (isPaused) => {
+        isPaused ? socket.send('pause', {}) : socket.send('resume', {})
+      })
 
-    this.onPauseAll(file.id, () => socket.send('pause', {}))
+      this.onPauseAll(file.id, () => socket.send('pause', {}))
 
-    this.onCancelAll(file.id, () => socket.send('pause', {}))
+      this.onCancelAll(file.id, () => socket.send('pause', {}))
 
-    this.onResumeAll(file.id, () => {
-      if (file.error) {
-        socket.send('pause', {})
-      }
-      socket.send('resume', {})
-    })
+      this.onResumeAll(file.id, () => {
+        if (file.error) {
+          socket.send('pause', {})
+        }
+        socket.send('resume', {})
+      })
 
-    this.onRetry(file.id, () => {
-      socket.send('pause', {})
-      socket.send('resume', {})
-    })
+      this.onRetry(file.id, () => {
+        socket.send('pause', {})
+        socket.send('resume', {})
+      })
 
-    this.onRetryAll(file.id, () => {
-      socket.send('pause', {})
-      socket.send('resume', {})
-    })
+      this.onRetryAll(file.id, () => {
+        socket.send('pause', {})
+        socket.send('resume', {})
+      })
 
-    if (file.isPaused) {
-      socket.send('pause', {})
-    }
+      if (file.isPaused) {
+        socket.send('pause', {})
+      }
 
-    socket.on('progress', (progressData) => emitSocketProgress(this, progressData, file))
+      socket.on('progress', (progressData) => emitSocketProgress(this, progressData, file))
 
-    socket.on('error', (errData) => {
-      this.uppy.emit('core:upload-error', file.id, new Error(errData.error))
-    })
+      socket.on('error', (errData) => {
+        this.uppy.emit('upload-error', file.id, new Error(errData.error))
+        reject(new Error(errData.error))
+      })
 
-    socket.on('success', (data) => {
-      this.uppy.emit('upload-success', file.id, data, data.url)
-      this.resetUploaderReferences(file.id)
+      socket.on('success', (data) => {
+        this.uppy.emit('upload-success', file.id, data, data.url)
+        this.resetUploaderReferences(file.id)
+        resolve()
+      })
     })
   }
 
@@ -381,10 +395,14 @@ module.exports = class Tus extends Plugin {
 
       if (file.error) {
         return Promise.reject(new Error(file.error))
-      } else if (!file.isRemote) {
-        return this.upload(file, current, total)
-      } else {
+      }
+
+      this.uppy.log(`uploading ${current} of ${total}`)
+
+      if (file.isRemote) {
         return this.uploadRemote(file, current, total)
+      } else {
+        return this.upload(file, current, total)
       }
     })
 

+ 5 - 0
src/plugins/XHRUpload.js

@@ -251,6 +251,11 @@ module.exports = class XHRUpload extends Plugin {
             socket.close()
             return resolve()
           })
+
+          socket.on('error', (errData) => {
+            this.uppy.emit('upload-error', file.id, new Error(errData.error))
+            reject(new Error(errData.error))
+          })
         })
       })
     })

+ 6 - 2
website/src/docs/tus.md

@@ -9,6 +9,7 @@ The Tus plugin brings [tus.io](http://tus.io) resumable file uploading to Uppy b
 
 ```js
 uppy.use(Tus, {
+  endpoint: 'https://master.tus.io/files/', // use your tus endpoint here
   resume: true,
   autoRetry: true,
   retryDelays: [0, 1000, 3000, 5000]
@@ -17,8 +18,11 @@ uppy.use(Tus, {
 
 ## Options
 
-The Tus plugin supports all of [tus-js-client][]'s options.
-Additionally:
+The Tus plugin supports all of [tus-js-client][]’s options. Additionally:
+
+### `endpoint: ''`
+
+URL to upload to, where your tus.io server is running.
 
 ### `autoRetry: true`