From 498d801b7fb51c1e45363e31475801892059b8b4 Mon Sep 17 00:00:00 2001 From: Jeff McMillen Date: Fri, 6 Dec 2024 10:00:54 -0600 Subject: [PATCH] Task/WP-729: Mutation hook: Move files (#996) * Converted useMove mutation to use React Query and TypeScript * Linted code to meet quality standards * Removed superfluous comments * Removed unnecessary dispatches to use React Query to properly move files * Linted client code * Edited request to use apiClient, removed console logs * Corrected body of PUT request * Working on test for mutation, still in progress * Update client/src/hooks/datafiles/mutations/useMove.ts Co-authored-by: Sal Tijerina * Adjusted Dispatch calls * Update client/src/hooks/datafiles/mutations/useMove.ts Adding closing dispatch calls at the end Co-authored-by: Sal Tijerina * Commenting out useMove.test.ts until React Query move mutation is 100% working * Corrected dispatch calls * Linted client-side code * Removed test file temporarily * Added more asynchronous calls to refine process * Removed extraneous console.log() --------- Co-authored-by: Jeff McMillen Co-authored-by: Sal Tijerina Co-authored-by: Chandra Y --- .../src/hooks/datafiles/mutations/useMove.js | 35 ----- .../src/hooks/datafiles/mutations/useMove.ts | 127 ++++++++++++++++++ 2 files changed, 127 insertions(+), 35 deletions(-) delete mode 100644 client/src/hooks/datafiles/mutations/useMove.js create mode 100644 client/src/hooks/datafiles/mutations/useMove.ts diff --git a/client/src/hooks/datafiles/mutations/useMove.js b/client/src/hooks/datafiles/mutations/useMove.js deleted file mode 100644 index 61ff849dd..000000000 --- a/client/src/hooks/datafiles/mutations/useMove.js +++ /dev/null @@ -1,35 +0,0 @@ -import { useDispatch, useSelector, shallowEqual } from 'react-redux'; -import { useSelectedFiles } from 'hooks/datafiles'; - -function useMove() { - const dispatch = useDispatch(); - - const { selectedFiles: selected } = useSelectedFiles(); - - const status = useSelector( - (state) => state.files.operationStatus.move, - shallowEqual - ); - - const setStatus = (newStatus) => - dispatch({ - type: 'DATA_FILES_SET_OPERATION_STATUS', - payload: { operation: 'move', status: newStatus }, - }); - - const move = ({ destSystem, destPath, callback }) => { - const filteredSelected = selected.filter((f) => status[f.id] !== 'SUCCESS'); - dispatch({ - type: 'DATA_FILES_MOVE', - payload: { - dest: { system: destSystem, path: destPath }, - src: filteredSelected, - reloadCallback: callback, - }, - }); - }; - - return { move, status, setStatus }; -} - -export default useMove; diff --git a/client/src/hooks/datafiles/mutations/useMove.ts b/client/src/hooks/datafiles/mutations/useMove.ts new file mode 100644 index 000000000..928823a58 --- /dev/null +++ b/client/src/hooks/datafiles/mutations/useMove.ts @@ -0,0 +1,127 @@ +import { useDispatch, useSelector, shallowEqual } from 'react-redux'; +import { useSelectedFiles } from 'hooks/datafiles'; +import { useMutation } from '@tanstack/react-query'; +import { apiClient } from 'utils/apiClient'; +import truncateMiddle from 'utils/truncateMiddle'; + +export async function moveFileUtil({ + api, + scheme, + system, + path, + destSystem, + destPath, +}: { + api: string; + scheme: string; + system: string; + path: string; + destSystem: string; + destPath: string; +}): Promise<{ name: string; path: string }> { + const body = { + dest_system: destSystem, + dest_path: destPath, + }; + const url = `/api/datafiles/${api}/move/${scheme}/${system}/${path}/`; + const request = await apiClient.put(url, body); + return request.data; +} + +function useMove() { + const dispatch = useDispatch(); + const { selectedFiles: selected } = useSelectedFiles(); + const status = useSelector( + (state: any) => state.files.operationStatus.move, + shallowEqual + ); + + const { api, scheme } = useSelector( + (state: any) => state.files.params.FilesListing + ); + const setStatus = () => { + dispatch({ + type: 'DATA_FILES_SET_OPERATION_STATUS', + payload: { operation: 'move', status: 'RUNNING' }, + }); + }; + + const { mutateAsync } = useMutation({ + mutationFn: moveFileUtil, + }); + + const move = ({ + destSystem, + destPath, + callback, + }: { + destSystem: string; + destPath: string; + callback: () => void; + }) => { + const filteredSelected = selected.filter( + (f: any) => status[f.id] !== 'SUCCESS' + ); + const moveCalls: Promise[] = filteredSelected.forEach((file: any) => { + dispatch({ + type: 'DATA_FILES_SET_OPERATION_STATUS_BY_KEY', + payload: { + status: 'RUNNING', + key: file.id, + operation: 'move', + }, + }); + return mutateAsync( + { + api: api, + scheme: scheme, + system: file.system, + path: file.path, + destSystem: destSystem, + destPath: destPath, + }, + { + onSuccess: () => { + dispatch({ + type: 'DATA_FILES_SET_OPERATION_STATUS_BY_KEY', + payload: { + status: 'SUCCESS', + key: (index: string) => index, + operation: 'move', + }, + }); + dispatch({ + type: 'DATA_FILES_TOGGLE_MODAL', + payload: { operation: 'move', props: {} }, + }); + dispatch({ + type: 'ADD_TOAST', + payload: { + message: `${ + filteredSelected.length > 1 + ? `${filteredSelected.length} files` + : 'File' + } moved to ${truncateMiddle(destPath, 20) || '/'}`, + }, + }); + callback(); + }, + onError: () => { + dispatch({ + type: 'DATA_FILES_SET_OPERATION_STATUS_BY_KEY', + payload: { + status: 'ERROR', + key: (index: string) => index, + operation: 'move', + }, + }); + }, + } + ); + }); + }; + + return { move, status, setStatus }; +} + +export default useMove;