mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-20 06:29:07 +00:00
refactor: extract time-to-end
This commit is contained in:
committed by
Carlos Valente
parent
41fe213ebb
commit
0f3feca7ab
@@ -150,6 +150,7 @@ export default function RundownEntry(props: RundownEntryProps) {
|
||||
if (data.type === SupportedEvent.Event) {
|
||||
return (
|
||||
<EventBlock
|
||||
eventId={data.id}
|
||||
eventIndex={eventIndex}
|
||||
cue={data.cue}
|
||||
timeStart={data.timeStart}
|
||||
@@ -157,7 +158,7 @@ export default function RundownEntry(props: RundownEntryProps) {
|
||||
duration={data.duration}
|
||||
timeStrategy={data.timeStrategy}
|
||||
linkStart={data.linkStart}
|
||||
eventId={data.id}
|
||||
isTimeToEnd={data.isTimeToEnd}
|
||||
isPublic={data.isPublic}
|
||||
endAction={data.endAction}
|
||||
timerType={data.timerType}
|
||||
|
||||
@@ -24,13 +24,14 @@ import RundownIndicators from './RundownIndicators';
|
||||
import style from './EventBlock.module.scss';
|
||||
|
||||
interface EventBlockProps {
|
||||
eventId: string;
|
||||
cue: string;
|
||||
timeStart: number;
|
||||
timeEnd: number;
|
||||
duration: number;
|
||||
timeStrategy: TimeStrategy;
|
||||
linkStart: MaybeString;
|
||||
eventId: string;
|
||||
isTimeToEnd: boolean;
|
||||
eventIndex: number;
|
||||
isPublic: boolean;
|
||||
endAction: EndAction;
|
||||
@@ -68,6 +69,7 @@ export default function EventBlock(props: EventBlockProps) {
|
||||
duration,
|
||||
timeStrategy,
|
||||
linkStart,
|
||||
isTimeToEnd,
|
||||
isPublic = true,
|
||||
eventIndex,
|
||||
endAction,
|
||||
@@ -286,6 +288,7 @@ export default function EventBlock(props: EventBlockProps) {
|
||||
timeEnd={timeEnd}
|
||||
duration={duration}
|
||||
linkStart={linkStart}
|
||||
isTimeToEnd={isTimeToEnd}
|
||||
timeStrategy={timeStrategy}
|
||||
eventId={eventId}
|
||||
eventIndex={eventIndex}
|
||||
|
||||
@@ -23,12 +23,13 @@ import EventBlockProgressBar from './composite/EventBlockProgressBar';
|
||||
import style from './EventBlock.module.scss';
|
||||
|
||||
interface EventBlockInnerProps {
|
||||
eventId: string;
|
||||
timeStart: number;
|
||||
timeEnd: number;
|
||||
duration: number;
|
||||
timeStrategy: TimeStrategy;
|
||||
linkStart: MaybeString;
|
||||
eventId: string;
|
||||
isTimeToEnd: boolean;
|
||||
eventIndex: number;
|
||||
isPublic: boolean;
|
||||
endAction: EndAction;
|
||||
@@ -43,14 +44,15 @@ interface EventBlockInnerProps {
|
||||
isRolling: boolean;
|
||||
}
|
||||
|
||||
const EventBlockInner = (props: EventBlockInnerProps) => {
|
||||
function EventBlockInner(props: EventBlockInnerProps) {
|
||||
const {
|
||||
eventId,
|
||||
timeStart,
|
||||
timeEnd,
|
||||
duration,
|
||||
timeStrategy,
|
||||
linkStart,
|
||||
eventId,
|
||||
isTimeToEnd,
|
||||
isPublic = true,
|
||||
endAction,
|
||||
timerType,
|
||||
@@ -91,7 +93,7 @@ const EventBlockInner = (props: EventBlockInnerProps) => {
|
||||
delay={delay}
|
||||
timeStrategy={timeStrategy}
|
||||
linkStart={linkStart}
|
||||
timerType={timerType}
|
||||
isTimeToEnd={isTimeToEnd}
|
||||
/>
|
||||
</div>
|
||||
<div className={style.titleSection}>
|
||||
@@ -122,6 +124,11 @@ const EventBlockInner = (props: EventBlockInnerProps) => {
|
||||
<EndActionIcon action={endAction} className={style.statusIcon} />
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip label={`${isTimeToEnd ? 'Time to End' : 'Count from start'}`} openDelay={tooltipDelayMid}>
|
||||
<span>
|
||||
<IoFlag className={`${style.statusIcon} ${isTimeToEnd ? style.active : style.disabled}`} />
|
||||
</span>
|
||||
</Tooltip>
|
||||
<Tooltip label={`${isPublic ? 'Event is public' : 'Event is private'}`} openDelay={tooltipDelayMid}>
|
||||
<span>
|
||||
<IoPeople className={`${style.statusIcon} ${isPublic ? style.active : style.disabled}`} />
|
||||
@@ -131,7 +138,7 @@ const EventBlockInner = (props: EventBlockInnerProps) => {
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default memo(EventBlockInner);
|
||||
|
||||
@@ -162,9 +169,5 @@ function TimerIcon(props: { type: TimerType; className: string }) {
|
||||
if (type === TimerType.None) {
|
||||
return <IoBan className={className} />;
|
||||
}
|
||||
if (type === TimerType.TimeToEnd) {
|
||||
const classes = cx([style.active, className]);
|
||||
return <IoFlag className={classes} />;
|
||||
}
|
||||
return <IoArrowDown className={className} />;
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
flex: 1;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 2rem;
|
||||
gap: 1rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.decorated {
|
||||
@@ -63,6 +64,7 @@
|
||||
gap: 0.5rem;
|
||||
max-width: max-content;
|
||||
cursor: pointer;
|
||||
height: 30px; // manually match the height of a text input
|
||||
}
|
||||
|
||||
.inline {
|
||||
|
||||
@@ -83,6 +83,7 @@ export default function EventEditor() {
|
||||
duration={event.duration}
|
||||
timeStrategy={event.timeStrategy}
|
||||
linkStart={event.linkStart}
|
||||
isTimeToEnd={event.isTimeToEnd}
|
||||
delay={event.delay ?? 0}
|
||||
isPublic={event.isPublic}
|
||||
endAction={event.endAction}
|
||||
|
||||
@@ -18,6 +18,7 @@ interface EventEditorTimesProps {
|
||||
duration: number;
|
||||
timeStrategy: TimeStrategy;
|
||||
linkStart: MaybeString;
|
||||
isTimeToEnd: boolean;
|
||||
delay: number;
|
||||
isPublic: boolean;
|
||||
endAction: EndAction;
|
||||
@@ -26,9 +27,9 @@ interface EventEditorTimesProps {
|
||||
timeDanger: number;
|
||||
}
|
||||
|
||||
type HandledActions = 'timerType' | 'endAction' | 'isPublic' | 'timeWarning' | 'timeDanger';
|
||||
type HandledActions = 'isTimeToEnd' | 'timerType' | 'endAction' | 'isPublic' | 'timeWarning' | 'timeDanger';
|
||||
|
||||
const EventEditorTimes = (props: EventEditorTimesProps) => {
|
||||
function EventEditorTimes(props: EventEditorTimesProps) {
|
||||
const {
|
||||
eventId,
|
||||
timeStart,
|
||||
@@ -36,6 +37,7 @@ const EventEditorTimes = (props: EventEditorTimesProps) => {
|
||||
duration,
|
||||
timeStrategy,
|
||||
linkStart,
|
||||
isTimeToEnd,
|
||||
delay,
|
||||
isPublic,
|
||||
endAction,
|
||||
@@ -51,6 +53,11 @@ const EventEditorTimes = (props: EventEditorTimesProps) => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (field === 'isTimeToEnd') {
|
||||
updateEvent({ id: eventId, isTimeToEnd: !(value as boolean) });
|
||||
return;
|
||||
}
|
||||
|
||||
if (field === 'timeWarning' || field === 'timeDanger') {
|
||||
const newTime = parseUserTime(value as string);
|
||||
updateEvent({ id: eventId, [field]: newTime });
|
||||
@@ -71,95 +78,115 @@ const EventEditorTimes = (props: EventEditorTimesProps) => {
|
||||
: '';
|
||||
|
||||
return (
|
||||
<div className={style.column}>
|
||||
<div>
|
||||
<Editor.Label>Event schedule</Editor.Label>
|
||||
<div className={style.inline}>
|
||||
<TimeInputFlow
|
||||
eventId={eventId}
|
||||
timeStart={timeStart}
|
||||
timeEnd={timeEnd}
|
||||
duration={duration}
|
||||
timeStrategy={timeStrategy}
|
||||
linkStart={linkStart}
|
||||
delay={delay}
|
||||
timerType={timerType}
|
||||
/>
|
||||
<>
|
||||
<div className={style.column}>
|
||||
<div>
|
||||
<Editor.Label>Event schedule</Editor.Label>
|
||||
<div className={style.inline}>
|
||||
<TimeInputFlow
|
||||
eventId={eventId}
|
||||
timeStart={timeStart}
|
||||
timeEnd={timeEnd}
|
||||
duration={duration}
|
||||
timeStrategy={timeStrategy}
|
||||
linkStart={linkStart}
|
||||
delay={delay}
|
||||
isTimeToEnd={isTimeToEnd}
|
||||
/>
|
||||
</div>
|
||||
<div className={style.delayLabel}>{delayLabel}</div>
|
||||
</div>
|
||||
<div className={style.delayLabel}>{delayLabel}</div>
|
||||
</div>
|
||||
|
||||
<div className={style.splitTwo}>
|
||||
<div>
|
||||
<Editor.Label htmlFor='timeWarning'>Warning Time</Editor.Label>
|
||||
<TimeInput
|
||||
id='timeWarning'
|
||||
name='timeWarning'
|
||||
submitHandler={handleSubmit}
|
||||
time={timeWarning}
|
||||
placeholder='Duration'
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Editor.Label htmlFor='timerType'>Timer Type</Editor.Label>
|
||||
<Select
|
||||
size='sm'
|
||||
id='timerType'
|
||||
name='timerType'
|
||||
value={timerType}
|
||||
onChange={(event) => handleSubmit('timerType', event.target.value)}
|
||||
variant='ontime'
|
||||
>
|
||||
<option value={TimerType.CountDown}>Count down</option>
|
||||
<option value={TimerType.CountUp}>Count up</option>
|
||||
<option value={TimerType.TimeToEnd}>Time to end</option>
|
||||
<option value={TimerType.Clock}>Clock</option>
|
||||
<option value={TimerType.None}>None</option>
|
||||
</Select>
|
||||
</div>
|
||||
<div>
|
||||
<Editor.Label htmlFor='timeDanger'>Danger Time</Editor.Label>
|
||||
<TimeInput
|
||||
id='timeDanger'
|
||||
name='timeDanger'
|
||||
submitHandler={handleSubmit}
|
||||
time={timeDanger}
|
||||
placeholder='Duration'
|
||||
/>
|
||||
</div>
|
||||
<div>
|
||||
<Editor.Label htmlFor='endAction'>End Action</Editor.Label>
|
||||
<Select
|
||||
id='endAction'
|
||||
size='sm'
|
||||
name='endAction'
|
||||
value={endAction}
|
||||
onChange={(event) => handleSubmit('endAction', event.target.value)}
|
||||
variant='ontime'
|
||||
>
|
||||
<option value={EndAction.None}>None</option>
|
||||
<option value={EndAction.Stop}>Stop</option>
|
||||
<option value={EndAction.LoadNext}>Load Next</option>
|
||||
<option value={EndAction.PlayNext}>Play Next</option>
|
||||
</Select>
|
||||
<Editor.Title>Event behaviour</Editor.Title>
|
||||
<div className={style.splitTwo}>
|
||||
<div>
|
||||
<Editor.Label htmlFor='endAction'>End Action</Editor.Label>
|
||||
<Select
|
||||
id='endAction'
|
||||
size='sm'
|
||||
name='endAction'
|
||||
value={endAction}
|
||||
onChange={(event) => handleSubmit('endAction', event.target.value)}
|
||||
variant='ontime'
|
||||
>
|
||||
<option value={EndAction.None}>None</option>
|
||||
<option value={EndAction.Stop}>Stop rundown</option>
|
||||
<option value={EndAction.LoadNext}>Load next event</option>
|
||||
<option value={EndAction.PlayNext}>Play next event</option>
|
||||
</Select>
|
||||
</div>
|
||||
<div>
|
||||
<Editor.Label htmlFor='timeToEnd'>Target Event Scheduled End</Editor.Label>
|
||||
<Editor.Label className={style.switchLabel}>
|
||||
<Switch
|
||||
id='timeToEnd'
|
||||
size='md'
|
||||
isChecked={isTimeToEnd}
|
||||
onChange={() => handleSubmit('isTimeToEnd', isTimeToEnd)}
|
||||
variant='ontime'
|
||||
/>
|
||||
{isTimeToEnd ? 'On' : 'Off'}
|
||||
</Editor.Label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div className={style.column}>
|
||||
<Editor.Title>Display options</Editor.Title>
|
||||
<div className={style.splitTwo}>
|
||||
<div>
|
||||
<Editor.Label htmlFor='timerType'>Timer Type</Editor.Label>
|
||||
<Select
|
||||
size='sm'
|
||||
id='timerType'
|
||||
name='timerType'
|
||||
value={timerType}
|
||||
onChange={(event) => handleSubmit('timerType', event.target.value)}
|
||||
variant='ontime'
|
||||
>
|
||||
<option value={TimerType.CountDown}>Count down</option>
|
||||
<option value={TimerType.CountUp}>Count up</option>
|
||||
<option value={TimerType.Clock}>Clock</option>
|
||||
<option value={TimerType.None}>None</option>
|
||||
</Select>
|
||||
</div>
|
||||
<div>
|
||||
<Editor.Label htmlFor='timeWarning'>Warning Time</Editor.Label>
|
||||
<TimeInput
|
||||
id='timeWarning'
|
||||
name='timeWarning'
|
||||
submitHandler={handleSubmit}
|
||||
time={timeWarning}
|
||||
placeholder='Duration'
|
||||
/>
|
||||
</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>
|
||||
<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
|
||||
id='timeDanger'
|
||||
name='timeDanger'
|
||||
submitHandler={handleSubmit}
|
||||
time={timeDanger}
|
||||
placeholder='Duration'
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default memo(EventEditorTimes);
|
||||
|
||||
@@ -29,6 +29,7 @@ const EventEditorTitles = (props: EventEditorTitlesProps) => {
|
||||
|
||||
return (
|
||||
<div className={style.column}>
|
||||
<Editor.Title>Event data</Editor.Title>
|
||||
<div className={style.splitTwo}>
|
||||
<div>
|
||||
<Editor.Label htmlFor='eventId'>Event ID (read only)</Editor.Label>
|
||||
|
||||
@@ -5,7 +5,7 @@ import { IoLink } from '@react-icons/all-files/io5/IoLink';
|
||||
import { IoLockClosed } from '@react-icons/all-files/io5/IoLockClosed';
|
||||
import { IoLockOpenOutline } from '@react-icons/all-files/io5/IoLockOpenOutline';
|
||||
import { IoUnlink } from '@react-icons/all-files/io5/IoUnlink';
|
||||
import { MaybeString, TimerType, TimeStrategy } from 'ontime-types';
|
||||
import { MaybeString, TimeStrategy } from 'ontime-types';
|
||||
|
||||
import TimeInputWithButton from '../../../common/components/input/time-input/TimeInputWithButton';
|
||||
import { useEventAction } from '../../../common/hooks/useEventAction';
|
||||
@@ -16,19 +16,19 @@ import style from './TimeInputFlow.module.scss';
|
||||
|
||||
interface EventBlockTimerProps {
|
||||
eventId: string;
|
||||
isTimeToEnd: boolean;
|
||||
timeStart: number;
|
||||
timeEnd: number;
|
||||
duration: number;
|
||||
timeStrategy: TimeStrategy;
|
||||
linkStart: MaybeString;
|
||||
delay: number;
|
||||
timerType: TimerType;
|
||||
}
|
||||
|
||||
type TimeActions = 'timeStart' | 'timeEnd' | 'duration';
|
||||
|
||||
const TimeInputFlow = (props: EventBlockTimerProps) => {
|
||||
const { eventId, timeStart, timeEnd, duration, timeStrategy, linkStart, delay, timerType } = props;
|
||||
function TimeInputFlow(props: EventBlockTimerProps) {
|
||||
const { eventId, isTimeToEnd, timeStart, timeEnd, duration, timeStrategy, linkStart, delay } = props;
|
||||
const { updateEvent, updateTimer } = useEventAction();
|
||||
|
||||
// In sync with EventEditorTimes
|
||||
@@ -49,8 +49,8 @@ const TimeInputFlow = (props: EventBlockTimerProps) => {
|
||||
warnings.push('Over midnight');
|
||||
}
|
||||
|
||||
if (timerType === TimerType.TimeToEnd) {
|
||||
warnings.push('Time to end');
|
||||
if (isTimeToEnd) {
|
||||
warnings.push('Target event scheduled end');
|
||||
}
|
||||
|
||||
const hasDelay = delay !== 0;
|
||||
@@ -128,6 +128,6 @@ const TimeInputFlow = (props: EventBlockTimerProps) => {
|
||||
)}
|
||||
</>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
export default memo(TimeInputFlow);
|
||||
|
||||
Reference in New Issue
Block a user