Clean up most of the schedules code to use server context

This commit is contained in:
Dane Everitt 2020-04-10 10:46:00 -07:00
parent 07d19ad326
commit 0ebf842757
No known key found for this signature in database
GPG Key ID: EEA66103B3D71F53
9 changed files with 132 additions and 92 deletions

View File

@ -6,14 +6,13 @@ import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
import Switch from '@/components/elements/Switch'; import Switch from '@/components/elements/Switch';
import createOrUpdateSchedule from '@/api/server/schedules/createOrUpdateSchedule'; import createOrUpdateSchedule from '@/api/server/schedules/createOrUpdateSchedule';
import { ServerContext } from '@/state/server'; import { ServerContext } from '@/state/server';
import { Actions, useStoreActions } from 'easy-peasy';
import { ApplicationStore } from '@/state';
import { httpErrorToHuman } from '@/api/http'; import { httpErrorToHuman } from '@/api/http';
import FlashMessageRender from '@/components/FlashMessageRender'; import FlashMessageRender from '@/components/FlashMessageRender';
import useServer from '@/plugins/useServer';
import useFlash from '@/plugins/useFlash';
type Props = { type Props = {
schedule?: Schedule; schedule?: Schedule;
onScheduleUpdated: (schedule: Schedule) => void;
} & RequiredModalProps; } & RequiredModalProps;
interface Values { interface Values {
@ -73,11 +72,13 @@ const EditScheduleModal = ({ schedule, ...props }: Omit<Props, 'onScheduleUpdate
); );
}; };
export default ({ schedule, onScheduleUpdated, visible, ...props }: Props) => { export default ({ schedule, visible, ...props }: Props) => {
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid); const { uuid } = useServer();
const { addError, clearFlashes } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes); const { addError, clearFlashes } = useFlash();
const [ modalVisible, setModalVisible ] = useState(visible); const [ modalVisible, setModalVisible ] = useState(visible);
const appendSchedule = ServerContext.useStoreActions(actions => actions.schedules.appendSchedule);
useEffect(() => { useEffect(() => {
setModalVisible(visible); setModalVisible(visible);
clearFlashes('schedule:edit'); clearFlashes('schedule:edit');
@ -98,7 +99,7 @@ export default ({ schedule, onScheduleUpdated, visible, ...props }: Props) => {
}) })
.then(schedule => { .then(schedule => {
setSubmitting(false); setSubmitting(false);
onScheduleUpdated(schedule); appendSchedule(schedule);
setModalVisible(false); setModalVisible(false);
}) })
.catch(error => { .catch(error => {

View File

@ -1,24 +1,20 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Task } from '@/api/server/schedules/getServerSchedules'; import { Schedule } from '@/api/server/schedules/getServerSchedules';
import TaskDetailsModal from '@/components/server/schedules/TaskDetailsModal'; import TaskDetailsModal from '@/components/server/schedules/TaskDetailsModal';
interface Props { interface Props {
scheduleId: number; schedule: Schedule;
onTaskAdded: (task: Task) => void;
} }
export default ({ scheduleId, onTaskAdded }: Props) => { export default ({ schedule }: Props) => {
const [ visible, setVisible ] = useState(false); const [ visible, setVisible ] = useState(false);
return ( return (
<> <>
{visible && {visible &&
<TaskDetailsModal <TaskDetailsModal
scheduleId={scheduleId} schedule={schedule}
onDismissed={task => { onDismissed={() => setVisible(false)}
task && onTaskAdded(task);
setVisible(false);
}}
/> />
} }
<button className={'btn btn-primary btn-sm'} onClick={() => setVisible(true)}> <button className={'btn btn-primary btn-sm'} onClick={() => setVisible(true)}>

View File

@ -1,4 +1,4 @@
import React, { useMemo, useState } from 'react'; import React, { useEffect, useMemo, useState } from 'react';
import getServerSchedules, { Schedule } from '@/api/server/schedules/getServerSchedules'; import getServerSchedules, { Schedule } from '@/api/server/schedules/getServerSchedules';
import { ServerContext } from '@/state/server'; import { ServerContext } from '@/state/server';
import Spinner from '@/components/elements/Spinner'; import Spinner from '@/components/elements/Spinner';
@ -10,27 +10,35 @@ import { Actions, useStoreActions } from 'easy-peasy';
import { ApplicationStore } from '@/state'; import { ApplicationStore } from '@/state';
import EditScheduleModal from '@/components/server/schedules/EditScheduleModal'; import EditScheduleModal from '@/components/server/schedules/EditScheduleModal';
import Can from '@/components/elements/Can'; import Can from '@/components/elements/Can';
import useServer from '@/plugins/useServer';
import useFlash from '@/plugins/useFlash';
import ListRefreshIndicator from '@/components/elements/ListRefreshIndicator';
export default ({ match, history }: RouteComponentProps) => { export default ({ match, history }: RouteComponentProps) => {
const { uuid } = ServerContext.useStoreState(state => state.server.data!); const { uuid } = useServer();
const [ schedules, setSchedules ] = useState<Schedule[] | null>(null); const { clearFlashes, addError } = useFlash();
const [ loading, setLoading ] = useState(true);
const [ visible, setVisible ] = useState(false); const [ visible, setVisible ] = useState(false);
const { clearFlashes, addError } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
useMemo(() => { const schedules = ServerContext.useStoreState(state => state.schedules.data);
const setSchedules = ServerContext.useStoreActions(actions => actions.schedules.setSchedules);
useEffect(() => {
clearFlashes('schedules'); clearFlashes('schedules');
getServerSchedules(uuid) getServerSchedules(uuid)
.then(schedules => setSchedules(schedules)) .then(schedules => setSchedules(schedules))
.catch(error => { .catch(error => {
addError({ message: httpErrorToHuman(error), key: 'schedules' }); addError({ message: httpErrorToHuman(error), key: 'schedules' });
console.error(error); console.error(error);
}); })
}, [ setSchedules ]); .then(() => setLoading(false));
}, []);
return ( return (
<div className={'my-10 mb-6'}> <div className={'my-10 mb-6'}>
<FlashMessageRender byKey={'schedules'} className={'mb-4'}/> <FlashMessageRender byKey={'schedules'} className={'mb-4'}/>
{!schedules ? <ListRefreshIndicator visible={loading}/>
{(!schedules.length && loading) ?
<Spinner size={'large'} centered={true}/> <Spinner size={'large'} centered={true}/>
: :
<> <>
@ -59,7 +67,6 @@ export default ({ match, history }: RouteComponentProps) => {
{visible && <EditScheduleModal {visible && <EditScheduleModal
appear={true} appear={true}
visible={true} visible={true}
onScheduleUpdated={schedule => setSchedules(s => [ ...(s || []), schedule ])}
onDismissed={() => setVisible(false)} onDismissed={() => setVisible(false)}
/>} />}
<button <button

View File

@ -2,11 +2,8 @@ import React, { useEffect, useState } from 'react';
import { RouteComponentProps } from 'react-router-dom'; import { RouteComponentProps } from 'react-router-dom';
import { Schedule } from '@/api/server/schedules/getServerSchedules'; import { Schedule } from '@/api/server/schedules/getServerSchedules';
import getServerSchedule from '@/api/server/schedules/getServerSchedule'; import getServerSchedule from '@/api/server/schedules/getServerSchedule';
import { ServerContext } from '@/state/server';
import Spinner from '@/components/elements/Spinner'; import Spinner from '@/components/elements/Spinner';
import FlashMessageRender from '@/components/FlashMessageRender'; import FlashMessageRender from '@/components/FlashMessageRender';
import { Actions, useStoreActions } from 'easy-peasy';
import { ApplicationStore } from '@/state';
import { httpErrorToHuman } from '@/api/http'; import { httpErrorToHuman } from '@/api/http';
import ScheduleRow from '@/components/server/schedules/ScheduleRow'; import ScheduleRow from '@/components/server/schedules/ScheduleRow';
import ScheduleTaskRow from '@/components/server/schedules/ScheduleTaskRow'; import ScheduleTaskRow from '@/components/server/schedules/ScheduleTaskRow';
@ -14,6 +11,9 @@ import EditScheduleModal from '@/components/server/schedules/EditScheduleModal';
import NewTaskButton from '@/components/server/schedules/NewTaskButton'; import NewTaskButton from '@/components/server/schedules/NewTaskButton';
import DeleteScheduleButton from '@/components/server/schedules/DeleteScheduleButton'; import DeleteScheduleButton from '@/components/server/schedules/DeleteScheduleButton';
import Can from '@/components/elements/Can'; import Can from '@/components/elements/Can';
import useServer from '@/plugins/useServer';
import useFlash from '@/plugins/useFlash';
import { ServerContext } from '@/state/server';
interface Params { interface Params {
id: string; id: string;
@ -24,11 +24,13 @@ interface State {
} }
export default ({ match, history, location: { state } }: RouteComponentProps<Params, {}, State>) => { export default ({ match, history, location: { state } }: RouteComponentProps<Params, {}, State>) => {
const { id, uuid } = ServerContext.useStoreState(state => state.server.data!); const { id, uuid } = useServer();
const { clearFlashes, addError } = useFlash();
const [ isLoading, setIsLoading ] = useState(true); const [ isLoading, setIsLoading ] = useState(true);
const [ showEditModal, setShowEditModal ] = useState(false); const [ showEditModal, setShowEditModal ] = useState(false);
const [ schedule, setSchedule ] = useState<Schedule | undefined>(state?.schedule);
const { clearFlashes, addError } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes); const schedule = ServerContext.useStoreState(st => st.schedules.data.find(s => s.id === state.schedule?.id), [ match ]);
const appendSchedule = ServerContext.useStoreActions(actions => actions.schedules.appendSchedule);
useEffect(() => { useEffect(() => {
if (schedule?.id === Number(match.params.id)) { if (schedule?.id === Number(match.params.id)) {
@ -38,13 +40,13 @@ export default ({ match, history, location: { state } }: RouteComponentProps<Par
clearFlashes('schedules'); clearFlashes('schedules');
getServerSchedule(uuid, Number(match.params.id)) getServerSchedule(uuid, Number(match.params.id))
.then(schedule => setSchedule(schedule)) .then(schedule => appendSchedule(schedule))
.catch(error => { .catch(error => {
console.error(error); console.error(error);
addError({ message: httpErrorToHuman(error), key: 'schedules' }); addError({ message: httpErrorToHuman(error), key: 'schedules' });
}) })
.then(() => setIsLoading(false)); .then(() => setIsLoading(false));
}, [ schedule, match ]); }, [ match ]);
return ( return (
<div className={'my-10 mb-6'}> <div className={'my-10 mb-6'}>
@ -59,7 +61,6 @@ export default ({ match, history, location: { state } }: RouteComponentProps<Par
<EditScheduleModal <EditScheduleModal
visible={showEditModal} visible={showEditModal}
schedule={schedule} schedule={schedule}
onScheduleUpdated={schedule => setSchedule(schedule)}
onDismissed={() => setShowEditModal(false)} onDismissed={() => setShowEditModal(false)}
/> />
<div className={'flex items-center mt-8 mb-4'}> <div className={'flex items-center mt-8 mb-4'}>
@ -67,23 +68,13 @@ export default ({ match, history, location: { state } }: RouteComponentProps<Par
<h2>Configured Tasks</h2> <h2>Configured Tasks</h2>
</div> </div>
</div> </div>
{schedule?.tasks.length > 0 ? {schedule.tasks.length > 0 ?
<> <>
{ {
schedule.tasks schedule.tasks
.sort((a, b) => a.sequenceId - b.sequenceId) .sort((a, b) => a.sequenceId - b.sequenceId)
.map(task => ( .map(task => (
<ScheduleTaskRow <ScheduleTaskRow key={task.id} task={task} schedule={schedule}/>
key={task.id}
task={task}
schedule={schedule.id}
onTaskUpdated={task => setSchedule(s => ({
...s!, tasks: s!.tasks.map(t => t.id === task.id ? task : t),
}))}
onTaskRemoved={() => setSchedule(s => ({
...s!, tasks: s!.tasks.filter(t => t.id !== task.id),
}))}
/>
)) ))
} }
{schedule.tasks.length > 1 && {schedule.tasks.length > 1 &&
@ -108,12 +99,7 @@ export default ({ match, history, location: { state } }: RouteComponentProps<Par
<button className={'btn btn-primary btn-sm mr-4'} onClick={() => setShowEditModal(true)}> <button className={'btn btn-primary btn-sm mr-4'} onClick={() => setShowEditModal(true)}>
Edit Edit
</button> </button>
<NewTaskButton <NewTaskButton schedule={schedule}/>
scheduleId={schedule.id}
onTaskAdded={task => setSchedule(s => ({
...s!, tasks: [ ...s!.tasks, task ],
}))}
/>
</Can> </Can>
</div> </div>
</> </>

View File

@ -1,39 +1,41 @@
import React, { useState } from 'react'; import React, { useState } from 'react';
import { Task } from '@/api/server/schedules/getServerSchedules'; import { Schedule, Task } from '@/api/server/schedules/getServerSchedules';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faTrashAlt } from '@fortawesome/free-solid-svg-icons/faTrashAlt'; import { faTrashAlt } from '@fortawesome/free-solid-svg-icons/faTrashAlt';
import { faCode } from '@fortawesome/free-solid-svg-icons/faCode'; import { faCode } from '@fortawesome/free-solid-svg-icons/faCode';
import { faToggleOn } from '@fortawesome/free-solid-svg-icons/faToggleOn'; import { faToggleOn } from '@fortawesome/free-solid-svg-icons/faToggleOn';
import ConfirmTaskDeletionModal from '@/components/server/schedules/ConfirmTaskDeletionModal'; import ConfirmTaskDeletionModal from '@/components/server/schedules/ConfirmTaskDeletionModal';
import { ServerContext } from '@/state/server';
import { Actions, useStoreActions } from 'easy-peasy';
import { ApplicationStore } from '@/state';
import deleteScheduleTask from '@/api/server/schedules/deleteScheduleTask'; import deleteScheduleTask from '@/api/server/schedules/deleteScheduleTask';
import { httpErrorToHuman } from '@/api/http'; import { httpErrorToHuman } from '@/api/http';
import SpinnerOverlay from '@/components/elements/SpinnerOverlay'; import SpinnerOverlay from '@/components/elements/SpinnerOverlay';
import TaskDetailsModal from '@/components/server/schedules/TaskDetailsModal'; import TaskDetailsModal from '@/components/server/schedules/TaskDetailsModal';
import { faPencilAlt } from '@fortawesome/free-solid-svg-icons/faPencilAlt'; import { faPencilAlt } from '@fortawesome/free-solid-svg-icons/faPencilAlt';
import Can from '@/components/elements/Can'; import Can from '@/components/elements/Can';
import useServer from '@/plugins/useServer';
import useFlash from '@/plugins/useFlash';
import { ServerContext } from '@/state/server';
interface Props { interface Props {
schedule: number; schedule: Schedule;
task: Task; task: Task;
onTaskUpdated: (task: Task) => void;
onTaskRemoved: () => void;
} }
export default ({ schedule, task, onTaskUpdated, onTaskRemoved }: Props) => { export default ({ schedule, task }: Props) => {
const { uuid } = useServer();
const { clearFlashes, addError } = useFlash();
const [ visible, setVisible ] = useState(false); const [ visible, setVisible ] = useState(false);
const [ isLoading, setIsLoading ] = useState(false); const [ isLoading, setIsLoading ] = useState(false);
const [ isEditing, setIsEditing ] = useState(false); const [ isEditing, setIsEditing ] = useState(false);
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid); const appendSchedule = ServerContext.useStoreActions(actions => actions.schedules.appendSchedule);
const { clearFlashes, addError } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
const onConfirmDeletion = () => { const onConfirmDeletion = () => {
setIsLoading(true); setIsLoading(true);
clearFlashes('schedules'); clearFlashes('schedules');
deleteScheduleTask(uuid, schedule, task.id) deleteScheduleTask(uuid, schedule.id, task.id)
.then(() => onTaskRemoved()) .then(() => appendSchedule({
...schedule,
tasks: schedule.tasks.filter(t => t.id !== task.id),
}))
.catch(error => { .catch(error => {
console.error(error); console.error(error);
setIsLoading(false); setIsLoading(false);
@ -45,12 +47,9 @@ export default ({ schedule, task, onTaskUpdated, onTaskRemoved }: Props) => {
<div className={'flex items-center bg-neutral-700 border border-neutral-600 mb-2 px-6 py-4 rounded'}> <div className={'flex items-center bg-neutral-700 border border-neutral-600 mb-2 px-6 py-4 rounded'}>
<SpinnerOverlay visible={isLoading} fixed={true} size={'large'}/> <SpinnerOverlay visible={isLoading} fixed={true} size={'large'}/>
{isEditing && <TaskDetailsModal {isEditing && <TaskDetailsModal
scheduleId={schedule} schedule={schedule}
task={task} task={task}
onDismissed={task => { onDismissed={() => setIsEditing(false)}
task && onTaskUpdated(task);
setIsEditing(false);
}}
/>} />}
<ConfirmTaskDeletionModal <ConfirmTaskDeletionModal
visible={visible} visible={visible}

View File

@ -1,22 +1,22 @@
import React, { useEffect } from 'react'; import React, { useEffect } from 'react';
import Modal from '@/components/elements/Modal'; import Modal from '@/components/elements/Modal';
import { Task } from '@/api/server/schedules/getServerSchedules'; import { Schedule, Task } from '@/api/server/schedules/getServerSchedules';
import { Field as FormikField, Form, Formik, FormikHelpers, useFormikContext } from 'formik'; import { Field as FormikField, Form, Formik, FormikHelpers, useFormikContext } from 'formik';
import { ServerContext } from '@/state/server'; import { ServerContext } from '@/state/server';
import { Actions, useStoreActions } from 'easy-peasy';
import { ApplicationStore } from '@/state';
import createOrUpdateScheduleTask from '@/api/server/schedules/createOrUpdateScheduleTask'; import createOrUpdateScheduleTask from '@/api/server/schedules/createOrUpdateScheduleTask';
import { httpErrorToHuman } from '@/api/http'; import { httpErrorToHuman } from '@/api/http';
import Field from '@/components/elements/Field'; import Field from '@/components/elements/Field';
import FlashMessageRender from '@/components/FlashMessageRender'; import FlashMessageRender from '@/components/FlashMessageRender';
import { number, object, string } from 'yup'; import { number, object, string } from 'yup';
import useFlash from '@/plugins/useFlash';
import useServer from '@/plugins/useServer';
interface Props { interface Props {
scheduleId: number; schedule: Schedule;
// If a task is provided we can assume we're editing it. If not provided, // If a task is provided we can assume we're editing it. If not provided,
// we are creating a new one. // we are creating a new one.
task?: Task; task?: Task;
onDismissed: (task: Task | undefined | void) => void; onDismissed: () => void;
} }
interface Values { interface Values {
@ -29,8 +29,10 @@ const TaskDetailsForm = ({ isEditingTask }: { isEditingTask: boolean }) => {
const { values: { action }, setFieldValue, setFieldTouched } = useFormikContext<Values>(); const { values: { action }, setFieldValue, setFieldTouched } = useFormikContext<Values>();
useEffect(() => { useEffect(() => {
return () => {
setFieldValue('payload', ''); setFieldValue('payload', '');
setFieldTouched('payload', false); setFieldTouched('payload', false);
};
}, [ action ]); }, [ action ]);
return ( return (
@ -80,9 +82,10 @@ const TaskDetailsForm = ({ isEditingTask }: { isEditingTask: boolean }) => {
); );
}; };
export default ({ task, scheduleId, onDismissed }: Props) => { export default ({ task, schedule, onDismissed }: Props) => {
const uuid = ServerContext.useStoreState(state => state.server.data!.uuid); const { uuid } = useServer();
const { clearFlashes, addError } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes); const { clearFlashes, addError } = useFlash();
const appendSchedule = ServerContext.useStoreActions(actions => actions.schedules.appendSchedule);
useEffect(() => { useEffect(() => {
clearFlashes('schedule:task'); clearFlashes('schedule:task');
@ -90,8 +93,16 @@ export default ({ task, scheduleId, onDismissed }: Props) => {
const submit = (values: Values, { setSubmitting }: FormikHelpers<Values>) => { const submit = (values: Values, { setSubmitting }: FormikHelpers<Values>) => {
clearFlashes('schedule:task'); clearFlashes('schedule:task');
createOrUpdateScheduleTask(uuid, scheduleId, task?.id, values) createOrUpdateScheduleTask(uuid, schedule.id, task?.id, values)
.then(task => onDismissed(task)) .then(task => {
let tasks = schedule.tasks.map(t => t.id === task.id ? task : t);
if (!schedule.tasks.find(t => t.id === task.id)) {
tasks = [ ...tasks, task ];
}
appendSchedule({ ...schedule, tasks });
onDismissed();
})
.catch(error => { .catch(error => {
console.error(error); console.error(error);
setSubmitting(false); setSubmitting(false);

View File

@ -9,6 +9,7 @@ import FlashMessageRender from '@/components/FlashMessageRender';
import getServerSubusers from '@/api/server/users/getServerSubusers'; import getServerSubusers from '@/api/server/users/getServerSubusers';
import { httpErrorToHuman } from '@/api/http'; import { httpErrorToHuman } from '@/api/http';
import Can from '@/components/elements/Can'; import Can from '@/components/elements/Can';
import ListRefreshIndicator from '@/components/elements/ListRefreshIndicator';
export default () => { export default () => {
const [ loading, setLoading ] = useState(true); const [ loading, setLoading ] = useState(true);
@ -21,10 +22,6 @@ export default () => {
const getPermissions = useStoreActions((actions: Actions<ApplicationStore>) => actions.permissions.getPermissions); const getPermissions = useStoreActions((actions: Actions<ApplicationStore>) => actions.permissions.getPermissions);
const { addError, clearFlashes } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes); const { addError, clearFlashes } = useStoreActions((actions: Actions<ApplicationStore>) => actions.flashes);
useEffect(() => {
getPermissions().catch(error => console.error(error));
}, []);
useEffect(() => { useEffect(() => {
clearFlashes('users'); clearFlashes('users');
getServerSubusers(uuid) getServerSubusers(uuid)
@ -38,12 +35,20 @@ export default () => {
}); });
}, []); }, []);
if (loading || !Object.keys(permissions).length) { useEffect(() => {
getPermissions().catch(error => {
addError({ key: 'users', message: httpErrorToHuman(error) });
console.error(error);
});
}, []);
if (!subusers.length && (loading || !Object.keys(permissions).length)) {
return <Spinner size={'large'} centered={true}/>; return <Spinner size={'large'} centered={true}/>;
} }
return ( return (
<div className={'mt-10 mb-6'}> <div className={'mt-10 mb-6'}>
<ListRefreshIndicator visible={loading}/>
<FlashMessageRender byKey={'users'} className={'mb-4'}/> <FlashMessageRender byKey={'users'} className={'mb-4'}/>
{!subusers.length ? {!subusers.length ?
<p className={'text-center text-sm text-neutral-400'}> <p className={'text-center text-sm text-neutral-400'}>

View File

@ -6,6 +6,7 @@ import files, { ServerFileStore } from '@/state/server/files';
import subusers, { ServerSubuserStore } from '@/state/server/subusers'; import subusers, { ServerSubuserStore } from '@/state/server/subusers';
import { composeWithDevTools } from 'redux-devtools-extension'; import { composeWithDevTools } from 'redux-devtools-extension';
import backups, { ServerBackupStore } from '@/state/server/backups'; import backups, { ServerBackupStore } from '@/state/server/backups';
import schedules, { ServerScheduleStore } from '@/state/server/schedules';
export type ServerStatus = 'offline' | 'starting' | 'stopping' | 'running'; export type ServerStatus = 'offline' | 'starting' | 'stopping' | 'running';
@ -74,6 +75,7 @@ export interface ServerStore {
subusers: ServerSubuserStore; subusers: ServerSubuserStore;
databases: ServerDatabaseStore; databases: ServerDatabaseStore;
files: ServerFileStore; files: ServerFileStore;
schedules: ServerScheduleStore;
backups: ServerBackupStore; backups: ServerBackupStore;
socket: SocketStore; socket: SocketStore;
status: ServerStatusStore; status: ServerStatusStore;
@ -88,6 +90,7 @@ export const ServerContext = createContextStore<ServerStore>({
files, files,
subusers, subusers,
backups, backups,
schedules,
clearServerState: action(state => { clearServerState: action(state => {
state.server.data = undefined; state.server.data = undefined;
state.server.permissions = []; state.server.permissions = [];
@ -95,7 +98,8 @@ export const ServerContext = createContextStore<ServerStore>({
state.subusers.data = []; state.subusers.data = [];
state.files.directory = '/'; state.files.directory = '/';
state.files.contents = []; state.files.contents = [];
state.backups.backups = []; state.backups.data = [];
state.schedules.data = [];
if (state.socket.instance) { if (state.socket.instance) {
state.socket.instance.removeAllListeners(); state.socket.instance.removeAllListeners();

View File

@ -0,0 +1,31 @@
import { action, Action } from 'easy-peasy';
import { Schedule } from '@/api/server/schedules/getServerSchedules';
export interface ServerScheduleStore {
data: Schedule[];
setSchedules: Action<ServerScheduleStore, Schedule[]>;
appendSchedule: Action<ServerScheduleStore, Schedule>;
removeSchedule: Action<ServerScheduleStore, number>;
}
const schedules: ServerScheduleStore = {
data: [],
setSchedules: action((state, payload) => {
state.data = payload;
}),
appendSchedule: action((state, payload) => {
if (state.data.find(schedule => schedule.id === payload.id)) {
state.data = state.data.map(schedule => schedule.id === payload.id ? payload : schedule);
} else {
state.data = [ ...state.data, payload ];
}
}),
removeSchedule: action((state, payload) => {
state.data = [ ...state.data.filter(schedule => schedule.id !== payload) ];
}),
};
export default schedules;