feat: expose planned start in operator

This commit is contained in:
Carlos Valente
2025-08-06 06:52:56 +02:00
committed by Carlos Valente
parent f1a8db9649
commit 49e923026e
4 changed files with 38 additions and 13 deletions
@@ -35,7 +35,7 @@ export default function Operator() {
const timeoutId = useRef<NodeJS.Timeout | null>(null); const timeoutId = useRef<NodeJS.Timeout | null>(null);
const { selectedEventId } = useSelectedEventId(); const { selectedEventId } = useSelectedEventId();
const { subscribe, mainSource, secondarySource, shouldEdit, hidePast } = useOperatorOptions(); const { subscribe, mainSource, secondarySource, shouldEdit, hidePast, showStart } = useOperatorOptions();
const { data: settings } = useSettings(); const { data: settings } = useSettings();
const [showEditPrompt, setShowEditPrompt] = useState(false); const [showEditPrompt, setShowEditPrompt] = useState(false);
@@ -160,6 +160,7 @@ export default function Operator() {
isSelected={isSelected} isSelected={isSelected}
isPast={isPast} isPast={isPast}
selectedRef={isSelected ? selectedRef : undefined} selectedRef={isSelected ? selectedRef : undefined}
showStart={showStart}
subscribed={subscribedData} subscribed={subscribedData}
totalGap={totalGap} totalGap={totalGap}
onLongPress={canEdit ? handleEdit : () => undefined} onLongPress={canEdit ? handleEdit : () => undefined}
@@ -208,6 +209,7 @@ export default function Operator() {
isSelected={isSelected} isSelected={isSelected}
isPast={isPast} isPast={isPast}
selectedRef={isSelected ? selectedRef : undefined} selectedRef={isSelected ? selectedRef : undefined}
showStart={showStart}
subscribed={subscribedData} subscribed={subscribedData}
totalGap={totalGap} totalGap={totalGap}
onLongPress={canEdit ? handleEdit : () => undefined} onLongPress={canEdit ? handleEdit : () => undefined}
@@ -1,3 +1,4 @@
@use '@/theme/viewerDefs' as *;
@import '../Operator.module.scss'; @import '../Operator.module.scss';
.event { .event {
@@ -5,13 +6,14 @@
border-top: 1px solid $white-1; border-top: 1px solid $white-1;
padding-right: 0.5rem; padding-right: 0.5rem;
color: $white-90; color: $white-90;
background-color: $gray-1300; background-color: $viewer-card-bg-color;
display: grid; display: grid;
align-items: center; align-items: center;
grid-template-columns: 1.25rem 1fr auto;
grid-template-rows: auto auto auto;
column-gap: 0.5rem; column-gap: 0.5rem;
row-gap: 0.5rem;
grid-template-rows: auto auto auto;
grid-template-columns: 1.25rem 1fr auto;
grid-template-areas: grid-template-areas:
'binder main schedule' 'binder main schedule'
'binder secondary running' 'binder secondary running'
@@ -69,14 +71,23 @@
white-space: pre-line; white-space: pre-line;
} }
.plannedStart, .timeUntil {
line-height: 1em;
background-color: $gray-1000;
padding: 0.25rem 0.5rem;
border-radius: 1px;
}
.plannedStart {
font-size: 1.5rem;
margin-right: 0.5rem;
}
.timeUntil { .timeUntil {
font-size: calc(1rem - 2px); font-size: calc(1rem - 2px);
line-height: 1em; line-height: 1em;
grid-area: schedule; grid-area: schedule;
justify-self: end; justify-self: end;
background-color: $gray-1000;
padding: 0.25rem 0.5rem;
border-radius: 1px;
} }
.runningTime { .runningTime {
@@ -1,6 +1,6 @@
import { memo, RefObject, SyntheticEvent } from 'react'; import { memo, RefObject, SyntheticEvent } from 'react';
import { useLongPress } from '@mantine/hooks'; import { useLongPress } from '@mantine/hooks';
import { MILLIS_PER_MINUTE, MILLIS_PER_SECOND } from 'ontime-utils'; import { MILLIS_PER_MINUTE, MILLIS_PER_SECOND, millisToString } from 'ontime-utils';
import DelayIndicator from '../../../common/components/delay-indicator/DelayIndicator'; import DelayIndicator from '../../../common/components/delay-indicator/DelayIndicator';
import { cx, getAccessibleColour } from '../../../common/utils/styleUtils'; import { cx, getAccessibleColour } from '../../../common/utils/styleUtils';
@@ -24,6 +24,7 @@ interface OperatorEventProps {
isSelected: boolean; isSelected: boolean;
isPast: boolean; isPast: boolean;
selectedRef?: RefObject<HTMLDivElement | null>; selectedRef?: RefObject<HTMLDivElement | null>;
showStart: boolean;
subscribed: Subscribed; subscribed: Subscribed;
totalGap: number; totalGap: number;
onLongPress: (event: EditEvent) => void; onLongPress: (event: EditEvent) => void;
@@ -44,6 +45,7 @@ function OperatorEvent({
isSelected, isSelected,
isPast, isPast,
selectedRef, selectedRef,
showStart,
subscribed, subscribed,
totalGap, totalGap,
onLongPress, onLongPress,
@@ -64,9 +66,8 @@ function OperatorEvent({
const operatorClasses = cx([ const operatorClasses = cx([
style.event, style.event,
isSelected ? style.running : null, isSelected && style.running,
subscribed ? style.subscribed : null, isPast && style.past,
isPast ? style.past : null,
]); ]);
return ( return (
@@ -75,9 +76,11 @@ function OperatorEvent({
<span className={style.cue}>{cue}</span> <span className={style.cue}>{cue}</span>
</div> </div>
<span className={style.mainField}>{main}</span> <span className={style.mainField}>
{showStart && <span className={style.plannedStart}>{millisToString(timeStart)}</span>}
{main}
</span>
<span className={style.secondaryField}>{secondary}</span> <span className={style.secondaryField}>{secondary}</span>
<OperatorEventSchedule <OperatorEventSchedule
timeStart={timeStart} timeStart={timeStart}
isPast={isPast} isPast={isPast}
@@ -67,6 +67,13 @@ export const getOperatorOptions = (customFields: CustomFields, timeFormat: strin
type: 'boolean', type: 'boolean',
defaultValue: false, defaultValue: false,
}, },
{
id: 'showStart',
title: 'Show planned start',
description: 'Whether to prepend the planned start to the items',
type: 'boolean',
defaultValue: false,
},
], ],
}, },
]; ];
@@ -78,6 +85,7 @@ type OperatorOptions = {
subscribe: string[]; subscribe: string[];
shouldEdit: boolean; shouldEdit: boolean;
hidePast: boolean; hidePast: boolean;
showStart: boolean;
}; };
/** /**
@@ -92,6 +100,7 @@ function getOptionsFromParams(searchParams: URLSearchParams): OperatorOptions {
subscribe: searchParams.getAll('subscribe'), subscribe: searchParams.getAll('subscribe'),
shouldEdit: isStringBoolean(searchParams.get('shouldEdit')), shouldEdit: isStringBoolean(searchParams.get('shouldEdit')),
hidePast: isStringBoolean(searchParams.get('hidePast')), hidePast: isStringBoolean(searchParams.get('hidePast')),
showStart: isStringBoolean(searchParams.get('showStart')),
}; };
} }