Jelajahi Sumber

Fix yo-yo + Uppy rendering issues, add focus on the first element in Modal tab, refactor getTarget — now called mount

Artur Paikin 9 tahun lalu
induk
melakukan
5eadd138c0

+ 17 - 9
src/core/Core.js

@@ -1,5 +1,6 @@
 import Utils from '../core/Utils'
 import Utils from '../core/Utils'
 import Translator from '../core/Translator'
 import Translator from '../core/Translator'
+import yo from 'yo-yo'
 import ee from 'events'
 import ee from 'events'
 
 
 /**
 /**
@@ -40,6 +41,14 @@ export default class Core {
     // for debugging and testing
     // for debugging and testing
     global.UppyState = this.state
     global.UppyState = this.state
     global.UppyAddFile = this.addFile.bind(this)
     global.UppyAddFile = this.addFile.bind(this)
+
+    this.updateAll = this.updateAll.bind(this)
+    this.setState = this.setState.bind(this)
+    this.getState = this.getState.bind(this)
+    this.use = this.use.bind(this)
+    this.actions = this.actions.bind(this)
+    this.run = this.run.bind(this)
+    this.getPlugin = this.getPlugin.bind(this)
   }
   }
 
 
   /**
   /**
@@ -60,7 +69,8 @@ export default class Core {
    * @param {newState} object
    * @param {newState} object
    */
    */
   setState (newState) {
   setState (newState) {
-    this.log(`Setting state to: ${newState}`)
+    this.log('Setting state to: ')
+    this.log(newState)
     this.state = Object.assign({}, this.state, newState)
     this.state = Object.assign({}, this.state, newState)
     this.updateAll()
     this.updateAll()
   }
   }
