Skip to content

Commit

Permalink
Task/WP-731: Mutation hook: Trash file/folder (#994)
Browse files Browse the repository at this point in the history
* Converted useTrash mutation to use React Query and TypeScript

* Linted code to meet quality standards

* Removed superfluous comments

* Removed extraneous dispatch calls and ran mutations on each selected file

* Added more asynchronous calls to further streamline process

* Still in the process of getting the trash mutation to work correctly

* Trash mutation actually works as intended

* Linted client-side code

* Reverting changes made to package and package-lock

* Refined trash mutation hook to use Axios and Promises

* Linted client-side code again

* Ensured a Promise is returned

---------

Co-authored-by: Jeff McMillen <[email protected]>
Co-authored-by: Sal Tijerina <[email protected]>
  • Loading branch information
3 people authored Dec 18, 2024
1 parent 67a9c23 commit 5b3872f
Show file tree
Hide file tree
Showing 3 changed files with 137 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import getFilePermissions from 'utils/filePermissions';
import { useModal, useSelectedFiles, useFileListing } from 'hooks/datafiles';
import { useSystemRole } from '../DataFilesProjectMembers/_cells/SystemRoleSelector';
import './DataFilesToolbar.scss';
import { useTrash } from 'hooks/datafiles/mutations';

export const ToolbarButton = ({ text, iconName, onClick, disabled }) => {
const iconClassName = `action icon-${iconName}`;
Expand Down Expand Up @@ -40,6 +41,7 @@ const DataFilesToolbar = ({ scheme, api }) => {
const { toggle } = useModal();
const { selectedFiles } = useSelectedFiles();
const { params } = useFileListing('FilesListing');
const { trash } = useTrash();

const history = useHistory();
const location = useLocation();
Expand Down Expand Up @@ -172,20 +174,15 @@ const DataFilesToolbar = ({ scheme, api }) => {
}
};

const trash = useCallback(() => {
const filteredSelected = selectedFiles.filter(
(f) => status[f.system + f.path] !== 'SUCCESS'
);
const homeDir = selectedSystem?.homeDir;

dispatch({
type: 'DATA_FILES_TRASH',
payload: {
src: filteredSelected,
homeDir: selectedSystem?.homeDir || '',
reloadCallback: reloadPage,
},
const trashCallback = useCallback(() => {
trash({
destSystem: selectedSystem.system,
homeDir: homeDir,
callback: reloadPage,
});
}, [selectedFiles, selectedSystem, reloadPage]);
}, [selectedFiles, reloadPage, status]);

const empty = () => {
dispatch({
Expand Down Expand Up @@ -271,7 +268,7 @@ const DataFilesToolbar = ({ scheme, api }) => {
<ToolbarButton
text={!inTrash ? 'Trash' : 'Empty'}
iconName="trash"
onClick={!inTrash ? trash : empty}
onClick={!inTrash ? trashCallback : empty}
disabled={!inTrash ? !canTrash : !canEmpty}
className={!inTrash ? '' : 'is-empty'}
/>
Expand Down
29 changes: 0 additions & 29 deletions client/src/hooks/datafiles/mutations/useTrash.js

This file was deleted.

127 changes: 127 additions & 0 deletions client/src/hooks/datafiles/mutations/useTrash.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
import { useSelector, useDispatch, shallowEqual } from 'react-redux';
import { useMutation } from '@tanstack/react-query';
import { useSelectedFiles } from 'hooks/datafiles';
import Cookies from 'js-cookie';
import { apiClient } from 'utils/apiClient';

export async function trashUtil({
api,
scheme,
system,
path,
homeDir,
}: {
api: string;
scheme: string;
system: string;
path: string;
homeDir: string;
}): Promise<{ file: any; path: string }> {
const url = `/api/datafiles/${api}/trash/${scheme}/${system}/${path}/`;
const body = {
homeDir: homeDir,
};
const response = await apiClient.put(url, body, {
headers: {
'X-CSRFToken': Cookies.get('csrftoken' || ''),
},
withCredentials: true,
});

return response.data;
}

function useTrash() {
const dispatch = useDispatch();
const { selectedFiles: selected } = useSelectedFiles();
const status = useSelector(
(state: any) => state.files.operationStatus.trash,
shallowEqual
);

const { api, scheme } = useSelector(
(state: any) => state.files.params.FilesListing
);

const setStatus = (newStatus: any) => {
dispatch({
type: 'DATA_FILES_SET_OPERATION_STATUS',
payload: { status: newStatus, operation: 'trash' },
});
};

const { mutateAsync } = useMutation({ mutationFn: trashUtil });

const trash = ({
destSystem,
homeDir,
callback,
}: {
destSystem: string;
homeDir: any;
callback: any;
}) => {
const filteredSelected = selected.filter(
(f: any) => status[f.id] !== 'SUCCESS'
);
const trashCalls: Promise<any>[] = filteredSelected.map((file: any) => {
dispatch({
type: 'DATA_FILES_SET_OPERATION_STATUS_BY_KEY',
payload: {
status: 'RUNNING',
key: (index: string) => index,
operation: 'trash',
},
});
return mutateAsync(
{
api: api,
scheme: scheme,
system: destSystem,
path: file.path,
homeDir: homeDir,
},
{
onSuccess: (response: any) => {
dispatch({
type: 'DATA_FILES_SET_OPERATION_STATUS_BY_KEY',
payload: {
status: 'SUCCESS',
key: (index: string) => index,
operation: 'trash',
},
});

callback();
},
onError: () => {
dispatch({
type: 'DATA_FILES_SET_OPERATION_STATUS_BY_KEY',
payload: {
status: 'ERROR',
key: (index: string) => index,
operation: 'trash',
},
});
},
}
);
});
Promise.all(trashCalls).then(() => {
dispatch({
type: 'ADD_TOAST',
payload: {
message: `${
filteredSelected.length > 1
? `${filteredSelected.length} files moved to Trash`
: 'File moved to Trash'
}`,
},
});
});
};

return { trash, status, setStatus };
}

export default useTrash;

0 comments on commit 5b3872f

Please sign in to comment.