@uploadcare/blocks
Advanced tools
Comparing version 0.25.0-alpha.3 to 0.25.0-alpha.4
@@ -81,2 +81,7 @@ // @ts-check | ||
}, | ||
validationMultipleLimitMsg: { | ||
type: String, | ||
value: null, | ||
nullable: true, | ||
}, | ||
ctxName: { | ||
@@ -83,0 +88,0 @@ type: String, |
export class FileItem extends UploaderBlock { | ||
/** @private */ | ||
private _entrySubs; | ||
/** @private */ | ||
/** | ||
* @private | ||
* @type {any} TODO: Add types for upload entry | ||
*/ | ||
private _entry; | ||
@@ -16,3 +19,6 @@ /** @private */ | ||
_reset(): void; | ||
/** @private */ | ||
/** | ||
* @private | ||
* @param {IntersectionObserverEntry[]} entries | ||
*/ | ||
private _observerCallback; | ||
@@ -46,2 +52,7 @@ /** @private */ | ||
private _handleEntryId; | ||
/** | ||
* @private | ||
* @param {any} entry TODO: add types | ||
*/ | ||
private _uploadIfPossible; | ||
/** @param {(typeof FileItemState)[keyof typeof FileItemState]} state */ | ||
@@ -63,4 +74,5 @@ _handleState(state: (typeof FileItemState)[keyof typeof FileItemState]): void; | ||
IDLE: symbol; | ||
LIMIT_OVERFLOW: symbol; | ||
}>; | ||
export {}; | ||
//# sourceMappingURL=FileItem.d.ts.map |
@@ -0,5 +1,6 @@ | ||
// @ts-check | ||
import { UploaderBlock } from '../../abstract/UploaderBlock.js'; | ||
import { ActivityBlock } from '../../abstract/ActivityBlock.js'; | ||
import { generateThumb } from '../utils/resizeImage.js'; | ||
import { uploadFile } from '@uploadcare/upload-client'; | ||
import { UploadClientError, uploadFile } from '@uploadcare/upload-client'; | ||
import { UiMessage } from '../MessageBox/MessageBox.js'; | ||
@@ -17,2 +18,3 @@ import { fileCssBg } from '../svg-backgrounds/svg-backgrounds.js'; | ||
IDLE: Symbol(3), | ||
LIMIT_OVERFLOW: Symbol(4), | ||
}); | ||
@@ -25,3 +27,6 @@ | ||
_entrySubs = new Set(); | ||
/** @private */ | ||
/** | ||
* @private | ||
* @type {any} TODO: Add types for upload entry | ||
*/ | ||
_entry = null; | ||
@@ -37,2 +42,3 @@ /** @private */ | ||
// @ts-ignore TODO: fix this | ||
init$ = { | ||
@@ -53,2 +59,3 @@ ...this.init$, | ||
isEditable: false, | ||
isLimitOverflow: false, | ||
state: FileItemState.IDLE, | ||
@@ -96,6 +103,8 @@ '*uploadTrigger': null, | ||
this._entry = null; | ||
this._isIntersecting = false; | ||
} | ||
/** @private */ | ||
/** | ||
* @private | ||
* @param {IntersectionObserverEntry[]} entries | ||
*/ | ||
_observerCallback(entries) { | ||
@@ -124,3 +133,5 @@ let [entry] = entries; | ||
if (entry.getValue('uploadError') || entry.getValue('validationErrorMsg')) { | ||
if (entry.getValue('validationMultipleLimitMsg')) { | ||
state = FileItemState.LIMIT_OVERFLOW; | ||
} else if (entry.getValue('uploadError') || entry.getValue('validationErrorMsg')) { | ||
state = FileItemState.FAILED; | ||
@@ -202,7 +213,10 @@ } else if (entry.getValue('isUploading')) { | ||
_subEntry(prop, handler) { | ||
let sub = this._entry.subscribe(prop, (value) => { | ||
if (this.isConnected) { | ||
handler(value); | ||
let sub = this._entry.subscribe( | ||
prop, | ||
/** @param {any} value */ (value) => { | ||
if (this.isConnected) { | ||
handler(value); | ||
} | ||
} | ||
}); | ||
); | ||
this._entrySubs.add(sub); | ||
@@ -253,12 +267,14 @@ } | ||
this._subEntry('validationErrorMsg', (validationErrorMsg) => { | ||
this._subEntry('validationErrorMsg', () => { | ||
this._debouncedCalculateState(); | ||
this.$.errorText = validationErrorMsg; | ||
}); | ||
this._subEntry('uploadError', (uploadError) => { | ||
this._subEntry('uploadError', () => { | ||
this._debouncedCalculateState(); | ||
this.$.errorText = uploadError?.message; | ||
}); | ||
this._subEntry('validationMultipleLimitMsg', () => { | ||
this._debouncedCalculateState(); | ||
}); | ||
this._subEntry('isUploading', () => { | ||
@@ -329,6 +345,8 @@ this._debouncedCalculateState(); | ||
if (!this.cfg.confirmUpload) { | ||
this.upload(); | ||
} | ||
this._subEntry('validationMultipleLimitMsg', () => { | ||
this._uploadIfPossible(entry); | ||
}); | ||
this._uploadIfPossible(entry); | ||
if (this._isIntersecting) { | ||
@@ -339,2 +357,17 @@ this._debouncedGenerateThumb(); | ||
/** | ||
* @private | ||
* @param {any} entry TODO: add types | ||
*/ | ||
_uploadIfPossible(entry) { | ||
if ( | ||
!this.cfg.confirmUpload && | ||
!entry.getValue('validationErrorMsg') && | ||
!entry.getValue('uploadError') && | ||
!entry.getValue('validationMultipleLimitMsg') | ||
) { | ||
this.upload(); | ||
} | ||
} | ||
initCallback() { | ||
@@ -380,2 +413,3 @@ super.initCallback(); | ||
isFailed: state === FileItemState.FAILED, | ||
isLimitOverflow: state === FileItemState.LIMIT_OVERFLOW, | ||
isUploading: state === FileItemState.UPLOADING, | ||
@@ -385,5 +419,9 @@ isFinished: state === FileItemState.FINISHED, | ||
isEditable: this.cfg.useCloudImageEditor && state === FileItemState.FINISHED && this._entry?.getValue('isImage'), | ||
errorText: | ||
this._entry.getValue('uploadError')?.message || | ||
this._entry.getValue('validationErrorMsg') || | ||
this._entry.getValue('validationMultipleLimitMsg'), | ||
}); | ||
if (state === FileItemState.FAILED) { | ||
if (state === FileItemState.FAILED || state === FileItemState.LIMIT_OVERFLOW) { | ||
this.$.badgeIcon = 'badge-error'; | ||
@@ -433,10 +471,4 @@ } else if (state === FileItemState.FINISHED) { | ||
} | ||
const entryIdx = this.uploadCollection.items().indexOf(entry.uid); | ||
const filesLimit = this.cfg.multiple ? this.cfg.multipleMax : 1; | ||
if (filesLimit && this.uploadCollection.size >= filesLimit && entryIdx > filesLimit - 1) { | ||
const message = this.l10n('files-count-allowed', { | ||
count: filesLimit, | ||
}); | ||
entry.setValue('validationErrorMsg', message); | ||
const multipleMax = this.cfg.multiple ? this.cfg.multipleMax : 1; | ||
if (this.uploadCollection.size > multipleMax) { | ||
return; | ||
@@ -447,2 +479,3 @@ } | ||
}); | ||
EventManager.emit( | ||
@@ -460,2 +493,3 @@ new EventData({ | ||
entry.setValue('validationErrorMsg', null); | ||
entry.setValue('validationMultipleLimitMsg', null); | ||
@@ -514,4 +548,8 @@ if (!entry.getValue('file') && entry.getValue('externalUrl')) { | ||
if (!error?.isCancel) { | ||
entry.setValue('uploadError', error); | ||
if (error instanceof UploadClientError) { | ||
if (!error.isCancel) { | ||
entry.setValue('uploadError', error); | ||
} | ||
} else { | ||
entry.setValue('uploadError', new Error('Unexpected error')); | ||
} | ||
@@ -523,3 +561,6 @@ } | ||
FileItem.template = /* HTML */ ` | ||
<div class="inner" set="@finished: isFinished; @uploading: isUploading; @failed: isFailed; @focused: isFocused"> | ||
<div | ||
class="inner" | ||
set="@finished: isFinished; @uploading: isUploading; @failed: isFailed; @limit-overflow: isLimitOverflow; @focused: isFocused" | ||
> | ||
<div class="thumb" set="style.backgroundImage: thumbUrl"> | ||
@@ -526,0 +567,0 @@ <div class="badge"> |
@@ -0,1 +1,10 @@ | ||
/** | ||
* @typedef {{ | ||
* total: number; | ||
* succeed: number; | ||
* uploading: number; | ||
* failed: number; | ||
* limitOverflow: number; | ||
* }} Summary | ||
*/ | ||
export class UploadList extends UploaderBlock { | ||
@@ -7,2 +16,4 @@ activityType: "upload-list"; | ||
}; | ||
/** @private */ | ||
private _validateMultipleLimit; | ||
/** | ||
@@ -17,3 +28,6 @@ * @private | ||
private _updateUploadsState; | ||
/** @private */ | ||
/** | ||
* @private | ||
* @param {Summary} summary | ||
*/ | ||
private _getHeaderText; | ||
@@ -24,3 +38,10 @@ } | ||
} | ||
export type Summary = { | ||
total: number; | ||
succeed: number; | ||
uploading: number; | ||
failed: number; | ||
limitOverflow: number; | ||
}; | ||
import { UploaderBlock } from '../../abstract/UploaderBlock.js'; | ||
//# sourceMappingURL=UploadList.d.ts.map |
@@ -0,1 +1,2 @@ | ||
// @ts-check | ||
import { UploaderBlock } from '../../abstract/UploaderBlock.js'; | ||
@@ -7,2 +8,12 @@ import { ActivityBlock } from '../../abstract/ActivityBlock.js'; | ||
/** | ||
* @typedef {{ | ||
* total: number; | ||
* succeed: number; | ||
* uploading: number; | ||
* failed: number; | ||
* limitOverflow: number; | ||
* }} Summary | ||
*/ | ||
export class UploadList extends UploaderBlock { | ||
@@ -12,2 +23,3 @@ historyTracked = true; | ||
// @ts-ignore TODO: fix this | ||
init$ = { | ||
@@ -54,4 +66,24 @@ ...this.init$, | ||
this._updateCountLimitMessage(); | ||
this._validateMultipleLimit(); | ||
}, 0); | ||
/** @private */ | ||
_validateMultipleLimit() { | ||
const entryIds = this.uploadCollection.items(); | ||
for (const entryId of entryIds) { | ||
const entry = this.uploadCollection.read(entryId); | ||
const entryIdx = entryIds.indexOf(entryId); | ||
const multipleMax = this.cfg.multiple ? this.cfg.multipleMax : 1; | ||
if (entryIdx >= multipleMax) { | ||
const message = this.l10n('files-count-allowed', { | ||
count: multipleMax, | ||
}); | ||
entry.setValue('validationMultipleLimitMsg', message); | ||
} else { | ||
entry.setValue('validationMultipleLimitMsg', null); | ||
} | ||
} | ||
} | ||
/** | ||
@@ -112,2 +144,3 @@ * @private | ||
let filesCount = itemIds.length; | ||
/** @type {Summary} */ | ||
let summary = { | ||
@@ -118,2 +151,3 @@ total: filesCount, | ||
failed: 0, | ||
limitOverflow: 0, | ||
}; | ||
@@ -131,6 +165,9 @@ for (let id of itemIds) { | ||
} | ||
if (item.getValue('validationMultipleLimitMsg')) { | ||
summary.limitOverflow += 1; | ||
} | ||
} | ||
let allDone = summary.total === summary.succeed + summary.failed; | ||
let allDone = summary.total === summary.succeed + summary.failed + summary.limitOverflow; | ||
let { passed: fitCountRestrictions, tooMany, exact } = this._validateFilesCount(); | ||
let fitValidation = summary.failed === 0; | ||
let fitValidation = summary.failed === 0 && summary.limitOverflow === 0; | ||
@@ -154,4 +191,8 @@ let doneBtnEnabled = summary.total > 0 && fitCountRestrictions && fitValidation; | ||
/** @private */ | ||
/** | ||
* @private | ||
* @param {Summary} summary | ||
*/ | ||
_getHeaderText(summary) { | ||
/** @param {keyof Summary} status */ | ||
const localizedText = (status) => { | ||
@@ -158,0 +199,0 @@ const count = summary[status]; |
@@ -696,3 +696,6 @@ export const ActivityBlock = class { | ||
static template = ` | ||
<div class="inner" set="@finished: isFinished; @uploading: isUploading; @failed: isFailed; @focused: isFocused"> | ||
<div | ||
class="inner" | ||
set="@finished: isFinished; @uploading: isUploading; @failed: isFailed; @limit-overflow: isLimitOverflow; @focused: isFocused" | ||
> | ||
<div class="thumb" set="style.backgroundImage: thumbUrl"> | ||
@@ -699,0 +702,0 @@ <div class="badge"> |
{ | ||
"name": "@uploadcare/blocks", | ||
"version": "0.25.0-alpha.3", | ||
"version": "0.25.0-alpha.4", | ||
"description": "Building blocks for Uploadcare products integration", | ||
@@ -5,0 +5,0 @@ "keywords": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is too big to display
Sorry, the diff of this file is not supported yet
2125171
21012