mirror of
https://github.com/jellyfin/jellyfin-web
synced 2025-03-30 19:56:21 +00:00
Migrate tasks edit page to react
This commit is contained in:
parent
e80b890bd2
commit
524d1b6574
20 changed files with 501 additions and 330 deletions
|
@ -15,6 +15,7 @@ export const ASYNC_ADMIN_ROUTES: AsyncRoute[] = [
|
|||
{ path: 'playback/trickplay', type: AppType.Dashboard },
|
||||
{ path: 'plugins/:pluginId', page: 'plugins/plugin', type: AppType.Dashboard },
|
||||
{ path: 'tasks', type: AppType.Dashboard },
|
||||
{ path: 'tasks/edit', type: AppType.Dashboard },
|
||||
{ path: 'users', type: AppType.Dashboard },
|
||||
{ path: 'users/access', type: AppType.Dashboard },
|
||||
{ path: 'users/add', type: AppType.Dashboard },
|
||||
|
|
|
@ -93,12 +93,5 @@ export const LEGACY_ADMIN_ROUTES: LegacyRoute[] = [
|
|||
controller: 'plugins/installed/index',
|
||||
view: 'plugins/installed/index.html'
|
||||
}
|
||||
}, {
|
||||
path: 'tasks/edit',
|
||||
pageProps: {
|
||||
appType: AppType.Dashboard,
|
||||
controller: 'scheduledtasks/scheduledtask',
|
||||
view: 'scheduledtasks/scheduledtask.html'
|
||||
}
|
||||
}
|
||||
];
|
||||
|
|
173
src/apps/dashboard/routes/tasks/edit.tsx
Normal file
173
src/apps/dashboard/routes/tasks/edit.tsx
Normal file
|
@ -0,0 +1,173 @@
|
|||
import React, { useCallback, useMemo, useState } from 'react';
|
||||
import Page from 'components/Page';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import Box from '@mui/material/Box';
|
||||
import Button from '@mui/material/Button';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import Typography from '@mui/material/Typography';
|
||||
import AddIcon from '@mui/icons-material/Add';
|
||||
import IconButton from '@mui/material/IconButton';
|
||||
import Tooltip from '@mui/material/Tooltip';
|
||||
import RemoveCircleIcon from '@mui/icons-material/RemoveCircle';
|
||||
import Loading from 'components/loading/LoadingComponent';
|
||||
import { MRT_ColumnDef, MRT_Table, useMaterialReactTable } from 'material-react-table';
|
||||
import type { TaskTriggerInfo } from '@jellyfin/sdk/lib/generated-client/models/task-trigger-info';
|
||||
import globalize from '../../../../lib/globalize';
|
||||
import { useTask } from 'apps/dashboard/features/tasks/api/useTask';
|
||||
import { useUpdateTask } from 'apps/dashboard/features/tasks/api/useUpdateTask';
|
||||
import ConfirmDialog from 'components/ConfirmDialog';
|
||||
import TaskTriggerCell from 'apps/dashboard/features/tasks/components/TaskTriggerCell';
|
||||
import NewTriggerForm from 'apps/dashboard/features/tasks/components/NewTriggerForm';
|
||||
|
||||
const TaskEdit = () => {
|
||||
const [ searchParams ] = useSearchParams();
|
||||
const updateTask = useUpdateTask();
|
||||
const taskId = searchParams.get('id');
|
||||
const { data: task, isLoading } = useTask({ taskId: taskId || '' });
|
||||
const [ isAddTriggerDialogOpen, setIsAddTriggerDialogOpen ] = useState(false);
|
||||
const [ isRemoveConfirmOpen, setIsRemoveConfirmOpen ] = useState(false);
|
||||
const [ pendingDeleteTrigger, setPendingDeleteTrigger ] = useState<TaskTriggerInfo | null>(null);
|
||||
|
||||
const onCloseRemoveConfirmDialog = useCallback(() => {
|
||||
setPendingDeleteTrigger(null);
|
||||
setIsRemoveConfirmOpen(false);
|
||||
}, []);
|
||||
|
||||
const onDeleteTrigger = useCallback((trigger: TaskTriggerInfo | null | undefined) => {
|
||||
if (trigger) {
|
||||
setPendingDeleteTrigger(trigger);
|
||||
setIsRemoveConfirmOpen(true);
|
||||
}
|
||||
}, []);
|
||||
|
||||
const onConfirmDelete = useCallback(() => {
|
||||
const triggersRemaining = task?.Triggers?.filter(trigger => trigger != pendingDeleteTrigger);
|
||||
|
||||
if (task?.Id && triggersRemaining) {
|
||||
updateTask.mutate({
|
||||
taskId: task.Id,
|
||||
taskTriggerInfo: triggersRemaining
|
||||
});
|
||||
setIsRemoveConfirmOpen(false);
|
||||
}
|
||||
}, [task, pendingDeleteTrigger, updateTask]);
|
||||
|
||||
const showAddTriggerDialog = useCallback(() => {
|
||||
setIsAddTriggerDialogOpen(true);
|
||||
}, []);
|
||||
|
||||
const handleNewTriggerDialogClose = useCallback(() => {
|
||||
setIsAddTriggerDialogOpen(false);
|
||||
}, []);
|
||||
|
||||
const onNewTriggerSubmit = useCallback((trigger: TaskTriggerInfo) => {
|
||||
if (task?.Triggers && task?.Id) {
|
||||
const triggers = [...task.Triggers, trigger];
|
||||
|
||||
updateTask.mutate({
|
||||
taskId: task.Id,
|
||||
taskTriggerInfo: triggers
|
||||
});
|
||||
setIsAddTriggerDialogOpen(false);
|
||||
}
|
||||
}, [task, updateTask]);
|
||||
|
||||
const columns = useMemo<MRT_ColumnDef<TaskTriggerInfo>[]>(() => [
|
||||
{
|
||||
id: 'TriggerTime',
|
||||
accessorFn: row => row,
|
||||
Cell: TaskTriggerCell,
|
||||
header: globalize.translate('LabelTime')
|
||||
}
|
||||
], []);
|
||||
|
||||
const table = useMaterialReactTable({
|
||||
columns,
|
||||
data: task?.Triggers || [],
|
||||
|
||||
enableSorting: false,
|
||||
enableFilters: false,
|
||||
enableColumnActions: false,
|
||||
enablePagination: false,
|
||||
|
||||
state: {
|
||||
isLoading
|
||||
},
|
||||
|
||||
muiTableContainerProps: {
|
||||
sx: {
|
||||
maxHeight: 'calc(100% - 7rem)' // 2 x 3.5rem for header and footer
|
||||
}
|
||||
},
|
||||
|
||||
// Custom actions
|
||||
enableRowActions: true,
|
||||
positionActionsColumn: 'last',
|
||||
displayColumnDefOptions: {
|
||||
'mrt-row-actions': {
|
||||
header: ''
|
||||
}
|
||||
},
|
||||
renderRowActions: ({ row }) => {
|
||||
return (
|
||||
<Box sx={{
|
||||
display: 'flex',
|
||||
justifyContent: 'flex-end'
|
||||
}}>
|
||||
<Tooltip disableInteractive title={globalize.translate('ButtonRemove')}>
|
||||
<IconButton
|
||||
color='error'
|
||||
// eslint-disable-next-line react/jsx-no-bind
|
||||
onClick={() => onDeleteTrigger(row.original)}
|
||||
>
|
||||
<RemoveCircleIcon />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
if (isLoading || !task) {
|
||||
return <Loading />;
|
||||
}
|
||||
|
||||
return (
|
||||
<Page
|
||||
id='scheduledTaskPage'
|
||||
className='mainAnimatedPage type-interior'
|
||||
>
|
||||
<ConfirmDialog
|
||||
open={isRemoveConfirmOpen}
|
||||
title={globalize.translate('HeaderDeleteTaskTrigger')}
|
||||
text={globalize.translate('MessageDeleteTaskTrigger')}
|
||||
onCancel={onCloseRemoveConfirmDialog}
|
||||
onConfirm={onConfirmDelete}
|
||||
confirmButtonColor='error'
|
||||
confirmButtonText={globalize.translate('ButtonRemove')}
|
||||
/>
|
||||
<NewTriggerForm
|
||||
open={isAddTriggerDialogOpen}
|
||||
title={globalize.translate('ButtonAddScheduledTaskTrigger')}
|
||||
onClose={handleNewTriggerDialogClose}
|
||||
onSubmit={onNewTriggerSubmit}
|
||||
/>
|
||||
<Box className='content-primary'>
|
||||
<Box className='readOnlyContent'>
|
||||
<Stack spacing={2}>
|
||||
<Typography variant='h2'>{task.Name}</Typography>
|
||||
<Typography variant='body1'>{task.Description}</Typography>
|
||||
<Button
|
||||
sx={{ alignSelf: 'flex-start' }}
|
||||
startIcon={<AddIcon />}
|
||||
onClick={showAddTriggerDialog}
|
||||
>{globalize.translate('ButtonAddScheduledTaskTrigger')}</Button>
|
||||
<MRT_Table table={table} />
|
||||
</Stack>
|
||||
</Box>
|
||||
</Box>
|
||||
</Page>
|
||||
);
|
||||
};
|
||||
|
||||
export default TaskEdit;
|
|
@ -3,10 +3,10 @@ import Page from 'components/Page';
|
|||
import globalize from 'lib/globalize';
|
||||
import Box from '@mui/material/Box';
|
||||
import Stack from '@mui/material/Stack';
|
||||
import { QUERY_KEY, useTasks } from '../../features/scheduledtasks/api/useTasks';
|
||||
import { getCategories, getTasksByCategory } from '../../features/scheduledtasks/utils/tasks';
|
||||
import { QUERY_KEY, useTasks } from '../../features/tasks/api/useTasks';
|
||||
import { getCategories, getTasksByCategory } from '../../features/tasks/utils/tasks';
|
||||
import Loading from 'components/loading/LoadingComponent';
|
||||
import Tasks from '../../features/scheduledtasks/components/Tasks';
|
||||
import Tasks from '../../features/tasks/components/Tasks';
|
||||
import type { TaskInfo } from '@jellyfin/sdk/lib/generated-client/models/task-info';
|
||||
import { SessionMessageType } from '@jellyfin/sdk/lib/generated-client/models/session-message-type';
|
||||
import serverNotifications from 'scripts/serverNotifications';
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue