From 221871d5c2bc56bc60a131f971d4f23b150ba28f Mon Sep 17 00:00:00 2001 From: Harshith Mohan <26010946+harshithmohan@users.noreply.github.com> Date: Sun, 26 Jul 2026 14:49:09 +0530 Subject: [PATCH] Update ReleaseManagement query layer for ShokoServer PR #1396 --- .../DuplicateFilesQuickSelectModal.tsx | 2 +- .../DuplicateFiles/DuplicatesInfo.tsx | 2 +- ....tsx => ReleaseManagementPreviewModal.tsx} | 4 +- .../ReleaseManagementSeriesDetail.tsx | 8 +- ...st.tsx => ReleaseManagementSeriesList.tsx} | 8 +- .../SeriesDetail/ManageVariationsModal.tsx | 4 +- .../Utilities/UtilitySeriesList.tsx | 37 ++++++--- .../react-query/duplicate-files/queries.ts | 58 ++++++++++++++ src/core/react-query/duplicate-files/types.ts | 18 +++++ .../react-query/missing-episodes/queries.ts | 58 ++++++++++++++ .../react-query/missing-episodes/types.ts | 18 +++++ .../release-management/mutations.ts | 2 +- .../react-query/release-management/queries.ts | 77 +++---------------- .../react-query/release-management/types.ts | 31 ++------ src/core/signalr/eventHandlers.ts | 10 ++- .../DuplicateFilesLinkedTab.tsx | 4 +- src/pages/utilities/MissingEpisodes.tsx | 6 +- src/pages/utilities/ReleaseManagement.tsx | 12 +-- vite.config.mjs | 2 +- 19 files changed, 226 insertions(+), 135 deletions(-) rename src/components/Utilities/ReleaseManagement/{MultipleReleasesPreviewModal.tsx => ReleaseManagementPreviewModal.tsx} (99%) rename src/components/Utilities/ReleaseManagement/{MultipleReleasesSeriesList.tsx => ReleaseManagementSeriesList.tsx} (97%) create mode 100644 src/core/react-query/duplicate-files/queries.ts create mode 100644 src/core/react-query/duplicate-files/types.ts create mode 100644 src/core/react-query/missing-episodes/queries.ts create mode 100644 src/core/react-query/missing-episodes/types.ts diff --git a/src/components/Utilities/DuplicateFiles/DuplicateFilesQuickSelectModal.tsx b/src/components/Utilities/DuplicateFiles/DuplicateFilesQuickSelectModal.tsx index f2dfb2887..a7ad12d67 100644 --- a/src/components/Utilities/DuplicateFiles/DuplicateFilesQuickSelectModal.tsx +++ b/src/components/Utilities/DuplicateFiles/DuplicateFilesQuickSelectModal.tsx @@ -73,7 +73,7 @@ const DuplicateFilesQuickSelectModal = ({ onClose, seriesId, show }: Props) => { { locationIds, removeFolder: true }, { onSuccess: () => { - resetQueries(['release-management']); + resetQueries(['duplicate-files']); toast.success( `${locationIds.length} ${locationIds.length === 1 ? 'duplicate file' : 'duplicate files'} deleted!`, ); diff --git a/src/components/Utilities/DuplicateFiles/DuplicatesInfo.tsx b/src/components/Utilities/DuplicateFiles/DuplicatesInfo.tsx index 869ab5489..c2f19d3a1 100644 --- a/src/components/Utilities/DuplicateFiles/DuplicatesInfo.tsx +++ b/src/components/Utilities/DuplicateFiles/DuplicatesInfo.tsx @@ -28,7 +28,7 @@ const DuplicatesInfo = ({ file, location }: Props) => { if (!confirmDelete) return; await deleteFileLocation({ locationId: location.ID }); - invalidateQueries(['release-management', 'series', 'episodes']); + invalidateQueries(['duplicate-files', 'series', 'episodes']); }; // To re-enable the correct keybinds once the delete confirmation modal closes diff --git a/src/components/Utilities/ReleaseManagement/MultipleReleasesPreviewModal.tsx b/src/components/Utilities/ReleaseManagement/ReleaseManagementPreviewModal.tsx similarity index 99% rename from src/components/Utilities/ReleaseManagement/MultipleReleasesPreviewModal.tsx rename to src/components/Utilities/ReleaseManagement/ReleaseManagementPreviewModal.tsx index 1019e7cd1..65d93edc5 100644 --- a/src/components/Utilities/ReleaseManagement/MultipleReleasesPreviewModal.tsx +++ b/src/components/Utilities/ReleaseManagement/ReleaseManagementPreviewModal.tsx @@ -134,7 +134,7 @@ const SeriesPreviewRow = ( ); }; -const MultipleReleasesPreviewModal = ({ +const ReleaseManagementPreviewModal = ({ allSelected, mixMatchSelection, onClose, @@ -304,4 +304,4 @@ const MultipleReleasesPreviewModal = ({ ); }; -export default MultipleReleasesPreviewModal; +export default ReleaseManagementPreviewModal; diff --git a/src/components/Utilities/ReleaseManagement/ReleaseManagementSeriesDetail.tsx b/src/components/Utilities/ReleaseManagement/ReleaseManagementSeriesDetail.tsx index 7b7bfe939..44ba21f5b 100644 --- a/src/components/Utilities/ReleaseManagement/ReleaseManagementSeriesDetail.tsx +++ b/src/components/Utilities/ReleaseManagement/ReleaseManagementSeriesDetail.tsx @@ -12,8 +12,8 @@ import Button from '@/components/Input/Button'; import Checkbox from '@/components/Input/Checkbox'; import ShokoPanel from '@/components/Panels/ShokoPanel'; import ShokoIcon from '@/components/ShokoIcon'; -import MultipleReleasesPreviewModal from '@/components/Utilities/ReleaseManagement/MultipleReleasesPreviewModal'; -import { useMultipleReleaseSeriesDetailQuery } from '@/core/react-query/release-management/queries'; +import ReleaseManagementPreviewModal from '@/components/Utilities/ReleaseManagement/ReleaseManagementPreviewModal'; +import { useReleaseManagementSeriesDetailQuery } from '@/core/react-query/release-management/queries'; import toast from '@/core/toast'; import { getAnidbAnimeLink } from '@/core/util'; import useNavigateVoid from '@/hooks/useNavigateVoid'; @@ -95,7 +95,7 @@ const ReleaseManagementSeriesDetail = () => { const [mixMatchSelection, setMixMatchSelection] = useImmer>(new Map()); const [mixMatchUnassignedCount, setMixMatchUnassignedCount] = useState(0); - const seriesQuery = useMultipleReleaseSeriesDetailQuery(seriesId, includeVariations, seriesId > 0); + const seriesQuery = useReleaseManagementSeriesDetailQuery(seriesId, includeVariations, seriesId > 0); const series = seriesQuery.data; useEffect(() => { @@ -236,7 +236,7 @@ const ReleaseManagementSeriesDetail = () => { onClose={toggleManageVariationsModal} /> - 0); + const seriesQuery = useReleaseManagementSeriesDetailQuery(seriesId, true, show && seriesId > 0); const allFiles = seriesQuery.data ? uniqBy(seriesQuery.data.Candidates.flatMap(candidate => candidate.Files), 'VideoLocalID') diff --git a/src/components/Utilities/UtilitySeriesList.tsx b/src/components/Utilities/UtilitySeriesList.tsx index b83a8ef58..c68b5d4e5 100644 --- a/src/components/Utilities/UtilitySeriesList.tsx +++ b/src/components/Utilities/UtilitySeriesList.tsx @@ -7,11 +7,9 @@ import { useToggle } from 'usehooks-ts'; import ShokoIcon from '@/components/ShokoIcon'; import UtilitiesTable from '@/components/Utilities/UtilitiesTable'; +import { useDuplicateFilesQuery, useDuplicateFilesSeriesQuery } from '@/core/react-query/duplicate-files/queries'; +import { useMissingEpisodesQuery, useMissingEpisodesSeriesQuery } from '@/core/react-query/missing-episodes/queries'; import { resetQueries } from '@/core/react-query/queryClient'; -import { - useReleaseManagementSeries, - useReleaseManagementSeriesEpisodes, -} from '@/core/react-query/release-management/queries'; import { getAnidbAnimeLink, getAnidbEpisodeLink } from '@/core/util'; import { getEpisodePrefix } from '@/core/utilities/getEpisodePrefix'; import useFlattenListResult from '@/hooks/useFlattenListResult'; @@ -20,7 +18,6 @@ import useRowSelection from '@/hooks/useRowSelection'; import DuplicateFilesModal from './DuplicateFiles/DuplicateFilesModal'; import type { UtilityHeaderType } from '@/components/Utilities/constants'; -import type { ReleaseManagementItemType } from '@/core/react-query/release-management/types'; import type { EpisodeType } from '@/core/types/api/episode'; import type { ReleaseManagementSeriesType } from '@/core/types/api/series'; @@ -128,7 +125,7 @@ const duplicatesEpisodeFileCountColumn: UtilityHeaderType = { }; type Props = { - type: ReleaseManagementItemType; + type: 'DuplicateFiles' | 'MissingEpisodes'; setSelectedEpisodes?: (episodes: EpisodeType[]) => void; setSelectedSeriesId?: (id: number) => void; setSeriesCount: (count: number) => void; @@ -148,14 +145,28 @@ const UtilitySeriesList = ( const [selectedSeries, setSelectedSeries] = useState(0); - const seriesQuery = useReleaseManagementSeries( - type, + const duplicateFilesSeriesQuery = useDuplicateFilesSeriesQuery( + { collecting: onlyCollecting, onlyFinishedSeries, pageSize: 50 }, + type === 'DuplicateFiles', + ); + const missingEpisodesSeriesQuery = useMissingEpisodesSeriesQuery( { collecting: onlyCollecting, onlyFinishedSeries, pageSize: 50 }, + type === 'MissingEpisodes', ); + const seriesQuery = type === 'DuplicateFiles' ? duplicateFilesSeriesQuery : missingEpisodesSeriesQuery; const [series, seriesCount] = useFlattenListResult(seriesQuery.data); - const episodesQuery = useReleaseManagementSeriesEpisodes( - type, + const duplicateFilesQuery = useDuplicateFilesQuery( + selectedSeries, + { + collecting: onlyCollecting, + includeDataFrom: ['AniDB'], + includeAbsolutePaths: true, + pageSize: 50, + }, + selectedSeries > 0 && type === 'DuplicateFiles', + ); + const missingEpisodesQuery = useMissingEpisodesQuery( selectedSeries, { collecting: onlyCollecting, @@ -163,12 +174,14 @@ const UtilitySeriesList = ( includeAbsolutePaths: true, pageSize: 50, }, - selectedSeries > 0, + selectedSeries > 0 && type === 'MissingEpisodes', ); + const episodesQuery = type === 'DuplicateFiles' ? duplicateFilesQuery : missingEpisodesQuery; const [episodes, episodeCount] = useFlattenListResult(episodesQuery.data); useEffect(() => () => { - resetQueries(['release-management', 'series', 'episodes']); + resetQueries(['duplicate-files', 'series', 'episodes']); + resetQueries(['missing-episodes', 'series', 'episodes']); }, []); const [showEpisodeModal, toggleEpisodeModal, setEpisodeModal] = useToggle(false); diff --git a/src/core/react-query/duplicate-files/queries.ts b/src/core/react-query/duplicate-files/queries.ts new file mode 100644 index 000000000..eef408ecb --- /dev/null +++ b/src/core/react-query/duplicate-files/queries.ts @@ -0,0 +1,58 @@ +import { useInfiniteQuery } from '@tanstack/react-query'; + +import { axios } from '@/core/axios'; + +import type { + DuplicateFilesEpisodesRequestType, + DuplicateFilesSeriesRequestType, +} from '@/core/react-query/duplicate-files/types'; +import type { ListResultType } from '@/core/types/api'; +import type { EpisodeType } from '@/core/types/api/episode'; +import type { ReleaseManagementSeriesType } from '@/core/types/api/series'; + +export const useDuplicateFilesSeriesQuery = (params: DuplicateFilesSeriesRequestType, enabled = true) => + useInfiniteQuery>({ + queryKey: ['duplicate-files', 'series', params], + queryFn: ({ pageParam }) => + axios.get( + 'DuplicateFiles/Series', + { + params: { + ...params, + page: pageParam as number, + }, + }, + ), + initialPageParam: 1, + getNextPageParam: (lastPage, _, lastPageParam: number) => { + if (!params.pageSize || lastPage.Total / params.pageSize <= lastPageParam) return undefined; + return lastPageParam + 1; + }, + enabled, + }); + +export const useDuplicateFilesQuery = ( + seriesId: number, + params: DuplicateFilesEpisodesRequestType, + enabled = true, +) => + useInfiniteQuery>({ + queryKey: ['duplicate-files', 'series', 'episodes', seriesId, params], + queryFn: ({ pageParam }) => + axios.get( + `DuplicateFiles/Series/${seriesId}/Episodes`, + { + params: { + ...params, + page: pageParam as number, + }, + }, + ), + initialPageParam: 1, + getNextPageParam: (lastPage, _, lastPageParam: number) => { + if (!params.pageSize || lastPage.Total / params.pageSize <= lastPageParam) return undefined; + return lastPageParam + 1; + }, + enabled, + staleTime: Infinity, + }); diff --git a/src/core/react-query/duplicate-files/types.ts b/src/core/react-query/duplicate-files/types.ts new file mode 100644 index 000000000..9be6d7ad3 --- /dev/null +++ b/src/core/react-query/duplicate-files/types.ts @@ -0,0 +1,18 @@ +import type { PaginationType } from '@/core/types/api'; +import type { DataSourceType } from '@/core/types/api/common'; + +export type DuplicateFilesSeriesRequestType = { + collecting?: boolean; + ignoreVariations?: boolean; + includeDataFrom?: DataSourceType[]; + onlyFinishedSeries?: boolean; +} & PaginationType; + +export type DuplicateFilesEpisodesRequestType = { + collecting?: boolean; + ignoreVariations?: boolean; + includeAbsolutePaths?: boolean; + includeDataFrom?: DataSourceType[]; + includeFiles?: boolean; + includeMediaInfo?: boolean; +} & PaginationType; diff --git a/src/core/react-query/missing-episodes/queries.ts b/src/core/react-query/missing-episodes/queries.ts new file mode 100644 index 000000000..86689ca63 --- /dev/null +++ b/src/core/react-query/missing-episodes/queries.ts @@ -0,0 +1,58 @@ +import { useInfiniteQuery } from '@tanstack/react-query'; + +import { axios } from '@/core/axios'; + +import type { + MissingEpisodesRequestType, + MissingEpisodesSeriesRequestType, +} from '@/core/react-query/missing-episodes/types'; +import type { ListResultType } from '@/core/types/api'; +import type { EpisodeType } from '@/core/types/api/episode'; +import type { ReleaseManagementSeriesType } from '@/core/types/api/series'; + +export const useMissingEpisodesSeriesQuery = (params: MissingEpisodesSeriesRequestType, enabled = true) => + useInfiniteQuery>({ + queryKey: ['missing-episodes', 'series', params], + queryFn: ({ pageParam }) => + axios.get( + 'MissingEpisodes/Series', + { + params: { + ...params, + page: pageParam as number, + }, + }, + ), + initialPageParam: 1, + getNextPageParam: (lastPage, _, lastPageParam: number) => { + if (!params.pageSize || lastPage.Total / params.pageSize <= lastPageParam) return undefined; + return lastPageParam + 1; + }, + enabled, + }); + +export const useMissingEpisodesQuery = ( + seriesId: number, + params: MissingEpisodesRequestType, + enabled = true, +) => + useInfiniteQuery>({ + queryKey: ['missing-episodes', 'series', 'episodes', seriesId, params], + queryFn: ({ pageParam }) => + axios.get( + `MissingEpisodes/Series/${seriesId}/Episodes`, + { + params: { + ...params, + page: pageParam as number, + }, + }, + ), + initialPageParam: 1, + getNextPageParam: (lastPage, _, lastPageParam: number) => { + if (!params.pageSize || lastPage.Total / params.pageSize <= lastPageParam) return undefined; + return lastPageParam + 1; + }, + enabled, + staleTime: Infinity, + }); diff --git a/src/core/react-query/missing-episodes/types.ts b/src/core/react-query/missing-episodes/types.ts new file mode 100644 index 000000000..334348a15 --- /dev/null +++ b/src/core/react-query/missing-episodes/types.ts @@ -0,0 +1,18 @@ +import type { PaginationType } from '@/core/types/api'; +import type { DataSourceType } from '@/core/types/api/common'; + +export type MissingEpisodesSeriesRequestType = { + collecting?: boolean; + ignoreVariations?: boolean; + includeDataFrom?: DataSourceType[]; + onlyFinishedSeries?: boolean; +} & PaginationType; + +export type MissingEpisodesRequestType = { + collecting?: boolean; + ignoreVariations?: boolean; + includeAbsolutePaths?: boolean; + includeDataFrom?: DataSourceType[]; + includeFiles?: boolean; + includeMediaInfo?: boolean; +} & PaginationType; diff --git a/src/core/react-query/release-management/mutations.ts b/src/core/react-query/release-management/mutations.ts index a5cb02363..770290712 100644 --- a/src/core/react-query/release-management/mutations.ts +++ b/src/core/react-query/release-management/mutations.ts @@ -6,5 +6,5 @@ import type { ReleaseDeletionRequestType } from '@/core/react-query/release-mana export const useReleaseDeleteMutation = () => useMutation({ - mutationFn: (body: ReleaseDeletionRequestType) => axios.post('ReleaseManagement/MultipleReleases/Execute', body), + mutationFn: (body: ReleaseDeletionRequestType) => axios.post('ReleaseManagement/Execute', body), }); diff --git a/src/core/react-query/release-management/queries.ts b/src/core/react-query/release-management/queries.ts index 721785aa4..bf9c44d74 100644 --- a/src/core/react-query/release-management/queries.ts +++ b/src/core/react-query/release-management/queries.ts @@ -3,76 +3,19 @@ import { useInfiniteQuery, useQuery } from '@tanstack/react-query'; import { axios } from '@/core/axios'; import type { - MultipleReleasesSeriesRequestType, ReleaseDeletionPreviewRequestType, - ReleaseManagementItemType, - ReleaseManagementSeriesEpisodesType, ReleaseManagementSeriesRequestType, ReleaseMixMatchDeletionPreviewRequestType, } from '@/core/react-query/release-management/types'; import type { ListResultType } from '@/core/types/api'; -import type { EpisodeType } from '@/core/types/api/episode'; import type { ReleaseDeletionPreviewType, SeriesWithCandidatesType } from '@/core/types/api/release-management'; -import type { ReleaseManagementSeriesType } from '@/core/types/api/series'; -export const useReleaseManagementSeries = ( - type: ReleaseManagementItemType, - params: ReleaseManagementSeriesRequestType, -) => - useInfiniteQuery>({ - queryKey: ['release-management', 'series', type, params], - queryFn: ({ pageParam }) => - axios.get( - `ReleaseManagement/${type}/Series`, - { - params: { - ...params, - // It is supposed to infer the type from the initialPageParam property but it doesn't work - page: pageParam as number, - }, - }, - ), - initialPageParam: 1, - getNextPageParam: (lastPage, _, lastPageParam: number) => { - if (!params.pageSize || lastPage.Total / params.pageSize <= lastPageParam) return undefined; - return lastPageParam + 1; - }, - }); - -export const useReleaseManagementSeriesEpisodes = ( - type: ReleaseManagementItemType, - seriesId: number, - params: ReleaseManagementSeriesEpisodesType, - enabled = true, -) => - useInfiniteQuery>({ - queryKey: ['release-management', 'series', 'episodes', type, seriesId, params], - queryFn: ({ pageParam }) => - axios.get( - `ReleaseManagement/${type}/Series/${seriesId}/Episodes`, - { - params: { - ...params, - // It is supposed to infer the type from the initialPageParam property but it doesn't work - page: pageParam as number, - }, - }, - ), - initialPageParam: 1, - getNextPageParam: (lastPage, _, lastPageParam: number) => { - if (!params.pageSize || lastPage.Total / params.pageSize <= lastPageParam) return undefined; - return lastPageParam + 1; - }, - enabled, - staleTime: Infinity, - }); - -export const useMultipleReleaseSeriesQuery = (params: MultipleReleasesSeriesRequestType) => +export const useReleaseManagementSeriesQuery = (params: ReleaseManagementSeriesRequestType) => useInfiniteQuery>({ - queryKey: ['release-management', 'multiple-releases', 'series', params], + queryKey: ['release-management', 'series', params], queryFn: ({ pageParam }) => axios.get( - 'ReleaseManagement/MultipleReleases/Series', + 'ReleaseManagement/Series', { params: { ...params, @@ -87,12 +30,12 @@ export const useMultipleReleaseSeriesQuery = (params: MultipleReleasesSeriesRequ }, }); -export const useMultipleReleaseSeriesDetailQuery = (seriesId: number, includeVariations = false, enabled = true) => +export const useReleaseManagementSeriesDetailQuery = (seriesId: number, includeVariations = false, enabled = true) => useQuery({ - queryKey: ['release-management', 'multiple-releases', 'series', seriesId, includeVariations], + queryKey: ['release-management', 'series', seriesId, includeVariations], queryFn: () => axios.get( - `ReleaseManagement/MultipleReleases/Series/${seriesId}`, + `ReleaseManagement/Series/${seriesId}`, { params: { includeVariations } }, ), enabled: enabled && seriesId > 0, @@ -106,9 +49,9 @@ export const useReleaseDeletionPreviewQuery = ( enabled = true, ) => useQuery({ - queryKey: ['release-management', 'multiple-releases', 'preview', body, onlyFinishedSeries, includeVariations], + queryKey: ['release-management', 'preview', body, onlyFinishedSeries, includeVariations], queryFn: () => - axios.post('ReleaseManagement/MultipleReleases/Preview', body, { + axios.post('ReleaseManagement/Preview', body, { params: { includeVariations, onlyFinishedSeries }, }), enabled, @@ -120,7 +63,7 @@ export const useReleaseMixMatchDeletionPreviewQuery = ( enabled = true, ) => useQuery({ - queryKey: ['release-management', 'multiple-releases', 'preview', 'mix-match', seriesId, body], - queryFn: () => axios.post(`ReleaseManagement/MultipleReleases/Series/${seriesId}/Override`, body), + queryKey: ['release-management', 'preview', 'mix-match', seriesId, body], + queryFn: () => axios.post(`ReleaseManagement/Series/${seriesId}/Override`, body), enabled, }); diff --git a/src/core/react-query/release-management/types.ts b/src/core/react-query/release-management/types.ts index 228bbcfb5..df74292af 100644 --- a/src/core/react-query/release-management/types.ts +++ b/src/core/react-query/release-management/types.ts @@ -1,36 +1,12 @@ import type { PaginationType } from '@/core/types/api'; -import type { DataSourceType } from '@/core/types/api/common'; -export type ReleaseManagementItemType = 'DuplicateFiles' | 'MissingEpisodes'; - -export type MultipleReleasesSeriesRequestType = { +export type ReleaseManagementSeriesRequestType = { onlyFinishedSeries?: boolean; onlyWithRedundant?: boolean; includeVariations?: boolean; search?: string; } & PaginationType; -export type ReleaseManagementSeriesRequestType = { - ignoreVariations?: boolean; - includeDataFrom?: DataSourceType[]; - collecting?: boolean; - onlyFinishedSeries?: boolean; -} & PaginationType; - -export type ReleaseManagementSeriesEpisodesType = { - includeDataFrom?: DataSourceType[]; - includeFiles?: boolean; - includeMediaInfo?: boolean; - includeAbsolutePaths?: boolean; - collecting?: boolean; - ignoreVariations?: boolean; -} & PaginationType; - -export type SeriesCandidateOverride = { - seriesID: number; - preferredCandidateKey: string; -}; - export type ReleaseMixMatchDeletionPreviewRequestType = { selectedPlaceIDs: number[]; }; @@ -38,7 +14,10 @@ export type ReleaseMixMatchDeletionPreviewRequestType = { export type ReleaseDeletionPreviewRequestType = { includedSeriesIDs?: number[]; excludedSeriesIDs?: number[]; - overrides?: SeriesCandidateOverride[]; + overrides?: { + seriesID: number; + preferredCandidateKey: string; + }[]; }; export type ReleaseDeletionRequestType = { diff --git a/src/core/signalr/eventHandlers.ts b/src/core/signalr/eventHandlers.ts index 645c692d9..1dbab4c6b 100644 --- a/src/core/signalr/eventHandlers.ts +++ b/src/core/signalr/eventHandlers.ts @@ -33,8 +33,12 @@ const invalidateSeries = debounce( 1000, ); -const invalidateReleaseManagement = debounce( - () => invalidateQueries(['release-management', 'multiple-releases']), +const invalidateUtilities = debounce( + () => { + invalidateQueries(['release-management']); + invalidateQueries(['duplicate-files']); + invalidateQueries(['missing-episodes']); + }, 2000, ); @@ -47,7 +51,7 @@ export const handleEvent = (event: string, data?: SeriesUpdateEventType) => { invalidateDashboard(); invalidateFiles(); invalidateManagedFolders(); - if (event === 'FileDeleted' || event === 'FileMatched') invalidateReleaseManagement(); + if (event === 'FileDeleted' || event === 'FileMatched') invalidateUtilities(); break; case 'FileMoved': invalidateFiles(); diff --git a/src/pages/utilities/DuplicateFilesTabs/DuplicateFilesLinkedTab.tsx b/src/pages/utilities/DuplicateFilesTabs/DuplicateFilesLinkedTab.tsx index b9a2dca53..446c5438e 100644 --- a/src/pages/utilities/DuplicateFilesTabs/DuplicateFilesLinkedTab.tsx +++ b/src/pages/utilities/DuplicateFilesTabs/DuplicateFilesLinkedTab.tsx @@ -20,14 +20,14 @@ import { resetQueries } from '@/core/react-query/queryClient'; const DuplicateFilesLinkedTab = () => { const [searchParams, setSearchParams] = useSearchParams(); - const isSeriesQueryFetching = useIsFetching({ queryKey: ['release-management', 'series'] }) > 0; + const isSeriesQueryFetching = useIsFetching({ queryKey: ['duplicate-files', 'series'] }) > 0; const [seriesCount, setSeriesCount] = useState(0); const [selectedSeries, setSelectedSeries] = useState(0); const handleRefresh = () => { if (isSeriesQueryFetching) return; - resetQueries(['release-management', 'series']); + resetQueries(['duplicate-files', 'series']); }; useHotkeys('r', handleRefresh, { scopes: 'primary' }); diff --git a/src/pages/utilities/MissingEpisodes.tsx b/src/pages/utilities/MissingEpisodes.tsx index e21651c35..e889b5ae3 100644 --- a/src/pages/utilities/MissingEpisodes.tsx +++ b/src/pages/utilities/MissingEpisodes.tsx @@ -22,14 +22,14 @@ import type { EpisodeType } from '@/core/types/api/episode'; const MissingEpisodes = () => { const [searchParams, setSearchParams] = useSearchParams(); - const isSeriesQueryFetching = useIsFetching({ queryKey: ['release-management', 'series'] }) > 0; + const isSeriesQueryFetching = useIsFetching({ queryKey: ['missing-episodes', 'series'] }) > 0; const [seriesCount, setSeriesCount] = useState(0); const [selectedEpisodes, setSelectedEpisodes] = useState([]); const handleRefresh = () => { if (isSeriesQueryFetching) return; - resetQueries(['release-management', 'series']); + resetQueries(['missing-episodes', 'series']); }; useHotkeys('r', handleRefresh, { scopes: 'primary' }); @@ -59,7 +59,7 @@ const MissingEpisodes = () => { .catch(() => toast.error('One or more operations failed!')) .finally(() => { setHidePending(false); - resetQueries(['release-management']); + resetQueries(['missing-episodes']); setSelectedEpisodes([]); }); }; diff --git a/src/pages/utilities/ReleaseManagement.tsx b/src/pages/utilities/ReleaseManagement.tsx index 158a7e39f..24977e51f 100644 --- a/src/pages/utilities/ReleaseManagement.tsx +++ b/src/pages/utilities/ReleaseManagement.tsx @@ -20,8 +20,8 @@ import Checkbox from '@/components/Input/Checkbox'; import Input from '@/components/Input/Input'; import ShokoPanel from '@/components/Panels/ShokoPanel'; import ItemCount from '@/components/Utilities/ItemCount'; -import MultipleReleasesPreviewModal from '@/components/Utilities/ReleaseManagement/MultipleReleasesPreviewModal'; -import MultipleReleasesSeriesList from '@/components/Utilities/ReleaseManagement/MultipleReleasesSeriesList'; +import ReleaseManagementPreviewModal from '@/components/Utilities/ReleaseManagement/ReleaseManagementPreviewModal'; +import ReleaseManagementSeriesList from '@/components/Utilities/ReleaseManagement/ReleaseManagementSeriesList'; import MenuButton from '@/components/Utilities/Unrecognized/MenuButton'; import { resetQueries } from '@/core/react-query/queryClient'; @@ -56,13 +56,13 @@ const ReleaseManagement = () => { const [allSelected, toggleAllSelected] = useToggle(true); const [selectedSeries, setSelectedSeries] = useState([]); - const isSeriesQueryFetching = useIsFetching({ queryKey: ['release-management', 'multiple-releases', 'series'] }) > 0; + const isSeriesQueryFetching = useIsFetching({ queryKey: ['release-management', 'series'] }) > 0; const [seriesCount, setSeriesCount] = useState(0); const selectedCount = allSelected ? (seriesCount - selectedSeries.length) : selectedSeries.length; const handleRefresh = () => { if (isSeriesQueryFetching) return; - resetQueries(['release-management', 'multiple-releases']); + resetQueries(['release-management']); }; useHotkeys('r', handleRefresh, { scopes: 'primary' }); @@ -157,7 +157,7 @@ const ReleaseManagement = () => { - { /> - { async function setupEnv(isDebug) { const gitHash = childProcess.execSync("git log --pretty=format:'%h' -n 1").toString().replace(/["']/g, ''); const appVersion = pkg.version; - const minimumServerVersion = '6.0.0-dev.384'; + const minimumServerVersion = '6.0.0-dev.388'; process.env.VITE_GITHASH = gitHash; process.env.VITE_APPVERSION = appVersion;