diff --git a/src/components/demo-components/dropzone-demo/AdvancedDropzoneDemo.jsx b/src/components/demo-components/dropzone-demo/AdvancedDropzoneDemo.jsx index f71d0c7e40c501bc7897d837e39855e8fd93b098..7fb9aea6f0f366dcfd1d5764e54a7e6090bad4f7 100644 --- a/src/components/demo-components/dropzone-demo/AdvancedDropzoneDemo.jsx +++ b/src/components/demo-components/dropzone-demo/AdvancedDropzoneDemo.jsx @@ -8,6 +8,7 @@ import { } from "../../../files-ui"; import { useEffect, useState } from "react"; import axios from "axios"; +import { ExtFileInstance } from "../../../files-ui/core"; const REMOTE = "https://files-ui-express-static-file-storage.vercel.app/39d33dff2d41b522c1ea276c4b82507f96b9699493d2e7b3f5c864ba743d9503"; //const LOCAL = "http://localhost/39d33dff2d41b522c1ea276c4b82507f96b9699493d2e7b3f5c864ba743d9503"; @@ -19,6 +20,15 @@ export default function AdvancedDropzoneDemo() { const updateFiles = (incommingFiles) => { console.log("incomming extFiles", incommingFiles); + const arrExtFIleInstances = incommingFiles.map( + (extFile) => new ExtFileInstance(extFile) + ); + const listExtFileObjects = arrExtFIleInstances.map((extFileInstance) => + extFileInstance.toExtFile() + ); + console.log("incomming arrExtFIleInstances", arrExtFIleInstances); + console.log("incomming listExtFileObjects", listExtFileObjects); + setExtFiles(incommingFiles); }; const onDelete = (id) => { @@ -56,7 +66,7 @@ export default function AdvancedDropzoneDemo() { } } const handleAbort = (id) => { - // alert(id); + // alert(id); setExtFiles( extFiles.map((ef) => { if (ef.id === id) { @@ -65,16 +75,16 @@ export default function AdvancedDropzoneDemo() { }) ); }; - const handleCancel= (id) => { + const handleCancel = (id) => { // alert(id); - setExtFiles( - extFiles.map((ef) => { - if (ef.id === id) { - return { ...ef, uploadStatus: undefined }; - } else return { ...ef }; - }) - ); - }; + setExtFiles( + extFiles.map((ef) => { + if (ef.id === id) { + return { ...ef, uploadStatus: undefined }; + } else return { ...ef }; + }) + ); + }; return ( <> <Dropzone diff --git a/src/components/demo-components/main-page/DropzoneMainPage.jsx b/src/components/demo-components/main-page/DropzoneMainPage.jsx index 2ded2ed94f5e4d4d51a33d6e2533c5483c5922cd..adde2c95212aee8dea73e07d37ce0a4a7f923aeb 100644 --- a/src/components/demo-components/main-page/DropzoneMainPage.jsx +++ b/src/components/demo-components/main-page/DropzoneMainPage.jsx @@ -41,13 +41,12 @@ const DropzoneMainPage = ({ darkMode = false }) => { // minHeight="400px" onChange={updateFiles} value={files} - maxFileSize={28 * 1024 * 10} + maxFileSize={28 * 1024 * 1024} maxFiles={5} - accept=".jpg, .png, application/json, video/*" + accept=".jpg, .png, application/json, video/*, .pdf" fakeUpload behaviour="add" uploadConfig={{ autoUpload: true , url:"fdbd"}} - //uploadConfig={{ autoUpload: true, url:"fdbd" }} > {files.length > 0 && files.map((file) => ( @@ -62,6 +61,7 @@ const DropzoneMainPage = ({ darkMode = false }) => { hd onSee={handleSee} resultOnTooltip + //uploadMessage="llalalal" /> ))} </Dropzone> diff --git a/src/files-ui/components/dropzone/components/dropzone/Dropzone.tsx b/src/files-ui/components/dropzone/components/dropzone/Dropzone.tsx index 19e38afbab90980e4a96c32b023d4d2a07a5dcf5..a5d4d61d8020e9988430ea89678c804e6dafddd2 100644 --- a/src/files-ui/components/dropzone/components/dropzone/Dropzone.tsx +++ b/src/files-ui/components/dropzone/components/dropzone/Dropzone.tsx @@ -25,6 +25,8 @@ import { cleanInput, isUploadAbleExtFile, sanitizeArrExtFile, + unexpectedErrorUploadResult, + getRandomInt, } from "../../../../core"; import { mergeProps } from "../../../overridable"; import InputHidden from "../../../input-hidden/InputHidden"; @@ -187,7 +189,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { return; } - // initialize new list of ExtFileInstances + // initialize a new list of ExtFileInstances let arrOfExtFilesInstances: ExtFileInstance[] = []; const totalNumber: number = localFiles.length; @@ -269,55 +271,81 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { instantPreparingToUploadOne(currentExtFileInstance); + //messge in footer setLocalMessage( uploadingMessenger(`${++currentCountUpload}/${missingUpload}`) ); - //CHANGE + + //CHANGE FILES handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); //UPLOADING => UPLOAD() //upload one file and notify about change let uploadResponse: UploadResponse; - try { - uploadResponse = fakeUpload - ? await fakeFuiUpload(currentExtFileInstance, DropzoneLocalizer) - : await uploadExtFile( - currentExtFileInstance, - url, - method, - headers, - uploadLabel - ); - } catch (error) { - uploadResponse = { - id: currentExtFileInstance.id, - serverResponse: { - success: false, - message: "Error on upload: unexpected error " + error, - payload: {}, - }, - uploadedFile: { ...currentExtFileInstance }, - }; + + 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( + currentExtFileInstance, + url, + method, + headers, + uploadLabel + ); + } catch (error) { + uploadResponse = unexpectedErrorUploadResult( + currentExtFileInstance.toExtFile() + ); + } } const { uploadedFile } = uploadResponse; + console.log("fake uploadResponse uploadedFile", uploadedFile); + //update instances currentExtFileInstance.uploadStatus = uploadedFile.uploadStatus; currentExtFileInstance.uploadMessage = uploadedFile.uploadMessage; - //add fake progress only on fakeupload - if (fakeUpload) { - console.log( - "Adding fake progress", - fakeUpload, - uploadedFile.progress - ); - currentExtFileInstance.progress = uploadedFile.progress; - } + console.log( + "fake uploadResponse currentExtFileInstance", + currentExtFileInstance + ); + console.log( + "fake uploadResponse currentExtFileInstance", + currentExtFileInstance.uploadStatus + ); + console.log( + "fake uploadResponse currentExtFileInstance", + currentExtFileInstance.uploadMessage + ); + + console.log( + "pre sanitizeArrExtFile", + arrOfExtFilesInstances.map((F) => {return{status:F.uploadStatus,message:F.uploadMessage}}) + ); + + //CHANGE if (!(currentExtFileInstance.uploadStatus === "aborted")) await sleepTransition(); + console.log( + "pre sanitizeArrExtFile", + arrOfExtFilesInstances.map((F) => {return{status:F.uploadStatus,message:F.uploadMessage}}) + ); handleFilesChange(sanitizeArrExtFile(arrOfExtFilesInstances), true); if (uploadedFile.uploadStatus === "error") { @@ -396,11 +424,11 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { }, [maxFileSize, accept, maxFiles, localization]); /** - * Performs the changes in the FuiFile list. - * Makes a new array of FuiFiles according to the "behaviour" prop. + * Performs the changes in the extFile list. + * Makes a new array of extFile according to the "behaviour" prop. * If isUploading state is not true and the behaviour props is equal to "add", - * the incoming extFileList is added at the end of the current list of fuiFiles. - * Otherwise, the complete fuiFile list replaced by the incomming fuiFileList + * the incoming extFileList is added at the end of the current list of extFile. + * Otherwise, the complete extFile list is replaced by the incomming extFile list * @param extFileList the new fileList * @param isUploading a flag that dscribes whther the uploading process is active or not */ @@ -410,7 +438,7 @@ const Dropzone: React.FC<DropzoneProps> = (props: DropzoneProps) => { ): void => { console.log( "handleFilesChange", - extFileList.map((F) => F.uploadStatus) + extFileList.map((F) => F.uploadMessage) ); let finalExtFileList: ExtFile[] = behaviour === "add" && !isUploading diff --git a/src/files-ui/core/types/ExtFile.ts b/src/files-ui/core/types/ExtFile.ts index 782b3f6b0faca0b88a80be18b4b8606885e213ec..2e840ac26bc270a831cb36312d1f954b790c60c3 100644 --- a/src/files-ui/core/types/ExtFile.ts +++ b/src/files-ui/core/types/ExtFile.ts @@ -200,84 +200,33 @@ export class ExtFileInstance { } - static toExtFile(extFile: ExtFileInstance): ExtFile { - const - { - id, - file, - name, - size, - type, - imageUrl, - valid, - errors, - uploadMessage, - uploadStatus, - progress, - xhr, - extraData, - extraUploadData, - serverResponse, - downloadUrl - } = extFile; - return { - id, - file, - name, - size, - type, - imageUrl, - valid, - errors, - uploadMessage, - uploadStatus, - progress, - xhr, - extraData, - extraUploadData, - serverResponse, - downloadUrl - }; + /** + * Copies all non undefined attributes from ExtFileInstance to a new ExtFile object + * @param extFileInstance the instance of ExtFile + * @returns an ExtFile object + */ + static toExtFile(extFileInstance: ExtFileInstance): ExtFile { + console.log("before toExtFile()", extFileInstance); + + let extFileClone: ExtFile = {}; // the new empty object + const extFileInstanceKeys = Object.keys(extFileInstance) as [keyof ExtFile]; + const extFileInstanceValues = Object.values(extFileInstance); + // let's copy all user properties into it + for (let i = 0; i < extFileInstanceKeys.length; i++) { + if (extFileInstanceValues[i] !== undefined) { + extFileClone[extFileInstanceKeys[i]] = extFileInstanceValues[i]; + } + } + console.log("after toExtFile()", extFileClone); + + return extFileClone; } + /** + * Copies all non undefined attributes from ExtFileInstance to a new ExtFile object. + * @returns an ExtFile object + */ toExtFile(): ExtFile { - const { - id, - file, - name, - size, - type, - imageUrl, - valid, - errors, - uploadMessage, - uploadStatus, - progress, - xhr, - extraData, - extraUploadData, - serverResponse, - downloadUrl - } = this; - - const result: ExtFile = { - id, - file, - name, - size, - type, - imageUrl, - valid, - errors, - uploadMessage, - uploadStatus, - progress, - xhr, - extraData, - extraUploadData, - serverResponse, - downloadUrl - }; - return result; + return ExtFileInstance.toExtFile(this); } static mock = (): ExtFileInstance => { diff --git a/src/files-ui/core/upload/utils.upload.ts b/src/files-ui/core/upload/utils.upload.ts index 121f7a5c9eba7dc98547f37b26a424315ac78256..316ab7f810b118085dca7b860dcc21a4a61c0e49 100644 --- a/src/files-ui/core/upload/utils.upload.ts +++ b/src/files-ui/core/upload/utils.upload.ts @@ -1,3 +1,4 @@ + import { ExtFile, ExtFileInstance, ServerResponse, UploadResponse, UPLOADSTATUS } from "../types" export const unexpectedErrorUploadResult = (extFile: ExtFile): UploadResponse => { @@ -6,10 +7,13 @@ export const unexpectedErrorUploadResult = (extFile: ExtFile): UploadResponse => uploadedFile: { ...extFile, - uploadMessage: "Unable to upload. xhr object was not provided", + uploadMessage: "Unexpected error", uploadStatus: "error" }, serverResponse: { + success: false, + message: "Error on upload: unexpected error ", + payload: {}, } } } @@ -24,20 +28,23 @@ export const unableToUploadResult = ( uploadStatus: "error" }, serverResponse: { + success: false, + message: "Error on upload: Unable to upload. XHR was not provided ", + payload: {}, } } } export const completeUploadResult = ( extFile: ExtFile, serverResponse: ServerResponse, - result: UPLOADSTATUS + uploadStatusresult: UPLOADSTATUS ): UploadResponse => { return { id: extFile.id, uploadedFile: { ...extFile, uploadMessage: serverResponse.message, - uploadStatus: result + uploadStatus: uploadStatusresult }, serverResponse: serverResponse } @@ -104,20 +111,26 @@ export const preparingToUploadOne = ( /** * Sleeps for 1200 miliseconds for showing a better transition * on uploading + * @param time the time to sleep in miliseconds * @returns true is everything is ok */ -export const sleepTransition = ( +export const sleepTransition = (time = 1500 ): Promise<boolean> => { return new Promise((resolve, reject) => { setTimeout(() => { resolve(true); - }, 1500); + }, time); }); } export const sanitizeArrExtFile = (arrExtFile: ExtFileInstance[]): ExtFile[] => { + console.log( + "sanitizeArrExtFile", + arrExtFile.map((F) => { return { status: F.uploadStatus, message: F.uploadMessage } }) + ); return arrExtFile.filter((extFileInstance: ExtFileInstance) => !extFileInstance.extraData?.deleted) + .map((extFileInstance: ExtFileInstance) => { if (extFileInstance.uploadStatus === "aborted" && !extFileInstance.uploadMessage) { @@ -125,7 +138,7 @@ export const sanitizeArrExtFile = (arrExtFile: ExtFileInstance[]): ExtFile[] => //extFileInstance.uploadStatus = "error"; } - return extFileInstance.toExtFile() + return ExtFileInstance.toExtFile(extFileInstance) as ExtFile }); } /** @@ -140,18 +153,23 @@ export const setNextUploadStatus = ( const prevStatus: UPLOADSTATUS | undefined = extFileInstance.uploadStatus; const nextStstaus: UPLOADSTATUS | undefined = extFileobj.uploadStatus; + console.log("setNextUploadStatus", prevStatus, nextStstaus); + console.log("setNextUploadStatus", extFileInstance.uploadMessage, extFileobj.uploadMessage); if ( prevStatus === "preparing" && ["aborted", undefined].includes(nextStstaus) ) { extFileInstance.uploadStatus = undefined; + extFileInstance.uploadMessage = extFileobj.uploadMessage; + } else if ( prevStatus === "uploading" && ["aborted", undefined].includes(nextStstaus) ) { extFileInstance.uploadStatus = "aborted"; + extFileInstance.uploadMessage = extFileobj.uploadMessage; } - extFileInstance.uploadMessage = extFileobj.uploadMessage; -} \ No newline at end of file +} + diff --git a/src/files-ui/core/utils/fakeupload.utils.ts b/src/files-ui/core/utils/fakeupload.utils.ts index 1131cd6158201cfa112a66ab2a92e82eb5e6f63f..54d20f3934178967237087a3cb09bb90efa4f8a4 100644 --- a/src/files-ui/core/utils/fakeupload.utils.ts +++ b/src/files-ui/core/utils/fakeupload.utils.ts @@ -1,3 +1,4 @@ + import { DropzoneLocalizerSelector } from "../localization"; import { ExtFile, ExtFileInstance, UploadResponse } from "../types"; @@ -105,9 +106,11 @@ export const uploadOneExtFile = ( * @returns a duiUploadResponse object that describes the result */ export const fakeFuiUpload = ( - extFile: ExtFileInstance, + extFileInstance: ExtFileInstance, DropzoneLocalizer = DropzoneLocalizerSelector("EN-en") ): Promise<UploadResponse> => { + const extFile:ExtFile = extFileInstance.toExtFile(); + return new Promise((resolve, reject) => { setTimeout(() => { const randomNumber: number = Math.floor(Math.random() * 10); @@ -143,4 +146,5 @@ export const fakeFuiUpload = ( } }, 1700); }); -}; \ No newline at end of file +}; + diff --git a/src/pages/api/FileMosaicApi.jsx b/src/pages/api/FileMosaicApi.jsx index 7b4e97c8e59932565ee9a984e40dd9c4373244e3..7e2324e8ddd44cb2e4106b5deefd8286119c7c44 100644 --- a/src/pages/api/FileMosaicApi.jsx +++ b/src/pages/api/FileMosaicApi.jsx @@ -1,4 +1,4 @@ -import { Alert } from "@mui/material"; +import { Alert, IconButton, Tooltip } from "@mui/material"; import * as React from "react"; import DescParagraph from "../../components/demo-components/desc-paragraph/DescParagraph"; import SubTitle from "../../components/demo-components/sub-title/SubTitle"; @@ -7,7 +7,7 @@ import RightMenuContainer from "../../components/layout-pages/RightMenuContainer import MainTitle from "../../components/main-title/MainTitle"; import RightMenu from "../../components/RightMenu/RightMenu"; import { FileMosaicAPIPropsRows } from "../../data/FileMosaicAPIPropsRows"; - +import FilterListIcon from "@mui/icons-material/FilterList"; import PropsTableApi from "./PropsTableApi"; const rightMenuItems = [ @@ -39,14 +39,15 @@ const FileMosaicApi = (props) => { visit the component demo pages: <ul> <li> - <a href="/components/filemosaic">FileMosaic. </a> + <a href="/components/filemosaic">FileMosaic</a> + </li> + <li> + <a href="/components/dropzone">Dropzone</a> </li> </ul> </Alert> </section> <section id="filemosaic-props"> - {/* <SubTitle content="Props" /> */} - <PropsTableApi rows={FileMosaicAPIPropsRows} /> </section> </MainContentContainer> @@ -57,4 +58,4 @@ const FileMosaicApi = (props) => { </React.Fragment> ); }; -export default FileMosaicApi; +export default FileMosaicApi; \ No newline at end of file