Browse Source

Merge pull request #238 from transloadit/feature/form-meta

Extract metadata from form, closes #153
Artur Paikin 7 years ago
parent
commit
d7a8b93a09

+ 5 - 2
examples/bundled-example/index.html

@@ -7,12 +7,15 @@
   </head>
   <body>
     <h1>Uppy is here</h1>
-    <button id="uppyModalOpener">Open Modal</button>
+    <button id="uppyModalOpener">Choose Files</button>
 
     <div class="Uppy">
-      <form class="UppyForm" action="/">
+      <form class="MyForm" action="/">
         <input type="file" />
+        <input type="hidden" name="bla" value="12333">
+        <input type="text" name="yo" value="1">
         <button type="submit">Upload</button>
+        <input type="submit">
       </form>
     </div>
 

+ 16 - 6
examples/bundled-example/main.js

@@ -6,6 +6,8 @@ const Instagram = require('../../src/plugins/Instagram')
 const Webcam = require('../../src/plugins/Webcam')
 const Tus10 = require('../../src/plugins/Tus10')
 // const Multipart = require('../../src/plugins/Multipart')
+// const DragDrop = require('../../src/plugins/FileInput')
+const FileInput = require('../../src/plugins/FileInput')
 const MetaData = require('../../src/plugins/MetaData')
 // const Informer = require('../../src/plugins/Informer')
 // const StatusBar = require('../../src/plugins/StatusBar')
@@ -18,21 +20,30 @@ const TUS_ENDPOINT = PROTOCOL + '://master.tus.io/files/'
 // import MagicLog from '../../src/plugins/MagicLog'
 // import PersistentState from '../../src/plugins/PersistentState'
 
-const uppy = Uppy({debug: true, autoProceed: false})
+const uppy = Uppy({
+  debug: true,
+  autoProceed: true,
+  meta: {
+    username: 'John'
+  }
+})
   .use(Dashboard, {
     trigger: '#uppyModalOpener',
     // maxWidth: 350,
     // maxHeight: 400,
-    // inline: false,
+    inline: false,
     // disableStatusBar: true,
     // disableInformer: true,
-    target: 'body',
+    setMetaFromTargetForm: true,
+    target: '.MyForm',
     locale: {
-      strings: {browse: 'wow'}
+      strings: { browse: 'wow' }
     }
   })
   .use(GoogleDrive, {target: Dashboard, host: 'http://localhost:3020'})
   .use(Dropbox, {target: Dashboard, host: 'http://localhost:3020'})
+  .use(GoogleDrive, {target: Dashboard, host: 'http://localhost:3020'})
+  .use(Dropbox, {target: Dashboard, host: 'http://localhost:3020'})
   .use(Instagram, {target: Dashboard, host: 'http://localhost:3020'})
   // .use(FileInput, {target: '.Uppy', locale: {
   //   strings: {selectToUpload: 'Выберите файл для загрузки'}
@@ -41,8 +52,7 @@ const uppy = Uppy({debug: true, autoProceed: false})
   //   strings: {chooseFile: 'Выберите файл'}
   // }})
   // .use(ProgressBar, {target: 'body'})
-  // .use(dummy)
-  .use(Webcam, {target: Dashboard})
+  // .use(Webcam, {target: Dashboard})
   // .use(Multipart, {endpoint: '//api2.transloadit.com'})
   .use(Tus10, {endpoint: TUS_ENDPOINT, resume: true})
   // .use(Informer, {target: Dashboard})

+ 5 - 0
package-lock.json

@@ -3449,6 +3449,11 @@
       "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=",
       "dev": true
     },
