1
0
mirror of https://github.com/Sonarr/Sonarr.git synced 2026-04-23 22:25:56 -04:00

Use react-query for root folders

New: Add tooltip for empty root folders
Closes #8196
This commit is contained in:
Mark McDowall
2025-11-24 21:25:47 -08:00
parent 449caa12e3
commit 7a5157df29
23 changed files with 267 additions and 274 deletions
@@ -12,8 +12,8 @@ import LoadingIndicator from 'Components/Loading/LoadingIndicator';
import PageContent from 'Components/Page/PageContent';
import PageContentBody from 'Components/Page/PageContentBody';
import { kinds } from 'Helpers/Props';
import useRootFolders, { useRootFolder } from 'RootFolder/useRootFolders';
import { clearImportSeries } from 'Store/Actions/importSeriesActions';
import { fetchRootFolders } from 'Store/Actions/rootFolderActions';
import translate from 'Utilities/String/translate';
import ImportSeriesFooter from './ImportSeriesFooter';
import ImportSeriesTable from './ImportSeriesTable';
@@ -27,10 +27,12 @@ function ImportSeries() {
const {
isFetching: rootFoldersFetching,
isPopulated: rootFoldersPopulated,
isFetched: rootFoldersFetched,
error: rootFoldersError,
items: rootFolders,
} = useSelector((state: AppState) => state.rootFolders);
data: rootFolders,
} = useRootFolders();
useRootFolder(rootFolderId, false);
const { path, unmappedFolders } = useMemo(() => {
const rootFolder = rootFolders.find((r) => r.id === rootFolderId);
@@ -65,8 +67,6 @@ function ImportSeries() {
}, [unmappedFolders]);
useEffect(() => {
dispatch(fetchRootFolders({ id: rootFolderId, timeout: false }));
return () => {
dispatch(clearImportSeries());
};
@@ -95,7 +95,7 @@ function ImportSeries() {
{!rootFoldersError &&
!rootFoldersFetching &&
rootFoldersPopulated &&
rootFoldersFetched &&
!unmappedFolders.length ? (
<Alert kind={kinds.INFO}>
{translate('AllSeriesInRootFolderHaveBeenImported', { path })}
@@ -104,7 +104,7 @@ function ImportSeries() {
{!rootFoldersError &&
!rootFoldersFetching &&
rootFoldersPopulated &&
rootFoldersFetched &&
!!unmappedFolders.length &&
scrollerRef.current ? (
<ImportSeriesTable
@@ -1,6 +1,4 @@
import React, { useCallback, useEffect, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux';
import AppState from 'App/State/AppState';
import Alert from 'Components/Alert';
import FieldSet from 'Components/FieldSet';
import FileBrowserModal from 'Components/FileBrowser/FileBrowserModal';
@@ -13,28 +11,24 @@ import PageContentBody from 'Components/Page/PageContentBody';
import usePrevious from 'Helpers/Hooks/usePrevious';
import { icons, kinds, sizes } from 'Helpers/Props';
import RootFolders from 'RootFolder/RootFolders';
import {
addRootFolder,
fetchRootFolders,
} from 'Store/Actions/rootFolderActions';
import useRootFolders, { useAddRootFolder } from 'RootFolder/useRootFolders';
import { useIsWindows } from 'System/Status/useSystemStatus';
import { InputChanged } from 'typings/inputs';
import translate from 'Utilities/String/translate';
import styles from './ImportSeriesSelectFolder.css';
function ImportSeriesSelectFolder() {
const dispatch = useDispatch();
const { isFetching, isPopulated, isSaving, error, saveError, items } =
useSelector((state: AppState) => state.rootFolders);
const { isFetching, isFetched, error, data } = useRootFolders();
const { addRootFolder, isAdding, addError } = useAddRootFolder();
const isWindows = useIsWindows();
const [isAddNewRootFolderModalOpen, setIsAddNewRootFolderModalOpen] =
useState(false);
const wasSaving = usePrevious(isSaving);
const wasAdding = usePrevious(isAdding);
const hasRootFolders = items.length > 0;
const hasRootFolders = data.length > 0;
const goodFolderExample = isWindows ? 'C:\\tv shows' : '/tv shows';
const badFolderExample = isWindows
? 'C:\\tv shows\\the simpsons'
@@ -50,18 +44,14 @@ function ImportSeriesSelectFolder() {
const handleNewRootFolderSelect = useCallback(
({ value }: InputChanged<string>) => {
dispatch(addRootFolder({ path: value }));
addRootFolder({ path: value });
},
[dispatch]
[addRootFolder]
);
useEffect(() => {
dispatch(fetchRootFolders());
}, [dispatch]);
useEffect(() => {
if (!isSaving && wasSaving && !saveError) {
items.reduce((acc, item) => {
if (!isAdding && wasAdding && !addError) {
data.reduce((acc, item) => {
if (item.id > acc) {
return item.id;
}
@@ -69,18 +59,18 @@ function ImportSeriesSelectFolder() {
return acc;
}, 0);
}
}, [isSaving, wasSaving, saveError, items]);
}, [isAdding, wasAdding, addError, data]);
return (
<PageContent title={translate('ImportSeries')}>
<PageContentBody>
{isFetching && !isPopulated ? <LoadingIndicator /> : null}
{isFetching && !isFetched ? <LoadingIndicator /> : null}
{!isFetching && error ? (
<Alert kind={kinds.DANGER}>{translate('RootFoldersLoadError')}</Alert>
) : null}
{!error && isPopulated && (
{!error && isFetched && (
<div>
<div className={styles.header}>
{translate('LibraryImportSeriesHeader')}
@@ -118,17 +108,17 @@ function ImportSeriesSelectFolder() {
</div>
) : null}
{!isSaving && saveError ? (
{!isAdding && addError ? (
<Alert className={styles.addErrorAlert} kind={kinds.DANGER}>
{translate('AddRootFolderError')}
<ul>
{Array.isArray(saveError.responseJSON) ? (
saveError.responseJSON.map((e, index) => {
{Array.isArray(addError.statusBody) ? (
addError.statusBody.map((e, index) => {
return <li key={index}>{e.errorMessage}</li>;
})
) : (
<li>{JSON.stringify(saveError.responseJSON)}</li>
<li>{JSON.stringify(addError.statusBody)}</li>
)}
</ul>
</Alert>