Showing
2 changed files
with
77 additions
and
2 deletions
1 | -import React, { useCallback } from "react"; | 1 | +import React, { useCallback, useState } from "react"; |
2 | -import { Table, message, Button } from "antd"; | 2 | +import { Table, message, Button, Popover } from "antd"; |
3 | import { ColumnsType } from "antd/lib/table"; | 3 | import { ColumnsType } from "antd/lib/table"; |
4 | import filesize from "filesize"; | 4 | import filesize from "filesize"; |
5 | 5 | ||
... | @@ -10,10 +10,12 @@ import { FileListItem } from "./FileListItem"; | ... | @@ -10,10 +10,12 @@ import { FileListItem } from "./FileListItem"; |
10 | import { FileItemActions } from "./FileItemActions"; | 10 | import { FileItemActions } from "./FileItemActions"; |
11 | 11 | ||
12 | import styles from "./FileList.module.scss"; | 12 | import styles from "./FileList.module.scss"; |
13 | +import { FileUploadPopover } from "./FileUploadPopover"; | ||
13 | 14 | ||
14 | export function FileList() { | 15 | export function FileList() { |
15 | const id = useParams<{ id: string }>().id; | 16 | const id = useParams<{ id: string }>().id; |
16 | const { data, reload } = useFileList(id); | 17 | const { data, reload } = useFileList(id); |
18 | + const [upload, setUpload] = useState<boolean>(false); | ||
17 | 19 | ||
18 | const api = useApi(); | 20 | const api = useApi(); |
19 | 21 | ||
... | @@ -103,9 +105,16 @@ export function FileList() { | ... | @@ -103,9 +105,16 @@ export function FileList() { |
103 | <div className={styles.header}> | 105 | <div className={styles.header}> |
104 | <div>{data.parent !== null && <h3>{data.name}</h3>}</div> | 106 | <div>{data.parent !== null && <h3>{data.name}</h3>}</div> |
105 | <div> | 107 | <div> |
108 | + <Popover | ||
109 | + content={<FileUploadPopover root={data.id} reload={reload} />} | ||
110 | + trigger="click" | ||
111 | + visible={upload} | ||
112 | + onVisibleChange={setUpload} | ||
113 | + > | ||
106 | <Button type="link" size="small"> | 114 | <Button type="link" size="small"> |
107 | 파일 업로드 | 115 | 파일 업로드 |
108 | </Button> | 116 | </Button> |
117 | + </Popover> | ||
109 | <Button type="link" size="small"> | 118 | <Button type="link" size="small"> |
110 | 새 폴더 | 119 | 새 폴더 |
111 | </Button> | 120 | </Button> | ... | ... |
frontend/src/file/FileUploadPopover.tsx
0 → 100644
1 | +import React, { useCallback, useRef } from "react"; | ||
2 | +import Dragger from "antd/lib/upload/Dragger"; | ||
3 | +import { InboxOutlined } from "@ant-design/icons"; | ||
4 | +import { useApi } from "util/useApi"; | ||
5 | + | ||
6 | +export type FileUploadPopoverProps = { | ||
7 | + root: number; | ||
8 | + reload: () => void; | ||
9 | +}; | ||
10 | + | ||
11 | +export function FileUploadPopover({ root, reload }: FileUploadPopoverProps) { | ||
12 | + const api = useApi(); | ||
13 | + const fields = useRef<any>(); | ||
14 | + const stateMap = useRef<Record<string, number>>({}); | ||
15 | + | ||
16 | + const getS3Object = useCallback( | ||
17 | + async (file: File) => { | ||
18 | + const body = new URLSearchParams(); | ||
19 | + body.set("name", file.name); | ||
20 | + body.set("size", file.size.toString()); | ||
21 | + | ||
22 | + const response = await api | ||
23 | + .post(`/items/${root}/upload/`, { body }) | ||
24 | + .json<any>(); | ||
25 | + | ||
26 | + stateMap.current[file.name] = response.item.id; | ||
27 | + fields.current = response.signed_url.fields; | ||
28 | + return response.signed_url.url; | ||
29 | + }, | ||
30 | + [api, root] | ||
31 | + ); | ||
32 | + | ||
33 | + const setObjectStatus = useCallback( | ||
34 | + async (info) => { | ||
35 | + if (info.file.status === "done") { | ||
36 | + const id = stateMap.current[info.file.name]; | ||
37 | + if (typeof id !== "undefined") { | ||
38 | + const body = new URLSearchParams(); | ||
39 | + body.set("item_id", id.toString()); | ||
40 | + await api.post(`/items/${id}/status/`, { body }); | ||
41 | + reload(); | ||
42 | + } | ||
43 | + } | ||
44 | + }, | ||
45 | + [api, reload] | ||
46 | + ); | ||
47 | + | ||
48 | + return ( | ||
49 | + <Dragger | ||
50 | + name="file" | ||
51 | + multiple={true} | ||
52 | + action={getS3Object} | ||
53 | + data={() => fields.current} | ||
54 | + onChange={setObjectStatus} | ||
55 | + style={{ padding: 40 }} | ||
56 | + > | ||
57 | + <p className="ant-upload-drag-icon"> | ||
58 | + <InboxOutlined /> | ||
59 | + </p> | ||
60 | + <p className="ant-upload-text"> | ||
61 | + 업로드할 파일을 선택하거나 드래그 하세요 | ||
62 | + </p> | ||
63 | + <p className="ant-upload-hint"></p> | ||
64 | + </Dragger> | ||
65 | + ); | ||
66 | +} |
-
Please register or login to post a comment