Skip to content

Commit 92c469c

Browse files
committed
added fileupload changes
1 parent d667c94 commit 92c469c

4 files changed

Lines changed: 210 additions & 0 deletions

File tree

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,9 @@
8282
"@codemirror/legacy-modes": "^6.5.0",
8383
"@mavrin/remark-typograf": "^2.2.0",
8484
"@xyflow/react": "^12.6.0",
85+
"@uppy/core": "^2.1.4",
86+
"@uppy/react": "^2.1.2",
87+
"@uppy/xhr-upload": "^2.0.7",
8588
"classnames": "^2.5.1",
8689
"codemirror": "^6.0.1",
8790
"color": "^4.2.3",

src/extensions/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,4 @@
11
export * from "./codemirror/CodeMirror";
22
export * from "./react-flow";
3+
export * from "./uppy/FileUpload";
4+
export * from "@uppy/core";
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
import React from "react";
2+
import { Meta, StoryFn } from "@storybook/react";
3+
4+
import { FileUpload } from "./FileUpload";
5+
6+
export default {
7+
title: "Extensions/FileUpload",
8+
component: FileUpload
9+
} as Meta<typeof FileUpload>;
10+
11+
const TemplateFull: StoryFn<typeof FileUpload> = args =>
12+
<FileUpload {...args} />;
13+
14+
export const BasicExample = TemplateFull.bind({});
15+
BasicExample.args = {
16+
id: "fileupload",
17+
onError: null,
18+
onSuccess: null,
19+
handleResponseData: null,
20+
localeOptions: {
21+
strings: {
22+
dropHereOr: "Drop here or %{browse}",
23+
browse: "browse"
24+
}
25+
},
26+
resetForm: true,
27+
autoProceed: true,
28+
restrictions: {
29+
maxFileSize: 1000000,
30+
minNumberOfFiles: 1,
31+
maxNumberOfFiles: 5,
32+
allowedFileTypes: [".jpg", ".png"]
33+
}
34+
};

src/extensions/uppy/FileUpload.tsx

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
import React from "react";
2+
import Uppy, { Locale, Restrictions, UppyEventMap, UppyFile } from "@uppy/core";
3+
import { DragDrop, ProgressBar, useUppy } from "@uppy/react";
4+
import XHRUpload, { XHRUploadOptions } from "@uppy/xhr-upload";
5+
6+
import { TestableComponent } from "../../components/interfaces";
7+
8+
import "@uppy/core/dist/style.css";
9+
import "@uppy/drag-drop/dist/style.css";
10+
import "@uppy/progress-bar/dist/style.css";
11+
12+
type eventNames = keyof UppyEventMap;
13+
14+
export interface FileUploadProps extends TestableComponent {
15+
/**
16+
* upload instance id
17+
*/
18+
id?: string;
19+
/**
20+
* upload error callback function
21+
*/
22+
onError?: (responseText: string) => void;
23+
/**
24+
* upload success callback function
25+
*/
26+
onSuccess?: (responseText: string) => void;
27+
/**
28+
* upload response callback function
29+
*/
30+
handleResponseData?: (responseText: string) => void;
31+
/**
32+
* locale options, like button labels etc.
33+
*/
34+
localeOptions?: Locale;
35+
/**
36+
* reset form after upload or in case of error/navigation steps
37+
*/
38+
resetForm?: boolean;
39+
/**
40+
* auto proceed bolean
41+
*/
42+
autoProceed?: boolean;
43+
/**
44+
* upload restrictions
45+
*/
46+
restrictions?: Restrictions;
47+
/**
48+
* additional upload files
49+
*/
50+
additionalFiles?: {
51+
id: string;
52+
name: string;
53+
size: number;
54+
data: Blob;
55+
}[];
56+
/**
57+
* xhr upload options
58+
*/
59+
xhrUploadOptions: XHRUploadOptions;
60+
/**
61+
* uppy events to register and unregister to
62+
*/
63+
events?: { [key in eventNames]?: any };
64+
/**
65+
* set uppy instance
66+
*/
67+
setInstance?: (instance: Uppy) => void;
68+
}
69+
70+
export { ProgressBar as FileUploadProgressBar, DragDrop as FileUploadDragDrop} from "@uppy/react";
71+
export type {XHRUploadOptions} from "@uppy/xhr-upload"
72+
73+
74+
export const FileUpload: React.FC<FileUploadProps> = ({
75+
id,
76+
onError,
77+
onSuccess,
78+
handleResponseData,
79+
resetForm,
80+
autoProceed = false,
81+
restrictions,
82+
additionalFiles,
83+
xhrUploadOptions,
84+
localeOptions,
85+
events,
86+
setInstance,
87+
children,
88+
...rest
89+
}) => {
90+
const uppy = useUppy(() => {
91+
return new Uppy({
92+
id,
93+
autoProceed,
94+
restrictions,
95+
locale: localeOptions,
96+
})
97+
.on("upload-success", (_, response) => {
98+
onSuccess?.(response.body);
99+
})
100+
.use(XHRUpload, {
101+
...xhrUploadOptions,
102+
getResponseData: (responseText) => {
103+
handleResponseData?.(responseText);
104+
return responseText;
105+
},
106+
getResponseError: (responseText) => {
107+
uppy.reset();
108+
109+
onError?.(responseText);
110+
return new Error(responseText);
111+
},
112+
});
113+
});
114+
115+
//events
116+
React.useEffect(() => {
117+
uppy && setInstance && setInstance(uppy);
118+
const eventEntries = Object.entries(events ?? {}) as [keyof UppyEventMap, (file: UppyFile) => Promise<void>][];
119+
const unregisterEvents = () => {
120+
eventEntries.length && eventEntries.forEach(([event, handler]) => uppy.off(event, handler));
121+
};
122+
123+
unregisterEvents();
124+
125+
eventEntries.length &&
126+
eventEntries.forEach(([event, handler]) => {
127+
uppy.on(event, handler);
128+
});
129+
130+
return () => unregisterEvents();
131+
},[events, uppy]);
132+
133+
React.useEffect(() => {
134+
if (resetForm) {
135+
uppy.reset();
136+
}
137+
138+
return () => {
139+
uppy.close();
140+
};
141+
}, [resetForm, uppy]);
142+
143+
React.useEffect(() => {
144+
if (additionalFiles) {
145+
additionalFiles.forEach((file) => {
146+
uppy.addFile({
147+
name: file.name,
148+
data: file.data,
149+
size: file.size,
150+
id: file.id,
151+
});
152+
});
153+
}
154+
}, [additionalFiles, uppy]);
155+
156+
if (!uppy) return null;
157+
158+
159+
return (
160+
<div {...rest}>
161+
{children ? (
162+
children
163+
) : (
164+
<>
165+
<DragDrop uppy={uppy} />
166+
<ProgressBar uppy={uppy} />
167+
</>
168+
)}
169+
</div>
170+
);
171+
};

0 commit comments

Comments
 (0)