chore: improve convention entry <> event

This commit is contained in:
Carlos Valente
2025-04-13 20:46:47 +02:00
committed by arc-alex
parent d2c7b34142
commit 82dc1bc56b
23 changed files with 211 additions and 210 deletions
+14 -13
View File
@@ -1,5 +1,6 @@
import axios, { AxiosResponse } from 'axios'; import axios, { AxiosResponse } from 'axios';
import { import {
EntryId,
MessageResponse, MessageResponse,
OntimeEntry, OntimeEntry,
OntimeEvent, OntimeEvent,
@@ -29,16 +30,16 @@ export async function fetchCurrentRundown(): Promise<Rundown> {
} }
/** /**
* HTTP request to post new event * HTTP request to post new entry
*/ */
export async function requestPostEvent(data: TransientEventPayload): Promise<AxiosResponse<OntimeEntry>> { export async function postAddEntry(data: TransientEventPayload): Promise<AxiosResponse<OntimeEntry>> {
return axios.post(rundownPath, data); return axios.post(rundownPath, data);
} }
/** /**
* HTTP request to put new event * HTTP request to edit an entry
*/ */
export async function requestPutEvent(data: Partial<OntimeEntry>): Promise<AxiosResponse<OntimeEntry>> { export async function putEditEntry(data: Partial<OntimeEntry>): Promise<AxiosResponse<OntimeEntry>> {
return axios.put(rundownPath, data); return axios.put(rundownPath, data);
} }
@@ -48,9 +49,9 @@ type BatchEditEntry = {
}; };
/** /**
* HTTP request to put multiple events * HTTP request to edit multiple events
*/ */
export async function requestBatchPutEvents(data: BatchEditEntry): Promise<AxiosResponse<MessageResponse>> { export async function putBatchEditEvents(data: BatchEditEntry): Promise<AxiosResponse<MessageResponse>> {
return axios.put(`${rundownPath}/batch`, data); return axios.put(`${rundownPath}/batch`, data);
} }
@@ -61,9 +62,9 @@ export type ReorderEntry = {
}; };
/** /**
* HTTP request to reorder events * HTTP request to reorder an entry
*/ */
export async function requestReorderEvent(data: ReorderEntry): Promise<AxiosResponse<OntimeEntry>> { export async function patchReorderEntry(data: ReorderEntry): Promise<AxiosResponse<OntimeEntry>> {
return axios.patch(`${rundownPath}/reorder`, data); return axios.patch(`${rundownPath}/reorder`, data);
} }
@@ -82,15 +83,15 @@ export async function requestEventSwap(data: SwapEntry): Promise<AxiosResponse<M
/** /**
* HTTP request to request application of delay * HTTP request to request application of delay
*/ */
export async function requestApplyDelay(eventId: string): Promise<AxiosResponse<MessageResponse>> { export async function requestApplyDelay(delayId: string): Promise<AxiosResponse<MessageResponse>> {
return axios.patch(`${rundownPath}/applydelay/${eventId}`); return axios.patch(`${rundownPath}/applydelay/${delayId}`);
} }
/** /**
* HTTP request to delete given event * HTTP request to delete entries
*/ */
export async function requestDelete(eventIds: string[]): Promise<AxiosResponse<MessageResponse>> { export async function deleteEntries(entryIds: EntryId[]): Promise<AxiosResponse<MessageResponse>> {
return axios.delete(rundownPath, { data: { ids: eventIds } }); return axios.delete(rundownPath, { data: { ids: entryIds } });
} }
/** /**
+2 -2
View File
@@ -7,7 +7,7 @@ import { addLog } from '../stores/logger';
import { nowInMillis } from '../utils/time'; import { nowInMillis } from '../utils/time';
/** /**
* Utility unrwap a potential axios error * Utility unwrap a potential axios error
* @param error * @param error
* @returns * @returns
*/ */
@@ -34,7 +34,7 @@ export function maybeAxiosError(error: unknown) {
} }
/** /**
* Utility unrwaps a potential axios error and sends to logger * Utility unwraps a potential axios error and sends to logger
* @param prepend * @param prepend
* @param error * @param error
*/ */
@@ -2,7 +2,7 @@ import { KeyboardEvent, useEffect, useRef, useState } from 'react';
import { Input, Radio, RadioGroup } from '@chakra-ui/react'; import { Input, Radio, RadioGroup } from '@chakra-ui/react';
import { millisToString, parseUserTime } from 'ontime-utils'; import { millisToString, parseUserTime } from 'ontime-utils';
import { useEventAction } from '../../../hooks/useEventAction'; import { useEntryActions } from '../../../hooks/useEntryAction';
import style from './DelayInput.module.scss'; import style from './DelayInput.module.scss';
@@ -13,7 +13,7 @@ interface DelayInputProps {
export default function DelayInput(props: DelayInputProps) { export default function DelayInput(props: DelayInputProps) {
const { eventId, duration } = props; const { eventId, duration } = props;
const { updateEvent } = useEventAction(); const { updateEntry } = useEntryActions();
const [value, setValue] = useState<string>(''); const [value, setValue] = useState<string>('');
const inputRef = useRef<HTMLInputElement | null>(null); const inputRef = useRef<HTMLInputElement | null>(null);
@@ -54,7 +54,7 @@ export default function DelayInput(props: DelayInputProps) {
}; };
const submitChange = (value: number) => { const submitChange = (value: number) => {
updateEvent({ updateEntry({
id: eventId, id: eventId,
duration: value, duration: value,
}); });
@@ -1,10 +1,9 @@
import { useCallback } from 'react'; import { useCallback } from 'react';
import { useMutation, useQueryClient } from '@tanstack/react-query'; import { useMutation, useQueryClient } from '@tanstack/react-query';
import { import {
EntryId,
isOntimeEvent, isOntimeEvent,
MaybeString, MaybeString,
OntimeBlock,
OntimeDelay,
OntimeEntry, OntimeEntry,
OntimeEvent, OntimeEvent,
Rundown, Rundown,
@@ -16,15 +15,15 @@ import { dayInMs, MILLIS_PER_SECOND, parseUserTime, reorderArray, swapEventData
import { RUNDOWN } from '../api/constants'; import { RUNDOWN } from '../api/constants';
import { import {
deleteEntries,
patchReorderEntry,
postAddEntry,
putBatchEditEvents,
putEditEntry,
ReorderEntry, ReorderEntry,
requestApplyDelay, requestApplyDelay,
requestBatchPutEvents,
requestDelete,
requestDeleteAll, requestDeleteAll,
requestEventSwap, requestEventSwap,
requestPostEvent,
requestPutEvent,
requestReorderEvent,
SwapEntry, SwapEntry,
} from '../api/rundown'; } from '../api/rundown';
import { logAxiosError } from '../api/utils'; import { logAxiosError } from '../api/utils';
@@ -41,9 +40,9 @@ export type EventOptions = Partial<{
}>; }>;
/** /**
* @description Set of utilities for events //TODO: should this be called useEntryAction and so on * Gather utilities for actions on entries
*/ */
export const useEventAction = () => { export const useEntryActions = () => {
const queryClient = useQueryClient(); const queryClient = useQueryClient();
const { const {
defaultPublic, defaultPublic,
@@ -56,8 +55,8 @@ export const useEventAction = () => {
defaultEndAction, defaultEndAction,
} = useEditorSettings(); } = useEditorSettings();
const getEventById = useCallback( const getEntryById = useCallback(
(eventId: string) => { (eventId: string): OntimeEntry | undefined => {
const cachedRundown = queryClient.getQueryData<Rundown>(RUNDOWN); const cachedRundown = queryClient.getQueryData<Rundown>(RUNDOWN);
if (!cachedRundown?.entries) { if (!cachedRundown?.entries) {
return; return;
@@ -68,11 +67,11 @@ export const useEventAction = () => {
); );
/** /**
* Calls mutation to add new event * Calls mutation to add new entry
* @private * @private
*/ */
const _addEventMutation = useMutation({ const _addEntryMutation = useMutation({
mutationFn: requestPostEvent, mutationFn: postAddEntry,
onSettled: () => { onSettled: () => {
queryClient.invalidateQueries({ queryKey: RUNDOWN }); queryClient.invalidateQueries({ queryKey: RUNDOWN });
}, },
@@ -80,14 +79,14 @@ export const useEventAction = () => {
}); });
/** /**
* Adds an event to rundown * Adds an entry to rundown
*/ */
const addEvent = useCallback( const addEntry = useCallback(
async (event: Partial<OntimeEvent | OntimeDelay | OntimeBlock>, options?: EventOptions) => { async (entry: Partial<OntimeEntry>, options?: EventOptions) => {
const newEvent: TransientEventPayload = { ...event }; const newEntry: TransientEventPayload = { ...entry };
// ************* CHECK OPTIONS specific to events // ************* CHECK OPTIONS specific to events
if (isOntimeEvent(newEvent)) { if (isOntimeEvent(newEntry)) {
// merge creation time options with event settings // merge creation time options with event settings
const applicationOptions = { const applicationOptions = {
after: options?.after, after: options?.after,
@@ -102,57 +101,57 @@ export const useEventAction = () => {
const rundownData = queryClient.getQueryData<Rundown>(RUNDOWN)!; const rundownData = queryClient.getQueryData<Rundown>(RUNDOWN)!;
const previousEvent = rundownData.entries[applicationOptions.lastEventId]; const previousEvent = rundownData.entries[applicationOptions.lastEventId];
if (isOntimeEvent(previousEvent)) { if (isOntimeEvent(previousEvent)) {
newEvent.timeStart = previousEvent.timeEnd; newEntry.timeStart = previousEvent.timeEnd;
} }
} }
// Override event with options from editor settings // Override event with options from editor settings
newEvent.linkStart = applicationOptions.linkPrevious; newEntry.linkStart = applicationOptions.linkPrevious;
newEvent.isPublic = applicationOptions.defaultPublic; newEntry.isPublic = applicationOptions.defaultPublic;
if (newEvent.duration === undefined && newEvent.timeEnd === undefined) { if (newEntry.duration === undefined && newEntry.timeEnd === undefined) {
newEvent.duration = parseUserTime(defaultDuration); newEntry.duration = parseUserTime(defaultDuration);
} }
if (newEvent.timeDanger === undefined) { if (newEntry.timeDanger === undefined) {
newEvent.timeDanger = parseUserTime(defaultDangerTime); newEntry.timeDanger = parseUserTime(defaultDangerTime);
} }
if (newEvent.timeWarning === undefined) { if (newEntry.timeWarning === undefined) {
newEvent.timeWarning = parseUserTime(defaultWarnTime); newEntry.timeWarning = parseUserTime(defaultWarnTime);
} }
if (newEvent.timerType === undefined) { if (newEntry.timerType === undefined) {
newEvent.timerType = defaultTimerType; newEntry.timerType = defaultTimerType;
} }
if (newEvent.endAction === undefined) { if (newEntry.endAction === undefined) {
newEvent.endAction = defaultEndAction; newEntry.endAction = defaultEndAction;
} }
if (newEvent.timeStrategy === undefined) { if (newEntry.timeStrategy === undefined) {
newEvent.timeStrategy = defaultTimeStrategy; newEntry.timeStrategy = defaultTimeStrategy;
} }
} }
// handle adding options that concern all event type // handle adding options that concern all event type
if (options?.after) { if (options?.after) {
// @ts-expect-error -- not sure how to type this, <after> is a transient property // @ts-expect-error -- not sure how to type this, <after> is a transient property
newEvent.after = options.after; newEntry.after = options.after;
} }
if (options?.before) { if (options?.before) {
// @ts-expect-error -- not sure how to type this, <before> is a transient property // @ts-expect-error -- not sure how to type this, <before> is a transient property
newEvent.before = options.before; newEntry.before = options.before;
} }
try { try {
await _addEventMutation.mutateAsync(newEvent as TransientEventPayload); await _addEntryMutation.mutateAsync(newEntry as TransientEventPayload);
} catch (error) { } catch (error) {
logAxiosError('Failed adding event', error); logAxiosError('Failed adding event', error);
} }
}, },
[ [
_addEventMutation, _addEntryMutation,
defaultDangerTime, defaultDangerTime,
defaultDuration, defaultDuration,
defaultEndAction, defaultEndAction,
@@ -166,11 +165,11 @@ export const useEventAction = () => {
); );
/** /**
* Calls mutation to update existing event * Calls mutation to update existing entry
* @private * @private
*/ */
const _updateEventMutation = useMutation({ const _updateEntryMutation = useMutation({
mutationFn: requestPutEvent, mutationFn: putEditEntry,
// we optimistically update here // we optimistically update here
onMutate: async (newEvent) => { onMutate: async (newEvent) => {
// cancel ongoing queries // cancel ongoing queries
@@ -210,35 +209,35 @@ export const useEventAction = () => {
}); });
/** /**
* Updates existing event * Updates existing entry
*/ */
const updateEvent = useCallback( const updateEntry = useCallback(
async (event: Partial<OntimeEntry>) => { async (event: Partial<OntimeEntry>) => {
try { try {
await _updateEventMutation.mutateAsync(event); await _updateEntryMutation.mutateAsync(event);
} catch (error) { } catch (error) {
logAxiosError('Error updating event', error); logAxiosError('Error updating event', error);
} }
}, },
[_updateEventMutation], [_updateEntryMutation],
); );
const updateCustomField = useCallback( const updateCustomField = useCallback(
async (eventId: string, field: string, value: string) => { async (entryId: EntryId, field: string, value: string) => {
updateEvent({ id: eventId, custom: { [field]: value } }); updateEntry({ id: entryId, custom: { [field]: value } });
}, },
[updateEvent], [updateEntry],
); );
/** /**
* Updates time of existing event * Updates time of existing event
* @param eventId {string} - id of the event * @param eventId {EntryId} - id of the event
* @param field {TimeField} - field to update * @param field {TimeField} - field to update
* @param value {string} - new value string to be parsed * @param value {string} - new value string to be parsed
* @param lockOnUpdate {boolean} - whether we will apply the lock / release on update * @param lockOnUpdate {boolean} - whether we will apply the lock / release on update
*/ */
const updateTimer = useCallback( const updateTimer = useCallback(
async (eventId: string, field: TimeField, value: string, lockOnUpdate?: boolean) => { async (eventId: EntryId, field: TimeField, value: string, lockOnUpdate?: boolean) => {
// an empty value with no lock has no domain validity // an empty value with no lock has no domain validity
if (!lockOnUpdate && value === '') { if (!lockOnUpdate && value === '') {
return; return;
@@ -268,7 +267,7 @@ export const useEventAction = () => {
} }
try { try {
await _updateEventMutation.mutateAsync(newEvent); await _updateEntryMutation.mutateAsync(newEvent);
} catch (error) { } catch (error) {
logAxiosError('Error updating event', error); logAxiosError('Error updating event', error);
} }
@@ -320,7 +319,7 @@ export const useEventAction = () => {
return previousEnd; return previousEnd;
} }
}, },
[_updateEventMutation, queryClient], [_updateEntryMutation, queryClient],
); );
/** /**
@@ -328,7 +327,7 @@ export const useEventAction = () => {
* @private * @private
*/ */
const _batchUpdateEventsMutation = useMutation({ const _batchUpdateEventsMutation = useMutation({
mutationFn: requestBatchPutEvents, mutationFn: putBatchEditEvents,
onMutate: async ({ ids, data }) => { onMutate: async ({ ids, data }) => {
// cancel ongoing queries // cancel ongoing queries
await queryClient.cancelQueries({ queryKey: RUNDOWN }); await queryClient.cancelQueries({ queryKey: RUNDOWN });
@@ -360,6 +359,7 @@ export const useEventAction = () => {
revision: -1, revision: -1,
}); });
} }
// Return a context with the previous rundown // Return a context with the previous rundown
return { previousRundown }; return { previousRundown };
}, },
@@ -384,13 +384,13 @@ export const useEventAction = () => {
); );
/** /**
* Calls mutation to delete an event * Calls mutation to delete an entry
* @private * @private
*/ */
const _deleteEventMutation = useMutation({ const _deleteEntryMutation = useMutation({
mutationFn: requestDelete, mutationFn: deleteEntries,
// we optimistically update here // we optimistically update here
onMutate: async (eventIds: string[]) => { onMutate: async (entryIds: EntryId[]) => {
// cancel ongoing queries // cancel ongoing queries
await queryClient.cancelQueries({ queryKey: RUNDOWN }); await queryClient.cancelQueries({ queryKey: RUNDOWN });
@@ -399,9 +399,9 @@ export const useEventAction = () => {
if (previousData) { if (previousData) {
// optimistically update object // optimistically update object
const newOrder = previousData.order.filter((id) => !eventIds.includes(id)); const newOrder = previousData.order.filter((id) => !entryIds.includes(id));
const newRundown = { ...previousData.entries }; const newRundown = { ...previousData.entries };
for (const eventId of eventIds) { for (const eventId of entryIds) {
delete newRundown[eventId]; delete newRundown[eventId];
} }
@@ -419,7 +419,7 @@ export const useEventAction = () => {
}, },
// Mutation fails, rollback undoes optimist update // Mutation fails, rollback undoes optimist update
onError: (_error, _eventId, context) => { onError: (_error, _entryIds, context) => {
queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData); queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData);
}, },
// Mutation finished, failed or successful // Mutation finished, failed or successful
@@ -431,24 +431,24 @@ export const useEventAction = () => {
}); });
/** /**
* Deletes an event form the list * Deletes an event entry from the rundown
*/ */
const deleteEvent = useCallback( const deleteEntry = useCallback(
async (eventIds: string[]) => { async (entryIds: EntryId[]) => {
try { try {
await _deleteEventMutation.mutateAsync(eventIds); await _deleteEntryMutation.mutateAsync(entryIds);
} catch (error) { } catch (error) {
logAxiosError('Error deleting event', error); logAxiosError('Error deleting event', error);
} }
}, },
[_deleteEventMutation], [_deleteEntryMutation],
); );
/** /**
* Calls mutation to delete all events * Calls mutation to delete all events
* @private * @private
*/ */
const _deleteAllEventsMutation = useMutation({ const _deleteAllEntriesMutation = useMutation({
mutationFn: requestDeleteAll, mutationFn: requestDeleteAll,
// we optimistically update here // we optimistically update here
onMutate: async () => { onMutate: async () => {
@@ -471,8 +471,8 @@ export const useEventAction = () => {
return { previousData }; return { previousData };
}, },
// Mutation fails, rollback undos optimist update // Mutation fails, rollback optimist update
onError: (_error, _eventId, context) => { onError: (_error, _, context) => {
queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData); queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData);
}, },
// Mutation finished, failed or successful // Mutation finished, failed or successful
@@ -484,15 +484,15 @@ export const useEventAction = () => {
}); });
/** /**
* Deletes all events from list * Deletes all entries in the rundown
*/ */
const deleteAllEvents = useCallback(async () => { const deleteAllEntries = useCallback(async () => {
try { try {
await _deleteAllEventsMutation.mutateAsync(); await _deleteAllEntriesMutation.mutateAsync();
} catch (error) { } catch (error) {
logAxiosError('Error deleting events', error); logAxiosError('Error deleting events', error);
} }
}, [_deleteAllEventsMutation]); }, [_deleteAllEntriesMutation]);
/** /**
* Calls mutation to apply a delay * Calls mutation to apply a delay
@@ -508,7 +508,7 @@ export const useEventAction = () => {
}); });
/** /**
* Applies a given delay block * Applies a given delay
*/ */
const applyDelay = useCallback( const applyDelay = useCallback(
async (delayEventId: string) => { async (delayEventId: string) => {
@@ -522,11 +522,11 @@ export const useEventAction = () => {
); );
/** /**
* Calls mutation to reorder an event * Calls mutation to reorder an entry
* @private * @private
*/ */
const _reorderEventMutation = useMutation({ const _reorderEntryMutation = useMutation({
mutationFn: requestReorderEvent, mutationFn: patchReorderEntry,
// we optimistically update here // we optimistically update here
onMutate: async (data) => { onMutate: async (data) => {
// cancel ongoing queries // cancel ongoing queries
@@ -552,7 +552,7 @@ export const useEventAction = () => {
}, },
// Mutation fails, rollback undoes optimist update // Mutation fails, rollback undoes optimist update
onError: (_error, _eventId, context) => { onError: (_error, _data, context) => {
queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData); queryClient.setQueryData<Rundown>(RUNDOWN, context?.previousData);
}, },
// Mutation finished, failed or successful // Mutation finished, failed or successful
@@ -564,22 +564,22 @@ export const useEventAction = () => {
}); });
/** /**
* Reorders a given event * Reorders a given entry
*/ */
const reorderEvent = useCallback( const reorderEntry = useCallback(
async (eventId: string, from: number, to: number) => { async (entryId: string, from: number, to: number) => {
try { try {
const reorderObject: ReorderEntry = { const reorderObject: ReorderEntry = {
eventId, eventId: entryId,
from, from,
to, to,
}; };
await _reorderEventMutation.mutateAsync(reorderObject); await _reorderEntryMutation.mutateAsync(reorderObject);
} catch (error) { } catch (error) {
logAxiosError('Error re-ordering event', error); logAxiosError('Error re-ordering event', error);
} }
}, },
[_reorderEventMutation], [_reorderEntryMutation],
); );
/** /**
@@ -649,15 +649,15 @@ export const useEventAction = () => {
); );
return { return {
addEvent, addEntry,
applyDelay, applyDelay,
batchUpdateEvents, batchUpdateEvents,
deleteEvent, deleteEntry,
deleteAllEvents, deleteAllEntries,
getEventById, getEntryById,
reorderEvent, reorderEntry,
swapEvents, swapEvents,
updateEvent, updateEntry,
updateTimer, updateTimer,
updateCustomField, updateCustomField,
}; };
@@ -2,7 +2,7 @@ import { useRef, useState } from 'react';
import { Button, Textarea } from '@chakra-ui/react'; import { Button, Textarea } from '@chakra-ui/react';
import { OntimeEvent } from 'ontime-types'; import { OntimeEvent } from 'ontime-types';
import { useEventAction } from '../../../common/hooks/useEventAction'; import { useEntryActions } from '../../../common/hooks/useEntryAction';
import type { EditEvent } from '../Operator'; import type { EditEvent } from '../Operator';
import style from './EditModal.module.scss'; import style from './EditModal.module.scss';
@@ -15,7 +15,7 @@ interface EditModalProps {
export default function EditModal(props: EditModalProps) { export default function EditModal(props: EditModalProps) {
const { event, onClose } = props; const { event, onClose } = props;
const { updateEvent } = useEventAction(); const { updateEntry } = useEntryActions();
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const inputRef = useRef<HTMLTextAreaElement[]>(new Array<HTMLTextAreaElement>()); const inputRef = useRef<HTMLTextAreaElement[]>(new Array<HTMLTextAreaElement>());
@@ -36,7 +36,7 @@ export default function EditModal(props: EditModalProps) {
}); });
if (patchObject.custom) { if (patchObject.custom) {
await updateEvent(patchObject); await updateEntry(patchObject);
} }
setLoading(false); setLoading(false);
+12 -12
View File
@@ -21,7 +21,7 @@ import {
reorderArray, reorderArray,
} from 'ontime-utils'; } from 'ontime-utils';
import { type EventOptions, useEventAction } from '../../common/hooks/useEventAction'; import { type EventOptions, useEntryActions } from '../../common/hooks/useEntryAction';
import useFollowComponent from '../../common/hooks/useFollowComponent'; import useFollowComponent from '../../common/hooks/useFollowComponent';
import { useRundownEditor } from '../../common/hooks/useSocket'; import { useRundownEditor } from '../../common/hooks/useSocket';
import { AppMode, useAppMode } from '../../common/stores/appModeStore'; import { AppMode, useAppMode } from '../../common/stores/appModeStore';
@@ -48,7 +48,7 @@ export default function Rundown({ data }: RundownProps) {
const [statefulEntries, setStatefulEntries] = useState<EntryId[]>(order); const [statefulEntries, setStatefulEntries] = useState<EntryId[]>(order);
const featureData = useRundownEditor(); const featureData = useRundownEditor();
const { addEvent, reorderEvent, deleteEvent } = useEventAction(); const { addEntry, reorderEntry, deleteEntry } = useEntryActions();
const { entryCopyId, setEntryCopyId } = useEntryCopy(); const { entryCopyId, setEntryCopyId } = useEntryCopy();
@@ -67,12 +67,12 @@ export default function Rundown({ data }: RundownProps) {
(cursor: string | null) => { (cursor: string | null) => {
if (!cursor) return; if (!cursor) return;
const { entry, index } = getPreviousNormal(entries, order, cursor); const { entry, index } = getPreviousNormal(entries, order, cursor);
deleteEvent([cursor]); deleteEntry([cursor]);
if (entry && index !== null) { if (entry && index !== null) {
setSelectedEvents({ id: entry.id, selectMode: 'click', index }); setSelectedEvents({ id: entry.id, selectMode: 'click', index });
} }
}, },
[entries, order, deleteEvent, setSelectedEvents], [entries, order, deleteEntry, setSelectedEvents],
); );
const insertCopyAtId = useCallback( const insertCopyAtId = useCallback(
@@ -86,10 +86,10 @@ export default function Rundown({ data }: RundownProps) {
if (cloneEntry?.type === SupportedEvent.Event) { if (cloneEntry?.type === SupportedEvent.Event) {
//if we don't have a cursor add the new event on top //if we don't have a cursor add the new event on top
const newEvent = cloneEvent(cloneEntry); const newEvent = cloneEvent(cloneEntry);
addEvent(newEvent, { after: adjustedCursor ?? undefined }); addEntry(newEvent, { after: adjustedCursor ?? undefined });
} }
}, },
[addEvent, order, entries], [addEntry, order, entries],
); );
const insertAtId = useCallback( const insertAtId = useCallback(
@@ -109,12 +109,12 @@ export default function Rundown({ data }: RundownProps) {
if (!above && id) { if (!above && id) {
options.lastEventId = id; options.lastEventId = id;
} }
addEvent(newEvent, options); addEntry(newEvent, options);
} else { } else {
addEvent({ type }, options); addEntry({ type }, options);
} }
}, },
[addEvent], [addEntry],
); );
const selectBlock = useCallback( const selectBlock = useCallback(
@@ -187,10 +187,10 @@ export default function Rundown({ data }: RundownProps) {
if (index !== null) { if (index !== null) {
const offsetIndex = direction === 'up' ? index + 1 : index - 1; const offsetIndex = direction === 'up' ? index + 1 : index - 1;
reorderEvent(cursor, offsetIndex, index); reorderEntry(cursor, offsetIndex, index);
} }
}, },
[order, reorderEvent, entries], [order, reorderEntry, entries],
); );
// shortcuts // shortcuts
@@ -254,7 +254,7 @@ export default function Rundown({ data }: RundownProps) {
setStatefulEntries((currentEntries) => { setStatefulEntries((currentEntries) => {
return reorderArray(currentEntries, fromIndex, toIndex); return reorderArray(currentEntries, fromIndex, toIndex);
}); });
reorderEvent(String(active.id), fromIndex, toIndex); reorderEntry(String(active.id), fromIndex, toIndex);
} }
} }
}; };
@@ -9,7 +9,7 @@ import {
SupportedEvent, SupportedEvent,
} from 'ontime-types'; } from 'ontime-types';
import { useEventAction } from '../../common/hooks/useEventAction'; import { useEntryActions } from '../../common/hooks/useEntryAction';
import useMemoisedFn from '../../common/hooks/useMemoisedFn'; import useMemoisedFn from '../../common/hooks/useMemoisedFn';
import { useEmitLog } from '../../common/stores/logger'; import { useEmitLog } from '../../common/stores/logger';
import { cloneEvent } from '../../common/utils/eventsManager'; import { cloneEvent } from '../../common/utils/eventsManager';
@@ -66,7 +66,7 @@ export default function RundownEntry(props: RundownEntryProps) {
isLinkedToLoaded, isLinkedToLoaded,
} = props; } = props;
const { emitError } = useEmitLog(); const { emitError } = useEmitLog();
const { addEvent, updateEvent, batchUpdateEvents, deleteEvent, swapEvents } = useEventAction(); const { addEntry, updateEntry, batchUpdateEvents, deleteEntry, swapEvents } = useEntryActions();
const { selectedEvents, unselect, clearSelectedEvents } = useEventSelection(); const { selectedEvents, unselect, clearSelectedEvents } = useEventSelection();
const removeOpenEvent = useCallback(() => { const removeOpenEvent = useCallback(() => {
@@ -91,26 +91,26 @@ export default function RundownEntry(props: RundownEntryProps) {
after: data.id, after: data.id,
lastEventId: previousEventId, lastEventId: previousEventId,
}; };
return addEvent(newEvent, options); return addEntry(newEvent, options);
} }
case 'event-before': { case 'event-before': {
const newEvent = { type: SupportedEvent.Event }; const newEvent = { type: SupportedEvent.Event };
const options = { const options = {
after: previousEntryId, after: previousEntryId,
}; };
return addEvent(newEvent, options); return addEntry(newEvent, options);
} }
case 'delay': { case 'delay': {
return addEvent({ type: SupportedEvent.Delay }, { after: data.id }); return addEntry({ type: SupportedEvent.Delay }, { after: data.id });
} }
case 'delay-before': { case 'delay-before': {
return addEvent({ type: SupportedEvent.Delay }, { after: previousEntryId }); return addEntry({ type: SupportedEvent.Delay }, { after: previousEntryId });
} }
case 'block': { case 'block': {
return addEvent({ type: SupportedEvent.Block }, { after: data.id }); return addEntry({ type: SupportedEvent.Block }, { after: data.id });
} }
case 'block-before': { case 'block-before': {
return addEvent({ type: SupportedEvent.Block }, { after: previousEntryId }); return addEntry({ type: SupportedEvent.Block }, { after: previousEntryId });
} }
case 'swap': { case 'swap': {
const { value } = payload as FieldValue; const { value } = payload as FieldValue;
@@ -119,14 +119,14 @@ export default function RundownEntry(props: RundownEntryProps) {
case 'delete': { case 'delete': {
if (selectedEvents.size > 1) { if (selectedEvents.size > 1) {
clearMultiSelection(); clearMultiSelection();
return deleteEvent(Array.from(selectedEvents)); return deleteEntry(Array.from(selectedEvents));
} }
removeOpenEvent(); removeOpenEvent();
return deleteEvent([data.id]); return deleteEntry([data.id]);
} }
case 'clone': { case 'clone': {
const newEvent = cloneEvent(data as OntimeEvent); const newEvent = cloneEvent(data as OntimeEvent);
addEvent(newEvent, { after: data.id }); addEntry(newEvent, { after: data.id });
break; break;
} }
case 'update': { case 'update': {
@@ -147,7 +147,7 @@ export default function RundownEntry(props: RundownEntryProps) {
if (field in data) { if (field in data) {
// @ts-expect-error -- not sure how to type this // @ts-expect-error -- not sure how to type this
newData[field] = value; newData[field] = value;
return updateEvent(newData); return updateEntry(newData);
} }
return emitError(`Unknown field: ${field}`); return emitError(`Unknown field: ${field}`);
@@ -2,7 +2,7 @@ import { useCallback, useRef } from 'react';
import { Input } from '@chakra-ui/react'; import { Input } from '@chakra-ui/react';
import useReactiveTextInput from '../../../common/components/input/text-input/useReactiveTextInput'; import useReactiveTextInput from '../../../common/components/input/text-input/useReactiveTextInput';
import { useEventAction } from '../../../common/hooks/useEventAction'; import { useEntryActions } from '../../../common/hooks/useEntryAction';
import { cx } from '../../../common/utils/styleUtils'; import { cx } from '../../../common/utils/styleUtils';
import style from './TitleEditor.module.scss'; import style from './TitleEditor.module.scss';
@@ -16,7 +16,7 @@ interface TitleEditorProps {
export default function EditableBlockTitle(props: TitleEditorProps) { export default function EditableBlockTitle(props: TitleEditorProps) {
const { title, eventId, placeholder, className } = props; const { title, eventId, placeholder, className } = props;
const { updateEvent } = useEventAction(); const { updateEntry } = useEntryActions();
const ref = useRef<HTMLInputElement | null>(null); const ref = useRef<HTMLInputElement | null>(null);
const submitCallback = useCallback( const submitCallback = useCallback(
(text: string) => { (text: string) => {
@@ -25,9 +25,9 @@ export default function EditableBlockTitle(props: TitleEditorProps) {
} }
const cleanVal = text.trim(); const cleanVal = text.trim();
updateEvent({ id: eventId, title: cleanVal }); updateEntry({ id: eventId, title: cleanVal });
}, },
[title, updateEvent, eventId], [title, updateEntry, eventId],
); );
const { value, onChange, onBlur, onKeyDown } = useReactiveTextInput(title, submitCallback, ref, { const { value, onChange, onBlur, onKeyDown } = useReactiveTextInput(title, submitCallback, ref, {
@@ -6,7 +6,7 @@ import { CSS } from '@dnd-kit/utilities';
import { OntimeDelay } from 'ontime-types'; import { OntimeDelay } from 'ontime-types';
import DelayInput from '../../../common/components/input/delay-input/DelayInput'; import DelayInput from '../../../common/components/input/delay-input/DelayInput';
import { useEventAction } from '../../../common/hooks/useEventAction'; import { useEntryActions } from '../../../common/hooks/useEntryAction';
import { cx } from '../../../common/utils/styleUtils'; import { cx } from '../../../common/utils/styleUtils';
import style from './DelayBlock.module.scss'; import style from './DelayBlock.module.scss';
@@ -18,7 +18,7 @@ interface DelayBlockProps {
export default function DelayBlock(props: DelayBlockProps) { export default function DelayBlock(props: DelayBlockProps) {
const { data, hasCursor } = props; const { data, hasCursor } = props;
const { applyDelay, deleteEvent } = useEventAction(); const { applyDelay, deleteEntry } = useEntryActions();
const handleRef = useRef<null | HTMLSpanElement>(null); const handleRef = useRef<null | HTMLSpanElement>(null);
const { const {
@@ -48,7 +48,7 @@ export default function DelayBlock(props: DelayBlockProps) {
}; };
const cancelDelayHandler = () => { const cancelDelayHandler = () => {
deleteEvent([data.id]); deleteEntry([data.id]);
}; };
const blockClasses = cx([style.delay, hasCursor ? style.hasCursor : null]); const blockClasses = cx([style.delay, hasCursor ? style.hasCursor : null]);
@@ -2,7 +2,7 @@ import { memo, MouseEvent } from 'react';
import { IoPause, IoPlay, IoReload, IoRemoveCircle, IoRemoveCircleOutline } from 'react-icons/io5'; import { IoPause, IoPlay, IoReload, IoRemoveCircle, IoRemoveCircleOutline } from 'react-icons/io5';
import TooltipActionBtn from '../../../../common/components/buttons/TooltipActionBtn'; import TooltipActionBtn from '../../../../common/components/buttons/TooltipActionBtn';
import { useEventAction } from '../../../../common/hooks/useEventAction'; import { useEntryActions } from '../../../../common/hooks/useEntryAction';
import { setEventPlayback } from '../../../../common/hooks/useSocket'; import { setEventPlayback } from '../../../../common/hooks/useSocket';
import { tooltipDelayMid } from '../../../../ontimeConfig'; import { tooltipDelayMid } from '../../../../ontimeConfig';
@@ -34,11 +34,11 @@ interface EventBlockPlaybackProps {
const EventBlockPlayback = (props: EventBlockPlaybackProps) => { const EventBlockPlayback = (props: EventBlockPlaybackProps) => {
const { eventId, skip, isPlaying, isPaused, loaded, disablePlayback } = props; const { eventId, skip, isPlaying, isPaused, loaded, disablePlayback } = props;
const { updateEvent } = useEventAction(); const { updateEntry } = useEntryActions();
const toggleSkip = (event: MouseEvent) => { const toggleSkip = (event: MouseEvent) => {
event.stopPropagation(); event.stopPropagation();
updateEvent({ id: eventId, skip: !skip }); updateEntry({ id: eventId, skip: !skip });
}; };
const actionHandler = (event: MouseEvent) => { const actionHandler = (event: MouseEvent) => {
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
import { CustomFieldLabel, OntimeEvent } from 'ontime-types'; import { CustomFieldLabel, OntimeEvent } from 'ontime-types';
import AppLink from '../../../common/components/link/app-link/AppLink'; import AppLink from '../../../common/components/link/app-link/AppLink';
import { useEventAction } from '../../../common/hooks/useEventAction'; import { useEntryActions } from '../../../common/hooks/useEntryAction';
import useCustomFields from '../../../common/hooks-query/useCustomFields'; import useCustomFields from '../../../common/hooks-query/useCustomFields';
import * as Editor from '../../editors/editor-utils/EditorUtils'; import * as Editor from '../../editors/editor-utils/EditorUtils';
@@ -23,7 +23,7 @@ interface EventEditorProps {
export default function EventEditor(props: EventEditorProps) { export default function EventEditor(props: EventEditorProps) {
const { event } = props; const { event } = props;
const { data: customFields } = useCustomFields(); const { data: customFields } = useCustomFields();
const { updateEvent } = useEventAction(); const { updateEntry } = useEntryActions();
const isEditor = window.location.pathname.includes('editor'); const isEditor = window.location.pathname.includes('editor');
@@ -31,12 +31,12 @@ export default function EventEditor(props: EventEditorProps) {
(field: EditorUpdateFields, value: string) => { (field: EditorUpdateFields, value: string) => {
if (field.startsWith('custom-')) { if (field.startsWith('custom-')) {
const fieldLabel = field.split('custom-')[1]; const fieldLabel = field.split('custom-')[1];
updateEvent({ id: event?.id, custom: { [fieldLabel]: value } }); updateEntry({ id: event?.id, custom: { [fieldLabel]: value } });
} else { } else {
updateEvent({ id: event?.id, [field]: value }); updateEntry({ id: event?.id, [field]: value });
} }
}, },
[event?.id, updateEvent], [event?.id, updateEntry],
); );
if (!event) { if (!event) {
@@ -5,7 +5,7 @@ import { EndAction, TimerType, TimeStrategy } from 'ontime-types';
import { millisToString, parseUserTime } from 'ontime-utils'; import { millisToString, parseUserTime } from 'ontime-utils';
import TimeInput from '../../../../common/components/input/time-input/TimeInput'; import TimeInput from '../../../../common/components/input/time-input/TimeInput';
import { useEventAction } from '../../../../common/hooks/useEventAction'; import { useEntryActions } from '../../../../common/hooks/useEntryAction';
import { millisToDelayString } from '../../../../common/utils/dateConfig'; import { millisToDelayString } from '../../../../common/utils/dateConfig';
import * as Editor from '../../../editors/editor-utils/EditorUtils'; import * as Editor from '../../../editors/editor-utils/EditorUtils';
import TimeInputFlow from '../../time-input-flow/TimeInputFlow'; import TimeInputFlow from '../../time-input-flow/TimeInputFlow';
@@ -46,27 +46,27 @@ function EventEditorTimes(props: EventEditorTimesProps) {
timeWarning, timeWarning,
timeDanger, timeDanger,
} = props; } = props;
const { updateEvent } = useEventAction(); const { updateEntry } = useEntryActions();
const handleSubmit = (field: HandledActions, value: string | boolean) => { const handleSubmit = (field: HandledActions, value: string | boolean) => {
if (field === 'isPublic') { if (field === 'isPublic') {
updateEvent({ id: eventId, isPublic: !(value as boolean) }); updateEntry({ id: eventId, isPublic: !(value as boolean) });
return; return;
} }
if (field === 'countToEnd') { if (field === 'countToEnd') {
updateEvent({ id: eventId, countToEnd: !(value as boolean) }); updateEntry({ id: eventId, countToEnd: !(value as boolean) });
return; return;
} }
if (field === 'timeWarning' || field === 'timeDanger') { if (field === 'timeWarning' || field === 'timeDanger') {
const newTime = parseUserTime(value as string); const newTime = parseUserTime(value as string);
updateEvent({ id: eventId, [field]: newTime }); updateEntry({ id: eventId, [field]: newTime });
return; return;
} }
if (field === 'timerType' || field === 'endAction') { if (field === 'timerType' || field === 'endAction') {
updateEvent({ id: eventId, [field]: value }); updateEntry({ id: eventId, [field]: value });
return; return;
} }
}; };
@@ -3,7 +3,7 @@ import { IoAdd } from 'react-icons/io5';
import { Button } from '@chakra-ui/react'; import { Button } from '@chakra-ui/react';
import { MaybeString, SupportedEvent } from 'ontime-types'; import { MaybeString, SupportedEvent } from 'ontime-types';
import { useEventAction } from '../../../common/hooks/useEventAction'; import { useEntryActions } from '../../../common/hooks/useEntryAction';
import { useEmitLog } from '../../../common/stores/logger'; import { useEmitLog } from '../../../common/stores/logger';
import style from './QuickAddBlock.module.scss'; import style from './QuickAddBlock.module.scss';
@@ -17,7 +17,7 @@ export default memo(QuickAddBlock);
function QuickAddBlock(props: QuickAddBlockProps) { function QuickAddBlock(props: QuickAddBlockProps) {
const { previousEventId, showBlocks } = props; const { previousEventId, showBlocks } = props;
const { addEvent } = useEventAction(); const { addEntry } = useEntryActions();
const { emitError } = useEmitLog(); const { emitError } = useEmitLog();
const doLinkPrevious = useRef<HTMLInputElement | null>(null); const doLinkPrevious = useRef<HTMLInputElement | null>(null);
@@ -37,7 +37,7 @@ function QuickAddBlock(props: QuickAddBlockProps) {
lastEventId: previousEventId, lastEventId: previousEventId,
linkPrevious, linkPrevious,
}; };
addEvent(newEvent, options); addEntry(newEvent, options);
break; break;
} }
case 'delay': { case 'delay': {
@@ -45,7 +45,7 @@ function QuickAddBlock(props: QuickAddBlockProps) {
lastEventId: previousEventId, lastEventId: previousEventId,
after: previousEventId, after: previousEventId,
}; };
addEvent({ type: SupportedEvent.Delay }, options); addEntry({ type: SupportedEvent.Delay }, options);
break; break;
} }
case 'block': { case 'block': {
@@ -53,7 +53,7 @@ function QuickAddBlock(props: QuickAddBlockProps) {
lastEventId: previousEventId, lastEventId: previousEventId,
after: previousEventId, after: previousEventId,
}; };
addEvent({ type: SupportedEvent.Block }, options); addEntry({ type: SupportedEvent.Block }, options);
break; break;
} }
default: { default: {
@@ -62,7 +62,7 @@ function QuickAddBlock(props: QuickAddBlockProps) {
} }
} }
}, },
[previousEventId, addEvent, emitError], [previousEventId, addEntry, emitError],
); );
return ( return (
@@ -11,23 +11,23 @@ import {
useDisclosure, useDisclosure,
} from '@chakra-ui/react'; } from '@chakra-ui/react';
import { useEventAction } from '../../../common/hooks/useEventAction'; import { useEntryActions } from '../../../common/hooks/useEntryAction';
import { useAppMode } from '../../../common/stores/appModeStore'; import { useAppMode } from '../../../common/stores/appModeStore';
import { useEventSelection } from '../useEventSelection'; import { useEventSelection } from '../useEventSelection';
export default function RundownMenu() { export default function RundownMenu() {
const clearSelectedEvents = useEventSelection((state) => state.clearSelectedEvents); const clearSelectedEvents = useEventSelection((state) => state.clearSelectedEvents);
const appMode = useAppMode((state) => state.mode); const appMode = useAppMode((state) => state.mode);
const { deleteAllEvents } = useEventAction(); const { deleteAllEntries } = useEntryActions();
const { isOpen, onOpen, onClose } = useDisclosure(); const { isOpen, onOpen, onClose } = useDisclosure();
const cancelRef = useRef<HTMLButtonElement | null>(null); const cancelRef = useRef<HTMLButtonElement | null>(null);
const deleteAll = useCallback(() => { const deleteAll = useCallback(() => {
deleteAllEvents(); deleteAllEntries();
clearSelectedEvents(); clearSelectedEvents();
onClose(); onClose();
}, [clearSelectedEvents, deleteAllEvents, onClose]); }, [clearSelectedEvents, deleteAllEntries, onClose]);
return ( return (
<> <>
@@ -5,7 +5,7 @@ import { TimeField, TimeStrategy } from 'ontime-types';
import { dayInMs } from 'ontime-utils'; import { dayInMs } from 'ontime-utils';
import TimeInputWithButton from '../../../common/components/input/time-input/TimeInputWithButton'; import TimeInputWithButton from '../../../common/components/input/time-input/TimeInputWithButton';
import { useEventAction } from '../../../common/hooks/useEventAction'; import { useEntryActions } from '../../../common/hooks/useEntryAction';
import { cx } from '../../../common/utils/styleUtils'; import { cx } from '../../../common/utils/styleUtils';
import { tooltipDelayFast, tooltipDelayMid } from '../../../ontimeConfig'; import { tooltipDelayFast, tooltipDelayMid } from '../../../ontimeConfig';
import * as Editor from '../../editors/editor-utils/EditorUtils'; import * as Editor from '../../editors/editor-utils/EditorUtils';
@@ -26,7 +26,7 @@ interface EventBlockTimerProps {
function TimeInputFlow(props: EventBlockTimerProps) { function TimeInputFlow(props: EventBlockTimerProps) {
const { eventId, countToEnd, timeStart, timeEnd, duration, timeStrategy, linkStart, delay, showLabels } = props; const { eventId, countToEnd, timeStart, timeEnd, duration, timeStrategy, linkStart, delay, showLabels } = props;
const { updateEvent, updateTimer } = useEventAction(); const { updateEntry, updateTimer } = useEntryActions();
// In sync with EventEditorTimes // In sync with EventEditorTimes
const handleSubmit = (field: TimeField, value: string) => { const handleSubmit = (field: TimeField, value: string) => {
@@ -34,11 +34,11 @@ function TimeInputFlow(props: EventBlockTimerProps) {
}; };
const handleChangeStrategy = (timeStrategy: TimeStrategy) => { const handleChangeStrategy = (timeStrategy: TimeStrategy) => {
updateEvent({ id: eventId, timeStrategy }); updateEntry({ id: eventId, timeStrategy });
}; };
const handleLink = (doLink: boolean) => { const handleLink = (doLink: boolean) => {
updateEvent({ id: eventId, linkStart: doLink }); updateEntry({ id: eventId, linkStart: doLink });
}; };
const warnings = []; const warnings = [];
@@ -1,5 +1,5 @@
import { MouseEvent } from 'react'; import { MouseEvent } from 'react';
import { isOntimeEvent, MaybeNumber, MaybeString, OntimeEvent, Rundown } from 'ontime-types'; import { EntryId, isOntimeEvent, MaybeNumber, MaybeString, Rundown } from 'ontime-types';
import { create } from 'zustand'; import { create } from 'zustand';
import { RUNDOWN } from '../../common/api/constants'; import { RUNDOWN } from '../../common/api/constants';
@@ -66,11 +66,11 @@ export const useEventSelection = create<EventSelectionStore>()((set, get) => ({
if (!rundownData) return; if (!rundownData) return;
// get list of rundown with only ontime events // get list of rundown with only ontime events
const events: OntimeEvent[] = []; const eventIds: EntryId[] = [];
rundownData.order.forEach((eventId) => { rundownData.flatOrder.forEach((eventId) => {
const event = rundownData.entries[eventId]; const event = rundownData.entries[eventId];
if (isOntimeEvent(event)) { if (isOntimeEvent(event)) {
events.push(event); eventIds.push(event.id);
} }
}); });
@@ -78,7 +78,7 @@ export const useEventSelection = create<EventSelectionStore>()((set, get) => ({
const end = anchoredIndex === null ? index : Math.max(anchoredIndex, index + 1); const end = anchoredIndex === null ? index : Math.max(anchoredIndex, index + 1);
// create new set with range of ids from start to end // create new set with range of ids from start to end
const selectedEventIds = events.slice(start, end).map((event) => event.id); const selectedEventIds = eventIds.slice(start, end);
return set({ return set({
selectedEvents: new Set([...selectedEvents, ...selectedEventIds]), selectedEvents: new Set([...selectedEvents, ...selectedEventIds]),
@@ -3,7 +3,7 @@ import { useTableNav } from '@table-nav/react';
import { ColumnDef, getCoreRowModel, useReactTable } from '@tanstack/react-table'; import { ColumnDef, getCoreRowModel, useReactTable } from '@tanstack/react-table';
import { isOntimeEvent, MaybeString, OntimeEntry, OntimeEvent, TimeField } from 'ontime-types'; import { isOntimeEvent, MaybeString, OntimeEntry, OntimeEvent, TimeField } from 'ontime-types';
import { useEventAction } from '../../../common/hooks/useEventAction'; import { useEntryActions } from '../../../common/hooks/useEntryAction';
import useFollowComponent from '../../../common/hooks/useFollowComponent'; import useFollowComponent from '../../../common/hooks/useFollowComponent';
import { useCuesheetOptions } from '../cuesheet.options'; import { useCuesheetOptions } from '../cuesheet.options';
@@ -24,7 +24,7 @@ interface CuesheetTableProps {
export default function CuesheetTable(props: CuesheetTableProps) { export default function CuesheetTable(props: CuesheetTableProps) {
const { data, columns, showModal } = props; const { data, columns, showModal } = props;
const { updateEvent, updateTimer } = useEventAction(); const { updateEntry, updateTimer } = useEntryActions();
const { followSelected, showDelayedTimes, hideTableSeconds } = useCuesheetOptions(); const { followSelected, showDelayedTimes, hideTableSeconds } = useCuesheetOptions();
const { columnVisibility, columnOrder, columnSizing, resetColumnOrder, setColumnVisibility, setColumnSizing } = const { columnVisibility, columnOrder, columnSizing, resetColumnOrder, setColumnVisibility, setColumnSizing } =
useColumnManager(columns); useColumnManager(columns);
@@ -64,11 +64,11 @@ export default function CuesheetTable(props: CuesheetTableProps) {
} }
if (isCustom) { if (isCustom) {
updateEvent({ id: event.id, custom: { [accessor]: payload } }); updateEntry({ id: event.id, custom: { [accessor]: payload } });
return; return;
} }
updateEvent({ id: event.id, [accessor]: payload }); updateEntry({ id: event.id, [accessor]: payload });
}, },
handleUpdateTimer: (eventId: string, field: TimeField, payload) => { handleUpdateTimer: (eventId: string, field: TimeField, payload) => {
// the timer element already contains logic to avoid submitting a unchanged value // the timer element already contains logic to avoid submitting a unchanged value
@@ -2,7 +2,7 @@ import { IoAdd, IoArrowDown, IoArrowUp, IoDuplicateOutline, IoOptions, IoTrash }
import { MenuDivider, MenuItem, MenuList } from '@chakra-ui/react'; import { MenuDivider, MenuItem, MenuList } from '@chakra-ui/react';
import { isOntimeEvent, SupportedEvent } from 'ontime-types'; import { isOntimeEvent, SupportedEvent } from 'ontime-types';
import { useEventAction } from '../../../../common/hooks/useEventAction'; import { useEntryActions } from '../../../../common/hooks/useEntryAction';
import { cloneEvent } from '../../../../common/utils/eventsManager'; import { cloneEvent } from '../../../../common/utils/eventsManager';
interface CuesheetTableMenuActionsProps { interface CuesheetTableMenuActionsProps {
@@ -13,17 +13,17 @@ interface CuesheetTableMenuActionsProps {
export default function CuesheetTableMenuActions(props: CuesheetTableMenuActionsProps) { export default function CuesheetTableMenuActions(props: CuesheetTableMenuActionsProps) {
const { eventId, entryIndex, showModal } = props; const { eventId, entryIndex, showModal } = props;
const { addEvent, getEventById, reorderEvent, deleteEvent } = useEventAction(); const { addEntry, getEntryById, reorderEntry, deleteEntry } = useEntryActions();
const handleCloneEvent = () => { const handleCloneEvent = () => {
const currentEvent = getEventById(eventId); const currentEvent = getEntryById(eventId);
if (!currentEvent || !isOntimeEvent(currentEvent)) { if (!currentEvent || !isOntimeEvent(currentEvent)) {
return; return;
} }
const newEvent = cloneEvent(currentEvent); const newEvent = cloneEvent(currentEvent);
try { try {
addEvent(newEvent, { after: eventId }); addEntry(newEvent, { after: eventId });
} catch (_error) { } catch (_error) {
// we do not handle errors here // we do not handle errors here
} }
@@ -35,10 +35,10 @@ export default function CuesheetTableMenuActions(props: CuesheetTableMenuActions
Edit ... Edit ...
</MenuItem> </MenuItem>
<MenuDivider /> <MenuDivider />
<MenuItem icon={<IoAdd />} onClick={() => addEvent({ type: SupportedEvent.Event }, { before: eventId })}> <MenuItem icon={<IoAdd />} onClick={() => addEntry({ type: SupportedEvent.Event }, { before: eventId })}>
Add event above Add event above
</MenuItem> </MenuItem>
<MenuItem icon={<IoAdd />} onClick={() => addEvent({ type: SupportedEvent.Event }, { after: eventId })}> <MenuItem icon={<IoAdd />} onClick={() => addEntry({ type: SupportedEvent.Event }, { after: eventId })}>
Add event below Add event below
</MenuItem> </MenuItem>
<MenuItem icon={<IoDuplicateOutline />} onClick={handleCloneEvent}> <MenuItem icon={<IoDuplicateOutline />} onClick={handleCloneEvent}>
@@ -48,14 +48,14 @@ export default function CuesheetTableMenuActions(props: CuesheetTableMenuActions
<MenuItem <MenuItem
isDisabled={entryIndex < 1} isDisabled={entryIndex < 1}
icon={<IoArrowUp />} icon={<IoArrowUp />}
onClick={() => reorderEvent(eventId, entryIndex, entryIndex - 1)} onClick={() => reorderEntry(eventId, entryIndex, entryIndex - 1)}
> >
Move up Move up
</MenuItem> </MenuItem>
<MenuItem icon={<IoArrowDown />} onClick={() => reorderEvent(eventId, entryIndex, entryIndex + 1)}> <MenuItem icon={<IoArrowDown />} onClick={() => reorderEntry(eventId, entryIndex, entryIndex + 1)}>
Move down Move down
</MenuItem> </MenuItem>
<MenuItem icon={<IoTrash />} onClick={() => deleteEvent([eventId])}> <MenuItem icon={<IoTrash />} onClick={() => deleteEntry([eventId])}>
Delete Delete
</MenuItem> </MenuItem>
</MenuList> </MenuList>
@@ -8,13 +8,13 @@ import {
addEvent, addEvent,
applyDelay, applyDelay,
batchEditEvents, batchEditEvents,
deleteAllEvents, deleteAllEntries,
deleteEvent, deleteEvent,
editEvent, editEvent,
reorderEvent, reorderEntry,
swapEvents, swapEvents,
} from '../../services/rundown-service/RundownService.js'; } from '../../services/rundown-service/RundownService.js';
import { getEventWithId, getCurrentRundown } from '../../services/rundown-service/rundownUtils.js'; import { getEntryWithId, getCurrentRundown } from '../../services/rundown-service/rundownUtils.js';
export async function rundownGetAll(_req: Request, res: Response<ProjectRundownsList>) { export async function rundownGetAll(_req: Request, res: Response<ProjectRundownsList>) {
const rundown = getCurrentRundown(); const rundown = getCurrentRundown();
@@ -30,7 +30,7 @@ export async function rundownGetById(req: Request, res: Response<OntimeEntry | E
const { eventId } = req.params; const { eventId } = req.params;
try { try {
const event = getEventWithId(eventId); const event = getEntryWithId(eventId);
if (!event) { if (!event) {
res.status(404).send({ message: 'Event not found' }); res.status(404).send({ message: 'Event not found' });
@@ -93,7 +93,7 @@ export async function rundownReorder(req: Request, res: Response<OntimeEntry | E
try { try {
const { eventId, from, to } = req.body; const { eventId, from, to } = req.body;
const event = await reorderEvent(eventId, from, to); const event = await reorderEntry(eventId, from, to);
res.status(200).send(event.newEvent); res.status(200).send(event.newEvent);
} catch (error) { } catch (error) {
const message = getErrorMessage(error); const message = getErrorMessage(error);
@@ -128,7 +128,7 @@ export async function rundownApplyDelay(req: Request, res: Response<MessageRespo
export async function rundownDelete(_req: Request, res: Response<MessageResponse | ErrorResponse>) { export async function rundownDelete(_req: Request, res: Response<MessageResponse | ErrorResponse>) {
try { try {
await deleteAllEvents(); await deleteAllEntries();
res.status(204).send({ message: 'All events deleted' }); res.status(204).send({ message: 'All events deleted' });
} catch (error) { } catch (error) {
const message = getErrorMessage(error); const message = getErrorMessage(error);
@@ -2,7 +2,7 @@ import { EndAction, OntimeEvent, TimerType, isKeyOfType, isOntimeEvent } from 'o
import { MILLIS_PER_SECOND, maxDuration } from 'ontime-utils'; import { MILLIS_PER_SECOND, maxDuration } from 'ontime-utils';
import { editEvent } from '../services/rundown-service/RundownService.js'; import { editEvent } from '../services/rundown-service/RundownService.js';
import { getEventWithId } from '../services/rundown-service/rundownUtils.js'; import { getEntryWithId } from '../services/rundown-service/rundownUtils.js';
import { coerceBoolean, coerceColour, coerceEnum, coerceNumber, coerceString } from '../utils/coerceType.js'; import { coerceBoolean, coerceColour, coerceEnum, coerceNumber, coerceString } from '../utils/coerceType.js';
import { getDataProvider } from '../classes/data-provider/DataProvider.js'; import { getDataProvider } from '../classes/data-provider/DataProvider.js';
@@ -64,7 +64,7 @@ export function parseProperty(property: string, value: unknown) {
* @param {Partial<OntimeEvent>} patchEvent * @param {Partial<OntimeEvent>} patchEvent
*/ */
export function updateEvent(patchEvent: Partial<OntimeEvent> & { id: string }) { export function updateEvent(patchEvent: Partial<OntimeEvent> & { id: string }) {
const event = getEventWithId(patchEvent?.id ?? ''); const event = getEntryWithId(patchEvent?.id ?? '');
if (!event) { if (!event) {
throw new Error(`Event with ID ${patchEvent?.id} not found`); throw new Error(`Event with ID ${patchEvent?.id} not found`);
} }
@@ -126,9 +126,9 @@ export async function deleteEvent(eventIds: string[]) {
} }
/** /**
* deletes all events in database * deletes all entries in database
*/ */
export async function deleteAllEvents() { export async function deleteAllEntries() {
const scopedMutation = cache.mutateCache(cache.removeAll); const scopedMutation = cache.mutateCache(cache.removeAll);
await scopedMutation({}); await scopedMutation({});
@@ -182,12 +182,12 @@ export async function batchEditEvents(ids: string[], data: Partial<OntimeEvent>)
} }
/** /**
* reorders a given event * reorders a given entry
* @param {string} eventId - ID of event from, for sanity check * @param {string} eventId - ID of event from, for sanity check
* @param {number} from - index of event from * @param {number} from - index of event from
* @param {number} to - index of event to * @param {number} to - index of event to
*/ */
export async function reorderEvent(eventId: string, from: number, to: number) { export async function reorderEntry(eventId: EntryId, from: number, to: number) {
const scopedMutation = cache.mutateCache(cache.reorder); const scopedMutation = cache.mutateCache(cache.reorder);
const reorderedItem = await scopedMutation({ eventId, from, to }); const reorderedItem = await scopedMutation({ eventId, from, to });
@@ -60,9 +60,9 @@ export function getEventAtIndex(eventIndex: number): OntimeEvent | undefined {
/** /**
* returns first event that matches a given ID * returns first event that matches a given ID
*/ */
export function getEventWithId(eventId: string): OntimeEntry | undefined { export function getEntryWithId(entryId: EntryId): OntimeEntry | undefined {
const { entries } = getCurrentRundown(); const { entries } = getCurrentRundown();
return entries[eventId]; return entries[entryId];
} }
/** /**
@@ -71,7 +71,7 @@ export function getEventWithId(eventId: string): OntimeEntry | undefined {
export function getFirstPlayable(playableOrder: EntryId[]): PlayableEvent | undefined { export function getFirstPlayable(playableOrder: EntryId[]): PlayableEvent | undefined {
const firstEventId = playableOrder.at(0); const firstEventId = playableOrder.at(0);
if (!firstEventId) return; if (!firstEventId) return;
return getEventWithId(firstEventId) as PlayableEvent | undefined; return getEntryWithId(firstEventId) as PlayableEvent | undefined;
} }
/** /**
@@ -84,7 +84,7 @@ export function getNextEventWithCue(targetCue: string, currentEventIndex = 0): O
for (let i = currentEventIndex; i < playableEventsOrder.length; i++) { for (let i = currentEventIndex; i < playableEventsOrder.length; i++) {
const eventId = playableEventsOrder[i]; const eventId = playableEventsOrder[i];
const event = getEventWithId(eventId) as PlayableEvent | undefined; const event = getEntryWithId(eventId) as PlayableEvent | undefined;
if (event?.cue.toLowerCase() === lowerCaseCue) { if (event?.cue.toLowerCase() === lowerCaseCue) {
return event; return event;
} }
@@ -114,7 +114,7 @@ export function findPrevious(currentEventId?: string): OntimeEvent | undefined {
return getFirstPlayable(playableEventsOrder); return getFirstPlayable(playableEventsOrder);
} }
return getEventWithId(previousEventId) as PlayableEvent | undefined; return getEntryWithId(previousEventId) as PlayableEvent | undefined;
} }
/** /**
@@ -140,7 +140,7 @@ export function findNext(currentEventId?: string): PlayableEvent | undefined {
return getFirstPlayable(playableEventsOrder); return getFirstPlayable(playableEventsOrder);
} }
return getEventWithId(nextEventId) as PlayableEvent | undefined; return getEntryWithId(nextEventId) as PlayableEvent | undefined;
} }
export function filterTimedEvents(rundown: Rundown, timedEventOrder: EntryId[]): OntimeEvent[] { export function filterTimedEvents(rundown: Rundown, timedEventOrder: EntryId[]): OntimeEvent[] {
@@ -30,7 +30,7 @@ import {
findPrevious, findPrevious,
getEventAtIndex, getEventAtIndex,
getNextEventWithCue, getNextEventWithCue,
getEventWithId, getEntryWithId,
getCurrentRundown, getCurrentRundown,
getTimedEvents, getTimedEvents,
getRundownData, getRundownData,
@@ -258,7 +258,7 @@ class RuntimeService {
if (safeOption || eventInMemory) { if (safeOption || eventInMemory) {
if (state.eventNow !== null) { if (state.eventNow !== null) {
// load stuff again, but keep running if our events still exist // load stuff again, but keep running if our events still exist
const eventNow = getEventWithId(state.eventNow.id); const eventNow = getEntryWithId(state.eventNow.id);
if (!isOntimeEvent(eventNow) || !isPlayableEvent(eventNow)) { if (!isOntimeEvent(eventNow) || !isPlayableEvent(eventNow)) {
// maybe the event was deleted or the skip state was changed // maybe the event was deleted or the skip state was changed
runtimeState.stop(); runtimeState.stop();
@@ -323,7 +323,7 @@ class RuntimeService {
*/ */
@broadcastResult @broadcastResult
public startById(eventId: string): boolean { public startById(eventId: string): boolean {
const event = getEventWithId(eventId); const event = getEntryWithId(eventId);
if (!event || !isOntimeEvent(event)) { if (!event || !isOntimeEvent(event)) {
return false; return false;
} }
@@ -377,7 +377,7 @@ class RuntimeService {
*/ */
@broadcastResult @broadcastResult
public loadById(eventId: string): boolean { public loadById(eventId: string): boolean {
const event = getEventWithId(eventId); const event = getEntryWithId(eventId);
if (!event || !isOntimeEvent(event)) { if (!event || !isOntimeEvent(event)) {
return false; return false;
} }
@@ -654,7 +654,7 @@ class RuntimeService {
// the db would have to change for the event not to exist // the db would have to change for the event not to exist
// we do not know the reason for the crash, so we check anyway // we do not know the reason for the crash, so we check anyway
const event = getEventWithId(selectedEventId); const event = getEntryWithId(selectedEventId);
if (!isOntimeEvent(event) || !isPlayableEvent(event)) { if (!isOntimeEvent(event) || !isPlayableEvent(event)) {
return; return;
} }