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;
}