Skip to content

Commit

Permalink
Pause/resume all uploads at once #65
Browse files Browse the repository at this point in the history
  • Loading branch information
arturi committed Aug 16, 2016
1 parent 9a7c3fb commit baf8e36
Show file tree
Hide file tree
Showing 5 changed files with 202 additions and 66 deletions.
25 changes: 17 additions & 8 deletions src/core/Core.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export default class Core {
data: file.data,
progress: {
percentage: 0,
uploadComplete: false,
uploadStarted: false
},
size: file.data.size,
Expand Down Expand Up @@ -180,30 +181,34 @@ export default class Core {
// `remove-file` removes a file from `state.files`, for example when
// a user decides not to upload particular file and clicks a button to remove it
this.emitter.on('file-remove', (fileID) => {
const updatedFiles = Object.assign({}, this.state.files)
const updatedFiles = Object.assign({}, this.getState().files)
delete updatedFiles[fileID]
this.setState({files: updatedFiles})
})

this.emitter.on('core:file-upload-started', (fileID) => {
this.emitter.on('core:file-upload-started', (fileID, upload) => {
const updatedFiles = Object.assign({}, this.getState().files)
const updatedFile = Object.assign({}, updatedFiles[fileID],
Object.assign({}, {
// can’t do that, because immutability. ??
// upload: upload,
progress: Object.assign({}, updatedFiles[fileID].progress, {
uploadStarted: Date.now()
})
}
))
updatedFiles[fileID] = updatedFile

this.setState({
files: updatedFiles
})
this.setState({files: updatedFiles})
})

this.emitter.on('upload-progress', (data) => {
const fileID = data.id
const updatedFiles = Object.assign({}, this.getState().files)
if (!updatedFiles[fileID]) {
console.error('Trying to set progress for a file that’s not with us anymore: ', fileID)
return
}

const updatedFile = Object.assign({}, updatedFiles[fileID],
Object.assign({}, {
Expand All @@ -218,12 +223,13 @@ export default class Core {

// calculate total progress, using the number of files currently uploading,
// multiplied by 100 and the summ of individual progress of each file
const inProgress = Object.keys(updatedFiles).map((file) => {
return file.progress !== 0
const inProgress = Object.keys(updatedFiles).filter((file) => {
return !updatedFiles[file].progress.uploadComplete &&
updatedFiles[file].progress.uploadStarted
})
const progressMax = Object.keys(inProgress).length * 100
let progressAll = 0
Object.keys(updatedFiles).forEach((file) => {
inProgress.forEach((file) => {
progressAll = progressAll + updatedFiles[file].progress.percentage
})

Expand All @@ -238,6 +244,9 @@ export default class Core {
this.emitter.on('upload-success', (fileID, uploadURL) => {
const updatedFiles = Object.assign({}, this.getState().files)
const updatedFile = Object.assign({}, updatedFiles[fileID], {
progress: Object.assign({}, updatedFiles[fileID].progress, {
uploadComplete: true
}),
uploadURL: uploadURL
})
updatedFiles[fileID] = updatedFile
Expand Down
74 changes: 55 additions & 19 deletions src/plugins/Dashboard/Dashboard.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import html from '../../core/html'
import Utils from '../../core/Utils'
import FileItem from './FileItem'
import FileCard from './FileCard'
import { closeIcon, localIcon, uploadIcon, dashboardBgIcon } from './icons'
import { closeIcon, localIcon, uploadIcon, dashboardBgIcon, iconPause, iconResume } from './icons'

export default function Dashboard (props, bus) {
// http://dev.edenspiekermann.com/2016/02/11/introducing-accessible-modal-dialog
Expand All @@ -12,12 +12,12 @@ export default function Dashboard (props, bus) {
const modal = state.modal
const container = props.container
const showFileCard = modal.showFileCard
const showProgressDetails = props.showProgressDetails

const hideModal = props.hideModal
const hideAllPanels = props.hideAllPanels
const showPanel = props.showPanel
const log = props.log
// const handleInputChange = props.handleInputChange

const acquirers = modal.targets.filter((target) => {
return target.type === 'acquirer'
Expand Down Expand Up @@ -55,13 +55,40 @@ export default function Dashboard (props, bus) {
})
}

const selectedFiles = Object.keys(files).filter((file) => {
return files[file].progress.percentage === 0
// return files[file].progress !== 100
const newFiles = Object.keys(files).filter((file) => {
return !files[file].progress.uploadStarted
})
const uploadStartedFiles = Object.keys(files).filter((file) => {
return files[file].progress.uploadStarted
})
const completeFiles = Object.keys(files).filter((file) => {
return files[file].progress.uploadComplete
})
const inProgressFiles = Object.keys(files).filter((file) => {
return !files[file].progress.uploadComplete &&
files[file].progress.uploadStarted &&
!files[file].isPaused
})

const uploadStartedFilesCount = Object.keys(uploadStartedFiles).length
const completeFilesCount = Object.keys(completeFiles).length
const inProgressFilesCount = Object.keys(inProgressFiles).length
const totalFileCount = Object.keys(files).length
const selectedFileCount = Object.keys(selectedFiles).length
const isSomethingSelected = selectedFileCount > 0
const newFileCount = Object.keys(newFiles).length

function renderPauseResume () {
if (uploadStartedFilesCount > 0) {
if (inProgressFilesCount > 0) {
return html`<button class="UppyDashboard-pauseResume UppyButton--circular UppyButton--yellow UppyButton--sizeS"
onclick=${() => bus.emit('core:pause-all')}>${iconPause()}</button>`
}

if (uploadStartedFilesCount !== completeFilesCount) {
return html`<button class="UppyDashboard-pauseResume UppyButton--circular UppyButton--green UppyButton--sizeS"
onclick=${() => bus.emit('core:resume-all')}>${iconResume()}</button>`
}
}
}

return html`<div class="Uppy UppyTheme--default UppyDashboard ${isTouchDevice ? 'Uppy--isTouchDevice' : ''}"
aria-hidden="${modal.isHidden}"
Expand Down Expand Up @@ -119,22 +146,31 @@ export default function Dashboard (props, bus) {
<ul class="UppyDashboard-filesInner">
${totalFileCount === 0
? html`<div class="UppyDashboard-bgIcon">${dashboardBgIcon()}</div>`
: ''
: null
}
${Object.keys(files).map((fileID) => {
return FileItem(files[fileID], bus)
return FileItem(
{file: files[fileID], showProgressDetails}, bus
)
})}
</ul>
${!props.autoProceed && isSomethingSelected
? html`<button class="UppyButton--circular UppyDashboard-upload"
type="button"
title="Upload"
onclick=${next}>
${uploadIcon()}
<sup class="UppyDashboard-uploadCount">${selectedFileCount}</sup>
</button>`
: null
}
<div class="UppyDashboard-actions">
${renderPauseResume()}
${!props.autoProceed && newFileCount > 0
? html`<button class="UppyButton--circular UppyButton--blue UppyButton--sizeM UppyDashboard-upload"
type="button"
title="Upload all files"
aria-label="Upload all files"
onclick=${next}>
${uploadIcon()}
<sup class="UppyDashboard-uploadCount"
title="Number of selected files"
aria-label="Number of selected files">
${newFileCount}</sup>
</button>`
: null
}
</div>
</div>
${acquirers.map((target) => {
Expand Down
48 changes: 34 additions & 14 deletions src/plugins/Dashboard/FileItem.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,10 +41,13 @@ function getSpeed (fileProgress) {
return uploadSpeed
}

export default function fileItem (file, bus) {
const isUploaded = file.progress.percentage === 100
const uploadInProgressOrComplete = file.progress.percentage > 0
const uploadInProgress = file.progress.percentage > 0 && file.progress.percentage < 100
export default function fileItem (props, bus) {
const file = props.file
const showProgressDetails = props.showProgressDetails

const isUploaded = file.progress.uploadComplete
const uploadInProgressOrComplete = file.progress.uploadStarted
const uploadInProgress = file.progress.uploadStarted && !file.progress.uploadComplete
const isPaused = file.isPaused || false

const fileName = Utils.getFileNameAndExtension(file.meta.name)[0]
Expand Down Expand Up @@ -72,19 +75,31 @@ export default function fileItem (file, bus) {
: getIconByMime(file.type.general)
}
<div class="UppyDashboardItem-progress">
<button class="UppyDashboardItem-progressBtn" onclick=${(e) => {
if (file.progress.percentage === 100) return
bus.emit('core:upload-pause', file.id)
}}>
<button class="UppyDashboardItem-progressBtn"
title="${isUploaded
? 'upload complete'
: file.isPaused ? 'resume upload' : 'pause upload'}"
onclick=${(e) => {
if (isUploaded) return
bus.emit('core:upload-pause', file.id)
}}>
${FileItemProgress({progress: file.progress.percentage, fileID: file.id}, bus)}
</button>
<div class="UppyDashboardItem-progressInfo">
${getETA(file.progress)} ・ ↑ ${prettyBytes(getSpeed(file.progress))} / s
</div>
${showProgressDetails
? html`<div class="UppyDashboardItem-progressInfo"
title="File progress: upload speed and ETA"
aria-label="File progress: upload speed and ETA">
${!file.isPaused && !isUploaded
? html`<span>${getETA(file.progress)} ・ ↑ ${prettyBytes(getSpeed(file.progress))}/s</span>`
: null
}
</div>`
: null
}
</div>
</div>
<div class="UppyDashboardItem-info">
<h4 class="UppyDashboardItem-name">
<h4 class="UppyDashboardItem-name" title="${fileName}">
${file.uploadURL
? html`<a href="${file.uploadURL}" target="_blank">${file.extension ? truncatedFileName + '.' + file.extension : truncatedFileName}</a>`
: file.extension ? truncatedFileName + '.' + file.extension : truncatedFileName
Expand All @@ -95,14 +110,19 @@ export default function fileItem (file, bus) {
</div>
${!uploadInProgressOrComplete
? html`<button class="UppyDashboardItem-edit"
onclick=${(e) => bus.emit('dashboard:file-card', file.id)}>${iconEdit()}</button>`
aria-label="Edit file"
title="Edit file"
onclick=${(e) => bus.emit('dashboard:file-card', file.id)}>
${iconEdit()}
</button>`
: null
}
</div>
<div class="UppyDashboardItem-action">
${!isUploaded
? html`<button class="UppyDashboardItem-remove"
aria-label="Remove this file"
aria-label="Remove file"
title="Remove file"
onclick=${remove}>
${removeIcon()}
</button>`
Expand Down
21 changes: 15 additions & 6 deletions src/plugins/Dashboard/icons.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit baf8e36

Please sign in to comment.