mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-23 16:09:11 +00:00
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:
committed by
Carlos Valente
parent
07074260a4
commit
3c7e061e51
@@ -242,13 +242,7 @@ export default function EventBlock(props: EventBlockProps) {
|
|||||||
onContextMenu={onContextMenu}
|
onContextMenu={onContextMenu}
|
||||||
id='event-block'
|
id='event-block'
|
||||||
>
|
>
|
||||||
<RundownIndicators
|
<RundownIndicators timeStart={timeStart} previousStart={previousStart} previousEnd={previousEnd} delay={delay} />
|
||||||
timeStart={timeStart}
|
|
||||||
timeEnd={timeEnd}
|
|
||||||
previousStart={previousStart}
|
|
||||||
previousEnd={previousEnd}
|
|
||||||
delay={delay}
|
|
||||||
/>
|
|
||||||
|
|
||||||
<div className={style.binder} style={{ ...binderColours }} tabIndex={-1}>
|
<div className={style.binder} style={{ ...binderColours }} tabIndex={-1}>
|
||||||
<span className={style.drag} ref={handleRef} {...dragAttributes} {...dragListeners}>
|
<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}`;
|
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(
|
export function formatOverlap(
|
||||||
previousStart: MaybeNumber,
|
previousStart: MaybeNumber,
|
||||||
previousEnd: MaybeNumber,
|
previousEnd: MaybeNumber,
|
||||||
timeStart: number,
|
timeStart: number,
|
||||||
timeEnd: number,
|
|
||||||
): string | undefined {
|
): string | undefined {
|
||||||
if (previousEnd === null) return;
|
const noPreviousElement = previousEnd === null || previousStart === null;
|
||||||
|
if (noPreviousElement) return;
|
||||||
|
|
||||||
const overlap = previousEnd - timeStart;
|
const overlap = previousEnd - timeStart;
|
||||||
if (overlap === 0) return;
|
if (overlap === 0) return;
|
||||||
|
|
||||||
if (previousStart && timeStart < previousEnd) {
|
const previousCrossMidnight = previousStart > previousEnd;
|
||||||
const overlap = timeEnd - previousStart;
|
const isNextDay = previousCrossMidnight
|
||||||
if (overlap > 0) {
|
? checkIsNextDay(previousEnd, timeStart) || previousEnd == 0 // exception for when previousEnd is precisely midnight
|
||||||
const overlapString = removeLeadingZero(millisToString(Math.abs(overlap)));
|
: checkIsNextDay(previousStart, timeStart);
|
||||||
return `Overlap ${overlapString}`;
|
|
||||||
}
|
const correctedPreviousEnd = previousCrossMidnight ? previousEnd + dayInMs : previousEnd;
|
||||||
const gap = timeStart + dayInMs - previousEnd;
|
|
||||||
|
if (isNextDay) {
|
||||||
|
const gap = dayInMs - correctedPreviousEnd + timeStart;
|
||||||
|
if (gap === 0) return;
|
||||||
const gapString = removeLeadingZero(millisToString(Math.abs(gap)));
|
const gapString = removeLeadingZero(millisToString(Math.abs(gap)));
|
||||||
return `Gap ${gapString} (next day)`;
|
return `Gap ${gapString} (next day)`;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,16 +6,15 @@ import style from './RundownIndicators.module.scss';
|
|||||||
|
|
||||||
interface RundownIndicatorProps {
|
interface RundownIndicatorProps {
|
||||||
timeStart: number;
|
timeStart: number;
|
||||||
timeEnd: number;
|
|
||||||
previousStart: MaybeNumber;
|
previousStart: MaybeNumber;
|
||||||
previousEnd: MaybeNumber;
|
previousEnd: MaybeNumber;
|
||||||
delay: number;
|
delay: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default function RundownIndicators(props: RundownIndicatorProps) {
|
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);
|
const hasDelay = formatDelay(timeStart, delay);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { MILLIS_PER_HOUR } from 'ontime-utils';
|
||||||
|
|
||||||
import { formatDelay, formatOverlap } from '../EventBlock.utils';
|
import { formatDelay, formatOverlap } from '../EventBlock.utils';
|
||||||
|
|
||||||
describe('formatDelay()', () => {
|
describe('formatDelay()', () => {
|
||||||
@@ -14,35 +16,47 @@ describe('formatOverlap()', () => {
|
|||||||
const previousStart = 0;
|
const previousStart = 0;
|
||||||
const previousEnd = 60000; // 1 min
|
const previousEnd = 60000; // 1 min
|
||||||
const timeStart = 30000; // 30 sec
|
const timeStart = 30000; // 30 sec
|
||||||
const timeEnd = 90000; // 1:30 min
|
const result = formatOverlap(previousStart, previousEnd, timeStart);
|
||||||
const result = formatOverlap(previousStart, previousEnd, timeStart, timeEnd);
|
|
||||||
expect(result).toEqual('Overlap 0:30');
|
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', () => {
|
it('handles events the day after, without overlap', () => {
|
||||||
const previousStart = new Date(0).setUTCHours(11);
|
const previousStart = 11 * MILLIS_PER_HOUR;
|
||||||
const previousEnd = new Date(0).setUTCHours(12);
|
const previousEnd = 12 * MILLIS_PER_HOUR;
|
||||||
const timeStart = new Date(0).setUTCHours(6);
|
const timeStart = 6 * MILLIS_PER_HOUR;
|
||||||
const timeEnd = new Date(0).setUTCHours(10);
|
const result = formatOverlap(previousStart, previousEnd, timeStart);
|
||||||
const result = formatOverlap(previousStart, previousEnd, timeStart, timeEnd);
|
|
||||||
expect(result).toBe('Gap 18:00:00 (next day)');
|
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', () => {
|
it('handles events the day after, with gap', () => {
|
||||||
const previousStart = new Date(0).setUTCHours(17);
|
const previousStart = 17 * MILLIS_PER_HOUR;
|
||||||
const previousEnd = new Date(0).setUTCHours(23);
|
const previousEnd = 23 * MILLIS_PER_HOUR;
|
||||||
const timeStart = new Date(0).setUTCHours(9);
|
const timeStart = 9 * MILLIS_PER_HOUR;
|
||||||
const timeEnd = new Date(0).setUTCHours(11);
|
const result = formatOverlap(previousStart, previousEnd, timeStart);
|
||||||
const result = formatOverlap(previousStart, previousEnd, timeStart, timeEnd);
|
|
||||||
expect(result).toBe('Gap 10:00:00 (next day)');
|
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');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user