mirror of
https://github.com/Sonarr/Sonarr.git
synced 2026-04-23 22:25:56 -04:00
Use react-query for series
This commit is contained in:
@@ -1,9 +1,6 @@
|
||||
import { orderBy } from 'lodash';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { useSelect } from 'App/Select/SelectContext';
|
||||
import AppState from 'App/State/AppState';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
import FormInputGroup from 'Components/Form/FormInputGroup';
|
||||
import FormLabel from 'Components/Form/FormLabel';
|
||||
@@ -14,8 +11,11 @@ import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes, kinds } from 'Helpers/Props';
|
||||
import Series from 'Series/Series';
|
||||
import { bulkDeleteSeries, setDeleteOption } from 'Store/Actions/seriesActions';
|
||||
import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector';
|
||||
import {
|
||||
setSeriesDeleteOptions,
|
||||
useSeriesDeleteOptions,
|
||||
} from 'Series/seriesOptionsStore';
|
||||
import useSeries, { useBulkDeleteSeries } from 'Series/useSeries';
|
||||
import { InputChanged } from 'typings/inputs';
|
||||
import formatBytes from 'Utilities/Number/formatBytes';
|
||||
import translate from 'Utilities/String/translate';
|
||||
@@ -25,17 +25,12 @@ export interface DeleteSeriesModalContentProps {
|
||||
onModalClose(): void;
|
||||
}
|
||||
|
||||
const selectDeleteOptions = createSelector(
|
||||
(state: AppState) => state.series.deleteOptions,
|
||||
(deleteOptions) => deleteOptions
|
||||
);
|
||||
|
||||
function DeleteSeriesModalContent({
|
||||
onModalClose,
|
||||
}: DeleteSeriesModalContentProps) {
|
||||
const { addImportListExclusion } = useSelector(selectDeleteOptions);
|
||||
const allSeries: Series[] = useSelector(createAllSeriesSelector());
|
||||
const dispatch = useDispatch();
|
||||
const { addImportListExclusion } = useSeriesDeleteOptions();
|
||||
const { data: allSeries } = useSeries();
|
||||
const { bulkDeleteSeries } = useBulkDeleteSeries();
|
||||
const [deleteFiles, setDeleteFiles] = useState(false);
|
||||
const { useSelectedIds } = useSelect<Series>();
|
||||
const seriesIds = useSelectedIds();
|
||||
@@ -57,25 +52,21 @@ function DeleteSeriesModalContent({
|
||||
|
||||
const onDeleteOptionChange = useCallback(
|
||||
({ name, value }: { name: string; value: boolean }) => {
|
||||
dispatch(
|
||||
setDeleteOption({
|
||||
[name]: value,
|
||||
})
|
||||
);
|
||||
setSeriesDeleteOptions({
|
||||
[name]: value,
|
||||
});
|
||||
},
|
||||
[dispatch]
|
||||
[]
|
||||
);
|
||||
|
||||
const onDeleteSeriesConfirmed = useCallback(() => {
|
||||
setDeleteFiles(false);
|
||||
|
||||
dispatch(
|
||||
bulkDeleteSeries({
|
||||
seriesIds,
|
||||
deleteFiles,
|
||||
addImportListExclusion,
|
||||
})
|
||||
);
|
||||
bulkDeleteSeries({
|
||||
seriesIds,
|
||||
deleteFiles,
|
||||
addImportListExclusion,
|
||||
});
|
||||
|
||||
onModalClose();
|
||||
}, [
|
||||
@@ -83,7 +74,7 @@ function DeleteSeriesModalContent({
|
||||
addImportListExclusion,
|
||||
setDeleteFiles,
|
||||
seriesIds,
|
||||
dispatch,
|
||||
bulkDeleteSeries,
|
||||
onModalClose,
|
||||
]);
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { orderBy } from 'lodash';
|
||||
import React, { useCallback, useMemo } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useSelect } from 'App/Select/SelectContext';
|
||||
import { RENAME_SERIES } from 'Commands/commandNames';
|
||||
import Alert from 'Components/Alert';
|
||||
@@ -12,8 +12,8 @@ import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { icons, kinds } from 'Helpers/Props';
|
||||
import Series from 'Series/Series';
|
||||
import useSeries from 'Series/useSeries';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './OrganizeSeriesModalContent.css';
|
||||
|
||||
@@ -24,7 +24,7 @@ export interface OrganizeSeriesModalContentProps {
|
||||
function OrganizeSeriesModalContent({
|
||||
onModalClose,
|
||||
}: OrganizeSeriesModalContentProps) {
|
||||
const allSeries: Series[] = useSelector(createAllSeriesSelector());
|
||||
const { data: allSeries } = useSeries();
|
||||
const dispatch = useDispatch();
|
||||
const { useSelectedIds } = useSelect<Series>();
|
||||
const seriesIds = useSelectedIds();
|
||||
|
||||
@@ -19,12 +19,7 @@ function SeasonDetails(props: SeasonDetailsProps) {
|
||||
return (
|
||||
<div className={styles.seasons}>
|
||||
{latestSeasons.map((season) => {
|
||||
const {
|
||||
seasonNumber,
|
||||
monitored,
|
||||
statistics,
|
||||
isSaving = false,
|
||||
} = season;
|
||||
const { seasonNumber, monitored, statistics } = season;
|
||||
|
||||
return (
|
||||
<SeasonPassSeason
|
||||
@@ -33,7 +28,6 @@ function SeasonDetails(props: SeasonDetailsProps) {
|
||||
seasonNumber={seasonNumber}
|
||||
monitored={monitored}
|
||||
statistics={statistics}
|
||||
isSaving={isSaving}
|
||||
/>
|
||||
);
|
||||
})}
|
||||
|
||||
@@ -1,10 +1,9 @@
|
||||
import classNames from 'classnames';
|
||||
import React, { useCallback } from 'react';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import MonitorToggleButton from 'Components/MonitorToggleButton';
|
||||
import formatSeason from 'Season/formatSeason';
|
||||
import { Statistics } from 'Series/Series';
|
||||
import { toggleSeasonMonitored } from 'Store/Actions/seriesActions';
|
||||
import { useToggleSeasonMonitored } from 'Series/useSeries';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './SeasonPassSeason.css';
|
||||
|
||||
@@ -13,7 +12,6 @@ interface SeasonPassSeasonProps {
|
||||
seasonNumber: number;
|
||||
monitored: boolean;
|
||||
statistics: Statistics;
|
||||
isSaving: boolean;
|
||||
}
|
||||
|
||||
function SeasonPassSeason(props: SeasonPassSeasonProps) {
|
||||
@@ -26,24 +24,22 @@ function SeasonPassSeason(props: SeasonPassSeasonProps) {
|
||||
totalEpisodeCount: 0,
|
||||
percentOfEpisodes: 0,
|
||||
},
|
||||
isSaving = false,
|
||||
} = props;
|
||||
|
||||
const { episodeFileCount, totalEpisodeCount, percentOfEpisodes } = statistics;
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const { toggleSeasonMonitored, isTogglingSeasonMonitored } =
|
||||
useToggleSeasonMonitored(seriesId);
|
||||
const onSeasonMonitoredPress = useCallback(() => {
|
||||
dispatch(
|
||||
toggleSeasonMonitored({ seriesId, seasonNumber, monitored: !monitored })
|
||||
);
|
||||
}, [seriesId, seasonNumber, monitored, dispatch]);
|
||||
toggleSeasonMonitored({ seasonNumber, monitored: !monitored });
|
||||
}, [seasonNumber, monitored, toggleSeasonMonitored]);
|
||||
|
||||
return (
|
||||
<div className={styles.season}>
|
||||
<div className={styles.info}>
|
||||
<MonitorToggleButton
|
||||
monitored={monitored}
|
||||
isSaving={isSaving}
|
||||
isSaving={isTogglingSeasonMonitored}
|
||||
onPress={onSeasonMonitoredPress}
|
||||
/>
|
||||
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
import React, { useCallback, useEffect, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { createSelector } from 'reselect';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useSelect } from 'App/Select/SelectContext';
|
||||
import AppState from 'App/State/AppState';
|
||||
import { RENAME_SERIES } from 'Commands/commandNames';
|
||||
import SpinnerButton from 'Components/Link/SpinnerButton';
|
||||
import PageContentFooter from 'Components/Page/PageContentFooter';
|
||||
@@ -10,9 +8,10 @@ import usePrevious from 'Helpers/Hooks/usePrevious';
|
||||
import { kinds } from 'Helpers/Props';
|
||||
import Series from 'Series/Series';
|
||||
import {
|
||||
saveSeriesEditor,
|
||||
updateSeriesMonitor,
|
||||
} from 'Store/Actions/seriesActions';
|
||||
useBulkDeleteSeries,
|
||||
useSaveSeriesEditor,
|
||||
useUpdateSeriesMonitor,
|
||||
} from 'Series/useSeries';
|
||||
import createCommandExecutingSelector from 'Store/Selectors/createCommandExecutingSelector';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import DeleteSeriesModal from './Delete/DeleteSeriesModal';
|
||||
@@ -31,28 +30,19 @@ interface SavePayload {
|
||||
moveFiles?: boolean;
|
||||
}
|
||||
|
||||
const seriesEditorSelector = createSelector(
|
||||
(state: AppState) => state.series,
|
||||
(series) => {
|
||||
const { isSaving, isDeleting, deleteError } = series;
|
||||
|
||||
return {
|
||||
isSaving,
|
||||
isDeleting,
|
||||
deleteError,
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
function SeriesIndexSelectFooter() {
|
||||
const { isSaving, isDeleting, deleteError } =
|
||||
useSelector(seriesEditorSelector);
|
||||
const { saveSeriesEditor, isSavingSeriesEditor } = useSaveSeriesEditor();
|
||||
const { updateSeriesMonitor, isUpdatingSeriesMonitor } =
|
||||
useUpdateSeriesMonitor();
|
||||
const { isBulkDeleting, bulkDeleteError } = useBulkDeleteSeries();
|
||||
|
||||
const isOrganizingSeries = useSelector(
|
||||
createCommandExecutingSelector(RENAME_SERIES)
|
||||
);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
const isSaving = isSavingSeriesEditor || isUpdatingSeriesMonitor;
|
||||
const isDeleting = isBulkDeleting;
|
||||
const deleteError = bulkDeleteError;
|
||||
|
||||
const [isEditModalOpen, setIsEditModalOpen] = useState(false);
|
||||
const [isOrganizeModalOpen, setIsOrganizeModalOpen] = useState(false);
|
||||
@@ -79,14 +69,12 @@ function SeriesIndexSelectFooter() {
|
||||
setIsSavingSeries(true);
|
||||
setIsEditModalOpen(false);
|
||||
|
||||
dispatch(
|
||||
saveSeriesEditor({
|
||||
...payload,
|
||||
seriesIds,
|
||||
})
|
||||
);
|
||||
saveSeriesEditor({
|
||||
...payload,
|
||||
seriesIds,
|
||||
});
|
||||
},
|
||||
[seriesIds, dispatch]
|
||||
[seriesIds, saveSeriesEditor]
|
||||
);
|
||||
|
||||
const onOrganizePress = useCallback(() => {
|
||||
@@ -106,19 +94,16 @@ function SeriesIndexSelectFooter() {
|
||||
}, [setIsTagsModalOpen]);
|
||||
|
||||
const onApplyTagsPress = useCallback(
|
||||
(tags: number[], applyTags: string) => {
|
||||
(tags: number[], _applyTags: string) => {
|
||||
setIsSavingTags(true);
|
||||
setIsTagsModalOpen(false);
|
||||
|
||||
dispatch(
|
||||
saveSeriesEditor({
|
||||
seriesIds,
|
||||
tags,
|
||||
applyTags,
|
||||
})
|
||||
);
|
||||
saveSeriesEditor({
|
||||
seriesIds,
|
||||
tags,
|
||||
});
|
||||
},
|
||||
[seriesIds, dispatch]
|
||||
[seriesIds, saveSeriesEditor]
|
||||
);
|
||||
|
||||
const onMonitoringPress = useCallback(() => {
|
||||
@@ -134,14 +119,12 @@ function SeriesIndexSelectFooter() {
|
||||
setIsSavingMonitoring(true);
|
||||
setIsMonitoringModalOpen(false);
|
||||
|
||||
dispatch(
|
||||
updateSeriesMonitor({
|
||||
seriesIds,
|
||||
monitor,
|
||||
})
|
||||
);
|
||||
updateSeriesMonitor({
|
||||
series: seriesIds.map((id) => ({ id })),
|
||||
monitoringOptions: { monitor },
|
||||
});
|
||||
},
|
||||
[seriesIds, dispatch]
|
||||
[seriesIds, updateSeriesMonitor]
|
||||
);
|
||||
|
||||
const onDeletePress = useCallback(() => {
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { uniq } from 'lodash';
|
||||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { useSelect } from 'App/Select/SelectContext';
|
||||
import Form from 'Components/Form/Form';
|
||||
import FormGroup from 'Components/Form/FormGroup';
|
||||
@@ -15,7 +14,7 @@ import ModalFooter from 'Components/Modal/ModalFooter';
|
||||
import ModalHeader from 'Components/Modal/ModalHeader';
|
||||
import { inputTypes, kinds, sizes } from 'Helpers/Props';
|
||||
import Series from 'Series/Series';
|
||||
import createAllSeriesSelector from 'Store/Selectors/createAllSeriesSelector';
|
||||
import { useMultipleSeries } from 'Series/useSeries';
|
||||
import { Tag, useTagList } from 'Tags/useTags';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import styles from './TagsModalContent.css';
|
||||
@@ -29,27 +28,24 @@ function TagsModalContent({
|
||||
onModalClose,
|
||||
onApplyTagsPress,
|
||||
}: TagsModalContentProps) {
|
||||
const allSeries: Series[] = useSelector(createAllSeriesSelector());
|
||||
const tagList: Tag[] = useTagList();
|
||||
|
||||
const [tags, setTags] = useState<number[]>([]);
|
||||
const [applyTags, setApplyTags] = useState('add');
|
||||
const { useSelectedIds } = useSelect<Series>();
|
||||
const seriesIds = useSelectedIds();
|
||||
const selectedSeries = useMultipleSeries(seriesIds);
|
||||
|
||||
const seriesTags = useMemo(() => {
|
||||
const tags = seriesIds.reduce((acc: number[], id) => {
|
||||
const s = allSeries.find((s) => s.id === id);
|
||||
|
||||
if (s) {
|
||||
acc.push(...s.tags);
|
||||
const tags = selectedSeries.reduce((acc: number[], series) => {
|
||||
if (series) {
|
||||
acc.push(...series.tags);
|
||||
}
|
||||
|
||||
return acc;
|
||||
}, []);
|
||||
|
||||
return uniq(tags);
|
||||
}, [allSeries, seriesIds]);
|
||||
}, [selectedSeries]);
|
||||
|
||||
const onTagsChange = useCallback(
|
||||
({ value }: { value: number[] }) => {
|
||||
|
||||
Reference in New Issue
Block a user