123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- const Plugin = require('@uppy/core/lib/Plugin')
- const Translator = require('@uppy/utils/lib/Translator')
- const StatusBarUI = require('./StatusBar')
- const statusBarStates = require('./StatusBarStates')
- const getSpeed = require('@uppy/utils/lib/getSpeed')
- const getBytesRemaining = require('@uppy/utils/lib/getBytesRemaining')
- const prettyETA = require('@uppy/utils/lib/prettyETA')
- const prettyBytes = require('prettier-bytes')
- /**
- * StatusBar: renders a status bar with upload/pause/resume/cancel/retry buttons,
- * progress percentage and time remaining.
- */
- module.exports = class StatusBar extends Plugin {
- constructor (uppy, opts) {
- super(uppy, opts)
- this.id = this.opts.id || 'StatusBar'
- this.title = 'StatusBar'
- this.type = 'progressindicator'
- const defaultLocale = {
- strings: {
- uploading: 'Uploading',
- complete: 'Complete',
- uploadFailed: 'Upload failed',
- pleasePressRetry: 'Please press Retry to upload again',
- paused: 'Paused',
- error: 'Error',
- retry: 'Retry',
- cancel: 'Cancel',
- pressToRetry: 'Press to retry',
- retryUpload: 'Retry upload',
- resumeUpload: 'Resume upload',
- cancelUpload: 'Cancel upload',
- pauseUpload: 'Pause upload',
- filesUploadedOfTotal: {
- 0: '%{complete} of %{smart_count} file uploaded',
- 1: '%{complete} of %{smart_count} files uploaded'
- },
- dataUploadedOfTotal: '%{complete} of %{total}',
- xTimeLeft: '%{time} left',
- uploadXFiles: {
- 0: 'Upload %{smart_count} file',
- 1: 'Upload %{smart_count} files'
- },
- uploadXNewFiles: {
- 0: 'Upload +%{smart_count} file',
- 1: 'Upload +%{smart_count} files'
- }
- }
- }
- // set default options
- const defaultOptions = {
- target: 'body',
- hideUploadButton: false,
- hideRetryButton: false,
- hidePauseResumeCancelButtons: false,
- showProgressDetails: false,
- locale: defaultLocale,
- hideAfterFinish: true
- }
- // merge default options with the ones set by user
- this.opts = Object.assign({}, defaultOptions, opts)
- this.locale = Object.assign({}, defaultLocale, this.opts.locale)
- this.locale.strings = Object.assign({}, defaultLocale.strings, this.opts.locale.strings)
- this.translator = new Translator({locale: this.locale})
- this.i18n = this.translator.translate.bind(this.translator)
- this.startUpload = this.startUpload.bind(this)
- this.render = this.render.bind(this)
- this.install = this.install.bind(this)
- }
- getTotalSpeed (files) {
- let totalSpeed = 0
- files.forEach((file) => {
- totalSpeed = totalSpeed + getSpeed(file.progress)
- })
- return totalSpeed
- }
- getTotalETA (files) {
- const totalSpeed = this.getTotalSpeed(files)
- if (totalSpeed === 0) {
- return 0
- }
- const totalBytesRemaining = files.reduce((total, file) => {
- return total + getBytesRemaining(file.progress)
- }, 0)
- return Math.round(totalBytesRemaining / totalSpeed * 10) / 10
- }
- startUpload () {
- return this.uppy.upload().catch((err) => {
- this.uppy.log(err.stack || err.message || err)
- // Ignore
- })
- }
- getUploadingState (isAllErrored, isAllComplete, files) {
- if (isAllErrored) {
- return statusBarStates.STATE_ERROR
- }
- if (isAllComplete) {
- return statusBarStates.STATE_COMPLETE
- }
- let state = statusBarStates.STATE_WAITING
- const fileIDs = Object.keys(files)
- for (let i = 0; i < fileIDs.length; i++) {
- const progress = files[fileIDs[i]].progress
- // If ANY files are being uploaded right now, show the uploading state.
- if (progress.uploadStarted && !progress.uploadComplete) {
- return statusBarStates.STATE_UPLOADING
- }
- // If files are being preprocessed AND postprocessed at this time, we show the
- // preprocess state. If any files are being uploaded we show uploading.
- if (progress.preprocess && state !== statusBarStates.STATE_UPLOADING) {
- state = statusBarStates.STATE_PREPROCESSING
- }
- // If NO files are being preprocessed or uploaded right now, but some files are
- // being postprocessed, show the postprocess state.
- if (progress.postprocess && state !== statusBarStates.STATE_UPLOADING && state !== statusBarStates.STATE_PREPROCESSING) {
- state = statusBarStates.STATE_POSTPROCESSING
- }
- }
- return state
- }
- render (state) {
- const files = state.files
- const uploadStartedFiles = Object.keys(files).filter((file) => {
- return files[file].progress.uploadStarted
- })
- const newFiles = Object.keys(files).filter((file) => {
- return !files[file].progress.uploadStarted &&
- !files[file].progress.preprocess &&
- !files[file].progress.postprocess
- })
- const completeFiles = Object.keys(files).filter((file) => {
- return files[file].progress.uploadComplete
- })
- const erroredFiles = Object.keys(files).filter((file) => {
- return files[file].error
- })
- const inProgressFiles = Object.keys(files).filter((file) => {
- return !files[file].progress.uploadComplete &&
- files[file].progress.uploadStarted &&
- !files[file].isPaused
- })
- const processingFiles = Object.keys(files).filter((file) => {
- return files[file].progress.preprocess || files[file].progress.postprocess
- })
- let inProgressFilesArray = inProgressFiles.map((file) => {
- return files[file]
- })
- const totalSpeed = prettyBytes(this.getTotalSpeed(inProgressFilesArray))
- const totalETA = prettyETA(this.getTotalETA(inProgressFilesArray))
- // total size and uploaded size
- let totalSize = 0
- let totalUploadedSize = 0
- inProgressFilesArray.forEach((file) => {
- totalSize = totalSize + (file.progress.bytesTotal || 0)
- totalUploadedSize = totalUploadedSize + (file.progress.bytesUploaded || 0)
- })
- totalSize = prettyBytes(totalSize)
- totalUploadedSize = prettyBytes(totalUploadedSize)
- const isUploadStarted = uploadStartedFiles.length > 0
- const isAllComplete = state.totalProgress === 100 &&
- completeFiles.length === Object.keys(files).length &&
- processingFiles.length === 0
- const isAllErrored = isUploadStarted &&
- erroredFiles.length === uploadStartedFiles.length
- const isAllPaused = inProgressFiles.length === 0 &&
- !isAllComplete &&
- !isAllErrored &&
- uploadStartedFiles.length > 0
- const resumableUploads = state.capabilities.resumableUploads || false
- return StatusBarUI({
- error: state.error,
- uploadState: this.getUploadingState(isAllErrored, isAllComplete, state.files || {}),
- totalProgress: state.totalProgress,
- totalSize: totalSize,
- totalUploadedSize: totalUploadedSize,
- uploadStarted: uploadStartedFiles.length,
- isAllComplete: isAllComplete,
- isAllPaused: isAllPaused,
- isAllErrored: isAllErrored,
- isUploadStarted: isUploadStarted,
- complete: completeFiles.length,
- newFiles: newFiles.length,
- inProgress: inProgressFiles.length,
- totalSpeed: totalSpeed,
- totalETA: totalETA,
- files: state.files,
- i18n: this.i18n,
- pauseAll: this.uppy.pauseAll,
- resumeAll: this.uppy.resumeAll,
- retryAll: this.uppy.retryAll,
- cancelAll: this.uppy.cancelAll,
- startUpload: this.startUpload,
- resumableUploads: resumableUploads,
- showProgressDetails: this.opts.showProgressDetails,
- hideUploadButton: this.opts.hideUploadButton,
- hideRetryButton: this.opts.hideRetryButton,
- hidePauseResumeCancelButtons: this.opts.hidePauseResumeCancelButtons,
- hideAfterFinish: this.opts.hideAfterFinish
- })
- }
- install () {
- const target = this.opts.target
- if (target) {
- this.mount(target, this)
- }
- }
- uninstall () {
- this.unmount()
- }
- }
|