김재형

Implement file upload

import React, { useCallback } from "react";
import { Table, message, Button } from "antd";
import React, { useCallback, useState } from "react";
import { Table, message, Button, Popover } from "antd";
import { ColumnsType } from "antd/lib/table";
import filesize from "filesize";
......@@ -10,10 +10,12 @@ import { FileListItem } from "./FileListItem";
import { FileItemActions } from "./FileItemActions";
import styles from "./FileList.module.scss";
import { FileUploadPopover } from "./FileUploadPopover";
export function FileList() {
const id = useParams<{ id: string }>().id;
const { data, reload } = useFileList(id);
const [upload, setUpload] = useState<boolean>(false);
const api = useApi();
......@@ -103,9 +105,16 @@ export function FileList() {
<div className={styles.header}>
<div>{data.parent !== null && <h3>{data.name}</h3>}</div>
<div>
<Button type="link" size="small">
파일 업로드
</Button>
<Popover
content={<FileUploadPopover root={data.id} reload={reload} />}
trigger="click"
visible={upload}
onVisibleChange={setUpload}
>
<Button type="link" size="small">
파일 업로드
</Button>
</Popover>
<Button type="link" size="small">
새 폴더
</Button>
......
import React, { useCallback, useRef } from "react";
import Dragger from "antd/lib/upload/Dragger";
import { InboxOutlined } from "@ant-design/icons";
import { useApi } from "util/useApi";
export type FileUploadPopoverProps = {
root: number;
reload: () => void;
};
export function FileUploadPopover({ root, reload }: FileUploadPopoverProps) {
const api = useApi();
const fields = useRef<any>();
const stateMap = useRef<Record<string, number>>({});
const getS3Object = useCallback(
async (file: File) => {
const body = new URLSearchParams();
body.set("name", file.name);
body.set("size", file.size.toString());
const response = await api
.post(`/items/${root}/upload/`, { body })
.json<any>();
stateMap.current[file.name] = response.item.id;
fields.current = response.signed_url.fields;
return response.signed_url.url;
},
[api, root]
);
const setObjectStatus = useCallback(
async (info) => {
if (info.file.status === "done") {
const id = stateMap.current[info.file.name];
if (typeof id !== "undefined") {
const body = new URLSearchParams();
body.set("item_id", id.toString());
await api.post(`/items/${id}/status/`, { body });
reload();
}
}
},
[api, reload]
);
return (
<Dragger
name="file"
multiple={true}
action={getS3Object}
data={() => fields.current}
onChange={setObjectStatus}
style={{ padding: 40 }}
>
<p className="ant-upload-drag-icon">
<InboxOutlined />
</p>
<p className="ant-upload-text">
업로드할 파일을 선택하거나 드래그 하세요
</p>
<p className="ant-upload-hint"></p>
</Dragger>
);
}