mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-07 16:33:51 +00:00
feat: add group metadata to overview
This commit is contained in:
committed by
Carlos Valente
parent
17a7d035bf
commit
a7ae8598db
@@ -1,6 +1,6 @@
|
||||
import { useEffect, useMemo, useRef, useState } from 'react';
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import { OntimeEntry, Rundown } from 'ontime-types';
|
||||
import { EntryId, OntimeEntry, Rundown } from 'ontime-types';
|
||||
|
||||
import { queryRefetchIntervalSlow } from '../../ontimeConfig';
|
||||
import { RUNDOWN } from '../api/constants';
|
||||
@@ -78,3 +78,18 @@ export function usePartialRundown(cb: (event: OntimeEntry) => boolean) {
|
||||
|
||||
return { data: filteredData, status };
|
||||
}
|
||||
|
||||
/**
|
||||
* Hook to get a specific entry by ID from the rundown
|
||||
*/
|
||||
export function useEntry(entryId: EntryId | null): OntimeEntry | null {
|
||||
const { data: rundown } = useRundown();
|
||||
|
||||
// track the specific entry we care about
|
||||
const entry = useMemo(() => {
|
||||
if (entryId === null) return null;
|
||||
return rundown.entries[entryId];
|
||||
}, [entryId, rundown.entries]);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
@@ -3,7 +3,13 @@ import { memo, PropsWithChildren, useMemo } from 'react';
|
||||
import { useIsMobileScreen } from '../../common/hooks/useIsMobileScreen';
|
||||
import { useRuntimeOverview } from '../../common/hooks/useSocket';
|
||||
|
||||
import { CurrentBlockOverview, OverviewWrapper, RuntimeOverview, TimerOverview } from './composite/OverviewWrapper';
|
||||
import {
|
||||
ClockOverview,
|
||||
CurrentBlockOverview,
|
||||
OverviewWrapper,
|
||||
RuntimeOverview,
|
||||
TimerOverview,
|
||||
} from './composite/OverviewWrapper';
|
||||
import { TimeRow } from './composite/TimeLayout';
|
||||
import { calculateEndAndDaySpan, formatedTime } from './overviewUtils';
|
||||
|
||||
@@ -51,8 +57,9 @@ function CuesheetDesktop({ children }: PropsWithChildren) {
|
||||
/>
|
||||
</div>
|
||||
<TimerOverview />
|
||||
<CurrentBlockOverview />
|
||||
<RuntimeOverview />
|
||||
<CurrentBlockOverview />
|
||||
<ClockOverview />
|
||||
<div>
|
||||
<TimeRow
|
||||
label='Planned end'
|
||||
|
||||
@@ -3,6 +3,7 @@ import { memo, PropsWithChildren, useMemo } from 'react';
|
||||
import { useRuntimeOverview } from '../../common/hooks/useSocket';
|
||||
|
||||
import {
|
||||
ClockOverview,
|
||||
CurrentBlockOverview,
|
||||
OverviewWrapper,
|
||||
ProgressOverview,
|
||||
@@ -42,8 +43,9 @@ function EditorOverview({ children }: PropsWithChildren) {
|
||||
/>
|
||||
</div>
|
||||
<ProgressOverview />
|
||||
<CurrentBlockOverview />
|
||||
<RuntimeOverview />
|
||||
<CurrentBlockOverview />
|
||||
<ClockOverview />
|
||||
<div>
|
||||
<TimeRow
|
||||
label='Planned end'
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
import { PropsWithChildren, ReactNode } from 'react';
|
||||
import { ErrorBoundary } from '@sentry/react';
|
||||
import { isOntimeBlock } from 'ontime-types';
|
||||
import { isPlaybackActive, millisToString } from 'ontime-utils';
|
||||
|
||||
import { useIsOnline, useRuntimePlaybackOverview, useTimer } from '../../../common/hooks/useSocket';
|
||||
import {
|
||||
useClock,
|
||||
useCurrentBlockId,
|
||||
useIsOnline,
|
||||
useRuntimePlaybackOverview,
|
||||
useTimer,
|
||||
} from '../../../common/hooks/useSocket';
|
||||
import useProjectData from '../../../common/hooks-query/useProjectData';
|
||||
import { cx, enDash, timerPlaceholder } from '../../../common/utils/styleUtils';
|
||||
import { useEntry } from '../../../common/hooks-query/useRundown';
|
||||
import { cx, enDash, timerPlaceholder, timerPlaceholderMin } from '../../../common/utils/styleUtils';
|
||||
import { formatedTime, getOffsetText } from '../overviewUtils';
|
||||
|
||||
import { TimeColumn } from './TimeLayout';
|
||||
import { TimeColumn, TimeRow } from './TimeLayout';
|
||||
|
||||
import style from '../Overview.module.scss';
|
||||
|
||||
@@ -44,10 +52,48 @@ export function TitlesOverview() {
|
||||
|
||||
export function CurrentBlockOverview() {
|
||||
const { blockStartedAt: blockStartAt, clock } = useRuntimePlaybackOverview();
|
||||
const { currentBlockId } = useCurrentBlockId();
|
||||
const entry = useEntry(currentBlockId);
|
||||
|
||||
const timeInBlock = formatedTime(blockStartAt ? clock - blockStartAt : null);
|
||||
const timeInBlock = formatedTime(blockStartAt ? clock - blockStartAt : null, 2);
|
||||
|
||||
return <TimeColumn label='Time in block' value={timeInBlock} className={style.clock} muted={blockStartAt === null} />;
|
||||
/**
|
||||
* The time to the end of the block
|
||||
* as scheduled
|
||||
* TODO(v4): this needs to be calculated according to offset mode
|
||||
*/
|
||||
const blockEnd = (() => {
|
||||
if (!entry) return timerPlaceholderMin;
|
||||
if (!isOntimeBlock(entry)) return timerPlaceholderMin;
|
||||
if (entry.timeEnd === null) return timerPlaceholderMin;
|
||||
return formatedTime(entry.timeEnd - clock, 2);
|
||||
})();
|
||||
|
||||
/**
|
||||
* The time to the end of the block
|
||||
* as projected accounting for delays and offset
|
||||
* TODO(v4): this needs to be calculated according to offset mode
|
||||
*/
|
||||
const projectedBlockEnd = (() => {
|
||||
if (blockStartAt === null || !entry) return timerPlaceholderMin;
|
||||
if (!isOntimeBlock(entry)) return timerPlaceholderMin;
|
||||
return formatedTime(blockStartAt + entry.duration - clock, 2);
|
||||
})();
|
||||
|
||||
return (
|
||||
<>
|
||||
<TimeColumn label='Elapsed in block' value={timeInBlock} className={style.clock} muted={blockStartAt === null} />
|
||||
<div>
|
||||
<TimeRow label='Block end' value={blockEnd} className={style.end} muted={blockStartAt === null} />
|
||||
<TimeRow
|
||||
label='Projected block end'
|
||||
value={projectedBlockEnd}
|
||||
className={style.end}
|
||||
muted={blockStartAt === null}
|
||||
/>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export function TimerOverview() {
|
||||
@@ -62,23 +108,23 @@ export function ProgressOverview() {
|
||||
const { numEvents, selectedEventIndex } = useRuntimePlaybackOverview();
|
||||
|
||||
const current = selectedEventIndex !== null ? selectedEventIndex + 1 : enDash;
|
||||
const ofTotal = numEvents || enDash;
|
||||
const progressText = numEvents ? `${current} of ${ofTotal}` : '-';
|
||||
const progressText = numEvents ? `${current} of ${numEvents || enDash}` : enDash;
|
||||
|
||||
return <TimeColumn label='Progress' value={progressText} />;
|
||||
}
|
||||
|
||||
export function RuntimeOverview() {
|
||||
const { clock, offset, playback } = useRuntimePlaybackOverview();
|
||||
const { offset, playback } = useRuntimePlaybackOverview();
|
||||
|
||||
const isPlaying = isPlaybackActive(playback);
|
||||
const offsetText = getOffsetText(isPlaying ? offset : null);
|
||||
const offsetClasses = cx([style.offset, isPlaying && (offset < 0 ? style.behind : style.ahead)]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<TimeColumn label='Offset' value={offsetText} className={offsetClasses} testId='offset' />
|
||||
<TimeColumn label='Time now' value={formatedTime(clock)} />
|
||||
</>
|
||||
);
|
||||
return <TimeColumn label='Offset' value={offsetText} className={offsetClasses} testId='offset' />;
|
||||
}
|
||||
|
||||
export function ClockOverview() {
|
||||
const { clock } = useClock();
|
||||
|
||||
return <TimeColumn label='Time now' value={formatedTime(clock)} />;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user