Skip to content

Commit

Permalink
refactor: compound timeline
Browse files Browse the repository at this point in the history
  • Loading branch information
cpvalente committed Oct 6, 2024
1 parent 6a55d13 commit ee7c9a3
Show file tree
Hide file tree
Showing 9 changed files with 82 additions and 126 deletions.
37 changes: 21 additions & 16 deletions apps/client/src/features/viewers/timeline/Timeline.module.scss
Original file line number Diff line number Diff line change
@@ -1,19 +1,15 @@
@use '../../../theme/viewerDefs' as *;

$timeline-entry-height: 20px;
$lane-height: 120px;
$timeline-height: 1rem;

.timeline {
flex: 1;
font-weight: 600;
color: $ui-white;
background-color: $ui-black;
}

.timelineEvents {
box-sizing: content-box;
box-shadow: inset 0 1rem 0 0 $gray-1100;
position: relative;
height: 100%;
}

.column {
Expand All @@ -23,17 +19,24 @@ $timeline-height: 1rem;
border-left: 1px solid $ui-black;
// avoiding content being larger than the view
height: calc(100% - 3rem);
}

// decorate timeline element
&::before {
content: '';
position: absolute;
box-sizing: content-box;
top: -$timeline-height;
left: 0;
right: 0;
height: $timeline-height;
background-color: $white-40;
// generate combined timeline
.timelineBlock {
height: $timeline-height;
background-color: $white-40;
width: 100%;

&[data-status='done'] {
&::before {
background-color: $active-red;
}
}

&[data-status='live'] {
&::before {
background-color: red;
}
}
}

Expand Down Expand Up @@ -69,6 +72,8 @@ $timeline-height: 1rem;
border-bottom: 2px solid $ui-black;
box-shadow: 0 0.25rem 0 0 var(--color, $gray-300);

// TODO: can I use has to avoid having this in multiple places?

&[data-status='done'] {
opacity: $opacity-disabled;
}
Expand Down
90 changes: 43 additions & 47 deletions apps/client/src/features/viewers/timeline/Timeline.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { isOntimeEvent, isPlayableEvent, MaybeNumber, OntimeRundown } from 'onti
import { checkIsNextDay, dayInMs, getLastEvent, MILLIS_PER_HOUR } from 'ontime-utils';

import TimelineMarkers from './timeline-markers/TimelineMarkers';
import TimelineProgressBar from './timeline-progress-bar/TimelineProgressBar';
import { getElementPosition, getEndHour, getStartHour } from './timeline.utils';
import { ProgressStatus, TimelineEntry } from './TimelineEntry';

Expand Down Expand Up @@ -39,57 +38,54 @@ function Timeline(props: TimelineProps) {
return (
<div className={style.timeline}>
<TimelineMarkers startHour={startHour} endHour={endHour} />
<TimelineProgressBar startHour={startHour} endHour={endHour} />
<div className={style.timelineEvents}>
{rundown.map((event) => {
// for now we dont render delays and blocks
if (!isOntimeEvent(event) || !isPlayableEvent(event)) {
return null;
}
{rundown.map((event) => {
// for now we dont render delays and blocks
if (!isOntimeEvent(event) || !isPlayableEvent(event)) {
return null;
}

// keep track of progress of rundown
if (eventStatus === 'live') {
eventStatus = 'future';
}
if (event.id === selectedEventId) {
eventStatus = 'live';
}
// keep track of progress of rundown
if (eventStatus === 'live') {
eventStatus = 'future';
}
if (event.id === selectedEventId) {
eventStatus = 'live';
}

// we only need to check for next day if we have a previous event
if (
previousEventStartTime !== null &&
checkIsNextDay(previousEventStartTime, event.timeStart, event.duration)
) {
elapsedDays++;
}
const normalisedStart = event.timeStart + elapsedDays * dayInMs;
// we only need to check for next day if we have a previous event
if (
previousEventStartTime !== null &&
checkIsNextDay(previousEventStartTime, event.timeStart, event.duration)
) {
elapsedDays++;
}
const normalisedStart = event.timeStart + elapsedDays * dayInMs;

const { left: elementLeftPosition, width: elementWidth } = getElementPosition(
startHour * MILLIS_PER_HOUR,
endHour * MILLIS_PER_HOUR,
normalisedStart + (event.delay ?? 0),
event.duration,
screenWidth,
);
const { left: elementLeftPosition, width: elementWidth } = getElementPosition(
startHour * MILLIS_PER_HOUR,
endHour * MILLIS_PER_HOUR,
normalisedStart + (event.delay ?? 0),
event.duration,
screenWidth,
);

// prepare values for next iteration
previousEventStartTime = normalisedStart;
// prepare values for next iteration
previousEventStartTime = normalisedStart;

return (
<TimelineEntry
key={event.id}
colour={event.colour}
delay={event.delay ?? 0}
duration={event.duration}
left={elementLeftPosition}
status={eventStatus}
start={normalisedStart} // dataset solves issues related to crossing midnight
title={event.title}
width={elementWidth}
/>
);
})}
</div>
return (
<TimelineEntry
key={event.id}
colour={event.colour}
delay={event.delay ?? 0}
duration={event.duration}
left={elementLeftPosition}
status={eventStatus}
start={normalisedStart} // dataset solves issues related to crossing midnight
title={event.title}
width={elementWidth}
/>
);
})}
</div>
);
}
4 changes: 3 additions & 1 deletion apps/client/src/features/viewers/timeline/TimelineEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,15 @@ export function TimelineEntry(props: TimelineEntryProps) {
return (
<div
className={columnClasses}
data-status={status}
style={{
'--color': colour,
'--lighter': lighterColour ?? '',
left: `${left}px`,
width: `${width}px`,
}}
>
<div className={style.timelineBlock} />
<div
className={contentClasses}
data-status={status}
Expand Down Expand Up @@ -76,7 +78,7 @@ interface TimelineEntryStatusProps {
start: number;
}

// we isolate this component to avoid isolate re-renders provoked by the clock changes
// extract component to isolate re-renders provoked by the clock changes
function TimelineEntryStatus(props: TimelineEntryStatusProps) {
const { status, start } = props;
const { clock, offset } = useTimelineStatus();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,9 @@ describe('getCSSPosition()', () => {
});
});

describe('makeTmelineSections', () => {
describe('makeTimelineSections', () => {
it('creates an array between the hours given, end excluded', () => {
const result = makeTimelineSections(11, 17);
expect(result).toEqual(['11:00', '12:00', '13:00', '14:00', '15:00', '16:00']);
});

it('wraps around midnight', () => {
const result = makeTimelineSections(22, 26);
expect(result).toEqual(['22:00', '23:00', '00:00', '01:00']);
expect(result).toEqual([11, 12, 13, 14, 15, 16]);
});
});
Original file line number Diff line number Diff line change
@@ -1,16 +1,17 @@
.markers {
position: absolute;
left: 0;
width: 100%;
color: $ui-white;
height: 100%;

display: flex;
height: 1rem;
line-height: 1rem;
margin-bottom: 0.25rem;
font-size: calc(1rem - 2px);
justify-content: space-evenly;

& > span {
flex-grow: 1;
border-left: 1px solid $white-7;
height: 100vh;

&:not(:first-child) {
border-left: 1px solid $white-7;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,17 @@ interface TimelineMarkersProps {
endHour: number;
}

/** Creates a line for every hour in the timeline */
export default function TimelineMarkers(props: TimelineMarkersProps) {
const { startHour, endHour } = props;

const elements = makeTimelineSections(startHour, endHour);

return (
<div className={style.markers}>
{elements.map((tag, index) => {
return <span key={`${index}-${tag}`}>{tag}</span>;
})}
{elements.map((tag) => (
<span key={tag} />
))}
</div>
);
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ export function getEndHour(endTime: number): number {
export function makeTimelineSections(firstHour: number, lastHour: number) {
const timelineSections = [];
for (let i = firstHour; i < lastHour; i++) {
timelineSections.push(removeSeconds(millisToString((i % 24) * MILLIS_PER_HOUR)));
timelineSections.push(i);
}
return timelineSections;
}
Expand Down

0 comments on commit ee7c9a3

Please sign in to comment.