Skip to content

Commit d78691f

Browse files
committed
Add onHeadersMapped fn
From: tableflowhq#230
1 parent 0b03fe7 commit d78691f

File tree

6 files changed

+13857
-19532
lines changed

6 files changed

+13857
-19532
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,13 @@ Example `data`:
224224
}
225225
```
226226
227+
### onHeadersMapped (_function_)
228+
Callback function that fires when headers have been mapped (when you dont want to wait for onComplete and you just want the mapped headers and the original uploaded file). It returns `selectedHeaderRow` which tells which row was selected as a header row in the previous step, `mappedHeaders` an object that contains the mapping definitions and `originalFile` which is the `File` object representing the original uploaded file without any modifications to it.
229+
When `onHeadersMapped` is defined, `onComplete` callback will not be fired.
230+
```jsx
231+
onHeadersMapped={(selectedHeaderRow, mappedHeaders, originalFile) => console.log(mappedHeaders)}
232+
```
233+
227234
### darkMode (_boolean_, default: `false`)
228235
229236
Toggle between dark mode (`true`) and light mode (`false`).

src/components/CSVImporter/CSVImporter.stories.tsx

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ const Template: Story<typeof ImporterComponent> = (args: CSVImporterProps) => {
5050
...args,
5151
};
5252

53+
console.log(props);
54+
5355
return (
5456
<div>
5557
{args.isModal && <button onClick={() => setIsOpen(true)}>Import</button>}
@@ -74,3 +76,14 @@ Importer.args = {
7476
},
7577
},
7678
};
79+
80+
const onHeadersMapped: CSVImporterProps['onHeadersMapped'] = async (selectedHeaderRow, mappedHeaders, originalFile) => {
81+
console.log("onHeadersMapped:", selectedHeaderRow, mappedHeaders, originalFile);
82+
return;
83+
};
84+
85+
export const ImporterWithHeadersMapped = Template.bind({});
86+
ImporterWithHeadersMapped.args = {
87+
...Importer.args,
88+
onHeadersMapped,
89+
};

src/components/CSVImporter/index.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ const CSVImporter = forwardRef((importerProps: CSVImporterProps, forwardRef?: an
2020
primaryColor = "#7a5ef8",
2121
className,
2222
onComplete,
23+
onHeadersMapped,
2324
customStyles,
2425
showDownloadTemplateButton,
2526
skipHeaderRowSelection,

src/importer/features/main/index.tsx

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ export default function Main(props: CSVImporterProps) {
2626
modalOnCloseTriggered = () => null,
2727
template,
2828
onComplete,
29+
onHeadersMapped,
2930
customStyles,
3031
showDownloadTemplateButton,
3132
skipHeaderRowSelection,
@@ -43,6 +44,7 @@ export default function Main(props: CSVImporterProps) {
4344
// Error handling
4445
const [initializationError, setInitializationError] = useState<string | null>(null);
4546
const [dataError, setDataError] = useState<string | null>(null);
47+
const [originalFile, setOriginalFile] = useState<File | null>(null);
4648

4749
// File data
4850
const emptyData = {
@@ -90,6 +92,7 @@ export default function Main(props: CSVImporterProps) {
9092
setColumnMapping({});
9193
setDataError(null);
9294
setStep(StepEnum.Upload);
95+
setOriginalFile(null);
9396
};
9497

9598
const requestClose = () => {
@@ -121,6 +124,7 @@ export default function Main(props: CSVImporterProps) {
121124
setDataError={setDataError}
122125
onSuccess={async (file: File) => {
123126
setDataError(null);
127+
setOriginalFile(file);
124128
const fileType = file.name.slice(file.name.lastIndexOf(".") + 1);
125129
if (!["csv", "xls", "xlsx"].includes(fileType)) {
126130
setDataError(t("Only CSV, XLS, and XLSX files can be uploaded"));
@@ -199,7 +203,18 @@ export default function Main(props: CSVImporterProps) {
199203
onSuccess={(columnMapping) => {
200204
setIsSubmitting(true);
201205
setColumnMapping(columnMapping);
202-
206+
if (onHeadersMapped) {
207+
onHeadersMapped(selectedHeaderRow, columnMapping, originalFile)
208+
.then(() => {
209+
setIsSubmitting(false);
210+
goNext();
211+
})
212+
.catch((error) => {
213+
console.error("onHeadersMapped error", error);
214+
setDataError("An error occurred while processing the data");
215+
});
216+
return;
217+
}
203218
// TODO (client-sdk): Move this type, add other data attributes (i.e. column definitions), and move the data processing to a function
204219
type MappedRow = {
205220
index: number;

src/types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Resource } from "i18next";
22
import { HTMLAttributes } from "react";
3+
import { TemplateColumnMapping } from "../importer/features/map-columns/types";
34

45
type ModalParams = {
56
isModal?: boolean;
@@ -14,6 +15,7 @@ export type CSVImporterProps = (HTMLAttributes<HTMLDialogElement> & HTMLAttribut
1415
primaryColor?: string;
1516
className?: string;
1617
onComplete?: (data: any) => void;
18+
onHeadersMapped?: (selectedHeaderRow: number | null, mappedHeaders: { [index: number]: TemplateColumnMapping }, originalFile: File | null) => Promise<void>;
1719
waitOnComplete?: boolean;
1820
customStyles?: Record<string, string> | string;
1921
showDownloadTemplateButton?: boolean;

0 commit comments

Comments
 (0)