@@ -80,6 +90,7 @@ export default class Core {
       const imgSrc = ev.target.result
       const imgSrc = ev.target.result
       const updatedFiles = Object.assign({}, this.state.files)
       const updatedFiles = Object.assign({}, this.state.files)
       updatedFiles[file.id].preview = imgSrc
       updatedFiles[file.id].preview = imgSrc
+      updatedFiles[file.id].previewEl = yo`<img alt="${file.name}" src="${imgSrc}">`
       this.setState({files: updatedFiles})
       this.setState({files: updatedFiles})
     })
     })
     reader.addEventListener('error', (err) => {
     reader.addEventListener('error', (err) => {
@@ -121,9 +132,9 @@ export default class Core {
 
 
     this.setState({files: updatedFiles})
     this.setState({files: updatedFiles})
 
 
-    // if (fileTypeGeneral === 'image') {
-    //   this.addImgPreviewToFile(updatedFiles[fileID])
-    // }
+    if (fileTypeGeneral === 'image') {
+      this.addImgPreviewToFile(updatedFiles[fileID])
+    }
 
 
     if (this.opts.autoProceed) {
     if (this.opts.autoProceed) {
       this.emitter.emit('next')
       this.emitter.emit('next')
@@ -260,7 +271,7 @@ export default class Core {
     if (msg === `${msg}`) {
     if (msg === `${msg}`) {
       console.log(`LOG: ${msg}`)
       console.log(`LOG: ${msg}`)
     } else {
     } else {
-      console.log('LOG')
+      console.log('LOG')
       console.dir(msg)
       console.dir(msg)
     }
     }
     global.uppyLog = global.uppyLog || ''
     global.uppyLog = global.uppyLog || ''
@@ -288,10 +299,7 @@ export default class Core {
  * All preseters(data) --> All acquirers(data) --> All uploaders(data) --> done
  * All preseters(data) --> All acquirers(data) --> All uploaders(data) --> done
  */
  */
   run () {
   run () {
-    this.log({
-      class: this.constructor.name,
-      method: 'run'
-    })
+    this.log('Core is run, initializing actions, installing plugins...')
 
 
     this.actions()
     this.actions()
 
 

+ 12 - 5
src/plugins/DragDrop.js

@@ -36,6 +36,7 @@ export default class DragDrop extends Plugin {
     this.handleDrop = this.handleDrop.bind(this)
     this.handleDrop = this.handleDrop.bind(this)
     this.checkDragDropSupport = this.checkDragDropSupport.bind(this)
     this.checkDragDropSupport = this.checkDragDropSupport.bind(this)
     this.handleInputChange = this.handleInputChange.bind(this)
     this.handleInputChange = this.handleInputChange.bind(this)
+    this.render = this.render.bind(this)
   }
   }
 
 
 /**
 /**
@@ -97,7 +98,13 @@ export default class DragDrop extends Plugin {
   }
   }
 
 
   focus () {
   focus () {
-    this.input.focus()
+    const firstInput = document.querySelector(`${this.target} .UppyDragDrop-focus`)
+
+    // only works for the first time if wrapped in setTimeout for some reason
+    // firstInput.focus()
+    setTimeout(function () {
+      firstInput.focus()
+    }, 10)
   }
   }
 
 
   render (state) {
   render (state) {
@@ -122,7 +129,7 @@ export default class DragDrop extends Plugin {
       <div class="UppyDragDrop-container ${this.isDragDropSupported ? 'is-dragdrop-supported' : ''}">
       <div class="UppyDragDrop-container ${this.isDragDropSupported ? 'is-dragdrop-supported' : ''}">
         <form class="UppyDragDrop-inner"
         <form class="UppyDragDrop-inner"
               onsubmit=${onSubmit}>
               onsubmit=${onSubmit}>
-          <input class="UppyDragDrop-input"
+          <input class="UppyDragDrop-input UppyDragDrop-focus"
                  type="file"
                  type="file"
                  name="files[]"
                  name="files[]"
                  multiple="true"
                  multiple="true"
@@ -144,9 +151,9 @@ export default class DragDrop extends Plugin {
   }
   }
 
 
   install () {
   install () {
-    this.el = this.render(this.core.state)
-    this.target = this.getTarget(this.opts.target, this, this.el, this.render.bind(this))
-    this.input = document.querySelector(`${this.target} .UppyDragDrop-input`)
+    const target = this.opts.target
+    const plugin = this
+    this.target = this.mount(target, plugin)
 
 
     dragDrop(`${this.target} .UppyDragDrop-container`, (files) => {
     dragDrop(`${this.target} .UppyDragDrop-container`, (files) => {
       this.handleDrop(files)
       this.handleDrop(files)

+ 14 - 6
src/plugins/Dummy.js

@@ -19,13 +19,15 @@ export default class Dummy extends Plugin {
     this.opts = Object.assign({}, defaultOptions, opts)
     this.opts = Object.assign({}, defaultOptions, opts)
 
 
     this.strange = yo`<h1>this is strange 1</h1>`
     this.strange = yo`<h1>this is strange 1</h1>`
+    this.render = this.render.bind(this)
+    this.install = this.install.bind(this)
   }
   }
 
 
   render () {
   render () {
-    const bla = yo`<h1>this is strange 2</h1>`
+    const bla = yo`<h2>this is strange 2</h2>`
     return yo`
     return yo`
       <div class="wow-this-works">
       <div class="wow-this-works">
-        <input type="text" value="hello">
+        <input class="UppyDummy-firstInput" type="text" value="hello">
         ${this.strange}
         ${this.strange}
         ${bla}
         ${bla}
       </div>
       </div>
@@ -33,12 +35,18 @@ export default class Dummy extends Plugin {
   }
   }
 
 
   focus () {
   focus () {
-    const firstInput = document.querySelector(`${this.target} *:input[type!=hidden]:first`)
-    firstInput.focus()
+    const firstInput = document.querySelector(`${this.target} .UppyDummy-firstInput`)
+
+    // only works for the first time if wrapped in setTimeout for some reason
+    // firstInput.focus()
+    setTimeout(function () {
+      firstInput.focus()
+    }, 10)
   }
   }
 
 
   install () {
   install () {
-    this.el = this.render()
-    this.target = this.getTarget(this.opts.target, this, this.el, this.render)
+    const target = this.opts.target
+    const plugin = this
+    this.target = this.mount(target, plugin)
   }
   }
 }
 }

+ 12 - 9
src/plugins/GoogleDrive.js

@@ -26,6 +26,7 @@ export default class Google extends Plugin {
     this.renderBrowser = this.renderBrowser.bind(this)
     this.renderBrowser = this.renderBrowser.bind(this)
     this.sortByTitle = this.sortByTitle.bind(this)
     this.sortByTitle = this.sortByTitle.bind(this)
     this.sortByDate = this.sortByDate.bind(this)
     this.sortByDate = this.sortByDate.bind(this)
+    this.render = this.render.bind(this)
 
 
     // set default options
     // set default options
     const defaultOptions = {}
     const defaultOptions = {}
@@ -34,13 +35,14 @@ export default class Google extends Plugin {
     this.opts = Object.assign({}, defaultOptions, opts)
     this.opts = Object.assign({}, defaultOptions, opts)
   }
   }
 
 
-  update (state) {
-    if (typeof this.el === 'undefined') {
-      return
-    }
+  focus () {
+    const firstInput = document.querySelector(`${this.target} .UppyGoogleDrive-focusInput`)
 
 
-    const newEl = this.render(this.core.state)
-    yo.update(this.el, newEl)
+    // only works for the first time if wrapped in setTimeout for some reason
+    // firstInput.focus()
+    setTimeout(function () {
+      firstInput.focus()
+    }, 10)
   }
   }
 
 
   /**
   /**
@@ -402,7 +404,7 @@ export default class Google extends Plugin {
           <div class="row">
           <div class="row">
             <div class="hidden-md-down col-lg-3 col-xl-3">
             <div class="hidden-md-down col-lg-3 col-xl-3">
               <ul class="UppyGoogleDrive-sidebar">
               <ul class="UppyGoogleDrive-sidebar">
-                <li class="UppyGoogleDrive-filter"><input type='text' onkeyup=${this.filterQuery} placeholder="Search.." value=${state.filterInput}/></li>
+                <li class="UppyGoogleDrive-filter"><input class="UppyGoogleDrive-focusInput" type='text' onkeyup=${this.filterQuery} placeholder="Search.." value=${state.filterInput}/></li>
                 <li><button onclick=${this.getSubFolder.bind(this, 'root', 'My Drive')}><img src="https://ssl.gstatic.com/docs/doclist/images/icon_11_collection_list_3.png"/> My Drive</button></li>
                 <li><button onclick=${this.getSubFolder.bind(this, 'root', 'My Drive')}><img src="https://ssl.gstatic.com/docs/doclist/images/icon_11_collection_list_3.png"/> My Drive</button></li>
                 <li><button><img src="https://ssl.gstatic.com/docs/doclist/images/icon_11_shared_collection_list_1.png"/> Shared with me</button></li>
                 <li><button><img src="https://ssl.gstatic.com/docs/doclist/images/icon_11_shared_collection_list_1.png"/> Shared with me</button></li>
                 <li><button onclick=${this.logout}>Logout</button></li>
                 <li><button onclick=${this.logout}>Logout</button></li>
@@ -457,8 +459,9 @@ export default class Google extends Plugin {
       }
       }
     })
     })
 
 
-    this.el = this.render(this.core.state)
-    this.target = this.getTarget(this.opts.target, this, this.el, this.render.bind(this))
+    const target = this.opts.target
+    const plugin = this
+    this.target = this.mount(target, plugin)
 
 
     this.checkAuthentication()
     this.checkAuthentication()
       .then((authenticated) => {
       .then((authenticated) => {

+ 15 - 6
src/plugins/Modal.js

@@ -28,13 +28,19 @@ export default class Modal extends Plugin {
 
 
     this.hideModal = this.hideModal.bind(this)
     this.hideModal = this.hideModal.bind(this)
     this.showModal = this.showModal.bind(this)
     this.showModal = this.showModal.bind(this)
+
+    this.addTarget = this.addTarget.bind(this)
+    this.showTabPanel = this.showTabPanel.bind(this)
+    this.events = this.events.bind(this)
+    this.render = this.render.bind(this)
+    this.install = this.install.bind(this)
   }
   }
 
 
-  addTarget (callerPlugin, render) {
-    const callerPluginId = callerPlugin.constructor.name
-    const callerPluginName = callerPlugin.title || callerPluginId
-    const callerPluginIcon = callerPlugin.icon || this.opts.defaultTabIcon
-    const callerPluginType = callerPlugin.type
+  addTarget (plugin) {
+    const callerPluginId = plugin.constructor.name
+    const callerPluginName = plugin.title || callerPluginId
+    const callerPluginIcon = plugin.icon || this.opts.defaultTabIcon
+    const callerPluginType = plugin.type
 
 
     if (callerPluginType !== 'acquirer' &&
     if (callerPluginType !== 'acquirer' &&
         callerPluginType !== 'progressindicator' &&
         callerPluginType !== 'progressindicator' &&
@@ -49,7 +55,8 @@ export default class Modal extends Plugin {
       name: callerPluginName,
       name: callerPluginName,
       icon: callerPluginIcon,
       icon: callerPluginIcon,
       type: callerPluginType,
       type: callerPluginType,
-      render: render,
+      focus: plugin.focus,
+      render: plugin.render,
       isHidden: true
       isHidden: true
     }
     }
 
 
@@ -71,6 +78,7 @@ export default class Modal extends Plugin {
     const newTargets = modal.targets.map((target) => {
     const newTargets = modal.targets.map((target) => {
       if (target.type === 'acquirer') {
       if (target.type === 'acquirer') {
         if (target.id === id) {
         if (target.id === id) {
+          target.focus()
           return Object.assign({}, target, {
           return Object.assign({}, target, {
             isHidden: false
             isHidden: false
           })
           })
@@ -118,6 +126,7 @@ export default class Modal extends Plugin {
     const newTargets = modal.targets.map((target) => {
     const newTargets = modal.targets.map((target) => {
       if (target.type === 'acquirer' && !found) {
       if (target.type === 'acquirer' && !found) {
         found = true
         found = true
+        target.focus()
 
 
         return Object.assign({}, target, {
         return Object.assign({}, target, {
           isHidden: false
           isHidden: false

+ 15 - 7
src/plugins/Plugin.js

@@ -15,7 +15,11 @@ 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.update = this.update.bind(this)
+    this.mount = this.mount.bind(this)
+    this.focus = this.focus.bind(this)
+    this.install = this.install.bind(this)
   }
   }
 
 
   update () {
   update () {
@@ -35,8 +39,8 @@ export default class Plugin {
    * @param {String|Object} target
    * @param {String|Object} target
    *
    *
    */
    */
-  getTarget (target, caller, el, render) {
-    const callerPluginName = caller.id
+  mount (target, plugin) {
+    const callerPluginName = plugin.id
 
 
     if (typeof target === 'string') {
     if (typeof target === 'string') {
       this.core.log(`Installing ${callerPluginName} to ${target}`)
       this.core.log(`Installing ${callerPluginName} to ${target}`)
@@ -45,16 +49,20 @@ export default class Plugin {
       // if (replaceTargetContent) {
       // if (replaceTargetContent) {
       //   document.querySelector(target).innerHTML = ''
       //   document.querySelector(target).innerHTML = ''
       // }
       // }
-      document.querySelector(target).appendChild(el)
+      const element = plugin.render(this.core.state)
+      document.querySelector(target).appendChild(element)
 
 
       return target
       return target
     } else {
     } else {
-      // TODO: is this the way to roll just to get the plugin name?
+      // TODO: is instantiating the plugin really the way to roll
+      // just to get the plugin name?
       const Target = target
       const Target = target
       const targetPluginName = new Target().id
       const targetPluginName = new Target().id
+
       this.core.log(`Installing ${callerPluginName} to ${targetPluginName}`)
       this.core.log(`Installing ${callerPluginName} to ${targetPluginName}`)
-      let targetPlugin = this.core.getPlugin(targetPluginName)
-      let selectorTarget = targetPlugin.addTarget(caller, render)
+
+      const targetPlugin = this.core.getPlugin(targetPluginName)
+      const selectorTarget = targetPlugin.addTarget(plugin)
 
 
       return selectorTarget
       return selectorTarget
     }
     }

+ 3 - 2
src/plugins/ProgressBar.js

@@ -31,7 +31,8 @@ export default class ProgressBar extends Plugin {
   }
   }
 
 
   install () {
   install () {
-    this.el = this.render(this.core.state)
-    this.target = this.getTarget(this.opts.target, this, this.el, this.render.bind(this))
+    const target = this.opts.target
+    const plugin = this
+    this.target = this.mount(target, plugin)
   }
   }
 }
 }

+ 23 - 20
src/plugins/ProgressDrawer.js

@@ -17,6 +17,8 @@ export default class ProgressDrawer extends Plugin {
 
 
     // merge default options with the ones set by user
     // merge default options with the ones set by user
     this.opts = Object.assign({}, defaultOptions, opts)
     this.opts = Object.assign({}, defaultOptions, opts)
+
+    this.render = this.render.bind(this)
   }
   }
 
 
   drawerItem (file) {
   drawerItem (file) {
@@ -30,27 +32,27 @@ export default class ProgressDrawer extends Plugin {
         <polygon points="2.836,14.708 5.665,11.878 13.415,19.628 26.334,6.712 29.164,9.54 13.415,25.288 "></polygon>
         <polygon points="2.836,14.708 5.665,11.878 13.415,19.628 26.334,6.712 29.164,9.54 13.415,25.288 "></polygon>
       </svg>`
       </svg>`
 
 
+    const fileIcon = yo`
+      <svg width="34" height="44" viewBox="0 0 21 29">
+        <path d="M2.473.31C1.44.31.59 1.21.59 2.307V26.31c0 1.097.85 2 1.883 2H18.71c1.03 0 1.88-.903 1.88-2V7.746a.525.525 0 0 0-.014-.108v-.015a.51.51 0 0 0-.014-.03v-.017a.51.51 0 0 0-.015-.03.482.482 0 0 0-.014-.016v-.015a.482.482 0 0 0-.015-.015.51.51 0 0 0-.014-.03.482.482 0 0 0-.014-.017.51.51 0 0 0-.015-.03.483.483 0 0 0-.03-.03L13.636.45a.47.47 0 0 0-.118-.093.448.448 0 0 0-.044-.015.448.448 0 0 0-.044-.016.448.448 0 0 0-.045-.015.44.44 0 0 0-.073 0H2.474zm0 .99h10.372v4.943c0 1.097.85 2 1.88 2h4.932V26.31c0 .56-.42 1.007-.948 1.007H2.472c-.527 0-.95-.446-.95-1.007V2.308c0-.56.423-1.008.95-1.008zm11.305.667l4.843 4.927.352.357h-4.246c-.527 0-.948-.446-.948-1.007V1.967z"
+              fill="#F6A623"
+              fill-rule="evenodd" />
+        <text font-family="ArialMT, Arial"
+              font-size="5"
+              font-weight="bold"
+              fill="#F6A623"
+              text-anchor="middle"
+              x="11"
+              y="22">
+          ${file.type.specific ? file.type.specific.toUpperCase() : '?'}
+        </text>
+      </svg>
+    `
+
     return yo`<li id="${file.id}" class="UppyProgressDrawer-item"
     return yo`<li id="${file.id}" class="UppyProgressDrawer-item"
                   title="${file.name}">
                   title="${file.name}">
       <div class="UppyProgressDrawer-itemInfo">
       <div class="UppyProgressDrawer-itemInfo">
-        <svg width="34" height="44" viewBox="0 0 21 29">
-          <path d="M2.473.31C1.44.31.59 1.21.59 2.307V26.31c0 1.097.85 2 1.883 2H18.71c1.03 0 1.88-.903 1.88-2V7.746a.525.525 0 0 0-.014-.108v-.015a.51.51 0 0 0-.014-.03v-.017a.51.51 0 0 0-.015-.03.482.482 0 0 0-.014-.016v-.015a.482.482 0 0 0-.015-.015.51.51 0 0 0-.014-.03.482.482 0 0 0-.014-.017.51.51 0 0 0-.015-.03.483.483 0 0 0-.03-.03L13.636.45a.47.47 0 0 0-.118-.093.448.448 0 0 0-.044-.015.448.448 0 0 0-.044-.016.448.448 0 0 0-.045-.015.44.44 0 0 0-.073 0H2.474zm0 .99h10.372v4.943c0 1.097.85 2 1.88 2h4.932V26.31c0 .56-.42 1.007-.948 1.007H2.472c-.527 0-.95-.446-.95-1.007V2.308c0-.56.423-1.008.95-1.008zm11.305.667l4.843 4.927.352.357h-4.246c-.527 0-.948-.446-.948-1.007V1.967z"
-                fill="#F6A623"
-                fill-rule="evenodd" />
-          <text font-family="ArialMT, Arial"
-                font-size="5"
-                font-weight="bold"
-                fill="#F6A623"
-                text-anchor="middle"
-                x="11"
-                y="22">
-            ${file.type.specific ? file.type.specific.toUpperCase() : '?'}
-          </text>
-          </svg>
-          ${file.type.general === 'image'
-            ? yo`<img class="UppyProgressDrawer-itemIcon" alt="${file.name}" src="${file.preview}">`
-            : yo`<span class="UppyProgressDrawer-itemType">${file.type.specific}</span>`
-          }
+          ${file.type.general === 'image' ? file.previewEl : fileIcon}
       </div>
       </div>
       <div class="UppyProgressDrawer-itemInner">
       <div class="UppyProgressDrawer-itemInner">
         <h4 class="UppyProgressDrawer-itemName">
         <h4 class="UppyProgressDrawer-itemName">
@@ -127,7 +129,8 @@ export default class ProgressDrawer extends Plugin {
   }
   }
 
 
   install () {
   install () {
-    this.el = this.render(this.core.state)
-    this.target = this.getTarget(this.opts.target, this, this.el, this.render.bind(this))
+    const target = this.opts.target
+    const plugin = this
+    this.target = this.mount(target, plugin)
   }
   }
 }
 }

+ 1 - 1
website/src/examples/modal/app.es6

@@ -1,4 +1,4 @@
-import Uppy from 'uppy/core'
+import Uppy from '../../../../src/core/Core.js'
 import Dummy from '../../../../src/plugins/Dummy.js'
 import Dummy from '../../../../src/plugins/Dummy.js'
 import Tus10 from '../../../../src/plugins/Tus10.js'
 import Tus10 from '../../../../src/plugins/Tus10.js'
 import Modal from '../../../../src/plugins/Modal.js'
 import Modal from '../../../../src/plugins/Modal.js'