From 23ccf7782febe9d1ab958db70dc48e42401056e4 Mon Sep 17 00:00:00 2001 From: Egor Didenko Date: Wed, 28 Aug 2024 14:58:43 -0400 Subject: [PATCH 1/7] feat(entry-file): added file upload source --- abstract/UploaderPublicApi.js | 1 + abstract/uploadEntrySchema.js | 1 + blocks/FileItem/FileItem.js | 1 + 3 files changed, 3 insertions(+) diff --git a/abstract/UploaderPublicApi.js b/abstract/UploaderPublicApi.js index 8de0c7d55..38f345ccc 100644 --- a/abstract/UploaderPublicApi.js +++ b/abstract/UploaderPublicApi.js @@ -240,6 +240,7 @@ export class UploaderPublicApi { isRemoved: status === 'removed', errors: /** @type {import('../types/exported.js').OutputFileEntry['errors']} */ (uploadEntryData.errors), status, + source: uploadEntryData?.source, }; return /** @type {import('../types/exported.js').OutputFileEntry} */ (outputItem); diff --git a/abstract/uploadEntrySchema.js b/abstract/uploadEntrySchema.js index 797384472..e43325abd 100644 --- a/abstract/uploadEntrySchema.js +++ b/abstract/uploadEntrySchema.js @@ -27,6 +27,7 @@ import { UploadcareFile } from '@uploadcare/upload-client'; * @property {string | null} fullPath * @property {import('@uploadcare/upload-client').Metadata | null} metadata * @property {boolean} isRemoved + * @property {String} source */ /** diff --git a/blocks/FileItem/FileItem.js b/blocks/FileItem/FileItem.js index a293ee2b4..d8bcbe750 100644 --- a/blocks/FileItem/FileItem.js +++ b/blocks/FileItem/FileItem.js @@ -392,6 +392,7 @@ export class FileItem extends UploaderBlock { cdnUrl: entry.getValue('cdnUrl') ?? fileInfo.cdnUrl, cdnUrlModifiers: entry.getValue('cdnUrlModifiers') ?? '', uploadProgress: 100, + source: entry.getValue('source') ?? '', }); if (entry === this._entry) { From 75ad4def051841d9116445e0b87986d1a4039ffd Mon Sep 17 00:00:00 2001 From: Egor Didenko Date: Sun, 1 Sep 2024 23:35:45 -0400 Subject: [PATCH 2/7] feat: added method getSourceTypes --- abstract/UploaderBlock.js | 6 ++++++ abstract/UploaderPublicApi.js | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/abstract/UploaderBlock.js b/abstract/UploaderBlock.js index 93d4d40f4..d1167336f 100644 --- a/abstract/UploaderBlock.js +++ b/abstract/UploaderBlock.js @@ -419,6 +419,10 @@ export class UploaderBlock extends ActivityBlock { const data = entriesIds.map((itemId) => this.api.getOutputItem(itemId)); return data; } + + getList() { + return UploaderBlock.sourceTypes; + } } /** @enum {String} */ @@ -444,3 +448,5 @@ UploaderBlock.sourceTypes = Object.freeze({ DRAW: 'draw', ...UploaderBlock.extSrcList, }); + +/** @typedef {(typeof UploaderBlock)['sourceTypes']} SourceTypes */ diff --git a/abstract/UploaderPublicApi.js b/abstract/UploaderPublicApi.js index 38f345ccc..2c9b168c1 100644 --- a/abstract/UploaderPublicApi.js +++ b/abstract/UploaderPublicApi.js @@ -330,6 +330,11 @@ export class UploaderPublicApi { return this._ctx.$['*currentActivity']; }; + /** @returns {Readonly} */ + getSourceTypes = () => { + return this._ctx.getList(); + }; + /** @param {boolean} opened */ setModalState = (opened) => { if (opened && !this._ctx.$['*currentActivity']) { From e13e3b88416e7b251223c7d296c1f846746bd4b8 Mon Sep 17 00:00:00 2001 From: Egor Didenko Date: Mon, 2 Sep 2024 10:20:26 -0400 Subject: [PATCH 3/7] feat: added export UploadSource, ExternalUploadSource --- abstract/UploaderBlock.js | 16 ++++++++-------- abstract/UploaderPublicApi.js | 5 ----- blocks/DropArea/DropArea.js | 2 +- blocks/SourceBtn/SourceBtn.js | 9 +++++---- blocks/UrlSource/UrlSource.js | 2 +- blocks/utils/UploadSource.js | 21 ++++++++++++++++++++- index.js | 1 + 7 files changed, 36 insertions(+), 20 deletions(-) diff --git a/abstract/UploaderBlock.js b/abstract/UploaderBlock.js index d1167336f..28e0d16c2 100644 --- a/abstract/UploaderBlock.js +++ b/abstract/UploaderBlock.js @@ -419,13 +419,12 @@ export class UploaderBlock extends ActivityBlock { const data = entriesIds.map((itemId) => this.api.getOutputItem(itemId)); return data; } - - getList() { - return UploaderBlock.sourceTypes; - } } -/** @enum {String} */ +/** + * @deprecated Use list sources ExternalUploadSource from from blocks/utils/UploadSource.js + * @enum {String} + */ UploaderBlock.extSrcList = Object.freeze({ FACEBOOK: 'facebook', DROPBOX: 'dropbox', @@ -440,7 +439,10 @@ UploaderBlock.extSrcList = Object.freeze({ HUDDLE: 'huddle', }); -/** @enum {String} */ +/** + * @deprecated Use list sources UploadSource from from blocks/utils/UploadSource.js + * @enum {String} + */ UploaderBlock.sourceTypes = Object.freeze({ LOCAL: 'local', URL: 'url', @@ -448,5 +450,3 @@ UploaderBlock.sourceTypes = Object.freeze({ DRAW: 'draw', ...UploaderBlock.extSrcList, }); - -/** @typedef {(typeof UploaderBlock)['sourceTypes']} SourceTypes */ diff --git a/abstract/UploaderPublicApi.js b/abstract/UploaderPublicApi.js index 2c9b168c1..38f345ccc 100644 --- a/abstract/UploaderPublicApi.js +++ b/abstract/UploaderPublicApi.js @@ -330,11 +330,6 @@ export class UploaderPublicApi { return this._ctx.$['*currentActivity']; }; - /** @returns {Readonly} */ - getSourceTypes = () => { - return this._ctx.getList(); - }; - /** @param {boolean} opened */ setModalState = (opened) => { if (opened && !this._ctx.$['*currentActivity']) { diff --git a/blocks/DropArea/DropArea.js b/blocks/DropArea/DropArea.js index b75785991..8c78e133e 100644 --- a/blocks/DropArea/DropArea.js +++ b/blocks/DropArea/DropArea.js @@ -151,7 +151,7 @@ export class DropArea extends UploaderBlock { this.subConfigValue('sourceList', (value) => { const list = stringToArray(value); // Enable drop area if local files are allowed - this.$.isEnabled = list.includes(UploaderBlock.sourceTypes.LOCAL); + this.$.isEnabled = list.includes(UploadSource.LOCAL); // Show drop area if it's enabled or default slot is overrided this.$.isVisible = this.$.isEnabled || !this.querySelector('[data-default-slot]'); }); diff --git a/blocks/SourceBtn/SourceBtn.js b/blocks/SourceBtn/SourceBtn.js index 45e50f34a..50dc1c944 100644 --- a/blocks/SourceBtn/SourceBtn.js +++ b/blocks/SourceBtn/SourceBtn.js @@ -1,6 +1,7 @@ // @ts-check import { UploaderBlock } from '../../abstract/UploaderBlock.js'; import { ActivityBlock } from '../../abstract/ActivityBlock.js'; +import { ExternalUploadSource, UploadSource } from '../utils/UploadSource.js'; const L10N_PREFIX = 'src-type-'; @@ -37,19 +38,19 @@ export class SourceBtn extends UploaderBlock { initTypes() { this.registerType({ - type: UploaderBlock.sourceTypes.LOCAL, + type: UploadSource.LOCAL, activate: () => { this.api.openSystemDialog(); return false; }, }); this.registerType({ - type: UploaderBlock.sourceTypes.URL, + type: UploadSource.URL, activity: ActivityBlock.activities.URL, textKey: 'from-url', }); this.registerType({ - type: UploaderBlock.sourceTypes.CAMERA, + type: UploadSource.CAMERA, activity: ActivityBlock.activities.CAMERA, activate: () => { const supportsCapture = 'capture' in document.createElement('input'); @@ -65,7 +66,7 @@ export class SourceBtn extends UploaderBlock { icon: 'edit-draw', }); - for (let externalSourceType of Object.values(UploaderBlock.extSrcList)) { + for (let externalSourceType of Object.values(ExternalUploadSource)) { this.registerType({ type: externalSourceType, activity: ActivityBlock.activities.EXTERNAL, diff --git a/blocks/UrlSource/UrlSource.js b/blocks/UrlSource/UrlSource.js index 80b7d6fa9..df91d0529 100644 --- a/blocks/UrlSource/UrlSource.js +++ b/blocks/UrlSource/UrlSource.js @@ -13,7 +13,7 @@ export class UrlSource extends UploaderBlock { e.preventDefault(); let url = this.ref.input['value']; - this.api.addFileFromUrl(url, { source: UploadSource.URL_TAB }); + this.api.addFileFromUrl(url, { source: UploadSource.URL }); this.$['*currentActivity'] = ActivityBlock.activities.UPLOAD_LIST; }, onCancel: () => { diff --git a/blocks/utils/UploadSource.js b/blocks/utils/UploadSource.js index 46101d9c2..4fee79e50 100644 --- a/blocks/utils/UploadSource.js +++ b/blocks/utils/UploadSource.js @@ -1,8 +1,27 @@ +// @ts-check +export const ExternalUploadSource = Object.freeze({ + FACEBOOK: 'facebook', + DROPBOX: 'dropbox', + GDRIVE: 'gdrive', + GPHOTOS: 'gphotos', + INSTAGRAM: 'instagram', + FLICKR: 'flickr', + VK: 'vk', + EVERNOTE: 'evernote', + BOX: 'box', + ONEDRIVE: 'onedrive', + HUDDLE: 'huddle', +}); + export const UploadSource = Object.freeze({ LOCAL: 'local', DROP_AREA: 'drop-area', - URL_TAB: 'url-tab', CAMERA: 'camera', EXTERNAL: 'external', API: 'js-api', + URL: 'url', + DRAW: 'draw', + ...ExternalUploadSource, }); + +/** @typedef {typeof UploadSource} SourceTypes */ diff --git a/index.js b/index.js index 9a0fa516f..ed4d4c792 100644 --- a/index.js +++ b/index.js @@ -44,6 +44,7 @@ export { defineComponents } from './abstract/defineComponents.js'; export { defineLocale } from './abstract/localeRegistry.js'; export { loadFileUploaderFrom } from './abstract/loadFileUploaderFrom.js'; export { toKebabCase } from './utils/toKebabCase.js'; +export { UploadSource, ExternalUploadSource } from './blocks/utils/UploadSource.js'; export * from './env.js'; From f928e6a95bb6e31687f6b2e0e8515c10fa19a077 Mon Sep 17 00:00:00 2001 From: Egor Didenko Date: Mon, 2 Sep 2024 10:37:49 -0400 Subject: [PATCH 4/7] feat: added types and handler fallback --- abstract/UploaderBlock.js | 19 +++---------------- blocks/FileItem/FileItem.js | 2 +- blocks/utils/UploadSource.js | 2 +- types/exported.d.ts | 3 +++ 4 files changed, 8 insertions(+), 18 deletions(-) diff --git a/abstract/UploaderBlock.js b/abstract/UploaderBlock.js index 28e0d16c2..408beafdb 100644 --- a/abstract/UploaderBlock.js +++ b/abstract/UploaderBlock.js @@ -15,6 +15,7 @@ import { TypedCollection } from './TypedCollection.js'; import { UploaderPublicApi } from './UploaderPublicApi.js'; import { ValidationManager } from './ValidationManager.js'; import { uploadEntrySchema } from './uploadEntrySchema.js'; +import { ExternalUploadSource, UploadSource } from '../blocks/utils/UploadSource.js'; export class UploaderBlock extends ActivityBlock { /** @protected */ @@ -426,17 +427,7 @@ export class UploaderBlock extends ActivityBlock { * @enum {String} */ UploaderBlock.extSrcList = Object.freeze({ - FACEBOOK: 'facebook', - DROPBOX: 'dropbox', - GDRIVE: 'gdrive', - GPHOTOS: 'gphotos', - INSTAGRAM: 'instagram', - FLICKR: 'flickr', - VK: 'vk', - EVERNOTE: 'evernote', - BOX: 'box', - ONEDRIVE: 'onedrive', - HUDDLE: 'huddle', + ...ExternalUploadSource, }); /** @@ -444,9 +435,5 @@ UploaderBlock.extSrcList = Object.freeze({ * @enum {String} */ UploaderBlock.sourceTypes = Object.freeze({ - LOCAL: 'local', - URL: 'url', - CAMERA: 'camera', - DRAW: 'draw', - ...UploaderBlock.extSrcList, + ...UploadSource, }); diff --git a/blocks/FileItem/FileItem.js b/blocks/FileItem/FileItem.js index d8bcbe750..724d001c1 100644 --- a/blocks/FileItem/FileItem.js +++ b/blocks/FileItem/FileItem.js @@ -392,7 +392,7 @@ export class FileItem extends UploaderBlock { cdnUrl: entry.getValue('cdnUrl') ?? fileInfo.cdnUrl, cdnUrlModifiers: entry.getValue('cdnUrlModifiers') ?? '', uploadProgress: 100, - source: entry.getValue('source') ?? '', + source: entry.getValue('source') ?? null, }); if (entry === this._entry) { diff --git a/blocks/utils/UploadSource.js b/blocks/utils/UploadSource.js index 4fee79e50..68e393912 100644 --- a/blocks/utils/UploadSource.js +++ b/blocks/utils/UploadSource.js @@ -24,4 +24,4 @@ export const UploadSource = Object.freeze({ ...ExternalUploadSource, }); -/** @typedef {typeof UploadSource} SourceTypes */ +/** @typedef {(typeof UploadSource)[keyof typeof UploadSource]} SourceTypes */ diff --git a/types/exported.d.ts b/types/exported.d.ts index d99654bf0..66b3c6886 100644 --- a/types/exported.d.ts +++ b/types/exported.d.ts @@ -5,6 +5,8 @@ import type { FuncFileValidator, FuncCollectionValidator } from '../abstract/Val export type { FuncFileValidator, FuncCollectionValidator } from '../abstract/ValidationManager'; export type { UploaderPublicApi } from '../abstract/UploaderPublicApi'; +export type { SourceTypes } from '../blocks/utils/UploadSource' + export type UploadError = import('@uploadcare/upload-client').UploadError; export type UploadcareFile = import('@uploadcare/upload-client').UploadcareFile; export type NetworkError = import('@uploadcare/upload-client').NetworkError; @@ -168,6 +170,7 @@ export type OutputFileEntry externalUrl: string | null; uploadProgress: number; fullPath: string | null; + source: SourceTypes; } & ( | { status: 'success'; From 990b5614cb3215b19dceafed880dfad1d6e15bff Mon Sep 17 00:00:00 2001 From: Egor Didenko Date: Mon, 2 Sep 2024 10:50:13 -0400 Subject: [PATCH 5/7] build(ssr): added check object and return stubbedExports with obj --- build-ssr-stubs.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build-ssr-stubs.js b/build-ssr-stubs.js index 0c382c729..31b347c62 100644 --- a/build-ssr-stubs.js +++ b/build-ssr-stubs.js @@ -72,6 +72,8 @@ const stubbedExports = Object.fromEntries( newValue = '() => {}'; } else if (typeof value === 'string') { newValue = `\`${value}\``; + } else if (typeof value === 'object') { + newValue = JSON.stringify(value); } else { throw new Error(`Unexpected export type: ${typeof value}`); } From 9e5024a2a6600d0a86413117fe49a2d2f5a9ccf5 Mon Sep 17 00:00:00 2001 From: Egor Didenko Date: Mon, 2 Sep 2024 10:56:45 -0400 Subject: [PATCH 6/7] feat(types): added SourceTypes in the OutputFileEntry --- types/exported.d.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/types/exported.d.ts b/types/exported.d.ts index 66b3c6886..278517d2c 100644 --- a/types/exported.d.ts +++ b/types/exported.d.ts @@ -5,8 +5,6 @@ import type { FuncFileValidator, FuncCollectionValidator } from '../abstract/Val export type { FuncFileValidator, FuncCollectionValidator } from '../abstract/ValidationManager'; export type { UploaderPublicApi } from '../abstract/UploaderPublicApi'; -export type { SourceTypes } from '../blocks/utils/UploadSource' - export type UploadError = import('@uploadcare/upload-client').UploadError; export type UploadcareFile = import('@uploadcare/upload-client').UploadcareFile; export type NetworkError = import('@uploadcare/upload-client').NetworkError; @@ -23,6 +21,7 @@ export type SecureUploadsSignatureResolver = () => Promise string; export type FileValidators = FuncFileValidator[]; export type CollectionValidators = FuncCollectionValidator[]; +export type SourceTypes = import('../blocks/utils/UploadSource').SourceTypes export type ConfigType = { pubkey: string; From ba9e7f65701bbed887f4faf2d80f0df879ac11c7 Mon Sep 17 00:00:00 2001 From: Egor Didenko Date: Mon, 2 Sep 2024 11:29:11 -0400 Subject: [PATCH 7/7] test(types): added test for source type in the file --- types/exported.d.ts | 2 +- types/test/uc-upload-ctx-provider.test-d.tsx | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/types/exported.d.ts b/types/exported.d.ts index 278517d2c..0f964bf02 100644 --- a/types/exported.d.ts +++ b/types/exported.d.ts @@ -169,7 +169,7 @@ export type OutputFileEntry externalUrl: string | null; uploadProgress: number; fullPath: string | null; - source: SourceTypes; + source: SourceTypes | null; } & ( | { status: 'success'; diff --git a/types/test/uc-upload-ctx-provider.test-d.tsx b/types/test/uc-upload-ctx-provider.test-d.tsx index 53a741126..a4c0ff11d 100644 --- a/types/test/uc-upload-ctx-provider.test-d.tsx +++ b/types/test/uc-upload-ctx-provider.test-d.tsx @@ -11,6 +11,7 @@ import { OutputFileErrorType, UploadCtxProvider } from '../../index.js'; +import { SourceTypes } from '../../blocks/utils/UploadSource.js'; const instance = new UploadCtxProvider(); instance.uploadCollection.size; @@ -96,6 +97,7 @@ instance.addEventListener('file-added', (e) => { expectType(state.cdnUrlModifiers); expectType(state.uuid); expectType(state.fileInfo); + expectType(state.source); }); instance.addEventListener('file-removed', (e) => {