diff --git a/CHANGELOG.md b/CHANGELOG.md index a778c126e478a61729f92b595142ca10f7cd5497..a076ec201f54be97f0d7beb76e84d18a7b64e5db 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,48 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. Thils file also consider all dropzone-ui [releases](https://github.com/dropzone-ui/dropzone-ui-react/releases). +## [1.2.0](https://github.com/files-ui/files-ui-react/releases/tag/v1.1.0) (2024-01-21) + +## ๐งช ๐ Allow uploading files with different URLs + +- Enhanced components to perform the upload operation with a different urls for each [ExtFile](https://www.files-ui.com/types#extfile). + - [ExtFile](https://www.files-ui.com/types#extfile): Added a new property in ExtFile type: `uploadUrl`. + - [\<Dropzone/\>](https://www.files-ui.com/components/dropzone) & [\<FileInputButton/\>](https://www.files-ui.com/components/fileinputbutton): There is a new sub-prop `uploadConfig.customUrl()` that is a fucntion that given an extFile object, obtains a custom url. +- The order of priority is as follows: + - 1) ExtFile.uploadUrl + - 2) DropzoneProps.UploadConfig.customUrl + - 3) DropzoneProps.UploadConfig.url + +- The setup can be as follows: + +```jsx + ... + return( + <React.Fragment> + <Dropzone + uploadConfig={ + customUrl: (extFile)=> "https://urlfromserver/" + extFile.name + } + /> + <FileInputButton + uploadConfig={ + customUrl: (extFile)=> "https://urlfromserver/" + extFile.name + } + /> + <Dropzone + onChange={updateFiles} + value={files} + > + {files.map((file) => ( + <FileMosaic key={file.id} {...file} uploadUrl={"https://urlfromserver/" + extFile.id}/> + ))} + </Dropzone> + + + </React.Fragment> + ) +``` + ## [1.1.0](https://github.com/files-ui/files-ui-react/releases/tag/v1.1.0) (2023-12-17) ## ๐งช New features and ๐ :hammer: Improvements @@ -35,7 +77,7 @@ Thils file also consider all dropzone-ui [releases](https://github.com/dropzone- - [\<FileCard/\>](https://www.files-ui.com/components/filecard): This new component is an alternative version of FileMosaic. It displays the file info in a card. Receives the same props as FileMosaic plus `elevation`. -- [\<FileInputButton/\>](https://www.files-ui.com/components/dropzone): This component replaces the old "InputButton" component. The features are the same as the dropzone except the header and footer related features. That means that this component now can trigger the upload progress. +- [\<FileInputButton/\>](https://www.files-ui.com/components/fileinputbutton): This component replaces the old "InputButton" component. The features are the same as the dropzone except the header and footer related features. That means that this component now can trigger the upload progress. Validation is optional, so non valid files can be uploaded. - [\<Avatar/\>](https://www.files-ui.com/components/avatar): This new component is designed tohandle the selection of images for changing the avatar. Can recieve as source an string url or even a File. diff --git a/package-lock.json b/package-lock.json index baa627f8bbd14321578b69f3930384bf7cc05d08..e836a741781d821ffd0a2e770121967bec520e2c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,16 +1,16 @@ { "name": "@files-ui/react", - "version": "1.0.8", + "version": "1.2.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@files-ui/react", - "version": "1.0.8", + "version": "1.2.0", "license": "MIT", "dependencies": { "@dynamicss/dynamicss": "^2.2.8", - "@files-ui/core": "latest" + "@files-ui/core": "^2.0.4" }, "devDependencies": { "@rollup/plugin-commonjs": "^24.0.1", @@ -646,9 +646,9 @@ "hasInstallScript": true }, "node_modules/@files-ui/core": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@files-ui/core/-/core-1.0.4.tgz", - "integrity": "sha512-CaSyHSwjeWEkctfALoK4MwAxq3Zr7+Ozyk5AMoB3s1UBIVgh2618wvNuUIHSVhWFKeB28bOoYxCzM2PEXO4QgA==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@files-ui/core/-/core-2.0.4.tgz", + "integrity": "sha512-zlUfkOYpLGw/EEe2ZO+OPDXstygEaaWYIPQtibhV6oR1KTXewMvvbyC8QU/Y9Jy77/8Ps6N/Rl1yjH0PUqdmXg==" }, "node_modules/@istanbuljs/load-nyc-config": { "version": "1.1.0", @@ -6801,9 +6801,9 @@ "integrity": "sha512-e6hrGUydr8f+c9E/9fHFSG5LoSLdq/MdZXXfbzEDWIVuzKF2hcdxZE7nHNqUNF2htw1mZ17Pyoshu3A6kFEeFA==" }, "@files-ui/core": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@files-ui/core/-/core-1.0.4.tgz", - "integrity": "sha512-CaSyHSwjeWEkctfALoK4MwAxq3Zr7+Ozyk5AMoB3s1UBIVgh2618wvNuUIHSVhWFKeB28bOoYxCzM2PEXO4QgA==" + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@files-ui/core/-/core-2.0.4.tgz", + "integrity": "sha512-zlUfkOYpLGw/EEe2ZO+OPDXstygEaaWYIPQtibhV6oR1KTXewMvvbyC8QU/Y9Jy77/8Ps6N/Rl1yjH0PUqdmXg==" }, "@istanbuljs/load-nyc-config": { "version": "1.1.0", diff --git a/package.json b/package.json index f8a623bf5993cf445b906c0cf4b9116027ea95bb..1d780540d358ba6b5c400537cce4fa1b6e11fd7a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@files-ui/react", - "version": "1.1.0", + "version": "1.2.0", "description": "UI components for file uploads with React js", "main": "./build/index.js", "module": "./build/index.es.js", @@ -68,7 +68,7 @@ }, "dependencies": { "@dynamicss/dynamicss": "^2.2.8", - "@files-ui/core": "latest" + "@files-ui/core": "^2.0.4" }, "publishConfig": { "access": "public" diff --git a/src/Dropzone/components/dropzone/Dropzone.tsx b/src/Dropzone/components/dropzone/Dropzone.tsx index ccff70c43ced0860657610b66f84ff6a281fc0d9..a130948cd18116684fef47cdd74af1923d061d4d 100644 --- a/src/Dropzone/components/dropzone/Dropzone.tsx +++ b/src/Dropzone/components/dropzone/Dropzone.tsx @@ -28,8 +28,10 @@ import { unexpectedErrorUploadResult, getRandomInt, addClassName, - Localization,completeAsureColor, FileIdGenerator, -} from "@files-ui/core" + Localization, + completeAsureColor, + FileIdGenerator, +} from "@files-ui/core"; import { mergeProps } from "../../../overridable"; import InputHidden from "../../../InputHidden/InputHidden"; import { @@ -59,7 +61,12 @@ import { } from "../../../utils"; import { FilesUiContext } from "../../../FilesUiProvider/FilesUiContext"; import DropLayer from "../../../DropLayer/components/DropLayer"; -import { useDropzoneFileListUpdater, useDropLayerClassName, useDropzoneClassName } from "../../../hooks"; +import { + useDropzoneFileListUpdater, + useDropLayerClassName, + useDropzoneClassName, +} from "../../../hooks"; +import { isThereValidUrl } from "../../../utils/url.utils"; //import { print_manager } from "../../../../../utils"; @@ -146,6 +153,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { cleanOnUpload = true, preparingTime = 1500, autoUpload = false, + urlFromExtFile, } = uploadConfig as UploadConfig; const { @@ -197,8 +205,11 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { const [localMessage, setLocalMessage] = React.useState<string>(""); //Id for uploding through FuiFileManager //const dropzoneId: string | number = useDropzoneFileListID(); - // const dropzoneId: string | number = React.useId(); - const dropzoneId: string = React.useMemo(() => FileIdGenerator.getNextId() + "",[]); + // const dropzoneId: string | number = React.useId(); + const dropzoneId: string = React.useMemo( + () => FileIdGenerator.getNextId() + "", + [] + ); //React.useId(); //Flag that determines whether to validate or not const validateFilesFlag: boolean = isValidateActive( @@ -224,6 +235,10 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { localization, validateFilesFlag ); + /** + * Flag that determines if component should perform upload given url + */ + const shouldUpload: boolean = isThereValidUrl(url, urlFromExtFile, localFiles); /** * Uploads each file in the array of ExtFiles * First, sets all the files in preparing status and awaits `preparingTime` miliseconds. @@ -247,7 +262,6 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { * @returns nothing */ const uploadfiles = async (localFiles: ExtFile[]): Promise<void> => { - //set uploading flag to true setIsUploading(true); @@ -271,12 +285,11 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { let arrOfExtFilesInstances: ExtFileInstance[] = []; const totalNumber: number = localFiles.length; - + const missingUpload: number = localFiles.filter((extFile: ExtFile) => isUploadAbleExtFile(extFile, validateFilesFlag) ).length; - let totalRejected: number = 0; let currentCountUpload: number = 0; @@ -285,7 +298,6 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { //no missing to upload if (!(missingUpload > 0)) { - setTimeout(() => { if (noMissingFilesLabel) setLocalMessage(DropzoneLocalizer.noFilesMessage as string); @@ -300,7 +312,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { setLocalMessage(uploadingMessenger(`${missingUpload}/${totalNumber}`)); // setIsUploading(true); //PREPARING stage - + onUploadStart?.(localFiles); arrOfExtFilesInstances = @@ -315,138 +327,154 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { x.toExtFile() ); - //CHANGE (o alejo el isUploading o lo alejo para que tenga m,as tiempo antes de la respuyesta) // setIsUploading(true); handleFilesChange(newExtFileLocal, true); - //AWAIT when preparing time is given //general sleep for all files await sleepPreparing(preparingTime); //return; let serverResponses: Array<ExtFile> = []; - - if(groupUpload) { - const unifiedUpload = (method, url, arrOfFiles) : Promise<{ success : boolean, message : string, payload: object }> => { - arrOfExtFilesInstances.forEach((el) => el.uploadStatus = "uploading"); - handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); - const formData = new FormData(); - for (let i=0; i < arrOfFiles.length; i++) { - formData.append('files', arrOfFiles[i].file ) - } - return new Promise((resolve, reject) => { - let xhr = new XMLHttpRequest(); - xhr.upload.onprogress = (e) => {arrOfExtFilesInstances.forEach((el) => { el.progress = (e.loaded / e.total) * 100 });handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true)}; - xhr.responseType = 'json' - xhr.onload = () => { - if (xhr.status >= 200 && xhr.status < 300) { - console.log(xhr.response); - console.log(typeof xhr.response); - resolve(xhr.response); - } else { - reject(xhr.response); - } - }; - xhr.onerror = (err) => { - reject(err); - }; - xhr.open(method, url); - xhr.send(formData) - }); - }; - try { - let respo:{ success : boolean, message : string, payload: object} = await unifiedUpload("POST", url, arrOfExtFilesInstances); - arrOfExtFilesInstances.forEach( el => el.uploadStatus = "success"); - arrOfExtFilesInstances.forEach( el => el.uploadMessage = respo.message); - } catch (err) { - arrOfExtFilesInstances.forEach( el => el.uploadStatus = "error"); - arrOfExtFilesInstances.forEach( el => el.uploadMessage = err.message); - console.log(err) + + if (groupUpload) { + const unifiedUpload = ( + method, + url, + arrOfFiles + ): Promise<{ success: boolean; message: string; payload: object }> => { + arrOfExtFilesInstances.forEach((el) => (el.uploadStatus = "uploading")); + handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); + const formData = new FormData(); + for (let i = 0; i < arrOfFiles.length; i++) { + formData.append("files", arrOfFiles[i].file); + } + return new Promise((resolve, reject) => { + let xhr = new XMLHttpRequest(); + xhr.upload.onprogress = (e) => { + arrOfExtFilesInstances.forEach((el) => { + el.progress = (e.loaded / e.total) * 100; + }); + handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); + }; + xhr.responseType = "json"; + xhr.onload = () => { + if (xhr.status >= 200 && xhr.status < 300) { + console.log(xhr.response); + console.log(typeof xhr.response); + resolve(xhr.response); + } else { + reject(xhr.response); + } + }; + xhr.onerror = (err) => { + reject(err); + }; + xhr.open(method, url); + xhr.send(formData); + }); + }; + try { + let respo: { success: boolean; message: string; payload: object } = + await unifiedUpload("POST", url, arrOfExtFilesInstances); + arrOfExtFilesInstances.forEach((el) => (el.uploadStatus = "success")); + arrOfExtFilesInstances.forEach( + (el) => (el.uploadMessage = respo.message) + ); + } catch (err) { + arrOfExtFilesInstances.forEach((el) => (el.uploadStatus = "error")); + arrOfExtFilesInstances.forEach( + (el) => (el.uploadMessage = err.message) + ); + console.log(err); } handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); } else { - //Uplad files one by one - for (let i = 0; i < arrOfExtFilesInstances.length; i++) { - const currentExtFileInstance: ExtFileInstance = arrOfExtFilesInstances[i]; + //Uplad files one by one + for (let i = 0; i < arrOfExtFilesInstances.length; i++) { + const currentExtFileInstance: ExtFileInstance = + arrOfExtFilesInstances[i]; + + if ( + currentExtFileInstance.uploadStatus === "preparing" && + !currentExtFileInstance.extraData?.deleted + ) { + //set stage to "uploading" in one file and notify change + // PREPARING => UPLOADING + await sleepTransition(); - - if ( - currentExtFileInstance.uploadStatus === "preparing" && - !currentExtFileInstance.extraData?.deleted - ) { - //set stage to "uploading" in one file and notify change - // PREPARING => UPLOADING - await sleepTransition(); + instantPreparingToUploadOne(currentExtFileInstance); - instantPreparingToUploadOne(currentExtFileInstance); + //messge in footer + if (uploadProgressMessage) + setLocalMessage( + uploadingMessenger(`${++currentCountUpload}/${missingUpload}`) + ); - //messge in footer - if (uploadProgressMessage) - setLocalMessage( - uploadingMessenger(`${++currentCountUpload}/${missingUpload}`) - ); + //CHANGE FILES + handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); - //CHANGE FILES - handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); + //UPLOADING => UPLOAD() + //upload one file and notify about change + let uploadResponse: ExtFile; - //UPLOADING => UPLOAD() - //upload one file and notify about change - let uploadResponse: ExtFile; - - if (fakeUpload) { - uploadResponse = await fakeFuiUpload( - currentExtFileInstance, - DropzoneLocalizer - ); - - let fakeProgress = 0; - while (fakeProgress < 100) { - fakeProgress += getRandomInt(21, 35); - currentExtFileInstance.progress = - fakeProgress > 100 ? 100 : fakeProgress; - await sleepTransition(1000); - handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); - } - } else { - try { - uploadResponse = await uploadExtFile( + if (fakeUpload) { + uploadResponse = await fakeFuiUpload( currentExtFileInstance, - url, - method, - headers, - uploadLabel - ); - } catch (error) { - uploadResponse = unexpectedErrorUploadResult( - currentExtFileInstance.toExtFile() + DropzoneLocalizer ); + + let fakeProgress = 0; + while (fakeProgress < 100) { + fakeProgress += getRandomInt(21, 35); + currentExtFileInstance.progress = + fakeProgress > 100 ? 100 : fakeProgress; + await sleepTransition(1000); + handleFilesChange( + sanitizeArrExtFile(arrOfExtFilesInstances), + true + ); + } + } else { + try { + uploadResponse = await uploadExtFile( + currentExtFileInstance, + url, + urlFromExtFile, + method, + headers, + uploadLabel + ); + } catch (error) { + uploadResponse = unexpectedErrorUploadResult( + currentExtFileInstance.toExtFile() + ); + } } - } - const uploadedFile = uploadResponse; + const uploadedFile = uploadResponse; - //update instances - currentExtFileInstance.uploadStatus = uploadedFile.uploadStatus; - currentExtFileInstance.uploadMessage = uploadedFile.uploadMessage; + //update instances + currentExtFileInstance.uploadStatus = uploadedFile.uploadStatus; + currentExtFileInstance.uploadMessage = uploadedFile.uploadMessage; - //CHANGE - if (!(currentExtFileInstance.uploadStatus === "aborted")) - await sleepTransition(); + //CHANGE + if (!(currentExtFileInstance.uploadStatus === "aborted")) + await sleepTransition(); - handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); + handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); - if (uploadedFile.uploadStatus === "error") { - totalRejected++; - } + if (uploadedFile.uploadStatus === "error") { + totalRejected++; + } - serverResponses.push(uploadResponse); - } else { - handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); + serverResponses.push(uploadResponse); + } else { + handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); + } } } - } setLocalFiles(sanitizeArrExtFile(arrOfExtFilesInstances)); // upload group finished :D @@ -466,7 +494,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { const handleAbortUpload = () => { const listExtFileLocal: ExtFileInstance[] | undefined = ExtFileManager.getExtFileInstanceList(dropzoneId); - + if (!listExtFileLocal) return; listExtFileLocal.forEach((extFileInstance: ExtFileInstance) => { if ( @@ -540,7 +568,6 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { extFileList: ExtFile[], isUploading?: boolean ): void => { - let finalExtFileList: ExtFile[] = behaviour === "add" && !isUploading ? [...localFiles, ...extFileList] @@ -551,7 +578,6 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { setLocalFiles(finalExtFileList); } if (autoUpload && !isUploading) { - uploadfiles(finalExtFileList); } }; @@ -575,7 +601,8 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { } } //init xhr on each ext file - if (url) extFileListOutput = toUploadableExtFileList(extFileListOutput); + if (shouldUpload) + extFileListOutput = toUploadableExtFileList(extFileListOutput); // Clean input element to trigger onChange event on input cleanInput(inputRef.current); @@ -595,8 +622,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { */ const outerFuiValidation = (fuiFileListToValidate: ExtFile[]): ExtFile[] => { const localValidator: FileValidatorProps = { maxFileSize, accept }; - - + let finalNumberOfValids: number = numberOfValidFiles; if (behaviour === "replace") { //re-start number of valids @@ -611,7 +637,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { maxFiles, localization ); - + return validatedFuiFileList; }; @@ -693,7 +719,8 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { } //init xhr on each ext file - if (url) extFileListOutput = toUploadableExtFileList(extFileListOutput); + if (shouldUpload) + extFileListOutput = toUploadableExtFileList(extFileListOutput); handleFilesChange(extFileListOutput); }; @@ -801,7 +828,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { maxFiles && validFilesCountHeader ? maxFiles : undefined } localization={localization} - urlPresent={url !== undefined && uploadFilesHeader} + urlPresent={shouldUpload && uploadFilesHeader} onUploadStart={ !autoUpload && !uploadButton ? () => uploadfiles(localFiles) diff --git a/src/Dropzone/components/dropzone/DropzoneProps.ts b/src/Dropzone/components/dropzone/DropzoneProps.ts index a3fc75a54d96a3bdf55316a1c36654c657c2a871..3ff9187af09873739a8491f592c1674b16a2e90d 100644 --- a/src/Dropzone/components/dropzone/DropzoneProps.ts +++ b/src/Dropzone/components/dropzone/DropzoneProps.ts @@ -153,8 +153,6 @@ export interface DropzoneFullProps extends OverridableComponentProps { * @default false */ disableRipple?: boolean; - - /** * Method for performing specific tasks on drag enter operations */ diff --git a/src/FileCard/FileCardProps.ts b/src/FileCard/FileCardProps.ts index d0ced8ffc57f7cc18a1a4cd101684f9ac556b83e..f37e660980c7bac044003e44b385352ce7984464 100644 --- a/src/FileCard/FileCardProps.ts +++ b/src/FileCard/FileCardProps.ts @@ -1,3 +1,4 @@ +import { ExtFile } from "@files-ui/core"; import { FileMosaicPropsMap } from "../FileMosaic/components/file-mosaic/FileMosaicProps"; @@ -7,7 +8,7 @@ export interface FileCardPropsMap extends FileMosaicPropsMap { } -export type FileCardProps = { +export type FileCardProps = ExtFile & { [F in keyof FileCardPropsMap]: FileCardPropsMap[F] } diff --git a/src/FileInputButton/FileInputButton.tsx b/src/FileInputButton/FileInputButton.tsx index dd90b1a633a37ba103e6ddfe8222540258e15747..07ddc2726bf6b0cec6e5457b1aee15dfdbc78e22 100644 --- a/src/FileInputButton/FileInputButton.tsx +++ b/src/FileInputButton/FileInputButton.tsx @@ -23,7 +23,7 @@ import { toUploadableExtFileList, cleanInput, FileIdGenerator, -} from "@files-ui/core" +} from "@files-ui/core"; import { DropzoneActions } from "../Dropzone/components/dropzone/DropzoneProps"; import DropzoneButtons from "../Dropzone/components/DropzoneButtons/DropzoneButtons"; import { FilesUiContext } from "../FilesUiProvider/FilesUiContext"; @@ -37,6 +37,7 @@ import { defaultFileInputButtonProps, FileInputButtonProps, } from "./InputButtonProps"; +import { isThereValidUrl } from "../utils/url.utils"; const FileInputButton: React.FC<FileInputButtonProps> = ( props: FileInputButtonProps @@ -114,6 +115,7 @@ const FileInputButton: React.FC<FileInputButtonProps> = ( cleanOnUpload = true, preparingTime = 1500, autoUpload = false, + urlFromExtFile, } = uploadConfig as UploadConfig; const { @@ -138,7 +140,10 @@ const FileInputButton: React.FC<FileInputButtonProps> = ( //Id for uploding through FuiFileManager //const inputButtonId: string | number = React.useId(); - const inputButtonId: string = React.useMemo(() => FileIdGenerator.getNextId() + "",[]); + const inputButtonId: string = React.useMemo( + () => FileIdGenerator.getNextId() + "", + [] + ); //Flag that determines whether to validate or not const validateFilesFlag: boolean = isValidateActive( accept, @@ -164,6 +169,14 @@ const FileInputButton: React.FC<FileInputButtonProps> = ( localization, validateFilesFlag ); + /** + * Flag that determines if component should perform upload given url + */ + const shouldUpload: boolean = isThereValidUrl( + url, + urlFromExtFile, + localFiles + ); /** * Uploads each file in the array of ExtFiles * First, sets all the files in preparing status and awaits `preparingTime` miliseconds. @@ -187,7 +200,6 @@ const FileInputButton: React.FC<FileInputButtonProps> = ( * @returns nothing */ const uploadfiles = async (localFiles: ExtFile[]): Promise<void> => { - //set uploading flag to true setIsUploading(true); @@ -241,7 +253,6 @@ const FileInputButton: React.FC<FileInputButtonProps> = ( x.toExtFile() ); - //CHANGE (o alejo el isUploading o lo alejo para que tenga m,as tiempo antes de la respuyesta) // setIsUploading(true); handleFilesChange(newExtFileLocal, true); @@ -259,8 +270,6 @@ const FileInputButton: React.FC<FileInputButtonProps> = ( for (let i = 0; i < arrOfExtFilesInstances.length; i++) { const currentExtFileInstance: ExtFileInstance = arrOfExtFilesInstances[i]; - - if ( currentExtFileInstance.uploadStatus === "preparing" && !currentExtFileInstance.extraData?.deleted @@ -297,6 +306,7 @@ const FileInputButton: React.FC<FileInputButtonProps> = ( uploadResponse = await uploadExtFile( currentExtFileInstance, url, + urlFromExtFile, method, headers, uploadLabel @@ -383,7 +393,6 @@ const FileInputButton: React.FC<FileInputButtonProps> = ( extFileList: ExtFile[], isUploading?: boolean ): void => { - let finalExtFileList: ExtFile[] = behaviour === "add" && !isUploading ? [...localFiles, ...extFileList] @@ -417,8 +426,9 @@ const FileInputButton: React.FC<FileInputButtonProps> = ( extFileListOutput = extFileListOutput.filter((f) => f.valid); } } - //init xhr on each dui file - if (url) extFileListOutput = toUploadableExtFileList(extFileListOutput); + //init xhr on each ext file + if (shouldUpload) + extFileListOutput = toUploadableExtFileList(extFileListOutput); // Clean input element to trigger onChange event on input cleanInput(inputRef.current); diff --git a/src/FileMosaic/components/file-mosaic/FileMosaicProps.ts b/src/FileMosaic/components/file-mosaic/FileMosaicProps.ts index b5b9948474ed215257bed34ccc77f166f3e2ef55..64817cdc198f4361cdb9dd9ab656b8f8093ee260 100644 --- a/src/FileMosaic/components/file-mosaic/FileMosaicProps.ts +++ b/src/FileMosaic/components/file-mosaic/FileMosaicProps.ts @@ -1,46 +1,7 @@ -import { Localization, UPLOADSTATUS } from "@files-ui/core" +import { ExtFile, Localization, UPLOADSTATUS } from "@files-ui/core" import { OverridableComponentProps } from "../../../overridable"; export interface FileMosaicPropsMap extends OverridableComponentProps { - /** - * The identifier for the file - */ - id?: string | number; - /** - * The file object obtained from client drop or selection - */ - file?: File; - /** - * The name of the file - */ - name?: string; - /** - * The file mime type - */ - type?: string; - /** - * the size of the file in bytes - */ - size?: number; - /** - * whether to show a valid or rejected message ("ok", "rejected") - * by def. valid is false (if not present, it's false too) - * This value wil affect preview behaviour, - * If not valid, the preview will not be shown, nor the view button - */ - valid?: boolean | null; - /** - * The list of errors according to the validation criteria or custom validation function given. - */ - errors?: string[]; - /** - * The message from server - */ - uploadMessage?: string; - /** - * The current upload status of the file - */ - uploadStatus?: UPLOADSTATUS; /** * if true, and if the file is an image, * makes visible the "view" button that will get the image url @@ -52,19 +13,6 @@ export interface FileMosaicPropsMap extends OverridableComponentProps { * @default false */ info?: boolean; - /** - * A string representation or web url of the image - * that will be set to the "src" prop of an <img/> If - * given, the component will use this image source instead of - * reading the image file. - */ - imageUrl?: string; - /** - * A string representation or web url of the video - * that will be set to the "src" prop of an <video/> tag - * <video src={`${videoUrl}`} /> - */ - videoUrl?: string; /** * If true, a background blur image will be shown */ @@ -127,7 +75,6 @@ export interface FileMosaicPropsMap extends OverridableComponentProps { * Callback fired when the component is right clicked if set. */ onRightClick?: (evt: React.MouseEvent) => void; - /** * Flag that determines whether actions are visible always, or only on hover event */ @@ -136,12 +83,6 @@ export interface FileMosaicPropsMap extends OverridableComponentProps { * If present a tooltip that contains the upload message will be diplayed on hover */ resultOnTooltip?: boolean; - /** - * The url to be used to perform a GET request in order to download the file. - * This action is triggered when download button is clicked or pressed. - * In case onDownload prop is given - */ - downloadUrl?: string; /** * If not present, image width will be set to 100%. * @@ -164,6 +105,7 @@ export type FileMosaicProps = /* { [D in keyof React.HTMLProps<HTMLDivElement>]: React.HTMLProps<HTMLDivElement>[D] } & */ + ExtFile & { [F in keyof FileMosaicPropsMap]: FileMosaicPropsMap[F] } diff --git a/src/utils/url.utils.ts b/src/utils/url.utils.ts new file mode 100644 index 0000000000000000000000000000000000000000..17877c2a838b82aa07b17f742cf3bd78eb1d7e9a --- /dev/null +++ b/src/utils/url.utils.ts @@ -0,0 +1,9 @@ +import { ExtFile, ExtFileInstance } from "@files-ui/core"; + +export const isThereValidUrl = ( + url?: string, + urlFunction?: Function, + extFileList?: ExtFile[] +): boolean => { + return ExtFileInstance.someValidUrl(extFileList) && url && url.length && urlFunction != undefined; +} \ No newline at end of file