Skip to content

Commit 2663196

Browse files
committed
Added Upload Action Button
1 parent 70c1040 commit 2663196

File tree

7 files changed

+64
-16
lines changed

7 files changed

+64
-16
lines changed

frontend/src/api/config.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ type ActionOptionMap = {
8888
undo: {
8989
delete_files: boolean;
9090
};
91+
upload: undefined;
9192
import_best: undefined;
9293
import_bootleg: undefined;
9394
import_terminal: undefined;
@@ -125,7 +126,6 @@ export interface InboxFolderFrontendConfig {
125126
export const ACTIONS: Record<string, Action> = {
126127
retag: {
127128
name: 'retag',
128-
label: 'Retag',
129129
options: {
130130
group_albums: false,
131131
autotag: true,
@@ -137,6 +137,9 @@ export const ACTIONS: Record<string, Action> = {
137137
delete_files: true,
138138
},
139139
},
140+
upload: {
141+
name: 'upload',
142+
},
140143
import_best: {
141144
name: 'import_best',
142145
},
@@ -178,7 +181,7 @@ export const DEFAULT_INBOX_FOLDER_FRONTEND_CONFIG: InboxFolderFrontendConfig = {
178181
},
179182
extra: {
180183
variant: 'text',
181-
actions: [ACTIONS.delete_imported_folders],
184+
actions: [ACTIONS.delete_imported_folders, ACTIONS.upload],
182185
},
183186
},
184187
};

frontend/src/components/common/hooks/useDrag.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ type Entries<T> = {
1010
*
1111
*/
1212
export function useDragAndDrop(
13-
elementRef: React.RefObject<HTMLDivElement> | null,
13+
elementRef: React.RefObject<HTMLDivElement | null> | null,
1414
options?: {
1515
onDrop?: (event: DragEvent) => void;
1616
onDragOver?: (event: DragEvent) => void;

frontend/src/components/inbox/actions/buttons.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {
1010
TerminalIcon,
1111
Trash2Icon,
1212
UngroupIcon,
13+
UploadIcon,
1314
} from 'lucide-react';
1415
import { useState } from 'react';
1516
import {
@@ -231,6 +232,8 @@ export function ActionIcon({ action }: { action: Action | Action['name'] }) {
231232
return <TagIcon size={size} />;
232233
case 'undo':
233234
return <HistoryIcon size={size} />;
235+
case 'upload':
236+
return <UploadIcon size={size} />;
234237
case 'import_bootleg':
235238
return <BootlegIcon size={size} />;
236239
case 'import_best':

frontend/src/components/inbox/actions/descriptions.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ export function getActionDescription(action: Action | Action['name']): string {
88
return 'Retag the selected album(s) this includes fetching candidates from your configured metadata sources.';
99
case 'undo':
1010
return 'Allows you to undo imports, this will remove the imported album(s) from your library.';
11+
case 'upload':
12+
return 'Open an overlay to select files for upload into the current inbox.';
1113
case 'import_bootleg':
1214
return 'Import album without using a candidate, this is useful where online metadata is not available, such as bootlegs or dubs.';
1315
case 'import_best':

frontend/src/components/inbox/actions/mutations.tsx

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,10 @@ import {
1616
import { EnqueueKind } from '@/pythonTypes';
1717

1818
import { InboxCardContext, useInboxCardContext } from '../cards/inboxCard';
19+
import {
20+
FileUploadContextType,
21+
useFileUploadContext,
22+
} from '../fileUpload/context';
1923
import {
2024
FolderSelectionContext,
2125
useFolderSelectionContext,
@@ -26,13 +30,15 @@ export function useActionMutation(action: Action) {
2630
const selectionContext = useFolderSelectionContext();
2731
const inboxContext = useInboxCardContext();
2832
const terminalContext = useTerminalContext();
33+
const uploadContext = useFileUploadContext();
2934
const navigate = useNavigate();
3035

3136
const [options, mutationArgs] = actionMutationOptionsAndArgs(
3237
action,
3338
socket,
3439
selectionContext,
3540
inboxContext,
41+
uploadContext,
3642
terminalContext,
3743
navigate
3844
);
@@ -56,6 +62,7 @@ function actionMutationOptionsAndArgs<T = unknown>(
5662
socket: StatusSocket | null,
5763
selectionContext: FolderSelectionContext,
5864
inboxContext: InboxCardContext,
65+
uploadContext: FileUploadContextType,
5966
terminalContext: TerminalContextI,
6067
navigate: UseNavigateResult<string>
6168
): [UseMutationOptions<unknown, APIError, T>, T] {
@@ -157,6 +164,15 @@ function actionMutationOptionsAndArgs<T = unknown>(
157164
escape: options?.escape ?? true, // default to escaping paths
158165
} as T,
159166
];
167+
case 'upload':
168+
return [
169+
uploadDialogMutationOptions as UseMutationOptions<
170+
unknown,
171+
APIError,
172+
T
173+
>,
174+
{ ...uploadContext, inboxFolder: inboxContext.folder } as T,
175+
];
160176
case 'import_terminal':
161177
return [
162178
importTerminalMutationOptions as UseMutationOptions<
@@ -211,6 +227,22 @@ const copyPathMutationOptions: UseMutationOptions<
211227
},
212228
};
213229

230+
const uploadDialogMutationOptions: UseMutationOptions<
231+
unknown,
232+
APIError,
233+
FileUploadContextType & { inboxFolder: InboxCardContext['folder'] }
234+
> = {
235+
// eslint-disable-next-line @typescript-eslint/require-await
236+
mutationFn: async ({ setUploadTargetDir, setOpenDialog, inboxFolder }) => {
237+
// keep the suggested name consistent with the one used in dropzone
238+
setUploadTargetDir(
239+
inboxFolder.full_path +
240+
`/upload_${formatDate(new Date(), '%Y%m%d_%H%M%S')}`
241+
);
242+
setOpenDialog(true);
243+
},
244+
};
245+
214246
function _escapePathForBash(path: string) {
215247
// escaping path is fishy, but this seems to be the best compromise
216248
// https://stackoverflow.com/questions/1779858/how-do-i-escape-a-string-for-a-shell-command-in-node

frontend/src/components/inbox/fileUpload/context.tsx

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@ import { useDragAndDrop } from '@/components/common/hooks/useDrag';
88

99
import { UploadDialog } from './dialog';
1010

11-
type FileUploadContextType = Omit<FileUploadState, 'mutate' | 'mutateAsync'> & {
11+
export type FileUploadContextType = Omit<
12+
FileUploadState,
13+
'mutate' | 'mutateAsync'
14+
> & {
1215
fileList: Array<File>;
1316
setFileList: React.Dispatch<React.SetStateAction<Array<File>>>;
1417
uploadFiles: () => Promise<{ status: string }>;
1518
uploadTargetDir: string | null;
1619
setUploadTargetDir: React.Dispatch<React.SetStateAction<string | null>>;
20+
openDialog: boolean;
21+
setOpenDialog: React.Dispatch<React.SetStateAction<boolean>>;
1722
reset: () => void;
1823

1924
// drag drop
@@ -31,6 +36,7 @@ export function FileUploadProvider({
3136
}) {
3237
const [fileList, setFileList] = useState<Array<File>>([]);
3338
const [uploadTargetDir, setUploadTargetDir] = useState<string | null>(null);
39+
const [openDialog, setOpenDialog] = useState(false);
3440

3541
const isOverWindow = useDragAndDrop(null, {
3642
preventDefault: true,
@@ -56,6 +62,8 @@ export function FileUploadProvider({
5662
},
5763
uploadTargetDir,
5864
setUploadTargetDir,
65+
openDialog,
66+
setOpenDialog,
5967
isOverWindow,
6068
}}
6169
>

frontend/src/components/inbox/fileUpload/dialog.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44
* ...
55
*/
66

7-
import { CheckIcon, FileMusicIcon, Upload, XIcon } from 'lucide-react';
8-
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
7+
import { CheckIcon, FileMusicIcon, UploadIcon, XIcon } from 'lucide-react';
8+
import { useCallback, useEffect, useMemo, useRef } from 'react';
99
import {
1010
alpha,
1111
Box,
@@ -32,15 +32,15 @@ import { useFileUploadContext } from './context';
3232

3333
export function UploadDialog() {
3434
const cancelButtonRef = useRef<CancelButtonRef>(null);
35-
const [open, setOpen] = useState(false);
36-
const { fileList, reset } = useFileUploadContext();
35+
const { fileList, reset, openDialog, setOpenDialog } =
36+
useFileUploadContext();
3737

3838
const resetDialog = useCallback(
3939
(close: boolean = true) => {
40-
if (close) setOpen(false);
40+
if (close) setOpenDialog(false);
4141
reset();
4242
},
43-
[reset]
43+
[reset, setOpenDialog]
4444
);
4545

4646
// SM@PS: Try to not use 'useEffect' for derived state. Kinda an antipattern
@@ -53,13 +53,13 @@ export function UploadDialog() {
5353
// Open dialog when files are added
5454
useEffect(() => {
5555
if (fileList.length > 0) {
56-
setOpen(true);
56+
setOpenDialog(true);
5757
}
58-
}, [fileList.length]);
58+
}, [fileList.length, setOpenDialog]);
5959

6060
return (
6161
<Dialog
62-
open={open}
62+
open={openDialog}
6363
title={title}
6464
onClose={(_event, reason) => {
6565
if (reason !== 'backdropClick') resetDialog();
@@ -326,7 +326,7 @@ function UploadButton({ onUpload }: { onUpload: () => void }) {
326326
return (
327327
<Button
328328
variant="contained"
329-
startIcon={<Upload />}
329+
startIcon={<UploadIcon />}
330330
onClick={() => {
331331
if (isSuccess) {
332332
reset();
@@ -479,8 +479,8 @@ function UploadFinished() {
479479
<Box
480480
sx={(theme) => ({
481481
border: '2px solid',
482-
borderColor: theme.palette.secondary.main,
483-
color: theme.palette.secondary.main,
482+
borderColor: theme.palette.primary.main,
483+
color: theme.palette.primary.main,
484484
paddingInline: 4,
485485
paddingBlock: 2,
486486
textAlign: 'center',

0 commit comments

Comments
 (0)