From 8d5f8454c4dd2274085e77b8b614e20ded2ea914 Mon Sep 17 00:00:00 2001 From: Nawaz Dhandala Date: Wed, 19 Nov 2025 16:02:41 +0000 Subject: [PATCH] Refactor FilePicker and AttachmentList components to enhance type definitions and improve code clarity --- .../UI/Components/FilePicker/FilePicker.tsx | 50 ++++++++++++++----- .../Components/Attachment/AttachmentList.tsx | 16 ++++-- 2 files changed, 50 insertions(+), 16 deletions(-) diff --git a/Common/UI/Components/FilePicker/FilePicker.tsx b/Common/UI/Components/FilePicker/FilePicker.tsx index 59c701bd82..e702618899 100644 --- a/Common/UI/Components/FilePicker/FilePicker.tsx +++ b/Common/UI/Components/FilePicker/FilePicker.tsx @@ -14,7 +14,8 @@ import React, { useEffect, useState, } from "react"; -import { useDropzone } from "react-dropzone"; +import { useDropzone, type FileRejection } from "react-dropzone"; +import type { AxiosProgressEvent } from "axios"; export interface ComponentProps { initialValue?: undefined | Array | FileModel; @@ -41,6 +42,21 @@ type UploadStatus = { errorMessage?: string | undefined; }; +type AddUploadStatusFunction = (status: UploadStatus) => void; +type UpdateUploadStatusFunction = ( + id: string, + updates: Partial, +) => void; +type UpdateUploadProgressFunction = ( + id: string, + total?: number, + loaded?: number, +) => void; +type RemoveUploadStatusFunction = (id: string) => void; +type BuildFileSizeErrorFunction = (fileNames: Array) => string; +type ResolveMimeTypeFunction = (file: File) => MimeType | undefined; +type FormatFileSizeFunction = (file: FileModel) => string | null; + const MAX_FILE_SIZE_BYTES: number = 10 * 1024 * 1024; // 10MB limit const FilePicker: FunctionComponent = ( @@ -53,13 +69,15 @@ const FilePicker: FunctionComponent = ( const [acceptTypes, setAcceptTypes] = useState>>({}); const [uploadStatuses, setUploadStatuses] = useState>([]); - const addUploadStatus = (status: UploadStatus): void => { + const addUploadStatus: AddUploadStatusFunction = ( + status: UploadStatus, + ): void => { setUploadStatuses((current: Array) => { return [...current, status]; }); }; - const updateUploadStatus = ( + const updateUploadStatus: UpdateUploadStatusFunction = ( id: string, updates: Partial, ): void => { @@ -75,7 +93,7 @@ const FilePicker: FunctionComponent = ( }); }; - const updateUploadProgress = ( + const updateUploadProgress: UpdateUploadProgressFunction = ( id: string, total?: number, loaded?: number, @@ -101,7 +119,7 @@ const FilePicker: FunctionComponent = ( }); }; - const removeUploadStatus = (id: string): void => { + const removeUploadStatus: RemoveUploadStatusFunction = (id: string): void => { setUploadStatuses((current: Array) => { return current.filter((upload: UploadStatus) => { return upload.id !== id; @@ -143,7 +161,9 @@ const FilePicker: FunctionComponent = ( } }, [props.value]); - const buildFileSizeError = (fileNames: Array): string => { + const buildFileSizeError: BuildFileSizeErrorFunction = ( + fileNames: Array, + ): string => { if (fileNames.length === 0) { return ""; } @@ -161,12 +181,12 @@ const FilePicker: FunctionComponent = ( noClick: true, disabled: props.readOnly || isLoading, maxSize: MAX_FILE_SIZE_BYTES, - onDropRejected: (fileRejections) => { + onDropRejected: (fileRejections: Array) => { const oversizedFiles: Array = fileRejections - .filter((rejection) => { + .filter((rejection: FileRejection) => { return rejection.file.size > MAX_FILE_SIZE_BYTES; }) - .map((rejection) => { + .map((rejection: FileRejection) => { return rejection.file.name; }); @@ -185,7 +205,9 @@ const FilePicker: FunctionComponent = ( try { // Upload these files. const filesResult: Array = []; - const resolveMimeType = (file: File): MimeType | undefined => { + const resolveMimeType: ResolveMimeTypeFunction = ( + file: File, + ): MimeType | undefined => { const direct: string | undefined = file.type || undefined; if (direct && Object.values(MimeType).includes(direct as MimeType)) { return direct as MimeType; @@ -260,7 +282,7 @@ const FilePicker: FunctionComponent = ( requestOptions: { overrideRequestUrl: CommonURL.fromURL(FILE_URL), apiRequestOptions: { - onUploadProgress: (progressEvent) => { + onUploadProgress: (progressEvent: AxiosProgressEvent) => { updateUploadProgress( uploadId, progressEvent.total, @@ -307,7 +329,9 @@ const FilePicker: FunctionComponent = ( type GetThumbsFunction = () => Array; - const formatFileSize = (file: FileModel): string | null => { + const formatFileSize: FormatFileSizeFunction = ( + file: FileModel, + ): string | null => { const buffer: Buffer | undefined = file.file; if (!buffer) { return null; @@ -324,7 +348,7 @@ const FilePicker: FunctionComponent = ( const getThumbs: GetThumbsFunction = (): Array => { return filesModel.map((file: FileModel, i: number) => { const key: string = file._id?.toString() || `${file.name || "file"}-${i}`; - const removeFile = (): void => { + const removeFile: VoidFunction = (): void => { const tempFileModel: Array = [...filesModel]; tempFileModel.splice(i, 1); setFilesModel(tempFileModel); diff --git a/Dashboard/src/Components/Attachment/AttachmentList.tsx b/Dashboard/src/Components/Attachment/AttachmentList.tsx index 3010a529a1..d4be7850ae 100644 --- a/Dashboard/src/Components/Attachment/AttachmentList.tsx +++ b/Dashboard/src/Components/Attachment/AttachmentList.tsx @@ -17,6 +17,10 @@ export interface AttachmentListProps { buildAttachmentUrl?: (fileId: string) => string; } +type GetFileExtensionFunction = (fileName?: string | null) => string | null; +type GetFileMetadataFunction = (file: FileModel) => string | null; +type GetAttachmentNameFunction = (file: FileModel) => string; + const AttachmentList: FunctionComponent = ( props: AttachmentListProps, ): ReactElement | null => { @@ -37,7 +41,9 @@ const AttachmentList: FunctionComponent = ( const projectId: string | null = ProjectUtil.getCurrentProjectId()?.toString() || null; - const getFileExtension = (fileName?: string | null): string | null => { + const getFileExtension: GetFileExtensionFunction = ( + fileName?: string | null, + ): string | null => { if (!fileName) { return null; } @@ -52,7 +58,9 @@ const AttachmentList: FunctionComponent = ( return trimmedName.substring(lastDotIndex + 1).toUpperCase(); }; - const getFileMetadata = (file: FileModel): string | null => { + const getFileMetadata: GetFileMetadataFunction = ( + file: FileModel, + ): string | null => { const metadataParts: Array = []; if (file.fileType) { @@ -72,7 +80,9 @@ const AttachmentList: FunctionComponent = ( return metadataParts.join(" • "); }; - const getAttachmentName = (file: FileModel): string => { + const getAttachmentName: GetAttachmentNameFunction = ( + file: FileModel, + ): string => { if (file.name) { return file.name; }