2022-11-25 20:25:03 +00:00
|
|
|
import { useState } from 'react';
|
2020-04-10 17:46:00 +00:00
|
|
|
import { Schedule, Task } from '@/api/server/schedules/getServerSchedules';
|
2020-03-18 06:33:53 +00:00
|
|
|
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
|
2021-05-01 18:24:18 +00:00
|
|
|
import {
|
|
|
|
faArrowCircleDown,
|
|
|
|
faClock,
|
|
|
|
faCode,
|
|
|
|
faFileArchive,
|
|
|
|
faPencilAlt,
|
|
|
|
faToggleOn,
|
|
|
|
faTrashAlt,
|
|
|
|
} from '@fortawesome/free-solid-svg-icons';
|
2020-03-19 04:08:32 +00:00
|
|
|
import deleteScheduleTask from '@/api/server/schedules/deleteScheduleTask';
|
|
|
|
import { httpErrorToHuman } from '@/api/http';
|
|
|
|
import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
|
2020-03-19 05:28:32 +00:00
|
|
|
import TaskDetailsModal from '@/components/server/schedules/TaskDetailsModal';
|
2020-03-30 05:20:27 +00:00
|
|
|
import Can from '@/components/elements/Can';
|
2020-04-10 17:46:00 +00:00
|
|
|
import useFlash from '@/plugins/useFlash';
|
|
|
|
import { ServerContext } from '@/state/server';
|
2020-07-05 00:00:19 +00:00
|
|
|
import tw from 'twin.macro';
|
|
|
|
import ConfirmationModal from '@/components/elements/ConfirmationModal';
|
2020-10-15 03:13:36 +00:00
|
|
|
import Icon from '@/components/elements/Icon';
|
2020-03-18 06:33:53 +00:00
|
|
|
|
|
|
|
interface Props {
|
2020-04-10 17:46:00 +00:00
|
|
|
schedule: Schedule;
|
2020-03-18 06:33:53 +00:00
|
|
|
task: Task;
|
|
|
|
}
|
|
|
|
|
2022-06-26 19:13:52 +00:00
|
|
|
const getActionDetails = (action: string): [string, any] => {
|
2020-06-19 04:00:04 +00:00
|
|
|
switch (action) {
|
2020-07-05 00:00:19 +00:00
|
|
|
case 'command':
|
2022-06-26 19:13:52 +00:00
|
|
|
return ['Send Command', faCode];
|
2020-07-05 00:00:19 +00:00
|
|
|
case 'power':
|
2022-06-26 19:13:52 +00:00
|
|
|
return ['Send Power Action', faToggleOn];
|
2020-07-05 00:00:19 +00:00
|
|
|
case 'backup':
|
2022-06-26 19:13:52 +00:00
|
|
|
return ['Create Backup', faFileArchive];
|
2020-07-05 00:00:19 +00:00
|
|
|
default:
|
2022-06-26 19:13:52 +00:00
|
|
|
return ['Unknown Action', faCode];
|
2020-06-19 04:00:04 +00:00
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2020-04-10 17:46:00 +00:00
|
|
|
export default ({ schedule, task }: Props) => {
|
2022-11-25 20:25:03 +00:00
|
|
|
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid);
|
2020-04-10 17:46:00 +00:00
|
|
|
const { clearFlashes, addError } = useFlash();
|
2022-06-26 19:13:52 +00:00
|
|
|
const [visible, setVisible] = useState(false);
|
|
|
|
const [isLoading, setIsLoading] = useState(false);
|
|
|
|
const [isEditing, setIsEditing] = useState(false);
|
2022-11-25 20:25:03 +00:00
|
|
|
const appendSchedule = ServerContext.useStoreActions(actions => actions.schedules.appendSchedule);
|
2020-03-19 04:08:32 +00:00
|
|
|
|
|
|
|
const onConfirmDeletion = () => {
|
|
|
|
setIsLoading(true);
|
|
|
|
clearFlashes('schedules');
|
2020-04-10 17:46:00 +00:00
|
|
|
deleteScheduleTask(uuid, schedule.id, task.id)
|
2022-06-26 19:13:52 +00:00
|
|
|
.then(() =>
|
|
|
|
appendSchedule({
|
|
|
|
...schedule,
|
2022-11-25 20:25:03 +00:00
|
|
|
tasks: schedule.tasks.filter(t => t.id !== task.id),
|
|
|
|
}),
|
2022-06-26 19:13:52 +00:00
|
|
|
)
|
2022-11-25 20:25:03 +00:00
|
|
|
.catch(error => {
|
2020-03-19 04:08:32 +00:00
|
|
|
console.error(error);
|
|
|
|
setIsLoading(false);
|
|
|
|
addError({ message: httpErrorToHuman(error), key: 'schedules' });
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2022-06-26 19:13:52 +00:00
|
|
|
const [title, icon] = getActionDetails(task.action);
|
2020-06-19 04:00:04 +00:00
|
|
|
|
2020-03-18 06:33:53 +00:00
|
|
|
return (
|
2020-10-15 03:13:36 +00:00
|
|
|
<div css={tw`sm:flex items-center p-3 sm:p-6 border-b border-neutral-800`}>
|
2022-06-26 19:13:52 +00:00
|
|
|
<SpinnerOverlay visible={isLoading} fixed size={'large'} />
|
2021-05-01 18:24:18 +00:00
|
|
|
<TaskDetailsModal
|
2020-04-10 17:46:00 +00:00
|
|
|
schedule={schedule}
|
2020-03-19 05:28:32 +00:00
|
|
|
task={task}
|
2021-05-01 18:24:18 +00:00
|
|
|
visible={isEditing}
|
|
|
|
onModalDismissed={() => setIsEditing(false)}
|
|
|
|
/>
|
2020-07-05 00:00:19 +00:00
|
|
|
<ConfirmationModal
|
|
|
|
title={'Confirm task deletion'}
|
|
|
|
buttonText={'Delete Task'}
|
|
|
|
onConfirmed={onConfirmDeletion}
|
2020-03-19 04:08:32 +00:00
|
|
|
visible={visible}
|
2020-08-18 04:35:11 +00:00
|
|
|
onModalDismissed={() => setVisible(false)}
|
2020-07-05 00:00:19 +00:00
|
|
|
>
|
|
|
|
Are you sure you want to delete this task? This action cannot be undone.
|
|
|
|
</ConfirmationModal>
|
2022-06-26 19:13:52 +00:00
|
|
|
<FontAwesomeIcon icon={icon} css={tw`text-lg text-white hidden md:block`} />
|
2020-10-15 03:13:36 +00:00
|
|
|
<div css={tw`flex-none sm:flex-1 w-full sm:w-auto overflow-x-auto`}>
|
2022-06-26 19:13:52 +00:00
|
|
|
<p css={tw`md:ml-6 text-neutral-200 uppercase text-sm`}>{title}</p>
|
|
|
|
{task.payload && (
|
|
|
|
<div css={tw`md:ml-6 mt-2`}>
|
|
|
|
{task.action === 'backup' && (
|
|
|
|
<p css={tw`text-xs uppercase text-neutral-400 mb-1`}>Ignoring files & folders:</p>
|
|
|
|
)}
|
|
|
|
<div
|
|
|
|
css={tw`font-mono bg-neutral-800 rounded py-1 px-2 text-sm w-auto inline-block whitespace-pre-wrap break-all`}
|
|
|
|
>
|
|
|
|
{task.payload}
|
|
|
|
</div>
|
2020-06-19 04:00:04 +00:00
|
|
|
</div>
|
2022-06-26 19:13:52 +00:00
|
|
|
)}
|
2020-03-18 06:33:53 +00:00
|
|
|
</div>
|
2020-10-15 03:13:36 +00:00
|
|
|
<div css={tw`mt-3 sm:mt-0 flex items-center w-full sm:w-auto`}>
|
2022-06-26 19:13:52 +00:00
|
|
|
{task.continueOnFailure && (
|
|
|
|
<div css={tw`mr-6`}>
|
|
|
|
<div css={tw`flex items-center px-2 py-1 bg-yellow-500 text-yellow-800 text-sm rounded-full`}>
|
|
|
|
<Icon icon={faArrowCircleDown} css={tw`w-3 h-3 mr-2`} />
|
|
|
|
Continues on Failure
|
|
|
|
</div>
|
2021-05-01 18:24:18 +00:00
|
|
|
</div>
|
2022-06-26 19:13:52 +00:00
|
|
|
)}
|
|
|
|
{task.sequenceId > 1 && task.timeOffset > 0 && (
|
|
|
|
<div css={tw`mr-6`}>
|
|
|
|
<div css={tw`flex items-center px-2 py-1 bg-neutral-500 text-sm rounded-full`}>
|
|
|
|
<Icon icon={faClock} css={tw`w-3 h-3 mr-2`} />
|
|
|
|
{task.timeOffset}s later
|
|
|
|
</div>
|
2020-10-15 03:13:36 +00:00
|
|
|
</div>
|
2022-06-26 19:13:52 +00:00
|
|
|
)}
|
2020-10-15 03:13:36 +00:00
|
|
|
<Can action={'schedule.update'}>
|
|
|
|
<button
|
|
|
|
type={'button'}
|
|
|
|
aria-label={'Edit scheduled task'}
|
|
|
|
css={tw`block text-sm p-2 text-neutral-500 hover:text-neutral-100 transition-colors duration-150 mr-4 ml-auto sm:ml-0`}
|
|
|
|
onClick={() => setIsEditing(true)}
|
|
|
|
>
|
2022-06-26 19:13:52 +00:00
|
|
|
<FontAwesomeIcon icon={faPencilAlt} />
|
2020-10-15 03:13:36 +00:00
|
|
|
</button>
|
|
|
|
</Can>
|
|
|
|
<Can action={'schedule.update'}>
|
|
|
|
<button
|
|
|
|
type={'button'}
|
|
|
|
aria-label={'Delete scheduled task'}
|
|
|
|
css={tw`block text-sm p-2 text-neutral-500 hover:text-red-600 transition-colors duration-150`}
|
|
|
|
onClick={() => setVisible(true)}
|
|
|
|
>
|
2022-06-26 19:13:52 +00:00
|
|
|
<FontAwesomeIcon icon={faTrashAlt} />
|
2020-10-15 03:13:36 +00:00
|
|
|
</button>
|
|
|
|
</Can>
|
2020-03-18 06:33:53 +00:00
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
);
|
|
|
|
};
|