refactor: improve detection of day after

fix: prevent mutation of initial object

refactor: download project file

Update apps/client/src/features/rundown/event-block/EventBlock.utils.ts

Co-authored-by: Alex Christoffer Rasmussen <ac@omnivox.dk>

Update apps/client/src/features/rundown/event-block/__tests__/EventBlock.utils.test.ts

Co-authored-by: Alex Christoffer Rasmussen <ac@omnivox.dk>
This commit is contained in:
Carlos Valente
2024-05-10 21:35:12 +02:00
committed by Carlos Valente
parent 07074260a4
commit 3c7e061e51
4 changed files with 64 additions and 40 deletions
@@ -242,13 +242,7 @@ export default function EventBlock(props: EventBlockProps) {
onContextMenu={onContextMenu}
id='event-block'
>
<RundownIndicators
timeStart={timeStart}
timeEnd={timeEnd}
previousStart={previousStart}
previousEnd={previousEnd}
delay={delay}
/>
<RundownIndicators timeStart={timeStart} previousStart={previousStart} previousEnd={previousEnd} delay={delay} />
<div className={style.binder} style={{ ...binderColours }} tabIndex={-1}>
<span className={style.drag} ref={handleRef} {...dragAttributes} {...dragListeners}>
@@ -10,24 +10,41 @@ export function formatDelay(timeStart: number, delay: number): string | undefine
return `New start ${timeTag}`;
}
/**
* Utility function checks whether a given event is the day after from its predecessor
* We consider an event to be the day after, if it begins before the start of the previous
* @example day after
* // 09:00 - 10:00
* // 08:00 - 10:30 <--- day after
* @example same day
* // 09:00 - 10:00
* // 09:30 - 10:30 <--- same day
*/
function checkIsNextDay(previousStart: number, timeStart: number): boolean {
return timeStart < previousStart;
}
export function formatOverlap(
previousStart: MaybeNumber,
previousEnd: MaybeNumber,
timeStart: number,
timeEnd: number,
): string | undefined {
if (previousEnd === null) return;
const noPreviousElement = previousEnd === null || previousStart === null;
if (noPreviousElement) return;
const overlap = previousEnd - timeStart;
if (overlap === 0) return;
if (previousStart && timeStart < previousEnd) {
const overlap = timeEnd - previousStart;
if (overlap > 0) {
const overlapString = removeLeadingZero(millisToString(Math.abs(overlap)));
return `Overlap ${overlapString}`;
}
const gap = timeStart + dayInMs - previousEnd;
const previousCrossMidnight = previousStart > previousEnd;
const isNextDay = previousCrossMidnight
? checkIsNextDay(previousEnd, timeStart) || previousEnd == 0 // exception for when previousEnd is precisely midnight
: checkIsNextDay(previousStart, timeStart);
const correctedPreviousEnd = previousCrossMidnight ? previousEnd + dayInMs : previousEnd;
if (isNextDay) {
const gap = dayInMs - correctedPreviousEnd + timeStart;
if (gap === 0) return;
const gapString = removeLeadingZero(millisToString(Math.abs(gap)));
return `Gap ${gapString} (next day)`;
}
@@ -6,16 +6,15 @@ import style from './RundownIndicators.module.scss';
interface RundownIndicatorProps {
timeStart: number;
timeEnd: number;
previousStart: MaybeNumber;
previousEnd: MaybeNumber;
delay: number;
}
export default function RundownIndicators(props: RundownIndicatorProps) {
const { timeStart, timeEnd, previousStart, previousEnd, delay } = props;
const { timeStart, previousStart, previousEnd, delay } = props;
const hasOverlap = formatOverlap(previousStart, previousEnd, timeStart, timeEnd);
const hasOverlap = formatOverlap(previousStart, previousEnd, timeStart);
const hasDelay = formatDelay(timeStart, delay);
return (
@@ -1,3 +1,5 @@
import { MILLIS_PER_HOUR } from 'ontime-utils';
import { formatDelay, formatOverlap } from '../EventBlock.utils';
describe('formatDelay()', () => {
@@ -14,35 +16,47 @@ describe('formatOverlap()', () => {
const previousStart = 0;
const previousEnd = 60000; // 1 min
const timeStart = 30000; // 30 sec
const timeEnd = 90000; // 1:30 min
const result = formatOverlap(previousStart, previousEnd, timeStart, timeEnd);
const result = formatOverlap(previousStart, previousEnd, timeStart);
expect(result).toEqual('Overlap 0:30');
});
it('bug #949 recognises an overlap between two times', () => {
const previousStart = 46800000; // 13:00:00
const previousEnd = 48600000; // 13:30:00
const timeStart = 48300000; // 13:25:00
const result = formatOverlap(previousStart, previousEnd, timeStart);
expect(result).toEqual('Overlap 5:00');
});
it('handles events the day after, without overlap', () => {
const previousStart = new Date(0).setUTCHours(11);
const previousEnd = new Date(0).setUTCHours(12);
const timeStart = new Date(0).setUTCHours(6);
const timeEnd = new Date(0).setUTCHours(10);
const result = formatOverlap(previousStart, previousEnd, timeStart, timeEnd);
const previousStart = 11 * MILLIS_PER_HOUR;
const previousEnd = 12 * MILLIS_PER_HOUR;
const timeStart = 6 * MILLIS_PER_HOUR;
const result = formatOverlap(previousStart, previousEnd, timeStart);
expect(result).toBe('Gap 18:00:00 (next day)');
});
it('handles events the day after, with overlap', () => {
const previousStart = new Date(0).setUTCHours(9);
const previousEnd = new Date(0).setUTCHours(10);
const timeStart = new Date(0).setUTCHours(6);
const timeEnd = new Date(0).setUTCHours(11);
const result = formatOverlap(previousStart, previousEnd, timeStart, timeEnd);
expect(result).toBe('Overlap 02:00:00');
});
it('handles events the day after, with gap', () => {
const previousStart = new Date(0).setUTCHours(17);
const previousEnd = new Date(0).setUTCHours(23);
const timeStart = new Date(0).setUTCHours(9);
const timeEnd = new Date(0).setUTCHours(11);
const result = formatOverlap(previousStart, previousEnd, timeStart, timeEnd);
const previousStart = 17 * MILLIS_PER_HOUR;
const previousEnd = 23 * MILLIS_PER_HOUR;
const timeStart = 9 * MILLIS_PER_HOUR;
const result = formatOverlap(previousStart, previousEnd, timeStart);
expect(result).toBe('Gap 10:00:00 (next day)');
});
it('handles events the day after, with previous ending at midnight', () => {
const previousStart = 23 * MILLIS_PER_HOUR; // 23:00:00
const previousEnd = 0; // 00:00:00
const timeStart = 1 * MILLIS_PER_HOUR; // 01:00:00
const result = formatOverlap(previousStart, previousEnd, timeStart);
expect(result).toBe('Gap 01:00:00 (next day)');
});
it('handles events the day after, with previous ending over midnight', () => {
const previousStart = 23 * MILLIS_PER_HOUR;
const previousEnd = 1 * MILLIS_PER_HOUR;
const timeStart = 2 * MILLIS_PER_HOUR;
const result = formatOverlap(previousStart, previousEnd, timeStart);
expect(result).toBe('Gap 01:00:00');
});
});