add rotation preview
This commit is contained in:
parent
622bdb383f
commit
4551481c0f
8 changed files with 157 additions and 115 deletions
|
|
@ -33,7 +33,7 @@ const ScheduleSlot: FC<ScheduleSlotProps> = observer((props) => {
|
|||
const { index, layerIndex, rotationIndex, event, startMoment, currentTimezone, color: propColor } = props;
|
||||
const { users } = event;
|
||||
|
||||
const trackMouse = true;
|
||||
const trackMouse = false;
|
||||
|
||||
const [mouseX, setMouseX] = useState<number>(0);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,15 +3,12 @@ import React, { FC, useMemo, useState, useEffect, useRef, useCallback } from 're
|
|||
import { HorizontalGroup, LoadingPlaceholder } from '@grafana/ui';
|
||||
import cn from 'classnames/bind';
|
||||
import dayjs from 'dayjs';
|
||||
import { observer } from 'mobx-react';
|
||||
import { CSSTransitionGroup } from 'react-transition-group'; // ES6
|
||||
|
||||
import ScheduleSlot from 'components/ScheduleSlot/ScheduleSlot';
|
||||
import Text from 'components/Text/Text';
|
||||
import { getFromString } from 'models/schedule/schedule.helpers';
|
||||
import { Rotation as RotationType, Schedule, Event } from 'models/schedule/schedule.types';
|
||||
import { Timezone } from 'models/timezone/timezone.types';
|
||||
import { useStore } from 'state/useStore';
|
||||
import { usePrevious } from 'utils/hooks';
|
||||
|
||||
import styles from './Rotation.module.css';
|
||||
|
|
@ -30,15 +27,13 @@ interface RotationProps {
|
|||
onClick: () => void;
|
||||
}
|
||||
|
||||
const Rotation: FC<RotationProps> = observer((props) => {
|
||||
const Rotation: FC<RotationProps> = (props) => {
|
||||
const { events, layerIndex, rotationIndex, startMoment, currentTimezone, color, onClick } = props;
|
||||
|
||||
const [animate, setAnimate] = useState<boolean>(true);
|
||||
const [width, setWidth] = useState<number | undefined>();
|
||||
const [transparent, setTransparent] = useState<boolean>(false);
|
||||
|
||||
const store = useStore();
|
||||
|
||||
const startMomentString = useMemo(() => getFromString(startMoment), [startMoment]);
|
||||
|
||||
const prevStartMomentString = usePrevious(startMomentString);
|
||||
|
|
@ -92,7 +87,6 @@ const Rotation: FC<RotationProps> = observer((props) => {
|
|||
<div
|
||||
className={cx('slots', { slots__animate: animate, slots__transparent: transparent })}
|
||||
style={{ transform: `translate(${x * 100}%, 0)` }}
|
||||
ref={slots}
|
||||
>
|
||||
{events.map((event, index) => {
|
||||
return (
|
||||
|
|
@ -110,7 +104,7 @@ const Rotation: FC<RotationProps> = observer((props) => {
|
|||
})}
|
||||
</div>
|
||||
) : (
|
||||
<div className={cx('empty')} />
|
||||
<Empty />
|
||||
)
|
||||
) : (
|
||||
<HorizontalGroup align="center" justify="center">
|
||||
|
|
@ -120,6 +114,10 @@ const Rotation: FC<RotationProps> = observer((props) => {
|
|||
</div>
|
||||
</div>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
const Empty = () => {
|
||||
return <div className={cx('empty')} />;
|
||||
};
|
||||
|
||||
export default Rotation;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import React, { FC, useCallback, useEffect, useState } from 'react';
|
||||
import React, { FC, useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import { dateTime, DateTime } from '@grafana/data';
|
||||
import {
|
||||
|
|
@ -22,21 +22,25 @@ import Text from 'components/Text/Text';
|
|||
import UserGroups from 'components/UserGroups/UserGroups';
|
||||
import WithConfirm from 'components/WithConfirm/WithConfirm';
|
||||
import RemoteSelect from 'containers/RemoteSelect/RemoteSelect';
|
||||
import { getFromString } from 'models/schedule/schedule.helpers';
|
||||
import { Rotation, Schedule, Shift } from 'models/schedule/schedule.types';
|
||||
import { getTzOffsetString } from 'models/timezone/timezone.helpers';
|
||||
import { Timezone } from 'models/timezone/timezone.types';
|
||||
import { User } from 'models/user/user.types';
|
||||
import { makeRequest } from 'network';
|
||||
import { getDateTime, getUTCString } from 'pages/schedule/Schedule.helpers';
|
||||
import { SelectOption } from 'state/types';
|
||||
import { useStore } from 'state/useStore';
|
||||
import { useDebouncedCallback } from 'utils/hooks';
|
||||
|
||||
import { RotationCreateData } from './RotationForm.types';
|
||||
|
||||
import styles from './RotationForm.module.css';
|
||||
|
||||
interface RotationFormProps {
|
||||
layerIndex: number;
|
||||
layerPriority: number;
|
||||
onHide: () => void;
|
||||
startMoment: dayjs.Dayjs;
|
||||
currentTimezone: Timezone;
|
||||
scheduleId: Schedule['id'];
|
||||
shiftId: Shift['id'] | 'new';
|
||||
|
|
@ -46,10 +50,10 @@ interface RotationFormProps {
|
|||
|
||||
const cx = cn.bind(styles);
|
||||
|
||||
const startOfDay = dayjs().startOf('day');
|
||||
const startOfDay = dayjs().startOf('day').add(1, 'day');
|
||||
|
||||
const RotationForm: FC<RotationFormProps> = observer((props) => {
|
||||
const { onHide, onCreate, currentTimezone, scheduleId, onUpdate, layerIndex, shiftId } = props;
|
||||
const { onHide, onCreate, startMoment, currentTimezone, scheduleId, onUpdate, layerPriority, shiftId } = props;
|
||||
|
||||
const [repeatEveryValue, setRepeatEveryValue] = useState<number>(1);
|
||||
const [repeatEveryPeriod, setRepeatEveryPeriod] = useState<number>(0);
|
||||
|
|
@ -88,9 +92,8 @@ const RotationForm: FC<RotationFormProps> = observer((props) => {
|
|||
}
|
||||
}, [shiftId]);
|
||||
|
||||
const handleCreate = useCallback(() => {
|
||||
const params = {
|
||||
title: 'Rotation ' + Math.floor(Math.random() * 100),
|
||||
const params = useMemo(
|
||||
() => ({
|
||||
rotation_start: getUTCString(rotationStart, currentTimezone),
|
||||
until: endLess ? null : getUTCString(rotationEnd, currentTimezone),
|
||||
shift_start: getUTCString(shiftStart, currentTimezone),
|
||||
|
|
@ -99,9 +102,25 @@ const RotationForm: FC<RotationFormProps> = observer((props) => {
|
|||
interval: repeatEveryValue,
|
||||
frequency: repeatEveryPeriod,
|
||||
by_day: repeatEveryPeriod === 1 ? selectedDays : null,
|
||||
priority_level: shiftId === 'new' ? layerIndex + 1 : shift?.priority_level,
|
||||
};
|
||||
priority_level: shiftId === 'new' ? layerPriority : shift?.priority_level,
|
||||
}),
|
||||
[
|
||||
rotationStart,
|
||||
currentTimezone,
|
||||
rotationEnd,
|
||||
shiftStart,
|
||||
shiftEnd,
|
||||
userGroups,
|
||||
repeatEveryValue,
|
||||
repeatEveryPeriod,
|
||||
selectedDays,
|
||||
shiftId,
|
||||
layerPriority,
|
||||
shift,
|
||||
]
|
||||
);
|
||||
|
||||
const handleCreate = useCallback(() => {
|
||||
if (shiftId === 'new') {
|
||||
store.scheduleStore.createRotation(scheduleId, false, params).then(() => {
|
||||
onHide();
|
||||
|
|
@ -113,18 +132,13 @@ const RotationForm: FC<RotationFormProps> = observer((props) => {
|
|||
onUpdate();
|
||||
});
|
||||
}
|
||||
}, [
|
||||
repeatEveryValue,
|
||||
repeatEveryPeriod,
|
||||
selectedDays,
|
||||
shiftStart,
|
||||
shiftEnd,
|
||||
rotationStart,
|
||||
endLess,
|
||||
rotationEnd,
|
||||
userGroups,
|
||||
layerIndex,
|
||||
]);
|
||||
}, [shiftId, params]);
|
||||
|
||||
const handleChange = useDebouncedCallback(() => {
|
||||
store.scheduleStore.updateRotationPreview(scheduleId, shiftId, getFromString(startMoment), false, params);
|
||||
}, 1000);
|
||||
|
||||
useEffect(handleChange, [params]);
|
||||
|
||||
useEffect(() => {
|
||||
if (shift) {
|
||||
|
|
@ -173,7 +187,7 @@ const RotationForm: FC<RotationFormProps> = observer((props) => {
|
|||
<HorizontalGroup justify="space-between">
|
||||
<Text size="medium">
|
||||
<HorizontalGroup spacing="sm">
|
||||
<span>[L{shiftId === 'new' ? layerIndex + 1 : shift?.priority_level}]</span>
|
||||
<span>[L{shiftId === 'new' ? layerPriority : shift?.priority_level}]</span>
|
||||
{shiftId === 'new' ? 'New Rotation' : shift?.title}
|
||||
</HorizontalGroup>
|
||||
</Text>
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ import { ValuePicker, IconButton, Icon, HorizontalGroup, Button, LoadingPlacehol
|
|||
import cn from 'classnames/bind';
|
||||
import dayjs from 'dayjs';
|
||||
import utc from 'dayjs/plugin/utc';
|
||||
import { toJS } from 'mobx';
|
||||
import { observer } from 'mobx-react';
|
||||
|
||||
import TimelineMarks from 'components/TimelineMarks/TimelineMarks';
|
||||
|
|
@ -11,7 +12,7 @@ import Rotation from 'containers/Rotation/Rotation';
|
|||
import RotationForm from 'containers/RotationForm/RotationForm';
|
||||
import { RotationCreateData } from 'containers/RotationForm/RotationForm.types';
|
||||
import { getFromString } from 'models/schedule/schedule.helpers';
|
||||
import { Event, Schedule, Shift } from 'models/schedule/schedule.types';
|
||||
import { Event, Layer, Schedule, Shift } from 'models/schedule/schedule.types';
|
||||
import { Timezone } from 'models/timezone/timezone.types';
|
||||
import { SelectOption, WithStoreProps } from 'state/types';
|
||||
import { withMobXProviderContext } from 'state/withStore';
|
||||
|
|
@ -33,12 +34,7 @@ interface RotationsProps extends WithStoreProps {
|
|||
|
||||
interface RotationsState {
|
||||
shiftIdToShowRotationForm?: Shift['id'];
|
||||
layerIndexToShowRotationForm?: number;
|
||||
}
|
||||
|
||||
interface Layer {
|
||||
priority: Shift['priority_level'];
|
||||
shifts: Array<{ shiftId: Shift['id']; events: Event[] }>;
|
||||
layerPriority?: Layer['priority'];
|
||||
}
|
||||
|
||||
@observer
|
||||
|
|
@ -49,7 +45,7 @@ class Rotations extends Component<RotationsProps, RotationsState> {
|
|||
|
||||
render() {
|
||||
const { scheduleId, startMoment, currentTimezone, onCreate, onUpdate, store, onClick } = this.props;
|
||||
const { shiftIdToShowRotationForm, layerIndexToShowRotationForm } = this.state;
|
||||
const { shiftIdToShowRotationForm, layerPriority } = this.state;
|
||||
|
||||
const base = 7 * 24 * 60; // in minutes
|
||||
const diff = dayjs().tz(currentTimezone).diff(startMoment, 'minutes');
|
||||
|
|
@ -58,32 +54,12 @@ class Rotations extends Component<RotationsProps, RotationsState> {
|
|||
|
||||
const currentTimeHidden = currentTimeX < 0 || currentTimeX > 1;
|
||||
|
||||
const shifts = store.scheduleStore.events[scheduleId]?.['rotation']?.[getFromString(startMoment)];
|
||||
const storeLayers = store.scheduleStore.events[scheduleId]?.['rotation']?.[getFromString(startMoment)] as Layer[];
|
||||
|
||||
const layers: Layer[] | undefined = shifts
|
||||
? shifts
|
||||
.reduce((memo, shift) => {
|
||||
const storeShift = store.scheduleStore.shifts[shift.shiftId];
|
||||
let layer = memo.find((level) => level.priority === storeShift.priority_level);
|
||||
if (!layer) {
|
||||
layer = { priority: storeShift.priority_level, shifts: [] };
|
||||
memo.push(layer);
|
||||
}
|
||||
layer.shifts.push(shift);
|
||||
|
||||
return memo;
|
||||
}, [])
|
||||
.sort((a, b) => {
|
||||
if (a.priority > b.priority) {
|
||||
return 1;
|
||||
}
|
||||
if (a.priority < b.priority) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
})
|
||||
: undefined;
|
||||
let layers = storeLayers;
|
||||
if (store.scheduleStore.rotationPreview) {
|
||||
layers = [...layers, { priority: 2, shifts: [store.scheduleStore.rotationPreview] }];
|
||||
}
|
||||
|
||||
const options = layers
|
||||
? layers.map((layer) => ({
|
||||
|
|
@ -92,7 +68,9 @@ class Rotations extends Component<RotationsProps, RotationsState> {
|
|||
}))
|
||||
: [];
|
||||
|
||||
options.push({ label: 'New Layer', value: layers?.length || 0 });
|
||||
const nextPriority = layers && layers.length ? layers[layers.length - 1].priority + 1 : 1;
|
||||
|
||||
options.push({ label: 'New Layer', value: nextPriority });
|
||||
|
||||
return (
|
||||
<>
|
||||
|
|
@ -158,7 +136,7 @@ class Rotations extends Component<RotationsProps, RotationsState> {
|
|||
<div className={cx('rotations')}>
|
||||
<Rotation
|
||||
onClick={() => {
|
||||
this.handleAddLayer(layers ? layers.length : 0);
|
||||
this.handleAddLayer(nextPriority);
|
||||
}}
|
||||
events={[]}
|
||||
layerIndex={0}
|
||||
|
|
@ -175,7 +153,7 @@ class Rotations extends Component<RotationsProps, RotationsState> {
|
|||
<div
|
||||
className={cx('add-rotations-layer')}
|
||||
onClick={() => {
|
||||
this.handleAddLayer(layers ? layers.length : 0);
|
||||
this.handleAddLayer(nextPriority);
|
||||
}}
|
||||
>
|
||||
Add rotations layer +
|
||||
|
|
@ -186,11 +164,10 @@ class Rotations extends Component<RotationsProps, RotationsState> {
|
|||
<RotationForm
|
||||
shiftId={shiftIdToShowRotationForm}
|
||||
scheduleId={scheduleId}
|
||||
layerIndex={layerIndexToShowRotationForm}
|
||||
layerPriority={layerPriority}
|
||||
startMoment={startMoment}
|
||||
currentTimezone={currentTimezone}
|
||||
onHide={() => {
|
||||
this.setState({ shiftIdToShowRotationForm: undefined });
|
||||
}}
|
||||
onHide={this.handleRotationFormHide}
|
||||
onUpdate={onUpdate}
|
||||
onCreate={onCreate}
|
||||
/>
|
||||
|
|
@ -199,18 +176,23 @@ class Rotations extends Component<RotationsProps, RotationsState> {
|
|||
);
|
||||
}
|
||||
|
||||
handleRotationFormHide = () => {
|
||||
const { store } = this.props;
|
||||
|
||||
store.scheduleStore.rotationPreview = undefined;
|
||||
this.setState({ shiftIdToShowRotationForm: undefined, layerPriority: undefined });
|
||||
};
|
||||
|
||||
onRotationClick = (shiftId: Shift['id']) => {
|
||||
this.setState({ shiftIdToShowRotationForm: shiftId });
|
||||
};
|
||||
|
||||
updateEvents = () => {};
|
||||
|
||||
handleAddLayer = (layerIndex: number) => {
|
||||
this.setState({ shiftIdToShowRotationForm: 'new', layerIndexToShowRotationForm: layerIndex });
|
||||
handleAddLayer = (layerPriority: number) => {
|
||||
this.setState({ shiftIdToShowRotationForm: 'new', layerPriority });
|
||||
};
|
||||
|
||||
handleAddRotation = (option: SelectOption) => {
|
||||
this.setState({ shiftIdToShowRotationForm: 'new', layerIndexToShowRotationForm: option.value });
|
||||
this.setState({ shiftIdToShowRotationForm: 'new', layerPriority: option.value });
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -69,23 +69,10 @@ class ScheduleFinal extends Component<ScheduleFinalProps, ScheduleOverridesState
|
|||
<div className={cx('rotations')}>
|
||||
{shifts && shifts.length ? (
|
||||
shifts.map(({ shiftId, events }, index) => (
|
||||
<Rotation
|
||||
key={index}
|
||||
events={events}
|
||||
startMoment={startMoment}
|
||||
currentTimezone={currentTimezone}
|
||||
/*layerIndex={0}
|
||||
rotationIndex={0}*/
|
||||
/>
|
||||
<Rotation key={index} events={events} startMoment={startMoment} currentTimezone={currentTimezone} />
|
||||
))
|
||||
) : (
|
||||
<Rotation
|
||||
events={[]}
|
||||
startMoment={startMoment}
|
||||
currentTimezone={currentTimezone}
|
||||
/*layerIndex={0}
|
||||
rotationIndex={0}*/
|
||||
/>
|
||||
<Rotation events={[]} startMoment={startMoment} currentTimezone={currentTimezone} />
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import dayjs from 'dayjs';
|
||||
|
||||
import { Event } from './schedule.types';
|
||||
import { Event, Shift } from './schedule.types';
|
||||
|
||||
export const getFromString = (moment: dayjs.Dayjs) => {
|
||||
return moment.format('YYYY-MM-DD');
|
||||
|
|
@ -23,3 +23,24 @@ export const fillGaps = (events: Event[]) => {
|
|||
|
||||
return newEvents;
|
||||
};
|
||||
|
||||
export const splitToShiftsAndFillGaps = (events: Event[]) => {
|
||||
const shifts: Array<{ shiftId: Shift['id']; events: Event[] }> = [];
|
||||
|
||||
for (const [i, event] of events.entries()) {
|
||||
if (event.shift?.pk) {
|
||||
let shift = shifts.find((shift) => shift.shiftId === event.shift?.pk);
|
||||
if (!shift) {
|
||||
shift = { shiftId: event.shift.pk, events: [] };
|
||||
shifts.push(shift);
|
||||
}
|
||||
shift.events.push(event);
|
||||
}
|
||||
}
|
||||
|
||||
shifts.forEach((shift) => {
|
||||
shift.events = fillGaps(shift.events);
|
||||
});
|
||||
|
||||
return shifts;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ import { makeRequest } from 'network';
|
|||
import { RootStore } from 'state';
|
||||
import { SelectOption } from 'state/types';
|
||||
|
||||
import { fillGaps } from './schedule.helpers';
|
||||
import { Events, Rotation, RotationType, Schedule, ScheduleEvent, Shift, Event } from './schedule.types';
|
||||
import { fillGaps, splitToShiftsAndFillGaps } from './schedule.helpers';
|
||||
import { Events, Rotation, RotationType, Schedule, ScheduleEvent, Shift, Event, Layer } from './schedule.types';
|
||||
|
||||
const DEFAULT_FORMAT = 'YYYY-MM-DDTHH:mm:ss';
|
||||
|
||||
|
|
@ -67,11 +67,17 @@ export class ScheduleStore extends BaseStore {
|
|||
events: {
|
||||
[scheduleId: string]: {
|
||||
[type: string]: {
|
||||
[startMoment: string]: Array<{ shiftId: string; events: Event[] }>;
|
||||
[startMoment: string]: Array<{ shiftId: string; events: Event[] }> | Layer[];
|
||||
};
|
||||
};
|
||||
} = {};
|
||||
|
||||
@observable.shallow
|
||||
rotationPreview?: { shiftId: Shift['id']; events: Event[] };
|
||||
|
||||
@observable.shallow
|
||||
finalPreview?: Array<{ shiftId: Shift['id']; events: Event[] }>;
|
||||
|
||||
@observable
|
||||
scheduleToScheduleEvents: {
|
||||
[id: string]: ScheduleEvent[];
|
||||
|
|
@ -187,6 +193,27 @@ export class ScheduleStore extends BaseStore {
|
|||
return response;
|
||||
}
|
||||
|
||||
async updateRotationPreview(
|
||||
scheduleId: Schedule['id'],
|
||||
shiftId: Shift['id'] | 'new',
|
||||
fromString: string,
|
||||
isOverride: boolean,
|
||||
params: Partial<Shift>
|
||||
) {
|
||||
const type = isOverride ? 3 : 2;
|
||||
|
||||
const typeString = isOverride ? 'override' : 'rotation';
|
||||
|
||||
const response = await makeRequest(`/oncall_shifts/preview/`, {
|
||||
params: { date: fromString },
|
||||
data: { type, schedule: scheduleId, ...params },
|
||||
method: 'POST',
|
||||
}).catch(this.onApiError);
|
||||
|
||||
this.rotationPreview = { shiftId: shiftId, events: fillGaps(response.rotation.filter((event) => !event.is_gap)) };
|
||||
this.finalPreview = splitToShiftsAndFillGaps(response.final);
|
||||
}
|
||||
|
||||
async updateRotation(shiftId: Shift['id'], params: Partial<Shift>) {
|
||||
const response = await makeRequest(`/oncall_shifts/${shiftId}`, {
|
||||
data: { ...params },
|
||||
|
|
@ -297,21 +324,9 @@ export class ScheduleStore extends BaseStore {
|
|||
method: 'GET',
|
||||
});
|
||||
|
||||
const events = type !== 'final' ? fillGaps(response.events) : response.events;
|
||||
|
||||
const shifts: Array<{ shiftId: Shift['id']; events: Event[] }> = [];
|
||||
|
||||
for (const [i, event] of response.events.entries()) {
|
||||
if (event.shift?.pk) {
|
||||
let shift = shifts.find((shift) => shift.shiftId === event.shift?.pk);
|
||||
if (!shift) {
|
||||
shift = { shiftId: event.shift.pk, events: [] };
|
||||
shifts.push(shift);
|
||||
}
|
||||
shift.events.push(event);
|
||||
}
|
||||
}
|
||||
const shifts = splitToShiftsAndFillGaps(response.events);
|
||||
|
||||
// merge users on frontend side, we don't need it now
|
||||
/*shifts.forEach((shift) => {
|
||||
for (let i = 0; i < shift.events.length; i++) {
|
||||
const iEvent = shift.events[i];
|
||||
|
|
@ -327,11 +342,31 @@ export class ScheduleStore extends BaseStore {
|
|||
}
|
||||
});*/
|
||||
|
||||
shifts.forEach((shift) => {
|
||||
shift.events = fillGaps(shift.events);
|
||||
});
|
||||
const layers: Layer[] | undefined =
|
||||
type === 'rotation'
|
||||
? shifts
|
||||
.reduce((memo, shift) => {
|
||||
const storeShift = this.shifts[shift.shiftId];
|
||||
let layer = memo.find((level) => level.priority === storeShift.priority_level);
|
||||
if (!layer) {
|
||||
layer = { priority: storeShift.priority_level, shifts: [] };
|
||||
memo.push(layer);
|
||||
}
|
||||
layer.shifts.push(shift);
|
||||
|
||||
//console.log(type, shifts);
|
||||
return memo;
|
||||
}, [])
|
||||
.sort((a, b) => {
|
||||
if (a.priority > b.priority) {
|
||||
return 1;
|
||||
}
|
||||
if (a.priority < b.priority) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
})
|
||||
: undefined;
|
||||
|
||||
this.events = {
|
||||
...this.events,
|
||||
|
|
@ -339,7 +374,7 @@ export class ScheduleStore extends BaseStore {
|
|||
...this.events[scheduleId],
|
||||
[type]: {
|
||||
...this.events[scheduleId]?.[type],
|
||||
[fromString]: shifts,
|
||||
[fromString]: layers ? layers : shifts,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -89,3 +89,8 @@ export interface Events {
|
|||
name: string;
|
||||
type: number; //?
|
||||
}
|
||||
|
||||
export interface Layer {
|
||||
priority: Shift['priority_level'];
|
||||
shifts: Array<{ shiftId: Shift['id']; events: Event[] }>;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue