Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions apps/client/src/declarations/declaration.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ declare global {
* - `handleUpdate` callback to update the entry when the user edits a cell
* - `handleUpdateTimer` callback to update the timer for a specific event
* - `options-showDelayedTimes` whether to show or hide delayed times
* - `options-showExpectedTimes` whether to show or hide live offset adjusted times
* - `options-hideTableSeconds` whether to hide seconds in the table
* - `options-hideIndexColumn` whether to hide the index column
* - `options-cuesheetMode` run or edit mode
Expand All @@ -52,6 +53,7 @@ declare module '@tanstack/react-table' {
handleUpdateTimer: (eventId: string, field: TimeField, payload: string) => void;
options: {
showDelayedTimes: boolean;
showExpectedTimes: boolean;
hideTableSeconds: boolean;
hideIndexColumn: boolean;
cuesheetMode: AppMode;
Expand Down
2 changes: 2 additions & 0 deletions apps/client/src/features/rundown/rundown.options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ type OptionValues = {
hideTableSeconds: boolean;
hideIndexColumn: boolean;
showDelayedTimes: boolean;
showExpectedTimes: boolean;
hideDelays: boolean;
};

const defaultOptions: OptionValues = {
hideTableSeconds: false,
hideIndexColumn: false,
showDelayedTimes: false,
showExpectedTimes: false,
hideDelays: false,
};

Expand Down
14 changes: 12 additions & 2 deletions apps/client/src/views/cuesheet/cuesheet-table/CuesheetTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export default function CuesheetTable({

const useOptions = tableRoot === 'editor' ? usePersistedRundownOptions : usePersistedCuesheetOptions;
const optionsStore = useOptions();
const { showDelayedTimes, hideTableSeconds, hideIndexColumn } = optionsStore;
const { showDelayedTimes, showExpectedTimes, hideTableSeconds, hideIndexColumn } = optionsStore;

const cursor = useEventSelection((state) => state.cursor);
const setScrollHandler = useEventSelection((state) => state.setScrollHandler);
Expand Down Expand Up @@ -104,12 +104,22 @@ export default function CuesheetTable({
},
options: {
showDelayedTimes,
showExpectedTimes,
hideTableSeconds,
cuesheetMode,
hideIndexColumn,
},
}),
[cuesheetMode, flatRundown, hideIndexColumn, hideTableSeconds, showDelayedTimes, updateEntry, updateTimer],
[
cuesheetMode,
flatRundown,
hideIndexColumn,
hideTableSeconds,
showDelayedTimes,
showExpectedTimes,
updateEntry,
updateTimer,
],
);

const { columnOrder, resetColumnOrder } = useColumnOrder(columns, tableRoot);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ interface TimeInputDurationProps {
initialValue: number;
lockedValue: boolean;
delayed?: boolean;
offset?: 'over' | 'under' | 'muted' | null;
onSubmit: (value: string) => void;
}

Expand All @@ -22,6 +23,7 @@ function TimeInputDuration({
initialValue,
lockedValue,
delayed,
offset,
onSubmit,
children,
}: PropsWithChildren<TimeInputDurationProps>) {
Expand Down Expand Up @@ -110,7 +112,7 @@ function TimeInputDuration({
onClick={handleFakeFocus}
onFocus={handleFakeFocus}
muted={!lockedValue}
offset={delayed ? 'over' : undefined}
offset={offset ?? (delayed ? 'over' : undefined)}
ref={textRef}
>
{children}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@ import { millisToString } from 'ontime-utils';
import { useCallback } from 'react';

import DelayIndicator from '../../../../common/components/delay-indicator/DelayIndicator';
import { useExpectedStartData } from '../../../../common/hooks/useSocket';
import { getOffsetState } from '../../../../common/utils/offset';
import type { ExtendedEntry } from '../../../../common/utils/rundownMetadata';
import { formatDuration, formatTime } from '../../../../common/utils/time';
import { formatDuration, formatTime, getExpectedTimesFromExtendedEvent } from '../../../../common/utils/time';
import { AppMode } from '../../../../ontimeConfig';
import { getCuesheetColumnAccessPolicy } from '../../cuesheet.policies';
import DurationInput from './DurationInput';
Expand All @@ -22,11 +24,13 @@ function getColumnLabel(column: CellContext<ExtendedEntry, unknown>['column']):
}

function MakeStart({ getValue, row, table, column }: CellContext<ExtendedEntry, unknown>) {
const expectedStartData = useExpectedStartData();

if (!table.options.meta) {
return null;
}

const { showDelayedTimes, hideTableSeconds } = table.options.meta.options;
const { showDelayedTimes, showExpectedTimes, hideTableSeconds } = table.options.meta.options;
const formatOpts = hideTableSeconds ? { format12: 'h:mm a', format24: 'HH:mm' } : undefined;

const event = row.original;
Expand All @@ -40,32 +44,42 @@ function MakeStart({ getValue, row, table, column }: CellContext<ExtendedEntry,

const startTime = getValue() as number;
const isStartLocked = !event.linkStart;
const displayTime = showDelayedTimes ? startTime + event.delay : startTime;
const expectedTimes = showExpectedTimes ? getExpectedTimesFromExtendedEvent(event, expectedStartData) : null;
const displayTime = expectedTimes ? expectedTimes.expectedStart : showDelayedTimes ? startTime + event.delay : startTime;
const offsetState = expectedTimes ? getOffsetState(displayTime - startTime) : null;
const formattedTime = formatTime(displayTime, formatOpts);

const canWrite = column.columnDef.meta?.canWrite;
if (!canWrite) {
return (
<MutedText numeric>
{formattedTime}
<DelayIndicator delayValue={event.delay} tooltipPrefix={millisToString(startTime)} />
{!expectedTimes && <DelayIndicator delayValue={event.delay} tooltipPrefix={millisToString(startTime)} />}
</MutedText>
);
}
return (
<TimeInput initialValue={startTime} onSubmit={update} lockedValue={isStartLocked} delayed={event.delay !== 0}>
<TimeInput
initialValue={startTime}
onSubmit={update}
lockedValue={isStartLocked}
delayed={event.delay !== 0}
offset={offsetState}
>
{formattedTime}
<DelayIndicator delayValue={event.delay} tooltipPrefix={millisToString(startTime)} />
{!expectedTimes && <DelayIndicator delayValue={event.delay} tooltipPrefix={millisToString(startTime)} />}
</TimeInput>
);
}

function MakeEnd({ getValue, row, table, column }: CellContext<ExtendedEntry, unknown>) {
const expectedStartData = useExpectedStartData();

if (!table.options.meta) {
return null;
}

const { showDelayedTimes, hideTableSeconds } = table.options.meta.options;
const { showDelayedTimes, showExpectedTimes, hideTableSeconds } = table.options.meta.options;
const formatOpts = hideTableSeconds ? { format12: 'h:mm a', format24: 'HH:mm' } : undefined;

const event = row.original;
Expand All @@ -79,23 +93,32 @@ function MakeEnd({ getValue, row, table, column }: CellContext<ExtendedEntry, un

const endTime = getValue() as number;
const isEndLocked = event.timeStrategy === TimeStrategy.LockEnd;
const displayTime = showDelayedTimes ? endTime + event.delay : endTime;
const expectedTimes = showExpectedTimes ? getExpectedTimesFromExtendedEvent(event, expectedStartData) : null;
const displayTime = expectedTimes ? expectedTimes.expectedEnd : showDelayedTimes ? endTime + event.delay : endTime;
const plannedTime = expectedTimes ? expectedTimes.plannedEnd : endTime;
const offsetState = expectedTimes ? getOffsetState(displayTime - plannedTime) : null;
const formattedTime = formatTime(displayTime, formatOpts);

const canWrite = column.columnDef.meta?.canWrite;
if (!canWrite) {
return (
<MutedText numeric>
{formattedTime}
<DelayIndicator delayValue={event.delay} tooltipPrefix={millisToString(endTime)} />
{!expectedTimes && <DelayIndicator delayValue={event.delay} tooltipPrefix={millisToString(endTime)} />}
</MutedText>
);
}

return (
<TimeInput initialValue={endTime} onSubmit={update} lockedValue={isEndLocked} delayed={event.delay !== 0}>
<TimeInput
initialValue={endTime}
onSubmit={update}
lockedValue={isEndLocked}
delayed={event.delay !== 0}
offset={offsetState}
>
{formattedTime}
<DelayIndicator delayValue={event.delay} tooltipPrefix={millisToString(endTime)} />
{!expectedTimes && <DelayIndicator delayValue={event.delay} tooltipPrefix={millisToString(endTime)} />}
</TimeInput>
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,14 @@ type TableHeaderOptionsStore = {
hideTableSeconds: boolean;
hideIndexColumn: boolean;
showDelayedTimes: boolean;
showExpectedTimes: boolean;
hideDelays: boolean;
setOption: <K extends keyof TableHeaderOptionValues>(key: K, value: TableHeaderOptionValues[K]) => void;
};

type TableHeaderOptionValues = Pick<
TableHeaderOptionsStore,
'hideTableSeconds' | 'hideIndexColumn' | 'showDelayedTimes' | 'hideDelays'
'hideTableSeconds' | 'hideIndexColumn' | 'showDelayedTimes' | 'showExpectedTimes' | 'hideDelays'
>;

type TableModeControls = {
Expand Down Expand Up @@ -161,6 +162,13 @@ function ViewSettings({ optionsStore }: ViewSettingsProps) {
/>
Show delayed times
</Editor.Label>
<Editor.Label className={style.option}>
<Checkbox
defaultChecked={optionsStore.showExpectedTimes}
onCheckedChange={(checked) => optionsStore.setOption('showExpectedTimes', checked)}
/>
Show expected times
</Editor.Label>
<Editor.Label className={style.option}>
<Checkbox
defaultChecked={optionsStore.hideDelays}
Expand Down
2 changes: 2 additions & 0 deletions apps/client/src/views/cuesheet/cuesheet.options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,15 @@ type OptionValues = {
hideTableSeconds: boolean;
hideIndexColumn: boolean;
showDelayedTimes: boolean;
showExpectedTimes: boolean;
hideDelays: boolean;
};

const defaultOptions: OptionValues = {
hideTableSeconds: false,
hideIndexColumn: false,
showDelayedTimes: false,
showExpectedTimes: false,
hideDelays: false,
};

Expand Down