diff --git a/src/components/CSVImporter/CSVImporter.stories.tsx b/src/components/CSVImporter/CSVImporter.stories.tsx index 5dde0422..cb02096d 100644 --- a/src/components/CSVImporter/CSVImporter.stories.tsx +++ b/src/components/CSVImporter/CSVImporter.stories.tsx @@ -52,7 +52,18 @@ const Template: Story = (args: CSVImporterProps) => { return (
- {args.isModal && } + {args.isModal && ( + <> + + { + args.file = e.target.files?.[0]; + setIsOpen(true); + }} + /> + + )}
); diff --git a/src/importer/components/UploaderWrapper/UploaderWrapper.tsx b/src/importer/components/UploaderWrapper/UploaderWrapper.tsx index f5d10b51..2f46c12c 100644 --- a/src/importer/components/UploaderWrapper/UploaderWrapper.tsx +++ b/src/importer/components/UploaderWrapper/UploaderWrapper.tsx @@ -1,10 +1,10 @@ import { useState } from "react"; -import { UploaderWrapperProps } from "./types"; import { useDropzone } from "react-dropzone"; -import { Box, Text } from "@chakra-ui/react"; import { Button } from "@chakra-ui/button"; -import { PiArrowCounterClockwise, PiFile } from "react-icons/pi"; +import { Box, Text } from "@chakra-ui/react"; import useThemeStore from "../../stores/theme"; +import { UploaderWrapperProps } from "./types"; +import { PiArrowCounterClockwise, PiFile } from "react-icons/pi"; export default function UploaderWrapper({ onSuccess, setDataError, ...props }: UploaderWrapperProps) { const [loading, setLoading] = useState(false); @@ -34,24 +34,19 @@ export default function UploaderWrapper({ onSuccess, setDataError, ...props }: U }); return ( - - + - + borderRadius="var(--border-radius-2)"> + {isDragActive ? ( Drop your file here ) : loading ? ( @@ -60,17 +55,20 @@ export default function UploaderWrapper({ onSuccess, setDataError, ...props }: U <> Drop your file here or - diff --git a/src/importer/features/main/index.tsx b/src/importer/features/main/index.tsx index 28c012fb..5f4c3202 100644 --- a/src/importer/features/main/index.tsx +++ b/src/importer/features/main/index.tsx @@ -28,6 +28,7 @@ export default function Main(props: CSVImporterProps) { customStyles, showDownloadTemplateButton, skipHeaderRowSelection, + file, } = props; const skipHeader = skipHeaderRowSelection ?? false; @@ -80,6 +81,10 @@ export default function Main(props: CSVImporterProps) { } }, [data]); + useEffect(() => { + if (file) processFile(file); + }, [file]); + // Actions const reload = () => { setData(emptyData); @@ -107,6 +112,64 @@ export default function Main(props: CSVImporterProps) { ); } + const processFile = async (file: File) => { + setDataError(null); + const fileType = file.name.slice(file.name.lastIndexOf(".") + 1); + if (!["csv", "xls", "xlsx"].includes(fileType)) { + setDataError("Only CSV, XLS, and XLSX files can be uploaded"); + return; + } + const reader = new FileReader(); + const isNotBlankRow = (row: string[]) => row.some((cell) => cell.toString().trim() !== ""); + reader.onload = async (e) => { + const bstr = e?.target?.result; + if (!bstr) { + return; + } + switch (fileType) { + case "csv": + Papa.parse(bstr.toString(), { + complete: function (results) { + const csvData = results.data as Array>; + const rows: FileRow[] = csvData.filter(isNotBlankRow).map((row: string[], index: number) => ({ index, values: row })); + setData({ + fileName: file.name, + rows: rows, + sheetList: [], + errors: results.errors.map((error) => error.message), + }); + goNext(); + }, + }); + break; + case "xlsx": + case "xls": + const workbook = XLSX.read(bstr as string, { type: "binary" }); + const sheetList = workbook.SheetNames; + const data = XLSX.utils.sheet_to_json(workbook.Sheets[sheetList[0]], { header: 1 }) as Array>; + const rows: FileRow[] = data.filter(isNotBlankRow).map((row: string[], index: number) => ({ index, values: row })); + setData({ + fileName: file.name, + rows: rows, + sheetList: sheetList, + errors: [], // TODO: Handle any parsing errors + }); + goNext(); + break; + } + }; + + switch (fileType) { + case "csv": + reader.readAsText(file, "utf-8"); + break; + case "xlsx": + case "xls": + reader.readAsBinaryString(file); + break; + } + }; + const renderContent = () => { switch (currentStep) { case StepEnum.Upload: @@ -116,63 +179,7 @@ export default function Main(props: CSVImporterProps) { skipHeaderRowSelection={skipHeader || false} showDownloadTemplateButton={showDownloadTemplateButton} setDataError={setDataError} - onSuccess={async (file: File) => { - setDataError(null); - const fileType = file.name.slice(file.name.lastIndexOf(".") + 1); - if (!["csv", "xls", "xlsx"].includes(fileType)) { - setDataError("Only CSV, XLS, and XLSX files can be uploaded"); - return; - } - const reader = new FileReader(); - const isNotBlankRow = (row: string[]) => row.some((cell) => cell.toString().trim() !== ""); - reader.onload = async (e) => { - const bstr = e?.target?.result; - if (!bstr) { - return; - } - switch (fileType) { - case "csv": - Papa.parse(bstr.toString(), { - complete: function (results) { - const csvData = results.data as Array>; - const rows: FileRow[] = csvData.filter(isNotBlankRow).map((row: string[], index: number) => ({ index, values: row })); - setData({ - fileName: file.name, - rows: rows, - sheetList: [], - errors: results.errors.map((error) => error.message), - }); - goNext(); - }, - }); - break; - case "xlsx": - case "xls": - const workbook = XLSX.read(bstr as string, { type: "binary" }); - const sheetList = workbook.SheetNames; - const data = XLSX.utils.sheet_to_json(workbook.Sheets[sheetList[0]], { header: 1 }) as Array>; - const rows: FileRow[] = data.filter(isNotBlankRow).map((row: string[], index: number) => ({ index, values: row })); - setData({ - fileName: file.name, - rows: rows, - sheetList: sheetList, - errors: [], // TODO: Handle any parsing errors - }); - goNext(); - break; - } - }; - - switch (fileType) { - case "csv": - reader.readAsText(file, "utf-8"); - break; - case "xlsx": - case "xls": - reader.readAsBinaryString(file); - break; - } - }} + onSuccess={processFile} /> ); case StepEnum.RowSelection: diff --git a/src/types/index.ts b/src/types/index.ts index 1a8961d2..6c77bf5b 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -17,4 +17,5 @@ export type CSVImporterProps = (HTMLAttributes & HTMLAttribut customStyles?: Record | string; showDownloadTemplateButton?: boolean; skipHeaderRowSelection?: boolean; + file?: File; } & ModalParams;