diff --git a/apps/client/src/common/api/rundown.ts b/apps/client/src/common/api/rundown.ts index dc9d5f7a5..267690ac4 100644 --- a/apps/client/src/common/api/rundown.ts +++ b/apps/client/src/common/api/rundown.ts @@ -95,14 +95,14 @@ export async function postCloneEntry(entryId: EntryId): Promise> { - return axios.post(`${rundownPath}/ungroup/${blockId}`); +export async function requestUngroup(groupId: EntryId): Promise> { + return axios.post(`${rundownPath}/ungroup/${groupId}`); } /** - * HTTP request for grouping a list of entries into a block + * HTTP request for grouping a list of entries into a group */ export async function requestGroupEntries(entryIds: EntryId[]): Promise> { return axios.post(`${rundownPath}/group`, { ids: entryIds }); diff --git a/apps/client/src/common/hooks/useEntryAction.ts b/apps/client/src/common/hooks/useEntryAction.ts index ffbe40335..0f8d78673 100644 --- a/apps/client/src/common/hooks/useEntryAction.ts +++ b/apps/client/src/common/hooks/useEntryAction.ts @@ -2,13 +2,14 @@ import { useCallback } from 'react'; import { useMutation, useQueryClient } from '@tanstack/react-query'; import { EntryId, - isOntimeBlock, isOntimeEvent, + isOntimeGroup, MaybeString, - OntimeBlock, OntimeEntry, OntimeEvent, + OntimeGroup, Rundown, + SupportedEntry, TimeField, TimeStrategy, TransientEventPayload, @@ -36,7 +37,7 @@ import { logAxiosError } from '../api/utils'; import { useEditorSettings } from '../stores/editorSettings'; export type EventOptions = Partial<{ - // options of any new entries (event / delay / block) + // options of any new entries (event / delay / group) after: MaybeString; before: MaybeString; // options of entries of type OntimeEvent @@ -552,7 +553,7 @@ export const useEntryActions = () => { ); /** - * Calls mutation to dissolve a block + * Calls mutation to dissolve a group * @private */ const { mutateAsync: ungroupMutation } = useMutation({ @@ -574,12 +575,12 @@ export const useEntryActions = () => { }); /** - * Deletes a block and moves its events to the top level + * Deletes a group and moves its events to the top level */ const ungroup = useCallback( - async (blockId: EntryId) => { + async (groupId: EntryId) => { try { - await ungroupMutation(blockId); + await ungroupMutation(groupId); } catch (error) { logAxiosError('Error dissolving group', error); } @@ -588,7 +589,7 @@ export const useEntryActions = () => { ); /** - * Calls mutation to create a block with a selection + * Calls mutation to create a group with a selection * @private */ const { mutateAsync: groupEntriesMutation } = useMutation({ @@ -610,7 +611,7 @@ export const useEntryActions = () => { }); /** - * Create a block with a selection + * Create a group with a selection */ const groupEntries = useCallback( async (entryIds: EntryId[]) => { @@ -674,8 +675,8 @@ export const useEntryActions = () => { } catch (error) { logAxiosError('Error re-ordering event', error); } - // the rundown needs to know whether we moved into a block - return rundown.entries[destinationId]?.type === 'block' ? destinationId : undefined; + // the rundown needs to know whether we moved into a group + return rundown.entries[destinationId]?.type === SupportedEntry.Group ? destinationId : undefined; }, [queryClient, reorderEntryMutation], ); @@ -798,12 +799,12 @@ function optimisticDeleteEntries(entryIds: EntryId[], rundown: Rundown) { } function deleteEntry(entry: OntimeEntry) { - if (isOntimeBlock(entry) || !entry.parent) { + if (isOntimeGroup(entry) || !entry.parent) { order = order.filter((id) => id !== entry.id); } else { const parent = entries[entry.parent]; if ('parent' in entries) { - (parent as OntimeBlock).entries = (parent as OntimeBlock).entries.filter( + (parent as OntimeGroup).entries = (parent as OntimeGroup).entries.filter( (parentEntry) => parentEntry !== entry.id, ); } diff --git a/apps/client/src/common/hooks/useSocket.ts b/apps/client/src/common/hooks/useSocket.ts index 941a49396..f1a7da0de 100644 --- a/apps/client/src/common/hooks/useSocket.ts +++ b/apps/client/src/common/hooks/useSocket.ts @@ -17,7 +17,6 @@ export const setClientRemote = { export const useRundownEditor = createSelector((state: RuntimeStore) => ({ playback: state.timer.playback, selectedEventId: state.eventNow?.id ?? null, - selectedBlockId: state.blockNow?.id ?? null, nextEventId: state.eventNext?.id ?? null, })); @@ -131,8 +130,8 @@ export const useSelectedEventId = createSelector((state: RuntimeStore) => ({ selectedEventId: state.eventNow?.id ?? null, })); -export const useCurrentBlockId = createSelector((state: RuntimeStore) => ({ - currentBlockId: state.blockNow?.id ?? null, +export const useCurrentGroupId = createSelector((state: RuntimeStore) => ({ + currentGroupId: state.groupNow?.id ?? null, })); export const setEventPlayback = { @@ -178,7 +177,7 @@ export const useRuntimePlaybackOverview = createSelector((state: RuntimeStore) = selectedEventIndex: state.runtime.selectedEventIndex, offset: state.runtime.offsetMode === OffsetMode.Absolute ? state.runtime.offsetAbs : state.runtime.offsetRel, - blockExpectedEnd: state.blockNow?.expectedEnd ?? null, + groupExpectedEnd: state.groupNow?.expectedEnd ?? null, })); export const useTimelineStatus = createSelector((state: RuntimeStore) => ({ diff --git a/apps/client/src/features/app-settings/panel/automations-panel/template-input/templateInput.utils.ts b/apps/client/src/features/app-settings/panel/automations-panel/template-input/templateInput.utils.ts index 9542b84f3..139fda596 100644 --- a/apps/client/src/features/app-settings/panel/automations-panel/template-input/templateInput.utils.ts +++ b/apps/client/src/features/app-settings/panel/automations-panel/template-input/templateInput.utils.ts @@ -25,8 +25,8 @@ const staticAutocompleteOptions = [ '{{runtime.plannedEnd}}', '{{runtime.actualStart}}', '{{runtime.expectedEnd}}', - '{{currentBlock.block}}', - '{{currentBlock.startedAt}}', + '{{currentGroup.id}}', + '{{currentGroup.startedAt}}', ]; const eventStaticPropertiesNow = [ diff --git a/apps/client/src/features/app-settings/panel/manage-panel/sources-panel/preview/PreviewRundown.tsx b/apps/client/src/features/app-settings/panel/manage-panel/sources-panel/preview/PreviewRundown.tsx index f456c1597..7d719ef6d 100644 --- a/apps/client/src/features/app-settings/panel/manage-panel/sources-panel/preview/PreviewRundown.tsx +++ b/apps/client/src/features/app-settings/panel/manage-panel/sources-panel/preview/PreviewRundown.tsx @@ -1,6 +1,6 @@ import { Fragment } from 'react'; import { IoLink } from 'react-icons/io5'; -import { CustomFields, isOntimeBlock, isOntimeEvent, Rundown } from 'ontime-types'; +import { CustomFields, isOntimeEvent, isOntimeGroup, Rundown } from 'ontime-types'; import { millisToString } from 'ontime-utils'; import Tag from '../../../../../../common/components/tag/Tag'; @@ -55,7 +55,7 @@ export default function PreviewRundown(props: PreviewRundownProps) { {rundown.order.map((entryId) => { const entry = rundown.entries[entryId]; - if (isOntimeBlock(entry)) { + if (isOntimeGroup(entry)) { return ( diff --git a/apps/client/src/features/operator/Operator.tsx b/apps/client/src/features/operator/Operator.tsx index 75fcc7a9a..22406b07c 100644 --- a/apps/client/src/features/operator/Operator.tsx +++ b/apps/client/src/features/operator/Operator.tsx @@ -1,5 +1,5 @@ import { Fragment, useCallback, useEffect, useMemo, useRef, useState } from 'react'; -import { isOntimeBlock, isOntimeEvent, OntimeView } from 'ontime-types'; +import { isOntimeEvent, isOntimeGroup, OntimeView } from 'ontime-types'; import EmptyPage from '../../common/components/state/EmptyPage'; import ViewParamsEditor from '../../common/components/view-params-editor/ViewParamsEditor'; @@ -16,8 +16,8 @@ import { getDefaultFormat } from '../../common/utils/time'; import EditModal from './edit-modal/EditModal'; import FollowButton from './follow-button/FollowButton'; -import OperatorBlock from './operator-block/OperatorBlock'; import OperatorEvent from './operator-event/OperatorEvent'; +import OperatorGroup from './operator-group/OperatorGroup'; import StatusBar from './status-bar/StatusBar'; import { getOperatorOptions, useOperatorOptions } from './operator.options'; import type { EditEvent } from './operator.types'; @@ -168,10 +168,10 @@ export default function Operator() { ); } - if (isOntimeBlock(entry)) { + if (isOntimeGroup(entry)) { return ( - + {entry.entries.map((nestedEntryId) => { const nestedEntry = data.entries[nestedEntryId]; if (!isOntimeEvent(nestedEntry)) { diff --git a/apps/client/src/features/operator/operator-block/OperatorBlock.tsx b/apps/client/src/features/operator/operator-block/OperatorBlock.tsx deleted file mode 100644 index fcadbba8f..000000000 --- a/apps/client/src/features/operator/operator-block/OperatorBlock.tsx +++ /dev/null @@ -1,13 +0,0 @@ -import { memo } from 'react'; - -import style from './OperatorBlock.module.scss'; - -interface OperatorBlockProps { - title: string; -} - -function OperatorBlock({ title }: OperatorBlockProps) { - return
{title}
; -} - -export default memo(OperatorBlock); diff --git a/apps/client/src/features/operator/operator-block/OperatorBlock.module.scss b/apps/client/src/features/operator/operator-group/OperatorGroup.module.scss similarity index 89% rename from apps/client/src/features/operator/operator-block/OperatorBlock.module.scss rename to apps/client/src/features/operator/operator-group/OperatorGroup.module.scss index 398592be1..44e29ab04 100644 --- a/apps/client/src/features/operator/operator-block/OperatorBlock.module.scss +++ b/apps/client/src/features/operator/operator-group/OperatorGroup.module.scss @@ -1,4 +1,4 @@ -.block { +.group { width: 100%; padding: 0.25rem 0.5rem; background-color: $gray-1350; @@ -7,7 +7,7 @@ // tablet @media (min-width: $min-tablet) { - .block { + .group { padding: 0.25rem 1rem; } } diff --git a/apps/client/src/features/operator/operator-group/OperatorGroup.tsx b/apps/client/src/features/operator/operator-group/OperatorGroup.tsx new file mode 100644 index 000000000..a30f9646e --- /dev/null +++ b/apps/client/src/features/operator/operator-group/OperatorGroup.tsx @@ -0,0 +1,12 @@ +import { memo } from 'react'; + +import style from './OperatorGroup.module.scss'; + +interface OperatorGroup { + title: string; +} + +export default memo(OperatorGroup); +function OperatorGroup({ title }: OperatorGroup) { + return
{title}
; +} diff --git a/apps/client/src/features/overview/composite/TimeElements.tsx b/apps/client/src/features/overview/composite/TimeElements.tsx index f85c739c5..d8fee75c8 100644 --- a/apps/client/src/features/overview/composite/TimeElements.tsx +++ b/apps/client/src/features/overview/composite/TimeElements.tsx @@ -8,13 +8,13 @@ import { TbFolderPin, TbFolderStar, } from 'react-icons/tb'; -import { OntimeBlock, OntimeEvent, TimerPhase, TimerType } from 'ontime-types'; +import { OntimeEvent, OntimeGroup, TimerPhase, TimerType } from 'ontime-types'; import { isPlaybackActive, millisToString } from 'ontime-utils'; import Tooltip from '../../../common/components/tooltip/Tooltip'; import { useClock, - useCurrentBlockId, + useCurrentGroupId, useNextFlag, useRuntimeOverview, useRuntimePlaybackOverview, @@ -98,15 +98,15 @@ export function MetadataTimes() { //TODO: there a some things here we still need to think about, mainly what to do whit the planed group duration in relation to the events function GroupTimes() { - const { clock, blockExpectedEnd } = useRuntimePlaybackOverview(); - const { currentBlockId } = useCurrentBlockId(); - const group = useEntry(currentBlockId) as OntimeBlock | null; + const { clock, groupExpectedEnd } = useRuntimePlaybackOverview(); + const { currentGroupId } = useCurrentGroupId(); + const group = useEntry(currentGroupId) as OntimeGroup | null; // the group end time dose not encode any day offsets const plannedGroupEnd = group && group.timeStart !== null ? group.timeStart + group.duration - clock : null; const plannedTimeUntilGroupEnd = formattedTime(plannedGroupEnd, 3, TimerType.CountDown); - const expectedGroupEnd = blockExpectedEnd !== null ? blockExpectedEnd - clock : null; + const expectedGroupEnd = groupExpectedEnd !== null ? groupExpectedEnd - clock : null; const expectedTimeUntilGroupEnd = formattedTime(expectedGroupEnd, 3, TimerType.CountDown); const groupTitle = group?.title ?? null; @@ -120,7 +120,7 @@ function GroupTimes() {
} /> - {expectedTimeUntilGroupEnd} + {expectedTimeUntilGroupEnd}
); diff --git a/apps/client/src/features/rundown/Rundown.tsx b/apps/client/src/features/rundown/Rundown.tsx index bff95df95..795a03b01 100644 --- a/apps/client/src/features/rundown/Rundown.tsx +++ b/apps/client/src/features/rundown/Rundown.tsx @@ -16,8 +16,8 @@ import { type EntryId, type MaybeString, type Rundown, - isOntimeBlock, isOntimeEvent, + isOntimeGroup, OntimeEntry, Playback, SupportedEntry, @@ -25,9 +25,9 @@ import { import { getFirstNormal, getLastNormal, - getNextBlockNormal, + getNextGroupNormal, getNextNormal, - getPreviousBlockNormal, + getPreviousGroupNormal, getPreviousNormal, reorderArray, } from 'ontime-utils'; @@ -41,8 +41,8 @@ import { AppMode, sessionKeys } from '../../ontimeConfig'; import QuickAddButtons from './entry-editor/quick-add-buttons/QuickAddButtons'; import QuickAddInline from './entry-editor/quick-add-cursor/QuickAddInline'; -import RundownBlock from './rundown-block/RundownBlock'; -import RundownBlockEnd from './rundown-block/RundownBlockEnd'; +import RundownGroup from './rundown-group/RundownGroup'; +import RundownGroupEnd from './rundown-group/RundownGroupEnd'; import { canDrop, makeRundownMetadata, makeSortableList } from './rundown.utils'; import RundownEmpty from './RundownEmpty'; import { useEventSelection } from './useEventSelection'; @@ -127,7 +127,7 @@ export default function Rundown({ data }: RundownProps) { [addEntry], ); - const selectBlock = useCallback( + const selectGroup = useCallback( (cursor: string | null, direction: 'up' | 'down') => { if (order.length < 1) { return; @@ -137,7 +137,7 @@ export default function Rundown({ data }: RundownProps) { // there is no cursor, we select the first or last depending on direction const selected = direction === 'up' ? getLastNormal(entries, order) : getFirstNormal(entries, order); - if (isOntimeBlock(selected)) { + if (isOntimeGroup(selected)) { setSelectedEvents({ id: selected.id, selectMode: 'click', index: direction === 'up' ? order.length : 0 }); return; } @@ -151,8 +151,8 @@ export default function Rundown({ data }: RundownProps) { // otherwise we select the next or previous const selected = direction === 'up' - ? getPreviousBlockNormal(entries, order, newCursor) - : getNextBlockNormal(entries, order, newCursor); + ? getPreviousGroupNormal(entries, order, newCursor) + : getNextGroupNormal(entries, order, newCursor); if (selected.entry !== null && selected.index !== null) { setSelectedEvents({ id: selected.entry.id, selectMode: 'click', index: selected.index }); @@ -188,11 +188,11 @@ export default function Rundown({ data }: RundownProps) { ); /** - * Checks whether a block is collapsed + * Checks whether a group is collapsed */ const getIsCollapsed = useCallback( - (blockId: EntryId): boolean => { - return Boolean(collapsedGroups.find((id) => id === blockId)); + (groupId: EntryId): boolean => { + return Boolean(collapsedGroups.find((id) => id === groupId)); }, [collapsedGroups], ); @@ -223,10 +223,10 @@ export default function Rundown({ data }: RundownProps) { return; } - const movedIntoBlockId = await move(cursor, direction); - // if we are moving into a block, we need to make sure it is expanded - if (movedIntoBlockId) { - handleCollapseGroup(false, movedIntoBlockId); + const movedIntoGroupId = await move(cursor, direction); + // if we are moving into a group, we need to make sure it is expanded + if (movedIntoGroupId) { + handleCollapseGroup(false, movedIntoGroupId); } }, [handleCollapseGroup, move], @@ -237,8 +237,8 @@ export default function Rundown({ data }: RundownProps) { ['alt + ArrowDown', () => selectEntry(cursor, 'down'), { preventDefault: true, usePhysicalKeys: true }], ['alt + ArrowUp', () => selectEntry(cursor, 'up'), { preventDefault: true, usePhysicalKeys: true }], - ['alt + shift + ArrowDown', () => selectBlock(cursor, 'down'), { preventDefault: true, usePhysicalKeys: true }], - ['alt + shift + ArrowUp', () => selectBlock(cursor, 'up'), { preventDefault: true, usePhysicalKeys: true }], + ['alt + shift + ArrowDown', () => selectGroup(cursor, 'down'), { preventDefault: true, usePhysicalKeys: true }], + ['alt + shift + ArrowUp', () => selectGroup(cursor, 'up'), { preventDefault: true, usePhysicalKeys: true }], ['alt + mod + ArrowDown', () => moveEntry(cursor, 'down'), { preventDefault: true, usePhysicalKeys: true }], ['alt + mod + ArrowUp', () => moveEntry(cursor, 'up'), { preventDefault: true, usePhysicalKeys: true }], @@ -260,12 +260,12 @@ export default function Rundown({ data }: RundownProps) { [ 'alt + G', - () => insertAtId({ type: SupportedEntry.Block }, cursor), + () => insertAtId({ type: SupportedEntry.Group }, cursor), { preventDefault: true, usePhysicalKeys: true }, ], [ 'alt + shift + G', - () => insertAtId({ type: SupportedEntry.Block }, cursor, true), + () => insertAtId({ type: SupportedEntry.Group }, cursor, true), { preventDefault: true, usePhysicalKeys: true }, ], @@ -335,7 +335,10 @@ export default function Rundown({ data }: RundownProps) { } // prevent dropping a group inside another - if (active.data.current?.type === 'block' && !canDrop(over.data.current?.type, over.data.current?.parent)) { + if ( + active.data.current?.type === SupportedEntry.Group && + !canDrop(over.data.current?.type, over.data.current?.parent) + ) { return; } @@ -346,10 +349,10 @@ export default function Rundown({ data }: RundownProps) { let order: 'before' | 'after' | 'insert' = fromIndex < toIndex ? 'after' : 'before'; /** - * We need to specially handle the end blocks - * Dragging before and end block will add the entry to the end of the block - * Dragging after an end block will add the event after the block itself - * Dragging to the top of a block either place before first entry or if no entries do insert + * We need to specially handle the end-group + * Dragging before a end-group will add the entry to the end of the group + * Dragging after a end-group will add the event after the group itself + * Dragging to the top of a group either place before first entry or if no entries do insert */ if (destinationId.startsWith('end-')) { destinationId = destinationId.replace('end-', ''); @@ -358,11 +361,11 @@ export default function Rundown({ data }: RundownProps) { order = 'insert'; } } else { - const block = data.entries[destinationId]; - if (isOntimeBlock(block) && order === 'after') { - if (block.entries.length === 0) order = 'insert'; + const group = data.entries[destinationId]; + if (isOntimeGroup(group) && order === 'after') { + if (group.entries.length === 0) order = 'insert'; else { - destinationId = block.entries[0]; + destinationId = group.entries[0]; order = 'before'; } } @@ -380,31 +383,31 @@ export default function Rundown({ data }: RundownProps) { }; /** - * When we drag a block, we force collapse it - * This avoids strange scenarios like dropping a block inside itself + * When we drag a group, we force collapse it + * This avoids strange scenarios like dropping a group inside itself */ - const collapseDraggedBlocks = (event: DragStartEvent) => { - const isBlock = event.active.data.current?.type === 'block'; - if (isBlock) { + const collapseDraggedGroups = (event: DragStartEvent) => { + const isGroup = event.active.data.current?.type === SupportedEntry.Group; + if (isGroup) { handleCollapseGroup(true, event.active.id as EntryId); } }; /** - * When we drag over a block, we expand it if it is collapsed + * When we drag over a group, we expand it if it is collapsed */ - const expandOverBlock = (event: DragOverEvent) => { - // if we are dragging a block, the drop operation is invalid so we dont expand - if (event.active.data.current?.type === 'block') { + const expandOverGroup = (event: DragOverEvent) => { + // if we are dragging a group, the drop operation is invalid so we dont expand + if (event.active.data.current?.type === 'group') { return; } - if (event.over?.data.current?.type !== 'block') { + if (event.over?.data.current?.type !== 'group') { return; } - const blockId = event.over?.id as EntryId; - const isCollapsed = getIsCollapsed(blockId); + const groupId = event.over?.id as EntryId; + const isCollapsed = getIsCollapsed(groupId); if (isCollapsed) { - handleCollapseGroup(false, blockId); + handleCollapseGroup(false, groupId); } }; @@ -424,37 +427,37 @@ export default function Rundown({ data }: RundownProps) {
- {isEditMode && } + {isEditMode && } {sortableData.map((entryId, index) => { - // the entry might be a pseudo block-end which does not generate metadata and should not be processed + // the entry might be a pseudo end-group which does not generate metadata and should not be processed if (entryId.startsWith('end-')) { const parentId = entryId.split('end-')[1]; - const isBlockCollapsed = getIsCollapsed(parentId); + const isGroupCollapsed = getIsCollapsed(parentId); - if (isBlockCollapsed) { + if (isGroupCollapsed) { return null; } // if the previous element is selected, it will have its own QuickAddInline - // we use thisId instead of previousEntryId because the block end does not process + // we use thisId instead of previousEntryId because the end-group does not process // and it does not cause the reassignment of the iteration id to the previous entry return ( {isEditMode && rundownMetadata.groupEntries === 0 && ( )} - + ); } @@ -469,7 +472,7 @@ export default function Rundown({ data }: RundownProps) { // if the entry has a parent, and it is collapsed, render nothing if ( - entry.type !== SupportedEntry.Block && + entry.type !== SupportedEntry.Group && rundownMetadata.groupId !== null && getIsCollapsed(rundownMetadata.groupId) ) { @@ -480,12 +483,12 @@ export default function Rundown({ data }: RundownProps) { const hasCursor = entry.id === cursor; /** - * Outside a block, the value will be undefined + * Outside a group, the value will be undefined * If the colour is empty string '' - * ie: we are inside a block, but there is no defined colour + * ie: we are inside a group, but there is no defined colour * we default to $gray-500 #9d9d9d */ - const blockColour = rundownMetadata.groupColour === '' ? '#9d9d9d' : rundownMetadata.groupColour; + const groupColour = rundownMetadata.groupColour === '' ? '#9d9d9d' : rundownMetadata.groupColour; const isFirst = index === 0; const isLast = entryId === order.at(-1); @@ -510,10 +513,10 @@ export default function Rundown({ data }: RundownProps) { * - if it is not the first entry (the buttons would be there) */} {isEditMode && hasCursor && !isFirst && ( - + )} - {isOntimeBlock(entry) ? ( - {isOntimeEvent(entry) && (
@@ -556,16 +559,16 @@ export default function Rundown({ data }: RundownProps) { * - edit mode only * - if there is a cursor * - if it is not the last entry (the buttons would be there) - * - if the entry is not the block header + * - if the entry is not the group header */} {isEditMode && hasCursor && !isLast && ( - + )} ); })} {isEditMode && ( - + )}
diff --git a/apps/client/src/features/rundown/RundownEmpty.tsx b/apps/client/src/features/rundown/RundownEmpty.tsx index 5b7dd551f..5718c1193 100644 --- a/apps/client/src/features/rundown/RundownEmpty.tsx +++ b/apps/client/src/features/rundown/RundownEmpty.tsx @@ -25,7 +25,7 @@ export default function RundownEmpty(props: RundownEmptyProps) { -
diff --git a/apps/client/src/features/rundown/RundownEntry.tsx b/apps/client/src/features/rundown/RundownEntry.tsx index f10bfc2d4..bbab55cf5 100644 --- a/apps/client/src/features/rundown/RundownEntry.tsx +++ b/apps/client/src/features/rundown/RundownEntry.tsx @@ -25,12 +25,12 @@ export type EventItemActions = | 'event-before' | 'delay' | 'delay-before' - | 'block' - | 'block-before' + | 'group' + | 'group-before' | 'swap' | 'delete' | 'clone' - | 'group' + | 'make-group' | 'update'; interface RundownEntryProps { @@ -106,11 +106,11 @@ export default function RundownEntry({ case 'delay-before': { return addEntry({ type: SupportedEntry.Delay }, { after: previousEntryId }); } - case 'block': { - return addEntry({ type: SupportedEntry.Block }, { after: data.id }); + case 'group': { + return addEntry({ type: SupportedEntry.Group }, { after: data.id }); } - case 'block-before': { - return addEntry({ type: SupportedEntry.Block }, { after: previousEntryId }); + case 'group-before': { + return addEntry({ type: SupportedEntry.Group }, { after: previousEntryId }); } case 'swap': { const { value } = payload as FieldValue; @@ -129,7 +129,7 @@ export default function RundownEntry({ addEntry(newEvent, { after: data.id }); break; } - case 'group': { + case 'make-group': { if (selectedEvents.size > 1) { clearMultiSelection(); return groupEntries(Array.from(selectedEvents)); diff --git a/apps/client/src/features/rundown/__tests__/rundown.utils.test.ts b/apps/client/src/features/rundown/__tests__/rundown.utils.test.ts index 047a05d51..3241d1460 100644 --- a/apps/client/src/features/rundown/__tests__/rundown.utils.test.ts +++ b/apps/client/src/features/rundown/__tests__/rundown.utils.test.ts @@ -1,4 +1,4 @@ -import { EntryId, OntimeBlock, OntimeDelay, OntimeEvent, RundownEntries, SupportedEntry } from 'ontime-types'; +import { EntryId, OntimeDelay, OntimeEvent, OntimeGroup, RundownEntries, SupportedEntry } from 'ontime-types'; import { makeRundownMetadata, makeSortableList, moveDown, moveUp, orderEntries } from '../rundown.utils'; @@ -18,16 +18,16 @@ describe('makeRundownMetadata()', () => { skip: false, linkStart: false, } as OntimeEvent, - block: { - id: 'block', - type: SupportedEntry.Block, + group: { + id: 'group', + type: SupportedEntry.Group, entries: ['11', 'delay', '12', '13'], colour: 'red', - } as OntimeBlock, + } as OntimeGroup, '11': { id: '11', type: SupportedEntry.Event, - parent: 'block', + parent: 'group', timeStart: 10, timeEnd: 11, duration: 1, @@ -39,13 +39,13 @@ describe('makeRundownMetadata()', () => { delay: { id: 'delay', type: SupportedEntry.Delay, - parent: 'block', + parent: 'group', duration: 0, } as OntimeDelay, '12': { id: '12', type: SupportedEntry.Event, - parent: 'block', + parent: 'group', timeStart: 11, timeEnd: 12, duration: 1, @@ -57,7 +57,7 @@ describe('makeRundownMetadata()', () => { '13': { id: '13', type: SupportedEntry.Event, - parent: 'block', + parent: 'group', timeStart: 12, timeEnd: 13, duration: 1, @@ -114,25 +114,25 @@ describe('makeRundownMetadata()', () => { groupEntries: undefined, }); - expect(process(demoEvents['block'])).toMatchObject({ + expect(process(demoEvents['group'])).toMatchObject({ previousEvent: demoEvents['1'], latestEvent: demoEvents['1'], previousEntryId: demoEvents['1'].id, - thisId: demoEvents['block'].id, + thisId: demoEvents['group'].id, eventIndex: 1, isPast: true, isNextDay: false, totalGap: 0, isLinkedToLoaded: false, isLoaded: false, - groupId: 'block', + groupId: 'group', groupColour: 'red', }); expect(process(demoEvents['11'])).toMatchObject({ previousEvent: demoEvents['1'], latestEvent: demoEvents['11'], - previousEntryId: demoEvents['block'].id, + previousEntryId: demoEvents['group'].id, thisId: demoEvents['11'].id, eventIndex: 2, isPast: true, @@ -140,7 +140,7 @@ describe('makeRundownMetadata()', () => { totalGap: 10, isLinkedToLoaded: false, isLoaded: false, - groupId: 'block', + groupId: 'group', groupColour: 'red', }); @@ -155,7 +155,7 @@ describe('makeRundownMetadata()', () => { totalGap: 10, isLinkedToLoaded: false, isLoaded: false, - groupId: 'block', + groupId: 'group', groupColour: 'red', }); @@ -170,7 +170,7 @@ describe('makeRundownMetadata()', () => { totalGap: 10, isLinkedToLoaded: false, isLoaded: true, - groupId: 'block', + groupId: 'group', groupColour: 'red', }); @@ -185,7 +185,7 @@ describe('makeRundownMetadata()', () => { totalGap: 10, isLinkedToLoaded: true, isLoaded: false, - groupId: 'block', + groupId: 'group', groupColour: 'red', }); @@ -205,18 +205,18 @@ describe('makeRundownMetadata()', () => { }); }); - it('populates previousEntries in blocks', () => { - const rundownStartsWithBlock = { - block: { - id: 'block', - type: SupportedEntry.Block, + it('populates previousEntries in groups', () => { + const rundownStartsWithGroup = { + group: { + id: 'group', + type: SupportedEntry.Group, colour: 'red', entries: ['1', '2'], - } as OntimeBlock, + } as OntimeGroup, '1': { id: '1', type: SupportedEntry.Event, - parent: 'block', + parent: 'group', timeStart: 1, timeEnd: 2, duration: 1, @@ -228,7 +228,7 @@ describe('makeRundownMetadata()', () => { '2': { id: '2', type: SupportedEntry.Event, - parent: 'block', + parent: 'group', timeStart: 2, timeEnd: 3, duration: 1, @@ -240,49 +240,49 @@ describe('makeRundownMetadata()', () => { }; const { process } = makeRundownMetadata(null); - expect(process(rundownStartsWithBlock.block)).toStrictEqual({ + expect(process(rundownStartsWithGroup.group)).toStrictEqual({ previousEvent: null, latestEvent: null, previousEntryId: null, - thisId: rundownStartsWithBlock.block.id, + thisId: rundownStartsWithGroup.group.id, eventIndex: 0, isPast: false, isNextDay: false, totalGap: 0, isLinkedToLoaded: false, isLoaded: false, - groupId: rundownStartsWithBlock.block.id, + groupId: rundownStartsWithGroup.group.id, groupColour: 'red', groupEntries: 2, }); - expect(process(rundownStartsWithBlock['1'])).toStrictEqual({ + expect(process(rundownStartsWithGroup['1'])).toStrictEqual({ previousEvent: null, - latestEvent: rundownStartsWithBlock['1'], - previousEntryId: rundownStartsWithBlock.block.id, - thisId: rundownStartsWithBlock['1'].id, + latestEvent: rundownStartsWithGroup['1'], + previousEntryId: rundownStartsWithGroup.group.id, + thisId: rundownStartsWithGroup['1'].id, eventIndex: 1, isPast: false, isNextDay: false, totalGap: 0, isLinkedToLoaded: false, isLoaded: false, - groupId: rundownStartsWithBlock.block.id, + groupId: rundownStartsWithGroup.group.id, groupColour: 'red', groupEntries: 2, }); - expect(process(rundownStartsWithBlock['2'])).toStrictEqual({ - previousEvent: rundownStartsWithBlock['1'], - latestEvent: rundownStartsWithBlock['2'], - previousEntryId: rundownStartsWithBlock['1'].id, - thisId: rundownStartsWithBlock['2'].id, + expect(process(rundownStartsWithGroup['2'])).toStrictEqual({ + previousEvent: rundownStartsWithGroup['1'], + latestEvent: rundownStartsWithGroup['2'], + previousEntryId: rundownStartsWithGroup['1'].id, + thisId: rundownStartsWithGroup['2'].id, eventIndex: 2, isPast: false, isNextDay: false, totalGap: 0, isLinkedToLoaded: false, isLoaded: false, - groupId: rundownStartsWithBlock.block.id, + groupId: rundownStartsWithGroup.group.id, groupColour: 'red', groupEntries: 2, }); @@ -290,52 +290,52 @@ describe('makeRundownMetadata()', () => { }); describe('makeSortableList()', () => { - it('generates a list with block ends', () => { - const order = ['block-1', '2', 'block-3', 'block-4']; + it('generates a list with group ends', () => { + const order = ['group-1', '2', 'group-3', 'group-4']; const entries: RundownEntries = { - 'block-1': { type: SupportedEntry.Block, id: 'block-1', entries: ['11'] } as OntimeBlock, - '11': { type: SupportedEntry.Event, id: '11', parent: 'block-1' } as OntimeEvent, + 'group-1': { type: SupportedEntry.Group, id: 'group-1', entries: ['11'] } as OntimeGroup, + '11': { type: SupportedEntry.Event, id: '11', parent: 'group-1' } as OntimeEvent, '2': { type: SupportedEntry.Event, id: '2', parent: null } as OntimeEvent, - 'block-3': { type: SupportedEntry.Block, id: 'block-3', entries: ['31'] } as OntimeBlock, - '31': { type: SupportedEntry.Event, id: '31', parent: 'block-3' } as OntimeEvent, - 'block-4': { type: SupportedEntry.Block, id: 'block-4', entries: [] as string[] } as OntimeBlock, + 'group-3': { type: SupportedEntry.Group, id: 'group-3', entries: ['31'] } as OntimeGroup, + '31': { type: SupportedEntry.Event, id: '31', parent: 'group-3' } as OntimeEvent, + 'group-4': { type: SupportedEntry.Group, id: 'group-4', entries: [] as string[] } as OntimeGroup, }; const sortableList = makeSortableList(order, entries); expect(sortableList).toStrictEqual([ - 'block-1', + 'group-1', '11', - 'end-block-1', + 'end-group-1', '2', - 'block-3', + 'group-3', '31', - 'end-block-3', - 'block-4', - 'end-block-4', + 'end-group-3', + 'group-4', + 'end-group-4', ]); }); - it('closes dangling blocks', () => { - const order = ['block']; + it('closes dangling group', () => { + const order = ['group']; const entries: RundownEntries = { - block: { type: SupportedEntry.Block, id: 'block-1', entries: ['11', '12'] } as OntimeBlock, - '11': { type: SupportedEntry.Event, id: '11', parent: 'block-1' } as OntimeEvent, - '12': { type: SupportedEntry.Event, id: '12', parent: 'block-1' } as OntimeEvent, + group: { type: SupportedEntry.Group, id: 'group-1', entries: ['11', '12'] } as OntimeGroup, + '11': { type: SupportedEntry.Event, id: '11', parent: 'group-1' } as OntimeEvent, + '12': { type: SupportedEntry.Event, id: '12', parent: 'group-1' } as OntimeEvent, }; const sortableList = makeSortableList(order, entries); - expect(sortableList).toStrictEqual(['block-1', '11', '12', 'end-block-1']); + expect(sortableList).toStrictEqual(['group-1', '11', '12', 'end-group-1']); }); - it('handles a list with a with just blocks', () => { - const order = ['block-1', 'block-2']; + it('handles a list with a with just groups', () => { + const order = ['group-1', 'group-2']; const entries: RundownEntries = { - 'block-1': { type: SupportedEntry.Block, id: 'block-1', entries: [] as string[] } as OntimeBlock, - 'block-2': { type: SupportedEntry.Block, id: 'block-2', entries: [] as string[] } as OntimeBlock, + 'group-1': { type: SupportedEntry.Group, id: 'group-1', entries: [] as string[] } as OntimeGroup, + 'group-2': { type: SupportedEntry.Group, id: 'group-2', entries: [] as string[] } as OntimeGroup, }; const sortableList = makeSortableList(order, entries); - expect(sortableList).toStrictEqual(['block-1', 'end-block-1', 'block-2', 'end-block-2']); + expect(sortableList).toStrictEqual(['group-1', 'end-group-1', 'group-2', 'end-group-2']); }); }); @@ -345,15 +345,15 @@ describe('moveUp()', () => { '1': { id: '1', type: 'event', parent: null } as OntimeEvent, '2': { id: '2', type: 'event', parent: null } as OntimeEvent, '3': { id: '3', type: 'event', parent: null } as OntimeEvent, - block: { id: 'block', type: 'block', entries: ['11', '12'] } as OntimeBlock, - '11': { id: '11', type: 'event', parent: 'block' } as OntimeEvent, - '12': { id: '12', type: 'event', parent: 'block' } as OntimeEvent, + group: { id: 'group', type: 'group', entries: ['11', '12'] } as OntimeGroup, + '11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent, + '12': { id: '12', type: 'event', parent: 'group' } as OntimeEvent, '4': { id: '4', type: 'event', parent: null } as OntimeEvent, - block2: { id: 'block2', type: 'block', entries: [] as EntryId[] } as OntimeBlock, + group2: { id: 'group2', type: 'group', entries: [] as EntryId[] } as OntimeGroup, '5': { id: '5', type: 'event', parent: null } as OntimeEvent, }, - order: ['1', '2', '3', 'block', '4', 'block2', '5'], - flatOrder: ['1', '2', '3', 'block', '11', '12', '4', 'block2', '5'], + order: ['1', '2', '3', 'group', '4', 'group2', '5'], + flatOrder: ['1', '2', '3', 'group', '11', '12', '4', 'group2', '5'], }; it('moving the first event is a noop', () => { @@ -370,7 +370,7 @@ describe('moveUp()', () => { }); }); - it('moves an entry up inside a block', () => { + it('moves an entry up inside a group', () => { expect(moveUp('12', rundown.flatOrder, rundown.entries)).toStrictEqual({ destinationId: '11', order: 'before', @@ -379,7 +379,7 @@ describe('moveUp()', () => { it('moves an entry up into an empty group', () => { expect(moveUp('5', rundown.flatOrder, rundown.entries)).toStrictEqual({ - destinationId: 'block2', + destinationId: 'group2', order: 'insert', }); }); @@ -393,45 +393,45 @@ describe('moveUp()', () => { it('moves an entry up out of a group', () => { expect(moveUp('11', rundown.flatOrder, rundown.entries)).toStrictEqual({ - destinationId: 'block', + destinationId: 'group', order: 'before', }); }); - it('moves a block in the rundown', () => { - expect(moveUp('block', rundown.flatOrder, rundown.entries)).toStrictEqual({ + it('moves a group in the rundown', () => { + expect(moveUp('group', rundown.flatOrder, rundown.entries)).toStrictEqual({ destinationId: '3', order: 'before', }); }); - it('swaps two blocks', () => { + it('swaps two groups', () => { const rundown = { entries: { - block: { id: 'block', type: 'block', entries: ['11'] } as OntimeBlock, - '11': { id: '11', type: 'event', parent: 'block' } as OntimeEvent, - block2: { id: 'block2', type: 'block', entries: [] as EntryId[] } as OntimeBlock, + group: { id: 'group', type: 'group', entries: ['11'] } as OntimeGroup, + '11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent, + group2: { id: 'group2', type: 'group', entries: [] as EntryId[] } as OntimeGroup, }, - order: ['block', 'block2'], - flatOrder: ['block', '11', 'block2'], + order: ['group', 'group2'], + flatOrder: ['group', '11', 'group2'], }; - expect(moveUp('block2', rundown.flatOrder, rundown.entries)).toStrictEqual({ - destinationId: 'block', + expect(moveUp('group2', rundown.flatOrder, rundown.entries)).toStrictEqual({ + destinationId: 'group', order: 'before', }); }); - it('moves before a block', () => { + it('moves before a group', () => { const rundown = { entries: { - block: { id: 'block', type: 'block', entries: ['11'] } as OntimeBlock, - '11': { id: '11', type: 'event', parent: 'block' } as OntimeEvent, + group: { id: 'group', type: 'group', entries: ['11'] } as OntimeGroup, + '11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent, }, - order: ['block'], - flatOrder: ['block', '11'], + order: ['group'], + flatOrder: ['group', '11'], }; expect(moveUp('11', rundown.flatOrder, rundown.entries)).toStrictEqual({ - destinationId: 'block', + destinationId: 'group', order: 'before', }); }); @@ -443,15 +443,15 @@ describe('moveDown()', () => { '1': { id: '1', type: 'event', parent: null } as OntimeEvent, '2': { id: '2', type: 'event', parent: null } as OntimeEvent, '3': { id: '3', type: 'event', parent: null } as OntimeEvent, - block: { id: 'block', type: 'block', entries: ['11', '12'] } as OntimeBlock, - '11': { id: '11', type: 'event', parent: 'block' } as OntimeEvent, - '12': { id: '12', type: 'event', parent: 'block' } as OntimeEvent, + group: { id: 'group', type: 'group', entries: ['11', '12'] } as OntimeGroup, + '11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent, + '12': { id: '12', type: 'event', parent: 'group' } as OntimeEvent, '4': { id: '4', type: 'event', parent: null } as OntimeEvent, - block2: { id: 'block2', type: 'block', entries: [] as EntryId[] } as OntimeBlock, + group2: { id: 'group2', type: 'group', entries: [] as EntryId[] } as OntimeGroup, '5': { id: '5', type: 'event', parent: null } as OntimeEvent, }, - order: ['1', '2', '3', 'block', '4', 'block2', '5'], - flatOrder: ['1', '2', '3', 'block', '11', '12', '4', 'block2', '5'], + order: ['1', '2', '3', 'group', '4', 'group2', '5'], + flatOrder: ['1', '2', '3', 'group', '11', '12', '4', 'group2', '5'], }; it('moving the last event is a noop', () => { @@ -468,7 +468,7 @@ describe('moveDown()', () => { }); }); - it('moves an entry down inside a block', () => { + it('moves an entry down inside a group', () => { expect(moveDown('11', rundown.flatOrder, rundown.entries)).toStrictEqual({ destinationId: '12', order: 'after', @@ -477,14 +477,14 @@ describe('moveDown()', () => { it('moves an entry down into an empty group', () => { expect(moveDown('4', rundown.flatOrder, rundown.entries)).toStrictEqual({ - destinationId: 'block2', + destinationId: 'group2', order: 'insert', }); }); it('moves an entry down out of a group', () => { expect(moveDown('12', rundown.flatOrder, rundown.entries)).toStrictEqual({ - destinationId: 'block', + destinationId: 'group', order: 'after', }); }); @@ -496,40 +496,40 @@ describe('moveDown()', () => { }); }); - it('moves a block in the rundown', () => { - expect(moveDown('block', rundown.flatOrder, rundown.entries)).toStrictEqual({ + it('moves a group in the rundown', () => { + expect(moveDown('group', rundown.flatOrder, rundown.entries)).toStrictEqual({ destinationId: '4', order: 'after', }); }); - it('swaps two blocks', () => { + it('swaps two groups', () => { const rundown = { entries: { - block: { id: 'block', type: 'block', entries: ['11'] } as OntimeBlock, - '11': { id: '11', type: 'event', parent: 'block' } as OntimeEvent, - block2: { id: 'block2', type: 'block', entries: [] as EntryId[] } as OntimeBlock, + group: { id: 'group', type: 'group', entries: ['11'] } as OntimeGroup, + '11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent, + group2: { id: 'group2', type: 'group', entries: [] as EntryId[] } as OntimeGroup, }, - order: ['block', 'block2'], - flatOrder: ['block', '11', 'block2'], + order: ['group', 'group2'], + flatOrder: ['group', '11', 'group2'], }; - expect(moveDown('block', rundown.flatOrder, rundown.entries)).toStrictEqual({ - destinationId: 'block2', + expect(moveDown('group', rundown.flatOrder, rundown.entries)).toStrictEqual({ + destinationId: 'group2', order: 'after', }); }); - it('moves after a block', () => { + it('moves after a group', () => { const rundown = { entries: { - block: { id: 'block', type: 'block', entries: ['11'] } as OntimeBlock, - '11': { id: '11', type: 'event', parent: 'block' } as OntimeEvent, + group: { id: 'group', type: 'group', entries: ['11'] } as OntimeGroup, + '11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent, }, - order: ['block'], - flatOrder: ['block', '11'], + order: ['group'], + flatOrder: ['group', '11'], }; expect(moveDown('11', rundown.flatOrder, rundown.entries)).toStrictEqual({ - destinationId: 'block', + destinationId: 'group', order: 'after', }); }); diff --git a/apps/client/src/features/rundown/common/EditableBlockTitle.tsx b/apps/client/src/features/rundown/common/TitleEditor.tsx similarity index 81% rename from apps/client/src/features/rundown/common/EditableBlockTitle.tsx rename to apps/client/src/features/rundown/common/TitleEditor.tsx index 513bbb800..52785ffad 100644 --- a/apps/client/src/features/rundown/common/EditableBlockTitle.tsx +++ b/apps/client/src/features/rundown/common/TitleEditor.tsx @@ -9,13 +9,12 @@ import style from './TitleEditor.module.scss'; interface TitleEditorProps { title: string; - eventId: string; + entryId: string; placeholder: string; className?: string; } -export default function EditableBlockTitle(props: TitleEditorProps) { - const { title, eventId, placeholder, className } = props; +export default function TitleEditor({ title, entryId, placeholder, className }: TitleEditorProps) { const { updateEntry } = useEntryActions(); const ref = useRef(null); const submitCallback = useCallback( @@ -25,9 +24,9 @@ export default function EditableBlockTitle(props: TitleEditorProps) { } const cleanVal = text.trim(); - updateEntry({ id: eventId, title: cleanVal }); + updateEntry({ id: entryId, title: cleanVal }); }, - [title, updateEntry, eventId], + [title, updateEntry, entryId], ); const { value, onChange, onBlur, onKeyDown } = useReactiveTextInput(title, submitCallback, ref, { @@ -38,7 +37,7 @@ export default function EditableBlockTitle(props: TitleEditorProps) { return ( - +
); } diff --git a/apps/client/src/features/rundown/entry-editor/BlockEditor.tsx b/apps/client/src/features/rundown/entry-editor/GroupEditor.tsx similarity index 74% rename from apps/client/src/features/rundown/entry-editor/BlockEditor.tsx rename to apps/client/src/features/rundown/entry-editor/GroupEditor.tsx index 372b648fc..2ed797d76 100644 --- a/apps/client/src/features/rundown/entry-editor/BlockEditor.tsx +++ b/apps/client/src/features/rundown/entry-editor/GroupEditor.tsx @@ -1,5 +1,5 @@ import { useCallback } from 'react'; -import { MaybeNumber, OntimeBlock } from 'ontime-types'; +import { MaybeNumber, OntimeGroup } from 'ontime-types'; import { millisToString } from 'ontime-utils'; import * as Editor from '../../../common/components/editor-utils/EditorUtils'; @@ -19,38 +19,38 @@ import TargetDurationInput from './composite/TargetDurationInput'; import style from './EntryEditor.module.scss'; // title + colour + custom field labels -export type BlockEditorUpdateTextFields = 'title' | 'colour' | string; -export type BlockEditorUpdateMaybeNumberFields = 'targetDuration'; +export type GroupEditorUpdateTextFields = 'title' | 'colour' | string; +export type GroupEditorUpdateMaybeNumberFields = 'targetDuration'; -interface BlockEditorProps { - block: OntimeBlock; +interface GroupEditorProps { + group: OntimeGroup; } -export default function BlockEditor({ block }: BlockEditorProps) { +export default function GroupEditor({ group }: GroupEditorProps) { const { data: customFields } = useCustomFields(); const { updateEntry } = useEntryActions(); const handleSubmit = useCallback( - (field: BlockEditorUpdateTextFields | BlockEditorUpdateMaybeNumberFields, value: string | MaybeNumber) => { + (field: GroupEditorUpdateTextFields | GroupEditorUpdateMaybeNumberFields, value: string | MaybeNumber) => { // Handle custom fields if (typeof field === 'string' && field.startsWith('custom-')) { const fieldLabel = field.split('custom-')[1]; - updateEntry({ id: block.id, custom: { [fieldLabel]: value as string } }); + updateEntry({ id: group.id, custom: { [fieldLabel]: value as string } }); return; } if (field === 'targetDuration') { - return updateEntry({ id: block.id, targetDuration: value as MaybeNumber }); + return updateEntry({ id: group.id, targetDuration: value as MaybeNumber }); } // all other strings are text fields - return updateEntry({ id: block.id, [field]: value as string }); + return updateEntry({ id: group.id, [field]: value as string }); }, - [block.id, updateEntry], + [group.id, updateEntry], ); const isEditor = window.location.pathname.includes('editor'); - const planOffset = typeof block.targetDuration !== 'number' ? null : block.duration - block.targetDuration; + const planOffset = typeof group.targetDuration !== 'number' ? null : group.duration - group.targetDuration; const planOffsetLabel = planOffset !== null ? getOffsetState(planOffset * -1) : null; return ( @@ -64,19 +64,19 @@ export default function BlockEditor({ block }: BlockEditorProps) { } First event start - {millisToString(block.timeStart, { fallback: timerPlaceholder })} + {millisToString(group.timeStart, { fallback: timerPlaceholder })}
Last event end - {millisToString(block.timeEnd, { fallback: timerPlaceholder })} + {millisToString(group.timeEnd, { fallback: timerPlaceholder })}
Scheduled duration - {millisToString(block.duration, { fallback: enDash })} + {millisToString(group.duration, { fallback: enDash })}
@@ -93,21 +93,21 @@ export default function BlockEditor({ block }: BlockEditorProps) {
- Block data + Group data
Colour - +
- - + +
@@ -115,7 +115,7 @@ export default function BlockEditor({ block }: BlockEditorProps) { Custom Fields {isEditor && Manage Custom Fields} - +
); diff --git a/apps/client/src/features/rundown/entry-editor/RundownEntryEditor.tsx b/apps/client/src/features/rundown/entry-editor/RundownEntryEditor.tsx index 538e64c5d..b934d2a47 100644 --- a/apps/client/src/features/rundown/entry-editor/RundownEntryEditor.tsx +++ b/apps/client/src/features/rundown/entry-editor/RundownEntryEditor.tsx @@ -1,11 +1,11 @@ import { useEffect, useState } from 'react'; import { - isOntimeBlock, isOntimeDelay, isOntimeEvent, + isOntimeGroup, isOntimeMilestone, - OntimeBlock, OntimeEvent, + OntimeGroup, OntimeMilestone, } from 'ontime-types'; @@ -13,9 +13,9 @@ import useRundown from '../../../common/hooks-query/useRundown'; import { useEventSelection } from '../useEventSelection'; import EventEditorFooter from './composite/EventEditorFooter'; -import BlockEditor from './BlockEditor'; import EventEditor from './EventEditor'; import EventEditorEmpty from './EventEditorEmpty'; +import GroupEditor from './GroupEditor'; import MilestoneEditor from './MilestoneEditor'; import style from './EntryEditor.module.scss'; @@ -24,7 +24,7 @@ export default function RundownEntryEditor() { const selectedEvents = useEventSelection((state) => state.selectedEvents); const { data } = useRundown(); - const [entry, setEntry] = useState(null); + const [entry, setEntry] = useState(null); useEffect(() => { if (data.order.length === 0) { @@ -67,10 +67,10 @@ export default function RundownEntryEditor() { ); } - if (isOntimeBlock(entry)) { + if (isOntimeGroup(entry)) { return (
- +
); } diff --git a/apps/client/src/features/rundown/entry-editor/composite/EventEditorCustomFields.tsx b/apps/client/src/features/rundown/entry-editor/composite/EventEditorCustomFields.tsx index be6b965c8..51468b5fe 100644 --- a/apps/client/src/features/rundown/entry-editor/composite/EventEditorCustomFields.tsx +++ b/apps/client/src/features/rundown/entry-editor/composite/EventEditorCustomFields.tsx @@ -1,5 +1,5 @@ import { CSSProperties, Fragment } from 'react'; -import { CustomFields, OntimeBlock, OntimeEvent, OntimeMilestone } from 'ontime-types'; +import { CustomFields, OntimeEvent, OntimeGroup, OntimeMilestone } from 'ontime-types'; import { getAccessibleColour } from '../../../../common/utils/styleUtils'; import { EventEditorUpdateFields } from '../EventEditor'; @@ -12,7 +12,7 @@ import style from '../EntryEditor.module.scss'; interface EntryEditorCustomFieldsProps { fields: CustomFields; - entry: OntimeEvent | OntimeBlock | OntimeMilestone; + entry: OntimeEvent | OntimeGroup | OntimeMilestone; handleSubmit: (field: EventEditorUpdateFields, value: string) => void; } diff --git a/apps/client/src/features/rundown/entry-editor/composite/EventTextInput.tsx b/apps/client/src/features/rundown/entry-editor/composite/EventTextInput.tsx index 8a7f5ec4a..43d1cf3af 100644 --- a/apps/client/src/features/rundown/entry-editor/composite/EventTextInput.tsx +++ b/apps/client/src/features/rundown/entry-editor/composite/EventTextInput.tsx @@ -3,11 +3,11 @@ import { useCallback, useRef } from 'react'; import * as Editor from '../../../../common/components/editor-utils/EditorUtils'; import Input, { type InputProps } from '../../../../common/components/input/input/Input'; import useReactiveTextInput from '../../../../common/components/input/text-input/useReactiveTextInput'; -import { BlockEditorUpdateTextFields } from '../BlockEditor'; import { EventEditorUpdateFields } from '../EventEditor'; +import { GroupEditorUpdateTextFields } from '../GroupEditor'; interface EntryEditorTextInputProps extends InputProps { - field: EventEditorUpdateFields | BlockEditorUpdateTextFields; + field: EventEditorUpdateFields | GroupEditorUpdateTextFields; label: string; initialValue: string; placeholder?: string; diff --git a/apps/client/src/features/rundown/entry-editor/composite/TargetDurationInput.tsx b/apps/client/src/features/rundown/entry-editor/composite/TargetDurationInput.tsx index 888f8921b..d1c5bf7eb 100644 --- a/apps/client/src/features/rundown/entry-editor/composite/TargetDurationInput.tsx +++ b/apps/client/src/features/rundown/entry-editor/composite/TargetDurationInput.tsx @@ -17,27 +17,27 @@ interface TargetDurationInputProps { } export default function TargetDurationInput({ duration, targetDuration, submitHandler }: TargetDurationInputProps) { - const isBlocked = targetDuration !== null; + const isLocked = targetDuration !== null; return (
Target duration - + submitHandler('targetDuration', isBlocked ? null : duration)} + className={cx([style.timeAction, isLocked && style.active])} + onClick={() => submitHandler('targetDuration', isLocked ? null : duration)} data-testid='lock__duration' - render={} + render={} > - {isBlocked ? : } + {isLocked ? : }
diff --git a/apps/client/src/features/rundown/entry-editor/quick-add-buttons/QuickAddButtons.tsx b/apps/client/src/features/rundown/entry-editor/quick-add-buttons/QuickAddButtons.tsx index add3c2293..bd4c4aa31 100644 --- a/apps/client/src/features/rundown/entry-editor/quick-add-buttons/QuickAddButtons.tsx +++ b/apps/client/src/features/rundown/entry-editor/quick-add-buttons/QuickAddButtons.tsx @@ -11,19 +11,19 @@ import style from './QuickAddButtons.module.scss'; interface QuickAddButtonsProps { previousEventId: MaybeString; - parentBlock: MaybeString; + parentGroup: MaybeString; backgroundColor?: string; } export default memo(QuickAddButtons); -function QuickAddButtons({ previousEventId, parentBlock, backgroundColor }: QuickAddButtonsProps) { +function QuickAddButtons({ previousEventId, parentGroup, backgroundColor }: QuickAddButtonsProps) { const { addEntry } = useEntryActions(); const addEvent = () => { addEntry( { type: SupportedEntry.Event, - parent: parentBlock, + parent: parentGroup, }, { after: previousEventId, @@ -34,7 +34,7 @@ function QuickAddButtons({ previousEventId, parentBlock, backgroundColor }: Quic const addDelay = () => { addEntry( - { type: SupportedEntry.Delay, parent: parentBlock }, + { type: SupportedEntry.Delay, parent: parentGroup }, { lastEventId: previousEventId, after: previousEventId, @@ -44,7 +44,7 @@ function QuickAddButtons({ previousEventId, parentBlock, backgroundColor }: Quic const addMilestone = () => { addEntry( - { type: SupportedEntry.Milestone, parent: parentBlock }, + { type: SupportedEntry.Milestone, parent: parentGroup }, { lastEventId: previousEventId, after: previousEventId, @@ -52,12 +52,12 @@ function QuickAddButtons({ previousEventId, parentBlock, backgroundColor }: Quic ); }; - const addBlock = () => { - if (parentBlock !== null) { + const addGroup = () => { + if (parentGroup !== null) { return; } addEntry( - { type: SupportedEntry.Block }, + { type: SupportedEntry.Group }, { lastEventId: previousEventId, after: previousEventId, @@ -67,15 +67,15 @@ function QuickAddButtons({ previousEventId, parentBlock, backgroundColor }: Quic /** * If the colour is empty string '' - * ie: we are inside a block, but there is no defined colour + * ie: we are inside a group, but there is no defined colour * we default to $gray-500 #9d9d9d */ - const blockColour = backgroundColor === '' ? '#9d9d9d' : backgroundColor; + const groupColour = backgroundColor === '' ? '#9d9d9d' : backgroundColor; return ( } onClick={addEvent}> @@ -93,8 +93,8 @@ function QuickAddButtons({ previousEventId, parentBlock, backgroundColor }: Quic Milestone - {parentBlock === null && ( - } onClick={addBlock}> + {parentGroup === null && ( + } onClick={addGroup}> Group diff --git a/apps/client/src/features/rundown/entry-editor/quick-add-cursor/QuickAddInline.tsx b/apps/client/src/features/rundown/entry-editor/quick-add-cursor/QuickAddInline.tsx index 6a7397663..4ef6c5417 100644 --- a/apps/client/src/features/rundown/entry-editor/quick-add-cursor/QuickAddInline.tsx +++ b/apps/client/src/features/rundown/entry-editor/quick-add-cursor/QuickAddInline.tsx @@ -10,18 +10,18 @@ import style from './QuickAddInline.module.scss'; interface QuickAddInlineProps { previousEventId: MaybeString; - parentBlock: MaybeString; + parentGroup: MaybeString; } export default memo(QuickAddInline); -function QuickAddInline({ previousEventId, parentBlock }: QuickAddInlineProps) { +function QuickAddInline({ previousEventId, parentGroup }: QuickAddInlineProps) { const { addEntry } = useEntryActions(); const addEvent = () => { addEntry( { type: SupportedEntry.Event, - parent: parentBlock, + parent: parentGroup, }, { after: previousEventId, @@ -32,7 +32,7 @@ function QuickAddInline({ previousEventId, parentBlock }: QuickAddInlineProps) { const addDelay = () => { addEntry( - { type: SupportedEntry.Delay, parent: parentBlock }, + { type: SupportedEntry.Delay, parent: parentGroup }, { lastEventId: previousEventId, after: previousEventId, @@ -42,7 +42,7 @@ function QuickAddInline({ previousEventId, parentBlock }: QuickAddInlineProps) { const addMilestone = () => { addEntry( - { type: SupportedEntry.Milestone, parent: parentBlock }, + { type: SupportedEntry.Milestone, parent: parentGroup }, { lastEventId: previousEventId, after: previousEventId, @@ -50,12 +50,12 @@ function QuickAddInline({ previousEventId, parentBlock }: QuickAddInlineProps) { ); }; - const addBlock = () => { - if (parentBlock !== null) { + const addGroup = () => { + if (parentGroup !== null) { return; } addEntry( - { type: SupportedEntry.Block }, + { type: SupportedEntry.Group }, { lastEventId: previousEventId, after: previousEventId, @@ -70,7 +70,7 @@ function QuickAddInline({ previousEventId, parentBlock }: QuickAddInlineProps) { { type: 'item', icon: IoAdd, label: 'Add Event', onClick: addEvent }, { type: 'item', icon: IoAdd, label: 'Add Delay', onClick: addDelay }, { type: 'item', icon: IoAdd, label: 'Add Milestone', onClick: addMilestone }, - { type: 'item', icon: IoAdd, label: 'Add Group', onClick: addBlock, disabled: parentBlock !== null }, + { type: 'item', icon: IoAdd, label: 'Add Group', onClick: addGroup, disabled: parentGroup !== null }, ]} render={} > diff --git a/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx b/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx index a7268c15a..537cc7a0f 100644 --- a/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx +++ b/apps/client/src/features/rundown/rundown-event/RundownEvent.tsx @@ -130,7 +130,7 @@ export default function RundownEvent({ }), }, { type: 'divider' }, - { type: 'item', label: 'Group', icon: IoFolder, onClick: () => actionHandler('group') }, + { type: 'item', label: 'Group', icon: IoFolder, onClick: () => actionHandler('make-group') }, { type: 'divider' }, { type: 'item', label: 'Delete', icon: IoTrash, onClick: () => actionHandler('delete') }, ] @@ -205,8 +205,8 @@ export default function RundownEvent({ } const elementInFocus = document.activeElement; - // we know the block is the grandparent of our binder - const blockElement = handleRef.current.closest('#event-block'); + // we know the group is the grandparent of our binder + const blockElement = handleRef.current.closest('#event-group'); // we only move focus if the block doesnt already contain focus if (blockElement && !blockElement.contains(elementInFocus)) { diff --git a/apps/client/src/features/rundown/rundown-event/RundownEventInner.tsx b/apps/client/src/features/rundown/rundown-event/RundownEventInner.tsx index 94db7072d..61ca42e2f 100644 --- a/apps/client/src/features/rundown/rundown-event/RundownEventInner.tsx +++ b/apps/client/src/features/rundown/rundown-event/RundownEventInner.tsx @@ -14,7 +14,7 @@ import { EndAction, Playback, TimerType, TimeStrategy } from 'ontime-types'; import Tooltip from '../../../common/components/tooltip/Tooltip'; import { cx } from '../../../common/utils/styleUtils'; -import EditableBlockTitle from '../common/EditableBlockTitle'; +import TitleEditor from '../common/TitleEditor'; import TimeInputFlow from '../time-input-flow/TimeInputFlow'; import RundownEventChip from './composite/RundownEventChip'; @@ -105,7 +105,7 @@ function RundownEventInner({ />
- + {isNext && UP NEXT}
)} -
+
{note}
{loaded && } diff --git a/apps/client/src/features/rundown/rundown-block/RundownBlock.module.scss b/apps/client/src/features/rundown/rundown-group/RundownGroup.module.scss similarity index 96% rename from apps/client/src/features/rundown/rundown-block/RundownBlock.module.scss rename to apps/client/src/features/rundown/rundown-group/RundownGroup.module.scss index eb0303c97..304b7788b 100644 --- a/apps/client/src/features/rundown/rundown-block/RundownBlock.module.scss +++ b/apps/client/src/features/rundown/rundown-group/RundownGroup.module.scss @@ -1,6 +1,6 @@ @use '../blockMixins' as *; -.block { +.group { @include block-styling; margin-block: 0.5rem; @@ -22,7 +22,7 @@ .binder { grid-area: binder; height: 100%; - background-color: var(--block-color, $gray-1050); + background-color: var(--user-bg, $gray-1050); color: $section-white; font-size: 1rem; display: grid; diff --git a/apps/client/src/features/rundown/rundown-block/RundownBlock.tsx b/apps/client/src/features/rundown/rundown-group/RundownGroup.tsx similarity index 86% rename from apps/client/src/features/rundown/rundown-block/RundownBlock.tsx rename to apps/client/src/features/rundown/rundown-group/RundownGroup.tsx index 48e2434cc..4db25e537 100644 --- a/apps/client/src/features/rundown/rundown-block/RundownBlock.tsx +++ b/apps/client/src/features/rundown/rundown-group/RundownGroup.tsx @@ -9,7 +9,7 @@ import { } from 'react-icons/io5'; import { useSortable } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; -import { EntryId, OntimeBlock } from 'ontime-types'; +import { EntryId, OntimeGroup } from 'ontime-types'; import IconButton from '../../../common/components/buttons/IconButton'; import { useContextMenu } from '../../../common/hooks/useContextMenu'; @@ -17,24 +17,24 @@ import { useEntryActions } from '../../../common/hooks/useEntryAction'; import { getOffsetState } from '../../../common/utils/offset'; import { cx, getAccessibleColour } from '../../../common/utils/styleUtils'; import { formatDuration, formatTime } from '../../../common/utils/time'; -import EditableBlockTitle from '../common/EditableBlockTitle'; +import TitleEditor from '../common/TitleEditor'; import { canDrop } from '../rundown.utils'; import { useEventSelection } from '../useEventSelection'; -import style from './RundownBlock.module.scss'; +import style from './RundownGroup.module.scss'; -interface RundownBlockProps { - data: OntimeBlock; +interface RundownGroupProps { + data: OntimeGroup; hasCursor: boolean; collapsed: boolean; onCollapse: (collapsed: boolean, groupId: EntryId) => void; } -//TODO: the block should maybe include a multiple day indicator -export default function RundownBlock({ data, hasCursor, collapsed, onCollapse }: RundownBlockProps) { +//TODO: the group should maybe include a multiple day indicator +export default function RundownGroup({ data, hasCursor, collapsed, onCollapse }: RundownGroupProps) { const handleRef = useRef(null); const { clone, ungroup, deleteEntry } = useEntryActions(); - const { selectedEvents, setSelectedBlock } = useEventSelection(); + const { selectedEvents, setSingleEntrySelection } = useEventSelection(); const [onContextMenu] = useContextMenu([ { @@ -71,7 +71,7 @@ export default function RundownBlock({ data, hasCursor, collapsed, onCollapse }: } = useSortable({ id: data.id, data: { - type: 'block', + type: 'group', }, animateLayoutChanges: () => false, }); @@ -87,7 +87,7 @@ export default function RundownBlock({ data, hasCursor, collapsed, onCollapse }: } // UI indexes are 1 based - setSelectedBlock({ id: data.id }); + setSingleEntrySelection({ id: data.id }); }; const binderColours = data.colour && getAccessibleColour(data.colour); @@ -115,16 +115,15 @@ export default function RundownBlock({ data, hasCursor, collapsed, onCollapse }: return (
- + onCollapse(!collapsed, data.id)}> {collapsed ? : } diff --git a/apps/client/src/features/rundown/rundown-block/RundownBlockEnd.module.scss b/apps/client/src/features/rundown/rundown-group/RundownGroupEnd.module.scss similarity index 94% rename from apps/client/src/features/rundown/rundown-block/RundownBlockEnd.module.scss rename to apps/client/src/features/rundown/rundown-group/RundownGroupEnd.module.scss index b2b024222..a1d119ecf 100644 --- a/apps/client/src/features/rundown/rundown-block/RundownBlockEnd.module.scss +++ b/apps/client/src/features/rundown/rundown-group/RundownGroupEnd.module.scss @@ -1,6 +1,6 @@ @use '../blockMixins' as *; -.blockEnd { +.groupEnd { cursor: default; height: 1rem; background-color: var(--user-bg, $gray-1050); diff --git a/apps/client/src/features/rundown/rundown-block/RundownBlockEnd.tsx b/apps/client/src/features/rundown/rundown-group/RundownGroupEnd.tsx similarity index 70% rename from apps/client/src/features/rundown/rundown-block/RundownBlockEnd.tsx rename to apps/client/src/features/rundown/rundown-group/RundownGroupEnd.tsx index 09c08feea..91c60903d 100644 --- a/apps/client/src/features/rundown/rundown-block/RundownBlockEnd.tsx +++ b/apps/client/src/features/rundown/rundown-group/RundownGroupEnd.tsx @@ -1,14 +1,14 @@ import { useSortable } from '@dnd-kit/sortable'; import { CSS } from '@dnd-kit/utilities'; -import style from './RundownBlockEnd.module.scss'; +import style from './RundownGroupEnd.module.scss'; -interface BlockEndProps { +interface RundownGroupEndProps { id: string; colour?: string; } -export default function RundownBlockEnd({ id, colour }: BlockEndProps) { +export default function RundownGroupEnd({ id, colour }: RundownGroupEndProps) { const { attributes: dragAttributes, listeners: dragListeners, @@ -18,10 +18,10 @@ export default function RundownBlockEnd({ id, colour }: BlockEndProps) { } = useSortable({ id, data: { - type: 'end-block', + type: 'end-group', }, animateLayoutChanges: () => false, - disabled: true, // we do not want to drag end blocks + disabled: true, // we do not want to drag end groups }); const dragStyle = { @@ -31,7 +31,7 @@ export default function RundownBlockEnd({ id, colour }: BlockEndProps) { return (
(null); const { updateEntry, deleteEntry } = useEntryActions(); - const { selectedEvents, setSelectedBlock } = useEventSelection(); + const { selectedEvents, setSingleEntrySelection } = useEventSelection(); const [onContextMenu] = useContextMenu([ { @@ -61,7 +61,7 @@ export default function RundownMilestone({ colour, cue, entryId, hasCursor, titl } // UI indexes are 1 based - setSelectedBlock({ id: entryId }); + setSingleEntrySelection({ id: entryId }); }; const handleUpdate = (field: 'cue' | 'title', value: string) => { diff --git a/apps/client/src/features/rundown/rundown.utils.ts b/apps/client/src/features/rundown/rundown.utils.ts index 19d07cdaa..8f4cd24ab 100644 --- a/apps/client/src/features/rundown/rundown.utils.ts +++ b/apps/client/src/features/rundown/rundown.utils.ts @@ -1,7 +1,7 @@ import { EntryId, - isOntimeBlock, isOntimeEvent, + isOntimeGroup, isPlayableEvent, MaybeString, OntimeDelay, @@ -81,12 +81,12 @@ function processEntry( processedData.isPast = false; } - if (isOntimeBlock(entry)) { + if (isOntimeGroup(entry)) { processedData.groupId = entry.id; processedData.groupColour = entry.colour; processedData.groupEntries = entry.entries.length; } else { - // for delays and blocks, we insert the group metadata + // for delays and groups, we insert the group metadata if ((entry as OntimeEvent | OntimeDelay | OntimeMilestone).parent !== processedData.groupId) { // if the parent is not the current group, we need to update the groupId processedData.groupId = (entry as OntimeEvent | OntimeDelay | OntimeMilestone).parent; @@ -129,7 +129,7 @@ function processEntry( * Creates a sortable list of entries * ------------------------------------ * Due to limitations in dnd-kit we need to flatten the list of entries - * This list should also be aware of any elements that are sortable (ie: block ends) + * This list should also be aware of any elements that are sortable (ie: group ends) */ export function makeSortableList(order: EntryId[], entries: RundownEntries): EntryId[] { const flatIds: EntryId[] = []; @@ -141,13 +141,13 @@ export function makeSortableList(order: EntryId[], entries: RundownEntries): Ent continue; } - if (isOntimeBlock(entry)) { - // inside a block there are delays and events + if (isOntimeGroup(entry)) { + // inside a group there are delays and events // there is no need for special handling flatIds.push(entry.id); flatIds.push(...entry.entries); - // close the block + // close the group flatIds.push(`end-${entry.id}`); } else { flatIds.push(entry.id); @@ -160,14 +160,14 @@ export function makeSortableList(order: EntryId[], entries: RundownEntries): Ent * Checks whether a drop operation is valid * Currently only used for validating dropping groups */ -export function canDrop(targetType?: SupportedEntry & 'end-block', targetParent?: EntryId | null): boolean { +export function canDrop(targetType?: SupportedEntry & 'end-group', targetParent?: EntryId | null): boolean { // this would mean inserting a group inside another - if (targetType === 'end-block') { + if (targetType === 'end-group') { return false; } // this means swapping places with another group - if (targetType === 'block') { + if (targetType === 'group') { return true; } @@ -182,7 +182,7 @@ export function canDrop(targetType?: SupportedEntry & 'end-block', targetParent? * - order: How to position relative to the destination: * - 'before': Place before the destination * - 'after': Place after the destination - * - 'insert': Insert into the destination (for blocks) + * - 'insert': Insert into the destination (for groups) */ export function moveUp( entryId: EntryId, @@ -195,7 +195,7 @@ export function moveUp( // 1. moving at the top of the list if (!previousEntryId) { - // 1a. we are in a block and need to move outside of it + // 1a. we are in a group and need to move outside of it if ('parent' in currentEntry && currentEntry.parent !== null) { return { destinationId: currentEntry.parent, order: 'before' }; } @@ -203,9 +203,9 @@ export function moveUp( return { destinationId: null, order: 'before' }; } - // 2. moving a block (always moves at top level) - if (isOntimeBlock(currentEntry)) { - // 21. if previous entry is inside a block, swap with parent + // 2. moving a group (always moves at top level) + if (isOntimeGroup(currentEntry)) { + // 21. if previous entry is inside a group, swap with parent const previousEntry = entries[previousEntryId]; if ('parent' in previousEntry && previousEntry.parent !== null) { return { destinationId: previousEntry.parent, order: 'before' }; @@ -218,17 +218,17 @@ export function moveUp( const previousEntry = entries[previousEntryId]; const currentEntryParent = currentEntry.parent; - // 3. moving in and out of a block - if (isOntimeBlock(previousEntry)) { - // 3a. if we're not already in the block, move into it + // 3. moving in and out of a group + if (isOntimeGroup(previousEntry)) { + // 3a. if we're not already in the group, move into it if (currentEntryParent === null) { return { destinationId: previousEntryId, order: 'insert' }; } - // 3b. otherwise, move before the block + // 3b. otherwise, move before the group return { destinationId: previousEntryId, order: 'before' }; } - // 4. moving into the same block as previous entry + // 4. moving into the same group as previous entry if (isOntimeEvent(previousEntry) && previousEntry.parent !== null && currentEntryParent === null) { return { destinationId: previousEntryId, order: 'after' }; } @@ -244,7 +244,7 @@ export function moveUp( * - order: How to position relative to the destination: * - 'before': Place before the destination * - 'after': Place after the destination - * - 'insert': Insert into the destination (for blocks) + * - 'insert': Insert into the destination (for groups) */ export function moveDown( entryId: EntryId, @@ -255,10 +255,10 @@ export function moveDown( const currentIndex = flatOrder.indexOf(entryId); const nextEntryId = flatOrder[currentIndex + 1]; - // 1. check if we're the last entry in a block + // 1. check if we're the last entry in a group if ('parent' in currentEntry && currentEntry.parent !== null) { - const parentBlock = entries[currentEntry.parent]; - if (isOntimeBlock(parentBlock) && parentBlock.entries[parentBlock.entries.length - 1] === entryId) { + const parentGroup = entries[currentEntry.parent]; + if (isOntimeGroup(parentGroup) && parentGroup.entries[parentGroup.entries.length - 1] === entryId) { return { destinationId: currentEntry.parent, order: 'after' }; } } @@ -268,42 +268,42 @@ export function moveDown( return { destinationId: null, order: 'after' }; } - // 3. moving a block (always moves at top level) - if (isOntimeBlock(currentEntry)) { - // if next entry is inside this block, skip past all children + // 3. moving a group (always moves at top level) + if (isOntimeGroup(currentEntry)) { + // if next entry is inside this group, skip past all children if (currentEntry.entries.includes(nextEntryId)) { - const afterBlockIndex = currentIndex + currentEntry.entries.length + 1; - const afterBlockId = flatOrder[afterBlockIndex]; + const afterGroupIndex = currentIndex + currentEntry.entries.length + 1; + const afterGroupId = flatOrder[afterGroupIndex]; - // 2a. block is the last top level entry - if (!afterBlockId) { + // 2a. group is the last top level entry + if (!afterGroupId) { return { destinationId: null, order: 'after' }; } // 2b. move after the next top level event - return { destinationId: afterBlockId, order: 'after' }; + return { destinationId: afterGroupId, order: 'after' }; } - // 2c. empty block move after the next entry + // 2c. empty group move after the next entry return { destinationId: nextEntryId, order: 'after' }; } const nextEntry = entries[nextEntryId]; const currentEntryParent = currentEntry.parent; - // 4. handle moving relative to blocks - if (isOntimeBlock(nextEntry)) { + // 4. handle moving relative to groups + if (isOntimeGroup(nextEntry)) { if (currentEntryParent === null) { - // we are entering a block + // we are entering a group if (nextEntry.entries.length === 0) { - // 3a. if the block is empty, insert into it + // 3a. if the group is empty, insert into it return { destinationId: nextEntryId, order: 'insert' }; } - // 3b. otherwise, add before the first entry in the block - const firstBlockEntryId = nextEntry.entries[0]; - return { destinationId: firstBlockEntryId, order: 'before' }; + // 3b. otherwise, add before the first entry in the group + const firstGroupEntryId = nextEntry.entries[0]; + return { destinationId: firstGroupEntryId, order: 'before' }; } } - // 5. handle moving between block and top level + // 5. handle moving between group and top level const nextEntryParent = isOntimeEvent(nextEntry) ? nextEntry.parent : null; if (nextEntryParent !== null && currentEntryParent === null) { return { destinationId: nextEntryId, order: 'after' }; diff --git a/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.tsx b/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.tsx index a628a369d..ca9f0580c 100644 --- a/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.tsx +++ b/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.tsx @@ -13,7 +13,7 @@ import TimeInputGroup from './TimeInputGroup'; import style from './TimeInputFlow.module.scss'; -interface EventBlockTimerProps { +interface TimeInputFlowProps { eventId: string; countToEnd: boolean; timeStart: number; @@ -36,7 +36,7 @@ function TimeInputFlow({ linkStart, delay, showLabels, -}: EventBlockTimerProps) { +}: TimeInputFlowProps) { const { updateEntry, updateTimer } = useEntryActions(); // In sync with EventEditorTimes diff --git a/apps/client/src/features/rundown/useEventSelection.ts b/apps/client/src/features/rundown/useEventSelection.ts index 09a059875..1c646d728 100644 --- a/apps/client/src/features/rundown/useEventSelection.ts +++ b/apps/client/src/features/rundown/useEventSelection.ts @@ -12,8 +12,8 @@ interface EventSelectionStore { selectedEvents: Set; anchoredIndex: MaybeNumber; cursor: MaybeString; - entryMode: 'event' | 'block' | null; - setSelectedBlock: (selectionArgs: { id: EntryId }) => void; + entryMode: 'event' | 'single' | null; + setSingleEntrySelection: (selectionArgs: { id: EntryId }) => void; setSelectedEvents: (selectionArgs: { id: EntryId; index: number; selectMode: SelectionMode }) => void; clearSelectedEvents: () => void; clearMultiSelect: () => void; @@ -25,14 +25,14 @@ export const useEventSelection = create()((set, get) => ({ anchoredIndex: null, cursor: null, entryMode: null, - setSelectedBlock: ({ id }) => { - set({ selectedEvents: new Set([id]), anchoredIndex: null, cursor: id, entryMode: 'block' }); + setSingleEntrySelection: ({ id }) => { + set({ selectedEvents: new Set([id]), anchoredIndex: null, cursor: id, entryMode: 'single' }); }, setSelectedEvents: ({ id, index, selectMode }) => { const { selectedEvents, anchoredIndex, entryMode } = get(); - // if we are in block mode, we replace the selection and change the mode - if (entryMode === 'block') { + // if we are in single mode, we replace the selection and change the mode + if (entryMode === 'single') { return set({ selectedEvents: new Set([id]), anchoredIndex: index, cursor: id, entryMode: 'event' }); } diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/CuesheetBody.tsx b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/CuesheetBody.tsx index 3bf15a18a..8ad181bfb 100644 --- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/CuesheetBody.tsx +++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/CuesheetBody.tsx @@ -2,12 +2,12 @@ import { RefObject, useEffect } from 'react'; import { useQueryClient } from '@tanstack/react-query'; import { RowModel, Table } from '@tanstack/react-table'; import { - isOntimeBlock, isOntimeDelay, isOntimeEvent, + isOntimeGroup, isOntimeMilestone, - OntimeBlock, OntimeEntry, + OntimeGroup, Rundown, } from 'ontime-types'; import { colourToHex, cssOrHexToColour } from 'ontime-utils'; @@ -18,9 +18,9 @@ import { useSelectedEventId } from '../../../../common/hooks/useSocket'; import { getAccessibleColour } from '../../../../common/utils/styleUtils'; import { usePersistedCuesheetOptions } from '../../cuesheet.options'; -import BlockRow from './BlockRow'; import DelayRow from './DelayRow'; import EventRow from './EventRow'; +import GroupRow from './GroupRow'; import MilestoneRow from './MilestoneRow'; import { cleanup } from './rowObserver'; @@ -39,7 +39,7 @@ export default function CuesheetBody({ rowModel, selectedRef, table }: CuesheetB let eventIndex = 0; // for the first event, it will be past if there is something selected let isPast = Boolean(selectedEventId); - let hadBlock = false; + let hadGroup = false; // remove the observer when the table unmounts useEffect(() => { @@ -62,11 +62,11 @@ export default function CuesheetBody({ rowModel, selectedRef, table }: CuesheetB isPast = false; } - if (isOntimeBlock(entry)) { + if (isOntimeGroup(entry)) { return ( - (RUNDOWN); const parentEntry = rundown?.entries[entry.parent]; - parentBgColour = (parentEntry as OntimeBlock).colour ?? null; + parentBgColour = (parentEntry as OntimeGroup).colour ?? null; } return ; } @@ -113,7 +113,7 @@ export default function CuesheetBody({ rowModel, selectedRef, table }: CuesheetB if (entry.parent) { const rundown = queryClient.getQueryData(RUNDOWN); const parentEntry = rundown?.entries[entry.parent]; - parentBgColour = (parentEntry as OntimeBlock | undefined)?.colour ?? null; + parentBgColour = (parentEntry as OntimeGroup | undefined)?.colour ?? null; } return ( @@ -153,15 +153,15 @@ export default function CuesheetBody({ rowModel, selectedRef, table }: CuesheetB } let parentBgColour: string | undefined; - let firstAfterBlock = false; + let firstAfterGroup = false; if (entry.parent) { const rundown = queryClient.getQueryData(RUNDOWN); - const parentEntry = rundown?.entries[entry.parent] as OntimeBlock | undefined; + const parentEntry = rundown?.entries[entry.parent] as OntimeGroup | undefined; parentBgColour = parentEntry?.colour; - hadBlock = true; - } else if (hadBlock) { - firstAfterBlock = true; - hadBlock = false; + hadGroup = true; + } else if (hadGroup) { + firstAfterGroup = true; + hadGroup = false; } return ( @@ -176,7 +176,7 @@ export default function CuesheetBody({ rowModel, selectedRef, table }: CuesheetB rowBgColour={rowBgColour} parentBgColour={parentBgColour} table={table} - firstAfterBlock={firstAfterBlock} + firstAfterGroup={firstAfterGroup} /> ); } diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.module.scss b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.module.scss index 60a13271b..639b46805 100644 --- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.module.scss +++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.module.scss @@ -11,7 +11,7 @@ background: color-mix(in srgb, transparent 80%, var(--user-bg, $gray-500) 20%); } - &.firstAfterBlock { + &.firstAfterGroup { margin-top: 1rem; } diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.tsx b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.tsx index f6b5661fd..7469dfbc2 100644 --- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.tsx +++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.tsx @@ -26,7 +26,7 @@ interface EventRowProps { rowBgColour?: string; parentBgColour?: string; table: Table; - firstAfterBlock: boolean; + firstAfterGroup: boolean; } export default function EventRow({ @@ -39,7 +39,7 @@ export default function EventRow({ rowBgColour, parentBgColour, table, - firstAfterBlock, + firstAfterGroup, }: EventRowProps) { const { cuesheetMode, hideIndexColumn } = table.options.meta?.options ?? { cuesheetMode: AppMode.Edit, @@ -75,7 +75,7 @@ export default function EventRow({ className={cx([ style.eventRow, event.skip && style.skip, - firstAfterBlock && style.firstAfterBlock, + firstAfterGroup && style.firstAfterGroup, Boolean(parentBgColour) && style.hasParent, ])} style={{ diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/BlockRow.module.scss b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/GroupRow.module.scss similarity index 98% rename from apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/BlockRow.module.scss rename to apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/GroupRow.module.scss index a75b8937c..ef701fa13 100644 --- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/BlockRow.module.scss +++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/GroupRow.module.scss @@ -1,6 +1,6 @@ @import '../CuesheetTable.module.scss'; -.blockRow { +.groupRow { margin-top: 1rem; width: 100%; display: flex; diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/BlockRow.tsx b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/GroupRow.tsx similarity index 76% rename from apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/BlockRow.tsx rename to apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/GroupRow.tsx index 3cf787199..7f1dfce4b 100644 --- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/BlockRow.tsx +++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/GroupRow.tsx @@ -3,14 +3,14 @@ import { flexRender, Table } from '@tanstack/react-table'; import { EntryId, OntimeEntry, SupportedEntry } from 'ontime-types'; import IconButton from '../../../../common/components/buttons/IconButton'; -import { useCurrentBlockId } from '../../../../common/hooks/useSocket'; +import { useCurrentGroupId } from '../../../../common/hooks/useSocket'; import { AppMode } from '../../../../ontimeConfig'; import { useCuesheetTableMenu } from '../cuesheet-table-menu/useCuesheetTableMenu'; -import style from './BlockRow.module.scss'; +import style from './GroupRow.module.scss'; -interface BlockRowProps { - blockId: EntryId; +interface GroupRowProps { + groupId: EntryId; colour: string; hidePast: boolean; rowId: string; @@ -18,8 +18,8 @@ interface BlockRowProps { table: Table; } -export default function BlockRow({ blockId, colour, hidePast, rowId, rowIndex, table }: BlockRowProps) { - const { currentBlockId } = useCurrentBlockId(); +export default function GroupRow({ groupId, colour, hidePast, rowId, rowIndex, table }: GroupRowProps) { + const { currentGroupId } = useCurrentGroupId(); const { cuesheetMode, hideIndexColumn } = table.options.meta?.options ?? { cuesheetMode: AppMode.Edit, @@ -28,12 +28,12 @@ export default function BlockRow({ blockId, colour, hidePast, rowId, rowIndex, t const openMenu = useCuesheetTableMenu((store) => store.openMenu); - if (hidePast && !currentBlockId) { + if (hidePast && !currentGroupId) { return null; } return ( - + {cuesheetMode === AppMode.Edit && ( { const rect = e.currentTarget.getBoundingClientRect(); const yPos = 8 + rect.y + rect.height / 2; - openMenu({ x: rect.x, y: yPos }, blockId, SupportedEntry.Block, rowIndex, null, null); + openMenu({ x: rect.x, y: yPos }, groupId, SupportedEntry.Group, rowIndex, null, null); }} > diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/cuesheetColsFactory.tsx b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/cuesheetColsFactory.tsx index 46f469b2f..a8fd9b0bc 100644 --- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/cuesheetColsFactory.tsx +++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/cuesheetColsFactory.tsx @@ -134,7 +134,7 @@ function MakeMultiLineField({ row, column, table }: CellContext { // remove time-related fields from the comparison // these are not calculated in the parser Object.values(filteredDemoProject.rundowns.default.entries).forEach((entry: any) => { - if (entry.type === SupportedEntry.Block) { + if (entry.type === SupportedEntry.Group) { delete entry.timeStart; delete entry.timeEnd; delete entry.duration; @@ -54,7 +54,7 @@ describe('test parseDatabaseModel() with demo project (valid)', () => { } }); Object.values(data.rundowns.default.entries).forEach((entry: any) => { - if (entry.type === SupportedEntry.Block) { + if (entry.type === SupportedEntry.Group) { delete entry.timeStart; delete entry.timeEnd; delete entry.duration; diff --git a/apps/server/src/api-data/db/migration/db.migration.v3.ts b/apps/server/src/api-data/db/migration/db.migration.v3.ts index 74cf8651b..309a104f1 100644 --- a/apps/server/src/api-data/db/migration/db.migration.v3.ts +++ b/apps/server/src/api-data/db/migration/db.migration.v3.ts @@ -5,7 +5,7 @@ import { EndAction, EntryCustomFields, NormalisedAutomation, - OntimeBlock, + OntimeGroup, OntimeEntry, ProjectData, ProjectRundowns, @@ -317,7 +317,8 @@ export function migrateAutomations(jsonData: object): AutomationSettings | undef * - add parent * * - block: - * - add all the new blocks of the block that is now a group + * - rename to group + * - create group data */ export function migrateRundown( jsonData: object, @@ -392,13 +393,13 @@ export function migrateRundown( }); } else if (entry.type === 'block') { if (parent) { - (newRundown.entries[parent] as OntimeBlock).entries = [...children]; + (newRundown.entries[parent] as OntimeGroup).entries = [...children]; children = []; } parent = entry.id; append({ id: entry.id, - type: SupportedEntry.Block, + type: SupportedEntry.Group, title: entry.title, note: '', // leave blank entries: [], // leave empty @@ -418,7 +419,7 @@ export function migrateRundown( } if (parent) { - (newRundown.entries[parent] as OntimeBlock).entries = [...children]; + (newRundown.entries[parent] as OntimeGroup).entries = [...children]; children = []; } diff --git a/apps/server/src/api-data/db/migration/migration.test.ts b/apps/server/src/api-data/db/migration/migration.test.ts index 8e757cde4..18cb79638 100644 --- a/apps/server/src/api-data/db/migration/migration.test.ts +++ b/apps/server/src/api-data/db/migration/migration.test.ts @@ -48,7 +48,7 @@ describe('v3 to v4', () => { dayOffset: 0, gap: 0, }, - { id: 'block0', type: 'block', title: 'BLOCK 0' }, + { id: 'group0', type: 'block', title: 'GROUP 0' }, { id: 'event2', type: SupportedEntry.Event, @@ -107,7 +107,7 @@ describe('v3 to v4', () => { dayOffset: 0, gap: 0, }, - { id: 'block1', type: 'block', title: 'BLOCK 1' }, + { id: 'group1', type: 'block', title: 'GROUP 1' }, { id: 'delay', type: 'delay', duration: 1000 }, ], project: { @@ -268,8 +268,8 @@ describe('v3 to v4', () => { const expectedRundown: Rundown = { id: 'default', title: 'Default', - order: ['event1', 'block0', 'block1'], - flatOrder: ['event1', 'block0', 'event2', 'event3', 'block1', 'delay'], + order: ['event1', 'group0', 'group1'], + flatOrder: ['event1', 'group0', 'event2', 'event3', 'group1', 'delay'], entries: { event1: { id: 'event1', @@ -298,10 +298,10 @@ describe('v3 to v4', () => { dayOffset: 0, gap: 0, }, - block0: { - id: 'block0', - type: SupportedEntry.Block, - title: 'BLOCK 0', + group0: { + id: 'group0', + type: SupportedEntry.Group, + title: 'GROUP 0', colour: '', custom: {}, duration: 0, @@ -337,7 +337,7 @@ describe('v3 to v4', () => { }, triggers: [{ id: 'testTrig', title: 'Test trigger', trigger: TimerLifeCycle.onStart, automationId: '1' }], flag: false, - parent: 'block0', + parent: 'group0', revision: -1, delay: 0, dayOffset: 0, @@ -368,16 +368,16 @@ describe('v3 to v4', () => { }, triggers: [{ id: 'testTrig', title: 'Test trigger', trigger: TimerLifeCycle.onStart, automationId: '1' }], flag: false, - parent: 'block0', + parent: 'group0', revision: -1, delay: 0, dayOffset: 0, gap: 0, }, - block1: { - id: 'block1', - type: SupportedEntry.Block, - title: 'BLOCK 1', + group1: { + id: 'group1', + type: SupportedEntry.Group, + title: 'GROUP 1', colour: '', custom: {}, duration: 0, @@ -393,7 +393,7 @@ describe('v3 to v4', () => { type: SupportedEntry.Delay, id: 'delay', duration: 1000, - parent: 'block1', + parent: 'group1', }, }, diff --git a/apps/server/src/api-data/excel/__tests__/excel.parser.test.ts b/apps/server/src/api-data/excel/__tests__/excel.parser.test.ts index 1a4692d7f..12c8a78d3 100644 --- a/apps/server/src/api-data/excel/__tests__/excel.parser.test.ts +++ b/apps/server/src/api-data/excel/__tests__/excel.parser.test.ts @@ -156,10 +156,10 @@ describe('parseExcel()', () => { expect((firstEvent as OntimeEvent).title).toBe('A song from the hearth'); }); - it('imports blocks', () => { + it('imports groups', () => { const testdata = [ ['Title', 'Timer type'], - ['a block', 'block'], + ['a group', 'group'], ['an event', 'clock'], ]; @@ -171,7 +171,7 @@ describe('parseExcel()', () => { const firstEvent = result.rundown.entries[result.rundown.order[0]]; expect(result.rundown.order.length).toBe(2); - expect((firstEvent as OntimeEvent).type).toBe(SupportedEntry.Block); + expect((firstEvent as OntimeEvent).type).toBe(SupportedEntry.Group); }); it('imports as events if there is no timer type column', () => { @@ -301,8 +301,8 @@ describe('parseExcel()', () => { ['9:45:00', '10:56:00', 'B', 'x', 'count-down'], ['10:00:00', '16:36:00', 'C', 'x', 'count-down'], ['21:45:00', '22:56:00', 'D', '', 'count-down'], - ['', '', 'BLOCK', 'x', 'block'], // <-- block with link - ['00:0:00', '23:56:00', 'E', 'x', 'count-down'], // <-- link past blocks + ['', '', 'GROUP', 'x', 'group'], // <-- group with link + ['00:0:00', '23:56:00', 'E', 'x', 'count-down'], // <-- must link past previous group ]; const importMap = { @@ -315,7 +315,7 @@ describe('parseExcel()', () => { const result = parseExcel(testData, {}, 'testSheet', importMap); expect(result.rundown.order.length).toBe(6); - expect(result.rundown.order).toMatchObject(['A', 'B', 'C', 'D', 'BLOCK', 'E']); + expect(result.rundown.order).toMatchObject(['A', 'B', 'C', 'D', 'GROUP', 'E']); expect(result.rundown.entries).toMatchObject({ A: { @@ -330,8 +330,8 @@ describe('parseExcel()', () => { D: { linkStart: false, }, - BLOCK: { - type: SupportedEntry.Block, + GROUP: { + type: SupportedEntry.Group, }, E: { linkStart: true, diff --git a/apps/server/src/api-data/excel/excel.parser.ts b/apps/server/src/api-data/excel/excel.parser.ts index 5cfc3a129..06ece46d6 100644 --- a/apps/server/src/api-data/excel/excel.parser.ts +++ b/apps/server/src/api-data/excel/excel.parser.ts @@ -2,10 +2,10 @@ import { CustomFields, Rundown, OntimeEvent, - OntimeBlock, + OntimeGroup, EntryCustomFields, SupportedEntry, - isOntimeBlock, + isOntimeGroup, TimerType, CustomFieldKey, } from 'ontime-types'; @@ -31,6 +31,7 @@ import { parseExcelDate } from '../../utils/time.js'; * @param {array} excelData - array with excel sheet * @param {ImportOptions} options - an object that contains the import map * @returns {object} - parsed object + * TODO: import milestones */ export const parseExcel = ( excelData: unknown[][], @@ -170,7 +171,7 @@ export const parseExcel = ( }, } as const; - const entry: Partial> = {}; + const entry: Partial> = {}; const entryCustomFields: EntryCustomFields = {}; for (let j = 0; j < row.length; j++) { @@ -178,16 +179,16 @@ export const parseExcel = ( // 1. we check if we have set a flag for a known field if (j === timerTypeIndex) { const maybeTimeType = makeString(column, ''); - if (maybeTimeType === 'block') { + if (maybeTimeType === 'group') { // we leave this as a clue for the object filtering later on - entry.type = SupportedEntry.Block; + entry.type = SupportedEntry.Group; entry.entries = []; } else if (maybeTimeType === '' || maybeTimeType === 'event' || isKnownTimerType(maybeTimeType)) { // @ts-expect-error -- we leave this as a clue for the object filtering later on entry.type = SupportedEntry.Event; entry.timerType = validateTimerType(maybeTimeType); } else { - // if it is not a block or a known type, we dont import it + // if it is not a group or a known type, we dont import it return; } } else if (j === titleIndex) { @@ -258,11 +259,11 @@ export const parseExcel = ( } const id = entry.id || generateId(); - // from excel, we can only get blocks and events - if (isOntimeBlock(entry)) { - const block: OntimeBlock = { ...entry, custom: { ...entryCustomFields } }; + // from excel, we can only get groups, milestones and events + if (isOntimeGroup(entry)) { + const group: OntimeGroup = { ...entry, custom: { ...entryCustomFields } }; rundown.order.push(id); - rundown.entries[id] = block; + rundown.entries[id] = group; return; } diff --git a/apps/server/src/api-data/rundown/__mocks__/rundown.mocks.ts b/apps/server/src/api-data/rundown/__mocks__/rundown.mocks.ts index 80a66a52d..eeee948a4 100644 --- a/apps/server/src/api-data/rundown/__mocks__/rundown.mocks.ts +++ b/apps/server/src/api-data/rundown/__mocks__/rundown.mocks.ts @@ -2,7 +2,7 @@ import { SupportedEntry, OntimeEvent, OntimeDelay, - OntimeBlock, + OntimeGroup, Rundown, CustomField, OntimeMilestone, @@ -16,8 +16,8 @@ const baseEvent = { revision: 1, }; -const baseBlock = { - type: SupportedEntry.Block, +const baseGroup = { + type: SupportedEntry.Group, entries: [], }; @@ -28,7 +28,7 @@ const baseMilestone = { }; /** - * Utility to create a Ontime event + * Utility to create an Ontime event */ export function makeOntimeEvent(patch: Partial): OntimeEvent { return { @@ -38,21 +38,21 @@ export function makeOntimeEvent(patch: Partial): OntimeEvent { } /** - * Utility to create a delay event + * Utility to create a delay entry */ export function makeOntimeDelay(patch: Partial): OntimeDelay { return { id: 'delay', type: SupportedEntry.Delay, duration: 0, ...patch } as OntimeDelay; } /** - * Utility to create a block event + * Utility to create a group entry */ -export function makeOntimeBlock(patch: Partial): OntimeBlock { - return { id: 'block', ...baseBlock, ...patch } as OntimeBlock; +export function makeOntimeGroup(patch: Partial): OntimeGroup { + return { id: 'group', ...baseGroup, ...patch } as OntimeGroup; } /** - * Utility to create a block event + * Utility to create a milestone entry */ export function makeOntimeMilestone(patch: Partial): OntimeMilestone { return { id: 'milestone', ...baseMilestone, ...patch } as OntimeMilestone; diff --git a/apps/server/src/api-data/rundown/__tests__/rundown.dao.test.ts b/apps/server/src/api-data/rundown/__tests__/rundown.dao.test.ts index c41a36194..682a38d34 100644 --- a/apps/server/src/api-data/rundown/__tests__/rundown.dao.test.ts +++ b/apps/server/src/api-data/rundown/__tests__/rundown.dao.test.ts @@ -1,10 +1,10 @@ -import { CustomFields, OntimeBlock, OntimeDelay, OntimeEvent, SupportedEntry, TimeStrategy } from 'ontime-types'; +import { CustomFields, OntimeGroup, OntimeDelay, OntimeEvent, SupportedEntry, TimeStrategy } from 'ontime-types'; import { dayInMs, MILLIS_PER_HOUR, MILLIS_PER_MINUTE } from 'ontime-utils'; import { makeOntimeEvent, makeRundown, - makeOntimeBlock, + makeOntimeGroup, makeOntimeDelay, makeCustomField, } from '../__mocks__/rundown.mocks.js'; @@ -112,7 +112,7 @@ describe('processRundown()', () => { order: ['1', '2', '3'], entries: { '1': makeOntimeEvent({ id: '1' }), - '2': makeOntimeBlock({ id: '2' }), + '2': makeOntimeGroup({ id: '2' }), '3': makeOntimeDelay({ id: '3' }), }, }); @@ -121,7 +121,7 @@ describe('processRundown()', () => { expect(initResult.order.length).toBe(3); expect(initResult.order).toStrictEqual(['1', '2', '3']); expect(initResult.entries['1'].type).toBe(SupportedEntry.Event); - expect(initResult.entries['2'].type).toBe(SupportedEntry.Block); + expect(initResult.entries['2'].type).toBe(SupportedEntry.Group); expect(initResult.entries['3'].type).toBe(SupportedEntry.Delay); }); @@ -142,14 +142,14 @@ describe('processRundown()', () => { it('accounts for gaps in rundown when calculating delays', () => { const rundown = makeRundown({ - order: ['1', 'delay', '2', 'block', '3', 'another-block', '4'], + order: ['1', 'delay', '2', 'group', '3', 'another-group', '4'], entries: { '1': makeOntimeEvent({ id: '1', timeStart: 100, timeEnd: 200, duration: 100 }), delay: makeOntimeDelay({ id: 'delay', duration: 200 }), '2': makeOntimeEvent({ id: '2', timeStart: 200, timeEnd: 300, duration: 100 }), - block: makeOntimeBlock({ id: 'block', title: 'break' }), + group: makeOntimeGroup({ id: 'group', title: 'break' }), '3': makeOntimeEvent({ id: '3', timeStart: 400, timeEnd: 500, duration: 100 }), - 'another-block': makeOntimeBlock({ id: 'another-block', title: 'another-break' }), + 'another-group': makeOntimeGroup({ id: 'another-group', title: 'another-break' }), '4': makeOntimeEvent({ id: '4', timeStart: 600, timeEnd: 700, duration: 100 }), }, }); @@ -297,14 +297,14 @@ describe('processRundown()', () => { it('handles negative delays', () => { const rundown = makeRundown({ - order: ['1', 'delay', '2', 'block', '3', 'another-block', '4'], + order: ['1', 'delay', '2', 'group', '3', 'another-group', '4'], entries: { '1': makeOntimeEvent({ id: '1', timeStart: 100, timeEnd: 200, duration: 100 }), delay: makeOntimeDelay({ id: 'delay', duration: -200 }), '2': makeOntimeEvent({ id: '2', timeStart: 200, timeEnd: 300, duration: 100 }), - block: makeOntimeBlock({ id: 'block', title: 'break' }), + group: makeOntimeGroup({ id: 'group', title: 'break' }), '3': makeOntimeEvent({ id: '3', timeStart: 400, timeEnd: 500, duration: 100 }), - 'another-block': makeOntimeBlock({ id: 'another-block', title: 'another-break' }), + 'another-group': makeOntimeGroup({ id: 'another-group', title: 'another-break' }), '4': makeOntimeEvent({ id: '4', timeStart: 600, timeEnd: 700, duration: 100 }), }, }); @@ -321,7 +321,7 @@ describe('processRundown()', () => { it('links times across events', () => { const rundown = makeRundown({ - order: ['1', '2', 'block', 'delay', '3'], + order: ['1', '2', 'group', 'delay', '3'], entries: { '1': makeOntimeEvent({ id: '1', @@ -338,7 +338,7 @@ describe('processRundown()', () => { linkStart: true, timeStrategy: TimeStrategy.LockEnd, }), - block: makeOntimeBlock({ id: 'block' }), + group: makeOntimeGroup({ id: 'group' }), delay: makeOntimeDelay({ id: 'delay' }), '3': makeOntimeEvent({ id: '3', @@ -570,7 +570,7 @@ describe('processRundown()', () => { const rundown = makeRundown({ order: ['1'], entries: { - '1': makeOntimeBlock({ id: '1', entries: ['100', '200', '300'] }), + '1': makeOntimeGroup({ id: '1', entries: ['100', '200', '300'] }), '100': makeOntimeEvent({ id: '100', timeStart: 100, timeEnd: 200, duration: 100, linkStart: false }), '200': makeOntimeEvent({ id: '200', timeStart: 200, timeEnd: 300, duration: 100 }), '300': makeOntimeEvent({ id: '300', timeStart: 300, timeEnd: 400, duration: 100 }), @@ -583,7 +583,7 @@ describe('processRundown()', () => { expect(generatedRundown.totalDelay).toBe(0); expect(generatedRundown.entries).toMatchObject({ '1': { - type: SupportedEntry.Block, + type: SupportedEntry.Group, entries: ['100', '200', '300'], timeStart: 100, timeEnd: 400, @@ -601,15 +601,15 @@ describe('processRundown()', () => { order: ['0', '1', '2', '3'], entries: { '0': makeOntimeEvent({ id: '0', timeStart: 0, timeEnd: 10, duration: 10, linkStart: false }), - '1': makeOntimeBlock({ id: '1', entries: ['101', '102', '103'] }), + '1': makeOntimeGroup({ id: '1', entries: ['101', '102', '103'] }), '101': makeOntimeEvent({ id: '101', timeStart: 100, timeEnd: 200, duration: 100, linkStart: false }), '102': makeOntimeEvent({ id: '102', timeStart: 200, timeEnd: 300, duration: 100, linkStart: true }), '103': makeOntimeEvent({ id: '103', timeStart: 300, timeEnd: 400, duration: 100, linkStart: true }), - '2': makeOntimeBlock({ id: '2', entries: ['201', '202', '203'] }), + '2': makeOntimeGroup({ id: '2', entries: ['201', '202', '203'] }), '201': makeOntimeEvent({ id: '201', timeStart: 500, timeEnd: 600, duration: 100, linkStart: false }), '202': makeOntimeEvent({ id: '202', timeStart: 600, timeEnd: 700, duration: 100, linkStart: true }), '203': makeOntimeEvent({ id: '203', timeStart: 700, timeEnd: 800, duration: 100, linkStart: true }), - '3': makeOntimeBlock({ id: '3', entries: ['301', '302', '303'] }), + '3': makeOntimeGroup({ id: '3', entries: ['301', '302', '303'] }), '301': makeOntimeEvent({ id: '301', timeStart: 900, timeEnd: 1000, duration: 100, linkStart: false }), '302': makeOntimeEvent({ id: '302', timeStart: 1000, timeEnd: 1100, duration: 100, linkStart: true }), '303': makeOntimeEvent({ id: '303', timeStart: 1100, timeEnd: 1200, duration: 100, linkStart: true }), @@ -623,7 +623,7 @@ describe('processRundown()', () => { expect(generatedRundown.entries).toMatchObject({ '0': { type: SupportedEntry.Event, parent: null }, '1': { - type: SupportedEntry.Block, + type: SupportedEntry.Group, entries: ['101', '102', '103'], timeStart: 100, timeEnd: 400, @@ -634,7 +634,7 @@ describe('processRundown()', () => { '102': { parent: '1' }, '103': { parent: '1' }, '2': { - type: SupportedEntry.Block, + type: SupportedEntry.Group, entries: ['201', '202', '203'], timeStart: 500, timeEnd: 800, @@ -645,7 +645,7 @@ describe('processRundown()', () => { '202': { id: '202', timeStart: 600, timeEnd: 700, duration: 100 }, '203': { id: '203', timeStart: 700, timeEnd: 800, duration: 100 }, '3': { - type: SupportedEntry.Block, + type: SupportedEntry.Group, entries: ['301', '302', '303'], timeStart: 900, timeEnd: 1200, @@ -688,36 +688,36 @@ describe('rundownMutation.add()', () => { expect(rundown.entries['mock']).toMatchObject(mockEvent); }); - test('adds an event at the top of the block if no after is given', () => { + test('adds an event at the top of the group if no after is given', () => { const mockEvent = makeOntimeEvent({ id: 'mock', cue: 'mock' }); const rundown = makeRundown({ flatOrder: ['1', '1a'], order: ['1'], entries: { - '1': makeOntimeBlock({ id: '1' }), + '1': makeOntimeGroup({ id: '1' }), '1a': makeOntimeEvent({ id: '1a', parent: '1' }), }, }); - rundownMutation.add(rundown, mockEvent, null, rundown.entries['1'] as OntimeBlock); + rundownMutation.add(rundown, mockEvent, null, rundown.entries['1'] as OntimeGroup); expect(rundown.order).toStrictEqual(['1']); expect(rundown.flatOrder).toStrictEqual(['1', 'mock', '1a']); expect(rundown.entries['mock']).toMatchObject(mockEvent); }); - test('adds an event at the a given location inside a block', () => { + test('adds an event at the a given location inside a group', () => { const mockEvent = makeOntimeEvent({ id: 'mock', cue: 'mock' }); const rundown = makeRundown({ flatOrder: ['1', '1a'], order: ['1'], entries: { - '1': makeOntimeBlock({ id: '1' }), + '1': makeOntimeGroup({ id: '1' }), '1a': makeOntimeEvent({ id: '1a', parent: '1' }), }, }); - rundownMutation.add(rundown, mockEvent, '1a', rundown.entries['1'] as OntimeBlock); + rundownMutation.add(rundown, mockEvent, '1a', rundown.entries['1'] as OntimeGroup); expect(rundown.order).toStrictEqual(['1']); expect(rundown.flatOrder).toStrictEqual(['1', '1a', 'mock']); @@ -785,11 +785,11 @@ describe('rundownMutation.remove()', () => { expect(rundown.entries['3']).not.toBeUndefined(); }); - it('deletes a block and its children', () => { + it('deletes a group and its children', () => { const rundown = makeRundown({ order: ['1', '4'], entries: { - '1': makeOntimeBlock({ id: '1', entries: ['2', '3'] }), + '1': makeOntimeGroup({ id: '1', entries: ['2', '3'] }), '2': makeOntimeEvent({ id: '2', parent: '1' }), '3': makeOntimeDelay({ id: '3', parent: '1' }), '4': makeOntimeEvent({ id: '4', parent: null }), @@ -811,7 +811,7 @@ describe('rundownMutation.remove()', () => { const rundown = makeRundown({ order: ['1', '4'], entries: { - '1': makeOntimeBlock({ id: '1', entries: ['2', '3'] }), + '1': makeOntimeGroup({ id: '1', entries: ['2', '3'] }), '2': makeOntimeEvent({ id: '2', parent: '1' }), '3': makeOntimeDelay({ id: '3', parent: '1' }), '4': makeOntimeEvent({ id: '4', parent: null }), @@ -849,11 +849,11 @@ describe('rundownMutation.removeAll()', () => { }); describe('rundownMutation.reorder()', () => { - it('moves an event into a block', () => { + it('moves an event into a group', () => { const rundown = makeRundown({ order: ['1', '2', '3'], entries: { - '1': makeOntimeBlock({ id: '1', entries: [] }), + '1': makeOntimeGroup({ id: '1', entries: [] }), '2': makeOntimeEvent({ id: '2', parent: null }), '3': makeOntimeEvent({ id: '3', parent: null }), }, @@ -870,12 +870,12 @@ describe('rundownMutation.reorder()', () => { }); }); - it('adds an event into a block', () => { + it('adds an event into a group', () => { const rundown = makeRundown({ order: ['1', '2'], flatOrder: ['1', '11', '2'], entries: { - '1': makeOntimeBlock({ id: '1', entries: ['11'] }), + '1': makeOntimeGroup({ id: '1', entries: ['11'] }), '11': makeOntimeEvent({ id: '11', parent: '1' }), '2': makeOntimeEvent({ id: '2', parent: null }), }, @@ -926,12 +926,12 @@ describe('rundownMutation.reorder()', () => { expect(rundown.order).toStrictEqual(['3', '1', '2']); }); - it('moves an event out and before a block', () => { + it('moves an event out and before a group', () => { const rundown = makeRundown({ order: ['1', '2'], flatOrder: ['1', '11', '2'], entries: { - '1': makeOntimeBlock({ id: '1', entries: ['11'] }), + '1': makeOntimeGroup({ id: '1', entries: ['11'] }), '11': makeOntimeEvent({ id: '11', parent: '1' }), '2': makeOntimeEvent({ id: '2', parent: null }), }, @@ -951,22 +951,22 @@ describe('rundownMutation.reorder()', () => { }); }); - it('moves an event out and after a block', () => { + it('moves an event out and after a group', () => { const rundown = makeRundown({ - order: ['1', 'block', '2'], - flatOrder: ['1', 'block', '11', '2'], + order: ['1', 'group', '2'], + flatOrder: ['1', 'group', '11', '2'], entries: { '1': makeOntimeEvent({ id: '1', parent: null }), - block: makeOntimeBlock({ id: 'block', entries: ['11'] }), - '11': makeOntimeEvent({ id: '11', parent: 'block' }), + group: makeOntimeGroup({ id: 'group', entries: ['11'] }), + '11': makeOntimeEvent({ id: '11', parent: 'group' }), '2': makeOntimeEvent({ id: '2', parent: null }), }, }); - rundownMutation.reorder(rundown, rundown.entries['11'], rundown.entries['block'], 'after'); + rundownMutation.reorder(rundown, rundown.entries['11'], rundown.entries['group'], 'after'); - expect(rundown.order).toStrictEqual(['1', 'block', '11', '2']); - expect(rundown.entries['block']).toMatchObject({ + expect(rundown.order).toStrictEqual(['1', 'group', '11', '2']); + expect(rundown.entries['group']).toMatchObject({ entries: [], }); expect(rundown.entries['11']).toMatchObject({ @@ -977,14 +977,14 @@ describe('rundownMutation.reorder()', () => { }); }); - it('moves an event between blocks', () => { + it('moves an event between groups', () => { const rundown = makeRundown({ order: ['1', '2'], flatOrder: ['1', '11', '2', '22'], entries: { - '1': makeOntimeBlock({ id: '1', entries: ['11'] }), + '1': makeOntimeGroup({ id: '1', entries: ['11'] }), '11': makeOntimeEvent({ id: '11', parent: '1' }), - '2': makeOntimeBlock({ id: '2', entries: ['22'] }), + '2': makeOntimeGroup({ id: '2', entries: ['22'] }), '22': makeOntimeEvent({ id: '22', parent: '2' }), }, }); @@ -1003,13 +1003,13 @@ describe('rundownMutation.reorder()', () => { }); }); - it('moves an event into an empty block', () => { + it('moves an event into an empty group', () => { const rundown = makeRundown({ order: ['1', '2'], flatOrder: ['1', '2', '22'], entries: { - '1': makeOntimeBlock({ id: '1', entries: [] }), - '2': makeOntimeBlock({ id: '2', entries: ['22'] }), + '1': makeOntimeGroup({ id: '1', entries: [] }), + '2': makeOntimeGroup({ id: '2', entries: ['22'] }), '22': makeOntimeEvent({ id: '22', parent: '2' }), }, }); @@ -1028,14 +1028,14 @@ describe('rundownMutation.reorder()', () => { }); }); - it('moves an event out of a block (up)', () => { + it('moves an event out of a group (up)', () => { const rundown = makeRundown({ order: ['1', '2'], flatOrder: ['1', '11', '2', '22'], entries: { - '1': makeOntimeBlock({ id: '1', entries: ['11'] }), + '1': makeOntimeGroup({ id: '1', entries: ['11'] }), '11': makeOntimeEvent({ id: '11', parent: '1' }), - '2': makeOntimeBlock({ id: '2', entries: ['22'] }), + '2': makeOntimeGroup({ id: '2', entries: ['22'] }), '22': makeOntimeEvent({ id: '22', parent: '2' }), }, }); @@ -1059,14 +1059,14 @@ describe('rundownMutation.reorder()', () => { }); }); - it('moves an event out of a block (down)', () => { + it('moves an event out of a group (down)', () => { const rundown = makeRundown({ order: ['1', '2'], flatOrder: ['1', '11', '2', '22'], entries: { - '1': makeOntimeBlock({ id: '1', entries: ['11'] }), + '1': makeOntimeGroup({ id: '1', entries: ['11'] }), '11': makeOntimeEvent({ id: '11', parent: '1' }), - '2': makeOntimeBlock({ id: '2', entries: ['22'] }), + '2': makeOntimeGroup({ id: '2', entries: ['22'] }), '22': makeOntimeEvent({ id: '22', parent: '2' }), }, }); @@ -1088,14 +1088,14 @@ describe('rundownMutation.reorder()', () => { }); }); - it('moves a block (up)', () => { + it('moves a group (up)', () => { const rundown = makeRundown({ order: ['1', '2'], flatOrder: ['1', '11', '2', '22'], entries: { - '1': makeOntimeBlock({ id: '1', entries: ['11'] }), + '1': makeOntimeGroup({ id: '1', entries: ['11'] }), '11': makeOntimeEvent({ id: '11', parent: '1' }), - '2': makeOntimeBlock({ id: '2', entries: ['22'] }), + '2': makeOntimeGroup({ id: '2', entries: ['22'] }), '22': makeOntimeEvent({ id: '22', parent: '2' }), }, }); @@ -1105,14 +1105,14 @@ describe('rundownMutation.reorder()', () => { expect(rundown.order).toStrictEqual(['2', '1']); }); - it('moves a block (down)', () => { + it('moves a group (down)', () => { const rundown = makeRundown({ order: ['1', '2'], flatOrder: ['1', '11', '2', '22'], entries: { - '1': makeOntimeBlock({ id: '1', entries: ['11'] }), + '1': makeOntimeGroup({ id: '1', entries: ['11'] }), '11': makeOntimeEvent({ id: '11', parent: '1' }), - '2': makeOntimeBlock({ id: '2', entries: ['22'] }), + '2': makeOntimeGroup({ id: '2', entries: ['22'] }), '22': makeOntimeEvent({ id: '22', parent: '2' }), }, }); @@ -1132,7 +1132,7 @@ describe('rundownMutation.applyDelay()', () => { delay: makeOntimeDelay({ id: 'delay', duration: 10 }), '1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 10, duration: 10 }), '2': makeOntimeEvent({ id: '2', timeStart: 10, timeEnd: 20, duration: 10, linkStart: true }), - '3': makeOntimeBlock({ id: '3' }), + '3': makeOntimeGroup({ id: '3' }), '4': makeOntimeEvent({ id: '4', timeStart: 20, timeEnd: 30, duration: 10, linkStart: false }), '5': makeOntimeEvent({ id: '5', timeStart: 30, timeEnd: 40, duration: 10, linkStart: true }), }, @@ -1158,7 +1158,7 @@ describe('rundownMutation.applyDelay()', () => { delay: makeOntimeDelay({ id: 'delay', duration: -10 }), '1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 10, duration: 10 }), '2': makeOntimeEvent({ id: '2', timeStart: 10, timeEnd: 20, duration: 10, linkStart: true }), - '3': makeOntimeBlock({ id: '3' }), + '3': makeOntimeGroup({ id: '3' }), '4': makeOntimeEvent({ id: '4', timeStart: 20, timeEnd: 30, duration: 10, linkStart: false }), '5': makeOntimeEvent({ id: '5', timeStart: 30, timeEnd: 40, duration: 10, linkStart: true }), }, @@ -1398,13 +1398,13 @@ describe('rundownMutation.applyDelay()', () => { expect(testRundown.entries).toMatchObject({ '1': { id: '1', timeStart: 0, timeEnd: 100, duration: 100 } }); }); - it('unlinks events to across blocks is it is the first event after the delay', () => { + it('unlinks events to across groups is it is the first event after the delay', () => { const testRundown = makeRundown({ - order: ['1', 'delay', 'block', '2'], + order: ['1', 'delay', 'group', '2'], entries: { '1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100, revision: 1 }), delay: makeOntimeDelay({ id: 'delay', duration: 50 }), - block: makeOntimeBlock({ id: 'block' }), + group: makeOntimeGroup({ id: 'group' }), '2': makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 150, duration: 50, revision: 1, linkStart: true }), }, }); @@ -1420,7 +1420,7 @@ describe('rundownMutation.applyDelay()', () => { duration: 100, revision: 1, }, - block: { id: 'block' }, + group: { id: 'group' }, '2': { id: '2', timeStart: 150, @@ -1432,13 +1432,13 @@ describe('rundownMutation.applyDelay()', () => { }); }); - it('applies a delay from inside a block', () => { + it('applies a delay from inside a group', () => { const testRundown = makeRundown({ - order: ['1', 'block', '2', '3'], + order: ['1', 'group', '2', '3'], entries: { '1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }), - block: makeOntimeBlock({ id: 'block', entries: ['delay'] }), - delay: makeOntimeDelay({ id: 'delay', duration: 100, parent: 'block' }), + group: makeOntimeGroup({ id: 'group', entries: ['delay'] }), + delay: makeOntimeDelay({ id: 'delay', duration: 100, parent: 'group' }), '2': makeOntimeEvent({ id: '2', timeStart: 100, timeEnd: 200, duration: 100, linkStart: true }), '3': makeOntimeEvent({ id: '3', timeStart: 200, timeEnd: 300, duration: 100, linkStart: true }), }, @@ -1476,18 +1476,18 @@ describe('rundownMutation.applyDelay()', () => { it('applies a delay from across nested orders', () => { const testRundown = makeRundown({ - order: ['1', 'delay', 'block', '2', '3'], + order: ['1', 'delay', 'group', '2', '3'], entries: { '1': makeOntimeEvent({ id: '1', timeStart: 0, timeEnd: 100, duration: 100 }), delay: makeOntimeDelay({ id: 'delay', duration: 100 }), - block: makeOntimeBlock({ id: 'block', entries: ['block-1'] }), - 'block-1': makeOntimeEvent({ - id: 'block-1', + group: makeOntimeGroup({ id: 'group', entries: ['group-1'] }), + 'group-1': makeOntimeEvent({ + id: 'group-1', timeStart: 100, timeEnd: 200, duration: 100, linkStart: true, - parent: 'block', + parent: 'group', }), '2': makeOntimeEvent({ id: '2', timeStart: 200, timeEnd: 300, duration: 100, linkStart: true }), '3': makeOntimeEvent({ id: '3', timeStart: 300, timeEnd: 400, duration: 100, linkStart: true }), @@ -1504,7 +1504,7 @@ describe('rundownMutation.applyDelay()', () => { duration: 100, revision: 1, }, - 'block-1': { + 'group-1': { timeStart: 200, timeEnd: 300, duration: 100, @@ -1579,11 +1579,11 @@ describe('rundownMutation.clone()', () => { }); }); - it('clones an event inside a block and adds it to the rundown', () => { + it('clones an event inside a group and adds it to the rundown', () => { const testRundown = makeRundown({ order: ['1'], entries: { - '1': makeOntimeBlock({ id: '1', entries: ['1a'] }), + '1': makeOntimeGroup({ id: '1', entries: ['1a'] }), '1a': makeOntimeEvent({ id: '1a', cue: 'nested', parent: '1' }), }, }); @@ -1599,11 +1599,11 @@ describe('rundownMutation.clone()', () => { }); }); - it('clones a block and its nested elements', () => { + it('clones a group and its nested elements', () => { const testRundown = makeRundown({ order: ['1'], entries: { - '1': makeOntimeBlock({ id: '1', title: 'top', entries: ['1a'] }), + '1': makeOntimeGroup({ id: '1', title: 'top', entries: ['1a'] }), '1a': makeOntimeEvent({ id: '1a', cue: 'nested', parent: '1' }), }, }); @@ -1612,10 +1612,10 @@ describe('rundownMutation.clone()', () => { expect(testRundown.order).toStrictEqual(['1', newEntry.id]); expect(testRundown.entries[newEntry.id]).toMatchObject({ - type: SupportedEntry.Block, + type: SupportedEntry.Group, entries: [expect.any(String)], }); - expect((testRundown.entries[newEntry.id] as OntimeBlock).entries[0]).not.toBe('1a'); + expect((testRundown.entries[newEntry.id] as OntimeGroup).entries[0]).not.toBe('1a'); }); }); @@ -1632,34 +1632,34 @@ describe('rundownMutation.group()', () => { rundownMutation.group(rundown, ['1', '2']); - const blockId = rundown.order[0]; - expect(blockId).toStrictEqual(expect.any(String)); + const groupId = rundown.order[0]; + expect(groupId).toStrictEqual(expect.any(String)); expect(rundown.order).toStrictEqual([expect.any(String), '3']); expect(rundown.entries).toMatchObject({ - [blockId]: { - type: SupportedEntry.Block, + [groupId]: { + type: SupportedEntry.Group, entries: ['1', '2'], }, - '1': { id: '1', type: SupportedEntry.Event, parent: blockId }, - '2': { id: '2', type: SupportedEntry.Event, parent: blockId }, + '1': { id: '1', type: SupportedEntry.Event, parent: groupId }, + '2': { id: '2', type: SupportedEntry.Event, parent: groupId }, '3': { id: '3', type: SupportedEntry.Event, parent: null }, }); }); }); describe('rundownMutation.ungroup()', () => { - it('should correctly dissolve a block into its events', () => { + it('should correctly dissolve a group into its events', () => { const testRundown = makeRundown({ order: ['1', '2'], entries: { '1': makeOntimeEvent({ id: '1', cue: 'data1', parent: null }), - '2': makeOntimeBlock({ id: '2', entries: ['21', '22'] }), + '2': makeOntimeGroup({ id: '2', entries: ['21', '22'] }), '21': makeOntimeEvent({ id: '21', cue: 'data21', parent: '2' }), '22': makeOntimeEvent({ id: '22', cue: 'data22', parent: '2' }), }, }); - rundownMutation.ungroup(testRundown, testRundown.entries['2'] as OntimeBlock); + rundownMutation.ungroup(testRundown, testRundown.entries['2'] as OntimeGroup); expect(testRundown.order).toStrictEqual(['1', '21', '22']); expect(testRundown.entries['2']).toBeUndefined(); diff --git a/apps/server/src/api-data/rundown/__tests__/rundown.parser.test.ts b/apps/server/src/api-data/rundown/__tests__/rundown.parser.test.ts index 1fd17a8d3..76affeefb 100644 --- a/apps/server/src/api-data/rundown/__tests__/rundown.parser.test.ts +++ b/apps/server/src/api-data/rundown/__tests__/rundown.parser.test.ts @@ -1,7 +1,7 @@ -import { SupportedEntry, OntimeEvent, OntimeBlock, Rundown, CustomFields } from 'ontime-types'; +import { SupportedEntry, OntimeEvent, OntimeGroup, Rundown, CustomFields } from 'ontime-types'; import { defaultRundown } from '../../../models/dataModel.js'; -import { makeOntimeBlock, makeOntimeEvent, makeOntimeMilestone } from '../__mocks__/rundown.mocks.js'; +import { makeOntimeGroup, makeOntimeEvent, makeOntimeMilestone } from '../__mocks__/rundown.mocks.js'; import { parseRundowns, parseRundown, handleCustomField, addToCustomAssignment } from '../rundown.parser.js'; @@ -47,7 +47,7 @@ describe('parseRundown()', () => { flatOrder: ['1', '2', '3', '4'], entries: { '1': { id: '1', type: SupportedEntry.Event, title: 'test', skip: false } as OntimeEvent, // OK - '2': { id: '1', type: SupportedEntry.Block, title: 'test 2' } as OntimeBlock, // duplicate ID + '2': { id: '1', type: SupportedEntry.Group, title: 'test 2' } as OntimeGroup, // duplicate ID '3': {} as OntimeEvent, // no data '4': { id: '4', title: 'test 2', skip: false } as OntimeEvent, // no type }, @@ -221,7 +221,7 @@ describe('parseRundown()', () => { flatOrder: ['1', '2', '21'], entries: { '1': makeOntimeEvent({ id: '1', custom: { lighting: 'yes' } }), - '2': makeOntimeBlock({ id: '2', entries: ['21'], custom: { lighting: '' } }), + '2': makeOntimeGroup({ id: '2', entries: ['21'], custom: { lighting: '' } }), '21': makeOntimeEvent({ id: '21', custom: { lighting: '' } }), }, revision: 1, @@ -237,7 +237,7 @@ describe('parseRundown()', () => { const parsedRundown = parseRundown(rundown, customFields); expect((parsedRundown.entries['1'] as OntimeEvent).custom).toStrictEqual({ lighting: 'yes' }); - expect((parsedRundown.entries['2'] as OntimeBlock).custom).not.toHaveProperty('lighting'); + expect((parsedRundown.entries['2'] as OntimeGroup).custom).not.toHaveProperty('lighting'); expect((parsedRundown.entries['21'] as OntimeEvent).custom).not.toHaveProperty('lighting'); }); @@ -245,41 +245,41 @@ describe('parseRundown()', () => { const rundown = { id: 'test', title: '', - order: ['block'], - flatOrder: ['block'], + order: ['group'], + flatOrder: ['group'], isNextDay: false, entries: { - block: makeOntimeBlock({ - id: 'block', - title: 'block-title', - note: 'block-note', + group: makeOntimeGroup({ + id: 'group', + title: 'group-title', + note: 'group-note', colour: 'red', entries: ['1', '2', '3'], }), - '1': makeOntimeEvent({ id: '1', parent: 'block' }), - '2': makeOntimeMilestone({ id: '2', parent: 'block' }), + '1': makeOntimeEvent({ id: '1', parent: 'group' }), + '2': makeOntimeMilestone({ id: '2', parent: 'group' }), }, revision: 1, } as Rundown; const parsedRundown = parseRundown(rundown, {}); - expect(parsedRundown.order).toStrictEqual(['block']); - expect(parsedRundown.flatOrder).toStrictEqual(['block', '1', '2']); + expect(parsedRundown.order).toStrictEqual(['group']); + expect(parsedRundown.flatOrder).toStrictEqual(['group', '1', '2']); expect(parsedRundown.entries).toMatchObject({ - block: { id: 'block', type: SupportedEntry.Block, entries: ['1', '2'] }, + group: { id: 'group', type: SupportedEntry.Group, entries: ['1', '2'] }, '1': { id: '1', type: SupportedEntry.Event }, '2': { id: '2', type: SupportedEntry.Milestone }, }); }); - it('parses events nested in blocks', () => { + it('parses events nested in groups', () => { const rundown = { id: 'test', title: '', - order: ['block'], - flatOrder: ['block'], + order: ['group'], + flatOrder: ['group'], entries: { - block: makeOntimeBlock({ id: 'block', entries: ['1', '2'] }), + group: makeOntimeGroup({ id: 'group', entries: ['1', '2'] }), '1': makeOntimeEvent({ id: '1' }), '2': makeOntimeEvent({ id: '2' }), }, @@ -288,7 +288,7 @@ describe('parseRundown()', () => { const parsedRundown = parseRundown(rundown, {}); expect(parsedRundown.order.length).toEqual(1); - expect(parsedRundown.entries.block).toMatchObject({ entries: ['1', '2'] }); + expect(parsedRundown.entries.group).toMatchObject({ entries: ['1', '2'] }); expect(Object.keys(parsedRundown.entries).length).toEqual(3); }); }); diff --git a/apps/server/src/api-data/rundown/__tests__/rundown.utils.test.ts b/apps/server/src/api-data/rundown/__tests__/rundown.utils.test.ts index 43adb62fd..77edb2c69 100644 --- a/apps/server/src/api-data/rundown/__tests__/rundown.utils.test.ts +++ b/apps/server/src/api-data/rundown/__tests__/rundown.utils.test.ts @@ -1,4 +1,4 @@ -import { TimeStrategy, EndAction, TimerType, OntimeEvent, OntimeBlock } from 'ontime-types'; +import { TimeStrategy, EndAction, TimerType, OntimeEvent, OntimeGroup } from 'ontime-types'; import { MILLIS_PER_HOUR } from 'ontime-utils'; import { assertType } from 'vitest'; @@ -11,7 +11,7 @@ import { getInsertAfterId, hasChanges, } from '../rundown.utils.js'; -import { makeOntimeBlock, makeOntimeEvent, makeRundown } from '../__mocks__/rundown.mocks.js'; +import { makeOntimeGroup, makeOntimeEvent, makeRundown } from '../__mocks__/rundown.mocks.js'; describe('test event validator', () => { it('validates a good object', () => { @@ -227,13 +227,13 @@ describe('getInsertAfterId()', () => { entries: { '1': makeOntimeEvent({ id: '1', parent: null }), '2': makeOntimeEvent({ id: '2', parent: null }), - block: makeOntimeBlock({ id: 'block', entries: ['31', '32'] }), - '31': makeOntimeEvent({ id: '31', parent: 'block' }), - '32': makeOntimeEvent({ id: '32', parent: 'block' }), - '4': makeOntimeEvent({ id: '31', parent: null }), + group: makeOntimeGroup({ id: 'group', entries: ['31', '32'] }), + '31': makeOntimeEvent({ id: '31', parent: 'group' }), + '32': makeOntimeEvent({ id: '32', parent: 'group' }), + '4': makeOntimeEvent({ id: '4', parent: null }), }, - order: ['1', '2', 'block', '4'], - flatOrder: ['1', '2', 'block', '31', '32', '4'], + order: ['1', '2', 'group', '4'], + flatOrder: ['1', '2', 'group', '31', '32', '4'], }); it('returns afterId if provided', () => { @@ -251,12 +251,12 @@ describe('getInsertAfterId()', () => { it('returns the previous id of an entry in the rundown', () => { expect(getInsertAfterId(rundown, null, undefined, '2')).toBe('1'); - expect(getInsertAfterId(rundown, null, undefined, '4')).toBe('block'); - expect(getInsertAfterId(rundown, null, undefined, 'block')).toBe('2'); + expect(getInsertAfterId(rundown, null, undefined, '4')).toBe('group'); + expect(getInsertAfterId(rundown, null, undefined, 'group')).toBe('2'); }); - it('returns the previous id of an event in a block', () => { - expect(getInsertAfterId(rundown, rundown.entries.block as OntimeBlock, undefined, '31')).toBeNull(); - expect(getInsertAfterId(rundown, rundown.entries.block as OntimeBlock, undefined, '32')).toBe('31'); + it('returns the previous id of an event in a group', () => { + expect(getInsertAfterId(rundown, rundown.entries.group as OntimeGroup, undefined, '31')).toBeNull(); + expect(getInsertAfterId(rundown, rundown.entries.group as OntimeGroup, undefined, '32')).toBe('31'); }); }); diff --git a/apps/server/src/api-data/rundown/rundown.dao.ts b/apps/server/src/api-data/rundown/rundown.dao.ts index 361fd5121..cfb7e3aed 100644 --- a/apps/server/src/api-data/rundown/rundown.dao.ts +++ b/apps/server/src/api-data/rundown/rundown.dao.ts @@ -15,10 +15,10 @@ import { CustomFieldKey, CustomFields, EntryId, - isOntimeBlock, + isOntimeGroup, isOntimeEvent, isPlayableEvent, - OntimeBlock, + OntimeGroup, OntimeDelay, OntimeEntry, OntimeEvent, @@ -32,9 +32,9 @@ import { getDataProvider } from '../../classes/data-provider/DataProvider.js'; import type { AssignedMap, CustomFieldsMetadata, RundownMetadata } from './rundown.types.js'; import { applyPatchToEntry, - cloneBlock, + cloneGroup, cloneEntry, - createBlock, + createGroup, deleteById, doesInvalidateMetadata, getUniqueId, @@ -176,14 +176,14 @@ export function createTransaction(options: TransactionOptions): Transaction { /** * Add entry to rundown, handles the following cases: - * - 1a. add entry in block, after a given entry - * - 1b. add entry in block, at the beginning + * - 1a. add entry in group, after a given entry + * - 1b. add entry in group, at the beginning * - 2a. add entry to the rundown, after a given entry * - 2b. add entry to the rundown, at the beginning */ -function add(rundown: Rundown, entry: OntimeEntry, afterId: EntryId | null, parent: OntimeBlock | null): OntimeEntry { +function add(rundown: Rundown, entry: OntimeEntry, afterId: EntryId | null, parent: OntimeGroup | null): OntimeEntry { if (parent) { - // 1. inserting an entry inside a block + // 1. inserting an entry inside a group if (afterId) { const atEventsIndex = parent.entries.indexOf(afterId) + 1; const atFlatIndex = rundown.flatOrder.indexOf(afterId) + 1; @@ -232,31 +232,31 @@ function edit(rundown: Rundown, patch: PatchWithId): { entry: OntimeEntry; didIn /** * Deletes an entry from the rundown - * - if the entry is an ontime block, we delete it along with its children - * - if the entry is inside a block, we delete it and remove the reference from the parent block + * - if the entry is an ontime group, we delete it along with its children + * - if the entry is inside a group, we delete it and remove the reference from the parent group */ function remove(rundown: Rundown, entry: OntimeEntry) { - if (isOntimeBlock(entry)) { - // for ontime blocks, we need to iterate through the children and delete them + if (isOntimeGroup(entry)) { + // for ontime groups, we need to iterate through the children and delete them for (let i = 0; i < entry.entries.length; i++) { const nestedEntryId = entry.entries[i]; deleteEntry(nestedEntryId); } } else if (entry.parent) { - // at this point, we are handling entries inside a block, so we need to remove the reference - const parentBlock = rundown.entries[entry.parent]; + // at this point, we are handling entries inside a group, so we need to remove the reference + const parentGroup = rundown.entries[entry.parent]; // eslint-disable-next-line no-unused-labels -- dev code path DEV: { - if (parentBlock && !isOntimeBlock(parentBlock)) { - consoleError(`Parent block with ID ${entry.parent} is not a valid OntimeBlock`); + if (parentGroup && !isOntimeGroup(parentGroup)) { + consoleError(`Parent group with ID ${entry.parent} is not a valid Group`); } } - if (parentBlock && isOntimeBlock(parentBlock)) { + if (parentGroup && isOntimeGroup(parentGroup)) { // we call a mutation to the parent event to remove the entry from the events - const filteredEvents = deleteById(parentBlock.entries, entry.id); - edit(rundown, { id: parentBlock.id, entries: filteredEvents }); + const filteredEvents = deleteById(parentGroup.entries, entry.id); + edit(rundown, { id: parentGroup.id, entries: filteredEvents }); } } deleteEntry(entry.id); @@ -281,22 +281,22 @@ function removeAll(rundown: Rundown): Rundown { /** * Reorders an entry in the rundown * Handle moving across order lists - * @param order - 'before' | 'after' | 'insert' - where to add the entry, insert serves to add the entry into an empty block - * @throws if we insert a block inside another + * @param order - 'before' | 'after' | 'insert' - where to add the entry, insert serves to add the entry into an empty group + * @throws if we insert a group inside another */ function reorder(rundown: Rundown, eventFrom: OntimeEntry, eventTo: OntimeEntry, order: 'before' | 'after' | 'insert') { // handle moving across parents const fromParent: EntryId | null = (eventFrom as { parent?: EntryId })?.parent ?? null; const toParent = (() => { - if (isOntimeBlock(eventTo)) { - // Special case: if we're moving relative to our own parent block, remove from block + if (isOntimeGroup(eventTo)) { + // Special case: if we're moving relative to our own parent group, remove from group if ('parent' in eventFrom && eventFrom.parent === eventTo.id) { return null; } if (order === 'insert') { - // prevent blocks from being inserted into other blocks - if (isOntimeBlock(eventFrom)) { - throw new Error('Cannot insert a block into another block'); + // prevent groups from being inserted into other groups + if (isOntimeGroup(eventFrom)) { + throw new Error('Cannot insert a group into another group'); } return eventTo.id; } @@ -310,8 +310,8 @@ function reorder(rundown: Rundown, eventFrom: OntimeEntry, eventTo: OntimeEntry, eventFrom.parent = toParent; } - const sourceArray = fromParent === null ? rundown.order : (rundown.entries[fromParent] as OntimeBlock).entries; - const destinationArray = toParent === null ? rundown.order : (rundown.entries[toParent] as OntimeBlock).entries; + const sourceArray = fromParent === null ? rundown.order : (rundown.entries[fromParent] as OntimeGroup).entries; + const destinationArray = toParent === null ? rundown.order : (rundown.entries[toParent] as OntimeGroup).entries; const fromIndex = sourceArray.indexOf(eventFrom.id); const toIndex = (() => { @@ -450,11 +450,11 @@ function swap(rundown: Rundown, eventFrom: OntimeEvent, eventTo: OntimeEvent) { /** * Inserts a clone of the given entry into the rundown - * Handles cloning children if the entry is a block + * Handles cloning children if the entry is a group */ function clone(rundown: Rundown, entry: OntimeEntry): OntimeEntry { - if (isOntimeBlock(entry)) { - const newBlock = cloneBlock(entry, getUniqueId(rundown)); + if (isOntimeGroup(entry)) { + const newGroup = cloneGroup(entry, getUniqueId(rundown)); const nestedIds: EntryId[] = []; for (let i = 0; i < entry.entries.length; i++) { @@ -464,83 +464,83 @@ function clone(rundown: Rundown, entry: OntimeEntry): OntimeEntry { continue; } - // clone the event and assign it to the new block + // clone the event and assign it to the new group const newNestedEntry = cloneEntry(nestedEntry, getUniqueId(rundown)); - (newNestedEntry as OntimeEvent | OntimeDelay).parent = newBlock.id; + (newNestedEntry as OntimeEvent | OntimeDelay).parent = newGroup.id; nestedIds.push(newNestedEntry.id); // we immediately insert the nested entries into the rundown rundown.entries[newNestedEntry.id] = newNestedEntry; } - // indexes + 1 since we are inserting after the cloned block + // indexes + 1 since we are inserting after the cloned group const atIndex = rundown.order.indexOf(entry.id) + 1; - newBlock.entries = nestedIds; - newBlock.title = `${entry.title || 'Untitled'} (copy)`; + newGroup.entries = nestedIds; + newGroup.title = `${entry.title || 'Untitled'} (copy)`; - rundown.entries[newBlock.id] = newBlock; - rundown.order = insertAtIndex(atIndex, newBlock.id, rundown.order); + rundown.entries[newGroup.id] = newGroup; + rundown.order = insertAtIndex(atIndex, newGroup.id, rundown.order); - return newBlock; + return newGroup; } else { - const parent: OntimeBlock | null = entry.parent ? (rundown.entries[entry.parent] as OntimeBlock) : null; + const parent: OntimeGroup | null = entry.parent ? (rundown.entries[entry.parent] as OntimeGroup) : null; return add(rundown, cloneEntry(entry, getUniqueId(rundown)), entry.id, parent); } } /** * Groups a list of entries - * It ensures that the entries get reassigned parent and the block gets a list of events + * It ensures that the entries get reassigned parent and the group gets a list of events * The group will be created at the index of the first event in the order, not at the lowest index * Mutates the given rundown */ -function group(rundown: Rundown, entryIds: EntryId[]): OntimeBlock { - const newBlock = createBlock({ id: getUniqueId(rundown) }); +function group(rundown: Rundown, entryIds: EntryId[]): OntimeGroup { + const newGroup = createGroup({ id: getUniqueId(rundown) }); const nestedEvents: EntryId[] = []; let firstIndex = -1; for (let i = 0; i < entryIds.length; i++) { const entryId = entryIds[i]; const entry = rundown.entries[entryId]; - if (!entry || isOntimeBlock(entry)) { + if (!entry || isOntimeGroup(entry)) { // invalid operation, we skip this entry continue; } - // the block will be created at the first selected event position + // the group will be created at the first selected event position // note that this is not the lowest index if (firstIndex === -1) { firstIndex = rundown.flatOrder.indexOf(entryId); } nestedEvents.push(entryId); - entry.parent = newBlock.id; + entry.parent = newGroup.id; rundown.flatOrder = rundown.flatOrder.filter((id) => id !== entryId); rundown.order = rundown.order.filter((id) => id !== entryId); } - newBlock.entries = nestedEvents; + newGroup.entries = nestedEvents; const insertIndex = Math.max(0, firstIndex); // we have filtered the items from the order - // we will insert them now, with only the block at top level ... - rundown.order = insertAtIndex(insertIndex, newBlock.id, rundown.order); - rundown.entries[newBlock.id] = newBlock; + // we will insert them now, with only the group at top level ... + rundown.order = insertAtIndex(insertIndex, newGroup.id, rundown.order); + rundown.entries[newGroup.id] = newGroup; - return newBlock; + return newGroup; } /** - * Deletes a block and moves all its children to the top level order + * Deletes a group and moves all its children to the top level order */ -function ungroup(rundown: Rundown, block: OntimeBlock) { - // get the events from the block and merge them into the order where the block was - const nestedEvents = block.entries; - const blockIndex = rundown.order.indexOf(block.id); - rundown.order.splice(blockIndex, 1, ...nestedEvents); +function ungroup(rundown: Rundown, group: OntimeGroup) { + // get the events from the group and merge them into the order where the group was + const nestedEvents = group.entries; + const groupIndex = rundown.order.indexOf(group.id); + rundown.order.splice(groupIndex, 1, ...nestedEvents); - // delete block from entries and remove its reference from the child events - delete rundown.entries[block.id]; + // delete the group from entries and remove its reference from the child events + delete rundown.entries[group.id]; for (let i = 0; i < nestedEvents.length; i++) { const eventId = nestedEvents[i]; const entry = rundown.entries[eventId]; @@ -720,16 +720,16 @@ export function processRundown( } const { processedEntry } = process(currentEntry, null); - // if the event is a block, we process the nested entries + // if the event is a group, we process the nested entries // the code here is a copy of the processing of top level events - if (isOntimeBlock(processedEntry)) { - let blockStartTime = null; - let blockEndTime = null; + if (isOntimeGroup(processedEntry)) { + let groupStartTime = null; + let groupEndTime = null; let isFirstLinked = false; - const blockEvents: EntryId[] = []; + const groupEvents: EntryId[] = []; processedEntry.duration = 0; - // check if the block contains nested entries + // check if the group contains nested entries for (let j = 0; j < processedEntry.entries.length; j++) { const nestedEntryId = processedEntry.entries[j]; const nestedEntry = initialRundown.entries[nestedEntryId]; @@ -738,7 +738,7 @@ export function processRundown( continue; } - blockEvents.push(nestedEntry.id); + groupEvents.push(nestedEntry.id); const { processedEntry: processedNestedEntry } = process(nestedEntry, processedEntry.id); // we dont extract metadata of skipped events, @@ -748,24 +748,24 @@ export function processRundown( } // first start is always the first event - if (blockStartTime === null) { - blockStartTime = processedNestedEntry.timeStart; + if (groupStartTime === null) { + groupStartTime = processedNestedEntry.timeStart; isFirstLinked = Boolean(processedNestedEntry.linkStart); } // lastEntry is the event with the latest end time - blockEndTime = processedNestedEntry.timeEnd; + groupEndTime = processedNestedEntry.timeEnd; if (j > 0) { processedEntry.duration += processedNestedEntry.gap; } processedEntry.duration = processedEntry.duration + processedNestedEntry.duration; } - // update block metadata - processedEntry.timeStart = blockStartTime; - processedEntry.timeEnd = blockEndTime; + // update group metadata + processedEntry.timeStart = groupStartTime; + processedEntry.timeEnd = groupEndTime; processedEntry.isFirstLinked = isFirstLinked; - processedEntry.entries = blockEvents; + processedEntry.entries = groupEvents; } } diff --git a/apps/server/src/api-data/rundown/rundown.parser.ts b/apps/server/src/api-data/rundown/rundown.parser.ts index af579e2ac..a1c011ead 100644 --- a/apps/server/src/api-data/rundown/rundown.parser.ts +++ b/apps/server/src/api-data/rundown/rundown.parser.ts @@ -6,7 +6,7 @@ import { OntimeEvent, isOntimeEvent, isOntimeDelay, - isOntimeBlock, + isOntimeGroup, CustomFieldKey, EntryId, OntimeEntry, @@ -21,7 +21,7 @@ import { defaultRundown } from '../../models/dataModel.js'; import { delay as delayDef } from '../../models/eventsDefinition.js'; import type { ErrorEmitter } from '../../utils/parserUtils.js'; -import { calculateDayOffset, cleanupCustomFields, createBlock, createEvent, createMilestone } from './rundown.utils.js'; +import { calculateDayOffset, cleanupCustomFields, createGroup, createEvent, createMilestone } from './rundown.utils.js'; import { RundownMetadata } from './rundown.types.js'; /** @@ -110,7 +110,11 @@ export function parseRundown( } else if (isOntimeMilestone(event)) { newEvent = createMilestone({ ...event, id }); cleanupCustomFields(newEvent.custom, parsedCustomFields); - } else if (isOntimeBlock(event)) { + /** + * We leave here an entry point for blocks for the alpha testers, should remove this after a while + */ + // @ts-expect-error -- we are checking a legacy type + } else if (event.type === 'block' || isOntimeGroup(event)) { for (let i = 0; i < event.entries.length; i++) { const nestedEventId = event.entries[i]; const nestedEvent = rundown.entries[nestedEventId]; @@ -143,7 +147,7 @@ export function parseRundown( } } - newEvent = createBlock({ ...structuredClone(event), id }); + newEvent = createGroup({ ...structuredClone(event), id }); // ensure entries exist if (event.entries?.length > 0) { newEvent.entries = event.entries.filter((eventId) => Object.hasOwn(rundown.entries, eventId)); @@ -240,9 +244,9 @@ export function makeRundownMetadata(customFields: CustomFields) { function process( entry: T, - childOfBlock: EntryId | null, + childOfGroup: EntryId | null, ): { processedData: ProcessedRundownMetadata; processedEntry: T } { - const data = processEntry(rundownMeta, customFields, entry, childOfBlock); + const data = processEntry(rundownMeta, customFields, entry, childOfGroup); rundownMeta = data.processedData; return data; } @@ -261,7 +265,7 @@ function processEntry( rundownMetadata: ProcessedRundownMetadata, customFields: CustomFields, entry: T, - childOfBlock: EntryId | null, + childOfGroup: EntryId | null, ): { processedData: ProcessedRundownMetadata; processedEntry: T } { const processedData = { ...rundownMetadata }; const currentEntry = structuredClone(entry); @@ -294,7 +298,7 @@ function processEntry( currentEntry.dayOffset = processedData.totalDays; currentEntry.delay = 0; // this means we dont calculate delays or gaps for skipped events currentEntry.gap = 0; // this means we dont calculate delays or gaps for skipped events - currentEntry.parent = childOfBlock; + currentEntry.parent = childOfGroup; // update rundown metadata, it only concerns playable events if (isPlayableEvent(currentEntry)) { @@ -353,10 +357,10 @@ function processEntry( } else if (isOntimeDelay(currentEntry)) { // !!! this must happen after handling the links processedData.totalDelay += currentEntry.duration; - currentEntry.parent = childOfBlock; + currentEntry.parent = childOfGroup; } - if (!childOfBlock) { + if (!childOfGroup) { processedData.order.push(currentEntry.id); } processedData.entries[currentEntry.id] = currentEntry; diff --git a/apps/server/src/api-data/rundown/rundown.service.ts b/apps/server/src/api-data/rundown/rundown.service.ts index ef7a116c4..f4142f84c 100644 --- a/apps/server/src/api-data/rundown/rundown.service.ts +++ b/apps/server/src/api-data/rundown/rundown.service.ts @@ -4,10 +4,10 @@ import { CustomFields, EntryId, EventPostPayload, - isOntimeBlock, + isOntimeGroup, isOntimeDelay, isOntimeEvent, - OntimeBlock, + OntimeGroup, OntimeEntry, PatchWithId, RefetchKey, @@ -35,12 +35,12 @@ export async function addEntry(eventData: EventPostPayload): Promise { /** * Moves an event to a new position in the rundown - * Handles moving across root orders (a block order and top level order) + * Handles moving across root orders (a group order and top level order) * @throws if entryId or destinationId not found */ export function reorderEntry(entryId: EntryId, destinationId: EntryId, order: 'before' | 'after' | 'insert') { @@ -356,7 +356,7 @@ export async function cloneEntry(entryId: EntryId): Promise { updateRuntimeOnChange(rundownMetadata); // notify timer and external services of change - if (isOntimeBlock(newEntry)) { + if (isOntimeGroup(newEntry)) { notifyChanges(rundownMetadata, revision, { timer: newEntry.entries, external: true }); } else if (isOntimeEvent(newEntry)) { notifyChanges(rundownMetadata, revision, { timer: [newEntry.id], external: true }); @@ -370,7 +370,7 @@ export async function cloneEntry(entryId: EntryId): Promise { } /** - * Groups a list of entries into a new block + * Groups a list of entries into a new group */ export async function groupEntries(entryIds: EntryId[]): Promise { const { rundown, commit } = createTransaction({ mutableRundown: true, mutableCustomFields: false }); @@ -391,17 +391,17 @@ export async function groupEntries(entryIds: EntryId[]): Promise { } /** - * Deletes a block and moves all its children to the top level + * Deletes a group and moves all its children to the top level */ -export async function ungroupEntries(blockId: EntryId): Promise { +export async function ungroupEntries(groupId: EntryId): Promise { const { rundown, commit } = createTransaction({ mutableRundown: true, mutableCustomFields: false }); - const block = rundown.entries[blockId]; - if (!block || !isOntimeBlock(block)) { - throw new Error(`Block with ID ${blockId} not found or is not a block`); + const group = rundown.entries[groupId]; + if (!group || !isOntimeGroup(group)) { + throw new Error(`Group with ID ${groupId} not found or is not a group`); } - rundownMutation.ungroup(rundown, block); + rundownMutation.ungroup(rundown, group); const { rundown: rundownResult, rundownMetadata, revision } = commit(); // schedule the side effects diff --git a/apps/server/src/api-data/rundown/rundown.utils.ts b/apps/server/src/api-data/rundown/rundown.utils.ts index b04a6f29f..1b6c4e534 100644 --- a/apps/server/src/api-data/rundown/rundown.utils.ts +++ b/apps/server/src/api-data/rundown/rundown.utils.ts @@ -2,12 +2,12 @@ import { CustomFields, EntryCustomFields, EntryId, - isOntimeBlock, + isOntimeGroup, isOntimeDelay, isOntimeEvent, isOntimeMilestone, OntimeBaseEvent, - OntimeBlock, + OntimeGroup, OntimeDelay, OntimeEntry, OntimeEvent, @@ -27,7 +27,7 @@ import { import { event as eventDef, - block as blockDef, + group as groupDef, delay as delayDef, milestone as milestoneDef, } from '../../models/eventsDefinition.js'; @@ -39,8 +39,8 @@ type CompleteEntry = ? OntimeEvent : T extends Partial ? OntimeDelay - : T extends Partial - ? OntimeBlock + : T extends Partial + ? OntimeGroup : T extends Partial ? OntimeMilestone : never; @@ -49,7 +49,7 @@ type CompleteEntry = * Generates a fully formed RundownEntry of the patch type */ export function generateEvent< - T extends Partial | Partial | Partial | Partial, + T extends Partial | Partial | Partial | Partial, >(rundown: Rundown, eventData: T, afterId: EntryId | null): CompleteEntry { if (isOntimeEvent(eventData)) { return createEvent(eventData, getCueCandidate(rundown.entries, rundown.order, afterId)) as CompleteEntry; @@ -61,9 +61,9 @@ export function generateEvent< return { ...delayDef, duration: eventData.duration ?? 0, id } as CompleteEntry; } - // TODO(v4): allow user to provide a larger patch of the block entry - if (isOntimeBlock(eventData)) { - return createBlock({ id, title: eventData.title ?? '' }) as CompleteEntry; + // TODO(v4): allow user to provide a larger patch of the group entry + if (isOntimeGroup(eventData)) { + return createGroup({ id, title: eventData.title ?? '' }) as CompleteEntry; } if (isOntimeMilestone(eventData)) { @@ -115,35 +115,35 @@ export function createEventPatch(originalEvent: OntimeEvent, patchEvent: Partial }; } -export function createBlockPatch(originalBlock: OntimeBlock, patchBlock: Partial): OntimeBlock { - if (Object.keys(patchBlock).length === 0) { - return originalBlock; +export function createGroupPatch(originalGroup: OntimeGroup, patchGroup: Partial): OntimeGroup { + if (Object.keys(patchGroup).length === 0) { + return originalGroup; } const maybeTargetDuration = () => { - if (typeof patchBlock.targetDuration === 'number') { - return patchBlock.targetDuration; + if (typeof patchGroup.targetDuration === 'number') { + return patchGroup.targetDuration; } - if (patchBlock.targetDuration === null || patchBlock.targetDuration === '') { + if (patchGroup.targetDuration === null || patchGroup.targetDuration === '') { return null; } - return originalBlock.targetDuration; + return originalGroup.targetDuration; }; return { - id: originalBlock.id, - type: SupportedEntry.Block, - title: makeString(patchBlock.title, originalBlock.title), - note: makeString(patchBlock.note, originalBlock.note), - entries: patchBlock.entries ?? originalBlock.entries, + id: originalGroup.id, + type: SupportedEntry.Group, + title: makeString(patchGroup.title, originalGroup.title), + note: makeString(patchGroup.note, originalGroup.note), + entries: patchGroup.entries ?? originalGroup.entries, targetDuration: maybeTargetDuration(), - colour: makeString(patchBlock.colour, originalBlock.colour), - revision: originalBlock.revision, - timeStart: originalBlock.timeStart, - timeEnd: originalBlock.timeEnd, - duration: originalBlock.duration, - isFirstLinked: originalBlock.isFirstLinked, - custom: { ...originalBlock.custom, ...patchBlock.custom }, + colour: makeString(patchGroup.colour, originalGroup.colour), + revision: originalGroup.revision, + timeStart: originalGroup.timeStart, + timeEnd: originalGroup.timeEnd, + duration: originalGroup.duration, + isFirstLinked: originalGroup.isFirstLinked, + custom: { ...originalGroup.custom, ...patchGroup.custom }, }; } @@ -179,10 +179,10 @@ export function applyPatchToEntry(eventFromRundown: OntimeEntry, patch: Partial< return newEvent; } - if (isOntimeBlock(eventFromRundown)) { - const newBlock = createBlockPatch(eventFromRundown as OntimeBlock, patch as Partial); - newBlock.revision++; - return newBlock; + if (isOntimeGroup(eventFromRundown)) { + const newGroup = createGroupPatch(eventFromRundown as OntimeGroup, patch as Partial); + newGroup.revision++; + return newGroup; } if (isOntimeMilestone(eventFromRundown)) { @@ -218,16 +218,16 @@ export const createEvent = (eventArgs: Partial, eventIndex: number }; /** - * Creates a new block from an optional patch + * Creates a new group from an optional patch */ -export function createBlock(patch?: Partial): OntimeBlock { +export function createGroup(patch?: Partial): OntimeGroup { if (!patch) { - return { ...blockDef, id: generateId() }; + return { ...groupDef, id: generateId() }; } return { id: patch.id ?? generateId(), - type: SupportedEntry.Block, + type: SupportedEntry.Group, title: patch.title ?? '', note: patch.note ?? '', entries: patch.entries ?? [], @@ -385,13 +385,13 @@ export function cloneMilestone(entry: OntimeMilestone, newId: EntryId): OntimeMi } /** - * Gathers business logic for how to clone an OntimeBlock + * Gathers business logic for how to clone an OntimeGroup */ -export function cloneBlock(entry: OntimeBlock, newId: EntryId): OntimeBlock { +export function cloneGroup(entry: OntimeGroup, newId: EntryId): OntimeGroup { const newEntry = structuredClone(entry); newEntry.id = newId; - // in blocks, we need to remove the events references + // in groups, we need to remove the events references newEntry.entries = []; newEntry.revision = 0; return newEntry; @@ -405,8 +405,8 @@ export function cloneEntry(entry: OntimeEntry, newId: EntryId): OntimeEntry { return cloneEvent(entry, newId); } else if (isOntimeDelay(entry)) { return cloneDelay(entry, newId); - } else if (isOntimeBlock(entry)) { - return cloneBlock(entry, newId); + } else if (isOntimeGroup(entry)) { + return cloneGroup(entry, newId); } else if (isOntimeMilestone(entry)) { return cloneMilestone(entry, newId); } @@ -452,7 +452,7 @@ export function calculateDayOffset( */ export function getInsertAfterId( rundown: Rundown, - parent: OntimeBlock | null, + parent: OntimeGroup | null, afterId?: EntryId, beforeId?: EntryId, ): EntryId | null { diff --git a/apps/server/src/api-data/rundown/rundown.validation.ts b/apps/server/src/api-data/rundown/rundown.validation.ts index 779ff5605..29563fb8a 100644 --- a/apps/server/src/api-data/rundown/rundown.validation.ts +++ b/apps/server/src/api-data/rundown/rundown.validation.ts @@ -2,7 +2,7 @@ import { body, param } from 'express-validator'; import { requestValidationFunction } from '../validation-utils/validationFunction.js'; export const rundownPostValidator = [ - body('type').isString().isIn(['event', 'delay', 'block', 'milestone']), + body('type').isString().isIn(['event', 'delay', 'group', 'milestone']), body('after').optional().isString(), body('before').optional().isString(), diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index c0a209251..9ab5c4c95 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -187,8 +187,8 @@ export const startServer = async (): Promise<{ message: string; serverPort: numb runtime: state.runtime, eventNow: state.eventNow, eventNext: state.eventNext, - blockNow: null, - blockNext: null, + groupNow: null, + groupNext: null, nextFlag: null, auxtimer1: { duration: timerConfig.auxTimerDefault, diff --git a/apps/server/src/models/demoProject.ts b/apps/server/src/models/demoProject.ts index 86f27d707..c0d5b9da4 100644 --- a/apps/server/src/models/demoProject.ts +++ b/apps/server/src/models/demoProject.ts @@ -40,7 +40,7 @@ export const demoDb: DatabaseModel = { }, '7eaf99': { id: '7eaf99', - type: SupportedEntry.Block, + type: SupportedEntry.Group, title: 'Morning Sessions', note: '', entries: ['9bf60f', 'bf71a2', 'c2697f', 'fa593e', 'a8b0b3'], @@ -160,7 +160,7 @@ export const demoDb: DatabaseModel = { }, f60403: { id: 'f60403', - type: SupportedEntry.Block, + type: SupportedEntry.Group, title: 'Lunch', note: '', entries: ['0aaa7d'], @@ -202,7 +202,7 @@ export const demoDb: DatabaseModel = { }, '6b0edb': { id: '6b0edb', - type: SupportedEntry.Block, + type: SupportedEntry.Group, title: 'Afternoon Sessions', note: '', entries: ['02afca', '75ce86', 'e10ed9', '07df89'], diff --git a/apps/server/src/models/eventsDefinition.ts b/apps/server/src/models/eventsDefinition.ts index b93cf8c94..c254aa813 100644 --- a/apps/server/src/models/eventsDefinition.ts +++ b/apps/server/src/models/eventsDefinition.ts @@ -1,6 +1,6 @@ import { EndAction, - OntimeBlock, + OntimeGroup, OntimeDelay, OntimeEvent, OntimeMilestone, @@ -54,8 +54,8 @@ export const milestone: Omit = { revision: 0, // calculated at runtime }; -export const block: Omit = { - type: SupportedEntry.Block, +export const group: Omit = { + type: SupportedEntry.Group, title: '', note: '', entries: [], diff --git a/apps/server/src/services/RestoreService.ts b/apps/server/src/services/RestoreService.ts index 99d401abb..5338b361e 100644 --- a/apps/server/src/services/RestoreService.ts +++ b/apps/server/src/services/RestoreService.ts @@ -12,7 +12,7 @@ export type RestorePoint = { addedTime: number; pausedAt: MaybeNumber; firstStart: MaybeNumber; - blockStartAt: MaybeNumber; + groupStartAt: MaybeNumber; }; /** @@ -51,7 +51,7 @@ export function isRestorePoint(obj: unknown): obj is RestorePoint { return false; } - if (typeof restorePoint.blockStartAt !== 'number' && restorePoint.blockStartAt !== null) { + if (typeof restorePoint.groupStartAt !== 'number' && restorePoint.groupStartAt !== null) { return false; } diff --git a/apps/server/src/services/__tests__/RestoreService.test.ts b/apps/server/src/services/__tests__/RestoreService.test.ts index cf7e7c911..5857cb9c4 100644 --- a/apps/server/src/services/__tests__/RestoreService.test.ts +++ b/apps/server/src/services/__tests__/RestoreService.test.ts @@ -14,7 +14,7 @@ describe('isRestorePoint()', () => { addedTime: 2, pausedAt: 3, firstStart: 1, - blockStartAt: 10, + groupStartAt: 10, }; expect(isRestorePoint(restorePoint)).toBe(true); @@ -25,7 +25,7 @@ describe('isRestorePoint()', () => { addedTime: 0, pausedAt: null, firstStart: 1, - blockStartAt: null, + groupStartAt: null, }; expect(isRestorePoint(restorePoint)).toBe(true); }); @@ -38,7 +38,7 @@ describe('isRestorePoint()', () => { startedAt: null, addedTime: 0, pausedAt: null, - blockStartAt: 10, + groupStartAt: 10, }; expect(isRestorePoint(restorePoint)).toBe(false); }); @@ -48,7 +48,7 @@ describe('isRestorePoint()', () => { startedAt: null, addedTime: 0, pausedAt: null, - blockStartAt: 10, + groupStartAt: 10, }; expect(isRestorePoint(restorePoint)).toBe(false); }); @@ -59,7 +59,7 @@ describe('isRestorePoint()', () => { startedAt: 'testing', addedTime: 0, pausedAt: null, - blockStartAt: 10, + groupStartAt: 10, }; expect(isRestorePoint(restorePoint)).toBe(false); }); @@ -76,7 +76,7 @@ describe('RestoreService()', () => { addedTime: 5678, pausedAt: 9087, firstStart: 1234, - blockStartAt: 1652, + groupStartAt: 1652, }; const restoreService = new RestoreService('/path/to/restore/file'); @@ -94,7 +94,7 @@ describe('RestoreService()', () => { addedTime: 0, pausedAt: null, firstStart: 1234, - blockStartAt: null, + groupStartAt: null, }; const restoreService = new RestoreService('/path/to/restore/file'); @@ -112,7 +112,7 @@ describe('RestoreService()', () => { addedTime: 1234, pausedAt: 1234, firstStart: 1234, - blockStartAt: 10, + groupStartAt: 10, }; const restoreService = new RestoreService('/path/to/restore/file'); @@ -132,7 +132,7 @@ describe('RestoreService()', () => { addedTime: 1234, pausedAt: 1234, firstStart: 1234, - blockStartAt: null, + groupStartAt: null, }; const restoreService = new RestoreService('/path/to/restore/file'); diff --git a/apps/server/src/services/runtime-service/RuntimeService.ts b/apps/server/src/services/runtime-service/RuntimeService.ts index 8598b388a..529700991 100644 --- a/apps/server/src/services/runtime-service/RuntimeService.ts +++ b/apps/server/src/services/runtime-service/RuntimeService.ts @@ -716,9 +716,9 @@ function broadcastResult(_target: any, _propertyKey: string, descriptor: Propert !deepEqual(RuntimeService.previousState?.runtime, state.runtime); // TODO: the value shows up one tick to late - const shouldBlockUpdate = - !deepEqual(RuntimeService?.previousState.blockNow, state.blockNow) || - RuntimeService?.previousState.blockNext !== state.blockNext; + const shouldGroupUpdate = + !deepEqual(RuntimeService?.previousState.groupNow, state.groupNow) || + RuntimeService?.previousState.groupNext !== state.groupNext; // TODO: the value shows up one tick to late const shouldNextFlagUpdate = !deepEqual(RuntimeService?.previousState?.nextFlag, state.nextFlag); @@ -728,7 +728,7 @@ function broadcastResult(_target: any, _propertyKey: string, descriptor: Propert * so if any of them are updated we also need to send the clock * in case nothing else is updating the clock will be updated at the notification rate */ - const shouldUpdateClock = shouldRuntimeUpdate || shouldBlockUpdate || normalClockUpdate; + const shouldUpdateClock = shouldRuntimeUpdate || shouldGroupUpdate || normalClockUpdate; // Now we set all the updates on the eventstore and update the previous value if (shouldUpdateTimer) { @@ -744,11 +744,11 @@ function broadcastResult(_target: any, _propertyKey: string, descriptor: Propert RuntimeService.previousState.runtime = structuredClone(state.runtime); } - if (shouldBlockUpdate) { - batch.add('blockNow', state.blockNow); - batch.add('blockNext', state.blockNext); - RuntimeService.previousState.blockNow = structuredClone(state.blockNow); - RuntimeService.previousState.blockNext = state.blockNext; + if (shouldGroupUpdate) { + batch.add('groupNow', state.groupNow); + batch.add('groupNext', state.groupNext); + RuntimeService.previousState.groupNow = structuredClone(state.groupNow); + RuntimeService.previousState.groupNext = structuredClone(state.groupNext); } if (shouldNextFlagUpdate) { @@ -808,7 +808,7 @@ function broadcastResult(_target: any, _propertyKey: string, descriptor: Propert addedTime: state.timer.addedTime, pausedAt: state._timer.pausedAt, firstStart: state.runtime.actualStart, - blockStartAt: state.blockNow?.startedAt ?? null, + groupStartAt: state.groupNow?.startedAt ?? null, }) .catch((_e) => { //we don't do anything with the error here diff --git a/apps/server/src/services/sheet-service/sheetUtils.ts b/apps/server/src/services/sheet-service/sheetUtils.ts index d9d27948c..559e21d9d 100644 --- a/apps/server/src/services/sheet-service/sheetUtils.ts +++ b/apps/server/src/services/sheet-service/sheetUtils.ts @@ -1,4 +1,4 @@ -import { isOntimeBlock, isOntimeEvent, OntimeEvent, OntimeEntry, RGBColour } from 'ontime-types'; +import { isOntimeGroup, isOntimeEvent, OntimeEvent, OntimeEntry, RGBColour } from 'ontime-types'; import { cssOrHexToColour, isLightColour, millisToString, mixColours } from 'ontime-utils'; import type { sheets_v4 } from '@googleapis/sheets'; @@ -100,7 +100,7 @@ export function cellRequestFromEvent( } } - const colors = isOntimeEvent(event) || isOntimeBlock(event) ? getAccessibleColour(event.colour) : undefined; + const colors = isOntimeEvent(event) || isOntimeGroup(event) ? getAccessibleColour(event.colour) : undefined; const cellColor: sheets_v4.Schema$CellData = !colors ? {} : { @@ -163,12 +163,12 @@ function getCellData(key: keyof OntimeEvent | 'blank', event: OntimeEntry) { } } - if (isOntimeBlock(event)) { + if (isOntimeGroup(event)) { if (key === 'title') { return { userEnteredValue: { stringValue: event[key] } }; } if (key === 'timerType') { - return { userEnteredValue: { stringValue: 'block' } }; + return { userEnteredValue: { stringValue: 'group' } }; } } diff --git a/apps/server/src/stores/__mocks__/runtimeState.mocks.ts b/apps/server/src/stores/__mocks__/runtimeState.mocks.ts index 338ba6c9e..c15bb43d3 100644 --- a/apps/server/src/stores/__mocks__/runtimeState.mocks.ts +++ b/apps/server/src/stores/__mocks__/runtimeState.mocks.ts @@ -6,8 +6,8 @@ const baseState: RuntimeState = { clock: 0, eventNow: null, eventNext: null, - blockNow: null, - blockNext: null, + groupNow: null, + groupNext: null, nextFlag: null, runtime: { selectedEventIndex: null, @@ -40,7 +40,7 @@ const baseState: RuntimeState = { _rundown: { totalDelay: 0, }, - _block: null, + _group: null, _end: null, _flag: null, }; diff --git a/apps/server/src/stores/__tests__/runtimeState.test.ts b/apps/server/src/stores/__tests__/runtimeState.test.ts index d1cdb36ec..d7d11b9d6 100644 --- a/apps/server/src/stores/__tests__/runtimeState.test.ts +++ b/apps/server/src/stores/__tests__/runtimeState.test.ts @@ -1,6 +1,6 @@ import { PlayableEvent, Playback, TimerPhase } from 'ontime-types'; -import { makeOntimeBlock, makeOntimeEvent, makeRundown } from '../../api-data/rundown/__mocks__/rundown.mocks.js'; +import { makeOntimeGroup, makeOntimeEvent, makeRundown } from '../../api-data/rundown/__mocks__/rundown.mocks.js'; import { initRundown } from '../../api-data/rundown/rundown.service.js'; import { @@ -9,7 +9,7 @@ import { clearState, getState, load, - loadBlockFlagAndEnd, + loadGroupFlagAndEnd, pause, roll, start, @@ -105,7 +105,7 @@ describe('mutation on runtimeState', () => { expect(newState.eventNext?.id).toBe('event2'); expect(newState.timer.playback).toBe(Playback.Armed); expect(newState.clock).not.toBe(666); - expect(newState.blockNow).toBeNull(); + expect(newState.groupNow).toBeNull(); // 2. Start event let success = start(); @@ -185,7 +185,7 @@ describe('mutation on runtimeState', () => { expect(newState.runtime.actualStart).toBeNull(); expect(newState.runtime.plannedStart).toBe(0); expect(newState.runtime.plannedEnd).toBe(1500); - expect(newState.blockNow).toBeNull(); + expect(newState.groupNow).toBeNull(); expect(newState.runtime.offsetAbs).toBe(0); // 2. Start event @@ -218,7 +218,7 @@ describe('mutation on runtimeState', () => { expect(newState.runtime.offsetAbs).toBe(delayBefore); // finish is the difference between the runtime and the schedule expect(newState.runtime.expectedEnd).toBe(entries.event2.timeEnd - newState.runtime.offsetAbs); - expect(newState.blockNow).toBeNull(); + expect(newState.groupNow).toBeNull(); // 4. Add time addTime(10); @@ -371,75 +371,75 @@ describe('roll mode', () => { }); }); -describe('loadBlock', () => { - test('from no-block to a block will clear startedAt', () => { +describe('loadGroup', () => { + test('from no-group to a group will clear startedAt', () => { const rundown = makeRundown({ entries: { 0: makeOntimeEvent({ id: '0', parent: null }), - 1: makeOntimeBlock({ id: '1', entries: ['11'] }), + 1: makeOntimeGroup({ id: '1', entries: ['11'] }), 11: makeOntimeEvent({ id: '11', parent: '1' }), - 2: makeOntimeBlock({ id: '2', entries: [] }), + 2: makeOntimeGroup({ id: '2', entries: [] }), 3: makeOntimeEvent({ id: '3', parent: null }), }, order: ['0', '1', '2', '3'], }); const state = { - blockNow: null, + groupNow: null, eventNow: rundown.entries[11], - } as unknown as RuntimeState; + } as RuntimeState; const metadata = { playableEventOrder: ['0', '11', '3'], flags: ['1'] } as RundownMetadata; - loadBlockFlagAndEnd(rundown, metadata, 2, state); + loadGroupFlagAndEnd(rundown, metadata, 2, state); expect(state).toMatchObject({ - blockNow: { id: rundown.entries[1].id, startedAt: null }, + groupNow: { id: rundown.entries[1].id, startedAt: null }, eventNow: rundown.entries[11], }); }); - test('from block to a different block will clear startedAt', () => { + test('from a group to a different group will clear startedAt', () => { const rundown = makeRundown({ entries: { 0: makeOntimeEvent({ id: '0', parent: null }), - 1: makeOntimeBlock({ id: '1', entries: ['11'] }), + 1: makeOntimeGroup({ id: '1', entries: ['11'] }), 11: makeOntimeEvent({ id: '11', parent: '1' }), - 2: makeOntimeBlock({ id: '2', entries: ['22'] }), + 2: makeOntimeGroup({ id: '2', entries: ['22'] }), 22: makeOntimeEvent({ id: '22', parent: '2' }), }, order: ['0', '1', '2'], }); const state = { - blockNow: { id: rundown.entries[1].id, startedAt: 123 }, + groupNow: { id: rundown.entries[1].id, startedAt: 123 }, eventNow: rundown.entries[22], } as RuntimeState; const metadata = { playableEventOrder: ['0', '11', '22'], flags: ['1'] } as RundownMetadata; - loadBlockFlagAndEnd(rundown, metadata, 1, state); + loadGroupFlagAndEnd(rundown, metadata, 1, state); expect(state).toMatchObject({ - blockNow: { id: rundown.entries[2].id, startedAt: null }, + groupNow: { id: rundown.entries[2].id, startedAt: null }, eventNow: rundown.entries[22], }); }); - test('from block to a no-block will clear startedAt', () => { + test('from group to a no-group will clear startedAt', () => { const rundown = makeRundown({ entries: { 0: makeOntimeEvent({ id: '0', parent: null }), - 1: makeOntimeBlock({ id: '1', entries: ['11'] }), + 1: makeOntimeGroup({ id: '1', entries: ['11'] }), 11: makeOntimeEvent({ id: '11', parent: '1' }), - 2: makeOntimeBlock({ id: '2', entries: ['22'] }), + 2: makeOntimeGroup({ id: '2', entries: ['22'] }), 22: makeOntimeEvent({ id: '22', parent: '2' }), }, order: ['0', '1', '2'], }); const state = { - blockNow: { + groupNow: { id: rundown.entries[1].id, startedAt: 123, }, @@ -448,18 +448,18 @@ describe('loadBlock', () => { const metadata = { playableEventOrder: ['0', '11', '22'], flags: ['1'] } as RundownMetadata; - loadBlockFlagAndEnd(rundown, metadata, 1, state); + loadGroupFlagAndEnd(rundown, metadata, 1, state); expect(state).toMatchObject({ - blockNow: null, + groupNow: null, eventNow: rundown.entries[0], }); }); - test('from block to same block will keep startedAt', () => { + test('from a group to same group will keep startedAt', () => { const rundown = makeRundown({ entries: { - 0: makeOntimeBlock({ id: '0', entries: ['1', '2'] }), + 0: makeOntimeGroup({ id: '0', entries: ['1', '2'] }), 1: makeOntimeEvent({ id: '1', parent: '0' }), 2: makeOntimeEvent({ id: '2', parent: '0' }), }, @@ -467,21 +467,21 @@ describe('loadBlock', () => { }); const state = { - blockNow: { id: rundown.entries[0].id, startedAt: 123 }, + groupNow: { id: rundown.entries[0].id, startedAt: 123 }, eventNow: rundown.entries[2], } as RuntimeState; const metadata = { playableEventOrder: ['1', '2'], flags: ['1'] } as RundownMetadata; - loadBlockFlagAndEnd(rundown, metadata, 0, state); + loadGroupFlagAndEnd(rundown, metadata, 0, state); expect(state).toMatchObject({ - blockNow: { id: rundown.entries[0].id, startedAt: 123 }, + groupNow: { id: rundown.entries[0].id, startedAt: 123 }, eventNow: rundown.entries[2], }); }); - test('from no-block to no-block will keep startedAt', () => { + test('from no-group to no-group will keep startedAt', () => { const rundown = makeRundown({ entries: { 0: makeOntimeEvent({ id: '0', parent: null }), @@ -491,16 +491,16 @@ describe('loadBlock', () => { }); const state = { - blockNow: null, + groupNow: null, eventNow: rundown.entries[0], } as RuntimeState; const metadata = { playableEventOrder: ['0', '1'], flags: ['1'] } as RundownMetadata; - loadBlockFlagAndEnd(rundown, metadata, 0, state); + loadGroupFlagAndEnd(rundown, metadata, 0, state); expect(state).toMatchObject({ - blockNow: null, + groupNow: null, eventNow: rundown.entries[0], }); }); diff --git a/apps/server/src/stores/runtimeState.ts b/apps/server/src/stores/runtimeState.ts index f8771b73b..9e2c14a24 100644 --- a/apps/server/src/stores/runtimeState.ts +++ b/apps/server/src/stores/runtimeState.ts @@ -1,11 +1,11 @@ import { - CurrentBlockState, + CurrentGroupState, EntryMetaData, isOntimeEvent, MaybeNumber, MaybeString, OffsetMode, - OntimeBlock, + OntimeGroup, OntimeEvent, PlayableEvent, Playback, @@ -36,8 +36,8 @@ type ExpectedMetadata = { event: OntimeEvent; accumulatedGap: number; isLinkedTo export type RuntimeState = { clock: number; // realtime clock - blockNow: CurrentBlockState | null; - blockNext: MaybeString; + groupNow: CurrentGroupState | null; + groupNext: MaybeString; nextFlag: EntryMetaData | null; eventNow: PlayableEvent | null; eventNext: PlayableEvent | null; @@ -53,15 +53,15 @@ export type RuntimeState = { _rundown: { totalDelay: number; // this value comes from rundown service }; - _block: ExpectedMetadata; + _group: ExpectedMetadata; _flag: ExpectedMetadata; _end: ExpectedMetadata; }; const runtimeState: RuntimeState = { clock: timeNow(), - blockNow: null, - blockNext: null, + groupNow: null, + groupNext: null, nextFlag: null, eventNow: null, eventNext: null, @@ -76,7 +76,7 @@ const runtimeState: RuntimeState = { _rundown: { totalDelay: 0, }, - _block: null, + _group: null, _flag: null, _end: null, }; @@ -107,7 +107,7 @@ export function clearEventData() { runtimeState.runtime.selectedEventIndex = null; //TODO: is there any ExpectedMetadata stuff we need to clear here - if (runtimeState.blockNow) runtimeState.blockNow.expectedEnd = null; + if (runtimeState.groupNow) runtimeState.groupNow.expectedEnd = null; runtimeState.timer.playback = Playback.Stop; runtimeState.clock = timeNow(); @@ -125,9 +125,9 @@ export function clearState() { runtimeState.eventNow = null; runtimeState.eventNext = null; - runtimeState.blockNow = null; - runtimeState.blockNext = null; - runtimeState._block = null; + runtimeState.groupNow = null; + runtimeState.groupNext = null; + runtimeState._group = null; runtimeState.nextFlag = null; runtimeState._flag = null; @@ -216,7 +216,7 @@ export function load( // load events in memory along with their data loadNow(rundown, metadata, eventIndex); loadNext(rundown, metadata, eventIndex); - loadBlockFlagAndEnd(rundown, metadata, eventIndex); + loadGroupFlagAndEnd(rundown, metadata, eventIndex); // update state runtimeState.timer.playback = Playback.Armed; @@ -235,8 +235,8 @@ export function load( runtimeState.runtime.offsetRel = offsetRel; getExpectedTimes(); } - if (typeof initialData.blockStartAt === 'number' && runtimeState.blockNow) { - runtimeState.blockNow.startedAt = initialData.blockStartAt; + if (typeof initialData.groupStartAt === 'number' && runtimeState.groupNow) { + runtimeState.groupNow.startedAt = initialData.groupStartAt; } } return event.id === runtimeState.eventNow?.id; @@ -357,7 +357,7 @@ export function updateAll(rundown: Rundown, metadata: RundownMetadata) { loadNow(rundown, metadata, eventNowIndex >= 0 ? eventNowIndex : undefined); loadNext(rundown, metadata, eventNowIndex >= 0 ? eventNowIndex : undefined); updateLoaded(runtimeState.eventNow ?? undefined); - loadBlockFlagAndEnd(rundown, metadata, eventNowIndex); + loadGroupFlagAndEnd(rundown, metadata, eventNowIndex); } export function start(state: RuntimeState = runtimeState): boolean { @@ -382,9 +382,9 @@ export function start(state: RuntimeState = runtimeState): boolean { state.timer.startedAt = state.clock; } - // update block start time - if (state.blockNow && state.blockNow.startedAt === null) { - state.blockNow.startedAt = state.clock; + // update group start time + if (state.groupNow && state.groupNow.startedAt === null) { + state.groupNow.startedAt = state.clock; } state.timer.playback = Playback.Play; @@ -609,8 +609,8 @@ export function roll( runtimeState.timer.startedAt = runtimeState.clock; // update runtime - if (runtimeState.blockNow && runtimeState.blockNow.startedAt === null) { - runtimeState.blockNow.startedAt = runtimeState.clock; + if (runtimeState.groupNow && runtimeState.groupNow.startedAt === null) { + runtimeState.groupNow.startedAt = runtimeState.clock; } if (!runtimeState.runtime.actualStart) { runtimeState.runtime.actualStart = runtimeState.clock; @@ -630,7 +630,7 @@ export function roll( throw new Error('No playable events found'); } - // we need to persist the current block state across loads + // we need to persist the current group state across loads clearEventData(); //account for offset but we only keep it if passed to us @@ -642,7 +642,7 @@ export function roll( // load events in memory along with their data loadNow(rundown, metadata, index); loadNext(rundown, metadata, index); - loadBlockFlagAndEnd(rundown, metadata, index); + loadGroupFlagAndEnd(rundown, metadata, index); // update roll state runtimeState.timer.playback = Playback.Roll; @@ -673,8 +673,8 @@ export function roll( // there is something to run, load event // update runtime - if (runtimeState.blockNow && runtimeState.blockNow.startedAt === null) { - runtimeState.blockNow.startedAt = runtimeState.clock; + if (runtimeState.groupNow && runtimeState.groupNow.startedAt === null) { + runtimeState.groupNow.startedAt = runtimeState.clock; } // event will finish on time @@ -702,7 +702,7 @@ export function roll( /** * calculates and sets values directly in state * - runtime.expectedEnd - * - blockNow.expectedEnd + * - groupNow.expectedEnd * - nextFlag.expectedStart */ function getExpectedTimes(state = runtimeState) { @@ -712,11 +712,11 @@ function getExpectedTimes(state = runtimeState) { if (!eventNow) return; state.runtime.expectedEnd = null; - if (state.blockNow) { - state.blockNow.expectedEnd = null; - const { _block } = state; - if (state.blockNow.startedAt !== null && _block !== null) { - const { event, accumulatedGap, isLinkedToLoaded } = _block; + if (state.groupNow) { + state.groupNow.expectedEnd = null; + const { _group } = state; + if (state.groupNow.startedAt !== null && _group !== null) { + const { event, accumulatedGap, isLinkedToLoaded } = _group; const expectedStart = getExpectedStart(event, { currentDay: eventNow.dayOffset, totalGap: accumulatedGap, @@ -726,7 +726,7 @@ function getExpectedTimes(state = runtimeState) { plannedStart, actualStart, }); - state.blockNow.expectedEnd = expectedStart + event.duration; + state.groupNow.expectedEnd = expectedStart + event.duration; } } @@ -765,7 +765,7 @@ function getExpectedTimes(state = runtimeState) { } } -export function loadBlockFlagAndEnd( +export function loadGroupFlagAndEnd( rundown: Rundown, metadata: RundownMetadata, currentIndex: MaybeNumber, @@ -774,14 +774,14 @@ export function loadBlockFlagAndEnd( if (currentIndex === null) return resetMetaData(); if (state.eventNow === null) return resetMetaData(); - const currentBlockId = state.eventNow.parent; + const currentGroupId = state.eventNow.parent; const flagsPresent = metadata.flags.length !== 0; const { playableEventOrder } = metadata; const { entries } = rundown; - const orderInBlock = currentBlockId ? (entries[currentBlockId] as OntimeBlock).entries : null; - const lastEventInGroup = orderInBlock ? getLastEventNormal(rundown.entries, orderInBlock).lastEvent : null; + const orderInGroup = currentGroupId ? (entries[currentGroupId] as OntimeGroup).entries : null; + const lastEventInGroup = orderInGroup ? getLastEventNormal(rundown.entries, orderInGroup).lastEvent : null; // if we don't have a any flags in the rundown then no need to look for it let foundFlag = !flagsPresent; @@ -811,12 +811,12 @@ export function loadBlockFlagAndEnd( if (!foundGroupEnd && entry.id === lastEventInGroup?.id) { foundGroupEnd = true; - state._block = { event: lastEventInGroup, isLinkedToLoaded, accumulatedGap }; + state._group = { event: lastEventInGroup, isLinkedToLoaded, accumulatedGap }; } - if (!foundNextGroup && entry.parent !== currentBlockId) { + if (!foundNextGroup && entry.parent !== currentGroupId) { foundNextGroup = true; - state.blockNext = entry.parent; + state.groupNext = entry.parent; } } } @@ -829,19 +829,19 @@ export function loadBlockFlagAndEnd( if (!foundFlag) state.nextFlag = null; - if (currentBlockId === null) { - state.blockNow = null; - } else if ((state.blockNow != null && state.blockNow.id != currentBlockId) || state.blockNow == null) { - // we went into a new block - and it is different from the one we might have come from + if (currentGroupId === null) { + state.groupNow = null; + } else if ((state.groupNow != null && state.groupNow.id != currentGroupId) || state.groupNow == null) { + // we went into a new group - and it is different from the one we might have come from // the id is set here, the start time is set when starting events - state.blockNow = { id: currentBlockId, startedAt: null, expectedEnd: null }; + state.groupNow = { id: currentGroupId, startedAt: null, expectedEnd: null }; } } const resetMetaData = (state = runtimeState) => { - state.blockNow = null; - state.blockNext = null; - state._block = null; + state.groupNow = null; + state.groupNext = null; + state._group = null; state.nextFlag = null; state._flag = null; state._end = null; diff --git a/apps/server/test-db/db.json b/apps/server/test-db/db.json index dce656d71..4b7d9e084 100644 --- a/apps/server/test-db/db.json +++ b/apps/server/test-db/db.json @@ -163,7 +163,7 @@ } }, "01e85": { - "type": "block", + "type": "group", "id": "01e85", "title": "Lunch break", "note": "", @@ -318,7 +318,7 @@ } }, "cb90b": { - "type": "block", + "type": "group", "id": "cb90b", "title": "Afternoon break", "note": "", diff --git a/e2e/tests/000-upload-showfile.spec.ts b/e2e/tests/000-upload-showfile.spec.ts index 13fa4c1fb..ea3ad4b91 100644 --- a/e2e/tests/000-upload-showfile.spec.ts +++ b/e2e/tests/000-upload-showfile.spec.ts @@ -34,13 +34,13 @@ test('project file upload', async ({ page }) => { await page.getByRole('button', { name: 'close' }).click(); // asset test events - const firstTitle = page.getByTestId('entry-1').getByTestId('block__title'); + const firstTitle = page.getByTestId('entry-1').getByTestId('entry__title'); await expect(firstTitle).toHaveValue('Albania'); - const secondTitle = page.getByTestId('entry-2').getByTestId('block__title'); + const secondTitle = page.getByTestId('entry-2').getByTestId('entry__title'); await expect(secondTitle).toHaveValue('Latvia'); - const thirdTitle = page.getByTestId('entry-3').getByTestId('block__title'); + const thirdTitle = page.getByTestId('entry-3').getByTestId('entry__title'); await expect(thirdTitle).toHaveValue('Lithuania'); }); diff --git a/e2e/tests/features/202-cuesheet.spec.ts b/e2e/tests/features/202-cuesheet.spec.ts index 36f4984a5..3f203335c 100644 --- a/e2e/tests/features/202-cuesheet.spec.ts +++ b/e2e/tests/features/202-cuesheet.spec.ts @@ -10,5 +10,5 @@ test('cuesheet displays events', async ({ page }) => { // there should be 16 rows in the table (same as the amount of events in the rundown) await expect(page.getByTestId('cuesheet-event')).toHaveCount(14); - await expect(page.getByTestId('cuesheet-block')).toHaveCount(2); + await expect(page.getByTestId('cuesheet-group')).toHaveCount(2); }); diff --git a/e2e/tests/features/203-delay-block.spec.ts b/e2e/tests/features/203-delay-block.spec.ts index 75f476afe..04baa4d8e 100644 --- a/e2e/tests/features/203-delay-block.spec.ts +++ b/e2e/tests/features/203-delay-block.spec.ts @@ -1,6 +1,6 @@ import { expect, test } from '@playwright/test'; -test('delay blocks add time to events', async ({ page }) => { +test('delays add time to events', async ({ page }) => { await page.goto('http://localhost:4001/editor'); // delete all events and add a new one @@ -17,7 +17,7 @@ test('delay blocks add time to events', async ({ page }) => { await page.getByTestId('rundown').getByPlaceholder('Duration').fill('20m'); await page.getByTestId('rundown').getByPlaceholder('Duration').press('Enter'); - // add delay block + // add delay await page.getByRole('button', { name: 'Delay' }).nth(0).click(); // fill positive delay @@ -64,10 +64,10 @@ test('delays are show correctly', async ({ page }) => { await page.getByTestId('rundown').getByTestId('time-input-duration').click(); await page.getByTestId('rundown').getByTestId('time-input-duration').fill('10'); await page.getByTestId('rundown').getByTestId('time-input-duration').press('Enter'); - await page.getByTestId('block__title').click(); - await page.getByTestId('block__title').fill('test'); - await page.getByTestId('block__title').press('Enter'); - await expect(page.getByTestId('entry-1').locator('#block-status')).toHaveAttribute('data-timerType', 'count-down'); + await page.getByTestId('entry__title').click(); + await page.getByTestId('entry__title').fill('test'); + await page.getByTestId('entry__title').press('Enter'); + await expect(page.getByTestId('entry-1').locator('#entry-status')).toHaveAttribute('data-timerType', 'count-down'); // add a delay await page.getByRole('button', { name: 'Delay' }).nth(0).click(); diff --git a/e2e/tests/features/204-editor-crud.spec.ts b/e2e/tests/features/204-editor-crud.spec.ts index 12f20e70d..1bc8800cb 100644 --- a/e2e/tests/features/204-editor-crud.spec.ts +++ b/e2e/tests/features/204-editor-crud.spec.ts @@ -8,13 +8,13 @@ test('CRUD operations on the rundown', async ({ page }) => { await page.getByRole('button', { name: 'Delete all' }).click(); await expect(page.getByTestId('rundown-event')).toHaveCount(0); await expect(page.getByTestId('rundown-delay')).toHaveCount(0); - await expect(page.getByTestId('rundown-block')).toHaveCount(0); + await expect(page.getByTestId('rundown-group')).toHaveCount(0); // create event from the rundown empty button await page.getByRole('button', { name: 'Create Event' }).click(); await expect(page.getByTestId('rundown-event')).toHaveCount(1); await expect(page.getByTestId('rundown-delay')).toHaveCount(0); - await expect(page.getByTestId('rundown-block')).toHaveCount(0); + await expect(page.getByTestId('rundown-group')).toHaveCount(0); // create groups using the quick add buttons await page.getByTestId('rundown').getByRole('button', { name: 'Group' }).nth(1).click(); @@ -22,7 +22,7 @@ test('CRUD operations on the rundown', async ({ page }) => { await page.getByRole('button', { name: 'Event', exact: true }).nth(1).click(); await expect(page.getByTestId('rundown-event')).toHaveCount(2); await expect(page.getByTestId('rundown-delay')).toHaveCount(1); - await expect(page.getByTestId('rundown-block')).toHaveCount(1); + await expect(page.getByTestId('rundown-group')).toHaveCount(1); // test quick add options - star2+5-t is last end await page.getByTestId('entry-2').getByTestId('time-input-duration').fill('20m'); @@ -30,13 +30,13 @@ test('CRUD operations on the rundown', async ({ page }) => { expect(await page.getByTestId('entry-3').getByTestId('time-input-timeStart').inputValue()).toContain('00:30:00'); await expect(page.getByTestId('rundown-event')).toHaveCount(3); await expect(page.getByTestId('rundown-delay')).toHaveCount(1); - await expect(page.getByTestId('rundown-block')).toHaveCount(1); + await expect(page.getByTestId('rundown-group')).toHaveCount(1); // test quick add options await page.getByRole('button', { name: 'Event', exact: true }).nth(1).click(); await expect(page.getByTestId('rundown-event')).toHaveCount(4); await expect(page.getByTestId('rundown-delay')).toHaveCount(1); - await expect(page.getByTestId('rundown-block')).toHaveCount(1); + await expect(page.getByTestId('rundown-group')).toHaveCount(1); - await expect(page.getByTestId('entry-4').locator('#block-status')).toHaveAttribute('data-timerType', 'count-down'); + await expect(page.getByTestId('entry-4').locator('#entry-status')).toHaveAttribute('data-timerType', 'count-down'); }); diff --git a/e2e/tests/features/205-operator.spec.ts b/e2e/tests/features/205-operator.spec.ts index ed636a119..14efce19e 100644 --- a/e2e/tests/features/205-operator.spec.ts +++ b/e2e/tests/features/205-operator.spec.ts @@ -30,23 +30,23 @@ test('smoke test operator', async ({ page }) => { await page.getByTestId('entry-1').click(); await page.getByRole('button', { name: 'Event', exact: true }).nth(1).click(); - await page.getByTestId('entry-1').getByTestId('block__title').click(); - await page.getByTestId('entry-1').getByTestId('block__title').fill('title 1'); - await page.getByTestId('entry-1').getByTestId('block__title').press('Enter'); + await page.getByTestId('entry-1').getByTestId('entry__title').click(); + await page.getByTestId('entry-1').getByTestId('entry__title').fill('title 1'); + await page.getByTestId('entry-1').getByTestId('entry__title').press('Enter'); await page.getByTestId('entry-2').click(); await page.getByRole('button', { name: 'Event', exact: true }).nth(1).click(); - await page.getByTestId('entry-2').getByTestId('block__title').click(); - await page.getByTestId('entry-2').getByTestId('block__title').fill('title 2'); - await page.getByTestId('entry-2').getByTestId('block__title').press('Enter'); + await page.getByTestId('entry-2').getByTestId('entry__title').click(); + await page.getByTestId('entry-2').getByTestId('entry__title').fill('title 2'); + await page.getByTestId('entry-2').getByTestId('entry__title').press('Enter'); await page.getByTestId('entry-3').click(); await page.getByRole('button', { name: 'Event', exact: true }).nth(1).click(); - await page.getByTestId('entry-3').getByTestId('block__title').click(); - await page.getByTestId('entry-3').getByTestId('block__title').fill('title 3'); - await page.getByTestId('entry-3').getByTestId('block__title').press('Enter'); + await page.getByTestId('entry-3').getByTestId('entry__title').click(); + await page.getByTestId('entry-3').getByTestId('entry__title').fill('title 3'); + await page.getByTestId('entry-3').getByTestId('entry__title').press('Enter'); // start an event await page.getByTestId('panel-timer-control').getByRole('button', { name: 'Start' }).click(); diff --git a/e2e/tests/features/206-url-preset.spec.ts b/e2e/tests/features/206-url-preset.spec.ts index df2c17e2b..8b6e5866b 100644 --- a/e2e/tests/features/206-url-preset.spec.ts +++ b/e2e/tests/features/206-url-preset.spec.ts @@ -123,9 +123,9 @@ test.describe('Sharing from cuesheet', () => { await page.getByRole('button', { name: 'Clear all' }).click(); await page.getByRole('button', { name: 'Delete all' }).click(); await page.getByRole('button', { name: 'Create Event' }).click(); - await page.getByTestId('entry-1').getByTestId('block__title').click(); - await page.getByTestId('entry-1').getByTestId('block__title').fill('title 1'); - await page.getByTestId('entry-1').getByTestId('block__title').press('Enter'); + await page.getByTestId('entry-1').getByTestId('entry__title').click(); + await page.getByTestId('entry-1').getByTestId('entry__title').fill('title 1'); + await page.getByTestId('entry-1').getByTestId('entry__title').press('Enter'); await page.close(); }); diff --git a/e2e/tests/features/209-rundown-shortcuts.spec.ts b/e2e/tests/features/209-rundown-shortcuts.spec.ts index 195e9bf80..027aeccdb 100644 --- a/e2e/tests/features/209-rundown-shortcuts.spec.ts +++ b/e2e/tests/features/209-rundown-shortcuts.spec.ts @@ -14,9 +14,9 @@ test('Copy-paste', async ({ page }) => { await page.getByLabel('Cue', { exact: true }).fill('4'); await page.getByLabel('Cue', { exact: true }).press('Enter'); await page.getByTestId('entry-1').click(); - await page.getByTestId('block__title').click(); - await page.getByTestId('block__title').fill('test'); - await page.getByTestId('block__title').press('Enter'); + await page.getByTestId('entry__title').click(); + await page.getByTestId('entry__title').fill('test'); + await page.getByTestId('entry__title').press('Enter'); // copy paste below await page.getByTestId('rundown-event').locator('div').filter({ hasText: '4' }).click(); @@ -25,7 +25,7 @@ test('Copy-paste', async ({ page }) => { // assert await expect(page.getByTestId('entry-2')).toBeVisible(); - await expect(page.getByTestId('entry-2').getByTestId('block__title')).toHaveValue('test'); + await expect(page.getByTestId('entry-2').getByTestId('entry__title')).toHaveValue('test'); await expect(page.getByTestId('entry-2').getByTestId('rundown-event')).toContainText('5'); // copy paste above @@ -35,7 +35,7 @@ test('Copy-paste', async ({ page }) => { // assert await expect(page.getByTestId('entry-2')).toBeVisible(); - await expect(page.getByTestId('entry-2').getByTestId('block__title')).toHaveValue('test'); + await expect(page.getByTestId('entry-2').getByTestId('entry__title')).toHaveValue('test'); await expect(page.getByTestId('entry-2').getByTestId('rundown-event')).toContainText('4.1'); }); @@ -67,37 +67,37 @@ test('Move', async ({ page }) => { await expect(page.getByTestId('entry-1').getByTestId('rundown-event')).toContainText('3'); }); -test('Add block', async ({ page }) => { +test('Add group', async ({ page }) => { await page.goto('http://localhost:4001/rundown'); // clear rundown await page.getByRole('button', { name: 'Clear all' }).click(); await page.getByRole('button', { name: 'Delete all' }).click(); await expect(page.getByTestId('rundown-event')).toHaveCount(0); - await expect(page.getByTestId('rundown-block')).toHaveCount(0); + await expect(page.getByTestId('rundown-group')).toHaveCount(0); // create events await page.getByRole('button', { name: 'Create Event' }).click(); await expect(page.getByTestId('rundown-event')).toHaveCount(1); - await expect(page.getByTestId('rundown-block')).toHaveCount(0); + await expect(page.getByTestId('rundown-group')).toHaveCount(0); await page.getByPlaceholder(/event title/i).fill('test'); await page.getByTestId('entry-1').click(); - // add block below + // add group below await page.getByTestId('rundown-event').locator('div').filter({ hasText: '1' }).press('Alt+G'); await expect(page.getByTestId('rundown-event')).toHaveCount(1); - await expect(page.getByTestId('rundown-block')).toHaveCount(1); - await page.getByTestId('rundown-block').getByTestId('block__title').fill('block below'); + await expect(page.getByTestId('rundown-group')).toHaveCount(1); + await page.getByTestId('rundown-group').getByTestId('entry__title').fill('group below'); - // add block above + // add group above await page.getByTestId('rundown-event').locator('div').filter({ hasText: '1' }).press('Alt+Shift+G'); await expect(page.getByTestId('rundown-event')).toHaveCount(1); - await expect(page.getByTestId('rundown-block')).toHaveCount(2); - await page.getByTestId('block__title').first().fill('block above'); + await expect(page.getByTestId('rundown-group')).toHaveCount(2); + await page.getByTestId('entry__title').first().fill('group above'); - await expect(page.getByTestId(/block__title/i).first()).toHaveValue('block above'); - await expect(page.getByTestId(/block__title/i).nth(2)).toHaveValue('block below'); - await expect(page.getByTestId('entry-1').getByTestId(/block__title/)).toHaveValue('test'); + await expect(page.getByTestId(/entry__title/i).first()).toHaveValue('group above'); + await expect(page.getByTestId(/entry__title/i).nth(2)).toHaveValue('group below'); + await expect(page.getByTestId('entry-1').getByTestId(/entry__title/)).toHaveValue('test'); }); test('Add delay', async ({ page }) => { @@ -114,7 +114,7 @@ test('Add delay', async ({ page }) => { await expect(page.getByTestId('rundown-event')).toHaveCount(1); await expect(page.getByTestId('rundown-delay')).toHaveCount(0); await page.getByTestId('entry-1').click(); - await page.getByTestId('block__title').press('Escape'); + await page.getByTestId('entry__title').press('Escape'); //add delay below await page.getByTestId('rundown-event').locator('div').filter({ hasText: '1' }).press('Alt+D'); @@ -141,7 +141,7 @@ test('Add event', async ({ page }) => { await page.getByRole('button', { name: 'Create Event' }).click(); await expect(page.getByTestId('rundown-event')).toHaveCount(1); await page.getByTestId('entry-1').click(); - await page.getByTestId('block__title').press('Escape'); + await page.getByTestId('entry__title').press('Escape'); //add event below await page.getByTestId('rundown-event').locator('div').filter({ hasText: '1' }).press('Alt+E'); diff --git a/e2e/tests/features/301-spreadsheet-import.spec.ts b/e2e/tests/features/301-spreadsheet-import.spec.ts index 5a99b79c0..6bb59e868 100644 --- a/e2e/tests/features/301-spreadsheet-import.spec.ts +++ b/e2e/tests/features/301-spreadsheet-import.spec.ts @@ -29,12 +29,12 @@ test('sheet file upload', async ({ page }) => { await page.getByRole('button', { name: 'Close settings' }).click(); // asset test events - const firstTitle = page.getByTestId('entry-1').getByTestId('block__title'); + const firstTitle = page.getByTestId('entry-1').getByTestId('entry__title'); await expect(firstTitle).toHaveValue('Attempt light check'); - const secondTitle = page.getByTestId('entry-2').getByTestId('block__title'); + const secondTitle = page.getByTestId('entry-2').getByTestId('entry__title'); await expect(secondTitle).toHaveValue('Preset'); - const thirdTitle = page.getByTestId('entry-3').getByTestId('block__title'); + const thirdTitle = page.getByTestId('entry-3').getByTestId('entry__title'); await expect(thirdTitle).toHaveValue('Albania'); }); diff --git a/e2e/tests/fixtures/e2e-test-db.json b/e2e/tests/fixtures/e2e-test-db.json index dcc71cde9..04ff2d118 100644 --- a/e2e/tests/fixtures/e2e-test-db.json +++ b/e2e/tests/fixtures/e2e-test-db.json @@ -181,7 +181,7 @@ } }, "01e85": { - "type": "block", + "type": "group", "id": "01e85", "title": "Lunch break", "note": "", @@ -336,7 +336,7 @@ } }, "cb90b": { - "type": "block", + "type": "group", "id": "cb90b", "title": "Afternoon break", "note": "", diff --git a/packages/types/src/definitions/core/OntimeEntry.ts b/packages/types/src/definitions/core/OntimeEntry.ts index 420f6f001..9e811b222 100644 --- a/packages/types/src/definitions/core/OntimeEntry.ts +++ b/packages/types/src/definitions/core/OntimeEntry.ts @@ -5,7 +5,7 @@ export type EntryId = string; export enum SupportedEntry { Event = 'event', Delay = 'delay', - Block = 'block', + Group = 'group', Milestone = 'milestone', } @@ -32,8 +32,8 @@ export type OntimeMilestone = OntimeBaseEvent & { revision: number; }; -export type OntimeBlock = OntimeBaseEvent & { - type: SupportedEntry.Block; +export type OntimeGroup = OntimeBaseEvent & { + type: SupportedEntry.Group; title: string; note: string; entries: EntryId[]; @@ -78,7 +78,7 @@ export type OntimeEvent = OntimeBaseEvent & { export type PlayableEvent = OntimeEvent & { skip: false }; export type TimeField = 'timeStart' | 'timeEnd' | 'duration'; -export type OntimeEntry = OntimeDelay | OntimeBlock | OntimeEvent | OntimeMilestone; +export type OntimeEntry = OntimeDelay | OntimeGroup | OntimeEvent | OntimeMilestone; // we need to create a manual union type since keys cannot be used in type unions -export type OntimeEntryCommonKeys = keyof OntimeEvent | keyof OntimeDelay | keyof OntimeBlock | keyof OntimeMilestone; +export type OntimeEntryCommonKeys = keyof OntimeEvent | keyof OntimeDelay | keyof OntimeGroup | keyof OntimeMilestone; diff --git a/packages/types/src/definitions/runtime/CurrentBlockState.type.ts b/packages/types/src/definitions/runtime/CurrentGroupState.type.ts similarity index 92% rename from packages/types/src/definitions/runtime/CurrentBlockState.type.ts rename to packages/types/src/definitions/runtime/CurrentGroupState.type.ts index fca199d76..9db2e943e 100644 --- a/packages/types/src/definitions/runtime/CurrentBlockState.type.ts +++ b/packages/types/src/definitions/runtime/CurrentGroupState.type.ts @@ -1,7 +1,7 @@ import type { MaybeNumber } from '../../utils/utils.type.js'; import type { EntryId } from '../core/OntimeEntry.js'; -export type CurrentBlockState = { +export type CurrentGroupState = { id: EntryId; startedAt: MaybeNumber; expectedEnd: MaybeNumber; diff --git a/packages/types/src/definitions/runtime/RuntimeStore.ts b/packages/types/src/definitions/runtime/RuntimeStore.ts index 6cc197a44..1167f62c7 100644 --- a/packages/types/src/definitions/runtime/RuntimeStore.ts +++ b/packages/types/src/definitions/runtime/RuntimeStore.ts @@ -38,8 +38,8 @@ export const runtimeStorePlaceholder: Readonly = { expectedEnd: null, // changes with runtime, based on offset, overflows over dayInMs offsetMode: OffsetMode.Absolute, }, - blockNow: null, - blockNext: null, + groupNow: null, + groupNext: null, nextFlag: null, eventNow: null, eventNext: null, diff --git a/packages/types/src/definitions/runtime/RuntimeStore.type.ts b/packages/types/src/definitions/runtime/RuntimeStore.type.ts index 51411d4d2..00ba4cd48 100644 --- a/packages/types/src/definitions/runtime/RuntimeStore.type.ts +++ b/packages/types/src/definitions/runtime/RuntimeStore.type.ts @@ -1,7 +1,7 @@ import type { MaybeString } from '../../utils/utils.type.js'; import type { OntimeEvent } from '../core/OntimeEntry.js'; import type { SimpleTimerState } from './AuxTimer.type.js'; -import type { CurrentBlockState, EntryMetaData } from './CurrentBlockState.type.js'; +import type { CurrentGroupState, EntryMetaData } from './CurrentGroupState.type.js'; import type { MessageState } from './MessageControl.type.js'; import type { Runtime } from './Runtime.type.js'; import type { TimerState } from './TimerState.type.js'; @@ -19,8 +19,8 @@ export type RuntimeStore = { eventNow: OntimeEvent | null; eventNext: OntimeEvent | null; - blockNow: CurrentBlockState | null; - blockNext: MaybeString; + groupNow: CurrentGroupState | null; + groupNext: MaybeString; nextFlag: EntryMetaData | null; // extra timers diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index 83a45038c..a9c149ddf 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -7,7 +7,7 @@ export { type EntryId, type OntimeBaseEvent, type OntimeDelay, - type OntimeBlock, + type OntimeGroup, type OntimeEntryCommonKeys, type OntimeEntry, type OntimeMilestone, @@ -101,7 +101,7 @@ export { OffsetMode } from './definitions/runtime/Runtime.type.js'; export type { RuntimeStore } from './definitions/runtime/RuntimeStore.type.js'; export { runtimeStorePlaceholder } from './definitions/runtime/RuntimeStore.js'; export { type TimerState, TimerPhase } from './definitions/runtime/TimerState.type.js'; -export type { CurrentBlockState, UpcomingEntry, EntryMetaData } from './definitions/runtime/CurrentBlockState.type.js'; +export type { CurrentGroupState, UpcomingEntry, EntryMetaData } from './definitions/runtime/CurrentGroupState.type.js'; // ---> Extra Timer export { type SimpleTimerState, SimplePlayback, SimpleDirection } from './definitions/runtime/AuxTimer.type.js'; @@ -111,7 +111,7 @@ export type { Client, ClientList, ClientType } from './definitions/Clients.type. // TYPE UTILITIES export { - isOntimeBlock, + isOntimeGroup, isOntimeDelay, isOntimeEvent, isOntimeMilestone, diff --git a/packages/types/src/utils/guards.ts b/packages/types/src/utils/guards.ts index 799adeaaf..f419c3fc5 100644 --- a/packages/types/src/utils/guards.ts +++ b/packages/types/src/utils/guards.ts @@ -1,9 +1,9 @@ import type { AutomationOutput, HTTPOutput, OntimeAction, OSCOutput } from '../definitions/core/Automation.type.js'; import type { - OntimeBlock, OntimeDelay, OntimeEntry, OntimeEvent, + OntimeGroup, OntimeMilestone, PlayableEvent, } from '../definitions/core/OntimeEntry.js'; @@ -24,8 +24,8 @@ export function isOntimeDelay(event: MaybeEvent): event is OntimeDelay { return event?.type === SupportedEntry.Delay; } -export function isOntimeBlock(event: MaybeEvent): event is OntimeBlock { - return event?.type === SupportedEntry.Block; +export function isOntimeGroup(event: MaybeEvent): event is OntimeGroup { + return event?.type === SupportedEntry.Group; } export function isOntimeMilestone(event: MaybeEvent): event is OntimeMilestone { diff --git a/packages/utils/index.ts b/packages/utils/index.ts index ae89b44a0..c2fdac5c8 100644 --- a/packages/utils/index.ts +++ b/packages/utils/index.ts @@ -16,7 +16,7 @@ export { getLastEventNormal, getLastNormal, getNext, - getNextBlockNormal, + getNextGroupNormal, getNextEvent, getNextEventNormal, getNextNormal, @@ -24,8 +24,8 @@ export { getPreviousEvent, getPreviousEventNormal, getPreviousNormal, - getPreviousBlock, - getPreviousBlockNormal, + getPreviousGroup, + getPreviousGroupNormal, swapEventData, } from './src/rundown-utils/rundownUtils.js'; export { getFirstRundown } from './src/rundown/rundown.utils.js'; diff --git a/packages/utils/src/rundown-utils/rundownUtils.test.ts b/packages/utils/src/rundown-utils/rundownUtils.test.ts index 280ba0881..49665550b 100644 --- a/packages/utils/src/rundown-utils/rundownUtils.test.ts +++ b/packages/utils/src/rundown-utils/rundownUtils.test.ts @@ -1,4 +1,4 @@ -import type { OntimeBlock, OntimeDelay, OntimeEntry, OntimeEvent } from 'ontime-types'; +import type { OntimeDelay, OntimeEntry, OntimeEvent, OntimeGroup } from 'ontime-types'; import { SupportedEntry } from 'ontime-types'; import { @@ -7,8 +7,8 @@ import { getNext, getNextEvent, getPrevious, - getPreviousBlock, getPreviousEvent, + getPreviousGroup, swapEventData, } from './rundownUtils'; @@ -33,7 +33,7 @@ describe('getNext()', () => { entries: { '1': { id: '1', type: SupportedEntry.Event } as OntimeEvent, '2': { id: '2', type: SupportedEntry.Delay } as OntimeDelay, - '3': { id: '3', type: SupportedEntry.Block } as OntimeBlock, + '3': { id: '3', type: SupportedEntry.Group } as OntimeGroup, '4': { id: '4', type: SupportedEntry.Event } as OntimeEvent, }, order: ['1', '2', '3', '4'], @@ -76,7 +76,7 @@ describe('getNextEvent()', () => { const testRundown = [ { id: '1', type: SupportedEntry.Event } as OntimeEvent, { id: '2', type: SupportedEntry.Delay } as OntimeDelay, - { id: '3', type: SupportedEntry.Block } as OntimeBlock, + { id: '3', type: SupportedEntry.Group } as OntimeGroup, { id: '4', type: SupportedEntry.Event } as OntimeEvent, ]; @@ -89,7 +89,7 @@ describe('getNextEvent()', () => { const testRundown = [ { id: '1', type: SupportedEntry.Event } as OntimeEvent, { id: '2', type: SupportedEntry.Delay } as OntimeDelay, - { id: '3', type: SupportedEntry.Block } as OntimeBlock, + { id: '3', type: SupportedEntry.Group } as OntimeGroup, ]; const { nextEvent, nextIndex } = getNextEvent(testRundown, '1'); @@ -119,7 +119,7 @@ describe('getPrevious()', () => { entries: { '1': { id: '1', type: SupportedEntry.Event } as OntimeEvent, '2': { id: '2', type: SupportedEntry.Delay } as OntimeDelay, - '3': { id: '3', type: SupportedEntry.Block } as OntimeBlock, + '3': { id: '3', type: SupportedEntry.Group } as OntimeGroup, '4': { id: '4', type: SupportedEntry.Event } as OntimeEvent, }, order: ['1', '2', '3', '4'], @@ -166,7 +166,7 @@ describe('getPreviousEvent()', () => { entries: { '1': { id: '1', type: SupportedEntry.Event } as OntimeEvent, '2': { id: '2', type: SupportedEntry.Delay } as OntimeDelay, - '3': { id: '3', type: SupportedEntry.Block } as OntimeBlock, + '3': { id: '3', type: SupportedEntry.Group } as OntimeGroup, '4': { id: '4', type: SupportedEntry.Event } as OntimeEvent, }, order: ['1', '2', '3', '4'], @@ -181,7 +181,7 @@ describe('getPreviousEvent()', () => { const testRundown = { entries: { '2': { id: '2', type: SupportedEntry.Delay } as OntimeDelay, - '3': { id: '3', type: SupportedEntry.Block } as OntimeBlock, + '3': { id: '3', type: SupportedEntry.Group } as OntimeGroup, '4': { id: '4', type: SupportedEntry.Event } as OntimeEvent, }, order: ['2', '3', '4'], @@ -247,7 +247,7 @@ describe('getLastEvent', () => { { id: '1', type: SupportedEntry.Event } as OntimeEvent, { id: '2', type: SupportedEntry.Delay } as OntimeDelay, { id: '3', type: SupportedEntry.Event } as OntimeEvent, - { id: '4', type: SupportedEntry.Block } as OntimeBlock, + { id: '4', type: SupportedEntry.Group } as OntimeGroup, ]; const { lastEvent } = getLastEvent(testRundown); @@ -263,7 +263,7 @@ describe('getLastEvent', () => { describe('getLastNormal', () => { it('returns the last entry', () => { const entries = { - 4: { id: '4', type: SupportedEntry.Block } as OntimeBlock, + 4: { id: '4', type: SupportedEntry.Group } as OntimeGroup, 1: { id: '1', type: SupportedEntry.Event } as OntimeEvent, 3: { id: '3', type: SupportedEntry.Event } as OntimeEvent, 2: { id: '2', type: SupportedEntry.Delay } as OntimeDelay, @@ -300,16 +300,16 @@ describe('getLastEvent', () => { }); }); - describe('getPreviousBlock()', () => { + describe('getPreviousGroup()', () => { const testRundown = { entries: { a: { id: 'a', type: SupportedEntry.Event } as OntimeEvent, b: { id: 'b', type: SupportedEntry.Event } as OntimeEvent, c: { id: 'c', type: SupportedEntry.Event } as OntimeEvent, d: { id: 'd', type: SupportedEntry.Delay } as OntimeDelay, - e: { id: 'e', type: SupportedEntry.Block } as OntimeBlock, + e: { id: 'e', type: SupportedEntry.Group } as OntimeGroup, f: { id: 'f', type: SupportedEntry.Event } as OntimeEvent, - g: { id: 'g', type: SupportedEntry.Block } as OntimeBlock, + g: { id: 'g', type: SupportedEntry.Group } as OntimeGroup, h: { id: 'h', type: SupportedEntry.Event } as OntimeEvent, }, order: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'], @@ -318,37 +318,37 @@ describe('getLastEvent', () => { test.each([ ['h', 'g'], ['f', 'e'], - ])('returns the relevant block', (id, expected) => { - const block = getPreviousBlock(testRundown, id); - expect(block?.id).toBe(expected); + ])('returns the relevant group', (id, expected) => { + const group = getPreviousGroup(testRundown, id); + expect(group?.id).toBe(expected); }); - it('returns null if there is no parent block relevant block', () => { - const block = getPreviousBlock(testRundown, 'a'); - expect(block).toBe(null); + it('returns null if there is no parent group relevant group', () => { + const group = getPreviousGroup(testRundown, 'a'); + expect(group).toBe(null); }); it('also works on index 0', () => { testRundown.order.unshift('0'); // @ts-expect-error -- we are adding an event to the rundown - testRundown.entries['0'] = { id: '0', type: SupportedEntry.Block } as OntimeBlock; - const block = getPreviousBlock(testRundown, 'a'); - expect(block?.id).toBe('0'); + testRundown.entries['0'] = { id: '0', type: SupportedEntry.Group } as OntimeGroup; + const group = getPreviousGroup(testRundown, 'a'); + expect(group?.id).toBe('0'); }); - it('returns the parent block if nested event', () => { + it('returns the parent group if nested event', () => { const testRundown = { entries: { 1: { id: '1', type: SupportedEntry.Event } as OntimeEvent, - block: { id: 'block', type: SupportedEntry.Block, entries: ['21', '22', '23'] } as OntimeBlock, - 21: { id: '21', type: SupportedEntry.Event, parent: 'block' } as OntimeEvent, - 22: { id: '22', type: SupportedEntry.Event, parent: 'block' } as OntimeEvent, - 23: { id: '23', type: SupportedEntry.Event, parent: 'block' } as OntimeEvent, + group: { id: 'group', type: SupportedEntry.Group, entries: ['21', '22', '23'] } as OntimeGroup, + 21: { id: '21', type: SupportedEntry.Event, parent: 'group' } as OntimeEvent, + 22: { id: '22', type: SupportedEntry.Event, parent: 'group' } as OntimeEvent, + 23: { id: '23', type: SupportedEntry.Event, parent: 'group' } as OntimeEvent, }, - order: ['1', 'block'], + order: ['1', 'group'], }; - const block = getPreviousBlock(testRundown, '21'); - expect(block?.id).toBe('block'); + const group = getPreviousGroup(testRundown, '21'); + expect(group?.id).toBe('group'); }); }); }); diff --git a/packages/utils/src/rundown-utils/rundownUtils.ts b/packages/utils/src/rundown-utils/rundownUtils.ts index 571ce793c..e21cade37 100644 --- a/packages/utils/src/rundown-utils/rundownUtils.ts +++ b/packages/utils/src/rundown-utils/rundownUtils.ts @@ -1,13 +1,13 @@ import type { EntryId, - OntimeBlock, OntimeEntry, OntimeEvent, + OntimeGroup, PlayableEvent, Rundown, RundownEntries, } from 'ontime-types'; -import { isOntimeBlock, isOntimeEvent, isPlayableEvent } from 'ontime-types'; +import { isOntimeEvent, isOntimeGroup, isPlayableEvent } from 'ontime-types'; type IndexAndEntry = { entry: OntimeEntry | null; index: number | null }; @@ -313,9 +313,9 @@ export function getEventWithId(rundown: OntimeEntry[], id: string): OntimeEntry } /** - * Gets relevant block element for a given ID + * Gets relevant group element for a given ID */ -export function getPreviousBlockNormal(rundown: RundownEntries, order: string[], currentId: string): IndexAndEntry { +export function getPreviousGroupNormal(rundown: RundownEntries, order: string[], currentId: string): IndexAndEntry { let foundCurrentEvent = false; // Iterate backwards through the rundown to find the current event for (let index = order.length - 1; index >= 0; index--) { @@ -325,20 +325,20 @@ export function getPreviousBlockNormal(rundown: RundownEntries, order: string[], foundCurrentEvent = true; continue; } - // the first block before the current event is the relevant one + // the first group before the current event is the relevant one const entry = rundown[id]; - if (foundCurrentEvent && isOntimeBlock(entry)) { + if (foundCurrentEvent && isOntimeGroup(entry)) { return { entry, index }; } } - // no blocks exist before current event + // no groups exist before current event return { entry: null, index: null }; } /** - * Gets next block element for a given ID + * Gets next group element for a given ID */ -export function getNextBlockNormal(rundown: RundownEntries, order: string[], currentId: string): IndexAndEntry { +export function getNextGroupNormal(rundown: RundownEntries, order: string[], currentId: string): IndexAndEntry { let foundCurrentEvent = false; // Iterate backwards through the rundown to find the current event for (let index = 0; index < order.length; index++) { @@ -348,25 +348,25 @@ export function getNextBlockNormal(rundown: RundownEntries, order: string[], cur foundCurrentEvent = true; continue; } - // the first block before the current event is the relevant one + // the first group before the current event is the relevant one const entry = rundown[id]; - if (foundCurrentEvent && isOntimeBlock(entry)) { + if (foundCurrentEvent && isOntimeGroup(entry)) { return { entry, index }; } } - // no blocks exist before current event + // no groups exist before current event return { entry: null, index: null }; } /** - * Gets relevant block element for a given ID + * Gets relevant group element for a given ID */ -export function getPreviousBlock(rundown: Pick, currentId: EntryId): OntimeBlock | null { +export function getPreviousGroup(rundown: Pick, currentId: EntryId): OntimeGroup | null { const currentEvent = rundown.entries[currentId]; - // check if event is inside a block + // check if event is inside a group if (isOntimeEvent(currentEvent) && currentEvent.parent) { - return rundown.entries[currentEvent.parent] as OntimeBlock; + return rundown.entries[currentEvent.parent] as OntimeGroup; } let foundCurrentEvent = false; @@ -379,11 +379,11 @@ export function getPreviousBlock(rundown: Pick, cu foundCurrentEvent = true; continue; } - // the first block before the current event is the relevant one - if (foundCurrentEvent && isOntimeBlock(entry)) { + // the first group before the current event is the relevant one + if (foundCurrentEvent && isOntimeGroup(entry)) { return entry; } } - // no blocks exist before null event + // no groups exist before null event return null; }