Showing
3 changed files
with
83 additions
and
1 deletions
... | @@ -3,9 +3,11 @@ import { Popconfirm, Popover, Button, message } from "antd"; | ... | @@ -3,9 +3,11 @@ import { Popconfirm, Popover, Button, message } from "antd"; |
3 | import { FileItem } from "./useFileList"; | 3 | import { FileItem } from "./useFileList"; |
4 | import styles from "./FileItemActions.module.scss"; | 4 | import styles from "./FileItemActions.module.scss"; |
5 | import { FileListPopover } from "./FileListPopover"; | 5 | import { FileListPopover } from "./FileListPopover"; |
6 | +import { FileRenamePopover } from "./FileRenamePopover"; | ||
6 | 7 | ||
7 | export type FileItemActionsProps = { | 8 | export type FileItemActionsProps = { |
8 | item: FileItem; | 9 | item: FileItem; |
10 | + onRename: (id: number, name: string) => void; | ||
9 | onMove: (id: number, to: number) => void; | 11 | onMove: (id: number, to: number) => void; |
10 | onCopy: (id: number, to: number) => void; | 12 | onCopy: (id: number, to: number) => void; |
11 | onDelete: (id: number) => void; | 13 | onDelete: (id: number) => void; |
... | @@ -13,18 +15,43 @@ export type FileItemActionsProps = { | ... | @@ -13,18 +15,43 @@ export type FileItemActionsProps = { |
13 | 15 | ||
14 | export function FileItemActions({ | 16 | export function FileItemActions({ |
15 | item, | 17 | item, |
18 | + onRename, | ||
16 | onMove, | 19 | onMove, |
17 | onCopy, | 20 | onCopy, |
18 | onDelete, | 21 | onDelete, |
19 | }: FileItemActionsProps) { | 22 | }: FileItemActionsProps) { |
23 | + const [rename, setRename] = useState<boolean>(false); | ||
20 | const [move, setMove] = useState<boolean>(false); | 24 | const [move, setMove] = useState<boolean>(false); |
21 | const [copy, setCopy] = useState<boolean>(false); | 25 | const [copy, setCopy] = useState<boolean>(false); |
22 | 26 | ||
23 | return ( | 27 | return ( |
24 | <div className={styles.actions}> | 28 | <div className={styles.actions}> |
29 | + <Popover | ||
30 | + title="변경할 이름을 입력하세요" | ||
31 | + content={ | ||
32 | + <FileRenamePopover | ||
33 | + name={item.name} | ||
34 | + onRename={(name: string) => { | ||
35 | + if (name === item.name) { | ||
36 | + return message.error("동일한 이름으로는 변경할 수 없습니다"); | ||
37 | + } | ||
38 | + if (!name) { | ||
39 | + return message.error("변경할 이름을 입력하세요"); | ||
40 | + } | ||
41 | + onRename(item.id, name); | ||
42 | + setRename(false); | ||
43 | + }} | ||
44 | + onCancel={() => setRename(false)} | ||
45 | + /> | ||
46 | + } | ||
47 | + trigger="click" | ||
48 | + visible={rename} | ||
49 | + onVisibleChange={setRename} | ||
50 | + > | ||
25 | <Button type="link" size="small"> | 51 | <Button type="link" size="small"> |
26 | 이름 변경 | 52 | 이름 변경 |
27 | </Button> | 53 | </Button> |
54 | + </Popover> | ||
28 | <Button type="link" size="small"> | 55 | <Button type="link" size="small"> |
29 | 공유 | 56 | 공유 |
30 | </Button> | 57 | </Button> | ... | ... |
... | @@ -17,6 +17,23 @@ export function FileList() { | ... | @@ -17,6 +17,23 @@ export function FileList() { |
17 | 17 | ||
18 | const api = useApi(); | 18 | const api = useApi(); |
19 | 19 | ||
20 | + const handleRename = useCallback( | ||
21 | + async (id: number, name: string) => { | ||
22 | + try { | ||
23 | + const body = new URLSearchParams(); | ||
24 | + body.set("name", name); | ||
25 | + | ||
26 | + await api.post(`/items/${id}/move/`, { body }); | ||
27 | + await reload(); | ||
28 | + | ||
29 | + message.info("이름이 변경되었습니다"); | ||
30 | + } catch { | ||
31 | + message.error("이름 변경에 실패했습니다"); | ||
32 | + } | ||
33 | + }, | ||
34 | + [api, reload] | ||
35 | + ); | ||
36 | + | ||
20 | const handleMove = useCallback( | 37 | const handleMove = useCallback( |
21 | async (id: number, to: number) => { | 38 | async (id: number, to: number) => { |
22 | try { | 39 | try { |
... | @@ -97,6 +114,7 @@ export function FileList() { | ... | @@ -97,6 +114,7 @@ export function FileList() { |
97 | <Table | 114 | <Table |
98 | rowKey="id" | 115 | rowKey="id" |
99 | columns={getColumns({ | 116 | columns={getColumns({ |
117 | + handleRename, | ||
100 | handleMove, | 118 | handleMove, |
101 | handleCopy, | 119 | handleCopy, |
102 | handleDelete, | 120 | handleDelete, |
... | @@ -109,19 +127,21 @@ export function FileList() { | ... | @@ -109,19 +127,21 @@ export function FileList() { |
109 | } | 127 | } |
110 | 128 | ||
111 | type GetColumnsParams = { | 129 | type GetColumnsParams = { |
130 | + handleRename: (id: number, name: string) => void; | ||
112 | handleMove: (id: number, to: number) => void; | 131 | handleMove: (id: number, to: number) => void; |
113 | handleCopy: (id: number, to: number) => void; | 132 | handleCopy: (id: number, to: number) => void; |
114 | handleDelete: (id: number) => void; | 133 | handleDelete: (id: number) => void; |
115 | }; | 134 | }; |
116 | 135 | ||
117 | function getColumns({ | 136 | function getColumns({ |
137 | + handleRename, | ||
118 | handleMove, | 138 | handleMove, |
119 | handleCopy, | 139 | handleCopy, |
120 | handleDelete, | 140 | handleDelete, |
121 | }: GetColumnsParams): ColumnsType<FileItem> { | 141 | }: GetColumnsParams): ColumnsType<FileItem> { |
122 | return [ | 142 | return [ |
123 | { | 143 | { |
124 | - title: "파일명", | 144 | + title: "이름", |
125 | key: "name", | 145 | key: "name", |
126 | dataIndex: "name", | 146 | dataIndex: "name", |
127 | render: (_name: string, item) => <FileListItem item={item} />, | 147 | render: (_name: string, item) => <FileListItem item={item} />, |
... | @@ -143,6 +163,7 @@ function getColumns({ | ... | @@ -143,6 +163,7 @@ function getColumns({ |
143 | item.is_folder ? null : ( | 163 | item.is_folder ? null : ( |
144 | <FileItemActions | 164 | <FileItemActions |
145 | item={item} | 165 | item={item} |
166 | + onRename={handleRename} | ||
146 | onMove={handleMove} | 167 | onMove={handleMove} |
147 | onCopy={handleCopy} | 168 | onCopy={handleCopy} |
148 | onDelete={handleDelete} | 169 | onDelete={handleDelete} | ... | ... |
frontend/src/file/FileRenamePopover.tsx
0 → 100644
1 | +import React, { useState } from "react"; | ||
2 | +import { Button, Input } from "antd"; | ||
3 | + | ||
4 | +export type FileRenamePopoverProps = { | ||
5 | + name: string; | ||
6 | + onRename: (name: string) => void; | ||
7 | + onCancel?: () => void; | ||
8 | +}; | ||
9 | + | ||
10 | +export function FileRenamePopover({ | ||
11 | + name: oldName, | ||
12 | + onRename, | ||
13 | + onCancel, | ||
14 | +}: FileRenamePopoverProps) { | ||
15 | + const [name, setName] = useState<string>(oldName); | ||
16 | + return ( | ||
17 | + <div> | ||
18 | + <Input | ||
19 | + value={name} | ||
20 | + onChange={(event) => setName(event.target.value)} | ||
21 | + placeholder="이름" | ||
22 | + style={{ marginBottom: 10 }} | ||
23 | + /> | ||
24 | + <div className="ant-popover-buttons"> | ||
25 | + <Button size="small" onClick={onCancel}> | ||
26 | + 취소 | ||
27 | + </Button> | ||
28 | + <Button type="primary" size="small" onClick={() => onRename(name)}> | ||
29 | + 변경 | ||
30 | + </Button> | ||
31 | + </div> | ||
32 | + </div> | ||
33 | + ); | ||
34 | +} |
-
Please register or login to post a comment