Skip to content
This repository was archived by the owner on Jan 5, 2024. It is now read-only.

Commit 26684b4

Browse files
committed
Eliminate legacy parser input type
1 parent e2e1414 commit 26684b4

File tree

5 files changed

+79
-76
lines changed

5 files changed

+79
-76
lines changed

src/components/Importer.tsx

+22-21
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import React, { useMemo, useState, useEffect, useContext } from 'react';
22

3-
import { FieldAssignmentMap, BaseRow, Preview } from '../parser';
4-
import { FileStep } from './file-step/FileStep';
3+
import { FieldAssignmentMap, BaseRow } from '../parser';
4+
import { FileStep, FileStepState } from './file-step/FileStep';
55
import { generatePreviewColumns } from './fields-step/ColumnPreview';
66
import { FieldsStep, Field } from './fields-step/FieldsStep';
77
import { ProgressDisplay } from './ProgressDisplay';
@@ -88,8 +88,8 @@ export function Importer<Row extends BaseRow>({
8888
// helper to combine our displayed content and the user code that provides field definitions
8989
const [fields, setFields] = useState<FieldDef[]>([]);
9090

91-
const [preview, setPreview] = useState<Preview | null>(null);
92-
const [formatAccepted, setFormatAccepted] = useState<boolean>(false);
91+
const [fileState, setFileState] = useState<FileStepState | null>(null);
92+
const [fileAccepted, setFileAccepted] = useState<boolean>(false);
9393

9494
const [
9595
fieldAssignments,
@@ -99,45 +99,46 @@ export function Importer<Row extends BaseRow>({
9999
const externalPreview = useMemo<ImporterFilePreview | null>(() => {
100100
// generate stable externally-visible data objects
101101
const externalColumns =
102-
preview && generatePreviewColumns(preview.firstRows, preview.hasHeaders);
102+
fileState &&
103+
generatePreviewColumns(fileState.firstRows, fileState.hasHeaders);
103104
return (
104-
preview &&
105+
fileState &&
105106
externalColumns && {
106-
rawData: preview.firstChunk,
107+
rawData: fileState.firstChunk,
107108
columns: externalColumns,
108-
skipHeaders: !preview.hasHeaders,
109-
parseWarning: preview.parseWarning
109+
skipHeaders: !fileState.hasHeaders,
110+
parseWarning: fileState.parseWarning
110111
}
111112
);
112-
}, [preview]);
113+
}, [fileState]);
113114

114115
// render provided child content that defines the fields
115116
const contentNodes = useMemo(() => {
116117
return typeof content === 'function'
117118
? content({
118-
file: preview && preview.file,
119+
file: fileState && fileState.file,
119120
preview: externalPreview
120121
})
121122
: content;
122-
}, [preview, externalPreview, content]);
123+
}, [fileState, externalPreview, content]);
123124
const contentWrap = (
124125
<FieldDefinitionContext.Provider value={setFields}>
125126
{contentNodes}
126127
</FieldDefinitionContext.Provider>
127128
);
128129

129-
if (!formatAccepted || preview === null || externalPreview === null) {
130+
if (!fileAccepted || fileState === null || externalPreview === null) {
130131
return (
131132
<div className="CSVImporter_Importer">
132133
<FileStep
133134
customConfig={customPapaParseConfig}
134135
assumeNoHeaders={assumeNoHeaders}
135-
currentPreview={preview}
136+
prevState={fileState}
136137
onChange={(parsedPreview) => {
137-
setPreview(parsedPreview);
138+
setFileState(parsedPreview);
138139
}}
139140
onAccept={() => {
140-
setFormatAccepted(true);
141+
setFileAccepted(true);
141142
}}
142143
/>
143144

@@ -150,15 +151,15 @@ export function Importer<Row extends BaseRow>({
150151
return (
151152
<div className="CSVImporter_Importer">
152153
<FieldsStep
154+
fileState={fileState}
153155
fields={fields}
154-
preview={preview}
155156
onAccept={(assignments) => {
156157
// @todo use onChange to preserve this state if going back and toggling hasHeaders
157158
setFieldAssignments(assignments);
158159
}}
159160
onCancel={() => {
160161
// keep existing preview data
161-
setFormatAccepted(false);
162+
setFileAccepted(false);
162163
}}
163164
/>
164165

@@ -170,7 +171,7 @@ export function Importer<Row extends BaseRow>({
170171
return (
171172
<div className="CSVImporter_Importer">
172173
<ProgressDisplay
173-
preview={preview}
174+
fileState={fileState}
174175
externalPreview={externalPreview}
175176
fieldAssignments={fieldAssignments}
176177
processChunk={processChunk}
@@ -179,8 +180,8 @@ export function Importer<Row extends BaseRow>({
179180
restartable
180181
? () => {
181182
// reset all state
182-
setPreview(null);
183-
setFormatAccepted(false);
183+
setFileState(null);
184+
setFileAccepted(false);
184185
setFieldAssignments(null);
185186
}
186187
: undefined

src/components/ProgressDisplay.tsx

+21-19
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import {
44
processFile,
55
FieldAssignmentMap,
66
ParseCallback,
7-
BaseRow,
8-
Preview
7+
BaseRow
98
} from '../parser';
9+
import { FileStepState } from './file-step/FileStep';
1010
import { ImporterFilePreview, ImportInfo } from './ImporterProps';
1111
import { ImporterFrame } from './ImporterFrame';
1212

@@ -25,7 +25,7 @@ function countUTF8Bytes(item: string) {
2525
}
2626

2727
export function ProgressDisplay<Row extends BaseRow>({
28-
preview,
28+
fileState,
2929
externalPreview,
3030
fieldAssignments,
3131
processChunk,
@@ -34,7 +34,7 @@ export function ProgressDisplay<Row extends BaseRow>({
3434
onRestart,
3535
onClose
3636
}: React.PropsWithChildren<{
37-
preview: Preview;
37+
fileState: FileStepState;
3838
externalPreview: ImporterFilePreview;
3939
fieldAssignments: FieldAssignmentMap;
4040
processChunk: ParseCallback<Row>;
@@ -61,32 +61,35 @@ export function ProgressDisplay<Row extends BaseRow>({
6161
});
6262

6363
return {
64-
file: preview.file,
64+
file: fileState.file,
6565
preview: externalPreview,
6666
fields: fieldList,
6767
columnFields: [...columnSparseList]
6868
};
69-
}, [preview, externalPreview, fieldAssignments]);
69+
}, [fileState, externalPreview, fieldAssignments]);
7070

7171
// estimate number of rows
7272
const estimatedRowCount = useMemo(() => {
7373
// sum up sizes of all the parsed preview rows and get estimated average
74-
const totalPreviewRowBytes = preview.firstRows.reduce((prevCount, row) => {
75-
const rowBytes = row.reduce((prev, item) => {
76-
return prev + countUTF8Bytes(item) + 1; // add a byte for separator or newline
77-
}, 0);
74+
const totalPreviewRowBytes = fileState.firstRows.reduce(
75+
(prevCount, row) => {
76+
const rowBytes = row.reduce((prev, item) => {
77+
return prev + countUTF8Bytes(item) + 1; // add a byte for separator or newline
78+
}, 0);
7879

79-
return prevCount + rowBytes;
80-
}, 0);
80+
return prevCount + rowBytes;
81+
},
82+
0
83+
);
8184

8285
const averagePreviewRowSize =
83-
totalPreviewRowBytes / preview.firstRows.length;
86+
totalPreviewRowBytes / fileState.firstRows.length;
8487

8588
// divide file size by estimated row size (or fall back to a sensible amount)
8689
return averagePreviewRowSize > 1
87-
? preview.file.size / averagePreviewRowSize
90+
? fileState.file.size / averagePreviewRowSize
8891
: 100;
89-
}, [preview]);
92+
}, [fileState]);
9093

9194
// notify on start of processing
9295
// (separate effect in case of errors)
@@ -122,8 +125,7 @@ export function ProgressDisplay<Row extends BaseRow>({
122125
const oplock = asyncLockRef.current;
123126

124127
processFile(
125-
preview,
126-
fieldAssignments,
128+
{ ...fileState, fieldAssignments },
127129
(deltaCount) => {
128130
// ignore if stale
129131
if (oplock !== asyncLockRef.current) {
@@ -156,7 +158,7 @@ export function ProgressDisplay<Row extends BaseRow>({
156158
// invalidate current oplock on change or unmount
157159
asyncLockRef.current += 1;
158160
};
159-
}, [preview, fieldAssignments]);
161+
}, [fileState, fieldAssignments]);
160162

161163
// simulate asymptotic progress percentage
162164
const progressPercentage = useMemo(() => {
@@ -174,7 +176,7 @@ export function ProgressDisplay<Row extends BaseRow>({
174176

175177
return (
176178
<ImporterFrame
177-
fileName={preview.file.name}
179+
fileName={fileState.file.name}
178180
subtitle="Import"
179181
error={error && (error.message || String(error))}
180182
secondaryDisabled={!isComplete || isDismissed}

src/components/fields-step/FieldsStep.tsx

+9-8
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import React, { useState, useMemo } from 'react';
22

3-
import { FieldAssignmentMap, Preview } from '../../parser';
3+
import { FieldAssignmentMap } from '../../parser';
4+
import { FileStepState } from '../file-step/FileStep';
45
import { ImporterFrame } from '../ImporterFrame';
56
import {
67
generatePreviewColumns,
@@ -16,18 +17,18 @@ import { ColumnDragTargetArea, FieldTouchedMap } from './ColumnDragTargetArea';
1617
export type Field = DragField;
1718

1819
export const FieldsStep: React.FC<{
20+
fileState: FileStepState;
1921
fields: Field[];
20-
preview: Preview;
2122
onAccept: (fieldAssignments: FieldAssignmentMap) => void;
2223
onCancel: () => void;
23-
}> = ({ fields, preview, onAccept, onCancel }) => {
24+
}> = ({ fileState, fields, onAccept, onCancel }) => {
2425
const columns = useMemo<Column[]>(
2526
() =>
2627
generatePreviewColumns(
27-
preview.firstRows,
28-
preview.hasHeaders
28+
fileState.firstRows,
29+
fileState.hasHeaders
2930
).map((item) => ({ ...item, code: generateColumnCode(item.index) })),
30-
[preview]
31+
[fileState]
3132
);
3233

3334
const initialAssignments = useMemo<FieldAssignmentMap>(() => {
@@ -102,7 +103,7 @@ export const FieldsStep: React.FC<{
102103

103104
return (
104105
<ImporterFrame
105-
fileName={preview.file.name}
106+
fileName={fileState.file.name}
106107
subtitle="Select Columns"
107108
error={validationError}
108109
onCancel={onCancel}
@@ -137,7 +138,7 @@ export const FieldsStep: React.FC<{
137138
/>
138139

139140
<ColumnDragTargetArea
140-
hasHeaders={preview.hasHeaders}
141+
hasHeaders={fileState.hasHeaders}
141142
fields={fields}
142143
columns={columns}
143144
fieldTouched={fieldTouched}

src/components/file-step/FileStep.tsx

+18-19
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ import React, { useMemo, useRef, useEffect, useState } from 'react';
33
import {
44
parsePreview,
55
PreviewResults,
6-
Preview,
6+
PreviewReport,
77
CustomizablePapaParseConfig
88
} from '../../parser';
99
import { ImporterFrame } from '../ImporterFrame';
@@ -14,38 +14,37 @@ import { FormatErrorMessage } from './FormatErrorMessage';
1414

1515
import './FileStep.scss';
1616

17+
export interface FileStepState extends PreviewReport {
18+
papaParseConfig: CustomizablePapaParseConfig; // config that was used for preview parsing
19+
hasHeaders: boolean;
20+
}
21+
1722
export const FileStep: React.FC<{
1823
customConfig: CustomizablePapaParseConfig;
1924
assumeNoHeaders?: boolean;
20-
currentPreview: Preview | null;
21-
onChange: (preview: Preview | null) => void;
25+
prevState: FileStepState | null;
26+
onChange: (state: FileStepState | null) => void;
2227
onAccept: () => void;
23-
}> = ({
24-
customConfig,
25-
assumeNoHeaders,
26-
currentPreview,
27-
onChange,
28-
onAccept
29-
}) => {
30-
const [selectedFile, setSelectedFile] = useState<File | null>(() =>
31-
currentPreview ? currentPreview.file : null
28+
}> = ({ customConfig, assumeNoHeaders, prevState, onChange, onAccept }) => {
29+
// seed from previous state as needed
30+
const [selectedFile, setSelectedFile] = useState<File | null>(
31+
prevState ? prevState.file : null
3232
);
3333

34-
// augmented PreviewResults from parser
3534
const [preview, setPreview] = useState<PreviewResults | null>(
3635
() =>
37-
currentPreview && {
36+
prevState && {
3837
parseError: undefined,
39-
...currentPreview
38+
...prevState
4039
}
4140
);
4241

43-
const [papaParseConfig, setPapaParseConfig] = useState(() =>
44-
currentPreview ? currentPreview.papaParseConfig : customConfig
42+
const [papaParseConfig, setPapaParseConfig] = useState(
43+
prevState ? prevState.papaParseConfig : customConfig
4544
);
4645

47-
const [hasHeaders, setHasHeaders] = useState(() =>
48-
currentPreview ? currentPreview.hasHeaders : false
46+
const [hasHeaders, setHasHeaders] = useState(
47+
prevState ? prevState.hasHeaders : false
4948
);
5049

5150
// wrap in ref to avoid triggering effect

src/parser.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,6 @@ export type PreviewResults =
3232
parseError: undefined;
3333
} & PreviewReport);
3434

35-
// complete "workspace" for kicking off the full parse @todo rename
36-
export interface Preview extends PreviewReport {
37-
papaParseConfig: CustomizablePapaParseConfig; // config that was used for preview parsing
38-
hasHeaders: boolean;
39-
}
40-
4135
export const PREVIEW_ROW_COUNT = 5;
4236

4337
export type FieldAssignmentMap = { [name: string]: number | undefined };
@@ -151,13 +145,19 @@ export function parsePreview(
151145
});
152146
}
153147

148+
export interface ParserInput {
149+
file: File;
150+
papaParseConfig: CustomizablePapaParseConfig;
151+
hasHeaders: boolean;
152+
fieldAssignments: FieldAssignmentMap;
153+
}
154+
154155
export function processFile<Row extends BaseRow>(
155-
preview: Preview,
156-
fieldAssignments: FieldAssignmentMap,
156+
input: ParserInput,
157157
reportProgress: (deltaCount: number) => void,
158158
callback: ParseCallback<Row>
159159
): Promise<void> {
160-
const { file, hasHeaders, papaParseConfig } = preview;
160+
const { file, hasHeaders, papaParseConfig, fieldAssignments } = input;
161161
const fieldNames = Object.keys(fieldAssignments);
162162

163163
// wrap synchronous errors in promise

0 commit comments

Comments
 (0)