Просмотр исходного кода

Merge branch 'master' of https://github.com/transloadit/uppy

Harry Hedger 9 лет назад
Родитель
Сommit
b4f297c695

+ 2 - 2
.babelrc

@@ -1,4 +1,4 @@
 {
 {
-  "presets": ["es2015"],
-  "plugins": ["transform-object-assign"]
+  "presets": ["es2015-loose"],
+  "plugins": ["transform-object-assign", "es6-promise"]
 }
 }

+ 3 - 3
CHANGELOG.md

@@ -58,10 +58,10 @@ Theme: Acceptance tests and Google Drive Polish
 
 
 - [ ] drive: possible UI polish (@hedgerh)
 - [ ] drive: possible UI polish (@hedgerh)
 - [ ] drive: write files to filesystem correctly (@hedgerh)
 - [ ] drive: write files to filesystem correctly (@hedgerh)
-- [ ] test: Fix 15s timeout image.jpg (@arturi)
-- [ ] test: Sign up for Browserstack.com Live account so we can check ourselves what gives and verify saucelabs isn't to blame (@arturi)
+- [x] test: Fix 15s timeout image.jpg (@arturi)
+- [x] test: Sign up for Browserstack.com Live account so we can check ourselves what gives and verify saucelabs isn't to blame (@arturi) <-- Turns out, Saucelabs already does that for us
 - [ ] test: Get tests to pass Latest version of Internet Explorer (Windows 10), Safari (OSX), Firefox (Linux), Opera (Windows 10) (@arturi)
 - [ ] test: Get tests to pass Latest version of Internet Explorer (Windows 10), Safari (OSX), Firefox (Linux), Opera (Windows 10) (@arturi)
-- [ ] test: Get saucelabs to show what gives (errors, screenshots, anything) (@arturi)
+- [x] test: Get saucelabs to show what gives (errors, screenshots, anything) (@arturi)
 - [x] build: sourcemaps for local development (@arturi) <-- Not adding it in production to save the extra request. For local dev, this was added already via Browserify
 - [x] build: sourcemaps for local development (@arturi) <-- Not adding it in production to save the extra request. For local dev, this was added already via Browserify
 - [x] core: Add polyfill for `fetch` (@hedgerh)
 - [x] core: Add polyfill for `fetch` (@hedgerh)
 - [x] core: Apply plugins when DOM elements aren't static (#25)
 - [x] core: Apply plugins when DOM elements aren't static (#25)

+ 8 - 4
package.json

@@ -55,21 +55,25 @@
     "babel-core": "6.7.4",
     "babel-core": "6.7.4",
     "babel-eslint": "6.0.2",
     "babel-eslint": "6.0.2",
     "babel-loader": "6.2.4",
     "babel-loader": "6.2.4",
+    "babel-plugin-es6-promise": "1.0.0",
     "babel-plugin-transform-object-assign": "6.5.0",
     "babel-plugin-transform-object-assign": "6.5.0",
+    "babel-plugin-transform-proto-to-assign": "6.8.0",
     "babel-polyfill": "6.7.4",
     "babel-polyfill": "6.7.4",
-    "babel-preset-es2015": "^6.0.0",
+    "babel-preset-es2015": "6.6.0",
+    "babel-preset-es2015-loose": "7.0.0",
     "babel-register": "6.7.2",
     "babel-register": "6.7.2",
     "babelify": "7.2.0",
     "babelify": "7.2.0",
     "browser-sync": "2.10.0",
     "browser-sync": "2.10.0",
     "browserify": "12.0.1",
     "browserify": "12.0.1",
     "chalk": "1.1.1",
     "chalk": "1.1.1",
     "disc": "1.3.2",
     "disc": "1.3.2",
+    "es6-promise": "3.1.2",
     "eslint": "2.7.0",
     "eslint": "2.7.0",
     "eslint-config-standard": "5.1.0",
     "eslint-config-standard": "5.1.0",
     "eslint-plugin-promise": "1.1.0",
     "eslint-plugin-promise": "1.1.0",
     "eslint-plugin-standard": "1.3.2",
     "eslint-plugin-standard": "1.3.2",
     "fakefile": "0.0.5",
     "fakefile": "0.0.5",
-    "isomorphic-fetch": "^2.2.1",
+    "isomorphic-fetch": "2.2.1",
     "multi-glob": "1.0.1",
     "multi-glob": "1.0.1",
     "nock": "^8.0.0",
     "nock": "^8.0.0",
     "node-fetch": "^1.5.0",
     "node-fetch": "^1.5.0",
@@ -77,7 +81,7 @@
     "node-sass": "3.4.2",
     "node-sass": "3.4.2",
     "nodemon": "1.8.1",
     "nodemon": "1.8.1",
     "parallelshell": "2.0.0",
     "parallelshell": "2.0.0",
