mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-19 22:24:11 +00:00
V2 fix socket (#296)
* refactor: rename timer endpoint * refactor: typescript * refactor: rename eventData and viewSettings * refactor: message manager uses event store
This commit is contained in:
@@ -3,14 +3,13 @@ import { DragDropContext, Droppable, DropResult } from 'react-beautiful-dnd';
|
||||
import { Button } from '@chakra-ui/react';
|
||||
import { IoAdd } from '@react-icons/all-files/io5/IoAdd';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import PropTypes from 'prop-types';
|
||||
import { OntimeRundown, SupportedEvent } from 'ontime-types';
|
||||
|
||||
import { defaultPublicAtom, showQuickEntryAtom, startTimeIsLastEndAtom } from '../../common/atoms/LocalEventSettings';
|
||||
import Empty from '../../common/components/state/Empty';
|
||||
import { CursorContext } from '../../common/context/CursorContext';
|
||||
import { useEventAction } from '../../common/hooks/useEventAction';
|
||||
import { useRundownEditor } from '../../common/hooks/useSocket';
|
||||
import { OntimeRundown, SupportedEvent } from '../../common/models/EventTypes';
|
||||
import { cloneEvent } from '../../common/utils/eventsManager';
|
||||
|
||||
import QuickAddBlock from './quick-add-block/QuickAddBlock';
|
||||
@@ -25,8 +24,7 @@ interface RundownProps {
|
||||
export default function Rundown(props: RundownProps) {
|
||||
const { entries } = props;
|
||||
const { data } = useRundownEditor();
|
||||
const { cursor, moveCursorUp, moveCursorDown, moveCursorTo, isCursorLocked } =
|
||||
useContext(CursorContext);
|
||||
const { cursor, moveCursorUp, moveCursorDown, moveCursorTo, isCursorLocked } = useContext(CursorContext);
|
||||
const startTimeIsLastEnd = useAtomValue(startTimeIsLastEndAtom);
|
||||
const defaultPublic = useAtomValue(defaultPublicAtom);
|
||||
const { addEvent, reorderEvent } = useEventAction();
|
||||
@@ -260,7 +258,3 @@ export default function Rundown(props: RundownProps) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Rundown.propTypes = {
|
||||
entries: PropTypes.array,
|
||||
};
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
import { useCallback, useContext } from 'react';
|
||||
import { useAtom, useAtomValue } from 'jotai';
|
||||
import { OntimeEvent, OntimeRundownEntry, Playback, SupportedEvent } from 'ontime-types';
|
||||
|
||||
import { defaultPublicAtom, editorEventId, startTimeIsLastEndAtom } from '../../common/atoms/LocalEventSettings';
|
||||
import { CursorContext } from '../../common/context/CursorContext';
|
||||
import { LoggingContext } from '../../common/context/LoggingContext';
|
||||
import { useEventAction } from '../../common/hooks/useEventAction';
|
||||
import { OntimeEvent, OntimeRundownEntry, SupportedEvent } from '../../common/models/EventTypes';
|
||||
import { Playback } from '../../common/models/OntimeTypes';
|
||||
import { cloneEvent } from '../../common/utils/eventsManager';
|
||||
import { calculateDuration } from '../../common/utils/timesManager';
|
||||
|
||||
@@ -14,14 +13,7 @@ import BlockBlock from './block-block/BlockBlock';
|
||||
import DelayBlock from './delay-block/DelayBlock';
|
||||
import EventBlock from './event-block/EventBlock';
|
||||
|
||||
export type EventItemActions =
|
||||
'set-cursor'
|
||||
| 'event'
|
||||
| 'delay'
|
||||
| 'block'
|
||||
| 'delete'
|
||||
| 'clone'
|
||||
| 'update'
|
||||
export type EventItemActions = 'set-cursor' | 'event' | 'delay' | 'block' | 'delete' | 'clone' | 'update';
|
||||
|
||||
interface RundownEntryProps {
|
||||
type: SupportedEvent;
|
||||
@@ -38,18 +30,7 @@ interface RundownEntryProps {
|
||||
}
|
||||
|
||||
export default function RundownEntry(props: RundownEntryProps) {
|
||||
const {
|
||||
index,
|
||||
eventIndex,
|
||||
data,
|
||||
selected,
|
||||
hasCursor,
|
||||
next,
|
||||
delay,
|
||||
previousEnd,
|
||||
previousEventId,
|
||||
playback,
|
||||
} = props;
|
||||
const { index, eventIndex, data, selected, hasCursor, next, delay, previousEnd, previousEventId, playback } = props;
|
||||
const { emitError } = useContext(LoggingContext);
|
||||
const startTimeIsLastEnd = useAtomValue(startTimeIsLastEndAtom);
|
||||
const defaultPublic = useAtomValue(defaultPublicAtom);
|
||||
@@ -61,7 +42,7 @@ export default function RundownEntry(props: RundownEntryProps) {
|
||||
type FieldValue = {
|
||||
field: keyof Omit<OntimeEvent, 'duration'> | 'durationOverride';
|
||||
value: unknown;
|
||||
}
|
||||
};
|
||||
const actionHandler = useCallback(
|
||||
(action: EventItemActions, payload?: number | FieldValue) => {
|
||||
switch (action) {
|
||||
@@ -171,19 +152,11 @@ export default function RundownEntry(props: RundownEntryProps) {
|
||||
/>
|
||||
);
|
||||
} else if (data.type === SupportedEvent.Block) {
|
||||
return <BlockBlock
|
||||
index={index}
|
||||
data={data}
|
||||
hasCursor={hasCursor}
|
||||
actionHandler={actionHandler}
|
||||
/>;
|
||||
// @ts-expect-error -- revise types here
|
||||
return <BlockBlock index={index} data={data} hasCursor={hasCursor} actionHandler={actionHandler} />;
|
||||
} else if (data.type === SupportedEvent.Delay) {
|
||||
return <DelayBlock
|
||||
index={index}
|
||||
data={data}
|
||||
hasCursor={hasCursor}
|
||||
actionHandler={actionHandler}
|
||||
/>;
|
||||
// @ts-expect-error -- revise types here
|
||||
return <DelayBlock index={index} data={data} hasCursor={hasCursor} actionHandler={actionHandler} />;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useEffect, useRef } from 'react';
|
||||
import { Draggable } from 'react-beautiful-dnd';
|
||||
import { IoReorderTwo } from '@react-icons/all-files/io5/IoReorderTwo';
|
||||
import { OntimeBlock, OntimeEvent } from 'ontime-types';
|
||||
|
||||
import { OntimeBlock, OntimeEvent } from '../../../common/models/EventTypes';
|
||||
import { cx } from '../../../common/utils/styleUtils';
|
||||
import BlockActionMenu from '../event-block/composite/BlockActionMenu';
|
||||
import { EventItemActions } from '../RundownEntry';
|
||||
|
||||
@@ -3,11 +3,11 @@ import { Draggable } from 'react-beautiful-dnd';
|
||||
import { Button, HStack } from '@chakra-ui/react';
|
||||
import { IoCheckmark } from '@react-icons/all-files/io5/IoCheckmark';
|
||||
import { IoReorderTwo } from '@react-icons/all-files/io5/IoReorderTwo';
|
||||
import { OntimeDelay, OntimeEvent } from 'ontime-types';
|
||||
|
||||
import DelayInput from '../../../common/components/input/delay-input/DelayInput';
|
||||
import { useEventAction } from '../../../common/hooks/useEventAction';
|
||||
import { millisToMinutes } from '../../../common/utils/dateConfig';
|
||||
|
||||
import { OntimeDelay, OntimeEvent } from '../../../common/models/EventTypes';
|
||||
import { cx } from '../../../common/utils/styleUtils';
|
||||
import BlockActionMenu from '../event-block/composite/BlockActionMenu';
|
||||
import { EventItemActions } from '../RundownEntry';
|
||||
@@ -15,10 +15,10 @@ import { EventItemActions } from '../RundownEntry';
|
||||
import style from './DelayBlock.module.scss';
|
||||
|
||||
interface DelayBlockProps {
|
||||
data: OntimeDelay,
|
||||
data: OntimeDelay;
|
||||
index: number;
|
||||
hasCursor: boolean;
|
||||
actionHandler: (action: EventItemActions, payload?: number | { field: keyof OntimeEvent, value: unknown }) => void;
|
||||
actionHandler: (action: EventItemActions, payload?: number | { field: keyof OntimeEvent; value: unknown }) => void;
|
||||
}
|
||||
|
||||
export default function DelayBlock(props: DelayBlockProps) {
|
||||
@@ -30,7 +30,7 @@ export default function DelayBlock(props: DelayBlockProps) {
|
||||
if (hasCursor) {
|
||||
onFocusRef?.current?.focus();
|
||||
}
|
||||
}, [hasCursor])
|
||||
}, [hasCursor]);
|
||||
|
||||
const applyDelayHandler = useCallback(() => {
|
||||
applyDelay(data.id);
|
||||
@@ -48,10 +48,7 @@ export default function DelayBlock(props: DelayBlockProps) {
|
||||
[data.id, updateEvent],
|
||||
);
|
||||
|
||||
const blockClasses = cx([
|
||||
style.delay,
|
||||
hasCursor ? style.hasCursor : null,
|
||||
]);
|
||||
const blockClasses = cx([style.delay, hasCursor ? style.hasCursor : null]);
|
||||
|
||||
const delayValue = data.duration != null ? millisToMinutes(data.duration) : undefined;
|
||||
|
||||
@@ -62,17 +59,9 @@ export default function DelayBlock(props: DelayBlockProps) {
|
||||
<span className={style.drag} {...provided.dragHandleProps} ref={onFocusRef}>
|
||||
<IoReorderTwo />
|
||||
</span>
|
||||
<DelayInput
|
||||
value={delayValue}
|
||||
submitHandler={delaySubmitHandler}
|
||||
/>
|
||||
<DelayInput value={delayValue} submitHandler={delaySubmitHandler} />
|
||||
<HStack spacing='8px' className={style.actionOverlay}>
|
||||
<Button
|
||||
onClick={applyDelayHandler}
|
||||
size='sm'
|
||||
leftIcon={<IoCheckmark />}
|
||||
variant='ontime-subtle-white'
|
||||
>
|
||||
<Button onClick={applyDelayHandler} size='sm' leftIcon={<IoCheckmark />} variant='ontime-subtle-white'>
|
||||
Apply delay
|
||||
</Button>
|
||||
<BlockActionMenu showAdd enableDelete actionHandler={actionHandler} />
|
||||
|
||||
@@ -10,14 +10,14 @@ import { IoReload } from '@react-icons/all-files/io5/IoReload';
|
||||
import { IoRemoveCircle } from '@react-icons/all-files/io5/IoRemoveCircle';
|
||||
import { IoRemoveCircleOutline } from '@react-icons/all-files/io5/IoRemoveCircleOutline';
|
||||
import { IoReorderTwo } from '@react-icons/all-files/io5/IoReorderTwo';
|
||||
import { useAtom } from 'jotai';
|
||||
import { Playback } from 'ontime-types';
|
||||
|
||||
import { editorEventId } from '../../../common/atoms/LocalEventSettings';
|
||||
import TooltipActionBtn from '../../../common/components/buttons/TooltipActionBtn';
|
||||
import { cx, getAccessibleColour } from '../../../common/utils/styleUtils';
|
||||
import { useAtom } from 'jotai';
|
||||
|
||||
import { useEventAction } from '../../../common/hooks/useEventAction';
|
||||
import { setEventPlayback } from '../../../common/hooks/useSocket';
|
||||
import { Playback } from '../../../common/models/OntimeTypes';
|
||||
import { cx, getAccessibleColour } from '../../../common/utils/styleUtils';
|
||||
import { tooltipDelayMid } from '../../../ontimeConfig';
|
||||
import { EventItemActions } from '../RundownEntry';
|
||||
|
||||
@@ -129,11 +129,7 @@ export default function EventBlock(props: EventBlockProps) {
|
||||
return (
|
||||
<Draggable key={eventId} draggableId={eventId} index={index}>
|
||||
{(provided) => (
|
||||
<div
|
||||
className={blockClasses}
|
||||
{...provided.draggableProps}
|
||||
ref={provided.innerRef}
|
||||
>
|
||||
<div className={blockClasses} {...provided.draggableProps} ref={provided.innerRef}>
|
||||
<div
|
||||
className={style.binder}
|
||||
style={{ ...binderColours }}
|
||||
@@ -206,22 +202,13 @@ export default function EventBlock(props: EventBlockProps) {
|
||||
<div className={selected ? style.progressBg : `${style.progressBg} ${style.hidden}`}>
|
||||
<EventBlockProgressBar playback={playback} />
|
||||
</div>
|
||||
<div className={style.eventStatus} tabIndex={-1}
|
||||
>
|
||||
<Tooltip
|
||||
label='Next event'
|
||||
isDisabled={!next}
|
||||
{...tooltipProps}
|
||||
>
|
||||
<div className={style.eventStatus} tabIndex={-1}>
|
||||
<Tooltip label='Next event' isDisabled={!next} {...tooltipProps}>
|
||||
<span>
|
||||
<IoPlaySkipForward
|
||||
className={`${style.statusIcon} ${next ? style.active : ''}`} />
|
||||
<IoPlaySkipForward className={`${style.statusIcon} ${next ? style.active : ''}`} />
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip
|
||||
label={`${isPublic ? 'Event is public' : 'Event is private'}`}
|
||||
{...tooltipProps}
|
||||
>
|
||||
<Tooltip label={`${isPublic ? 'Event is public' : 'Event is private'}`} {...tooltipProps}>
|
||||
<span>
|
||||
<IoPeople className={`${style.statusIcon} ${isPublic ? style.active : ''}`} />
|
||||
</span>
|
||||
@@ -234,7 +221,7 @@ export default function EventBlock(props: EventBlockProps) {
|
||||
variant='ontime-subtle-white'
|
||||
size='sm'
|
||||
icon={<IoOptions />}
|
||||
clickHandler={() => setOpenId((prev) => prev === eventId ? null : eventId)}
|
||||
clickHandler={() => setOpenId((prev) => (prev === eventId ? null : eventId))}
|
||||
tooltip='Event options'
|
||||
aria-label='Event options'
|
||||
tabIndex={-1}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import { Playback } from 'ontime-types';
|
||||
|
||||
import { useTimer } from '../../../../common/hooks/useSocket';
|
||||
import { Playback } from '../../../../common/models/OntimeTypes';
|
||||
import { clamp } from '../../../../common/utils/math';
|
||||
|
||||
import style from './EventBlockProgressBar.module.scss';
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { useCallback, useContext, useRef } from 'react';
|
||||
import { Button, Checkbox, Tooltip } from '@chakra-ui/react';
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { SupportedEvent } from 'ontime-types';
|
||||
|
||||
import { defaultPublicAtom, startTimeIsLastEndAtom } from '../../../common/atoms/LocalEventSettings';
|
||||
import { LoggingContext } from '../../../common/context/LoggingContext';
|
||||
import { useEventAction } from '../../../common/hooks/useEventAction';
|
||||
import { SupportedEvent } from '../../../common/models/EventTypes';
|
||||
import { useAtomValue } from 'jotai';
|
||||
|
||||
import { tooltipDelayMid } from '../../../ontimeConfig';
|
||||
|
||||
import style from './QuickAddBlock.module.scss';
|
||||
@@ -19,13 +19,7 @@ interface QuickAddBlockProps {
|
||||
}
|
||||
|
||||
export default function QuickAddBlock(props: QuickAddBlockProps) {
|
||||
const {
|
||||
showKbd,
|
||||
eventId,
|
||||
previousEventId,
|
||||
disableAddDelay = true,
|
||||
disableAddBlock,
|
||||
} = props;
|
||||
const { showKbd, eventId, previousEventId, disableAddDelay = true, disableAddBlock } = props;
|
||||
const { addEvent } = useEventAction();
|
||||
const { emitError } = useContext(LoggingContext);
|
||||
const startTimeIsLastEnd = useAtomValue(startTimeIsLastEndAtom);
|
||||
@@ -33,45 +27,47 @@ export default function QuickAddBlock(props: QuickAddBlockProps) {
|
||||
const doStartTime = useRef<HTMLInputElement | null>(null);
|
||||
const doPublic = useRef<HTMLInputElement | null>(null);
|
||||
|
||||
const handleCreateEvent = useCallback((eventType: SupportedEvent) => {
|
||||
switch (eventType) {
|
||||
case 'event': {
|
||||
const isPublicOption = doPublic?.current?.checked;
|
||||
const startTimeIsLastEndOption = doStartTime?.current?.checked;
|
||||
const handleCreateEvent = useCallback(
|
||||
(eventType: SupportedEvent) => {
|
||||
switch (eventType) {
|
||||
case 'event': {
|
||||
const isPublicOption = doPublic?.current?.checked;
|
||||
const startTimeIsLastEndOption = doStartTime?.current?.checked;
|
||||
|
||||
const newEvent = { type: SupportedEvent.Event };
|
||||
const options = {
|
||||
defaultPublic: isPublicOption,
|
||||
startTimeIsLastEnd: startTimeIsLastEndOption,
|
||||
lastEventId: previousEventId,
|
||||
after: eventId,
|
||||
};
|
||||
addEvent(newEvent, options);
|
||||
break;
|
||||
}
|
||||
case 'delay': {
|
||||
const options = {
|
||||
lastEventId: previousEventId,
|
||||
after: eventId,
|
||||
const newEvent = { type: SupportedEvent.Event };
|
||||
const options = {
|
||||
defaultPublic: isPublicOption,
|
||||
startTimeIsLastEnd: startTimeIsLastEndOption,
|
||||
lastEventId: previousEventId,
|
||||
after: eventId,
|
||||
};
|
||||
addEvent(newEvent, options);
|
||||
break;
|
||||
}
|
||||
addEvent({ type: SupportedEvent.Delay }, options);
|
||||
break;
|
||||
}
|
||||
case 'block': {
|
||||
const options= {
|
||||
lastEventId: previousEventId,
|
||||
after: eventId,
|
||||
case 'delay': {
|
||||
const options = {
|
||||
lastEventId: previousEventId,
|
||||
after: eventId,
|
||||
};
|
||||
addEvent({ type: SupportedEvent.Delay }, options);
|
||||
break;
|
||||
}
|
||||
case 'block': {
|
||||
const options = {
|
||||
lastEventId: previousEventId,
|
||||
after: eventId,
|
||||
};
|
||||
addEvent({ type: SupportedEvent.Block }, options);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
emitError(`Cannot create unknown event type: ${eventType}`);
|
||||
break;
|
||||
}
|
||||
addEvent({ type: SupportedEvent.Block }, options);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
emitError(`Cannot create unknown event type: ${eventType}`);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
}, [previousEventId, eventId, addEvent, emitError]);
|
||||
},
|
||||
[previousEventId, eventId, addEvent, emitError],
|
||||
);
|
||||
|
||||
return (
|
||||
<div className={style.quickAdd}>
|
||||
@@ -110,20 +106,10 @@ export default function QuickAddBlock(props: QuickAddBlockProps) {
|
||||
</Tooltip>
|
||||
</div>
|
||||
<div className={style.options}>
|
||||
<Checkbox
|
||||
ref={doStartTime}
|
||||
size='sm'
|
||||
variant='ontime-ondark'
|
||||
defaultChecked={startTimeIsLastEnd}
|
||||
>
|
||||
<Checkbox ref={doStartTime} size='sm' variant='ontime-ondark' defaultChecked={startTimeIsLastEnd}>
|
||||
Start time is last end
|
||||
</Checkbox>
|
||||
<Checkbox
|
||||
ref={doPublic}
|
||||
size='sm'
|
||||
variant='ontime-ondark'
|
||||
defaultChecked={defaultPublic}
|
||||
>
|
||||
<Checkbox ref={doPublic} size='sm' variant='ontime-ondark' defaultChecked={defaultPublic}>
|
||||
Event is public
|
||||
</Checkbox>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user