mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-25 22:46:31 -04:00
Use react-query for Quality Definitions
This commit is contained in:
@@ -1,31 +1,29 @@
|
||||
import React, { useCallback } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import TextInput from 'Components/Form/TextInput';
|
||||
import Quality from 'Quality/Quality';
|
||||
import { setQualityDefinitionValue } from 'Store/Actions/settingsActions';
|
||||
import { useManageQualityDefinitions } from './useQualityDefinitions';
|
||||
import styles from './QualityDefinition.css';
|
||||
|
||||
interface QualityDefinitionProps {
|
||||
id: number;
|
||||
quality: Quality;
|
||||
title: string;
|
||||
updateDefinition: ReturnType<
|
||||
typeof useManageQualityDefinitions
|
||||
>['updateDefinition'];
|
||||
}
|
||||
|
||||
function QualityDefinition(props: QualityDefinitionProps) {
|
||||
const { id, quality, title } = props;
|
||||
const dispatch = useDispatch();
|
||||
|
||||
function QualityDefinition({
|
||||
id,
|
||||
quality,
|
||||
title,
|
||||
updateDefinition,
|
||||
}: QualityDefinitionProps) {
|
||||
const handleTitleChange = useCallback(
|
||||
({ value }: { value: string }) => {
|
||||
dispatch(
|
||||
setQualityDefinitionValue({
|
||||
id,
|
||||
name: 'title',
|
||||
value,
|
||||
})
|
||||
);
|
||||
updateDefinition(id, 'title', value);
|
||||
},
|
||||
[id, dispatch]
|
||||
[id, updateDefinition]
|
||||
);
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,42 +1,17 @@
|
||||
import { isEmpty } from 'lodash';
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import React, { useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import AppState from 'App/State/AppState';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import PageSectionContent from 'Components/Page/PageSectionContent';
|
||||
import usePrevious from 'Helpers/Hooks/usePrevious';
|
||||
import {
|
||||
fetchQualityDefinitions,
|
||||
saveQualityDefinitions,
|
||||
} from 'Store/Actions/settingsActions';
|
||||
import {
|
||||
OnChildStateChange,
|
||||
SetChildSave,
|
||||
} from 'typings/Settings/SettingsState';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import QualityDefinition from './QualityDefinition';
|
||||
import { useManageQualityDefinitions } from './useQualityDefinitions';
|
||||
import styles from './QualityDefinitions.css';
|
||||
|
||||
function createQualityDefinitionsSelector() {
|
||||
return createSelector(
|
||||
(state: AppState) => state.settings.qualityDefinitions,
|
||||
(qualityDefinitions) => {
|
||||
const items = qualityDefinitions.items.map((item) => {
|
||||
const pendingChanges = qualityDefinitions.pendingChanges[item.id] || {};
|
||||
|
||||
return Object.assign({}, item, pendingChanges);
|
||||
});
|
||||
|
||||
return {
|
||||
...qualityDefinitions,
|
||||
items,
|
||||
hasPendingChanges: !isEmpty(qualityDefinitions.pendingChanges),
|
||||
};
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
interface QualityDefinitionsProps {
|
||||
isResettingQualityDefinitions: boolean;
|
||||
setChildSave: SetChildSave;
|
||||
@@ -48,21 +23,27 @@ function QualityDefinitions({
|
||||
setChildSave,
|
||||
onChildStateChange,
|
||||
}: QualityDefinitionsProps) {
|
||||
const dispatch = useDispatch();
|
||||
const { items, isFetching, isPopulated, isSaving, error, hasPendingChanges } =
|
||||
useSelector(createQualityDefinitionsSelector());
|
||||
const queryClient = useQueryClient();
|
||||
const {
|
||||
items,
|
||||
isFetching,
|
||||
isFetched,
|
||||
isSaving,
|
||||
error,
|
||||
hasPendingChanges,
|
||||
updateDefinition,
|
||||
saveQualityDefinitions,
|
||||
} = useManageQualityDefinitions();
|
||||
|
||||
const wasResettingQualityDefinitions = usePrevious(
|
||||
isResettingQualityDefinitions
|
||||
);
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchQualityDefinitions());
|
||||
|
||||
setChildSave(() => {
|
||||
dispatch(saveQualityDefinitions());
|
||||
saveQualityDefinitions();
|
||||
});
|
||||
}, [dispatch, setChildSave]);
|
||||
}, [saveQualityDefinitions, setChildSave]);
|
||||
|
||||
useEffect(() => {
|
||||
onChildStateChange({
|
||||
@@ -73,16 +54,20 @@ function QualityDefinitions({
|
||||
|
||||
useEffect(() => {
|
||||
if (wasResettingQualityDefinitions && !isResettingQualityDefinitions) {
|
||||
dispatch(fetchQualityDefinitions());
|
||||
queryClient.invalidateQueries({ queryKey: ['/qualitydefinition'] });
|
||||
}
|
||||
}, [isResettingQualityDefinitions, wasResettingQualityDefinitions, dispatch]);
|
||||
}, [
|
||||
isResettingQualityDefinitions,
|
||||
wasResettingQualityDefinitions,
|
||||
queryClient,
|
||||
]);
|
||||
|
||||
return (
|
||||
<FieldSet legend={translate('QualityDefinitions')}>
|
||||
<PageSectionContent
|
||||
errorMessage={translate('QualityDefinitionsLoadError')}
|
||||
isFetching={isFetching}
|
||||
isPopulated={isPopulated}
|
||||
isPopulated={isFetched}
|
||||
error={error}
|
||||
>
|
||||
<div className={styles.header}>
|
||||
@@ -92,7 +77,13 @@ function QualityDefinitions({
|
||||
|
||||
<div className={styles.definitions}>
|
||||
{items.map((item) => {
|
||||
return <QualityDefinition key={item.id} {...item} />;
|
||||
return (
|
||||
<QualityDefinition
|
||||
key={item.id}
|
||||
{...item}
|
||||
updateDefinition={updateDefinition}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
</PageSectionContent>
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import { useQueryClient } from '@tanstack/react-query';
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import useApiMutation from 'Helpers/Hooks/useApiMutation';
|
||||
import useApiQuery from 'Helpers/Hooks/useApiQuery';
|
||||
import { usePendingItemsStore } from 'Helpers/Hooks/usePendingItemsStore';
|
||||
import QualityDefinitionModel from 'Quality/QualityDefinitionModel';
|
||||
import { useSaveSettings } from 'Settings/useSettings';
|
||||
|
||||
const PATH = '/qualitydefinition';
|
||||
const DEFAULT_QUALITY_DEFINITIONS: QualityDefinitionModel[] = [];
|
||||
|
||||
export const useQualityDefinitions = () => {
|
||||
const result = useApiQuery<QualityDefinitionModel[]>({
|
||||
path: PATH,
|
||||
});
|
||||
|
||||
return {
|
||||
...result,
|
||||
data: result.data ?? DEFAULT_QUALITY_DEFINITIONS,
|
||||
};
|
||||
};
|
||||
|
||||
export const useSaveQualityDefinitions = (onSuccess?: () => void) => {
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
const { mutate, isPending, error } = useApiMutation<
|
||||
QualityDefinitionModel[],
|
||||
QualityDefinitionModel[]
|
||||
>({
|
||||
path: PATH,
|
||||
method: 'PUT',
|
||||
mutationOptions: {
|
||||
onSuccess: (updatedSettings: QualityDefinitionModel[]) => {
|
||||
queryClient.setQueryData<QualityDefinitionModel[]>(
|
||||
[PATH],
|
||||
updatedSettings
|
||||
);
|
||||
onSuccess?.();
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
return {
|
||||
save: mutate,
|
||||
isSaving: isPending,
|
||||
saveError: error,
|
||||
};
|
||||
};
|
||||
|
||||
export const useManageQualityDefinitions = () => {
|
||||
const { data, isFetching, isFetched, error } = useQualityDefinitions();
|
||||
const {
|
||||
setPendingItem,
|
||||
clearPendingItems,
|
||||
getItemsWithPendingChanges,
|
||||
getPendingChangesForSave,
|
||||
hasPendingChanges,
|
||||
} = usePendingItemsStore<QualityDefinitionModel>();
|
||||
|
||||
const { save, isSaving, saveError } = useSaveSettings(
|
||||
PATH,
|
||||
clearPendingItems
|
||||
);
|
||||
|
||||
const settings = useMemo(() => {
|
||||
return {
|
||||
items: getItemsWithPendingChanges(data),
|
||||
hasPendingChanges,
|
||||
};
|
||||
}, [data, getItemsWithPendingChanges, hasPendingChanges]);
|
||||
|
||||
const saveQualityDefinitions = useCallback(() => {
|
||||
const updatedSettings = getPendingChangesForSave(data);
|
||||
save(updatedSettings);
|
||||
}, [data, getPendingChangesForSave, save]);
|
||||
|
||||
const updateDefinition = useCallback(
|
||||
<K extends keyof QualityDefinitionModel>(
|
||||
id: number,
|
||||
key: keyof QualityDefinitionModel,
|
||||
value: QualityDefinitionModel[K]
|
||||
) => {
|
||||
const originalItem = data.find((def) => def.id === id);
|
||||
setPendingItem(id, key, value, originalItem);
|
||||
},
|
||||
[data, setPendingItem]
|
||||
);
|
||||
|
||||
return {
|
||||
...settings,
|
||||
updateDefinition,
|
||||
saveQualityDefinitions,
|
||||
isFetching,
|
||||
isFetched,
|
||||
isSaving,
|
||||
error,
|
||||
saveError,
|
||||
};
|
||||
};
|
||||
Reference in New Issue
Block a user