diff --git a/src/components/Uploader/Uploader.jsx b/src/components/Uploader/Uploader.jsx deleted file mode 100644 index 01d5bc4..0000000 --- a/src/components/Uploader/Uploader.jsx +++ /dev/null @@ -1,38 +0,0 @@ -import { useAppSelector } from "../../hooks/store"; -import UploadItem from "../UploadItem"; -import React from "react"; - -const Uploader = React.forwardRef((props, ref) => { - const uploads = useAppSelector((state) => state.uploader.uploads); - - return ( -
-
-

- Uploading {uploads.length} {uploads.length === 1 ? "file" : "files"} -

-
- props.minimizeUploader()}> - upload__hide - - props.cancelAllUploadsEvent()}> - upload__hide - -
-
-
- {props.uploaderShow - ? uploads.map((upload) => { - return ; - }) - : undefined} -
-
- ); -}); - -export default Uploader; diff --git a/src/components/Uploader/index.jsx b/src/components/Uploader/index.jsx deleted file mode 100644 index 904254d..0000000 --- a/src/components/Uploader/index.jsx +++ /dev/null @@ -1,60 +0,0 @@ -import Uploader from "./Uploader"; -import {showUploader, hideUploader} from "../../actions/main"; -import {startCancelAllUploads} from "../../actions/uploads"; -import {connect} from "react-redux"; -import React from "react"; - -class UploaderContainer extends React.Component { - - constructor(props) { - super(props); - - this.uploaderWrapper = React.createRef() - this.prevUploadLength = 0; - } - - minimizeUploader = () => { - - const uploaderShow = this.props.uploaderShow; - const dispatch = this.props.dispatch; - - if (uploaderShow) { - - dispatch(hideUploader()) - - } else { - - dispatch(showUploader()) - } - } - - cancelAllUploadsEvent = () => { - - this.props.dispatch(startCancelAllUploads(this.props.uploads)) - } - - componentDidUpdate = () => { - - if (this.props.uploads.length !== this.prevUploadLength) { - if (this.uploaderWrapper.current) this.uploaderWrapper.current.scrollTop = 0; - } - - this.prevUploadLength = this.props.uploads.length; - } - - render() { - return - } - -} - -const connectStateToProp = (state) => ({ - uploads: state.uploads, - uploaderShow: state.main.uploaderShow -}) - -export default connect(connectStateToProp)(UploaderContainer); \ No newline at end of file diff --git a/src/components/Uploader/index.tsx b/src/components/Uploader/index.tsx new file mode 100644 index 0000000..b437839 --- /dev/null +++ b/src/components/Uploader/index.tsx @@ -0,0 +1,61 @@ +import { useAppDispatch, useAppSelector } from "../../hooks/store"; +import CloseIcon from "../../icons/CloseIcon"; +import MinimizeIcon from "../../icons/MinimizeIcon"; +import { resetUploads } from "../../reducers/uploader"; +import { cancelAllFileUploads } from "../../utils/cancelTokenManager"; +import UploadItem from "../UploadItem"; +import { memo, useMemo, useState } from "react"; + +const Uploader = memo(() => { + const [minimized, setMinimized] = useState(false); + const uploads = useAppSelector((state) => state.uploader.uploads); + const dispatch = useAppDispatch(); + + const toggleMinimize = () => { + setMinimized(!minimized); + }; + + const uploadTitle = useMemo(() => { + const uploadedCount = uploads.filter((upload) => upload.completed).length; + const currentlyUploadingCount = uploads.filter( + (upload) => !upload.completed + ).length; + + if (currentlyUploadingCount) { + return `Uploading ${currentlyUploadingCount} file${ + currentlyUploadingCount > 1 ? "s" : "" + }`; + } else { + return `Uploaded ${uploadedCount} file${uploadedCount > 1 ? "s" : ""}`; + } + }, [uploads]); + + const closeUploader = () => { + cancelAllFileUploads(); + dispatch(resetUploads()); + }; + + return ( +
+
+

{uploadTitle}

+
+ + + + + + +
+
+
+ {!minimized && + uploads.map((upload) => { + return ; + })} +
+
+ ); +}); + +export default Uploader; diff --git a/src/hooks/files.ts b/src/hooks/files.ts index 7d83da8..25b1665 100644 --- a/src/hooks/files.ts +++ b/src/hooks/files.ts @@ -21,7 +21,10 @@ import { useUtils } from "./utils"; import { FileInterface } from "../types/file"; import { v4 as uuid } from "uuid"; import axiosNonInterceptor from "axios"; -import { addFileUploadCancelToken } from "../utils/cancelTokenManager"; +import { + addFileUploadCancelToken, + removeFileUploadCancelToken, +} from "../utils/cancelTokenManager"; import { debounce } from "lodash"; import { addUpload, editUpload } from "../reducers/uploader"; @@ -209,7 +212,7 @@ export const useUploader = () => { const debounceDispatch = debounce(dispatch, 200); - const uploadFiles = async (files: FileList) => { + const uploadFiles = (files: FileList) => { for (let i = 0; i < files.length; i++) { const parent = params.id || "/"; @@ -262,23 +265,26 @@ export const useUploader = () => { data.append("size", currentFile.size.toString()); data.append("file", currentFile); - try { - await uploadFileAPI(data, config); - dispatch( - editUpload({ - id: currentID, - updateData: { completed: true, progress: 100 }, - }) - ); - } catch (e) { - console.log("Error uploading file", e); - dispatch( - editUpload({ - id: currentID, - updateData: { canceled: true }, - }) - ); - } + uploadFileAPI(data, config) + .then(() => { + dispatch( + editUpload({ + id: currentID, + updateData: { completed: true, progress: 100 }, + }) + ); + removeFileUploadCancelToken(currentID); + }) + .catch((e) => { + console.log("Error uploading file", e); + dispatch( + editUpload({ + id: currentID, + updateData: { canceled: true }, + }) + ); + removeFileUploadCancelToken(currentID); + }); } }; diff --git a/src/icons/MinimizeIcon.tsx b/src/icons/MinimizeIcon.tsx new file mode 100644 index 0000000..6c96276 --- /dev/null +++ b/src/icons/MinimizeIcon.tsx @@ -0,0 +1,12 @@ +type MinimizeIconType = React.SVGAttributes; + +const MinimizeIcon: React.FC = (props) => { + return ( + + minus + + + ); +}; + +export default MinimizeIcon; diff --git a/src/reducers/uploader.ts b/src/reducers/uploader.ts index cf8f87c..7b3242b 100644 --- a/src/reducers/uploader.ts +++ b/src/reducers/uploader.ts @@ -22,7 +22,7 @@ const uploaderSlice = createSlice({ initialState, reducers: { addUpload(state, action: PayloadAction) { - state.uploads.push(action.payload); + state.uploads.unshift(action.payload); }, editUpload( state, @@ -48,9 +48,12 @@ const uploaderSlice = createSlice({ state.uploads = uploads; }, + resetUploads(state) { + state.uploads = []; + }, }, }); -export const { addUpload, editUpload } = uploaderSlice.actions; +export const { addUpload, editUpload, resetUploads } = uploaderSlice.actions; export default uploaderSlice.reducer; diff --git a/src/utils/cancelTokenManager.ts b/src/utils/cancelTokenManager.ts index 757e1d1..6c1c759 100644 --- a/src/utils/cancelTokenManager.ts +++ b/src/utils/cancelTokenManager.ts @@ -14,6 +14,10 @@ export const addFileUploadCancelToken = (id: string, cancelToken: any) => { cancelTokens[id] = cancelToken; }; +export const removeFileUploadCancelToken = (id: string) => { + delete cancelTokens[id]; +}; + export const getCancelToken = (id: string) => { return cancelTokens[id]; };