mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-22 01:40:29 +00:00
Mention the file name in exceedsSize error message (#2918)
* Mention the file name in exceedsSize error message * Fix implementation and tests * Undo accidental commited changes
This commit is contained in:
parent
d4c5d715b6
commit
f2d30420f3
4 changed files with 126 additions and 113 deletions
|
|
@ -13,6 +13,8 @@ const findIndex = require('@uppy/utils/lib/findIndex')
|
|||
const supportsUploadProgress = require('./supportsUploadProgress')
|
||||
const { justErrorsLogger, debugLogger } = require('./loggers')
|
||||
const Plugin = require('./Plugin')
|
||||
const { version } = require('../package.json')
|
||||
|
||||
// Exported from here.
|
||||
class RestrictionError extends Error {
|
||||
constructor (...args) {
|
||||
|
|
@ -27,7 +29,7 @@ class RestrictionError extends Error {
|
|||
* adds/removes files and metadata.
|
||||
*/
|
||||
class Uppy {
|
||||
static VERSION = require('../package.json').version
|
||||
static VERSION = version
|
||||
|
||||
/**
|
||||
* Instantiate Uppy
|
||||
|
|
@ -55,7 +57,7 @@ class Uppy {
|
|||
// substitution.
|
||||
// TODO: In 2.0 `exceedsSize2` should be removed in and `exceedsSize` updated to use substitution.
|
||||
exceedsSize2: '%{backwardsCompat} %{size}',
|
||||
exceedsSize: 'This file exceeds maximum allowed size of',
|
||||
exceedsSize: '%{file} exceeds maximum allowed size of',
|
||||
inferiorSize: 'This file is smaller than the allowed size of %{size}',
|
||||
youCanOnlyUploadFileTypes: 'You can only upload: %{types}',
|
||||
noNewAlreadyUploading: 'Cannot add new files: already uploading',
|
||||
|
|
@ -108,7 +110,7 @@ class Uppy {
|
|||
allowedFileTypes: null,
|
||||
},
|
||||
meta: {},
|
||||
onBeforeFileAdded: (currentFile, files) => currentFile,
|
||||
onBeforeFileAdded: (currentFile) => currentFile,
|
||||
onBeforeUpload: (files) => files,
|
||||
store: DefaultStore(),
|
||||
logger: justErrorsLogger,
|
||||
|
|
@ -160,11 +162,13 @@ class Uppy {
|
|||
this.validateRestrictions = this.validateRestrictions.bind(this)
|
||||
|
||||
// ___Why throttle at 500ms?
|
||||
// - We must throttle at >250ms for superfocus in Dashboard to work well (because animation takes 0.25s, and we want to wait for all animations to be over before refocusing).
|
||||
// [Practical Check]: if thottle is at 100ms, then if you are uploading a file, and click 'ADD MORE FILES', - focus won't activate in Firefox.
|
||||
// - We must throttle at >250ms for superfocus in Dashboard to work well
|
||||
// (because animation takes 0.25s, and we want to wait for all animations to be over before refocusing).
|
||||
// [Practical Check]: if thottle is at 100ms, then if you are uploading a file,
|
||||
// and click 'ADD MORE FILES', - focus won't activate in Firefox.
|
||||
// - We must throttle at around >500ms to avoid performance lags.
|
||||
// [Practical Check] Firefox, try to upload a big file for a prolonged period of time. Laptop will start to heat up.
|
||||
this._calculateProgress = throttle(this._calculateProgress.bind(this), 500, { leading: true, trailing: true })
|
||||
this.calculateProgress = throttle(this.calculateProgress.bind(this), 500, { leading: true, trailing: true })
|
||||
|
||||
this.updateOnlineStatus = this.updateOnlineStatus.bind(this)
|
||||
this.resetProgress = this.resetProgress.bind(this)
|
||||
|
|
@ -207,7 +211,7 @@ class Uppy {
|
|||
recoveredState: null,
|
||||
})
|
||||
|
||||
this._storeUnsubscribe = this.store.subscribe((prevState, nextState, patch) => {
|
||||
this.storeUnsubscribe = this.store.subscribe((prevState, nextState, patch) => {
|
||||
this.emit('state-update', prevState, nextState, patch)
|
||||
this.updateAll(nextState)
|
||||
})
|
||||
|
|
@ -217,7 +221,7 @@ class Uppy {
|
|||
window[this.opts.id] = this
|
||||
}
|
||||
|
||||
this._addListeners()
|
||||
this.addListeners()
|
||||
|
||||
// Re-enable if we’ll need some capabilities on boot, like isMobileDevice
|
||||
// this._setCapabilities()
|
||||
|
|
@ -436,7 +440,7 @@ class Uppy {
|
|||
*/
|
||||
validateRestrictions (file, files) {
|
||||
try {
|
||||
this._checkRestrictions(file, files)
|
||||
this.checkRestrictions(file, files)
|
||||
return {
|
||||
result: true,
|
||||
}
|
||||
|
|
@ -456,7 +460,7 @@ class Uppy {
|
|||
* @param {Array} [files] array to check maxNumberOfFiles and maxTotalFileSize
|
||||
* @private
|
||||
*/
|
||||
_checkRestrictions (file, files = this.getFiles()) {
|
||||
checkRestrictions (file, files = this.getFiles()) {
|
||||
const { maxFileSize, minFileSize, maxTotalFileSize, maxNumberOfFiles, allowedFileTypes } = this.opts.restrictions
|
||||
|
||||
if (maxNumberOfFiles) {
|
||||
|
|
@ -490,13 +494,14 @@ class Uppy {
|
|||
if (maxTotalFileSize && file.size != null) {
|
||||
let totalFilesSize = 0
|
||||
totalFilesSize += file.size
|
||||
files.forEach((file) => {
|
||||
totalFilesSize += file.size
|
||||
files.forEach((f) => {
|
||||
totalFilesSize += f.size
|
||||
})
|
||||
if (totalFilesSize > maxTotalFileSize) {
|
||||
throw new RestrictionError(this.i18n('exceedsSize2', {
|
||||
backwardsCompat: this.i18n('exceedsSize'),
|
||||
size: prettierBytes(maxTotalFileSize),
|
||||
file: file.name,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
@ -507,6 +512,7 @@ class Uppy {
|
|||
throw new RestrictionError(this.i18n('exceedsSize2', {
|
||||
backwardsCompat: this.i18n('exceedsSize'),
|
||||
size: prettierBytes(maxFileSize),
|
||||
file: file.name,
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
|
@ -526,7 +532,7 @@ class Uppy {
|
|||
*
|
||||
* @private
|
||||
*/
|
||||
_checkMinNumberOfFiles (files) {
|
||||
checkMinNumberOfFiles (files) {
|
||||
const { minNumberOfFiles } = this.opts.restrictions
|
||||
if (Object.keys(files).length < minNumberOfFiles) {
|
||||
throw new RestrictionError(`${this.i18n('youHaveToAtLeastSelectX', { smart_count: minNumberOfFiles })}`)
|
||||
|
|
@ -544,7 +550,7 @@ class Uppy {
|
|||
* @param {boolean} [options.throwErr=true] — Errors shouldn’t be thrown, for example, in `upload-error` event
|
||||
* @private
|
||||
*/
|
||||
_showOrLogErrorAndThrow (err, { showInformer = true, file = null, throwErr = true } = {}) {
|
||||
showOrLogErrorAndThrow (err, { showInformer = true, file = null, throwErr = true } = {}) {
|
||||
const message = typeof err === 'object' ? err.message : err
|
||||
const details = (typeof err === 'object' && err.details) ? err.details : ''
|
||||
|
||||
|
|
@ -572,11 +578,11 @@ class Uppy {
|
|||
}
|
||||
}
|
||||
|
||||
_assertNewUploadAllowed (file) {
|
||||
assertNewUploadAllowed (file) {
|
||||
const { allowNewUpload } = this.getState()
|
||||
|
||||
if (allowNewUpload === false) {
|
||||
this._showOrLogErrorAndThrow(new RestrictionError(this.i18n('noNewAlreadyUploading')), { file })
|
||||
this.showOrLogErrorAndThrow(new RestrictionError(this.i18n('noNewAlreadyUploading')), { file })
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -587,15 +593,16 @@ class Uppy {
|
|||
*
|
||||
* The `files` value is passed in because it may be updated by the caller without updating the store.
|
||||
*/
|
||||
_checkAndCreateFileStateObject (files, file) {
|
||||
const fileType = getFileType(file)
|
||||
checkAndCreateFileStateObject (files, f) {
|
||||
const fileType = getFileType(f)
|
||||
let file = f
|
||||
file.type = fileType
|
||||
|
||||
const onBeforeFileAddedResult = this.opts.onBeforeFileAdded(file, files)
|
||||
|
||||
if (onBeforeFileAddedResult === false) {
|
||||
// Don’t show UI info for this error, as it should be done by the developer
|
||||
this._showOrLogErrorAndThrow(new RestrictionError('Cannot add the file because onBeforeFileAdded returned false.'), { showInformer: false, file })
|
||||
this.showOrLogErrorAndThrow(new RestrictionError('Cannot add the file because onBeforeFileAdded returned false.'), { showInformer: false, file })
|
||||
}
|
||||
|
||||
if (typeof onBeforeFileAddedResult === 'object' && onBeforeFileAddedResult) {
|
||||
|
|
@ -616,7 +623,7 @@ class Uppy {
|
|||
const fileID = generateFileID(file)
|
||||
|
||||
if (files[fileID] && !files[fileID].isGhost) {
|
||||
this._showOrLogErrorAndThrow(new RestrictionError(this.i18n('noDuplicates', { fileName })), { file })
|
||||
this.showOrLogErrorAndThrow(new RestrictionError(this.i18n('noDuplicates', { fileName })), { file })
|
||||
}
|
||||
|
||||
const meta = file.meta || {}
|
||||
|
|
@ -624,7 +631,7 @@ class Uppy {
|
|||
meta.type = fileType
|
||||
|
||||
// `null` means the size is unknown.
|
||||
const size = isFinite(file.data.size) ? file.data.size : null
|
||||
const size = Number.isFinite(file.data.size) ? file.data.size : null
|
||||
const newFile = {
|
||||
source: file.source || '',
|
||||
id: fileID,
|
||||
|
|
@ -651,16 +658,16 @@ class Uppy {
|
|||
|
||||
try {
|
||||
const filesArray = Object.keys(files).map(i => files[i])
|
||||
this._checkRestrictions(newFile, filesArray)
|
||||
this.checkRestrictions(newFile, filesArray)
|
||||
} catch (err) {
|
||||
this._showOrLogErrorAndThrow(err, { file: newFile })
|
||||
this.showOrLogErrorAndThrow(err, { file: newFile })
|
||||
}
|
||||
|
||||
return newFile
|
||||
}
|
||||
|
||||
// Schedule an upload if `autoProceed` is enabled.
|
||||
_startIfAutoProceed () {
|
||||
startIfAutoProceed () {
|
||||
if (this.opts.autoProceed && !this.scheduledAutoProceed) {
|
||||
this.scheduledAutoProceed = setTimeout(() => {
|
||||
this.scheduledAutoProceed = null
|
||||
|
|
@ -682,10 +689,10 @@ class Uppy {
|
|||
* @returns {string} id for the added file
|
||||
*/
|
||||
addFile (file) {
|
||||
this._assertNewUploadAllowed(file)
|
||||
this.assertNewUploadAllowed(file)
|
||||
|
||||
const { files } = this.getState()
|
||||
let newFile = this._checkAndCreateFileStateObject(files, file)
|
||||
let newFile = this.checkAndCreateFileStateObject(files, file)
|
||||
|
||||
// Users are asked to re-select recovered files without data,
|
||||
// and to keep the progress, meta and everthing else, we only replace said data
|
||||
|
|
@ -709,7 +716,7 @@ class Uppy {
|
|||
this.emit('files-added', [newFile])
|
||||
this.log(`Added file: ${newFile.name}, ${newFile.id}, mime type: ${newFile.type}`)
|
||||
|
||||
this._startIfAutoProceed()
|
||||
this.startIfAutoProceed()
|
||||
|
||||
return newFile.id
|
||||
}
|
||||
|
|
@ -722,7 +729,7 @@ class Uppy {
|
|||
* Programmatic users should usually still use `addFile()` on individual files.
|
||||
*/
|
||||
addFiles (fileDescriptors) {
|
||||
this._assertNewUploadAllowed()
|
||||
this.assertNewUploadAllowed()
|
||||
|
||||
// create a copy of the files object only once
|
||||
const files = { ...this.getState().files }
|
||||
|
|
@ -730,7 +737,7 @@ class Uppy {
|
|||
const errors = []
|
||||
for (let i = 0; i < fileDescriptors.length; i++) {
|
||||
try {
|
||||
let newFile = this._checkAndCreateFileStateObject(files, fileDescriptors[i])
|
||||
let newFile = this.checkAndCreateFileStateObject(files, fileDescriptors[i])
|
||||
// Users are asked to re-select recovered files without data,
|
||||
// and to keep the progress, meta and everthing else, we only replace said data
|
||||
if (files[newFile.id] && files[newFile.id].isGhost) {
|
||||
|
|
@ -767,7 +774,7 @@ class Uppy {
|
|||
}
|
||||
|
||||
if (newFiles.length > 0) {
|
||||
this._startIfAutoProceed()
|
||||
this.startIfAutoProceed()
|
||||
}
|
||||
|
||||
if (errors.length > 0) {
|
||||
|
|
@ -838,7 +845,7 @@ class Uppy {
|
|||
}
|
||||
|
||||
this.setState(stateUpdate)
|
||||
this._calculateTotalProgress()
|
||||
this.calculateTotalProgress()
|
||||
|
||||
const removedFileIDs = Object.keys(removedFiles)
|
||||
removedFileIDs.forEach((fileID) => {
|
||||
|
|
@ -859,7 +866,7 @@ class Uppy {
|
|||
pauseResume (fileID) {
|
||||
if (!this.getState().capabilities.resumableUploads
|
||||
|| this.getFile(fileID).uploadComplete) {
|
||||
return
|
||||
return undefined
|
||||
}
|
||||
|
||||
const wasPaused = this.getFile(fileID).isPaused || false
|
||||
|
|
@ -938,10 +945,10 @@ class Uppy {
|
|||
})
|
||||
}
|
||||
|
||||
const uploadID = this._createUpload(filesToRetry, {
|
||||
const uploadID = this.createUpload(filesToRetry, {
|
||||
forceAllowNewUpload: true, // create new upload even if allowNewUpload: false
|
||||
})
|
||||
return this._runUpload(uploadID)
|
||||
return this.runUpload(uploadID)
|
||||
}
|
||||
|
||||
cancelAll () {
|
||||
|
|
@ -969,10 +976,10 @@ class Uppy {
|
|||
|
||||
this.emit('upload-retry', fileID)
|
||||
|
||||
const uploadID = this._createUpload([fileID], {
|
||||
const uploadID = this.createUpload([fileID], {
|
||||
forceAllowNewUpload: true, // create new upload even if allowNewUpload: false
|
||||
})
|
||||
return this._runUpload(uploadID)
|
||||
return this.runUpload(uploadID)
|
||||
}
|
||||
|
||||
reset () {
|
||||
|
|
@ -987,14 +994,14 @@ class Uppy {
|
|||
})
|
||||
}
|
||||
|
||||
_calculateProgress (file, data) {
|
||||
calculateProgress (file, data) {
|
||||
if (!this.getFile(file.id)) {
|
||||
this.log(`Not setting progress for a file that has been removed: ${file.id}`)
|
||||
return
|
||||
}
|
||||
|
||||
// bytesTotal may be null or zero; in that case we can't divide by it
|
||||
const canHavePercentage = isFinite(data.bytesTotal) && data.bytesTotal > 0
|
||||
const canHavePercentage = Number.isFinite(data.bytesTotal) && data.bytesTotal > 0
|
||||
this.setFileState(file.id, {
|
||||
progress: {
|
||||
...this.getFile(file.id).progress,
|
||||
|
|
@ -1003,15 +1010,15 @@ class Uppy {
|
|||
percentage: canHavePercentage
|
||||
// TODO(goto-bus-stop) flooring this should probably be the choice of the UI?
|
||||
// we get more accurate calculations if we don't round this at all.
|
||||
? Math.round(data.bytesUploaded / data.bytesTotal * 100)
|
||||
? Math.round((data.bytesUploaded / data.bytesTotal) * 100)
|
||||
: 0,
|
||||
},
|
||||
})
|
||||
|
||||
this._calculateTotalProgress()
|
||||
this.calculateTotalProgress()
|
||||
}
|
||||
|
||||
_calculateTotalProgress () {
|
||||
calculateTotalProgress () {
|
||||
// calculate total progress, using the number of files currently uploading,
|
||||
// multiplied by 100 and the summ of individual progress of each file
|
||||
const files = this.getFiles()
|
||||
|
|
@ -1036,7 +1043,7 @@ class Uppy {
|
|||
const currentProgress = unsizedFiles.reduce((acc, file) => {
|
||||
return acc + file.progress.percentage
|
||||
}, 0)
|
||||
const totalProgress = Math.round(currentProgress / progressMax * 100)
|
||||
const totalProgress = Math.round((currentProgress / progressMax) * 100)
|
||||
this.setState({ totalProgress })
|
||||
return
|
||||
}
|
||||
|
|
@ -1052,12 +1059,12 @@ class Uppy {
|
|||
uploadedSize += file.progress.bytesUploaded
|
||||
})
|
||||
unsizedFiles.forEach((file) => {
|
||||
uploadedSize += averageSize * (file.progress.percentage || 0) / 100
|
||||
uploadedSize += (averageSize * (file.progress.percentage || 0)) / 100
|
||||
})
|
||||
|
||||
let totalProgress = totalSize === 0
|
||||
? 0
|
||||
: Math.round(uploadedSize / totalSize * 100)
|
||||
: Math.round((uploadedSize / totalSize) * 100)
|
||||
|
||||
// hot fix, because:
|
||||
// uploadedSize ended up larger than totalSize, resulting in 1325% total
|
||||
|
|
@ -1073,7 +1080,7 @@ class Uppy {
|
|||
* Registers listeners for all global actions, like:
|
||||
* `error`, `file-removed`, `upload-progress`
|
||||
*/
|
||||
_addListeners () {
|
||||
addListeners () {
|
||||
/**
|
||||
* @param {Error} error
|
||||
* @param {object} [file]
|
||||
|
|
@ -1107,11 +1114,11 @@ class Uppy {
|
|||
newError.details += ` ${error.details}`
|
||||
}
|
||||
newError.message = this.i18n('failedToUpload', { file: file.name })
|
||||
this._showOrLogErrorAndThrow(newError, {
|
||||
this.showOrLogErrorAndThrow(newError, {
|
||||
throwErr: false,
|
||||
})
|
||||
} else {
|
||||
this._showOrLogErrorAndThrow(error, {
|
||||
this.showOrLogErrorAndThrow(error, {
|
||||
throwErr: false,
|
||||
})
|
||||
}
|
||||
|
|
@ -1121,7 +1128,7 @@ class Uppy {
|
|||
this.setState({ error: null })
|
||||
})
|
||||
|
||||
this.on('upload-started', (file, upload) => {
|
||||
this.on('upload-started', (file) => {
|
||||
if (!this.getFile(file.id)) {
|
||||
this.log(`Not setting progress for a file that has been removed: ${file.id}`)
|
||||
return
|
||||
|
|
@ -1137,7 +1144,7 @@ class Uppy {
|
|||
})
|
||||
})
|
||||
|
||||
this.on('upload-progress', this._calculateProgress)
|
||||
this.on('upload-progress', this.calculateProgress)
|
||||
|
||||
this.on('upload-success', (file, uploadResp) => {
|
||||
if (!this.getFile(file.id)) {
|
||||
|
|
@ -1161,7 +1168,7 @@ class Uppy {
|
|||
isPaused: false,
|
||||
})
|
||||
|
||||
this._calculateTotalProgress()
|
||||
this.calculateTotalProgress()
|
||||
})
|
||||
|
||||
this.on('preprocess-progress', (file, progress) => {
|
||||
|
|
@ -1220,7 +1227,7 @@ class Uppy {
|
|||
|
||||
this.on('restored', () => {
|
||||
// Files may have changed--ensure progress is still accurate.
|
||||
this._calculateTotalProgress()
|
||||
this.calculateTotalProgress()
|
||||
})
|
||||
|
||||
// show informer if offline
|
||||
|
|
@ -1261,6 +1268,7 @@ class Uppy {
|
|||
* @param {object} [opts] object with options to be passed to Plugin
|
||||
* @returns {object} self for chaining
|
||||
*/
|
||||
// eslint-disable-next-line no-shadow
|
||||
use (Plugin, opts) {
|
||||
if (typeof Plugin !== 'function') {
|
||||
const msg = `Expected a plugin class, but got ${Plugin === null ? 'null' : typeof Plugin}.`
|
||||
|
|
@ -1368,7 +1376,7 @@ class Uppy {
|
|||
|
||||
this.reset()
|
||||
|
||||
this._storeUnsubscribe()
|
||||
this.storeUnsubscribe()
|
||||
|
||||
this.iteratePlugins((plugin) => {
|
||||
this.removePlugin(plugin)
|
||||
|
|
@ -1447,11 +1455,11 @@ class Uppy {
|
|||
this.log(`Core: attempting to restore upload "${uploadID}"`)
|
||||
|
||||
if (!this.getState().currentUploads[uploadID]) {
|
||||
this._removeUpload(uploadID)
|
||||
this.removeUpload(uploadID)
|
||||
return Promise.reject(new Error('Nonexistent upload'))
|
||||
}
|
||||
|
||||
return this._runUpload(uploadID)
|
||||
return this.runUpload(uploadID)
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1460,10 +1468,9 @@ class Uppy {
|
|||
* @param {Array<string>} fileIDs File IDs to include in this upload.
|
||||
* @returns {string} ID of this upload.
|
||||
*/
|
||||
_createUpload (fileIDs, opts = {}) {
|
||||
const {
|
||||
forceAllowNewUpload = false, // uppy.retryAll sets this to true — when retrying we want to ignore `allowNewUpload: false`
|
||||
} = opts
|
||||
createUpload (fileIDs, opts = {}) {
|
||||
// uppy.retryAll sets this to true — when retrying we want to ignore `allowNewUpload: false`
|
||||
const { forceAllowNewUpload = false } = opts
|
||||
|
||||
const { allowNewUpload, currentUploads } = this.getState()
|
||||
if (!allowNewUpload && !forceAllowNewUpload) {
|
||||
|
|
@ -1493,7 +1500,7 @@ class Uppy {
|
|||
return uploadID
|
||||
}
|
||||
|
||||
_getUpload (uploadID) {
|
||||
getUpload (uploadID) {
|
||||
const { currentUploads } = this.getState()
|
||||
|
||||
return currentUploads[uploadID]
|
||||
|
|
@ -1506,7 +1513,7 @@ class Uppy {
|
|||
* @param {object} data Data properties to add to the result object.
|
||||
*/
|
||||
addResultData (uploadID, data) {
|
||||
if (!this._getUpload(uploadID)) {
|
||||
if (!this.getUpload(uploadID)) {
|
||||
this.log(`Not setting result for an upload that has been removed: ${uploadID}`)
|
||||
return
|
||||
}
|
||||
|
|
@ -1522,7 +1529,7 @@ class Uppy {
|
|||
*
|
||||
* @param {string} uploadID The ID of the upload.
|
||||
*/
|
||||
_removeUpload (uploadID) {
|
||||
removeUpload (uploadID) {
|
||||
const currentUploads = { ...this.getState().currentUploads }
|
||||
delete currentUploads[uploadID]
|
||||
|
||||
|
|
@ -1536,7 +1543,7 @@ class Uppy {
|
|||
*
|
||||
* @private
|
||||
*/
|
||||
_runUpload (uploadID) {
|
||||
runUpload (uploadID) {
|
||||
const uploadData = this.getState().currentUploads[uploadID]
|
||||
const restoreStep = uploadData.step
|
||||
|
||||
|
|
@ -1573,8 +1580,9 @@ class Uppy {
|
|||
|
||||
// TODO give this the `updatedUpload` object as its only parameter maybe?
|
||||
// Otherwise when more metadata may be added to the upload this would keep getting more parameters
|
||||
// eslint-disable-next-line consistent-return
|
||||
return fn(updatedUpload.fileIDs, uploadID)
|
||||
}).then((result) => {
|
||||
}).then(() => {
|
||||
return null
|
||||
})
|
||||
})
|
||||
|
|
@ -1583,7 +1591,7 @@ class Uppy {
|
|||
// promise from this method if the upload failed.
|
||||
lastStep.catch((err) => {
|
||||
this.emit('error', err, uploadID)
|
||||
this._removeUpload(uploadID)
|
||||
this.removeUpload(uploadID)
|
||||
})
|
||||
|
||||
return lastStep.then(() => {
|
||||
|
|
@ -1628,8 +1636,9 @@ class Uppy {
|
|||
const { result } = currentUpload
|
||||
this.emit('complete', result)
|
||||
|
||||
this._removeUpload(uploadID)
|
||||
this.removeUpload(uploadID)
|
||||
|
||||
// eslint-disable-next-line consistent-return
|
||||
return result
|
||||
}).then((result) => {
|
||||
if (result == null) {
|
||||
|
|
@ -1667,14 +1676,15 @@ class Uppy {
|
|||
}
|
||||
|
||||
return Promise.resolve()
|
||||
.then(() => this._checkMinNumberOfFiles(files))
|
||||
.then(() => this.checkMinNumberOfFiles(files))
|
||||
.catch((err) => {
|
||||
this._showOrLogErrorAndThrow(err)
|
||||
this.showOrLogErrorAndThrow(err)
|
||||
})
|
||||
.then(() => {
|
||||
const { currentUploads } = this.getState()
|
||||
// get a list of files that are currently assigned to uploads
|
||||
const currentlyUploadingFiles = Object.keys(currentUploads).reduce((prev, curr) => prev.concat(currentUploads[curr].fileIDs), [])
|
||||
const currentlyUploadingFiles = Object.keys(currentUploads)
|
||||
.reduce((prev, curr) => prev.concat(currentUploads[curr].fileIDs), [])
|
||||
|
||||
const waitingFileIDs = []
|
||||
Object.keys(files).forEach((fileID) => {
|
||||
|
|
@ -1685,18 +1695,18 @@ class Uppy {
|
|||
}
|
||||
})
|
||||
|
||||
const uploadID = this._createUpload(waitingFileIDs)
|
||||
return this._runUpload(uploadID)
|
||||
const uploadID = this.createUpload(waitingFileIDs)
|
||||
return this.runUpload(uploadID)
|
||||
})
|
||||
.catch((err) => {
|
||||
this._showOrLogErrorAndThrow(err, {
|
||||
this.showOrLogErrorAndThrow(err, {
|
||||
showInformer: false,
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = function (opts) {
|
||||
module.exports = function core (opts) {
|
||||
return new Uppy(opts)
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
/* eslint no-console: "off", no-restricted-syntax: "off" */
|
||||
const fs = require('fs')
|
||||
const path = require('path')
|
||||
const prettierBytes = require('@transloadit/prettier-bytes')
|
||||
|
|
@ -69,15 +70,13 @@ describe('src/Core', () => {
|
|||
it('should not be able to add a plugin that has no id', () => {
|
||||
const core = Core()
|
||||
|
||||
expect(() =>
|
||||
core.use(InvalidPluginWithoutId)).toThrowErrorMatchingSnapshot()
|
||||
expect(() => core.use(InvalidPluginWithoutId)).toThrowErrorMatchingSnapshot()
|
||||
})
|
||||
|
||||
it('should not be able to add a plugin that has no type', () => {
|
||||
const core = Core()
|
||||
|
||||
expect(() =>
|
||||
core.use(InvalidPluginWithoutType)).toThrowErrorMatchingSnapshot()
|
||||
expect(() => core.use(InvalidPluginWithoutType)).toThrowErrorMatchingSnapshot()
|
||||
})
|
||||
|
||||
it('should return the plugin that matches the specified name', () => {
|
||||
|
|
@ -259,7 +258,7 @@ describe('src/Core', () => {
|
|||
})
|
||||
|
||||
const fileIDs = Object.keys(core.getState().files)
|
||||
const id = core._createUpload(fileIDs)
|
||||
const id = core.createUpload(fileIDs)
|
||||
|
||||
expect(core.getState().currentUploads[id]).toBeDefined()
|
||||
expect(Object.keys(core.getState().files).length).toEqual(2)
|
||||
|
|
@ -307,13 +306,13 @@ describe('src/Core', () => {
|
|||
describe('upload hooks', () => {
|
||||
it('should add data returned from upload hooks to the .upload() result', () => {
|
||||
const core = new Core()
|
||||
core.addPreProcessor((fileIDs, uploadID) => {
|
||||
core.addPreProcessor((_, uploadID) => {
|
||||
core.addResultData(uploadID, { pre: 'ok' })
|
||||
})
|
||||
core.addPostProcessor((fileIDs, uploadID) => {
|
||||
core.addPostProcessor((_, uploadID) => {
|
||||
core.addResultData(uploadID, { post: 'ok' })
|
||||
})
|
||||
core.addUploader((fileIDs, uploadID) => {
|
||||
core.addUploader((_, uploadID) => {
|
||||
core.addResultData(uploadID, { upload: 'ok' })
|
||||
})
|
||||
return core.upload().then((result) => {
|
||||
|
|
@ -327,16 +326,16 @@ describe('src/Core', () => {
|
|||
describe('preprocessors', () => {
|
||||
it('should add a preprocessor', () => {
|
||||
const core = new Core()
|
||||
const preprocessor = function () {}
|
||||
const preprocessor = () => {}
|
||||
core.addPreProcessor(preprocessor)
|
||||
expect(core.preProcessors[0]).toEqual(preprocessor)
|
||||
})
|
||||
|
||||
it('should remove a preprocessor', () => {
|
||||
const core = new Core()
|
||||
const preprocessor1 = function () {}
|
||||
const preprocessor2 = function () {}
|
||||
const preprocessor3 = function () {}
|
||||
const preprocessor1 = () => {}
|
||||
const preprocessor2 = () => {}
|
||||
const preprocessor3 = () => {}
|
||||
core.addPreProcessor(preprocessor1)
|
||||
core.addPreProcessor(preprocessor2)
|
||||
core.addPreProcessor(preprocessor3)
|
||||
|
|
@ -456,16 +455,16 @@ describe('src/Core', () => {
|
|||
describe('postprocessors', () => {
|
||||
it('should add a postprocessor', () => {
|
||||
const core = new Core()
|
||||
const postprocessor = function () {}
|
||||
const postprocessor = () => {}
|
||||
core.addPostProcessor(postprocessor)
|
||||
expect(core.postProcessors[0]).toEqual(postprocessor)
|
||||
})
|
||||
|
||||
it('should remove a postprocessor', () => {
|
||||
const core = new Core()
|
||||
const postprocessor1 = function () {}
|
||||
const postprocessor2 = function () {}
|
||||
const postprocessor3 = function () {}
|
||||
const postprocessor1 = () => {}
|
||||
const postprocessor2 = () => {}
|
||||
const postprocessor3 = () => {}
|
||||
core.addPostProcessor(postprocessor1)
|
||||
core.addPostProcessor(postprocessor2)
|
||||
core.addPostProcessor(postprocessor3)
|
||||
|
|
@ -586,16 +585,16 @@ describe('src/Core', () => {
|
|||
describe('uploaders', () => {
|
||||
it('should add an uploader', () => {
|
||||
const core = new Core()
|
||||
const uploader = function () {}
|
||||
const uploader = () => {}
|
||||
core.addUploader(uploader)
|
||||
expect(core.uploaders[0]).toEqual(uploader)
|
||||
})
|
||||
|
||||
it('should remove an uploader', () => {
|
||||
const core = new Core()
|
||||
const uploader1 = function () {}
|
||||
const uploader2 = function () {}
|
||||
const uploader3 = function () {}
|
||||
const uploader1 = () => {}
|
||||
const uploader2 = () => {}
|
||||
const uploader3 = () => {}
|
||||
core.addUploader(uploader1)
|
||||
core.addUploader(uploader2)
|
||||
core.addUploader(uploader3)
|
||||
|
|
@ -733,10 +732,11 @@ describe('src/Core', () => {
|
|||
|
||||
it('should not allow a file if onBeforeFileAdded returned false', () => {
|
||||
const core = new Core({
|
||||
onBeforeFileAdded: (file, files) => {
|
||||
onBeforeFileAdded: (file) => {
|
||||
if (file.source === 'jest') {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
},
|
||||
})
|
||||
expect(() => {
|
||||
|
|
@ -851,7 +851,7 @@ describe('src/Core', () => {
|
|||
describe('uploading a file', () => {
|
||||
it('should return a { successful, failed } pair containing file objects', () => {
|
||||
const core = new Core()
|
||||
core.addUploader((fileIDs) => Promise.resolve())
|
||||
core.addUploader(() => Promise.resolve())
|
||||
|
||||
core.addFile({ source: 'jest', name: 'foo.jpg', type: 'image/jpeg', data: new Uint8Array() })
|
||||
core.addFile({ source: 'jest', name: 'bar.jpg', type: 'image/jpeg', data: new Uint8Array() })
|
||||
|
|
@ -903,7 +903,7 @@ describe('src/Core', () => {
|
|||
fileIDs: ['uppy-file4/jpg-1e-image/jpeg', 'uppy-file5/jpg-1e-image/jpeg', 'uppy-file6/jpg-1e-image/jpeg'],
|
||||
},
|
||||
}
|
||||
core.addUploader((fileIDs) => Promise.resolve())
|
||||
core.addUploader(() => Promise.resolve())
|
||||
|
||||
core.addFile({ source: 'jest', name: 'foo.jpg', type: 'image/jpeg', data: new Uint8Array() })
|
||||
core.addFile({ source: 'jest', name: 'bar.jpg', type: 'image/jpeg', data: new Uint8Array() })
|
||||
|
|
@ -914,8 +914,9 @@ describe('src/Core', () => {
|
|||
|
||||
it('should not upload if onBeforeUpload returned false', () => {
|
||||
const core = new Core({
|
||||
// eslint-disable-next-line consistent-return
|
||||
onBeforeUpload: (files) => {
|
||||
for (var fileId in files) {
|
||||
for (const fileId in files) {
|
||||
if (files[fileId].name === '123.foo') {
|
||||
return false
|
||||
}
|
||||
|
|
@ -1296,7 +1297,7 @@ describe('src/Core', () => {
|
|||
bytesTotal: 17175,
|
||||
})
|
||||
|
||||
core._calculateProgress.flush()
|
||||
core.calculateProgress.flush()
|
||||
|
||||
expect(core.getFile(fileId).progress).toEqual({
|
||||
percentage: 100,
|
||||
|
|
@ -1331,7 +1332,7 @@ describe('src/Core', () => {
|
|||
data: {},
|
||||
})
|
||||
|
||||
core._calculateTotalProgress()
|
||||
core.calculateTotalProgress()
|
||||
|
||||
const uploadPromise = core.upload()
|
||||
await new Promise((resolve) => core.once('upload-started', resolve))
|
||||
|
|
@ -1404,7 +1405,7 @@ describe('src/Core', () => {
|
|||
data: {},
|
||||
})
|
||||
|
||||
core._calculateTotalProgress()
|
||||
core.calculateTotalProgress()
|
||||
|
||||
// foo.jpg at 35%, bar.jpg at 0%
|
||||
expect(core.getState().totalProgress).toBe(18)
|
||||
|
|
@ -1445,8 +1446,8 @@ describe('src/Core', () => {
|
|||
bytesTotal: 17175,
|
||||
})
|
||||
|
||||
core._calculateTotalProgress()
|
||||
core._calculateProgress.flush()
|
||||
core.calculateTotalProgress()
|
||||
core.calculateProgress.flush()
|
||||
|
||||
expect(core.getState().totalProgress).toEqual(66)
|
||||
})
|
||||
|
|
@ -1483,8 +1484,8 @@ describe('src/Core', () => {
|
|||
bytesTotal: 17175,
|
||||
})
|
||||
|
||||
core._calculateTotalProgress()
|
||||
core._calculateProgress.flush()
|
||||
core.calculateTotalProgress()
|
||||
core.calculateProgress.flush()
|
||||
|
||||
expect(core.getState().totalProgress).toEqual(66)
|
||||
|
||||
|
|
@ -1618,8 +1619,8 @@ describe('src/Core', () => {
|
|||
})
|
||||
throw new Error('should have thrown')
|
||||
} catch (err) {
|
||||
expect(err).toMatchObject(new Error('This file exceeds maximum allowed size of 1.2 KB'))
|
||||
expect(core.getState().info.message).toEqual('This file exceeds maximum allowed size of 1.2 KB')
|
||||
expect(err).toMatchObject(new Error('foo.jpg exceeds maximum allowed size of 1.2 KB'))
|
||||
expect(core.getState().info.message).toEqual('foo.jpg exceeds maximum allowed size of 1.2 KB')
|
||||
}
|
||||
})
|
||||
|
||||
|
|
@ -1666,7 +1667,7 @@ describe('src/Core', () => {
|
|||
data: new File([sampleImage], { type: 'image/jpeg' }),
|
||||
})
|
||||
}).toThrowError(
|
||||
new Error('This file exceeds maximum allowed size of 33 KB')
|
||||
new Error('foo1.jpg exceeds maximum allowed size of 33 KB')
|
||||
)
|
||||
})
|
||||
|
||||
|
|
@ -1724,11 +1725,13 @@ describe('src/Core', () => {
|
|||
name: 'test.jpg',
|
||||
data: new Blob([Buffer.alloc(2 * maxFileSize)]),
|
||||
}
|
||||
const errorMessage = `${core.i18n('exceedsSize')} ${prettierBytes(maxFileSize)}`
|
||||
const errorMessage = `${core.i18n('exceedsSize', { file: file.name })} ${prettierBytes(maxFileSize)}`
|
||||
try {
|
||||
core.on('restriction-failed', restrictionsViolatedEventMock)
|
||||
core.addFile(file)
|
||||
} catch (err) {}
|
||||
} catch (err) {
|
||||
// something
|
||||
}
|
||||
|
||||
expect(restrictionsViolatedEventMock.mock.calls.length).toEqual(1)
|
||||
expect(restrictionsViolatedEventMock.mock.calls[0][0].name).toEqual(file.name)
|
||||
|
|
@ -1910,7 +1913,7 @@ describe('src/Core', () => {
|
|||
data: new File([sampleImage], { type: 'image/jpeg' }),
|
||||
})
|
||||
|
||||
core._createUpload(Object.keys(core.getState().files))
|
||||
core.createUpload(Object.keys(core.getState().files))
|
||||
const uploadId = Object.keys(core.getState().currentUploads)[0]
|
||||
const currentUploadsState = {}
|
||||
currentUploadsState[uploadId] = {
|
||||
|
|
@ -1932,7 +1935,7 @@ describe('src/Core', () => {
|
|||
},
|
||||
})
|
||||
|
||||
expect(core.i18n('exceedsSize')).toBe('This file exceeds maximum allowed size of')
|
||||
expect(core.i18n('exceedsSize')).toBe('%{file} exceeds maximum allowed size of')
|
||||
expect(core.i18n('test')).toBe('beep boop')
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ en_US.strings = {
|
|||
enterCorrectUrl: 'Incorrect URL: Please make sure you are entering a direct link to a file',
|
||||
enterTextToSearch: 'Enter text to search for images',
|
||||
enterUrlToImport: 'Enter URL to import a file',
|
||||
exceedsSize: 'This file exceeds maximum allowed size of',
|
||||
exceedsSize: '%{file} exceeds maximum allowed size of',
|
||||
exceedsSize2: '%{backwardsCompat} %{size}',
|
||||
failedToFetch: 'Companion failed to fetch this URL, please make sure it’s correct',
|
||||
failedToUpload: 'Failed to upload %{file}',
|
||||
|
|
|
|||
|
|
@ -41,8 +41,8 @@ nl_NL.strings = {
|
|||
encoding: 'Coderen...',
|
||||
enterCorrectUrl: 'Ongeldige URL: Zorg dat je een directe link naar een bestand invoert',
|
||||
enterUrlToImport: 'Voeg URL toe om een bestand te importeren',
|
||||
exceedsSize2: 'Dit bestand overschrijdt de maximaal toegelaten bestandsgrootte van %{size}',
|
||||
exceedsSize: 'Dit bestand overschrijdt de maximaal toegelaten bestandsgrootte van',
|
||||
exceedsSize2: '%{file} overschrijdt de maximaal toegelaten bestandsgrootte van %{size}',
|
||||
exceedsSize: '%{file} overschrijdt de maximaal toegelaten bestandsgrootte van',
|
||||
failedToFetch: 'Companion kan deze URL niet laden, controleer of de URL correct is',
|
||||
failedToUpload: 'Kon %{file} niet uploaden',
|
||||
fileSource: 'Bronbestand: %{name}',
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue