mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-19 06:04:05 +00:00
refactor: scope rundown to selected
This commit is contained in:
committed by
Carlos Valente
parent
a8182cac8c
commit
4706ed39f6
@@ -3,33 +3,33 @@ import { useViewportSize } from '@mantine/hooks';
|
||||
import { isOntimeEvent, isPlayableEvent, MaybeNumber, OntimeRundown } from 'ontime-types';
|
||||
import { checkIsNextDay, dayInMs, getLastEvent, MILLIS_PER_HOUR } from 'ontime-utils';
|
||||
|
||||
import { useTimelineOverview } from '../../../common/hooks/useSocket';
|
||||
|
||||
import TimelineMarkers from './timeline-markers/TimelineMarkers';
|
||||
import ProgressBar from './timeline-progress-bar/TimelineProgressBar';
|
||||
import TimelineProgressBar from './timeline-progress-bar/TimelineProgressBar';
|
||||
import { getElementPosition, getEndHour, getStartHour } from './timeline.utils';
|
||||
import { ProgressStatus, TimelineEntry } from './TimelineEntry';
|
||||
|
||||
import style from './Timeline.module.scss';
|
||||
|
||||
interface TimelineProps {
|
||||
selectedEventId: string | null;
|
||||
firstStart: number;
|
||||
rundown: OntimeRundown;
|
||||
selectedEventId: string | null;
|
||||
totalDuration: number;
|
||||
}
|
||||
|
||||
export default memo(Timeline);
|
||||
|
||||
function Timeline(props: TimelineProps) {
|
||||
const { selectedEventId, rundown } = props;
|
||||
const { firstStart, rundown, selectedEventId, totalDuration } = props;
|
||||
const { width: screenWidth } = useViewportSize();
|
||||
const { plannedStart, plannedEnd } = useTimelineOverview();
|
||||
|
||||
if (plannedStart === null || plannedEnd === null) {
|
||||
if (totalDuration === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { lastEvent } = getLastEvent(rundown);
|
||||
const startHour = getStartHour(plannedStart);
|
||||
const endHour = getEndHour(plannedEnd + (lastEvent?.delay ?? 0));
|
||||
const startHour = getStartHour(firstStart);
|
||||
const endHour = getEndHour(firstStart + totalDuration + (lastEvent?.delay ?? 0));
|
||||
|
||||
let previousEventStartTime: MaybeNumber = null;
|
||||
// we use selectedEventId as a signifier on whether the timeline is live
|
||||
@@ -39,7 +39,7 @@ function Timeline(props: TimelineProps) {
|
||||
return (
|
||||
<div className={style.timeline}>
|
||||
<TimelineMarkers startHour={startHour} endHour={endHour} />
|
||||
<ProgressBar startHour={startHour} endHour={endHour} />
|
||||
<TimelineProgressBar startHour={startHour} endHour={endHour} />
|
||||
<div className={style.timelineEvents}>
|
||||
{rundown.map((event) => {
|
||||
// for now we dont render delays and blocks
|
||||
|
||||
@@ -35,7 +35,7 @@ export default function TimelinePage(props: TimelinePageProps) {
|
||||
const { backstageEvents, general, selectedId, settings, time, viewSettings } = props;
|
||||
const { shouldRender } = useRuntimeStylesheet(viewSettings?.overrideStyles && overrideStylesURL);
|
||||
// holds copy of the rundown with only relevant events
|
||||
const scopedRundown = useScopedRundown(backstageEvents, selectedId);
|
||||
const { scopedRundown, firstStart, totalDuration } = useScopedRundown(backstageEvents, selectedId);
|
||||
const { getLocalizedString } = useTranslation();
|
||||
const clock = formatTime(time.clock);
|
||||
|
||||
@@ -82,7 +82,12 @@ export default function TimelinePage(props: TimelinePageProps) {
|
||||
category='next'
|
||||
/>
|
||||
</div>
|
||||
<Timeline selectedEventId={selectedId} rundown={scopedRundown} />
|
||||
<Timeline
|
||||
firstStart={firstStart}
|
||||
rundown={scopedRundown}
|
||||
selectedEventId={selectedId}
|
||||
totalDuration={totalDuration}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useSearchParams } from 'react-router-dom';
|
||||
import { isOntimeEvent, MaybeString, OntimeEvent, OntimeRundown } from 'ontime-types';
|
||||
import { isOntimeEvent, isPlayableEvent, MaybeString, OntimeEvent, OntimeRundown, PlayableEvent } from 'ontime-types';
|
||||
import {
|
||||
dayInMs,
|
||||
getEventWithId,
|
||||
getFirstEvent,
|
||||
getNextEvent,
|
||||
getTimeFromPrevious,
|
||||
isNewLatest,
|
||||
MILLIS_PER_HOUR,
|
||||
millisToString,
|
||||
removeSeconds,
|
||||
@@ -89,31 +91,80 @@ export function getStatusLabel(timeToStart: number, status: ProgressStatus): str
|
||||
return formatDuration(timeToStart);
|
||||
}
|
||||
|
||||
export function useScopedRundown(rundown: OntimeRundown, selectedEventId: MaybeString): OntimeRundown {
|
||||
interface ScopedRundownData {
|
||||
scopedRundown: PlayableEvent[];
|
||||
firstStart: number;
|
||||
totalDuration: number;
|
||||
}
|
||||
|
||||
export function useScopedRundown(rundown: OntimeRundown, selectedEventId: MaybeString): ScopedRundownData {
|
||||
const [searchParams] = useSearchParams();
|
||||
|
||||
const data = useMemo(() => {
|
||||
if (rundown.length === 0) {
|
||||
return [];
|
||||
return { scopedRundown: [], firstStart: 0, totalDuration: 0 };
|
||||
}
|
||||
|
||||
const hideBackstage = isStringBoolean(searchParams.get('hideBackstage'));
|
||||
const hidePast = isStringBoolean(searchParams.get('hidePast'));
|
||||
|
||||
let scopedRundown = [...rundown];
|
||||
const scopedRundown: PlayableEvent[] = [];
|
||||
let selectedIndex = selectedEventId ? Infinity : -1;
|
||||
let firstStart = null;
|
||||
let totalDuration = 0;
|
||||
let lastEntry: PlayableEvent | null = null;
|
||||
|
||||
if (hidePast && selectedEventId) {
|
||||
const currentIndex = rundown.findIndex((event) => event.id === selectedEventId);
|
||||
if (currentIndex >= 0) {
|
||||
scopedRundown = scopedRundown.slice(currentIndex);
|
||||
for (let i = 0; i < rundown.length; i++) {
|
||||
const currentEntry = rundown[i];
|
||||
// we only deal with playableEvents
|
||||
if (isOntimeEvent(currentEntry) && isPlayableEvent(currentEntry)) {
|
||||
if (currentEntry.id === selectedEventId) {
|
||||
selectedIndex = i;
|
||||
}
|
||||
|
||||
// maybe filter past
|
||||
if (hidePast && i < selectedIndex) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// maybe filter backstage
|
||||
if (!currentEntry.isPublic && hideBackstage) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// add to scopedRundown
|
||||
scopedRundown.push(currentEntry);
|
||||
|
||||
/**
|
||||
* Derive timers
|
||||
* This logic is partially from rundownCache.generate
|
||||
* With the addition of deriving the current day offset
|
||||
*/
|
||||
if (firstStart === null) {
|
||||
firstStart = currentEntry.timeStart;
|
||||
}
|
||||
|
||||
const timeFromPrevious: number = getTimeFromPrevious(
|
||||
currentEntry.timeStart,
|
||||
lastEntry?.timeStart,
|
||||
lastEntry?.timeEnd,
|
||||
lastEntry?.duration,
|
||||
);
|
||||
|
||||
if (timeFromPrevious === 0) {
|
||||
totalDuration += currentEntry.duration;
|
||||
} else if (timeFromPrevious > 0) {
|
||||
totalDuration += timeFromPrevious + currentEntry.duration;
|
||||
} else if (timeFromPrevious < 0) {
|
||||
totalDuration += Math.max(currentEntry.duration + timeFromPrevious, 0);
|
||||
}
|
||||
if (isNewLatest(currentEntry.timeStart, currentEntry.timeEnd, lastEntry?.timeStart, lastEntry?.timeEnd)) {
|
||||
lastEntry = currentEntry;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (hideBackstage) {
|
||||
scopedRundown = scopedRundown.filter((event) => !isOntimeEvent(event) || event.isPublic);
|
||||
}
|
||||
|
||||
return scopedRundown;
|
||||
return { scopedRundown, firstStart: firstStart ?? 0, totalDuration };
|
||||
}, [rundown, searchParams, selectedEventId]);
|
||||
|
||||
return data;
|
||||
|
||||
Reference in New Issue
Block a user