Skip to content

Commit 233644f

Browse files
committed
fix #25: Import JSON file
1 parent bd725de commit 233644f

File tree

4 files changed

+158
-19
lines changed

4 files changed

+158
-19
lines changed

src/components/drop-zone.tsx

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
import { Upload } from "lucide-react";
2+
import { ReactNode, useState } from "react";
3+
4+
interface DropZoneProps {
5+
onDrop?: (file: File) => void;
6+
children: ReactNode;
7+
}
8+
9+
export const DropZone = ({ onDrop, children }: DropZoneProps) => {
10+
const [isDragging, setIsDragging] = useState(false);
11+
12+
const handleOnDrop = (e: React.DragEvent<HTMLDivElement>) => {
13+
e.preventDefault();
14+
setIsDragging(false);
15+
const file = e.dataTransfer.files[0];
16+
if (file) {
17+
onDrop?.(file);
18+
}
19+
};
20+
21+
return (
22+
<div
23+
onDrop={handleOnDrop}
24+
onDragOver={(e) => {
25+
setIsDragging(true);
26+
e.preventDefault();
27+
}}
28+
onDragEnter={() => setIsDragging(true)}
29+
onDragLeave={() => setIsDragging(false)}
30+
data-drag={isDragging ? "true" : "false"}
31+
className="relative"
32+
>
33+
{children}
34+
<div
35+
data-drag={isDragging ? "true" : "false"}
36+
className="
37+
invisible data-[drag=true]:visible opacity-0 data-[drag=true]:opacity-80
38+
absolute flex w-full h-full top-0 left-0 p-2 bg-white
39+
transition-opacity duration-200
40+
"
41+
>
42+
<div
43+
className="
44+
flex flex-col items-center justify-center gap-4
45+
w-full h-full
46+
border-2 border-dashed border-joe-green-600 rounded-lg text-lg
47+
"
48+
>
49+
<div>Drop JSON file here</div>
50+
<div>
51+
<Upload />
52+
</div>
53+
</div>
54+
</div>
55+
</div>
56+
);
57+
};

src/components/editor/json-editor.tsx

Lines changed: 31 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
findSmallestNode,
1010
generateNormalizedPathNode,
1111
} from "@/lib/normalized-path";
12+
import { DropZone } from "../drop-zone";
1213

1314
export const JSONEditor = () => {
1415
const { document, setDocument, jsonDocument } = useJSONPath();
@@ -63,25 +64,36 @@ export const JSONEditor = () => {
6364
setDocument(value || "");
6465
};
6566

67+
const handleOnDrop = (file: File) => {
68+
const reader = new FileReader();
69+
reader.onload = (event) => {
70+
const content = event.target?.result as string;
71+
setDocument(content);
72+
};
73+
reader.readAsText(file);
74+
};
75+
6676
return (
67-
<Editor
68-
className={cn("border-2", jsonDocument.error && "border-red-400")}
69-
height="600px"
70-
path="json"
71-
defaultLanguage="json"
72-
value={document}
73-
loading="Loading..."
74-
onMount={handleEditorDidMount}
75-
onChange={handleOnChange}
76-
options={{
77-
wordWrap: "on",
78-
minimap: {
79-
enabled: false,
80-
},
81-
scrollBeyondLastLine: false,
82-
formatOnPaste: true,
83-
formatOnType: true,
84-
}}
85-
/>
77+
<DropZone onDrop={handleOnDrop}>
78+
<Editor
79+
className={cn("border-2", jsonDocument.error && "border-red-400")}
80+
height="600px"
81+
path="json"
82+
defaultLanguage="json"
83+
value={document}
84+
loading="Loading..."
85+
onMount={handleEditorDidMount}
86+
onChange={handleOnChange}
87+
options={{
88+
wordWrap: "on",
89+
minimap: {
90+
enabled: false,
91+
},
92+
scrollBeyondLastLine: false,
93+
formatOnPaste: true,
94+
formatOnType: true,
95+
}}
96+
/>
97+
</DropZone>
8698
);
8799
};

src/components/import-file.tsx

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
import { useRef } from "react";
2+
import { Button } from "./ui/button";
3+
import { useJSONPath } from "@/hooks/use-jsonpath";
4+
5+
export const ImportFile = () => {
6+
const { setDocument } = useJSONPath();
7+
const inputRef = useRef<HTMLInputElement>(null);
8+
9+
const handleOnClick = () => {
10+
inputRef.current?.click();
11+
};
12+
13+
const handleOnInput = (event: React.ChangeEvent<HTMLInputElement>) => {
14+
const file = event.target.files?.[0];
15+
if (file) {
16+
const reader = new FileReader();
17+
reader.onload = (event) => {
18+
const content = event.target?.result as string;
19+
setDocument(content);
20+
};
21+
reader.readAsText(file);
22+
}
23+
};
24+
25+
return (
26+
<div>
27+
<Button variant="outline" onClick={handleOnClick}>
28+
Import File
29+
</Button>
30+
<input
31+
ref={inputRef}
32+
className="hidden"
33+
type="file"
34+
onInput={handleOnInput}
35+
accept="
36+
application/jsonjson,
37+
.jsonl,
38+
.ndjson,
39+
.geojson,
40+
.topojson,
41+
.jwt,
42+
.webmanifest,
43+
.har,
44+
.mcstructure,
45+
.eslintrc,
46+
.prettierrc,
47+
.babelrc,
48+
.code-snippets,
49+
.ipynb,
50+
.vg,
51+
.vl,
52+
.template,
53+
application/json,
54+
application/geo+json,
55+
application/x-ndjson,
56+
application/jsonlines,
57+
application/schema+json,
58+
application/jwt,
59+
application/feed+json,
60+
application/vnd.oai.openapi+json,
61+
application/vnd.swagger+json,
62+
application/manifest+json,
63+
application/x-ipynb+json,
64+
"
65+
></input>
66+
</div>
67+
);
68+
};

src/components/online-evaluator.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import { Result } from "./editor/result";
44
import { OutputPathSwitch } from "./output-path-switch";
55
import { useJSONPath } from "@/hooks/use-jsonpath";
66
import { DownloadButton } from "./download-button";
7+
import { ImportFile } from "./import-file";
78

89
export const JSONPathOnlineEvaluator = () => {
910
const { outputPaths, setOutputPaths } = useJSONPath();
@@ -16,6 +17,7 @@ export const JSONPathOnlineEvaluator = () => {
1617
<div>
1718
<div className="flex justify-between items-center mb-1">
1819
<h2 className="py-1 text-xl text-joe-green-950">Document</h2>
20+
<ImportFile />
1921
</div>
2022
<JSONEditor />
2123
</div>

0 commit comments

Comments
 (0)