mirror of
https://github.com/transloadit/uppy.git
synced 2026-07-21 01:15:35 +00:00
While the frameworks have good alternatives now with new components and hooks, Uppy is also popular in 'vanilla' JS setups without frameworks using the CDN bundle. Consumers of this were left with no viable alternative so it's sensible to bring back status bar and drag drop for the CDN publish (at least until we also publish/document using hooks via CDN). The framework packages don't really need this, as the alternatives are viable there. - Bring back `@uppy/status-bar` and `@uppy/drag-drop` from git tag `4.18.1` (latest release before 5.0) - Put exports maps on both packages - Put both packages in the CDN bundle - Version appropriately with changesets - Override existing locale keys. Unfortunately now that status-bar was merged into dashboard, the keys need to exist in both places but our tooling was setup to error when the same keys are found. Now it just overrides the existing key (to the same value in this case)
275 lines
6.8 KiB
TypeScript
275 lines
6.8 KiB
TypeScript
import type { Body, Meta, State, Uppy, UppyFile } from '@uppy/core'
|
|
import type { I18n } from '@uppy/utils'
|
|
import classNames from 'classnames'
|
|
import {
|
|
CancelBtn,
|
|
DoneBtn,
|
|
PauseResumeButton,
|
|
ProgressBarComplete,
|
|
ProgressBarError,
|
|
ProgressBarProcessing,
|
|
ProgressBarUploading,
|
|
RetryBtn,
|
|
UploadBtn,
|
|
} from './Components.js'
|
|
import calculateProcessingProgress from './calculateProcessingProgress.js'
|
|
import statusBarStates from './StatusBarStates.js'
|
|
|
|
const {
|
|
STATE_ERROR,
|
|
STATE_WAITING,
|
|
STATE_PREPROCESSING,
|
|
STATE_UPLOADING,
|
|
STATE_POSTPROCESSING,
|
|
STATE_COMPLETE,
|
|
} = statusBarStates
|
|
|
|
export interface StatusBarUIProps<M extends Meta, B extends Body> {
|
|
newFiles: number
|
|
allowNewUpload: boolean
|
|
isUploadInProgress: boolean
|
|
isAllPaused: boolean
|
|
resumableUploads: boolean
|
|
error: any
|
|
hideUploadButton?: boolean
|
|
hidePauseResumeButton?: boolean
|
|
hideCancelButton?: boolean
|
|
hideRetryButton?: boolean
|
|
recoveredState: State<M, B>['recoveredState']
|
|
uploadState: (typeof statusBarStates)[keyof typeof statusBarStates]
|
|
totalProgress: number
|
|
files: Record<string, UppyFile<M, B>>
|
|
supportsUploadProgress: boolean
|
|
hideAfterFinish?: boolean
|
|
isSomeGhost: boolean
|
|
doneButtonHandler?: (() => void) | null
|
|
isUploadStarted: boolean
|
|
i18n: I18n
|
|
startUpload: () => void
|
|
uppy: Uppy<M, B>
|
|
isAllComplete: boolean
|
|
showProgressDetails?: boolean
|
|
numUploads: number
|
|
complete: number
|
|
totalSize: number | null
|
|
totalETA: number | null
|
|
totalUploadedSize: number
|
|
}
|
|
|
|
export default function StatusBarUI<M extends Meta, B extends Body>({
|
|
newFiles,
|
|
allowNewUpload,
|
|
isUploadInProgress,
|
|
isAllPaused,
|
|
resumableUploads,
|
|
error,
|
|
hideUploadButton = undefined,
|
|
hidePauseResumeButton = false,
|
|
hideCancelButton = false,
|
|
hideRetryButton = false,
|
|
recoveredState,
|
|
uploadState,
|
|
totalProgress,
|
|
files,
|
|
supportsUploadProgress,
|
|
hideAfterFinish = false,
|
|
isSomeGhost,
|
|
doneButtonHandler = undefined,
|
|
isUploadStarted,
|
|
i18n,
|
|
startUpload,
|
|
uppy,
|
|
isAllComplete,
|
|
showProgressDetails = undefined,
|
|
numUploads,
|
|
complete,
|
|
totalSize,
|
|
totalETA,
|
|
totalUploadedSize,
|
|
}: StatusBarUIProps<M, B>) {
|
|
function getProgressValue(): number | null {
|
|
switch (uploadState) {
|
|
case STATE_POSTPROCESSING:
|
|
case STATE_PREPROCESSING: {
|
|
const progress = calculateProcessingProgress(files)
|
|
|
|
if (progress.mode === 'determinate') {
|
|
return progress.value * 100
|
|
}
|
|
return totalProgress
|
|
}
|
|
case STATE_ERROR: {
|
|
return null
|
|
}
|
|
case STATE_UPLOADING: {
|
|
if (!supportsUploadProgress) {
|
|
return null
|
|
}
|
|
return totalProgress
|
|
}
|
|
default:
|
|
return totalProgress
|
|
}
|
|
}
|
|
|
|
function getIsIndeterminate(): boolean {
|
|
switch (uploadState) {
|
|
case STATE_POSTPROCESSING:
|
|
case STATE_PREPROCESSING: {
|
|
const { mode } = calculateProcessingProgress(files)
|
|
return mode === 'indeterminate'
|
|
}
|
|
case STATE_UPLOADING: {
|
|
if (!supportsUploadProgress) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
default:
|
|
return false
|
|
}
|
|
}
|
|
|
|
const progressValue = getProgressValue()
|
|
|
|
const width = progressValue ?? 100
|
|
|
|
const showUploadBtn =
|
|
!error &&
|
|
newFiles &&
|
|
((!isUploadInProgress && !isAllPaused) || recoveredState) &&
|
|
allowNewUpload &&
|
|
!hideUploadButton
|
|
|
|
const showCancelBtn =
|
|
!hideCancelButton &&
|
|
uploadState !== STATE_WAITING &&
|
|
uploadState !== STATE_COMPLETE
|
|
|
|
const showPauseResumeBtn =
|
|
resumableUploads &&
|
|
!hidePauseResumeButton &&
|
|
uploadState === STATE_UPLOADING
|
|
|
|
const showRetryBtn = error && !isAllComplete && !hideRetryButton
|
|
|
|
const showDoneBtn = doneButtonHandler && uploadState === STATE_COMPLETE
|
|
|
|
const progressClassNames = classNames('uppy-StatusBar-progress', {
|
|
'is-indeterminate': getIsIndeterminate(),
|
|
})
|
|
|
|
const statusBarClassNames = classNames(
|
|
'uppy-StatusBar',
|
|
`is-${uploadState}`,
|
|
{ 'has-ghosts': isSomeGhost },
|
|
)
|
|
|
|
const progressBarStateEl = (() => {
|
|
switch (uploadState) {
|
|
case STATE_PREPROCESSING:
|
|
case STATE_POSTPROCESSING:
|
|
return (
|
|
<ProgressBarProcessing
|
|
progress={calculateProcessingProgress(files)}
|
|
/>
|
|
)
|
|
case STATE_COMPLETE:
|
|
return <ProgressBarComplete i18n={i18n} />
|
|
case STATE_ERROR:
|
|
return (
|
|
<ProgressBarError
|
|
error={error}
|
|
i18n={i18n}
|
|
numUploads={numUploads}
|
|
complete={complete}
|
|
/>
|
|
)
|
|
case STATE_UPLOADING:
|
|
return (
|
|
<ProgressBarUploading
|
|
i18n={i18n}
|
|
supportsUploadProgress={supportsUploadProgress}
|
|
totalProgress={totalProgress}
|
|
showProgressDetails={showProgressDetails}
|
|
isUploadStarted={isUploadStarted}
|
|
isAllComplete={isAllComplete}
|
|
isAllPaused={isAllPaused}
|
|
newFiles={newFiles}
|
|
numUploads={numUploads}
|
|
complete={complete}
|
|
totalUploadedSize={totalUploadedSize}
|
|
totalSize={totalSize}
|
|
totalETA={totalETA}
|
|
startUpload={startUpload}
|
|
/>
|
|
)
|
|
default:
|
|
return null
|
|
}
|
|
})()
|
|
|
|
const atLeastOneAction =
|
|
showUploadBtn ||
|
|
showRetryBtn ||
|
|
showPauseResumeBtn ||
|
|
showCancelBtn ||
|
|
showDoneBtn
|
|
const thereIsNothingInside = !atLeastOneAction && !progressBarStateEl
|
|
|
|
const isHidden =
|
|
thereIsNothingInside || (uploadState === STATE_COMPLETE && hideAfterFinish)
|
|
|
|
if (isHidden) {
|
|
return null
|
|
}
|
|
|
|
return (
|
|
<div className={statusBarClassNames}>
|
|
<div
|
|
className={progressClassNames}
|
|
style={{ width: `${width}%` }}
|
|
role="progressbar"
|
|
aria-label={`${width}%`}
|
|
aria-valuetext={`${width}%`}
|
|
aria-valuemin={0}
|
|
aria-valuemax={100}
|
|
aria-valuenow={progressValue!}
|
|
/>
|
|
|
|
{progressBarStateEl}
|
|
|
|
<div className="uppy-StatusBar-actions">
|
|
{showUploadBtn ? (
|
|
<UploadBtn
|
|
newFiles={newFiles}
|
|
isUploadStarted={isUploadStarted}
|
|
recoveredState={recoveredState}
|
|
i18n={i18n}
|
|
isSomeGhost={isSomeGhost}
|
|
startUpload={startUpload}
|
|
uploadState={uploadState}
|
|
/>
|
|
) : null}
|
|
|
|
{showRetryBtn ? <RetryBtn i18n={i18n} uppy={uppy} /> : null}
|
|
|
|
{showPauseResumeBtn ? (
|
|
<PauseResumeButton
|
|
isAllPaused={isAllPaused}
|
|
i18n={i18n}
|
|
isAllComplete={isAllComplete}
|
|
resumableUploads={resumableUploads}
|
|
uppy={uppy}
|
|
/>
|
|
) : null}
|
|
|
|
{showCancelBtn ? <CancelBtn i18n={i18n} uppy={uppy} /> : null}
|
|
|
|
{showDoneBtn ? (
|
|
<DoneBtn i18n={i18n} doneButtonHandler={doneButtonHandler} />
|
|
) : null}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|