diff --git a/examples/bundled-example/index.html b/examples/bundled-example/index.html index 50df14205..5255b3e57 100644 --- a/examples/bundled-example/index.html +++ b/examples/bundled-example/index.html @@ -7,12 +7,15 @@

Uppy is here

- +
-
+ + + +
diff --git a/examples/bundled-example/main.js b/examples/bundled-example/main.js index a77b7ee57..90cc56bfa 100644 --- a/examples/bundled-example/main.js +++ b/examples/bundled-example/main.js @@ -1,10 +1,12 @@ const Uppy = require('../../src/core/Core.js') -const Dashboard = require('../../src/plugins/Dashboard') -const GoogleDrive = require('../../src/plugins/GoogleDrive') -const Dropbox = require('../../src/plugins/Dropbox') -const Webcam = require('../../src/plugins/Webcam') +// const Dashboard = require('../../src/plugins/Dashboard') +// const GoogleDrive = require('../../src/plugins/GoogleDrive') +// const Dropbox = require('../../src/plugins/Dropbox') +// 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') @@ -17,30 +19,44 @@ 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}) - .use(Dashboard, { - trigger: '#uppyModalOpener', - // maxWidth: 350, - // maxHeight: 400, - // inline: false, - // disableStatusBar: true, - // disableInformer: true, - target: 'body', +const uppy = Uppy({ + debug: true, + autoProceed: true, + meta: { + username: 'Artur' + } +}) + // .use(Dashboard, { + // trigger: '#uppyModalOpener', + // // maxWidth: 350, + // // maxHeight: 400, + // inline: false, + // // disableStatusBar: true, + // // disableInformer: true, + // setMetaFromTargetForm: true, + // target: '.MyForm', + // locale: { + // strings: { browse: 'wow' } + // } + // }) + // .use(GoogleDrive, {target: Dashboard, host: 'http://localhost:3020'}) + // .use(Dropbox, {target: Dashboard, host: 'http://localhost:3020'}) + .use(FileInput, { + target: '.MyForm', + replaceTargetContent: false, + setMetaFromTargetForm: true, locale: { - strings: {browse: 'wow'} - } - }) - .use(GoogleDrive, {target: Dashboard, host: 'http://localhost:3020'}) - .use(Dropbox, {target: Dashboard, host: 'http://localhost:3020'}) - // .use(FileInput, {target: '.Uppy', locale: { - // strings: {selectToUpload: 'Выберите файл для загрузки'} - // }}) - // .use(DragDrop, {target: 'body', locale: { - // strings: {chooseFile: 'Выберите файл'} - // }}) + strings: { selectToUpload: 'Выберите файл для загрузки' } + }}) + // .use(DragDrop, { + // target: '.MyForm', + // locale: { + // strings: {chooseFile: 'Выберите файл'} + // }, + // setMetaFromTargetForm: true + // }) // .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}) diff --git a/src/core/Core.js b/src/core/Core.js index f36c34dd5..739d1e2a9 100644 --- a/src/core/Core.js +++ b/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 @@ -134,6 +135,11 @@ class Uppy { } } + setMeta (data) { + const newMeta = Object.assign({}, this.getState().meta, data) + this.setState({meta: newMeta}) + } + updateMeta (data, fileID) { const updatedFiles = Object.assign({}, this.getState().files) const newMeta = Object.assign({}, updatedFiles[fileID].meta, data) @@ -159,9 +165,7 @@ class Uppy { id: fileID, name: fileName, extension: fileExtension || '', - meta: { - name: fileName - }, + meta: Object.assign({}, this.getState().metaData), type: { general: fileTypeGeneral, specific: fileTypeSpecific @@ -187,7 +191,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) { @@ -526,16 +530,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 } diff --git a/src/core/Utils.js b/src/core/Utils.js index 07dfeadf9..5c6713af3 100644 --- a/src/core/Utils.js +++ b/src/core/Utils.js @@ -401,6 +401,27 @@ function findDOMElement (element) { } } +/** +* Get metadata object from a form element +* +* @param {Node|string} element +* @return {Object|null} +*/ + +function getMetaFromForm (element) { + if (!element || element.tagName !== 'FORM') { + console.error('Metadata can only be extracted from form elements') + return null + } + + var formData = new FormData(element) + var result = {} + for (var entry of formData.entries()) { + result[entry[0]] = entry[1] + } + return result +} + function getSocketHost (url) { // get the host domain var regex = /^(?:https?:\/\/|\/\/)?(?:[^@\n]+@)?(?:www\.)?([^\n]+)/ @@ -451,6 +472,7 @@ module.exports = { copyToClipboard, prettyETA, findDOMElement, + getMetaFromForm, getSocketHost, emitSocketProgress } diff --git a/src/plugins/Dashboard/index.js b/src/plugins/Dashboard/index.js index 6bbcb142b..8a1432659 100644 --- a/src/plugins/Dashboard/index.js +++ b/src/plugins/Dashboard/index.js @@ -48,6 +48,7 @@ module.exports = class DashboardUI extends Plugin { semiTransparent: false, defaultTabIcon: defaultTabIcon(), showProgressDetails: false, + setMetaFromTargetForm: false, locale: defaultLocale } @@ -88,7 +89,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 +163,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 +176,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) { + console.error('Dashboard modal trigger not found, you won’t be able to select files. Make sure `trigger` is set correctly in Dashboard options') } document.body.addEventListener('keyup', this.handleEscapeKeyPress) @@ -223,7 +224,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 +304,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 +365,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, @@ -392,6 +393,10 @@ module.exports = class DashboardUI extends Plugin { targets: [] }}) + if (this.opts.setMetaFromTargetForm) { + this.setMetaFromTargetForm() + } + const target = this.opts.target const plugin = this this.target = this.mount(target, plugin) diff --git a/src/plugins/DragDrop/index.js b/src/plugins/DragDrop/index.js index 38078f038..f1c7fd40b 100644 --- a/src/plugins/DragDrop/index.js +++ b/src/plugins/DragDrop/index.js @@ -37,6 +37,7 @@ module.exports = class DragDrop extends Plugin { // Default options const defaultOpts = { target: '.UppyDragDrop', + setMetaFromTargetForm: false, locale: defaultLocale } @@ -143,6 +144,10 @@ module.exports = class DragDrop extends Plugin { } install () { + if (this.opts.setMetaFromTargetForm) { + this.setMetaFromTargetForm() + } + const target = this.opts.target const plugin = this this.target = this.mount(target, plugin) diff --git a/src/plugins/FileInput.js b/src/plugins/FileInput.js index 7d2e4c3a0..05390fa04 100644 --- a/src/plugins/FileInput.js +++ b/src/plugins/FileInput.js @@ -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 = { @@ -23,7 +23,8 @@ module.exports = class FileInput extends Plugin { multipleFiles: true, pretty: true, locale: defaultLocale, - inputName: 'files[]' + inputName: 'files[]', + getMetaDataFromForm: false } // Merge default options with the ones set by user @@ -77,6 +78,10 @@ module.exports = class FileInput extends Plugin { } install () { + if (this.opts.setMetaFromTargetForm) { + this.setMetaFromTargetForm() + } + const target = this.opts.target const plugin = this this.target = this.mount(target, plugin) diff --git a/src/plugins/MetaData.js b/src/plugins/MetaData.js index 41e560ff1..bb10e3fd7 100644 --- a/src/plugins/MetaData.js +++ b/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) } } diff --git a/src/plugins/Plugin.js b/src/plugins/Plugin.js index dcb0c1c4d..01cb35e7d 100644 --- a/src/plugins/Plugin.js +++ b/src/plugins/Plugin.js @@ -1,6 +1,6 @@ const yo = require('yo-yo') const nanoraf = require('nanoraf') -const { findDOMElement } = require('../core/Utils') +const { findDOMElement, getMetaFromForm } = require('../core/Utils') /** * Boilerplate that all Plugins share - and should not be used @@ -89,6 +89,18 @@ module.exports = class Plugin { } } + setMetaFromTargetForm () { + const el = findDOMElement(this.opts.target) + const formMetaData = getMetaFromForm(el) + if (formMetaData) { + this.core.log('Adding metadata from form:') + this.core.log(formMetaData) + this.core.setMeta(formMetaData) + } else { + this.core.log('Couldn’t extract metadata from form') + } + } + // focus () { // return // }