Remove public event feature (#1645)

This commit is contained in:
Alex Christoffer Rasmussen
2025-06-19 18:07:42 +02:00
committed by GitHub
parent 4e561cf01f
commit c522860d28
99 changed files with 173 additions and 1129 deletions
@@ -31,7 +31,6 @@ const staticSelectProperties = [
{ value: 'eventNow.title', label: 'Title' },
{ value: 'eventNow.cue', label: 'Cue' },
{ value: 'eventNow.countToEnd', label: 'Count to end' },
{ value: 'eventNow.isPublic', label: 'Is public' },
{ value: 'eventNow.note', label: 'Note' },
{ value: 'eventNow.colour', label: 'Colour' },
];
@@ -38,7 +38,6 @@ const eventStaticPropertiesNow = [
'{{eventNow.timeStart}}',
'{{eventNow.timeEnd}}',
'{{eventNow.duration}}',
'{{eventNow.isPublic}}',
'{{eventNow.colour}}',
'{{eventNow.delay}}',
];
@@ -51,7 +50,6 @@ const eventStaticPropertiesNext = [
'{{eventNext.timeStart}}',
'{{eventNext.timeEnd}}',
'{{eventNext.duration}}',
'{{eventNext.isPublic}}',
'{{eventNext.colour}}',
'{{eventNext.delay}}',
];
@@ -13,7 +13,6 @@ export default function EditorSettingsForm() {
defaultTimeStrategy,
defaultWarnTime,
defaultDangerTime,
defaultPublic,
defaultTimerType,
defaultEndAction,
setDefaultDuration,
@@ -21,7 +20,6 @@ export default function EditorSettingsForm() {
setTimeStrategy,
setWarnTime,
setDangerTime,
setDefaultPublic,
setDefaultTimerType,
setDefaultEndAction,
} = useEditorSettings((state) => state);
@@ -127,17 +125,6 @@ export default function EditorSettingsForm() {
/>
</Panel.ListItem>
</Panel.ListGroup>
<Panel.ListGroup>
<Panel.ListItem>
<Panel.Field title='Default public' description='New events will be public' />
<Switch
variant='ontime'
size='lg'
defaultChecked={defaultPublic}
onChange={(event) => setDefaultPublic(event.target.checked)}
/>
</Panel.ListItem>
</Panel.ListGroup>
</Panel.Section>
<Panel.Section>
<Panel.Title>Run mode</Panel.Title>
@@ -8,7 +8,7 @@ import { PROJECT_LIST } from '../../../../common/api/constants';
import { createProject } from '../../../../common/api/db';
import { maybeAxiosError } from '../../../../common/api/utils';
import { preventEscape } from '../../../../common/utils/keyEvent';
import { documentationUrl, websiteUrl } from '../../../../externals';
import { documentationUrl } from '../../../../externals';
import * as Panel from '../../panel-utils/PanelUtils';
import style from './ProjectPanel.module.scss';
@@ -20,8 +20,6 @@ interface ProjectCreateFromProps {
type ProjectCreateFormValues = {
title?: string;
description?: string;
publicInfo?: string;
publicUrl?: string;
backstageInfo?: string;
backstageUrl?: string;
custom?: { title: string; value: string }[];
@@ -120,28 +118,6 @@ export default function ProjectCreateForm(props: ProjectCreateFromProps) {
{...register('description')}
/>
</label>
<label>
Public info
<Textarea
variant='ontime-filled'
size='sm'
maxLength={150}
placeholder='Shows always start ontime'
autoComplete='off'
resize='none'
{...register('publicInfo')}
/>
</label>
<label>
Public QR code Url
<Input
variant='ontime-filled'
size='sm'
placeholder={websiteUrl}
autoComplete='off'
{...register('publicUrl')}
/>
</label>
<label>
Backstage info
<Textarea
@@ -10,7 +10,7 @@ import { maybeAxiosError } from '../../../../common/api/utils';
import useProjectData from '../../../../common/hooks-query/useProjectData';
import { preventEscape } from '../../../../common/utils/keyEvent';
import { validateLogo } from '../../../../common/utils/uploadUtils';
import { documentationUrl, websiteUrl } from '../../../../externals';
import { documentationUrl } from '../../../../externals';
import * as Panel from '../../panel-utils/PanelUtils';
import style from './ProjectPanel.module.scss';
@@ -198,28 +198,6 @@ export default function ProjectData() {
{...register('description')}
/>
</label>
<label>
Public info
<Textarea
variant='ontime-filled'
size='sm'
maxLength={150}
placeholder='Shows always start ontime'
autoComplete='off'
resize='none'
{...register('publicInfo')}
/>
</label>
<label>
Public QR code URL
<Input
variant='ontime-filled'
size='sm'
placeholder={websiteUrl}
autoComplete='off'
{...register('publicUrl')}
/>
</label>
<label>
Backstage info
<Textarea
@@ -12,7 +12,6 @@ describe('convertToImportMap', () => {
Duration: 'duration',
Cue: 'cue',
Title: 'title',
'Is Public': 'public',
Skip: 'skip',
Note: 'notes',
Colour: 'colour',
@@ -12,7 +12,6 @@ const namedImportMap = {
Cue: 'cue',
Title: 'title',
'Count to end': 'count to end',
'Is Public': 'public',
Skip: 'skip',
Note: 'notes',
Colour: 'colour',
@@ -50,7 +49,6 @@ export function convertToImportMap(namedImportMap: NamedImportMap): ImportMap {
cue: namedImportMap.Cue,
title: namedImportMap.Title,
countToEnd: namedImportMap['Count to end'],
isPublic: namedImportMap['Is Public'],
skip: namedImportMap.Skip,
note: namedImportMap.Note,
colour: namedImportMap.Colour,
@@ -41,7 +41,6 @@ export default function PreviewRundown(props: PreviewRundownProps) {
<th>Warning Time</th>
<th>Danger Time</th>
<th>Count to end</th>
<th>Is Public</th>
<th>Skip</th>
<th>Colour</th>
<th>Timer Type</th>
@@ -75,7 +74,6 @@ export default function PreviewRundown(props: PreviewRundownProps) {
eventIndex += 1;
const colour = entry.colour ? getAccessibleColour(entry.colour) : {};
const countToEnd = booleanToText(entry.countToEnd);
const isPublic = booleanToText(entry.isPublic);
const skip = booleanToText(entry.skip);
return (
@@ -98,7 +96,6 @@ export default function PreviewRundown(props: PreviewRundownProps) {
<td>{millisToString(entry.timeWarning)}</td>
<td>{millisToString(entry.timeDanger)}</td>
<td className={style.center}>{countToEnd && <Tag>{countToEnd}</Tag>}</td>
<td className={style.center}>{isPublic && <Tag>{isPublic}</Tag>}</td>
<td>{skip && <Tag>{skip}</Tag>}</td>
<td style={{ ...colour }}>{entry.colour}</td>
<td className={style.center}>
@@ -175,7 +175,6 @@ export default function RundownEntry(props: RundownEntryProps) {
timeStrategy={data.timeStrategy}
linkStart={data.linkStart}
countToEnd={data.countToEnd}
isPublic={data.isPublic}
endAction={data.endAction}
timerType={data.timerType}
title={data.title}
@@ -196,6 +195,7 @@ export default function RundownEntry(props: RundownEntryProps) {
totalGap={totalGap}
isLinkedToLoaded={isLinkedToLoaded}
actionHandler={actionHandler}
hasTriggers={data.triggers.length > 0}
/>
);
} else if (isOntimeDelay(data)) {
@@ -4,8 +4,6 @@ import {
IoDuplicateOutline,
IoFolder,
IoLink,
IoPeople,
IoPeopleOutline,
IoReorderTwo,
IoSwapVertical,
IoTrash,
@@ -36,7 +34,6 @@ interface EventBlockProps {
linkStart: boolean;
countToEnd: boolean;
eventIndex: number;
isPublic: boolean;
endAction: EndAction;
timerType: TimerType;
title: string;
@@ -65,6 +62,7 @@ interface EventBlockProps {
value: unknown;
},
) => void;
hasTriggers: boolean;
}
export default function EventBlock(props: EventBlockProps) {
@@ -77,7 +75,6 @@ export default function EventBlock(props: EventBlockProps) {
timeStrategy,
linkStart,
countToEnd,
isPublic = true,
eventIndex,
endAction,
timerType,
@@ -99,6 +96,7 @@ export default function EventBlock(props: EventBlockProps) {
totalGap,
isLinkedToLoaded,
actionHandler,
hasTriggers,
} = props;
const { selectedEventId, setSelectedEventId, clearSelectedEventId } = useEventIdSwapping();
const { selectedEvents, setSelectedEvents } = useEventSelection();
@@ -126,25 +124,6 @@ export default function EventBlock(props: EventBlockProps) {
value: null,
}),
},
{
label: 'Make public',
icon: IoPeople,
onClick: () =>
actionHandler('update', {
field: 'isPublic',
value: true,
}),
withDivider: true,
},
{
label: 'Make private',
icon: IoPeopleOutline,
onClick: () =>
actionHandler('update', {
field: 'isPublic',
value: false,
}),
},
{ withDivider: true, label: 'Group', icon: IoFolder, onClick: () => actionHandler('group') },
{ withDivider: true, label: 'Delete', icon: IoTrash, onClick: () => actionHandler('delete') },
]
@@ -158,16 +137,6 @@ export default function EventBlock(props: EventBlockProps) {
value: linkStart,
}),
},
{
label: 'Toggle public',
icon: IoPeopleOutline,
onClick: () =>
actionHandler('update', {
field: 'isPublic',
value: !isPublic,
}),
withDivider: true,
},
{
label: 'Add to swap',
icon: IoAdd,
@@ -308,7 +277,6 @@ export default function EventBlock(props: EventBlockProps) {
timeStrategy={timeStrategy}
eventId={eventId}
eventIndex={eventIndex}
isPublic={isPublic}
endAction={endAction}
timerType={timerType}
title={title}
@@ -323,6 +291,7 @@ export default function EventBlock(props: EventBlockProps) {
isPast={isPast}
totalGap={totalGap}
isLinkedToLoaded={isLinkedToLoaded}
hasTriggers={hasTriggers}
/>
)}
</div>
@@ -4,7 +4,7 @@ import {
IoArrowUp,
IoBan,
IoFlag,
IoPeople,
IoFlash,
IoPlay,
IoPlayForward,
IoPlaySkipForward,
@@ -33,7 +33,6 @@ interface EventBlockInnerProps {
linkStart: boolean;
countToEnd: boolean;
eventIndex: number;
isPublic: boolean;
endAction: EndAction;
timerType: TimerType;
title: string;
@@ -48,6 +47,7 @@ interface EventBlockInnerProps {
isPast: boolean;
totalGap: number;
isLinkedToLoaded: boolean;
hasTriggers: boolean;
}
function EventBlockInner(props: EventBlockInnerProps) {
@@ -59,7 +59,6 @@ function EventBlockInner(props: EventBlockInnerProps) {
timeStrategy,
linkStart,
countToEnd,
isPublic = true,
endAction,
timerType,
title,
@@ -74,6 +73,7 @@ function EventBlockInner(props: EventBlockInnerProps) {
isPast,
totalGap,
isLinkedToLoaded,
hasTriggers,
} = props;
const [renderInner, setRenderInner] = useState(false);
@@ -132,7 +132,7 @@ function EventBlockInner(props: EventBlockInnerProps) {
duration={duration}
/>
)}
<div className={style.statusElements} id='block-status' data-ispublic={isPublic}>
<div className={style.statusElements} id='block-status' data-timerType={timerType}>
<span className={style.eventNote}>{note}</span>
<div className={loaded ? style.progressBg : `${style.progressBg} ${style.hidden}`}>
{loaded && <EventBlockProgressBar />}
@@ -153,9 +153,9 @@ function EventBlockInner(props: EventBlockInnerProps) {
<IoFlag className={`${style.statusIcon} ${countToEnd ? style.active : style.disabled}`} />
</span>
</Tooltip>
<Tooltip label={`${isPublic ? 'Event is public' : 'Event is private'}`} openDelay={tooltipDelayMid}>
<Tooltip label='Event has Triggers' openDelay={tooltipDelayMid}>
<span>
<IoPeople className={`${style.statusIcon} ${isPublic ? style.active : style.disabled}`} />
<IoFlash className={`${style.statusIcon} ${hasTriggers ? style.active : style.disabled}`} />
</span>
</Tooltip>
</div>
@@ -56,7 +56,6 @@ export default function EventEditor(props: EventEditorProps) {
linkStart={event.linkStart}
countToEnd={event.countToEnd}
delay={event.delay ?? 0}
isPublic={event.isPublic}
endAction={event.endAction}
timerType={event.timerType}
timeWarning={event.timeWarning}
@@ -21,14 +21,13 @@ interface EventEditorTimesProps {
linkStart: boolean;
countToEnd: boolean;
delay: number;
isPublic: boolean;
endAction: EndAction;
timerType: TimerType;
timeWarning: number;
timeDanger: number;
}
type HandledActions = 'countToEnd' | 'timerType' | 'endAction' | 'isPublic' | 'timeWarning' | 'timeDanger';
type HandledActions = 'countToEnd' | 'timerType' | 'endAction' | 'timeWarning' | 'timeDanger';
function EventEditorTimes(props: EventEditorTimesProps) {
const {
@@ -40,7 +39,6 @@ function EventEditorTimes(props: EventEditorTimesProps) {
linkStart,
countToEnd,
delay,
isPublic,
endAction,
timerType,
timeWarning,
@@ -49,11 +47,6 @@ function EventEditorTimes(props: EventEditorTimesProps) {
const { updateEntry } = useEntryActions();
const handleSubmit = (field: HandledActions, value: string | boolean) => {
if (field === 'isPublic') {
updateEntry({ id: eventId, isPublic: !(value as boolean) });
return;
}
if (field === 'countToEnd') {
updateEntry({ id: eventId, countToEnd: !(value as boolean) });
return;
@@ -160,6 +153,9 @@ function EventEditorTimes(props: EventEditorTimesProps) {
<option value={TimerType.None}>None</option>
</Select>
</div>
<div>
{/* TODO: rearrange this grid */}
</div>
<div>
<Editor.Label htmlFor='timeWarning'>Warning Time</Editor.Label>
<TimeInput
@@ -171,19 +167,6 @@ function EventEditorTimes(props: EventEditorTimesProps) {
/>
</div>
<div>
<Editor.Label htmlFor='isPublic'>Event Visibility</Editor.Label>
<Editor.Label className={style.switchLabel}>
<Switch
id='isPublic'
size='md'
isChecked={isPublic}
onChange={() => handleSubmit('isPublic', isPublic)}
variant='ontime'
/>
{isPublic ? 'Public' : 'Private'}
</Editor.Label>
</div>
<div>
<Editor.Label htmlFor='timeDanger'>Danger Time</Editor.Label>
<TimeInput
@@ -20,7 +20,6 @@ function QuickAddBlock(props: QuickAddBlockProps) {
const { addEntry } = useEntryActions();
const doLinkPrevious = useRef<HTMLInputElement | null>(null);
const doPublic = useRef<HTMLInputElement | null>(null);
const addEvent = () => {
addEntry(
@@ -30,7 +29,6 @@ function QuickAddBlock(props: QuickAddBlockProps) {
},
{
after: previousEventId,
defaultPublic: doPublic?.current?.checked,
lastEventId: previousEventId,
linkPrevious: doLinkPrevious?.current?.checked,
},
@@ -1,4 +1,4 @@
import { ComponentType, useMemo } from 'react';
import { ComponentType } from 'react';
import { ViewExtendedTimer } from 'common/models/TimeManager.type';
import {
CustomFields,
@@ -8,7 +8,6 @@ import {
Runtime,
Settings,
SimpleTimerState,
SupportedEntry,
TimerType,
ViewSettings,
} from 'ontime-types';
@@ -25,19 +24,15 @@ import { useViewOptionsStore } from '../../common/stores/viewOptions';
type WithDataProps = {
auxTimer: SimpleTimerState;
backstageEvents: OntimeEvent[];
events: OntimeEvent[];
customFields: CustomFields;
eventNext: OntimeEvent | null;
eventNow: OntimeEvent | null;
events: OntimeEvent[];
general: ProjectData;
isMirrored: boolean;
message: MessageState;
nextId: string | null;
onAir: boolean;
publicEventNext: OntimeEvent | null;
publicEventNow: OntimeEvent | null;
publicSelectedId: string | null;
runtime: Runtime;
selectedId: string | null;
settings: Settings | undefined; // TODO: what is the case for this being undefined?
@@ -61,17 +56,9 @@ const withData = <P extends WithDataProps>(Component: ComponentType<P>) => {
const { data: settings } = useSettings();
const { data: customFields } = useCustomFields();
const publicEvents = useMemo(() => {
if (Array.isArray(rundownData)) {
return rundownData.filter((e) => e.type === SupportedEntry.Event && e.title && e.isPublic);
}
return [];
}, [rundownData]);
// websocket data
const { clock, timer, message, onAir, eventNext, publicEventNext, publicEventNow, eventNow, runtime, auxtimer1 } =
const { clock, timer, message, onAir, eventNext, eventNow, runtime, auxtimer1 } =
useStore(runtimeStore);
const publicSelectedId = publicEventNow?.id ?? null;
const selectedId = eventNow?.id ?? null;
const nextId = eventNext?.id ?? null;
@@ -91,19 +78,15 @@ const withData = <P extends WithDataProps>(Component: ComponentType<P>) => {
<Component
{...props}
auxTimer={auxtimer1}
backstageEvents={rundownData}
events={rundownData}
customFields={customFields}
eventNext={eventNext}
eventNow={eventNow}
events={publicEvents}
general={project}
isMirrored={isMirrored}
message={message}
nextId={nextId}
onAir={onAir}
publicEventNext={publicEventNext}
publicEventNow={publicEventNow}
publicSelectedId={publicSelectedId}
runtime={runtime}
selectedId={selectedId}
settings={settings}
@@ -7,7 +7,6 @@ import {
ProjectData,
Runtime,
Settings,
SupportedEntry,
TimerPhase,
} from 'ontime-types';
@@ -27,7 +26,7 @@ import CountdownSelect from './CountdownSelect';
import './Countdown.scss';
interface CountdownProps {
backstageEvents: OntimeEvent[];
events: OntimeEvent[];
general: ProjectData;
isMirrored: boolean;
runtime: Runtime;
@@ -37,7 +36,7 @@ interface CountdownProps {
}
export default function Countdown(props: CountdownProps) {
const { backstageEvents, general, isMirrored, runtime, selectedId, settings, time } = props;
const { events, general, isMirrored, runtime, selectedId, settings, time } = props;
const [searchParams] = useSearchParams();
const { getLocalizedString } = useTranslation();
@@ -49,7 +48,7 @@ export default function Countdown(props: CountdownProps) {
// eg. http://localhost:4001/countdown?eventId=ei0us
// update data to the event we are following
useEffect(() => {
if (!backstageEvents) {
if (!events) {
return;
}
@@ -63,7 +62,6 @@ export default function Countdown(props: CountdownProps) {
}
let followThis: OntimeEvent | null = null;
const events: OntimeEvent[] = [...backstageEvents].filter((event) => event.type === SupportedEntry.Event);
if (eventId !== null) {
followThis = events.find((event) => event.id === eventId) || null;
@@ -72,11 +70,11 @@ export default function Countdown(props: CountdownProps) {
}
if (followThis !== null) {
setFollow(followThis);
const idx: number = backstageEvents.findIndex((event: OntimeEntry) => event.id === followThis?.id);
const delayToEvent = backstageEvents[idx]?.delay ?? 0;
const idx: number = events.findIndex((event: OntimeEntry) => event.id === followThis?.id);
const delayToEvent = events[idx]?.delay ?? 0;
setDelay(delayToEvent);
}
}, [backstageEvents, searchParams]);
}, [events, searchParams]);
const { message: runningMessage, timer: runningTimer } = fetchTimerData(time, follow, selectedId, runtime.offset);
@@ -119,7 +117,7 @@ export default function Countdown(props: CountdownProps) {
{general?.projectLogo && <ViewLogo name={general.projectLogo} className='logo' />}
<ViewParamsEditor viewOptions={viewOptions} />
{follow === null ? (
<CountdownSelect events={backstageEvents} />
<CountdownSelect events={events} />
) : (
<div className='countdown-container' data-testid='countdown-event'>
<div className='clock-container'>
@@ -1,3 +1,5 @@
import { ViewExtendedTimer } from 'common/models/TimeManager.type';
import { OntimeEvent } from 'ontime-types';
import { dayInMs } from 'ontime-utils';
import { fetchTimerData, sanitiseTitle, TimerMessage } from '../countdown.helpers';
@@ -14,7 +16,7 @@ describe('sanitiseTitle() function', () => {
it('should return {no title} when invalid', () => {
const invalidTitles = ['', undefined, null];
for (const title of invalidTitles) {
expect(sanitiseTitle(title)).toBe('{no title}');
expect(sanitiseTitle(title as unknown as string)).toBe('{no title}');
}
});
});
@@ -23,10 +25,10 @@ describe('fetchTimerData() function', () => {
it('shows current timer if current is the one we follow', () => {
const followId = 'testId';
const currentMockValue = 13;
const follow = { id: followId };
const time = { current: currentMockValue };
const follow = { id: followId } as OntimeEvent;
const time = { current: currentMockValue } as ViewExtendedTimer;
const { message, timer } = fetchTimerData(time, follow, followId);
const { message, timer } = fetchTimerData(time, follow, followId, 0);
expect(message).toBe(TimerMessage.running);
expect(timer).toBe(currentMockValue);
});
@@ -34,10 +36,10 @@ describe('fetchTimerData() function', () => {
it('shows the countdown to an upcoming event', () => {
const startMockValue = 10000;
const timeNow = 1000;
const follow = { id: 'anotherevent', timeStart: startMockValue };
const time = { clock: timeNow };
const follow = { id: 'anotherevent', timeStart: startMockValue } as OntimeEvent;
const time = { clock: timeNow } as ViewExtendedTimer;
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent');
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent', 0);
expect(message).toBe(TimerMessage.toStart);
expect(timer).toBe(startMockValue - timeNow);
});
@@ -47,10 +49,10 @@ describe('fetchTimerData() function', () => {
const endMockValue = 20000;
const timeNow = 15000;
const followId = 'testId';
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue };
const time = { clock: timeNow, current: endMockValue - startMockValue };
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue } as OntimeEvent;
const time = { clock: timeNow, current: endMockValue - startMockValue } as ViewExtendedTimer;
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent');
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent', 0);
expect(message).toBe(TimerMessage.waiting);
expect(timer).toBe(endMockValue - startMockValue);
});
@@ -60,10 +62,10 @@ describe('fetchTimerData() function', () => {
const endMockValue = 20000;
const timeNow = 30000;
const followId = 'testId';
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue };
const time = { clock: timeNow, current: endMockValue - startMockValue };
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue } as OntimeEvent;
const time = { clock: timeNow, current: endMockValue - startMockValue } as ViewExtendedTimer;
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent');
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent', 0);
expect(message).toBe(TimerMessage.ended);
expect(timer).toBe(endMockValue);
});
@@ -73,10 +75,10 @@ describe('fetchTimerData() function', () => {
const endMockValue = 1000;
const timeNow = 15000;
const followId = 'testId';
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue };
const time = { clock: timeNow, current: dayInMs + endMockValue - startMockValue };
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue } as OntimeEvent;
const time = { clock: timeNow, current: dayInMs + endMockValue - startMockValue } as ViewExtendedTimer;
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent');
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent', 0);
expect(message).toBe(TimerMessage.waiting);
expect(timer).toBe(dayInMs + endMockValue - startMockValue);
});
@@ -86,10 +88,10 @@ describe('fetchTimerData() function', () => {
const endMockValue = 1000;
const timeNow = 15000;
const followId = 'testId';
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue };
const time = { clock: timeNow, current: dayInMs + endMockValue - startMockValue };
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue } as OntimeEvent;
const time = { clock: timeNow, current: dayInMs + endMockValue - startMockValue } as ViewExtendedTimer;
const { message, timer } = fetchTimerData(time, follow, followId);
const { message, timer } = fetchTimerData(time, follow, followId, 0);
expect(message).toBe(TimerMessage.running);
expect(timer).toBe(dayInMs + endMockValue - startMockValue);
});
@@ -99,10 +101,10 @@ describe('fetchTimerData() function', () => {
const endMockValue = 1000;
const timeNow = 2000;
const followId = 'testId';
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue };
const time = { clock: timeNow, current: dayInMs + endMockValue - startMockValue };
const follow = { id: followId, timeStart: startMockValue, timeEnd: endMockValue } as OntimeEvent;
const time = { clock: timeNow, current: dayInMs + endMockValue - startMockValue } as ViewExtendedTimer;
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent');
const { message, timer } = fetchTimerData(time, follow, 'notthesameevent', 0);
expect(message).toBe(TimerMessage.toStart);
expect(timer).toBe(startMockValue - timeNow);
});
@@ -26,7 +26,7 @@ export default function LowerThird(props: LowerProps) {
const animationTimeout = useRef<NodeJS.Timeout>();
const [playState, setPlayState] = useState<boolean>(false);
const [textValue, setTextValue] = useState<{ top: string; bottom: string }>({ top: '', bottom: '' });
useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
useRuntimeStylesheet(viewSettings?.overrideStyles ? overrideStylesURL : undefined);
const options = useLowerOptions();
const { playback } = time;
@@ -17,7 +17,7 @@ import StudioClockSchedule from './StudioClockSchedule';
import './StudioClock.scss';
interface StudioClockProps {
backstageEvents: OntimeEntry[];
events: OntimeEntry[];
eventNext: OntimeEvent | null;
general: ProjectData;
isMirrored: boolean;
@@ -29,7 +29,7 @@ interface StudioClockProps {
}
export default function StudioClock(props: StudioClockProps) {
const { backstageEvents, eventNext, general, isMirrored, time, selectedId, nextId, onAir, settings } = props;
const { events, eventNext, general, isMirrored, time, selectedId, nextId, onAir, settings } = props;
const [searchParams] = useSearchParams();
@@ -102,7 +102,7 @@ export default function StudioClock(props: StudioClockProps) {
</div>
</div>
{!hideRight && (
<StudioClockSchedule rundown={backstageEvents} selectedId={selectedId} nextId={nextId} onAir={onAir} />
<StudioClockSchedule rundown={events} selectedId={selectedId} nextId={nextId} onAir={onAir} />
)}
</div>
);