diff --git a/apps/client/src/features/viewers/timeline/Timeline.module.scss b/apps/client/src/features/viewers/timeline/Timeline.module.scss index 430bb9ee47..7aafe09a32 100644 --- a/apps/client/src/features/viewers/timeline/Timeline.module.scss +++ b/apps/client/src/features/viewers/timeline/Timeline.module.scss @@ -1,39 +1,40 @@ @use '../../../theme/viewerDefs' as *; -$timeline-entry-height: 20px; -$lane-height: 120px; $timeline-height: 1rem; +$view-background: $ui-black; .timeline { flex: 1; font-weight: 600; color: $ui-white; - background-color: $ui-black; -} - -.timelineEvents { + background-color: $view-background; + box-sizing: content-box; + // create progress background + box-shadow: inset 0 1rem 0 0 $gray-1100; position: relative; - height: 100%; } .column { display: flex; flex-direction: column; position: absolute; - border-left: 1px solid $ui-black; + border-left: 1px solid $view-background; // avoiding content being larger than the view height: calc(100% - 3rem); +} + +// generate combined timeline +.timelineBlock { + height: $timeline-height; + background: $white-60; + width: 100%; - // 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; + &[data-status='done'] { + background: $active-red; + } + + &[data-status='live'] { + background: linear-gradient(to right, $active-red var(--progress, 0%), $white-60 var(--progress, 0%)); } } @@ -66,7 +67,8 @@ $timeline-height: 1rem; line-height: 1rem; background-color: var(--lighter, $viewer-card-bg-color); - border-bottom: 2px solid $ui-black; + border-bottom: 2px solid $view-background; + border-top: 2px solid $view-background; box-shadow: 0 0.25rem 0 0 var(--color, $gray-300); &[data-status='done'] { diff --git a/apps/client/src/features/viewers/timeline/Timeline.tsx b/apps/client/src/features/viewers/timeline/Timeline.tsx index a8463f36d1..6cfeb8ab69 100644 --- a/apps/client/src/features/viewers/timeline/Timeline.tsx +++ b/apps/client/src/features/viewers/timeline/Timeline.tsx @@ -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'; @@ -39,57 +38,54 @@ function Timeline(props: TimelineProps) { return (
- -
- {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 ( - - ); - })} -
+ return ( + + ); + })}
); } diff --git a/apps/client/src/features/viewers/timeline/TimelineEntry.tsx b/apps/client/src/features/viewers/timeline/TimelineEntry.tsx index 433af75b82..6435400161 100644 --- a/apps/client/src/features/viewers/timeline/TimelineEntry.tsx +++ b/apps/client/src/features/viewers/timeline/TimelineEntry.tsx @@ -1,4 +1,5 @@ -import { useTimelineStatus } from '../../../common/hooks/useSocket'; +import { useTimelineStatus, useTimer } from '../../../common/hooks/useSocket'; +import { getProgress } from '../../../common/utils/getProgress'; import { alpha, cx } from '../../../common/utils/styleUtils'; import { formatDuration, formatTime } from '../../../common/utils/time'; import { useTranslation } from '../../../translation/TranslationProvider'; @@ -48,6 +49,7 @@ export function TimelineEntry(props: TimelineEntryProps) { width: `${width}px`, }} > + {status === 'live' ? :
}
{statusText}
; } + +/** Generates a block level progress bar */ +function ActiveBlock() { + const { current, duration } = useTimer(); + const progress = getProgress(current, duration); + return
; +} diff --git a/apps/client/src/features/viewers/timeline/__tests__/timeline.utils.test.ts b/apps/client/src/features/viewers/timeline/__tests__/timeline.utils.test.ts index a522b36ef1..f99d699eb0 100644 --- a/apps/client/src/features/viewers/timeline/__tests__/timeline.utils.test.ts +++ b/apps/client/src/features/viewers/timeline/__tests__/timeline.utils.test.ts @@ -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]); }); }); diff --git a/apps/client/src/features/viewers/timeline/timeline-markers/TimelineMarkers.module.scss b/apps/client/src/features/viewers/timeline/timeline-markers/TimelineMarkers.module.scss index b2961ee42c..8969a2d7e1 100644 --- a/apps/client/src/features/viewers/timeline/timeline-markers/TimelineMarkers.module.scss +++ b/apps/client/src/features/viewers/timeline/timeline-markers/TimelineMarkers.module.scss @@ -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; + } } } diff --git a/apps/client/src/features/viewers/timeline/timeline-markers/TimelineMarkers.tsx b/apps/client/src/features/viewers/timeline/timeline-markers/TimelineMarkers.tsx index 2b91b3107e..96b8a35dfb 100644 --- a/apps/client/src/features/viewers/timeline/timeline-markers/TimelineMarkers.tsx +++ b/apps/client/src/features/viewers/timeline/timeline-markers/TimelineMarkers.tsx @@ -7,6 +7,7 @@ interface TimelineMarkersProps { endHour: number; } +/** Creates a line for every hour in the timeline */ export default function TimelineMarkers(props: TimelineMarkersProps) { const { startHour, endHour } = props; @@ -14,9 +15,9 @@ export default function TimelineMarkers(props: TimelineMarkersProps) { return (
- {elements.map((tag, index) => { - return {tag}; - })} + {elements.map((tag) => ( + + ))}
); } diff --git a/apps/client/src/features/viewers/timeline/timeline-progress-bar/TimelineProgressBar.module.scss b/apps/client/src/features/viewers/timeline/timeline-progress-bar/TimelineProgressBar.module.scss deleted file mode 100644 index 1997b1a099..0000000000 --- a/apps/client/src/features/viewers/timeline/timeline-progress-bar/TimelineProgressBar.module.scss +++ /dev/null @@ -1,19 +0,0 @@ -.progressBar { - width: 100%; - height: 1rem; - position: relative; - - background-color: $gray-1000; -} - -.progress { - height: 100%; - position: absolute; - left: 0; - top: 0; - z-index: 2; - - background-color: $active-red; - transition-duration: 0.3s; - transition-property: width; -} diff --git a/apps/client/src/features/viewers/timeline/timeline-progress-bar/TimelineProgressBar.tsx b/apps/client/src/features/viewers/timeline/timeline-progress-bar/TimelineProgressBar.tsx deleted file mode 100644 index 53480800c9..0000000000 --- a/apps/client/src/features/viewers/timeline/timeline-progress-bar/TimelineProgressBar.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import { MILLIS_PER_HOUR } from 'ontime-utils'; - -import { useClock } from '../../../../common/hooks/useSocket'; -import { getRelativePositionX } from '../timeline.utils'; - -import style from './TimelineProgressBar.module.scss'; - -interface ProgressBarProps { - startHour: number; - endHour: number; -} - -export default function ProgressBar(props: ProgressBarProps) { - const { startHour, endHour } = props; - // TODO: how to account for days? - const { clock } = useClock(); - - const width = getRelativePositionX(startHour * MILLIS_PER_HOUR, endHour * MILLIS_PER_HOUR, clock); - - return ( -
-
-
- ); -} diff --git a/apps/client/src/features/viewers/timeline/timeline.utils.ts b/apps/client/src/features/viewers/timeline/timeline.utils.ts index 1903abaf84..bc6bcfa9cd 100644 --- a/apps/client/src/features/viewers/timeline/timeline.utils.ts +++ b/apps/client/src/features/viewers/timeline/timeline.utils.ts @@ -9,8 +9,6 @@ import { getTimeFromPrevious, isNewLatest, MILLIS_PER_HOUR, - millisToString, - removeSeconds, } from 'ontime-utils'; import { clamp } from '../../../common/utils/math'; @@ -71,7 +69,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; }