mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-23 18:29:09 +00:00
Merge branch 'master' into fix/storeOptions
This commit is contained in:
commit
bf694a855e
38 changed files with 4919 additions and 395 deletions
10
CHANGELOG.md
10
CHANGELOG.md
|
|
@ -86,7 +86,7 @@ What we need to do to release Uppy 1.0
|
|||
- [ ] core: research !important styles to be immune to any environment/page. Maybe use smth like `postcss-safe-important`. Or increase specificity (with .Uppy) (@arturi)
|
||||
- [ ] test: add https://github.com/pa11y/pa11y for automated accessibility testing (@arturi)
|
||||
- [ ] test: add tests for `npm install uppy` and running in different browsers, the real world use case (@arturi)
|
||||
- [ ] core: Uppy ID per instance
|
||||
- [x] core: Uppy ID per instance (@goto-bus-stop)
|
||||
- [ ] core: allow setting custom `id` for plugins: https://github.com/transloadit/uppy/pull/328#issuecomment-328242214 (@arturi)
|
||||
- [ ] core: move `setPluginState` to Plugin class ? (@goto-bus-stop)
|
||||
- [ ] add `FormEncapsulator`: a plugin that is used in conjunction with any other acquirer, responsible for injecting any result (like from Transloadit plugin) back into the form (jquery-sdk includes the whole Assembly Status JSON in a hidden field i think)
|
||||
|
|
@ -105,7 +105,13 @@ Theme: React and Retry
|
|||
- [ ] core: retry or show error when upload can’t start / fails (offline, wrong endpoint) — now it just sits there; add error in file progress state, UI, question mark button (@arturi @goto-bus-stop)
|
||||
- [ ] core: improve and merge in the React PR (@arturi @goto-bus-stop)
|
||||
- [ ] goldenretriver: add “ghost” files (@arturi @goto-bus-stop)
|
||||
- [ ] dashboard: expose/document show/hide/isOpen API (@arturi)
|
||||
- [ ] core: remove unused bootstrap styles (#329 / @arturi)
|
||||
- [x] core: experiment with yo-yo --> preact and picodom (#297 / @arturi)
|
||||
- [x] dashboard: fix FileItem source icon position and copy (@arturi)
|
||||
- [x] dashboard: expose and document the show/hide/isOpen API (@arturi)
|
||||
- [x] dashboard: allow multiple `triggers` of the same class `.open-uppy` (@arturi)
|
||||
- [x] core: Handle sync returns and throws in possibly-async function options (#315 / @goto-bus-stop)
|
||||
- [x] core: switch to Jest tests, add more tests for Core and Utils (@richardwillars)
|
||||
|
||||
## 0.18.1
|
||||
|
||||
|
|
|
|||
|
|
@ -1,20 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -o pipefail
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
# set -o xtrace
|
||||
|
||||
# Set magic variables for current file & dir
|
||||
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
||||
__base="$(basename ${__file} .sh)"
|
||||
|
||||
SRC="src/index.js"
|
||||
OUT="${OUT:-uppy.js}"
|
||||
OUTDIR="dist"
|
||||
|
||||
FLAGS="-t [ babelify ] --standalone Uppy"
|
||||
|
||||
mkdir -p "${OUTDIR}"
|
||||
|
||||
browserify ${@:-} $SRC $FLAGS > $OUTDIR/$OUT
|
||||
|
|
@ -1,21 +0,0 @@
|
|||
#!/usr/bin/env bash
|
||||
set -o pipefail
|
||||
set -o errexit
|
||||
set -o nounset
|
||||
# set -o xtrace
|
||||
|
||||
# Set magic variables for current file & dir
|
||||
__dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
__file="${__dir}/$(basename "${BASH_SOURCE[0]}")"
|
||||
__base="$(basename ${__file} .sh)"
|
||||
|
||||
OUTDIR="dist/locales"
|
||||
|
||||
FLAGS="-t [ babelify ]"
|
||||
|
||||
mkdir -p "${OUTDIR}"
|
||||
|
||||
for file in ./src/locales/*.js; do
|
||||
# echo "$file";
|
||||
node_modules/.bin/browserify $file $FLAGS > $OUTDIR/${file##*/};
|
||||
done
|
||||
31
bin/disc.js
Normal file
31
bin/disc.js
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const { PassThrough } = require('stream')
|
||||
const browserify = require('browserify')
|
||||
const babelify = require('babelify')
|
||||
const minifyify = require('minifyify')
|
||||
const disc = require('disc')
|
||||
|
||||
const outputPath = path.join(__dirname, '../website/src/disc.html')
|
||||
|
||||
const bundler = browserify(path.join(__dirname, '../src/index.js'), {
|
||||
fullPaths: true,
|
||||
standalone: 'Uppy'
|
||||
})
|
||||
|
||||
bundler.plugin(minifyify, { map: false })
|
||||
bundler.transform(babelify)
|
||||
|
||||
bundler.bundle()
|
||||
.pipe(disc())
|
||||
.pipe(prepend('---\nlayout: false\n---\n'))
|
||||
.pipe(fs.createWriteStream(outputPath))
|
||||
.on('error', (err) => {
|
||||
throw err
|
||||
})
|
||||
|
||||
function prepend (text) {
|
||||
const stream = new PassThrough()
|
||||
stream.write(text)
|
||||
return stream
|
||||
}
|
||||
1
examples/multiple-instances/.gitignore
vendored
Normal file
1
examples/multiple-instances/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
uppy.min.css
|
||||
7
examples/multiple-instances/aliasify.js
Normal file
7
examples/multiple-instances/aliasify.js
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
const path = require('path')
|
||||
|
||||
module.exports = {
|
||||
replacements: {
|
||||
'^uppy/lib/(.*?)$': path.join(__dirname, '../../src/$1')
|
||||
}
|
||||
}
|
||||
31
examples/multiple-instances/index.html
Normal file
31
examples/multiple-instances/index.html
Normal file
|
|
@ -0,0 +1,31 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Uppy example: Multiple instances</title>
|
||||
</head>
|
||||
<body>
|
||||
<style>
|
||||
main {
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
align-items: center;
|
||||
}
|
||||
h1 { text-align: center }
|
||||
</style>
|
||||
<main>
|
||||
<div>
|
||||
<h1>Instance A</h1>
|
||||
<div id="a"></div>
|
||||
</div>
|
||||
<div>
|
||||
<h1>Instance B</h1>
|
||||
<div id="b"></div>
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<link href="uppy.min.css" rel="stylesheet">
|
||||
<script src="bundle.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
32
examples/multiple-instances/main.js
Normal file
32
examples/multiple-instances/main.js
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
const Uppy = require('uppy/lib/core')
|
||||
const Dashboard = require('uppy/lib/plugins/Dashboard')
|
||||
const RestoreFiles = require('uppy/lib/plugins/RestoreFiles')
|
||||
|
||||
// Initialise two Uppy instances with the RestoreFiles plugin,
|
||||
// but with different `id`s.
|
||||
const a = Uppy({
|
||||
id: 'a',
|
||||
debug: true
|
||||
})
|
||||
.use(Dashboard, {
|
||||
target: '#a',
|
||||
inline: true,
|
||||
maxWidth: 400
|
||||
})
|
||||
.use(RestoreFiles, { serviceWorker: false })
|
||||
.run()
|
||||
|
||||
const b = Uppy({
|
||||
id: 'b',
|
||||
debug: true
|
||||
})
|
||||
.use(Dashboard, {
|
||||
target: '#b',
|
||||
inline: true,
|
||||
maxWidth: 400
|
||||
})
|
||||
.use(RestoreFiles, { serviceWorker: false })
|
||||
.run()
|
||||
|
||||
window.a = a
|
||||
window.b = b
|
||||
3048
examples/multiple-instances/package-lock.json
generated
Normal file
3048
examples/multiple-instances/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
15
examples/multiple-instances/package.json
Normal file
15
examples/multiple-instances/package.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"private": true,
|
||||
"name": "uppy-multiple-instances-example",
|
||||
"scripts": {
|
||||
"css": "cp ../../dist/uppy.min.css .",
|
||||
"start": "npm run css && budo main.js:bundle.js -- -t babelify -g aliasify"
|
||||
},
|
||||
"aliasify": "./aliasify.js",
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"aliasify": "^2.1.0",
|
||||
"babelify": "^7.3.0",
|
||||
"budo": "^10.0.4"
|
||||
}
|
||||
}
|
||||
13
examples/multiple-instances/readme.md
Normal file
13
examples/multiple-instances/readme.md
Normal file
|
|
@ -0,0 +1,13 @@
|
|||
# Multiple Instances
|
||||
|
||||
This example uses Uppy with the RestoreFiles plugin.
|
||||
It has two instances on the same page, side-by-side, but with different `id`s so their stored files don't interfere with each other.
|
||||
|
||||
## Run it
|
||||
|
||||
Move into this directory, then:
|
||||
|
||||
```bash
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
1298
package-lock.json
generated
1298
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -86,8 +86,9 @@
|
|||
"nanoraf": "3.0.1",
|
||||
"on-load": "3.2.0",
|
||||
"prettier-bytes": "1.0.4",
|
||||
"promise-settle": "^0.3.0",
|
||||
"socket.io-client": "2.0.1",
|
||||
"tus-js-client": "1.4.3",
|
||||
"tus-js-client": "^1.4.4",
|
||||
"url-parse": "1.1.9",
|
||||
"whatwg-fetch": "2.0.3",
|
||||
"yo-yo": "1.4.0",
|
||||
|
|
@ -98,7 +99,6 @@
|
|||
"build:css": "node ./bin/build-css.js",
|
||||
"build:gzip": "node ./bin/gzip.js",
|
||||
"size": "echo 'JS Bundle mingz:' && cat ./dist/uppy.min.js | gzip | wc -c && echo 'CSS Bundle mingz:' && cat ./dist/uppy.min.css | gzip | wc -c",
|
||||
"build:bundle:fullpath": "env OUT=uppy-fp.js ./bin/build-bundle --full-paths",
|
||||
"build:js": "npm-run-all build:bundle build:lib",
|
||||
"build:lib": "babel --version && babel src --source-maps -d lib",
|
||||
"build": "npm-run-all --parallel build:js build:css --serial build:gzip size",
|
||||
|
|
@ -132,7 +132,7 @@
|
|||
"web:clean": "cd website && ./node_modules/.bin/hexo clean",
|
||||
"web:deploy": "npm-run-all web:install web:disc web:build && ./bin/web-deploy",
|
||||
"web:generated-docs": "cd website && node node_modules/documentation/bin/documentation.js readme ../src/index.js --readme-file=src/docs/api.md --section 'Uppy Core & Plugins' -q --github -c doc-order.json",
|
||||
"web:disc": "npm run build:bundle:fullpath && discify dist/uppy-fp.js --output website/src/_disc.html && echo '---\nlayout: false\n---\n' |cat - website/src/_disc.html > website/src/disc.html && rm website/src/_disc.html",
|
||||
"web:disc": "node ./bin/disc.js",
|
||||
"web:install": "cd website && npm install",
|
||||
"web:bundle:update:watch": "onchange 'dist/**/*.css' 'dist/**/*.js' --initial --verbose -- node website/update.js",
|
||||
"web:examples:watch": "cd website && node build-examples.js watch",
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ class Uppy {
|
|||
|
||||
// set default options
|
||||
const defaultOptions = {
|
||||
id: 'uppy',
|
||||
autoProceed: true,
|
||||
debug: false,
|
||||
restrictions: {
|
||||
|
|
@ -71,6 +72,8 @@ class Uppy {
|
|||
this.updateMeta = this.updateMeta.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)
|
||||
this.addFile = this.addFile.bind(this)
|
||||
this.removeFile = this.removeFile.bind(this)
|
||||
this.calculateProgress = this.calculateProgress.bind(this)
|
||||
|
|
@ -225,16 +228,31 @@ class Uppy {
|
|||
this.setState({files: updatedFiles})
|
||||
}
|
||||
|
||||
checkRestrictions (checkMinNumberOfFiles, file, fileType) {
|
||||
const {maxFileSize, maxNumberOfFiles, minNumberOfFiles, allowedFileTypes} = this.opts.restrictions
|
||||
|
||||
if (checkMinNumberOfFiles && minNumberOfFiles) {
|
||||
if (Object.keys(this.state.files).length < minNumberOfFiles) {
|
||||
this.info(`${this.i18n('youHaveToAtLeastSelectX', {smart_count: minNumberOfFiles})}`, 'error', 5000)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
/**
|
||||
* Check if minNumberOfFiles restriction is reached before uploading
|
||||
*
|
||||
* @return {boolean}
|
||||
* @private
|
||||
*/
|
||||
checkMinNumberOfFiles () {
|
||||
const {minNumberOfFiles} = this.opts.restrictions
|
||||
if (Object.keys(this.state.files).length < minNumberOfFiles) {
|
||||
this.info(`${this.i18n('youHaveToAtLeastSelectX', {smart_count: minNumberOfFiles})}`, 'error', 5000)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if file passes a set of restrictions set in options: maxFileSize,
|
||||
* maxNumberOfFiles and allowedFileTypes
|
||||
*
|
||||
* @param {object} file object to check
|
||||
* @return {boolean}
|
||||
* @private
|
||||
*/
|
||||
checkRestrictions (file) {
|
||||
const {maxFileSize, maxNumberOfFiles, allowedFileTypes} = this.opts.restrictions
|
||||
|
||||
if (maxNumberOfFiles) {
|
||||
if (Object.keys(this.state.files).length + 1 > maxNumberOfFiles) {
|
||||
|
|
@ -244,7 +262,7 @@ class Uppy {
|
|||
}
|
||||
|
||||
if (allowedFileTypes) {
|
||||
const isCorrectFileType = allowedFileTypes.filter(match(fileType.join('/'))).length > 0
|
||||
const isCorrectFileType = allowedFileTypes.filter(match(file.type.mime)).length > 0
|
||||
if (!isCorrectFileType) {
|
||||
const allowedFileTypesString = allowedFileTypes.join(', ')
|
||||
this.info(`${this.i18n('youCanOnlyUploadFileTypes')} ${allowedFileTypesString}`, 'error', 5000)
|
||||
|
|
@ -262,6 +280,13 @@ class Uppy {
|
|||
return true
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new file to `state.files`. This will run `onBeforeFileAdded`,
|
||||
* try to guess file type in a clever way, check file against restrictions,
|
||||
* and start an upload if `autoProceed === true`.
|
||||
*
|
||||
* @param {object} file object to add
|
||||
*/
|
||||
addFile (file) {
|
||||
// Wrap this in a Promise `.then()` handler so errors will reject the Promise
|
||||
// instead of throwing.
|
||||
|
|
@ -290,7 +315,8 @@ class Uppy {
|
|||
meta: Object.assign({}, { name: fileName }, this.getState().meta),
|
||||
type: {
|
||||
general: fileTypeGeneral,
|
||||
specific: fileTypeSpecific
|
||||
specific: fileTypeSpecific,
|
||||
mime: fileType.join('/')
|
||||
},
|
||||
data: file.data,
|
||||
progress: {
|
||||
|
|
@ -306,7 +332,7 @@ class Uppy {
|
|||
preview: file.preview
|
||||
}
|
||||
|
||||
const isFileAllowed = this.checkRestrictions(false, newFile, fileType)
|
||||
const isFileAllowed = this.checkRestrictions(newFile)
|
||||
if (!isFileAllowed) return Promise.reject('File not allowed')
|
||||
|
||||
updatedFiles[fileID] = newFile
|
||||
|
|
@ -422,7 +448,7 @@ class Uppy {
|
|||
progressAll = progressAll + files[file].progress.percentage
|
||||
})
|
||||
|
||||
const totalProgress = Math.floor((progressAll * 100 / progressMax).toFixed(2))
|
||||
const totalProgress = progressMax === 0 ? 0 : Math.floor((progressAll * 100 / progressMax).toFixed(2))
|
||||
|
||||
this.setState({
|
||||
totalProgress: totalProgress
|
||||
|
|
@ -525,13 +551,6 @@ class Uppy {
|
|||
})
|
||||
|
||||
this.calculateTotalProgress()
|
||||
|
||||
if (this.getState().totalProgress === 100) {
|
||||
const completeFiles = Object.keys(updatedFiles).filter((file) => {
|
||||
return updatedFiles[file].progress.uploadComplete
|
||||
})
|
||||
this.emit('core:upload-complete', completeFiles.length)
|
||||
}
|
||||
})
|
||||
|
||||
this.on('core:update-meta', (data, fileID) => {
|
||||
|
|
@ -582,14 +601,17 @@ class Uppy {
|
|||
|
||||
// show informer if offline
|
||||
if (typeof window !== 'undefined') {
|
||||
window.addEventListener('online', () => this.isOnline(true))
|
||||
window.addEventListener('offline', () => this.isOnline(false))
|
||||
setTimeout(() => this.isOnline(), 3000)
|
||||
window.addEventListener('online', () => this.updateOnlineStatus())
|
||||
window.addEventListener('offline', () => this.updateOnlineStatus())
|
||||
setTimeout(() => this.updateOnlineStatus(), 3000)
|
||||
}
|
||||
}
|
||||
|
||||
isOnline (status) {
|
||||
const online = status || window.navigator.onLine
|
||||
updateOnlineStatus () {
|
||||
const online =
|
||||
typeof window.navigator.onLine !== 'undefined'
|
||||
? window.navigator.onLine
|
||||
: true
|
||||
if (!online) {
|
||||
this.emit('is-offline')
|
||||
this.info('No internet connection', 'error', 0)
|
||||
|
|
@ -604,6 +626,10 @@ class Uppy {
|
|||
}
|
||||
}
|
||||
|
||||
getID () {
|
||||
return this.opts.id
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a plugin with Core
|
||||
*
|
||||
|
|
@ -737,19 +763,11 @@ class Uppy {
|
|||
}
|
||||
|
||||
// hide the informer after `duration` milliseconds
|
||||
this.infoTimeoutID = setTimeout(() => {
|
||||
const newInformer = Object.assign({}, this.state.info, {
|
||||
isHidden: true
|
||||
})
|
||||
this.setState({
|
||||
info: newInformer
|
||||
})
|
||||
this.emit('core:info-hidden')
|
||||
}, duration)
|
||||
this.infoTimeoutID = setTimeout(this.hideInfo, duration)
|
||||
}
|
||||
|
||||
hideInfo () {
|
||||
const newInfo = Object.assign({}, this.core.state.info, {
|
||||
const newInfo = Object.assign({}, this.state.info, {
|
||||
isHidden: true
|
||||
})
|
||||
this.setState({
|
||||
|
|
@ -796,17 +814,8 @@ class Uppy {
|
|||
*/
|
||||
run () {
|
||||
this.log('Core is run, initializing actions...')
|
||||
|
||||
this.actions()
|
||||
|
||||
// Forse set `autoProceed` option to false if there are multiple selector Plugins active
|
||||
// if (this.plugins.acquirer && this.plugins.acquirer.length > 1) {
|
||||
// this.opts.autoProceed = false
|
||||
// }
|
||||
|
||||
// Install all plugins
|
||||
// this.installAll()
|
||||
|
||||
return this
|
||||
}
|
||||
|
||||
|
|
@ -922,7 +931,7 @@ class Uppy {
|
|||
* @return {Promise}
|
||||
*/
|
||||
upload (forceUpload) {
|
||||
const isMinNumberOfFilesReached = this.checkRestrictions(true)
|
||||
const isMinNumberOfFilesReached = this.checkMinNumberOfFiles()
|
||||
if (!isMinNumberOfFilesReached) {
|
||||
return Promise.reject('Minimum number of files has not been reached')
|
||||
}
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
|
|
@ -529,6 +529,23 @@ function findDOMElement (element) {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find one or more DOM elements.
|
||||
*
|
||||
* @param {string} element
|
||||
* @return {Array|null}
|
||||
*/
|
||||
function findAllDOMElements (element) {
|
||||
if (typeof element === 'string') {
|
||||
const elements = [].slice.call(document.querySelectorAll(element))
|
||||
return elements.length > 0 ? elements : null
|
||||
}
|
||||
|
||||
if (typeof element === 'object' && isDOMElement(element)) {
|
||||
return [element]
|
||||
}
|
||||
}
|
||||
|
||||
function getSocketHost (url) {
|
||||
// get the host domain
|
||||
var regex = /^(?:https?:\/\/|\/\/)?(?:[^@\n]+@)?(?:www\.)?([^\n]+)/
|
||||
|
|
@ -580,6 +597,7 @@ module.exports = {
|
|||
copyToClipboard,
|
||||
prettyETA,
|
||||
findDOMElement,
|
||||
findAllDOMElements,
|
||||
getSocketHost,
|
||||
emitSocketProgress
|
||||
}
|
||||
|
|
|
|||
|
|
@ -129,13 +129,24 @@ describe('core/utils', () => {
|
|||
})
|
||||
|
||||
describe('isTouchDevice', () => {
|
||||
it("should return true if it's a touch device", () => {
|
||||
global.window.ontouchstart = () => {}
|
||||
expect(utils.isTouchDevice()).toEqual(true)
|
||||
const RealTouchStart = global.window.ontouchstart
|
||||
const RealMaxTouchPoints = global.navigator.maxTouchPoints
|
||||
|
||||
delete global.window.ontouchstart
|
||||
global.navigator.maxTouchPoints = () => {}
|
||||
beforeEach(() => {
|
||||
global.window.ontouchstart = true
|
||||
global.navigator.maxTouchPoints = 1
|
||||
})
|
||||
|
||||
afterEach(() => {
|
||||
global.navigator.maxTouchPoints = RealMaxTouchPoints
|
||||
global.window.ontouchstart = RealTouchStart
|
||||
})
|
||||
|
||||
xit("should return true if it's a touch device", () => {
|
||||
expect(utils.isTouchDevice()).toEqual(true)
|
||||
delete global.window.ontouchstart
|
||||
global.navigator.maxTouchPoints = false
|
||||
expect(utils.isTouchDevice()).toEqual(false)
|
||||
})
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -69,7 +69,7 @@ module.exports = function Dashboard (props) {
|
|||
type="button"
|
||||
aria-label="${props.i18n('closeModal')}"
|
||||
title="${props.i18n('closeModal')}"
|
||||
onclick=${props.hideModal}>${closeIcon()}</button>
|
||||
onclick=${props.closeModal}>${closeIcon()}</button>
|
||||
|
||||
<div class="UppyDashboard-innerWrap">
|
||||
|
||||
|
|
|
|||
|
|
@ -3,26 +3,26 @@ const html = require('yo-yo')
|
|||
// https://css-tricks.com/creating-svg-icon-system-react/
|
||||
|
||||
function defaultTabIcon () {
|
||||
return html`<svg class="UppyIcon" width="30" height="30" viewBox="0 0 30 30">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="30" height="30" viewBox="0 0 30 30">
|
||||
<path d="M15 30c8.284 0 15-6.716 15-15 0-8.284-6.716-15-15-15C6.716 0 0 6.716 0 15c0 8.284 6.716 15 15 15zm4.258-12.676v6.846h-8.426v-6.846H5.204l9.82-12.364 9.82 12.364H19.26z" />
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function iconCopy () {
|
||||
return html`<svg class="UppyIcon" width="51" height="51" viewBox="0 0 51 51">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="51" height="51" viewBox="0 0 51 51">
|
||||
<path d="M17.21 45.765a5.394 5.394 0 0 1-7.62 0l-4.12-4.122a5.393 5.393 0 0 1 0-7.618l6.774-6.775-2.404-2.404-6.775 6.776c-3.424 3.427-3.424 9 0 12.426l4.12 4.123a8.766 8.766 0 0 0 6.216 2.57c2.25 0 4.5-.858 6.214-2.57l13.55-13.552a8.72 8.72 0 0 0 2.575-6.213 8.73 8.73 0 0 0-2.575-6.213l-4.123-4.12-2.404 2.404 4.123 4.12a5.352 5.352 0 0 1 1.58 3.81c0 1.438-.562 2.79-1.58 3.808l-13.55 13.55z"/>
|
||||
<path d="M44.256 2.858A8.728 8.728 0 0 0 38.043.283h-.002a8.73 8.73 0 0 0-6.212 2.574l-13.55 13.55a8.725 8.725 0 0 0-2.575 6.214 8.73 8.73 0 0 0 2.574 6.216l4.12 4.12 2.405-2.403-4.12-4.12a5.357 5.357 0 0 1-1.58-3.812c0-1.437.562-2.79 1.58-3.808l13.55-13.55a5.348 5.348 0 0 1 3.81-1.58c1.44 0 2.792.562 3.81 1.58l4.12 4.12c2.1 2.1 2.1 5.518 0 7.617L39.2 23.775l2.404 2.404 6.775-6.777c3.426-3.427 3.426-9 0-12.426l-4.12-4.12z"/>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function iconResume () {
|
||||
return html`<svg class="UppyIcon" width="25" height="25" viewBox="0 0 44 44">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="25" height="25" viewBox="0 0 44 44">
|
||||
<polygon class="play" transform="translate(6, 5.5)" points="13 21.6666667 13 11 21 16.3333333" />
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function iconPause () {
|
||||
return html`<svg class="UppyIcon" width="25px" height="25px" viewBox="0 0 44 44">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="25px" height="25px" viewBox="0 0 44 44">
|
||||
<g transform="translate(18, 17)" class="pause">
|
||||
<rect x="0" y="0" width="2" height="10" rx="0" />
|
||||
<rect x="6" y="0" width="2" height="10" rx="0" />
|
||||
|
|
@ -31,77 +31,77 @@ function iconPause () {
|
|||
}
|
||||
|
||||
function iconEdit () {
|
||||
return html`<svg class="UppyIcon" width="28" height="28" viewBox="0 0 28 28">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="28" height="28" viewBox="0 0 28 28">
|
||||
<path d="M25.436 2.566a7.98 7.98 0 0 0-2.078-1.51C22.638.703 21.906.5 21.198.5a3 3 0 0 0-1.023.17 2.436 2.436 0 0 0-.893.562L2.292 18.217.5 27.5l9.28-1.796 16.99-16.99c.255-.254.444-.56.562-.888a3 3 0 0 0 .17-1.023c0-.708-.205-1.44-.555-2.16a8 8 0 0 0-1.51-2.077zM9.01 24.252l-4.313.834c0-.03.008-.06.012-.09.007-.944-.74-1.715-1.67-1.723-.04 0-.078.007-.118.01l.83-4.29L17.72 5.024l5.264 5.264L9.01 24.252zm16.84-16.96a.818.818 0 0 1-.194.31l-1.57 1.57-5.26-5.26 1.57-1.57a.82.82 0 0 1 .31-.194 1.45 1.45 0 0 1 .492-.074c.397 0 .917.126 1.468.397.55.27 1.13.678 1.656 1.21.53.53.94 1.11 1.208 1.655.272.55.397 1.07.393 1.468.004.193-.027.358-.074.488z" />
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function localIcon () {
|
||||
return html`<svg class="UppyIcon" width="27" height="25" viewBox="0 0 27 25">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="27" height="25" viewBox="0 0 27 25">
|
||||
<path d="M5.586 9.288a.313.313 0 0 0 .282.176h4.84v3.922c0 1.514 1.25 2.24 2.792 2.24 1.54 0 2.79-.726 2.79-2.24V9.464h4.84c.122 0 .23-.068.284-.176a.304.304 0 0 0-.046-.324L13.735.106a.316.316 0 0 0-.472 0l-7.63 8.857a.302.302 0 0 0-.047.325z"/>
|
||||
<path d="M24.3 5.093c-.218-.76-.54-1.187-1.208-1.187h-4.856l1.018 1.18h3.948l2.043 11.038h-7.193v2.728H9.114v-2.725h-7.36l2.66-11.04h3.33l1.018-1.18H3.907c-.668 0-1.06.46-1.21 1.186L0 16.456v7.062C0 24.338.676 25 1.51 25h23.98c.833 0 1.51-.663 1.51-1.482v-7.062L24.3 5.093z"/>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function closeIcon () {
|
||||
return html`<svg class="UppyIcon" width="14px" height="14px" viewBox="0 0 19 19">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="14px" height="14px" viewBox="0 0 19 19">
|
||||
<path d="M17.318 17.232L9.94 9.854 9.586 9.5l-.354.354-7.378 7.378h.707l-.62-.62v.706L9.318 9.94l.354-.354-.354-.354L1.94 1.854v.707l.62-.62h-.706l7.378 7.378.354.354.354-.354 7.378-7.378h-.707l.622.62v-.706L9.854 9.232l-.354.354.354.354 7.378 7.378.708-.707-7.38-7.378v.708l7.38-7.38.353-.353-.353-.353-.622-.622-.353-.353-.354.352-7.378 7.38h.708L2.56 1.23 2.208.88l-.353.353-.622.62-.353.355.352.353 7.38 7.38v-.708l-7.38 7.38-.353.353.352.353.622.622.353.353.354-.353 7.38-7.38h-.708l7.38 7.38z"/>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function pluginIcon () {
|
||||
return html`<svg class="UppyIcon" width="16px" height="16px" viewBox="0 0 32 30">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="16px" height="16px" viewBox="0 0 32 30">
|
||||
<path d="M6.6209894,11.1451162 C6.6823051,11.2751669 6.81374248,11.3572188 6.95463813,11.3572188 L12.6925482,11.3572188 L12.6925482,16.0630427 C12.6925482,17.880509 14.1726048,18.75 16.0000083,18.75 C17.8261072,18.75 19.3074684,17.8801847 19.3074684,16.0630427 L19.3074684,11.3572188 L25.0437478,11.3572188 C25.1875787,11.3572188 25.3164069,11.2751669 25.3790272,11.1451162 C25.4370814,11.0173358 25.4171865,10.8642587 25.3252129,10.7562615 L16.278212,0.127131837 C16.2093949,0.0463771751 16.1069846,0 15.9996822,0 C15.8910751,0 15.7886648,0.0463771751 15.718217,0.127131837 L6.6761083,10.7559371 C6.58250402,10.8642587 6.56293518,11.0173358 6.6209894,11.1451162 L6.6209894,11.1451162 Z"/>
|
||||
<path d="M28.8008722,6.11142645 C28.5417891,5.19831555 28.1583331,4.6875 27.3684848,4.6875 L21.6124454,4.6875 L22.8190234,6.10307874 L27.4986725,6.10307874 L29.9195817,19.3486449 L21.3943891,19.3502502 L21.3943891,22.622552 L10.8023461,22.622552 L10.8023461,19.3524977 L2.07815702,19.3534609 L5.22979699,6.10307874 L9.17871529,6.10307874 L10.3840011,4.6875 L4.6308691,4.6875 C3.83940559,4.6875 3.37421888,5.2390909 3.19815864,6.11142645 L0,19.7470874 L0,28.2212959 C0,29.2043992 0.801477937,30 1.78870751,30 L30.2096773,30 C31.198199,30 32,29.2043992 32,28.2212959 L32,19.7470874 L28.8008722,6.11142645 L28.8008722,6.11142645 Z"/>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function checkIcon () {
|
||||
return html`<svg class="UppyIcon UppyIcon-check" width="13px" height="9px" viewBox="0 0 13 9">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon UppyIcon-check" width="13px" height="9px" viewBox="0 0 13 9">
|
||||
<polygon points="5 7.293 1.354 3.647 0.646 4.354 5 8.707 12.354 1.354 11.646 0.647"></polygon>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function iconAudio () {
|
||||
return html`<svg class="UppyIcon" viewBox="0 0 55 55">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" viewBox="0 0 55 55">
|
||||
<path d="M52.66.25c-.216-.19-.5-.276-.79-.242l-31 4.01a1 1 0 0 0-.87.992V40.622C18.174 38.428 15.273 37 12 37c-5.514 0-10 4.037-10 9s4.486 9 10 9 10-4.037 10-9c0-.232-.02-.46-.04-.687.014-.065.04-.124.04-.192V16.12l29-3.753v18.257C49.174 28.428 46.273 27 43 27c-5.514 0-10 4.037-10 9s4.486 9 10 9c5.464 0 9.913-3.966 9.993-8.867 0-.013.007-.024.007-.037V1a.998.998 0 0 0-.34-.75zM12 53c-4.41 0-8-3.14-8-7s3.59-7 8-7 8 3.14 8 7-3.59 7-8 7zm31-10c-4.41 0-8-3.14-8-7s3.59-7 8-7 8 3.14 8 7-3.59 7-8 7zM22 14.1V5.89l29-3.753v8.21l-29 3.754z"/>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function iconVideo () {
|
||||
return html`<svg class="UppyIcon" viewBox="0 0 58 58">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" viewBox="0 0 58 58">
|
||||
<path d="M36.537 28.156l-11-7a1.005 1.005 0 0 0-1.02-.033C24.2 21.3 24 21.635 24 22v14a1 1 0 0 0 1.537.844l11-7a1.002 1.002 0 0 0 0-1.688zM26 34.18V23.82L34.137 29 26 34.18z"/><path d="M57 6H1a1 1 0 0 0-1 1v44a1 1 0 0 0 1 1h56a1 1 0 0 0 1-1V7a1 1 0 0 0-1-1zM10 28H2v-9h8v9zm-8 2h8v9H2v-9zm10 10V8h34v42H12V40zm44-12h-8v-9h8v9zm-8 2h8v9h-8v-9zm8-22v9h-8V8h8zM2 8h8v9H2V8zm0 42v-9h8v9H2zm54 0h-8v-9h8v9z"/>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function iconPDF () {
|
||||
return html`<svg class="UppyIcon" viewBox="0 0 342 335">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" viewBox="0 0 342 335">
|
||||
<path d="M329.337 227.84c-2.1 1.3-8.1 2.1-11.9 2.1-12.4 0-27.6-5.7-49.1-14.9 8.3-.6 15.8-.9 22.6-.9 12.4 0 16 0 28.2 3.1 12.1 3 12.2 9.3 10.2 10.6zm-215.1 1.9c4.8-8.4 9.7-17.3 14.7-26.8 12.2-23.1 20-41.3 25.7-56.2 11.5 20.9 25.8 38.6 42.5 52.8 2.1 1.8 4.3 3.5 6.7 5.3-34.1 6.8-63.6 15-89.6 24.9zm39.8-218.9c6.8 0 10.7 17.06 11 33.16.3 16-3.4 27.2-8.1 35.6-3.9-12.4-5.7-31.8-5.7-44.5 0 0-.3-24.26 2.8-24.26zm-133.4 307.2c3.9-10.5 19.1-31.3 41.6-49.8 1.4-1.1 4.9-4.4 8.1-7.4-23.5 37.6-39.3 52.5-49.7 57.2zm315.2-112.3c-6.8-6.7-22-10.2-45-10.5-15.6-.2-34.3 1.2-54.1 3.9-8.8-5.1-17.9-10.6-25.1-17.3-19.2-18-35.2-42.9-45.2-70.3.6-2.6 1.2-4.8 1.7-7.1 0 0 10.8-61.5 7.9-82.3-.4-2.9-.6-3.7-1.4-5.9l-.9-2.5c-2.9-6.76-8.7-13.96-17.8-13.57l-5.3-.17h-.1c-10.1 0-18.4 5.17-20.5 12.84-6.6 24.3.2 60.5 12.5 107.4l-3.2 7.7c-8.8 21.4-19.8 43-29.5 62l-1.3 2.5c-10.2 20-19.5 37-27.9 51.4l-8.7 4.6c-.6.4-15.5 8.2-19 10.3-29.6 17.7-49.28 37.8-52.54 53.8-1.04 5-.26 11.5 5.01 14.6l8.4 4.2c3.63 1.8 7.53 2.7 11.43 2.7 21.1 0 45.6-26.2 79.3-85.1 39-12.7 83.4-23.3 122.3-29.1 29.6 16.7 66 28.3 89 28.3 4.1 0 7.6-.4 10.5-1.2 4.4-1.1 8.1-3.6 10.4-7.1 4.4-6.7 5.4-15.9 4.1-25.4-.3-2.8-2.6-6.3-5-8.7z" />
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function iconFile () {
|
||||
return html`<svg class="UppyIcon" width="44" height="58" viewBox="0 0 44 58">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="44" height="58" viewBox="0 0 44 58">
|
||||
<path d="M27.437.517a1 1 0 0 0-.094.03H4.25C2.037.548.217 2.368.217 4.58v48.405c0 2.212 1.82 4.03 4.03 4.03H39.03c2.21 0 4.03-1.818 4.03-4.03V15.61a1 1 0 0 0-.03-.28 1 1 0 0 0 0-.093 1 1 0 0 0-.03-.032 1 1 0 0 0 0-.03 1 1 0 0 0-.032-.063 1 1 0 0 0-.03-.063 1 1 0 0 0-.032 0 1 1 0 0 0-.03-.063 1 1 0 0 0-.032-.03 1 1 0 0 0-.03-.063 1 1 0 0 0-.063-.062l-14.593-14a1 1 0 0 0-.062-.062A1 1 0 0 0 28 .708a1 1 0 0 0-.374-.157 1 1 0 0 0-.156 0 1 1 0 0 0-.03-.03l-.003-.003zM4.25 2.547h22.218v9.97c0 2.21 1.82 4.03 4.03 4.03h10.564v36.438a2.02 2.02 0 0 1-2.032 2.032H4.25c-1.13 0-2.032-.9-2.032-2.032V4.58c0-1.13.902-2.032 2.03-2.032zm24.218 1.345l10.375 9.937.75.718H30.5c-1.13 0-2.032-.9-2.032-2.03V3.89z" />
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function iconText () {
|
||||
return html`<svg class="UppyIcon" viewBox="0 0 64 64">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" viewBox="0 0 64 64">
|
||||
<path d="M8 64h48V0H22.586L8 14.586V64zm46-2H10V16h14V2h30v60zM11.414 14L22 3.414V14H11.414z"/>
|
||||
<path d="M32 13h14v2H32zM18 23h28v2H18zM18 33h28v2H18zM18 43h28v2H18zM18 53h28v2H18z"/>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function uploadIcon () {
|
||||
return html`<svg class="UppyIcon" width="37" height="33" viewBox="0 0 37 33">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="37" height="33" viewBox="0 0 37 33">
|
||||
<path d="M29.107 24.5c4.07 0 7.393-3.355 7.393-7.442 0-3.994-3.105-7.307-7.012-7.502l.468.415C29.02 4.52 24.34.5 18.886.5c-4.348 0-8.27 2.522-10.138 6.506l.446-.288C4.394 6.782.5 10.758.5 15.608c0 4.924 3.906 8.892 8.76 8.892h4.872c.635 0 1.095-.467 1.095-1.104 0-.636-.46-1.103-1.095-1.103H9.26c-3.644 0-6.63-3.035-6.63-6.744 0-3.71 2.926-6.685 6.57-6.685h.964l.14-.28.177-.362c1.477-3.4 4.744-5.576 8.347-5.576 4.58 0 8.45 3.452 9.01 8.072l.06.536.05.446h1.101c2.87 0 5.204 2.37 5.204 5.295s-2.333 5.296-5.204 5.296h-6.062c-.634 0-1.094.467-1.094 1.103 0 .637.46 1.104 1.094 1.104h6.12z"/>
|
||||
<path d="M23.196 18.92l-4.828-5.258-.366-.4-.368.398-4.828 5.196a1.13 1.13 0 0 0 0 1.546c.428.46 1.11.46 1.537 0l3.45-3.71-.868-.34v15.03c0 .64.445 1.118 1.075 1.118.63 0 1.075-.48 1.075-1.12V16.35l-.867.34 3.45 3.712a1 1 0 0 0 .767.345 1 1 0 0 0 .77-.345c.416-.33.416-1.036 0-1.485v.003z"/>
|
||||
</svg>`
|
||||
}
|
||||
|
||||
function dashboardBgIcon () {
|
||||
return html`<svg class="UppyIcon" width="48" height="69" viewBox="0 0 48 69">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="48" height="69" viewBox="0 0 48 69">
|
||||
<path d="M.5 1.5h5zM10.5 1.5h5zM20.5 1.5h5zM30.504 1.5h5zM45.5 11.5v5zM45.5 21.5v5zM45.5 31.5v5zM45.5 41.502v5zM45.5 51.502v5zM45.5 61.5v5zM45.5 66.502h-4.998zM35.503 66.502h-5zM25.5 66.502h-5zM15.5 66.502h-5zM5.5 66.502h-5zM.5 66.502v-5zM.5 56.502v-5zM.5 46.503V41.5zM.5 36.5v-5zM.5 26.5v-5zM.5 16.5v-5zM.5 6.5V1.498zM44.807 11H36V2.195z"/>
|
||||
</svg>`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ const dragDrop = require('drag-drop')
|
|||
const Dashboard = require('./Dashboard')
|
||||
const StatusBar = require('../StatusBar')
|
||||
const Informer = require('../Informer')
|
||||
const { findDOMElement } = require('../../core/Utils')
|
||||
const { findAllDOMElements } = require('../../core/Utils')
|
||||
const prettyBytes = require('prettier-bytes')
|
||||
const { defaultTabIcon } = require('./icons')
|
||||
|
||||
|
|
@ -14,8 +14,8 @@ const { defaultTabIcon } = require('./icons')
|
|||
module.exports = class DashboardUI extends Plugin {
|
||||
constructor (core, opts) {
|
||||
super(core, opts)
|
||||
this.id = 'DashboardUI'
|
||||
this.title = 'Dashboard UI'
|
||||
this.id = 'Dashboard'
|
||||
this.title = 'Dashboard'
|
||||
this.type = 'orchestrator'
|
||||
|
||||
const defaultLocale = {
|
||||
|
|
@ -67,8 +67,9 @@ module.exports = class DashboardUI extends Plugin {
|
|||
this.translator = new Translator({locale: this.locale})
|
||||
this.containerWidth = this.translator.translate.bind(this.translator)
|
||||
|
||||
this.hideModal = this.hideModal.bind(this)
|
||||
this.showModal = this.showModal.bind(this)
|
||||
this.closeModal = this.closeModal.bind(this)
|
||||
this.openModal = this.openModal.bind(this)
|
||||
this.isModalOpen = this.isModalOpen.bind(this)
|
||||
|
||||
this.addTarget = this.addTarget.bind(this)
|
||||
this.actions = this.actions.bind(this)
|
||||
|
|
@ -144,21 +145,7 @@ module.exports = class DashboardUI extends Plugin {
|
|||
})})
|
||||
}
|
||||
|
||||
hideModal () {
|
||||
const modal = this.core.getState().modal
|
||||
|
||||
this.core.setState({
|
||||
modal: Object.assign({}, modal, {
|
||||
isHidden: true
|
||||
})
|
||||
})
|
||||
|
||||
document.body.classList.remove('is-UppyDashboard-open')
|
||||
|
||||
window.scrollTo(0, this.savedDocumentScrollPosition)
|
||||
}
|
||||
|
||||
showModal () {
|
||||
openModal () {
|
||||
const modal = this.core.getState().modal
|
||||
|
||||
this.core.setState({
|
||||
|
|
@ -183,22 +170,40 @@ module.exports = class DashboardUI extends Plugin {
|
|||
setTimeout(this.updateDashboardElWidth, 500)
|
||||
}
|
||||
|
||||
closeModal () {
|
||||
const modal = this.core.getState().modal
|
||||
|
||||
this.core.setState({
|
||||
modal: Object.assign({}, modal, {
|
||||
isHidden: true
|
||||
})
|
||||
})
|
||||
|
||||
document.body.classList.remove('is-UppyDashboard-open')
|
||||
|
||||
window.scrollTo(0, this.savedDocumentScrollPosition)
|
||||
}
|
||||
|
||||
isModalOpen () {
|
||||
return !this.core.getState().modal.isHidden || false
|
||||
}
|
||||
|
||||
// Close the Modal on esc key press
|
||||
handleEscapeKeyPress (event) {
|
||||
if (event.keyCode === 27) {
|
||||
this.hideModal()
|
||||
this.closeModal()
|
||||
}
|
||||
}
|
||||
|
||||
handleClickOutside () {
|
||||
if (this.opts.closeModalOnClickOutside) this.hideModal()
|
||||
if (this.opts.closeModalOnClickOutside) this.closeModal()
|
||||
}
|
||||
|
||||
initEvents () {
|
||||
// Modal open button
|
||||
const showModalTrigger = findDOMElement(this.opts.trigger)
|
||||
const showModalTrigger = findAllDOMElements(this.opts.trigger)
|
||||
if (!this.opts.inline && showModalTrigger) {
|
||||
showModalTrigger.addEventListener('click', this.showModal)
|
||||
showModalTrigger.forEach(trigger => trigger.addEventListener('click', this.openModal))
|
||||
}
|
||||
|
||||
if (!this.opts.inline && !showModalTrigger) {
|
||||
|
|
@ -214,9 +219,9 @@ module.exports = class DashboardUI extends Plugin {
|
|||
}
|
||||
|
||||
removeEvents () {
|
||||
const showModalTrigger = findDOMElement(this.opts.trigger)
|
||||
const showModalTrigger = findAllDOMElements(this.opts.trigger)
|
||||
if (!this.opts.inline && showModalTrigger) {
|
||||
showModalTrigger.removeEventListener('click', this.showModal)
|
||||
showModalTrigger.forEach(trigger => trigger.removeEventListener('click', this.openModal))
|
||||
}
|
||||
|
||||
this.removeDragDropListener()
|
||||
|
|
@ -260,7 +265,7 @@ module.exports = class DashboardUI extends Plugin {
|
|||
}
|
||||
|
||||
handleDrop (files) {
|
||||
this.core.log('All right, someone dropped something...')
|
||||
this.core.log('[Dashboard] Files were dropped')
|
||||
|
||||
files.forEach((file) => {
|
||||
this.core.addFile({
|
||||
|
|
@ -301,7 +306,6 @@ module.exports = class DashboardUI extends Plugin {
|
|||
inProgressFilesArray.push(files[file])
|
||||
})
|
||||
|
||||
// total size and uploaded size
|
||||
let totalSize = 0
|
||||
let totalUploadedSize = 0
|
||||
inProgressFilesArray.forEach((file) => {
|
||||
|
|
@ -327,7 +331,7 @@ module.exports = class DashboardUI extends Plugin {
|
|||
}
|
||||
|
||||
const pauseUpload = (fileID) => {
|
||||
this.core.emit.emit('core:upload-pause', fileID)
|
||||
this.core.emit('core:upload-pause', fileID)
|
||||
}
|
||||
|
||||
const cancelUpload = (fileID) => {
|
||||
|
|
@ -344,12 +348,6 @@ module.exports = class DashboardUI extends Plugin {
|
|||
this.core.emit('dashboard:file-card')
|
||||
}
|
||||
|
||||
const info = (text, type, duration) => {
|
||||
this.core.info(text, type, duration)
|
||||
}
|
||||
|
||||
const resumableUploads = this.core.state.capabilities.resumableUploads || false
|
||||
|
||||
return Dashboard({
|
||||
state: state,
|
||||
modal: state.modal,
|
||||
|
|
@ -363,7 +361,7 @@ module.exports = class DashboardUI extends Plugin {
|
|||
autoProceed: this.core.opts.autoProceed,
|
||||
hideUploadButton: this.opts.hideUploadButton,
|
||||
id: this.id,
|
||||
hideModal: this.hideModal,
|
||||
closeModal: this.closeModal,
|
||||
handleClickOutside: this.handleClickOutside,
|
||||
showProgressDetails: this.opts.showProgressDetails,
|
||||
inline: this.opts.inline,
|
||||
|
|
@ -376,10 +374,10 @@ module.exports = class DashboardUI extends Plugin {
|
|||
resumeAll: this.resumeAll,
|
||||
addFile: this.core.addFile,
|
||||
removeFile: this.core.removeFile,
|
||||
info: info,
|
||||
info: this.core.info,
|
||||
note: this.opts.note,
|
||||
metaFields: state.metaFields,
|
||||
resumableUploads: resumableUploads,
|
||||
resumableUploads: this.core.state.capabilities.resumableUploads || false,
|
||||
startUpload: startUpload,
|
||||
pauseUpload: pauseUpload,
|
||||
cancelUpload: cancelUpload,
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module.exports = class DragDrop extends Plugin {
|
|||
this.id = 'DragDrop'
|
||||
this.title = 'Drag & Drop'
|
||||
this.icon = html`
|
||||
<svg class="UppyIcon" width="28" height="28" viewBox="0 0 16 16">
|
||||
<svg aria-hidden="true" class="UppyIcon" 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="M9.778 12.89H4V2.666a.44.44 0 0 0-.444-.445.44.44 0 0 0-.445.445v10.666c0 .25.197.445.446.445h6.222a.44.44 0 0 0 .444-.445.44.44 0 0 0-.444-.444z"/>
|
||||
<path d="M.444 16h6.223a.44.44 0 0 0 .444-.444.44.44 0 0 0-.443-.445H.89V4.89a.44.44 0 0 0-.446-.446A.44.44 0 0 0 0 4.89v10.666c0 .248.196.444.444.444z"/>
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ const html = require('yo-yo')
|
|||
|
||||
module.exports = {
|
||||
folder: () =>
|
||||
html`<svg class="UppyIcon" style="width:16px;margin-right:3px" viewBox="0 0 276.157 276.157">
|
||||
html`<svg aria-hidden="true" class="UppyIcon" style="width:16px;margin-right:3px" viewBox="0 0 276.157 276.157">
|
||||
<path d="M273.08 101.378c-3.3-4.65-8.86-7.32-15.254-7.32h-24.34V67.59c0-10.2-8.3-18.5-18.5-18.5h-85.322c-3.63 0-9.295-2.875-11.436-5.805l-6.386-8.735c-4.982-6.814-15.104-11.954-23.546-11.954H58.73c-9.292 0-18.638 6.608-21.737 15.372l-2.033 5.752c-.958 2.71-4.72 5.37-7.596 5.37H18.5C8.3 49.09 0 57.39 0 67.59v167.07c0 .886.16 1.73.443 2.52.152 3.306 1.18 6.424 3.053 9.064 3.3 4.652 8.86 7.32 15.255 7.32h188.487c11.395 0 23.27-8.425 27.035-19.18l40.677-116.188c2.11-6.035 1.43-12.164-1.87-16.816zM18.5 64.088h8.864c9.295 0 18.64-6.607 21.738-15.37l2.032-5.75c.96-2.712 4.722-5.373 7.597-5.373h29.565c3.63 0 9.295 2.876 11.437 5.806l6.386 8.735c4.982 6.815 15.104 11.954 23.546 11.954h85.322c1.898 0 3.5 1.602 3.5 3.5v26.47H69.34c-11.395 0-23.27 8.423-27.035 19.178L15 191.23V67.59c0-1.898 1.603-3.5 3.5-3.5zm242.29 49.15l-40.676 116.188c-1.674 4.78-7.812 9.135-12.877 9.135H18.75c-1.447 0-2.576-.372-3.02-.997-.442-.625-.422-1.814.057-3.18l40.677-116.19c1.674-4.78 7.812-9.134 12.877-9.134h188.487c1.448 0 2.577.372 3.02.997.443.625.423 1.814-.056 3.18z"/>
|
||||
</svg>`,
|
||||
music: () =>
|
||||
html`<svg class="UppyIcon" width="16.000000pt" height="16.000000pt" viewBox="0 0 48.000000 48.000000"
|
||||
html`<svg aria-hidden="true" class="UppyIcon" width="16.000000pt" height="16.000000pt" viewBox="0 0 48.000000 48.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<g transform="translate(0.000000,48.000000) scale(0.100000,-0.100000)"
|
||||
fill="#525050" stroke="none">
|
||||
|
|
@ -40,7 +40,7 @@ module.exports = {
|
|||
</svg>`,
|
||||
page_white_picture: () =>
|
||||
html`
|
||||
<svg class="UppyIcon" width="16.000000pt" height="16.000000pt" viewBox="0 0 48.000000 36.000000"
|
||||
<svg aria-hidden="true" class="UppyIcon" width="16.000000pt" height="16.000000pt" viewBox="0 0 48.000000 36.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<g transform="translate(0.000000,36.000000) scale(0.100000,-0.100000)"
|
||||
fill="#565555" stroke="none">
|
||||
|
|
@ -74,7 +74,7 @@ module.exports = {
|
|||
</g>
|
||||
</svg>`,
|
||||
word: () =>
|
||||
html`<svg class="UppyIcon" width="16.000000pt" height="16.000000pt" viewBox="0 0 48.000000 48.000000"
|
||||
html`<svg aria-hidden="true" class="UppyIcon" width="16.000000pt" height="16.000000pt" viewBox="0 0 48.000000 48.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<g transform="translate(0.000000,48.000000) scale(0.100000,-0.100000)"
|
||||
fill="#423d3d" stroke="none">
|
||||
|
|
@ -109,7 +109,7 @@ module.exports = {
|
|||
</g>
|
||||
</svg>`,
|
||||
powerpoint: () =>
|
||||
html`<svg class="UppyIcon" width="16.000000pt" height="16.000000pt" viewBox="0 0 16.000000 16.000000"
|
||||
html`<svg aria-hidden="true" class="UppyIcon" width="16.000000pt" height="16.000000pt" viewBox="0 0 16.000000 16.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<g transform="translate(0.000000,144.000000) scale(0.100000,-0.100000)"
|
||||
fill="#494747" stroke="none">
|
||||
|
|
@ -170,7 +170,7 @@ module.exports = {
|
|||
</g>
|
||||
</svg>`,
|
||||
page_white: () =>
|
||||
html`<svg class="UppyIcon" width="16.000000pt" height="16.000000pt" viewBox="0 0 48.000000 48.000000"
|
||||
html`<svg aria-hidden="true" class="UppyIcon" width="16.000000pt" height="16.000000pt" viewBox="0 0 48.000000 48.000000"
|
||||
preserveAspectRatio="xMidYMid meet">
|
||||
<g transform="translate(0.000000,48.000000) scale(0.100000,-0.100000)"
|
||||
fill="#000000" stroke="none">
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ module.exports = class Google extends Plugin {
|
|||
this.title = 'Google Drive'
|
||||
this.stateId = 'googleDrive'
|
||||
this.icon = () => html`
|
||||
<svg class="UppyIcon UppyModalTab-icon" width="28" height="28" viewBox="0 0 16 16">
|
||||
<svg aria-hidden="true" class="UppyIcon 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"/>
|
||||
</svg>
|
||||
`
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ module.exports = class Instagram extends Plugin {
|
|||
this.title = 'Instagram'
|
||||
this.stateId = 'instagram'
|
||||
this.icon = () => html`
|
||||
<svg class="UppyIcon UppyModalTab-icon" width="28" height="28" viewBox="0 0 512 512">
|
||||
<svg aria-hidden="true" class="UppyIcon UppyModalTab-icon" width="28" height="28" viewBox="0 0 512 512">
|
||||
<path
|
||||
d="M256,49.471c67.266,0,75.233.257,101.8,1.469,24.562,1.121,37.9,5.224,46.778,8.674a78.052,78.052,0,0,1,28.966,18.845,78.052,78.052,0,0,1,18.845,28.966c3.45,8.877,7.554,22.216,8.674,46.778,1.212,26.565,1.469,34.532,1.469,101.8s-0.257,75.233-1.469,101.8c-1.121,24.562-5.225,37.9-8.674,46.778a83.427,83.427,0,0,1-47.811,47.811c-8.877,3.45-22.216,7.554-46.778,8.674-26.56,1.212-34.527,1.469-101.8,1.469s-75.237-.257-101.8-1.469c-24.562-1.121-37.9-5.225-46.778-8.674a78.051,78.051,0,0,1-28.966-18.845,78.053,78.053,0,0,1-18.845-28.966c-3.45-8.877-7.554-22.216-8.674-46.778-1.212-26.564-1.469-34.532-1.469-101.8s0.257-75.233,1.469-101.8c1.121-24.562,5.224-37.9,8.674-46.778A78.052,78.052,0,0,1,78.458,78.458a78.053,78.053,0,0,1,28.966-18.845c8.877-3.45,22.216-7.554,46.778-8.674,26.565-1.212,34.532-1.469,101.8-1.469m0-45.391c-68.418,0-77,.29-103.866,1.516-26.815,1.224-45.127,5.482-61.151,11.71a123.488,123.488,0,0,0-44.62,29.057A123.488,123.488,0,0,0,17.3,90.982C11.077,107.007,6.819,125.319,5.6,152.134,4.369,179,4.079,187.582,4.079,256S4.369,333,5.6,359.866c1.224,26.815,5.482,45.127,11.71,61.151a123.489,123.489,0,0,0,29.057,44.62,123.486,123.486,0,0,0,44.62,29.057c16.025,6.228,34.337,10.486,61.151,11.71,26.87,1.226,35.449,1.516,103.866,1.516s77-.29,103.866-1.516c26.815-1.224,45.127-5.482,61.151-11.71a128.817,128.817,0,0,0,73.677-73.677c6.228-16.025,10.486-34.337,11.71-61.151,1.226-26.87,1.516-35.449,1.516-103.866s-0.29-77-1.516-103.866c-1.224-26.815-5.482-45.127-11.71-61.151a123.486,123.486,0,0,0-29.057-44.62A123.487,123.487,0,0,0,421.018,17.3C404.993,11.077,386.681,6.819,359.866,5.6,333,4.369,324.418,4.079,256,4.079h0Z"/>
|
||||
<path
|
||||
|
|
|
|||
|
|
@ -3,14 +3,16 @@ const indexedDB = window.indexedDB || window.webkitIndexedDB || window.mozIndexe
|
|||
const isSupported = !!indexedDB
|
||||
|
||||
const DB_NAME = 'uppy-blobs'
|
||||
const DB_VERSION = 1
|
||||
const STORE_NAME = 'files' // maybe have a thumbnail store in the future
|
||||
const DB_VERSION = 2
|
||||
|
||||
function connect (dbName, name) {
|
||||
function connect (dbName) {
|
||||
const request = indexedDB.open(dbName, DB_VERSION)
|
||||
return new Promise((resolve, reject) => {
|
||||
request.onupgradeneeded = (event) => {
|
||||
const db = event.target.result
|
||||
const store = db.createObjectStore(name, { keyPath: 'id' })
|
||||
const store = db.createObjectStore(STORE_NAME, { keyPath: 'id' })
|
||||
store.createIndex('store', 'store', { unique: false })
|
||||
store.transaction.oncomplete = () => {
|
||||
resolve(db)
|
||||
}
|
||||
|
|
@ -41,7 +43,11 @@ class IndexedDBStore {
|
|||
}, opts)
|
||||
|
||||
this.name = this.opts.storeName
|
||||
this.ready = connect(this.opts.dbName, this.opts.storeName)
|
||||
this.ready = connect(this.opts.dbName)
|
||||
}
|
||||
|
||||
key (fileID) {
|
||||
return `${this.name}!${fileID}`
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -49,13 +55,18 @@ class IndexedDBStore {
|
|||
*/
|
||||
list () {
|
||||
return this.ready.then((db) => {
|
||||
const transaction = db.transaction([this.name], 'readonly')
|
||||
const request = transaction.objectStore(this.name).getAll()
|
||||
const transaction = db.transaction([STORE_NAME], 'readonly')
|
||||
const store = transaction.objectStore(STORE_NAME)
|
||||
const request = store.index('store')
|
||||
.getAll(IDBKeyRange.only(this.name))
|
||||
return waitForRequest(request)
|
||||
}).then((files) => {
|
||||
const result = {}
|
||||
files.forEach((file) => {
|
||||
result[file.id] = file
|
||||
result[file.fileID] = {
|
||||
id: file.fileID,
|
||||
data: file.data
|
||||
}
|
||||
})
|
||||
return result
|
||||
})
|
||||
|
|
@ -66,10 +77,14 @@ class IndexedDBStore {
|
|||
*/
|
||||
get (fileID) {
|
||||
return this.ready.then((db) => {
|
||||
const transaction = db.transaction([this.name], 'readonly')
|
||||
const request = transaction.objectStore(this.name).get(fileID)
|
||||
const transaction = db.transaction([STORE_NAME], 'readonly')
|
||||
const request = transaction.objectStore(STORE_NAME)
|
||||
.get(this.key(fileID))
|
||||
return waitForRequest(request)
|
||||
}).then((result) => result.data)
|
||||
}).then((result) => ({
|
||||
id: result.data.fileID,
|
||||
data: result.data.data
|
||||
}))
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -79,8 +94,10 @@ class IndexedDBStore {
|
|||
*/
|
||||
getSize () {
|
||||
return this.ready.then((db) => {
|
||||
const transaction = db.transaction([this.name], 'readonly')
|
||||
const request = transaction.objectStore(this.name).openCursor()
|
||||
const transaction = db.transaction([STORE_NAME], 'readonly')
|
||||
const store = transaction.objectStore(STORE_NAME)
|
||||
const request = store.index('store')
|
||||
.openCursor(IDBKeyRange.only(this.name))
|
||||
return new Promise((resolve, reject) => {
|
||||
let size = 0
|
||||
request.onsuccess = (event) => {
|
||||
|
|
@ -112,9 +129,11 @@ class IndexedDBStore {
|
|||
}
|
||||
return this.ready
|
||||
}).then((db) => {
|
||||
const transaction = db.transaction([this.name], 'readwrite')
|
||||
const request = transaction.objectStore(this.name).add({
|
||||
id: file.id,
|
||||
const transaction = db.transaction([STORE_NAME], 'readwrite')
|
||||
const request = transaction.objectStore(STORE_NAME).add({
|
||||
id: this.key(file.id),
|
||||
fileID: file.id,
|
||||
store: this.name,
|
||||
data: file.data
|
||||
})
|
||||
return waitForRequest(request)
|
||||
|
|
@ -126,8 +145,9 @@ class IndexedDBStore {
|
|||
*/
|
||||
delete (fileID) {
|
||||
return this.ready.then((db) => {
|
||||
const transaction = db.transaction([this.name], 'readwrite')
|
||||
const request = transaction.objectStore(this.name).delete(fileID)
|
||||
const transaction = db.transaction([STORE_NAME], 'readwrite')
|
||||
const request = transaction.objectStore(STORE_NAME)
|
||||
.delete(this.key(fileID))
|
||||
return waitForRequest(request)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,12 +1,19 @@
|
|||
/* globals clients */
|
||||
|
||||
const fileCache = {}
|
||||
const fileCache = Object.create(null)
|
||||
|
||||
function getCache (name) {
|
||||
if (!fileCache[name]) {
|
||||
fileCache[name] = Object.create(null)
|
||||
}
|
||||
return fileCache[name]
|
||||
}
|
||||
|
||||
self.addEventListener('install', (event) => {
|
||||
console.log('Installing Uppy Service Worker...')
|
||||
|
||||
event.waitUntil(Promise.resolve()
|
||||
.then(() => self.skipWaiting()))
|
||||
.then(() => self.skipWaiting()))
|
||||
})
|
||||
|
||||
self.addEventListener('activate', (event) => {
|
||||
|
|
@ -21,30 +28,34 @@ function sendMessageToAllClients (msg) {
|
|||
})
|
||||
}
|
||||
|
||||
function addFile (file) {
|
||||
fileCache[file.id] = file
|
||||
function addFile (store, file) {
|
||||
getCache(store)[file.id] = file
|
||||
console.log('Added file to service worker cache:', file)
|
||||
}
|
||||
|
||||
function removeFile (fileID) {
|
||||
delete fileCache[fileID]
|
||||
function removeFile (store, fileID) {
|
||||
delete getCache(store)[fileID]
|
||||
console.log('Removed file from service worker cache:', fileID)
|
||||
}
|
||||
|
||||
function getFiles () {
|
||||
sendMessageToAllClients({ type: 'ALL_FILES', files: fileCache })
|
||||
function getFiles (store) {
|
||||
sendMessageToAllClients({
|
||||
type: 'uppy/ALL_FILES',
|
||||
store,
|
||||
files: getCache(store)
|
||||
})
|
||||
}
|
||||
|
||||
self.addEventListener('message', (event) => {
|
||||
switch (event.data.type) {
|
||||
case 'ADD_FILE':
|
||||
addFile(event.data.data)
|
||||
case 'uppy/ADD_FILE':
|
||||
addFile(event.data.store, event.data.data)
|
||||
break
|
||||
case 'REMOVE_FILE':
|
||||
removeFile(event.data.data)
|
||||
case 'uppy/REMOVE_FILE':
|
||||
removeFile(event.data.store, event.data.data)
|
||||
break
|
||||
case 'GET_FILES':
|
||||
getFiles()
|
||||
case 'uppy/GET_FILES':
|
||||
getFiles(event.data.store)
|
||||
break
|
||||
}
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const isSupported = 'serviceWorker' in navigator
|
||||
|
||||
class ServiceWorkerStore {
|
||||
constructor (core) {
|
||||
constructor (core, opts) {
|
||||
this.core = core
|
||||
this.ready = new Promise((resolve, reject) => {
|
||||
// service worker stuff
|
||||
|
|
@ -9,6 +9,7 @@ class ServiceWorkerStore {
|
|||
resolve()
|
||||
})
|
||||
})
|
||||
this.name = opts.storeName
|
||||
}
|
||||
|
||||
list () {
|
||||
|
|
@ -20,8 +21,11 @@ class ServiceWorkerStore {
|
|||
|
||||
console.log('Loading stored blobs from Service Worker')
|
||||
const onMessage = (event) => {
|
||||
if (event.data.store !== this.name) {
|
||||
return
|
||||
}
|
||||
switch (event.data.type) {
|
||||
case 'ALL_FILES':
|
||||
case 'uppy/ALL_FILES':
|
||||
defer.resolve(event.data.files)
|
||||
navigator.serviceWorker.removeEventListener('message', onMessage)
|
||||
break
|
||||
|
|
@ -32,7 +36,8 @@ class ServiceWorkerStore {
|
|||
navigator.serviceWorker.addEventListener('message', onMessage)
|
||||
|
||||
navigator.serviceWorker.controller.postMessage({
|
||||
type: 'GET_FILES'
|
||||
type: 'uppy/GET_FILES',
|
||||
data: { store: this.name }
|
||||
})
|
||||
})
|
||||
|
||||
|
|
@ -42,8 +47,9 @@ class ServiceWorkerStore {
|
|||
put (file) {
|
||||
return this.ready.then(() => {
|
||||
navigator.serviceWorker.controller.postMessage({
|
||||
type: 'ADD_FILE',
|
||||
type: 'uppy/ADD_FILE',
|
||||
data: {
|
||||
store: this.name,
|
||||
id: file.id,
|
||||
data: file.data
|
||||
}
|
||||
|
|
@ -54,7 +60,8 @@ class ServiceWorkerStore {
|
|||
delete (fileID) {
|
||||
return this.ready.then(() => {
|
||||
navigator.serviceWorker.controller.postMessage({
|
||||
type: 'REMOVE_FILE',
|
||||
type: 'uppy/REMOVE_FILE',
|
||||
store: this.name,
|
||||
data: fileID
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -25,9 +25,13 @@ module.exports = class RestoreFiles extends Plugin {
|
|||
// merge default options with the ones set by user
|
||||
this.opts = Object.assign({}, defaultOptions, opts)
|
||||
|
||||
// const Store = this.opts.serviceWorker ? ServiceWorkerStore : IndexedDBStore
|
||||
this.ServiceWorkerStore = this.opts.serviceWorker ? new ServiceWorkerStore(core) : false
|
||||
this.IndexedDBStore = new IndexedDBStore(core, opts.indexedDB || {})
|
||||
this.ServiceWorkerStore = null
|
||||
if (this.opts.serviceWorker) {
|
||||
this.ServiceWorkerStore = new ServiceWorkerStore(core, { storeName: core.getID() })
|
||||
}
|
||||
this.IndexedDBStore = new IndexedDBStore(core, Object.assign({},
|
||||
opts.indexedDB || {},
|
||||
{ storeName: core.getID() }))
|
||||
|
||||
this.saveFilesStateToLocalStorage = this.saveFilesStateToLocalStorage.bind(this)
|
||||
this.loadFilesStateFromLocalStorage = this.loadFilesStateFromLocalStorage.bind(this)
|
||||
|
|
@ -37,7 +41,7 @@ module.exports = class RestoreFiles extends Plugin {
|
|||
}
|
||||
|
||||
loadFilesStateFromLocalStorage () {
|
||||
const savedState = localStorage.getItem('uppyState')
|
||||
const savedState = localStorage.getItem(`uppyState:${this.core.opts.id}`)
|
||||
|
||||
if (savedState) {
|
||||
this.core.log('Recovered some state from Local Storage')
|
||||
|
|
@ -50,7 +54,7 @@ module.exports = class RestoreFiles extends Plugin {
|
|||
currentUploads: this.core.state.currentUploads,
|
||||
files: this.core.state.files
|
||||
})
|
||||
localStorage.setItem('uppyState', files)
|
||||
localStorage.setItem(`uppyState:${this.core.opts.id}`, files)
|
||||
}
|
||||
|
||||
loadFileBlobsFromServiceWorker () {
|
||||
|
|
|
|||
|
|
@ -141,7 +141,7 @@ const ProgressBarComplete = ({ totalProgress }) => {
|
|||
return html`
|
||||
<div class="UppyStatusBar-content">
|
||||
<span title="Complete">
|
||||
<svg class="UppyStatusBar-action UppyIcon" width="18" height="17" viewBox="0 0 23 17">
|
||||
<svg aria-hidden="true" class="UppyStatusBar-action UppyIcon" width="18" height="17" viewBox="0 0 23 17">
|
||||
<path d="M8.944 17L0 7.865l2.555-2.61 6.39 6.525L20.41 0 23 2.645z" />
|
||||
</svg>
|
||||
Upload complete・${totalProgress}%
|
||||
|
|
@ -170,13 +170,13 @@ const pauseResumeButtons = (props) => {
|
|||
return html`<button title="${title}" class="UppyStatusBar-action" type="button" onclick=${() => togglePauseResume(props)}>
|
||||
${props.resumableUploads
|
||||
? props.isAllPaused
|
||||
? html`<svg class="UppyIcon" width="15" height="17" viewBox="0 0 11 13">
|
||||
? html`<svg aria-hidden="true" class="UppyIcon" width="15" height="17" viewBox="0 0 11 13">
|
||||
<path d="M1.26 12.534a.67.67 0 0 1-.674.012.67.67 0 0 1-.336-.583v-11C.25.724.38.5.586.382a.658.658 0 0 1 .673.012l9.165 5.5a.66.66 0 0 1 .325.57.66.66 0 0 1-.325.573l-9.166 5.5z" />
|
||||
</svg>`
|
||||
: html`<svg class="UppyIcon" width="16" height="17" viewBox="0 0 12 13">
|
||||
: html`<svg aria-hidden="true" class="UppyIcon" width="16" height="17" viewBox="0 0 12 13">
|
||||
<path d="M4.888.81v11.38c0 .446-.324.81-.722.81H2.722C2.324 13 2 12.636 2 12.19V.81c0-.446.324-.81.722-.81h1.444c.398 0 .722.364.722.81zM9.888.81v11.38c0 .446-.324.81-.722.81H7.722C7.324 13 7 12.636 7 12.19V.81c0-.446.324-.81.722-.81h1.444c.398 0 .722.364.722.81z"/>
|
||||
</svg>`
|
||||
: html`<svg class="UppyIcon" width="16px" height="16px" viewBox="0 0 19 19">
|
||||
: html`<svg aria-hidden="true" class="UppyIcon" width="16px" height="16px" viewBox="0 0 19 19">
|
||||
<path d="M17.318 17.232L9.94 9.854 9.586 9.5l-.354.354-7.378 7.378h.707l-.62-.62v.706L9.318 9.94l.354-.354-.354-.354L1.94 1.854v.707l.62-.62h-.706l7.378 7.378.354.354.354-.354 7.378-7.378h-.707l.622.62v-.706L9.854 9.232l-.354.354.354.354 7.378 7.378.708-.707-7.38-7.378v.708l7.38-7.38.353-.353-.353-.353-.622-.622-.353-.353-.354.352-7.378 7.38h.708L2.56 1.23 2.208.88l-.353.353-.622.62-.353.355.352.353 7.38 7.38v-.708l-7.38 7.38-.353.353.352.353.622.622.353.353.354-.353 7.38-7.38h-.708l7.38 7.38z"/>
|
||||
</svg>`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ const prettyBytes = require('prettier-bytes')
|
|||
module.exports = class StatusBarUI extends Plugin {
|
||||
constructor (core, opts) {
|
||||
super(core, opts)
|
||||
this.id = 'StatusBarUI'
|
||||
this.title = 'StatusBar UI'
|
||||
this.id = 'StatusBar'
|
||||
this.title = 'StatusBar'
|
||||
this.type = 'progressindicator'
|
||||
|
||||
// set default options
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
const Plugin = require('./Plugin')
|
||||
const tus = require('tus-js-client')
|
||||
const settle = require('promise-settle')
|
||||
const UppySocket = require('../core/UppySocket')
|
||||
const Utils = require('../core/Utils')
|
||||
require('whatwg-fetch')
|
||||
|
|
@ -324,16 +325,16 @@ module.exports = class Tus10 extends Plugin {
|
|||
}
|
||||
|
||||
uploadFiles (files) {
|
||||
files.forEach((file, index) => {
|
||||
return settle(files.map((file, index) => {
|
||||
const current = parseInt(index, 10) + 1
|
||||
const total = files.length
|
||||
|
||||
if (!file.isRemote) {
|
||||
this.upload(file, current, total)
|
||||
return this.upload(file, current, total)
|
||||
} else {
|
||||
this.uploadRemote(file, current, total)
|
||||
return this.uploadRemote(file, current, total)
|
||||
}
|
||||
})
|
||||
}))
|
||||
}
|
||||
|
||||
handleUpload (fileIDs) {
|
||||
|
|
@ -345,11 +346,7 @@ module.exports = class Tus10 extends Plugin {
|
|||
this.core.log('Tus is uploading...')
|
||||
const filesToUpload = fileIDs.map((fileID) => this.core.getFile(fileID))
|
||||
|
||||
this.uploadFiles(filesToUpload)
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.core.once('core:upload-complete', resolve)
|
||||
})
|
||||
return this.uploadFiles(filesToUpload)
|
||||
}
|
||||
|
||||
actions () {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const html = require('yo-yo')
|
||||
|
||||
module.exports = (props) => {
|
||||
return html`<svg class="UppyIcon" width="100" height="77" viewBox="0 0 100 77">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="100" height="77" viewBox="0 0 100 77">
|
||||
<path d="M50 32c-7.168 0-13 5.832-13 13s5.832 13 13 13 13-5.832 13-13-5.832-13-13-13z"/>
|
||||
<path d="M87 13H72c0-7.18-5.82-13-13-13H41c-7.18 0-13 5.82-13 13H13C5.82 13 0 18.82 0 26v38c0 7.18 5.82 13 13 13h74c7.18 0 13-5.82 13-13V26c0-7.18-5.82-13-13-13zM50 68c-12.683 0-23-10.318-23-23s10.317-23 23-23 23 10.318 23 23-10.317 23-23 23z"/>
|
||||
</svg>`
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const html = require('yo-yo')
|
||||
|
||||
module.exports = (props) => {
|
||||
return html`<svg class="UppyIcon" width="100" height="100" viewBox="0 0 100 100">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="100" height="100" viewBox="0 0 100 100">
|
||||
<circle cx="50" cy="50" r="40" />
|
||||
</svg>`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
const html = require('yo-yo')
|
||||
|
||||
module.exports = (props) => {
|
||||
return html`<svg class="UppyIcon" width="100" height="100" viewBox="0 0 100 100">
|
||||
return html`<svg aria-hidden="true" class="UppyIcon" width="100" height="100" viewBox="0 0 100 100">
|
||||
<rect x="15" y="15" width="70" height="70" />
|
||||
</svg>`
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ const html = require('yo-yo')
|
|||
|
||||
module.exports = (props) => {
|
||||
return html`
|
||||
<svg class="UppyIcon" width="18" height="21" viewBox="0 0 18 21">
|
||||
<svg aria-hidden="true" class="UppyIcon" width="18" height="21" viewBox="0 0 18 21">
|
||||
<path d="M14.8 16.9c1.9-1.7 3.2-4.1 3.2-6.9 0-5-4-9-9-9s-9 4-9 9c0 2.8 1.2 5.2 3.2 6.9C1.9 17.9.5 19.4 0 21h3c1-1.9 11-1.9 12 0h3c-.5-1.6-1.9-3.1-3.2-4.1zM9 4c3.3 0 6 2.7 6 6s-2.7 6-6 6-6-2.7-6-6 2.7-6 6-6z"/>
|
||||
<path d="M9 14c2.2 0 4-1.8 4-4s-1.8-4-4-4-4 1.8-4 4 1.8 4 4 4zM8 8c.6 0 1 .4 1 1s-.4 1-1 1-1-.4-1-1c0-.5.4-1 1-1z"/>
|
||||
</svg>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
const Plugin = require('./Plugin')
|
||||
const settle = require('promise-settle')
|
||||
const UppySocket = require('../core/UppySocket')
|
||||
const Utils = require('../core/Utils')
|
||||
|
||||
|
|
@ -176,16 +177,16 @@ module.exports = class XHRUpload extends Plugin {
|
|||
}
|
||||
|
||||
selectForUpload (files) {
|
||||
files.forEach((file, i) => {
|
||||
return settle(files.map((file, i) => {
|
||||
const current = parseInt(i, 10) + 1
|
||||
const total = files.length
|
||||
|
||||
if (file.isRemote) {
|
||||
this.uploadRemote(file, current, total)
|
||||
return this.uploadRemote(file, current, total)
|
||||
} else {
|
||||
this.upload(file, current, total)
|
||||
return this.upload(file, current, total)
|
||||
}
|
||||
})
|
||||
}))
|
||||
|
||||
// if (this.opts.bundle) {
|
||||
// uploaders.push(this.upload(files, 0, files.length))
|
||||
|
|
@ -208,11 +209,7 @@ module.exports = class XHRUpload extends Plugin {
|
|||
return this.core.state.files[fileID]
|
||||
}
|
||||
|
||||
this.selectForUpload(files)
|
||||
|
||||
return new Promise((resolve) => {
|
||||
this.core.once('core:upload-complete', resolve)
|
||||
})
|
||||
return this.selectForUpload(files).then(() => null)
|
||||
}
|
||||
|
||||
install () {
|
||||
|
|
|
|||
|
|
@ -21,12 +21,14 @@ Dashboard is a universal UI plugin for Uppy:
|
|||
uppy.use(Dashboard, {
|
||||
target: 'body',
|
||||
getMetaFromForm: true,
|
||||
trigger: '#uppy-select-files',
|
||||
inline: false,
|
||||
width: 750,
|
||||
height: 550,
|
||||
showProgressDetails: false,
|
||||
hideUploadButton: false,
|
||||
note: false,
|
||||
disableStatusBar: false,
|
||||
disableInformer: false,
|
||||
closeModalOnClickOutside: false,
|
||||
locale: {
|
||||
strings: {
|
||||
selectToUpload: 'Select files to upload',
|
||||
|
|
@ -60,7 +62,7 @@ By default Dashboard will be rendered as a modal, which is opened via clicking o
|
|||
|
||||
### `trigger: '#uppy-select-files'`
|
||||
|
||||
String with a CSS selector for a button that will trigger opening Dashboard modal.
|
||||
String with a CSS selector for a button that will trigger opening Dashboard modal. Multiple buttons or links can be used, if it’s a class selector (`.uppy-choose`, for example).
|
||||
|
||||
### `width: 750`
|
||||
|
||||
|
|
@ -88,4 +90,29 @@ See [general plugin options](/docs/plugins).
|
|||
|
||||
### `locale`
|
||||
|
||||
See [general plugin options](/docs/plugins).
|
||||
See [general plugin options](/docs/plugins).
|
||||
|
||||
## Methods
|
||||
|
||||
### `openModal()`
|
||||
|
||||
Shows the Dashboard modal. Use it like this:
|
||||
|
||||
`uppy.getPlugin('Dashboard').openModal()`
|
||||
|
||||
### `closeModal()`
|
||||
|
||||
Hides the Dashboard modal. Use it like this:
|
||||
|
||||
`uppy.getPlugin('Dashboard').closeModal()`
|
||||
|
||||
### `isModalOpen()`
|
||||
|
||||
Returns `true` if the Dashboard modal is open, `false` otherwise.
|
||||
|
||||
```js
|
||||
const dashboard = uppy.getPlugin('Dashboard')
|
||||
if ( dashboard.isModalOpen() ) {
|
||||
dashboard.closeModal()
|
||||
}
|
||||
```
|
||||
|
|
@ -11,6 +11,7 @@ Core module that orchistrated everything in Uppy, exposing `state`, `events` and
|
|||
|
||||
```js
|
||||
const uppy = Uppy({
|
||||
id: 'uppy',
|
||||
autoProceed: true,
|
||||
restrictions: {
|
||||
maxFileSize: false,
|
||||
|
|
@ -25,6 +26,20 @@ const uppy = Uppy({
|
|||
})
|
||||
```
|
||||
|
||||
### `id: 'uppy'`
|
||||
|
||||
A site-wide unique ID for the instance.
|
||||
If multiple Uppy instances are being used, for example on two different pages, an `id` should be specified.
|
||||
This allows Uppy to store information in `localStorage` without colliding with other Uppy instances.
|
||||
|
||||
Note that this ID should be persistent across page reloads and navigation—it shouldn't be a random number that's different every time Uppy is loaded.
|
||||
For example, if one Uppy instance is used to upload user avatars, and another to add photos to a blog post, you might use:
|
||||
|
||||
```js
|
||||
const avatarUploader = Uppy({ id: 'avatar' })
|
||||
const photoUploader = Uppy({ id: 'post' })
|
||||
```
|
||||
|
||||
### `autoProceed: true`
|
||||
|
||||
Starts upload automatically after the first file is selected.
|
||||
|
|
@ -129,6 +144,10 @@ uppy.use(DragDrop, {target: 'body'})
|
|||
|
||||
Initializes everything after setup. Must be called before calling `.upload()` or using Uppy in any meaningful way.
|
||||
|
||||
### `uppy.getID()`
|
||||
|
||||
Get the uppy instance ID, see the [`id` option](#id-39-uppy-39).
|
||||
|
||||
### `uppy.addFile(fileObject)`
|
||||
|
||||
Add a new file to Uppy’s internal state.
|
||||
|
|
@ -222,7 +241,7 @@ uppy.updateMeta('myfileID', {resize: 1500})
|
|||
|
||||
### `uppy.reset()`
|
||||
|
||||
Stop all uploads in progress and clear file selection, set progress to 0. Basically, return things to the way they were before any user input.
|
||||
Stop all uploads in progress and clear file selection, set progress to 0. Basically, return things to the way they were before any user input.
|
||||
|
||||
### `uppy.close()`
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue