김재형

Implement file copy

...@@ -7,15 +7,18 @@ import { FileListPopover } from "./FileListPopover"; ...@@ -7,15 +7,18 @@ import { FileListPopover } from "./FileListPopover";
7 export type FileItemActionsProps = { 7 export type FileItemActionsProps = {
8 item: FileItem; 8 item: FileItem;
9 onMove: (id: number, to: number) => void; 9 onMove: (id: number, to: number) => void;
10 + onCopy: (id: number, to: number) => void;
10 onDelete: (id: number) => void; 11 onDelete: (id: number) => void;
11 }; 12 };
12 13
13 export function FileItemActions({ 14 export function FileItemActions({
14 item, 15 item,
15 onMove, 16 onMove,
17 + onCopy,
16 onDelete, 18 onDelete,
17 }: FileItemActionsProps) { 19 }: FileItemActionsProps) {
18 const [move, setMove] = useState<boolean>(false); 20 const [move, setMove] = useState<boolean>(false);
21 + const [copy, setCopy] = useState<boolean>(false);
19 22
20 return ( 23 return (
21 <div className={styles.actions}> 24 <div className={styles.actions}>
...@@ -48,9 +51,26 @@ export function FileItemActions({ ...@@ -48,9 +51,26 @@ export function FileItemActions({
48 이동 51 이동
49 </Button> 52 </Button>
50 </Popover> 53 </Popover>
51 - <Button type="link" size="small"> 54 + <Popover
52 - 복사 55 + title="복사할 폴더를 선택하세요"
53 - </Button> 56 + content={
57 + <FileListPopover
58 + root={item.parent}
59 + onSelect={(to: number) => {
60 + onCopy(item.id, to);
61 + setCopy(false);
62 + }}
63 + onCancel={() => setCopy(false)}
64 + />
65 + }
66 + trigger="click"
67 + visible={copy}
68 + onVisibleChange={setCopy}
69 + >
70 + <Button type="link" size="small">
71 + 복사
72 + </Button>
73 + </Popover>
54 <Popconfirm 74 <Popconfirm
55 title="정말로 삭제하시겠습니까?" 75 title="정말로 삭제하시겠습니까?"
56 onConfirm={() => onDelete(item.id)} 76 onConfirm={() => onDelete(item.id)}
......
...@@ -34,6 +34,23 @@ export function FileList() { ...@@ -34,6 +34,23 @@ export function FileList() {
34 [api, reload] 34 [api, reload]
35 ); 35 );
36 36
37 + const handleCopy = useCallback(
38 + async (id: number, to: number) => {
39 + try {
40 + const body = new URLSearchParams();
41 + body.set("parent", to.toString(10));
42 +
43 + await api.post(`/items/${id}/copy/`, { body });
44 + await reload();
45 +
46 + message.info("복사되었습니다");
47 + } catch {
48 + message.error("파일 복사에 실패했습니다");
49 + }
50 + },
51 + [api, reload]
52 + );
53 +
37 const handleDelete = useCallback( 54 const handleDelete = useCallback(
38 async (id: number) => { 55 async (id: number) => {
39 try { 56 try {
...@@ -81,6 +98,7 @@ export function FileList() { ...@@ -81,6 +98,7 @@ export function FileList() {
81 rowKey="id" 98 rowKey="id"
82 columns={getColumns({ 99 columns={getColumns({
83 handleMove, 100 handleMove,
101 + handleCopy,
84 handleDelete, 102 handleDelete,
85 })} 103 })}
86 dataSource={list} 104 dataSource={list}
...@@ -92,11 +110,13 @@ export function FileList() { ...@@ -92,11 +110,13 @@ export function FileList() {
92 110
93 type GetColumnsParams = { 111 type GetColumnsParams = {
94 handleMove: (id: number, to: number) => void; 112 handleMove: (id: number, to: number) => void;
113 + handleCopy: (id: number, to: number) => void;
95 handleDelete: (id: number) => void; 114 handleDelete: (id: number) => void;
96 }; 115 };
97 116
98 function getColumns({ 117 function getColumns({
99 handleMove, 118 handleMove,
119 + handleCopy,
100 handleDelete, 120 handleDelete,
101 }: GetColumnsParams): ColumnsType<FileItem> { 121 }: GetColumnsParams): ColumnsType<FileItem> {
102 return [ 122 return [
...@@ -124,6 +144,7 @@ function getColumns({ ...@@ -124,6 +144,7 @@ function getColumns({
124 <FileItemActions 144 <FileItemActions
125 item={item} 145 item={item}
126 onMove={handleMove} 146 onMove={handleMove}
147 + onCopy={handleCopy}
127 onDelete={handleDelete} 148 onDelete={handleDelete}
128 /> 149 />
129 ), 150 ),
......