Skip to content

Commit

Permalink
More QoL changes to renamer (#995)
Browse files Browse the repository at this point in the history
  • Loading branch information
harshithmohan authored Aug 20, 2024
1 parent 22ebb96 commit c28846d
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 28 deletions.
12 changes: 6 additions & 6 deletions src/components/Utilities/Renamer/ConfigModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,11 @@ type Props = {
onClose: () => void;
rename: boolean;
show: boolean;
changeAltSelectedConfig: (configName: string) => void;
changeSelectedConfig: (configName: string) => void;
};

const ConfigModal = (props: Props) => {
const {
changeAltSelectedConfig,
changeSelectedConfig,
config,
onClose,
Expand All @@ -38,6 +36,8 @@ const ConfigModal = (props: Props) => {
const [selectedRenamer, setSelectedRenamer] = useState('na');

useEffect(() => {
if (config.Name === '') return;

if (rename) {
setConfigName(config.Name);
setSelectedRenamer(config.RenamerID);
Expand All @@ -58,7 +58,7 @@ const ConfigModal = (props: Props) => {
await patchConfig(
{
configName: config.Name,
operations: [{ op: 'replace', path: 'Name', value: configName }],
operations: [{ op: 'replace', path: '/Name', value: configName }],
},
);
} else {
Expand All @@ -78,7 +78,7 @@ const ConfigModal = (props: Props) => {
return;
}

changeAltSelectedConfig(configName);
changeSelectedConfig(configName);
onClose();
};

Expand Down Expand Up @@ -118,8 +118,8 @@ const ConfigModal = (props: Props) => {
)}

{rename && (
<option key={config.RenamerID} value={config.RenamerID}>
{config.RenamerID}
<option key={selectedRenamer} value={selectedRenamer}>
{selectedRenamer}
</option>
)}
</Select>
Expand Down
33 changes: 26 additions & 7 deletions src/core/react-query/renamer/mutations.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import { useMutation } from '@tanstack/react-query';
import { applyPatch } from 'fast-json-patch';

import { axios } from '@/core/axios';
import { invalidateQueries } from '@/core/react-query/queryClient';
import queryClient, { invalidateQueries } from '@/core/react-query/queryClient';
import { updateApiErrors, updateResults } from '@/core/react-query/renamer/helpers';

import type {
RenamerConfigResponseType,
RenamerConfigType,
RenamerPatchRequestType,
RenamerPreviewRequestType,
RenamerRelocateRequestType,
RenamerResultType,
} from '@/core/react-query/renamer/types';
import type { Operation } from 'fast-json-patch';

export const useRenamerPreviewMutation = () =>
useMutation<RenamerResultType[], unknown, RenamerPreviewRequestType>({
Expand Down Expand Up @@ -44,17 +46,34 @@ export const useRenamerSaveConfigMutation = () =>
});

export const useRenamerPatchConfigMutation = () =>
useMutation({
mutationFn: ({ configName, operations }: { configName: string, operations: Operation[] }) =>
axios.patch(`Renamer/Config/${configName}`, operations),
useMutation<RenamerConfigType, unknown, RenamerPatchRequestType>({
mutationFn: ({ configName, operations }) => axios.patch(`Renamer/Config/${configName}`, operations),
onMutate: ({ configName, operations }) => {
const data = queryClient.getQueryData<RenamerConfigType[]>(['renamer', 'config'])?.slice();
if (!data) return;

const configIndex = data.findIndex(config => config.Name === configName);
data[configIndex] = applyPatch(data[configIndex], operations).newDocument;

// Side effects are not triggered if it's not set to [] first
// There is someting wrong with how tanstack query's structural sharing works
queryClient.setQueryData(['renamer', 'config'], []);
queryClient.setQueryData(['renamer', 'config'], data);
},
onSuccess: () => {
invalidateQueries(['renamer']);
invalidateQueries(['settings']);
},
});

export const useRenamerNewConfigMutation = () =>
useMutation({
mutationFn: (config: RenamerConfigResponseType) => axios.post('Renamer/Config', config),
useMutation<unknown, unknown, RenamerConfigResponseType>({
mutationFn: config => axios.post('Renamer/Config', config),
onMutate: (config) => {
queryClient.setQueryData(
['renamer', 'config'],
(data: RenamerConfigType[]) => [...data, config],
);
},
onSuccess: () => invalidateQueries(['renamer']),
});
7 changes: 7 additions & 0 deletions src/core/react-query/renamer/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { Operation } from 'fast-json-patch';

type RenamerBaseType = {
RenamerID: string;
Version?: string;
Expand Down Expand Up @@ -92,3 +94,8 @@ export type RenamerRelocateRequestType = RenamerRelocateBaseRequestType & {
configName: string;
deleteEmptyDirectories?: boolean;
};

export type RenamerPatchRequestType = {
configName: string;
operations: Operation[];
};
37 changes: 22 additions & 15 deletions src/pages/utilities/Renamer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import {
mdiRefresh,
} from '@mdi/js';
import { Icon } from '@mdi/react';
import cx from 'classnames';
import { produce } from 'immer';
import { chunk, filter, find, isEqual, map } from 'lodash';
import { useImmer } from 'use-immer';
Expand Down Expand Up @@ -180,14 +181,19 @@ const getStatusColumn = (renameResults: Record<number, RenamerResultType>) => ({
} as UtilityHeaderType<FileType>);

const Menu = React.memo((
props: { moveFiles: boolean, toggleMoveFiles: () => void, selectedRows: FileType[] },
props: { disable: boolean, moveFiles: boolean, toggleMoveFiles: () => void, selectedRows: FileType[] },
) => {
const { moveFiles, selectedRows, toggleMoveFiles } = props;
const { disable, moveFiles, selectedRows, toggleMoveFiles } = props;

const dispatch = useDispatch();

return (
<div className="flex h-13 grow items-center gap-x-4 rounded-lg border border-panel-border bg-panel-background-alt px-4 py-3">
<div
className={cx(
'flex h-13 grow items-center gap-x-4 rounded-lg border border-panel-border bg-panel-background-alt px-4 py-3 transition-opacity',
disable ? 'opacity-65 pointer-events-none' : '',
)}
>
<MenuButton
onClick={() => dispatch(clearRenameResults())}
icon={mdiRefresh}
Expand All @@ -197,6 +203,7 @@ const Menu = React.memo((
onClick={() => dispatch(removeFiles(selectedRows.map(row => row.ID)))}
icon={mdiMinusCircleOutline}
name="Remove"
disabled={!disable && selectedRows.length === 0}
/>
<MenuButton
onClick={() => dispatch(clearFiles())}
Expand Down Expand Up @@ -227,8 +234,6 @@ const Renamer = () => {
selectedConfig,
setSelectedConfig,
] = useState<RenamerConfigType>({ RenamerID: '', Name: '' });
// Used as temp variable to set the selected config after renaming or creating a new config
const [altSelectedConfig, setAltSelectedConfig] = useState<string>();

const [
newConfig,
Expand Down Expand Up @@ -300,7 +305,6 @@ const Renamer = () => {

setSelectedConfig(tempConfig);
setNewConfig(tempConfig.Settings);
setAltSelectedConfig(undefined);
});

// Handle the below 3 hooks with care. These are used for auto-updating previews on changes.
Expand Down Expand Up @@ -366,11 +370,9 @@ const Renamer = () => {
}, [dispatch, moveFiles]);

useEffect(() => {
if (!renamerConfigsQuery.data) return;
changeSelectedConfig(altSelectedConfig ?? (settings.Plugins.Renamer.DefaultRenamer ?? 'Default'));
// This should not run when altSelectedConfig changes
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [changeSelectedConfig, renamerConfigsQuery.data, settings]);
if (!renamerConfigsQuery.isSuccess) return;
changeSelectedConfig(settings.Plugins.Renamer.DefaultRenamer ?? 'Default');
}, [changeSelectedConfig, renamerConfigsQuery.isSuccess, settings]);

const {
handleRowSelect,
Expand Down Expand Up @@ -414,7 +416,12 @@ const Renamer = () => {
<div className="flex grow flex-col gap-y-3">
<ShokoPanel title="File Rename">
<div className="flex items-center gap-x-3">
<Menu selectedRows={selectedRows} moveFiles={moveFiles} toggleMoveFiles={toggleMoveFiles} />
<Menu
selectedRows={selectedRows}
moveFiles={moveFiles}
toggleMoveFiles={toggleMoveFiles}
disable={relocatePending}
/>
<div className="flex gap-x-3">
<Button
buttonType="secondary"
Expand All @@ -430,6 +437,7 @@ const Renamer = () => {
buttonSize="normal"
className="flex h-13 items-center"
onClick={toggleAddFilesModal}
disabled={relocatePending}
>
Add Files
</Button>
Expand All @@ -439,7 +447,7 @@ const Renamer = () => {
className="flex h-13 flex-wrap items-center gap-x-2"
onClick={handleRename}
loading={relocatePending}
disabled={configEdited}
disabled={configEdited || relocatePending || addedFiles.length === 0}
tooltip={configEdited ? 'Config has been edited, please save before relocating files' : ''}
>
<Icon path={mdiFileDocumentEditOutline} size={1} />
Expand All @@ -451,7 +459,7 @@ const Renamer = () => {
</ShokoPanel>

<AnimateHeight height={showSettings ? 'auto' : 0}>
<div className="my-3 flex !h-[32rem] gap-x-6">
<div className={cx('my-3 flex !h-[32rem] gap-x-6', relocatePending && 'opacity-65 pointer-events-none')}>
{renamerConfigsQuery.isSuccess && (
<>
<div className="flex w-1/3 flex-col gap-y-6">
Expand Down Expand Up @@ -529,7 +537,6 @@ const Renamer = () => {
onClose={toggleConfigModal}
rename={configModelRename}
config={selectedConfig}
changeAltSelectedConfig={setAltSelectedConfig}
changeSelectedConfig={changeSelectedConfig}
/>
</div>
Expand Down

0 comments on commit c28846d

Please sign in to comment.