-    "selenium-webdriver": "^2.52.0",
+    "selenium-webdriver": "2.52.0",
     "tap-spec": "^4.1.1",
     "tap-spec": "^4.1.1",
     "tape": "4.4.0",
     "tape": "4.4.0",
     "uppy-server": "0.0.3",
     "uppy-server": "0.0.3",
@@ -86,7 +90,7 @@
   "dependencies": {
   "dependencies": {
     "drag-drop": "2.11.0",
     "drag-drop": "2.11.0",
     "tus-js-client": "1.1.3",
     "tus-js-client": "1.1.3",
-    "whatwg-fetch": "^1.0.0",
+    "whatwg-fetch": "1.0.0",
     "yo-yo": "1.1.1"
     "yo-yo": "1.1.1"
   }
   }
 }
 }

+ 5 - 3
src/core/Core.js

@@ -187,9 +187,10 @@ export default class Core {
   use (Plugin, opts) {
   use (Plugin, opts) {
     // Instantiate
     // Instantiate
     const plugin = new Plugin(this, opts)
     const plugin = new Plugin(this, opts)
+    const pluginName = Utils.getFnName(plugin.constructor)
     this.plugins[plugin.type] = this.plugins[plugin.type] || []
     this.plugins[plugin.type] = this.plugins[plugin.type] || []
 
 
-    if (!plugin.constructor.name) {
+    if (!pluginName) {
       throw new Error('Your plugin must have a name')
       throw new Error('Your plugin must have a name')
     }
     }
 
 
@@ -197,7 +198,7 @@ export default class Core {
       throw new Error('Your plugin must have a type')
       throw new Error('Your plugin must have a type')
     }
     }
 
 
-    let existsPluginAlready = this.getPlugin(plugin.constructor.name)
+    let existsPluginAlready = this.getPlugin(pluginName)
     if (existsPluginAlready) {
     if (existsPluginAlready) {
       let msg = `Already found a plugin named '${existsPluginAlready.name}'.
       let msg = `Already found a plugin named '${existsPluginAlready.name}'.
         Tried to use: '${plugin.constructor.name}'.
         Tried to use: '${plugin.constructor.name}'.
@@ -221,7 +222,8 @@ export default class Core {
   getPlugin (name) {
   getPlugin (name) {
     let foundPlugin = false
     let foundPlugin = false
     this.iteratePlugins((plugin) => {
     this.iteratePlugins((plugin) => {
-      if (plugin.constructor.name === name) {
+      const pluginName = Utils.getFnName(plugin.constructor)
+      if (pluginName === name) {
         foundPlugin = plugin
         foundPlugin = plugin
         return false
         return false
       }
       }

+ 22 - 7
src/core/Utils.js

@@ -32,12 +32,12 @@ function promiseWaterfall (methods) {
  * @param {requestCallback} cb
  * @param {requestCallback} cb
  * @return {String}
  * @return {String}
  */
  */
-function addListenerMulti (el, events, cb) {
-  const eventsArray = events.split(' ')
-  for (let event in eventsArray) {
-    el.addEventListener(eventsArray[event], cb, false)
-  }
-}
+// function addListenerMulti (el, events, cb) {
+//   const eventsArray = events.split(' ')
+//   for (let event in eventsArray) {
+//     el.addEventListener(eventsArray[event], cb, false)
+//   }
+// }
 
 
 /**
 /**
  * Shallow flatten nested arrays.
  * Shallow flatten nested arrays.
@@ -103,10 +103,25 @@ function extend (...objs) {
   return Object.assign.apply(this, [{}].concat(objs))
   return Object.assign.apply(this, [{}].concat(objs))
 }
 }
 
 
+/**
+ * Takes function or class, returns its name.
+ * Because IE doesn’t support `constructor.name`.
+ * https://gist.github.com/dfkaye/6384439, http://stackoverflow.com/a/15714445
+ *
+ * @param {Object} fn — function
+ *
+ */
+function getFnName (fn) {
+  var f = typeof fn === 'function'
+  var s = f && ((fn.name && ['', fn.name]) || fn.toString().match(/function ([^\(]+)/))
+  return (!f && 'not a function') || (s && s[1] || 'anonymous')
+}
+
 export default {
 export default {
   promiseWaterfall,
   promiseWaterfall,
   generateFileID,
   generateFileID,
-  addListenerMulti,
+  getFnName,
+  // addListenerMulti,
   every,
   every,
   flatten,
   flatten,
   groupBy,
   groupBy,

+ 7 - 9
src/plugins/DragDrop.js

@@ -10,7 +10,8 @@ export default class DragDrop extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
     this.type = 'acquirer'
     this.type = 'acquirer'
-    this.name = 'Drag & Drop'
+    this.id = 'DragDrop'
+    this.title = 'Drag & Drop'
     this.icon = yo`
     this.icon = yo`
       <svg class="UppyModalTab-icon" width="28" height="28" viewBox="0 0 16 16">
       <svg class="UppyModalTab-icon" width="28" height="28" viewBox="0 0 16 16">
         <path d="M15.982 2.97c0-.02 0-.02-.018-.037 0-.017-.017-.035-.035-.053 0 0 0-.018-.02-.018-.017-.018-.034-.053-.052-.07L13.19.123c-.017-.017-.034-.035-.07-.053h-.018c-.018-.017-.035-.017-.053-.034h-.02c-.017 0-.034-.018-.052-.018h-6.31a.415.415 0 0 0-.446.426V11.11c0 .25.196.446.445.446h8.89A.44.44 0 0 0 16 11.11V3.023c-.018-.018-.018-.035-.018-.053zm-2.65-1.46l1.157 1.157h-1.157V1.51zm1.78 9.157h-8V.89h5.332v2.22c0 .25.196.446.445.446h2.22v7.11z"/>
         <path d="M15.982 2.97c0-.02 0-.02-.018-.037 0-.017-.017-.035-.035-.053 0 0 0-.018-.02-.018-.017-.018-.034-.053-.052-.07L13.19.123c-.017-.017-.034-.035-.07-.053h-.018c-.018-.017-.035-.017-.053-.034h-.02c-.017 0-.034-.018-.052-.018h-6.31a.415.415 0 0 0-.446.426V11.11c0 .25.196.446.445.446h8.89A.44.44 0 0 0 16 11.11V3.023c-.018-.018-.018-.035-.018-.053zm-2.65-1.46l1.157 1.157h-1.157V1.51zm1.78 9.157h-8V.89h5.332v2.22c0 .25.196.446.445.446h2.22v7.11z"/>
@@ -76,11 +77,12 @@ export default class DragDrop extends Plugin {
     })
     })
   }
   }
 
 
-  handleInputChange () {
+  handleInputChange (ev) {
     this.core.log('All right, something selected through input...')
     this.core.log('All right, something selected through input...')
+    const files = ev.target.files
 
 
-    const newFiles = Object.keys(this.input.files).map((key) => {
-      this.input.files[key]
+    const newFiles = Object.keys(files).map((file) => {
+      return files[file]
     })
     })
 
 
     this.core.emitter.emit('file-add', {
     this.core.emitter.emit('file-add', {
@@ -107,10 +109,6 @@ export default class DragDrop extends Plugin {
       this.core.emitter.emit('next')
       this.core.emitter.emit('next')
     }
     }
 
 
-    const onChange = (ev) => {
-      this.handleInputChange()
-    }
-
     const onSubmit = (ev) => {
     const onSubmit = (ev) => {
       ev.preventDefault()
       ev.preventDefault()
     }
     }
@@ -123,7 +121,7 @@ export default class DragDrop extends Plugin {
                  type="file"
                  type="file"
                  name="files[]"
                  name="files[]"
                  multiple="true"
                  multiple="true"
-                 onchange=${onChange} />
+                 onchange=${this.handleInputChange.bind(this)} />
           <label class="UppyDragDrop-label" onclick=${onSelect}>
           <label class="UppyDragDrop-label" onclick=${onSelect}>
             <strong>${this.core.i18n('chooseFile')}</strong>
             <strong>${this.core.i18n('chooseFile')}</strong>
             <span class="UppyDragDrop-dragText">${this.core.i18n('orDragDrop')}</span>
             <span class="UppyDragDrop-dragText">${this.core.i18n('orDragDrop')}</span>

+ 3 - 0
src/plugins/Dropbox.js

@@ -4,6 +4,9 @@ export default class Dropbox extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
     this.type = 'acquirer'
     this.type = 'acquirer'
+    this.id = 'Dropbox'
+    this.title = 'Dropbox'
+
     this.authenticate = this.authenticate.bind(this)
     this.authenticate = this.authenticate.bind(this)
     this.connect = this.connect.bind(this)
     this.connect = this.connect.bind(this)
     this.render = this.render.bind(this)
     this.render = this.render.bind(this)

+ 8 - 2
src/plugins/Dummy.js

@@ -9,7 +9,8 @@ export default class Dummy extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
     this.type = 'acquirer'
     this.type = 'acquirer'
-    this.name = 'Dummy'
+    this.id = 'Dummy'
+    this.title = 'Dummy'
 
 
     // set default options
     // set default options
     const defaultOptions = {}
     const defaultOptions = {}
@@ -18,7 +19,7 @@ export default class Dummy extends Plugin {
     this.opts = Object.assign({}, defaultOptions, opts)
     this.opts = Object.assign({}, defaultOptions, opts)
   }
   }
 
 
-  render () {
+  render (state) {
     return yo`
     return yo`
       <div class="wow-this-works">
       <div class="wow-this-works">
         <input type="text" value="hello">
         <input type="text" value="hello">
@@ -27,6 +28,11 @@ export default class Dummy extends Plugin {
     `
     `
   }
   }
 
 
+  focus () {
+    const firstInput = document.querySelector(`${this.target} *:input[type!=hidden]:first`)
+    firstInput.focus()
+  }
+
   install (state) {
   install (state) {
     this.el = this.render(this.core.state)
     this.el = this.render(this.core.state)
     this.target = this.getTarget(this.opts.target, this, this.el, this.render.bind(this))
     this.target = this.getTarget(this.opts.target, this, this.el, this.render.bind(this))

+ 2 - 0
src/plugins/Formtag.js

@@ -4,6 +4,8 @@ import yo from 'yo-yo'
 export default class Formtag extends Plugin {
 export default class Formtag extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
+    this.id = 'Formtag'
+    this.title = 'Formtag'
     this.type = 'acquirer'
     this.type = 'acquirer'
 
 
     // Default options
     // Default options

+ 4 - 2
src/plugins/GoogleDrive.js

@@ -7,14 +7,16 @@ export default class Google extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
     this.type = 'acquirer'
     this.type = 'acquirer'
-    this.files = []
-    this.name = 'Google Drive'
+    this.id = 'GoogleDriver'
+    this.titile = 'Google Drive'
     this.icon = yo`
     this.icon = yo`
       <svg class="UppyModalTab-icon" width="28" height="28" viewBox="0 0 16 16">
       <svg class="UppyModalTab-icon" width="28" height="28" viewBox="0 0 16 16">
         <path d="M2.955 14.93l2.667-4.62H16l-2.667 4.62H2.955zm2.378-4.62l-2.666 4.62L0 10.31l5.19-8.99 2.666 4.62-2.523 4.37zm10.523-.25h-5.333l-5.19-8.99h5.334l5.19 8.99z"/>
         <path d="M2.955 14.93l2.667-4.62H16l-2.667 4.62H2.955zm2.378-4.62l-2.666 4.62L0 10.31l5.19-8.99 2.666 4.62-2.523 4.37zm10.523-.25h-5.333l-5.19-8.99h5.334l5.19 8.99z"/>
       </svg>
       </svg>
     `
     `
 
 
+    this.files = []
+
     this.filterQuery = this.filterQuery.bind(this)
     this.filterQuery = this.filterQuery.bind(this)
     this.getFile = this.getFile.bind(this)
     this.getFile = this.getFile.bind(this)
     this.getFolder = this.getFolder.bind(this)
     this.getFolder = this.getFolder.bind(this)

+ 2 - 0
src/plugins/Modal.js

@@ -8,6 +8,8 @@ import yo from 'yo-yo'
 export default class Modal extends Plugin {
 export default class Modal extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
+    this.id = 'Modal'
+    this.title = 'Modal'
     this.type = 'orchestrator'
     this.type = 'orchestrator'
 
 
     // set default options
     // set default options

+ 2 - 1
src/plugins/Multipart.js

@@ -4,7 +4,8 @@ export default class Multipart extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
     this.type = 'uploader'
     this.type = 'uploader'
-    this.name = 'Multipart'
+    this.id = 'Multipart'
+    this.title = 'Multipart'
 
 
     // Default options
     // Default options
     const defaultOptions = {
     const defaultOptions = {

+ 8 - 4
src/plugins/Plugin.js

@@ -1,4 +1,5 @@
 import yo from 'yo-yo'
 import yo from 'yo-yo'
+import Utils from '../core/Utils'
 
 
 /**
 /**
  * Boilerplate that all Plugins share - and should not be used
  * Boilerplate that all Plugins share - and should not be used
@@ -15,7 +16,7 @@ export default class Plugin {
     this.core = core
     this.core = core
     this.opts = opts
     this.opts = opts
     this.type = 'none'
     this.type = 'none'
-    this.name = this.constructor.name
+    // this.name = this.constructor.name
   }
   }
 
 
   update () {
   update () {
@@ -36,8 +37,10 @@ export default class Plugin {
    *
    *
    */
    */
   getTarget (target, caller, el, render) {
   getTarget (target, caller, el, render) {
+    const callerPluginName = Utils.getFnName(caller.constructor)
+
     if (typeof target === 'string') {
     if (typeof target === 'string') {
-      this.core.log(`Installing ${caller.name} to ${target}`)
+      this.core.log(`Installing ${callerPluginName} to ${target}`)
 
 
       // clear everything inside the target selector
       // clear everything inside the target selector
       // if (replaceTargetContent) {
       // if (replaceTargetContent) {
@@ -47,8 +50,9 @@ export default class Plugin {
 
 
       return target
       return target
     } else {
     } else {
-      this.core.log(`Installing ${caller.name} to ${target.name}`)
-      let targetPlugin = this.core.getPlugin(target.name)
+      const targetPluginName = Utils.getFnName(target)
+      this.core.log(`Installing ${callerPluginName} to ${targetPluginName}`)
+      let targetPlugin = this.core.getPlugin(targetPluginName)
       let selectorTarget = targetPlugin.addTarget(caller, render)
       let selectorTarget = targetPlugin.addTarget(caller, render)
 
 
       return selectorTarget
       return selectorTarget

+ 2 - 1
src/plugins/Present.js

@@ -7,8 +7,9 @@ import Plugin from './Plugin'
 export default class Present extends Plugin {
 export default class Present extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
+    this.id = 'Present'
+    this.title = 'Present'
     this.type = 'presenter'
     this.type = 'presenter'
-    this.name = 'Present'
 
 
     // set default options
     // set default options
     const defaultOptions = {
     const defaultOptions = {

+ 2 - 0
src/plugins/ProgressBar.js

@@ -8,6 +8,8 @@ import yo from 'yo-yo'
 export default class ProgressBar extends Plugin {
 export default class ProgressBar extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
+    this.id = 'ProgressBar'
+    this.title = 'Progress Bar'
     this.type = 'progressindicator'
     this.type = 'progressindicator'
 
 
     // set default options
     // set default options

+ 2 - 1
src/plugins/ProgressDrawer.js

@@ -8,7 +8,8 @@ import yo from 'yo-yo'
 export default class ProgressDrawer extends Plugin {
 export default class ProgressDrawer extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
-    this.name = 'Progress Drawer'
+    this.id = 'ProgressDrawer'
+    this.title = 'Progress Drawer'
     this.type = 'progressindicator'
     this.type = 'progressindicator'
 
 
     // set default options
     // set default options

+ 2 - 0
src/plugins/Spinner.js

@@ -8,6 +8,8 @@ export default class Spinner extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
     this.type = 'progressindicator'
     this.type = 'progressindicator'
+    this.id = 'Spinner'
+    this.title = 'Spinner'
 
 
     // set default options
     // set default options
     const defaultOptions = {}
     const defaultOptions = {}

+ 2 - 0
src/plugins/TransloaditBasic.js

@@ -6,6 +6,8 @@ export default class TransloaditBasic extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
     this.type = 'presetter'
     this.type = 'presetter'
+    this.id = 'TransloaditBasic'
+    this.title = 'Transloadit Basic'
     this.core
     this.core
       .use(DragDrop, {modal: true, wait: true})
       .use(DragDrop, {modal: true, wait: true})
       .use(Tus10, {endpoint: 'http://master.tus.io:8080'})
       .use(Tus10, {endpoint: 'http://master.tus.io:8080'})

+ 2 - 1
src/plugins/Tus10.js

@@ -9,7 +9,8 @@ export default class Tus10 extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
     this.type = 'uploader'
     this.type = 'uploader'
-    this.type = 'Tus'
+    this.id = 'Tus'
+    this.title = 'Tus'
 
 
     // set default options
     // set default options
     const defaultOptions = {}
     const defaultOptions = {}

+ 0 - 211
src/plugins/_OldModal.js

@@ -1,211 +0,0 @@
-import Plugin from './Plugin'
-import Utils from '../core/Utils'
-
-/**
- * Modal
- *
- */
-export default class Modal extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
-    this.type = 'orchestrator'
-
-    // set default options
-    const defaultOptions = {
-      defaultTabIcon: `
-        <svg class="UppyModalTab-icon" width="28" height="28" viewBox="0 0 101 58" xmlns="http://www.w3.org/2000/svg">
-          <path d="M17.582.3L.915 41.713l32.94 13.295L17.582.3zm83.333 41.414L67.975 55.01 84.25.3l16.665 41.414zm-48.998 5.403L63.443 35.59H38.386l11.527 11.526v5.905l-3.063 3.32 1.474 1.36 2.59-2.806 2.59 2.807 1.475-1.357-3.064-3.32v-5.906zm16.06-26.702c-3.973 0-7.194-3.22-7.194-7.193 0-3.973 3.222-7.193 7.193-7.193 3.974 0 7.193 3.22 7.193 7.19 0 3.974-3.22 7.194-7.195 7.194zM70.48 8.682c-.737 0-1.336.6-1.336 1.337 0 .736.6 1.335 1.337 1.335.738 0 1.338-.598 1.338-1.336 0-.74-.6-1.338-1.338-1.338zM33.855 20.415c-3.973 0-7.193-3.22-7.193-7.193 0-3.973 3.22-7.193 7.195-7.193 3.973 0 7.192 3.22 7.192 7.19 0 3.974-3.22 7.194-7.192 7.194zM36.36 8.682c-.737 0-1.336.6-1.336 1.337 0 .736.6 1.335 1.337 1.335.738 0 1.338-.598 1.338-1.336 0-.74-.598-1.338-1.337-1.338z"/>
-        </svg>
-      `,
-      panelSelectorPrefix: 'UppyModalContent-panel'
-    }
-
-    this.tabPanels = []
-
-    this.isModalVisible = false
-
-    // merge default options with the ones set by user
-    this.opts = Object.assign({}, defaultOptions, opts)
-
-    this.initTabs = this.initTabs.bind(this)
-    this.hideModal = this.hideModal.bind(this)
-    this.showModal = this.showModal.bind(this)
-    this.install = this.install.bind(this)
-  }
-
-  prepareTarget (callerPlugin) {
-    const callerPluginId = callerPlugin.constructor.name
-    const callerPluginName = callerPlugin.name || callerPluginId
-    const callerPluginIcon = callerPlugin.icon || this.opts.defaultTabIcon
-
-    switch (callerPlugin.type) {
-      case 'progressindicator':
-        return '.UppyModal-progressBarContainer'
-      case 'presenter':
-        return '.UppyModal-presenter'
-      case 'acquirer':
-
-        // add tab panel, where plugin will render
-        const modalContent = document.querySelector('.UppyModalContent')
-        const nodeForPlugin = document.createElement('div')
-
-        modalContent.appendChild(nodeForPlugin)
-        nodeForPlugin.outerHTML = `
-          <div class="UppyModalContent-panel ${this.opts.panelSelectorPrefix}--${callerPluginId}"
-               role="tabpanel"
-               aria-hidden="true">
-          </div>`
-
-        // add tab switch button
-        const modalTabs = document.querySelector('.UppyModalTabs')
-        const modalTab = document.createElement('div')
-
-        modalTabs.appendChild(modalTab)
-        modalTab.outerHTML = `
-          <li class="UppyModalTab">
-            <button class="UppyModalTab-btn"
-                    role="tab"
-                    aria-controls="${callerPluginId}"
-                    data-open="${this.opts.panelSelectorPrefix}--${callerPluginId}">
-              ${callerPluginIcon}
-              <span class="UppyModalTab-name">${callerPluginName}</span>
-            </button>
-          </li>`
-
-        return `.${this.opts.panelSelectorPrefix}--${callerPluginId}`
-      default:
-        let msg = 'Error: Modal can only be used by plugins of types: acquirer, progressindicator'
-        this.core.log(msg)
-        break
-    }
-  }
-
-  allDone () {
-    this.hideAllTabPanels()
-  }
-
-  render () {
-    // http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog
-
-    return `
-      <div class="UppyModal"
-           aria-hidden="true"
-           aria-labelledby="modalTitle"
-           aria-describedby="modalDescription"
-           role="dialog">
-        <div class="UppyModal-overlay js-UppyModal-close" tabindex="-1"></div>
-        <div class="UppyModal-inner">
-          <button class="UppyModal-close js-UppyModal-close" title="Close Uppy modal">×</button>
-
-          <ul class="UppyModalTabs" role="tablist"></ul>
-
-          <div class="UppyModalContent">
-            <div class="UppyModal-presenter"></div>
-            <div class="UppyModal-progress">
-              <div class="UppyModal-progressBarContainer"></div>
-            </div>
-          </div>
-
-        </div>
-      </div>
-    `
-  }
-
-  hideModal () {
-    this.isModalVisible = false
-    this.modalEl.setAttribute('aria-hidden', 'true')
-    this.core.emitter.emit('reset')
-  }
-
-  showModal () {
-    this.isModalVisible = true
-    this.modalEl.removeAttribute('aria-hidden')
-    this.initTabs()
-  }
-
-  hideAllTabPanels () {
-    this.tabPanels.forEach((tabPanel) => tabPanel.setAttribute('aria-hidden', true))
-    this.tabs.forEach((tab) => tab.removeAttribute('aria-selected'))
-  }
-
-  showTabPanel (pluginSelector, pluginName) {
-    this.hideAllTabPanels()
-
-    const tab = document.querySelector(`[aria-controls="${pluginName}"]`)
-    const tabPanel = document.querySelector(`.${pluginSelector}`)
-
-    tabPanel.removeAttribute('aria-hidden')
-    tab.setAttribute('aria-selected', 'true')
-
-    this.core.log(pluginName)
-    this.core.getPlugin(pluginName).focus()
-  }
-
-  events () {
-    // Listen for allDone event to close all tabs
-    this.core.emitter.on('allDone', () => this.allDone())
-
-    // this.core.emitter.on('file-add', (data) => {
-    //   this.nextButton.classList.add('is-active')
-    //
-    //   const files = Object.keys(this.core.state.selectedFiles)
-    //   const selectedFileCount = files.length
-    //   this.nextButton.innerHTML = this.core.i18n('uploadFiles', {'smart_count': selectedFileCount})
-    // })
-
-    // this.core.emitter.on('reset', () => this.nextButton.classList.remove('is-active'))
-
-    // Close the Modal on esc key press
-    document.body.addEventListener('keyup', (event) => {
-      if (event.keyCode === 27) {
-        this.hideModal()
-      }
-    })
-
-    // Close on click outside modal or close buttons
-    document.addEventListener('click', (e) => {
-      if (e.target.classList.contains('js-UppyModal-close')) {
-        this.hideModal()
-      }
-    })
-  }
-
-  initTabs () {
-    // Get all tab buttons and loop through them, to determine which
-    // tabPanel they trigger, set events
-    this.tabs = Utils.qsa('.UppyModalTab-btn')
-    this.tabs.forEach((tab) => {
-      const pluginSelector = tab.getAttribute('data-open')
-      const pluginName = tab.getAttribute('aria-controls')
-      const tabPanel = document.querySelector(`.${pluginSelector}`)
-      this.tabPanels.push(tabPanel)
-
-      tab.addEventListener('click', (event) => {
-        event.preventDefault()
-        this.showTabPanel(pluginSelector, pluginName)
-      })
-    })
-
-    // Select first tab right away
-    this.tabs[0].click()
-  }
-
-  install () {
-    const node = document.createElement('div')
-    document.body.appendChild(node)
-    node.outerHTML = this.render()
-    this.modalEl = document.querySelector('.UppyModal')
-
-    // Add events for opening and closing the modal
-    // const hideModalTrigger = Utils.qsa('.js-UppyModal-close')
-    this.showModalTrigger = document.querySelector(this.opts.trigger)
-    this.showModalTrigger.addEventListener('click', this.showModal)
-
-    // When `next` (upload) button is clicked, emit `next` event,
-    // so that plugins can proceed to the next stage
-    // this.nextButton = document.querySelector('.UppyModal-next')
-    // this.nextButton.addEventListener('click', () => this.core.emitter.emit('next'))
-
-    this.events()
-  }
-}

+ 0 - 62
src/plugins/_OldProgressBar.js

@@ -1,62 +0,0 @@
-import Plugin from './Plugin'
-
-/**
- * Progress bar
- *
- */
-export default class ProgressBar extends Plugin {
-  constructor (core, opts) {
-    super(core, opts)
-    this.type = 'progressindicator'
-
-    // set default options
-    const defaultOptions = {}
-
-    // merge default options with the ones set by user
-    this.opts = Object.assign({}, defaultOptions, opts)
-  }
-
-  setProgress (percentage) {
-    this.progressBarContainerEl.classList.add('is-active')
-    this.progressBarPercentageEl.innerHTML = `${percentage}%`
-    this.progressBarInnerEl.setAttribute('style', `width: ${percentage}%`)
-  }
-
-  init () {
-    const caller = this
-    this.target = this.getTarget(this.opts.target, caller)
-
-    this.uploadButton = document.querySelector('.js-UppyModal-next')
-    this.progressBarContainerEl = document.querySelector(this.target)
-    this.progressBarContainerEl.innerHTML = `<div class="UppyProgressBar">
-        <div class="UppyProgressBar-inner"></div>
-        <div class="UppyProgressBar-percentage"></div>
-      </div>`
-    this.progressBarPercentageEl = document.querySelector(`${this.target} .UppyProgressBar-percentage`)
-    this.progressBarInnerEl = document.querySelector(`${this.target} .UppyProgressBar-inner`)
-  }
-
-  events () {
-    // When there is some progress (uploading), emit this event to adjust progressbar
-    this.core.emitter.on('upload-progress', (data) => {
-      const percentage = data.percentage
-      const uploader = data.uploader
-      this.core.log(
-        `progress is: ${percentage}, set by ${uploader.constructor.name}`
-      )
-      // this.setProgress(percentage)
-    })
-
-    this.core.emitter.on('reset', (data) => {
-      this.progressBarContainerEl.classList.remove('is-active')
-      this.uploadButton.classList.remove('is-active')
-      this.uploadButton.innerHTML = this.core.i18n('upload')
-    })
-  }
-
-  install () {
-    this.init()
-    this.events()
-    return
-  }
-}

+ 22 - 18
test/acceptance/index.js

@@ -14,8 +14,8 @@ require('babel-register')
 var webdriver = require('selenium-webdriver')
 var webdriver = require('selenium-webdriver')
 var remote = require('selenium-webdriver/remote')
 var remote = require('selenium-webdriver/remote')
 
 
-var username = process.env.USERNAME
-var accessKey = process.env.ACCESS_KEY
+var username = process.env.SAUCELABS_USERNAME
+var accessKey = process.env.SAUCELABS_ACCESS_KEY
 
 
 // if accessKey is supplied as env variable, this is a remote Saucelabs test
 // if accessKey is supplied as env variable, this is a remote Saucelabs test
 var isRemoteTest = accessKey ? true : ''
 var isRemoteTest = accessKey ? true : ''
@@ -24,33 +24,37 @@ var host = isRemoteTest ? 'http://uppy.io' : 'http://localhost:4000'
 // FYI: old Chrome on Windows XP,
 // FYI: old Chrome on Windows XP,
 // Opera 12 on Linux — didn’t pass
 // Opera 12 on Linux — didn’t pass
 var platforms = [
 var platforms = [
-  // { browser: 'Opera', version: '12', os: 'Linux' },
+  // { browser: 'Opera', version: '12.15', os: 'Linux' },
   // { browser: 'iphone', version: '9.2', os: 'OS X 10.10' },
   // { browser: 'iphone', version: '9.2', os: 'OS X 10.10' },
-  { browser: 'firefox', version: '34.0', os: 'Windows 7' },
-  { browser: 'chrome', version: '48.0', os: 'Windows XP' }
+  // { browser: 'Safari', version: '8.0', os: 'OS X 10.10' },
+  { browser: 'Internet Explorer', version: '10.0', os: 'Windows 8' },
+  { browser: 'Internet Explorer', version: '11.103', os: 'Windows 10' },
+  { browser: 'Firefox', version: '34.0', os: 'Windows 7' },
+  { browser: 'Chrome', version: '48.0', os: 'Windows XP' },
+  { browser: 'Firefox', version: '38.0', os: 'Linux' }
 ]
 ]
 
 
 var tests = [
 var tests = [
   require('./multipart.spec.js'),
   require('./multipart.spec.js'),
-  require('./i18n.spec.js')
-  // require('./dragdrop.spec.js')
+  require('./i18n.spec.js'),
+  require('./dragdrop.spec.js')
 ]
 ]
 
 
 function buildDriver (platform) {
 function buildDriver (platform) {
   var driver
   var driver
   if (isRemoteTest) {
   if (isRemoteTest) {
     driver = new webdriver
     driver = new webdriver
-        .Builder()
-        .withCapabilities({
-          'browserName': platform.browser,
-          'platform': platform.os,
-          'version': platform.version,
-          'username': username,
-          'accessKey': accessKey
-        })
-        .usingServer('http://' + username + ':' + accessKey +
-                    '@ondemand.saucelabs.com:80/wd/hub')
-        .build()
+      .Builder()
+      .withCapabilities({
+        'browserName': platform.browser,
+        'platform': platform.os,
+        'version': platform.version,
+        'username': username,
+        'accessKey': accessKey
+      })
+      .usingServer('http://' + username + ':' + accessKey +
+                   '@ondemand.saucelabs.com:80/wd/hub')
+      .build()
     driver.setFileDetector(new remote.FileDetector())
     driver.setFileDetector(new remote.FileDetector())
   } else {
   } else {
     driver = new webdriver
     driver = new webdriver

+ 1 - 0
test/unit/mocks/plugin-acquirer1.js

@@ -4,6 +4,7 @@ export default class TestSelector1 extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
     this.type = 'acquirer'
     this.type = 'acquirer'
+    this.id = 'TestSelector1'
     this.name = this.constructor.name
     this.name = this.constructor.name
   }
   }
 
 

+ 1 - 0
test/unit/mocks/plugin-acquirer2.js

@@ -4,6 +4,7 @@ export default class TestSelector2 extends Plugin {
   constructor (core, opts) {
   constructor (core, opts) {
     super(core, opts)
     super(core, opts)
     this.type = 'acquirer'
     this.type = 'acquirer'
+    this.id = 'TestSelector2'
     this.name = this.constructor.name
     this.name = this.constructor.name
   }
   }
 
 

+ 1 - 0
website/themes/uppy/layout/partials/social.ejs

@@ -7,4 +7,5 @@ allowtransparency="true" frameborder="0" scrolling="0" width="100" height="20"><
    <span class="wrapper">
    <span class="wrapper">
      <a href="https://travis-ci.org/transloadit/uppy"><img src="https://travis-ci.org/transloadit/uppy.svg" alt="Build Status"></a>
      <a href="https://travis-ci.org/transloadit/uppy"><img src="https://travis-ci.org/transloadit/uppy.svg" alt="Build Status"></a>
    </span>
    </span>
+  </li>
 </ul>
 </ul>