mirror of
https://github.com/Sonarr/Sonarr
synced 2025-12-06 08:28:37 +01:00
Use react-query for tasks
This commit is contained in:
parent
565f967f7a
commit
3091f40ca8
6 changed files with 46 additions and 66 deletions
|
|
@ -1,12 +1,7 @@
|
|||
import Task from 'typings/Task';
|
||||
import AppSectionState from './AppSectionState';
|
||||
import BackupAppState from './BackupAppState';
|
||||
|
||||
export type TaskAppState = AppSectionState<Task>;
|
||||
|
||||
interface SystemAppState {
|
||||
backups: BackupAppState;
|
||||
tasks: TaskAppState;
|
||||
}
|
||||
|
||||
export default SystemAppState;
|
||||
|
|
|
|||
|
|
@ -292,7 +292,11 @@ function SignalRListener() {
|
|||
}
|
||||
|
||||
if (name === 'system/task') {
|
||||
dispatch(fetchCommands());
|
||||
if (version < 5) {
|
||||
return;
|
||||
}
|
||||
|
||||
queryClient.invalidateQueries({ queryKey: ['/system/task'] });
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,13 +18,6 @@ const backupsSection = 'system.backups';
|
|||
// State
|
||||
|
||||
export const defaultState = {
|
||||
tasks: {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
error: null,
|
||||
items: []
|
||||
},
|
||||
|
||||
backups: {
|
||||
isFetching: false,
|
||||
isPopulated: false,
|
||||
|
|
@ -40,9 +33,6 @@ export const defaultState = {
|
|||
//
|
||||
// Actions Types
|
||||
|
||||
export const FETCH_TASK = 'system/tasks/fetchTask';
|
||||
export const FETCH_TASKS = 'system/tasks/fetchTasks';
|
||||
|
||||
export const FETCH_BACKUPS = 'system/backups/fetchBackups';
|
||||
export const RESTORE_BACKUP = 'system/backups/restoreBackup';
|
||||
export const CLEAR_RESTORE_BACKUP = 'system/backups/clearRestoreBackup';
|
||||
|
|
@ -54,9 +44,6 @@ export const SHUTDOWN = 'system/shutdown';
|
|||
//
|
||||
// Action Creators
|
||||
|
||||
export const fetchTask = createThunk(FETCH_TASK);
|
||||
export const fetchTasks = createThunk(FETCH_TASKS);
|
||||
|
||||
export const fetchBackups = createThunk(FETCH_BACKUPS);
|
||||
export const restoreBackup = createThunk(RESTORE_BACKUP);
|
||||
export const clearRestoreBackup = createAction(CLEAR_RESTORE_BACKUP);
|
||||
|
|
@ -69,9 +56,6 @@ export const shutdown = createThunk(SHUTDOWN);
|
|||
// Action Handlers
|
||||
|
||||
export const actionHandlers = handleThunks({
|
||||
[FETCH_TASK]: createFetchHandler('system.tasks', '/system/task'),
|
||||
[FETCH_TASKS]: createFetchHandler('system.tasks', '/system/task'),
|
||||
|
||||
[FETCH_BACKUPS]: createFetchHandler(backupsSection, '/system/backup'),
|
||||
|
||||
[RESTORE_BACKUP]: function(getState, payload, dispatch) {
|
||||
|
|
|
|||
|
|
@ -4,10 +4,8 @@ import { useDispatch, useSelector } from 'react-redux';
|
|||
import SpinnerIconButton from 'Components/Link/SpinnerIconButton';
|
||||
import TableRowCell from 'Components/Table/Cells/TableRowCell';
|
||||
import TableRow from 'Components/Table/TableRow';
|
||||
import usePrevious from 'Helpers/Hooks/usePrevious';
|
||||
import { icons } from 'Helpers/Props';
|
||||
import { executeCommand } from 'Store/Actions/commandActions';
|
||||
import { fetchTask } from 'Store/Actions/systemActions';
|
||||
import createCommandSelector from 'Store/Selectors/createCommandSelector';
|
||||
import createUISettingsSelector from 'Store/Selectors/createUISettingsSelector';
|
||||
import { isCommandExecuting } from 'Utilities/Command';
|
||||
|
|
@ -27,20 +25,16 @@ interface ScheduledTaskRowProps {
|
|||
nextExecution: string;
|
||||
}
|
||||
|
||||
function ScheduledTaskRow(props: ScheduledTaskRowProps) {
|
||||
const {
|
||||
id,
|
||||
taskName,
|
||||
name,
|
||||
interval,
|
||||
lastExecution,
|
||||
lastStartTime,
|
||||
lastDuration,
|
||||
nextExecution,
|
||||
} = props;
|
||||
|
||||
function ScheduledTaskRow({
|
||||
taskName,
|
||||
name,
|
||||
interval,
|
||||
lastExecution,
|
||||
lastStartTime,
|
||||
lastDuration,
|
||||
nextExecution,
|
||||
}: ScheduledTaskRowProps) {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const { showRelativeDates, longDateFormat, shortDateFormat, timeFormat } =
|
||||
useSelector(createUISettingsSelector());
|
||||
const command = useSelector(createCommandSelector(taskName));
|
||||
|
|
@ -49,7 +43,6 @@ function ScheduledTaskRow(props: ScheduledTaskRowProps) {
|
|||
|
||||
const isQueued = !!(command && command.status === 'queued');
|
||||
const isExecuting = isCommandExecuting(command);
|
||||
const wasExecuting = usePrevious(isExecuting);
|
||||
const isDisabled = interval === 0;
|
||||
const executeNow = !isDisabled && moment().isAfter(nextExecution);
|
||||
const hasNextExecutionTime = !isDisabled && !executeNow;
|
||||
|
|
@ -88,21 +81,9 @@ function ScheduledTaskRow(props: ScheduledTaskRowProps) {
|
|||
]);
|
||||
|
||||
const handleExecutePress = useCallback(() => {
|
||||
dispatch(
|
||||
executeCommand({
|
||||
name: taskName,
|
||||
})
|
||||
);
|
||||
dispatch(executeCommand({ name: taskName }));
|
||||
}, [taskName, dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isExecuting && wasExecuting) {
|
||||
setTimeout(() => {
|
||||
dispatch(fetchTask({ id }));
|
||||
}, 1000);
|
||||
}
|
||||
}, [id, isExecuting, wasExecuting, dispatch]);
|
||||
|
||||
useEffect(() => {
|
||||
const interval = setInterval(() => setTime(Date.now()), 1000);
|
||||
return () => {
|
||||
|
|
|
|||
|
|
@ -1,13 +1,11 @@
|
|||
import React, { useEffect } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import AppState from 'App/State/AppState';
|
||||
import React from 'react';
|
||||
import FieldSet from 'Components/FieldSet';
|
||||
import LoadingIndicator from 'Components/Loading/LoadingIndicator';
|
||||
import Column from 'Components/Table/Column';
|
||||
import Table from 'Components/Table/Table';
|
||||
import TableBody from 'Components/Table/TableBody';
|
||||
import { fetchTasks } from 'Store/Actions/systemActions';
|
||||
import translate from 'Utilities/String/translate';
|
||||
import useTasks from '../useTasks';
|
||||
import ScheduledTaskRow from './ScheduledTaskRow';
|
||||
|
||||
const columns: Column[] = [
|
||||
|
|
@ -44,28 +42,31 @@ const columns: Column[] = [
|
|||
];
|
||||
|
||||
function ScheduledTasks() {
|
||||
const dispatch = useDispatch();
|
||||
const { isFetching, isPopulated, items } = useSelector(
|
||||
(state: AppState) => state.system.tasks
|
||||
);
|
||||
const { data: tasks, isLoading, error } = useTasks();
|
||||
|
||||
useEffect(() => {
|
||||
dispatch(fetchTasks());
|
||||
}, [dispatch]);
|
||||
if (error) {
|
||||
return (
|
||||
<FieldSet legend={translate('Scheduled')}>
|
||||
<div>Error loading tasks: {error.message}</div>
|
||||
</FieldSet>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<FieldSet legend={translate('Scheduled')}>
|
||||
{isFetching && !isPopulated && <LoadingIndicator />}
|
||||
{isLoading && <LoadingIndicator />}
|
||||
|
||||
{isPopulated && (
|
||||
{tasks.length > 0 && (
|
||||
<Table columns={columns}>
|
||||
<TableBody>
|
||||
{items.map((item) => {
|
||||
return <ScheduledTaskRow key={item.id} {...item} />;
|
||||
{tasks.map((task) => {
|
||||
return <ScheduledTaskRow key={task.id} {...task} />;
|
||||
})}
|
||||
</TableBody>
|
||||
</Table>
|
||||
)}
|
||||
|
||||
{!isLoading && tasks.length === 0 && <div>No scheduled tasks found.</div>}
|
||||
</FieldSet>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
15
frontend/src/System/Tasks/useTasks.ts
Normal file
15
frontend/src/System/Tasks/useTasks.ts
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
import useApiQuery from 'Helpers/Hooks/useApiQuery';
|
||||
import Task from 'typings/Task';
|
||||
|
||||
const useTasks = () => {
|
||||
const result = useApiQuery<Task[]>({
|
||||
path: '/system/task',
|
||||
});
|
||||
|
||||
return {
|
||||
...result,
|
||||
data: result.data ?? [],
|
||||
};
|
||||
};
|
||||
|
||||
export default useTasks;
|
||||
Loading…
Reference in a new issue