+    "get-form-data": {
+      "version": "1.2.5",
+      "resolved": "https://registry.npmjs.org/get-form-data/-/get-form-data-1.2.5.tgz",
+      "integrity": "sha1-yQ+bix0tvbRulIDoi6xjKT/msYI="
+    },
     "get-stdin": {
       "version": "4.0.1",
       "resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",

+ 1 - 0
package.json

@@ -76,6 +76,7 @@
   "dependencies": {
     "drag-drop": "2.13.2",
     "es6-promise": "3.2.1",
+    "get-form-data": "^1.2.5",
     "lodash.throttle": "4.1.1",
     "namespace-emitter": "1.0.0",
     "nanoraf": "3.0.1",

+ 17 - 9
src/core/Core.js

@@ -53,7 +53,8 @@ class Uppy {
       capabilities: {
         resumableUploads: false
       },
-      totalProgress: 0
+      totalProgress: 0,
+      meta: Object.assign({}, this.opts.meta)
     }
 
     // for debugging and testing
@@ -142,6 +143,13 @@ class Uppy {
     }
   }
 
+  setMeta (data) {
+    const newMeta = Object.assign({}, this.getState().meta, data)
+    this.log('Adding metadata:')
+    this.log(data)
+    this.setState({meta: newMeta})
+  }
+
   updateMeta (data, fileID) {
     const updatedFiles = Object.assign({}, this.getState().files)
     const newMeta = Object.assign({}, updatedFiles[fileID].meta, data)
@@ -167,9 +175,7 @@ class Uppy {
         id: fileID,
         name: fileName,
         extension: fileExtension || '',
-        meta: {
-          name: fileName
-        },
+        meta: Object.assign({}, this.getState().meta),
         type: {
           general: fileTypeGeneral,
           specific: fileTypeSpecific
@@ -195,7 +201,7 @@ class Uppy {
       updatedFiles[fileID] = newFile
       this.setState({files: updatedFiles})
 
-      this.bus.emit('file-added', fileID)
+      this.bus.emit('core:file-added', fileID)
       this.log(`Added file: ${fileName}, ${fileID}, mime type: ${fileType}`)
 
       if (this.opts.autoProceed && !this.scheduledAutoProceed) {
@@ -535,16 +541,18 @@ class Uppy {
     if (!this.opts.debug) {
       return
     }
+
+    if (type === 'error') {
+      console.error(`LOG: ${msg}`)
+      return
+    }
+
     if (msg === `${msg}`) {
       console.log(`LOG: ${msg}`)
     } else {
       console.dir(msg)
     }
 
-    if (type === 'error') {
-      console.error(`LOG: ${msg}`)
-    }
-
     global.uppyLog = global.uppyLog + '\n' + 'DEBUG LOG: ' + msg
   }
 

+ 14 - 12
src/plugins/Dashboard/index.js

@@ -42,12 +42,14 @@ module.exports = class DashboardUI extends Plugin {
     // set default options
     const defaultOptions = {
       target: 'body',
+      getMetaFromForm: true,
       inline: false,
       width: 750,
       height: 550,
       semiTransparent: false,
       defaultTabIcon: defaultTabIcon(),
       showProgressDetails: false,
+      setMetaFromTargetForm: true,
       locale: defaultLocale
     }
 
@@ -88,7 +90,7 @@ module.exports = class DashboardUI extends Plugin {
     if (callerPluginType !== 'acquirer' &&
         callerPluginType !== 'progressindicator' &&
         callerPluginType !== 'presenter') {
-      let msg = 'Error: Modal can only be used by plugins of types: acquirer, progressindicator, presenter'
+      let msg = 'Dashboard: Modal can only be used by plugins of types: acquirer, progressindicator, presenter'
       this.core.log(msg)
       return
     }
@@ -162,9 +164,9 @@ module.exports = class DashboardUI extends Plugin {
     // focus on modal inner block
     this.target.querySelector('.UppyDashboard-inner').focus()
 
-    this.updateDashboardElWidth()
+    // this.updateDashboardElWidth()
     // to be sure, sometimes when the function runs, container size is still 0
-    setTimeout(this.updateDashboardElWidth, 300)
+    setTimeout(this.updateDashboardElWidth, 500)
   }
 
   // Close the Modal on esc key press
@@ -175,14 +177,14 @@ module.exports = class DashboardUI extends Plugin {
   }
 
   initEvents () {
-    // const dashboardEl = this.target.querySelector(`${this.opts.target} .UppyDashboard`)
-
     // Modal open button
     const showModalTrigger = findDOMElement(this.opts.trigger)
     if (!this.opts.inline && showModalTrigger) {
       showModalTrigger.addEventListener('click', this.showModal)
-    } else {
-      this.core.log('Modal trigger wasn’t found')
+    }
+
+    if (!this.opts.inline && !showModalTrigger) {
+      this.core.log('Dashboard modal trigger not found, you won’t be able to select files. Make sure `trigger` is set correctly in Dashboard options', 'error')
     }
 
     document.body.addEventListener('keyup', this.handleEscapeKeyPress)
@@ -223,7 +225,7 @@ module.exports = class DashboardUI extends Plugin {
 
   updateDashboardElWidth () {
     const dashboardEl = this.target.querySelector('.UppyDashboard-inner')
-    // console.log(dashboardEl.offsetWidth)
+    this.core.log(`Dashboard width: ${dashboardEl.offsetWidth}`)
 
     const modal = this.core.getState().modal
     this.core.setState({
@@ -303,9 +305,9 @@ module.exports = class DashboardUI extends Plugin {
       return target.type === 'progressindicator'
     })
 
-    const addFile = (file) => {
-      this.core.emitter.emit('core:file-add', file)
-    }
+    // const addFile = (file) => {
+    //   this.core.emitter.emit('core:file-add', file)
+    // }
 
     const removeFile = (fileID) => {
       this.core.emitter.emit('core:file-remove', fileID)
@@ -364,7 +366,7 @@ module.exports = class DashboardUI extends Plugin {
       i18n: this.containerWidth,
       pauseAll: this.pauseAll,
       resumeAll: this.resumeAll,
-      addFile: addFile,
+      addFile: this.core.addFile,
       removeFile: removeFile,
       info: info,
       metaFields: state.metaFields,

+ 1 - 0
src/plugins/DragDrop/index.js

@@ -37,6 +37,7 @@ module.exports = class DragDrop extends Plugin {
     // Default options
     const defaultOpts = {
       target: '.UppyDragDrop',
+      getMetaFromForm: true,
       locale: defaultLocale
     }
 

+ 4 - 3
src/plugins/FileInput.js

@@ -1,5 +1,5 @@
 const Plugin = require('./Plugin')
-const Utils = require('../core/Utils')
+const { toArray } = require('../core/Utils')
 const Translator = require('../core/Translator')
 const html = require('yo-yo')
 
@@ -7,7 +7,7 @@ module.exports = class FileInput extends Plugin {
   constructor (core, opts) {
     super(core, opts)
     this.id = 'FileInput'
-    this.title = 'FileInput'
+    this.title = 'File Input'
     this.type = 'acquirer'
 
     const defaultLocale = {
@@ -19,6 +19,7 @@ module.exports = class FileInput extends Plugin {
     // Default options
     const defaultOptions = {
       target: '.UppyForm',
+      getMetaFromForm: true,
       replaceTargetContent: true,
       multipleFiles: true,
       pretty: true,
@@ -42,7 +43,7 @@ module.exports = class FileInput extends Plugin {
   handleInputChange (ev) {
     this.core.log('All right, something selected through input...')
 
-    const files = Utils.toArray(ev.target.files)
+    const files = toArray(ev.target.files)
 
     files.forEach((file) => {
       this.core.emitter.emit('core:file-add', {

+ 2 - 2
src/plugins/MetaData.js

@@ -38,7 +38,7 @@ module.exports = class MetaData extends Plugin {
       metaFields: metaFields
     })
 
-    this.core.emitter.on('file-added', this.handleFileAdded)
+    this.core.emitter.on('core:file-added', this.handleFileAdded)
   }
 
   install () {
@@ -46,6 +46,6 @@ module.exports = class MetaData extends Plugin {
   }
 
   uninstall () {
-    this.core.emitter.off('file-added', this.handleFileAdded)
+    this.core.emitter.off('core:file-added', this.handleFileAdded)
   }
 }

+ 7 - 5
src/plugins/Plugin.js

@@ -1,6 +1,7 @@
 const yo = require('yo-yo')
 const nanoraf = require('nanoraf')
 const { findDOMElement } = require('../core/Utils')
+const getFormData = require('get-form-data')
 
 /**
  * Boilerplate that all Plugins share - and should not be used
@@ -23,7 +24,6 @@ module.exports = class Plugin {
 
     this.update = this.update.bind(this)
     this.mount = this.mount.bind(this)
-    // this.focus = this.focus.bind(this)
     this.install = this.install.bind(this)
     this.uninstall = this.uninstall.bind(this)
   }
@@ -59,6 +59,12 @@ module.exports = class Plugin {
     if (targetElement) {
       this.core.log(`Installing ${callerPluginName} to a DOM element`)
 
+      // attempt to extract meta from form element
+      if (this.opts.getMetaFromForm && targetElement.nodeName === 'FORM') {
+        const formMeta = getFormData(targetElement)
+        this.core.setMeta(formMeta)
+      }
+
       // clear everything inside the target container
       if (this.opts.replaceTargetContent) {
         targetElement.innerHTML = ''
@@ -89,10 +95,6 @@ module.exports = class Plugin {
     }
   }
 
-  // focus () {
-  //   return
-  // }
-
   install () {
     return
   }