diff --git a/apps/cli/package.json b/apps/cli/package.json
index 633e6790c6..0610bc693f 100644
--- a/apps/cli/package.json
+++ b/apps/cli/package.json
@@ -1,6 +1,6 @@
{
"name": "@getontime/cli",
- "version": "3.3.2",
+ "version": "3.4.0-alpha-timeline.2",
"author": "Carlos Valente",
"description": "Time keeping for live events",
"repository": "https://github.com/cpvalente/ontime",
diff --git a/apps/client/package.json b/apps/client/package.json
index a369376d35..3260b95665 100644
--- a/apps/client/package.json
+++ b/apps/client/package.json
@@ -1,6 +1,6 @@
{
"name": "ontime-ui",
- "version": "3.3.2",
+ "version": "3.4.0-alpha-timeline.2",
"private": true,
"type": "module",
"dependencies": {
diff --git a/apps/client/src/common/components/view-params-editor/constants.ts b/apps/client/src/common/components/view-params-editor/constants.ts
index ee7c9bce75..5219cd2389 100644
--- a/apps/client/src/common/components/view-params-editor/constants.ts
+++ b/apps/client/src/common/components/view-params-editor/constants.ts
@@ -511,5 +511,14 @@ export const getOperatorOptions = (customFields: CustomFields, timeFormat: strin
export const getCountdownOptions = (timeFormat: string): ParamField[] => [getTimeOption(timeFormat), hideTimerSeconds];
export const getProgressOptions = (timeFormat: string): ParamField[] => {
- return [getTimeOption(timeFormat)];
+ return [
+ getTimeOption(timeFormat),
+ {
+ id: 'fullHeight',
+ title: 'Full height columns',
+ description: 'Whether the columns in the timeline should be the full height ',
+ type: 'boolean',
+ defaultValue: false,
+ },
+ ];
};
diff --git a/apps/client/src/common/utils/styleUtils.ts b/apps/client/src/common/utils/styleUtils.ts
index b54e94358c..5b1f081ed1 100644
--- a/apps/client/src/common/utils/styleUtils.ts
+++ b/apps/client/src/common/utils/styleUtils.ts
@@ -24,6 +24,19 @@ export const getAccessibleColour = (bgColour?: string): ColourCombination => {
return { backgroundColor: '#1a1a1a', color: '#fffffa' };
};
+/**
+ * Adds opacity to a given colour, returns undefined if invalid
+ */
+export function alpha(colour: string, amount: number): string | undefined {
+ try {
+ const withAlpha = Color(colour).alpha(amount).hexa();
+ return withAlpha;
+ } catch (_error) {
+ /* we do not handle errors here */
+ }
+ return;
+}
+
/**
* @description Creates a list of classnames from array of css module conditions
* @param classNames - css modules objects
diff --git a/apps/client/src/features/timeline/Timeline/Timeline.module.scss b/apps/client/src/features/timeline/Timeline/Timeline.module.scss
index 55a3288a34..86ec5f1775 100644
--- a/apps/client/src/features/timeline/Timeline/Timeline.module.scss
+++ b/apps/client/src/features/timeline/Timeline/Timeline.module.scss
@@ -6,40 +6,43 @@ $timeline-entry-height: 20px;
.timelineEvents {
position: relative;
+ height: 100%;
}
-.entryIndicator {
+.entryColumn {
position: absolute;
- background-color: var(--color, $ui-white);
- height: $timeline-entry-height;
+ background-color: var(--lighter, $gray-500);
+ border-bottom: 0.25rem solid var(--color, $ui-white);
+ border-right: 1px solid $ui-black;
+ min-height: 80px;
+
+ &.fullHeight {
+ height: calc(100% - 4rem);
+ }
}
.entryContent {
- position: absolute;
- margin-top: $timeline-entry-height;
padding-top: var(--top, 0);
- border-left: 2px solid var(--color, $ui-white);
-
- color: $ui-white;
-
- white-space: nowrap;
-
- > div {
- min-width: 100%;
- padding-inline: 0.5em;
- width: fit-content;
- background-color: $ui-black;
- }
&.lastElement {
- border-left: none;
- border-right: 2px solid var(--color, $ui-black);
text-align: right;
-
transform: translateX(-100%);
}
}
+.entryText {
+ position: relative;
+ z-index: 2;
+ color: $ui-white;
+ padding-inline: 0.5em;
+ width: fit-content;
+ white-space: nowrap;
+
+ &.textBg {
+ background-color: var(--bg, $black-10);
+ }
+}
+
.start,
.title {
font-weight: 600;
@@ -49,7 +52,7 @@ $timeline-entry-height: 20px;
[data-status='finished'] {
color: $gray-500;
.status {
- display: none
+ display: none;
}
}
diff --git a/apps/client/src/features/timeline/Timeline/Timeline.tsx b/apps/client/src/features/timeline/Timeline/Timeline.tsx
index 187bca5127..0bf1c41e33 100644
--- a/apps/client/src/features/timeline/Timeline/Timeline.tsx
+++ b/apps/client/src/features/timeline/Timeline/Timeline.tsx
@@ -1,9 +1,11 @@
import { memo } from 'react';
+import { useSearchParams } from 'react-router-dom';
import { useViewportSize } from '@mantine/hooks';
import { isOntimeEvent, MaybeNumber } from 'ontime-types';
import { dayInMs, getFirstEventNormal, getLastEventNormal, MILLIS_PER_HOUR } from 'ontime-utils';
import useRundown from '../../../common/hooks-query/useRundown';
+import { isStringBoolean } from '../../viewers/common/viewUtils';
import { type ProgressStatus, TimelineEntry } from './TimelineEntry';
import { TimelineMarkers } from './TimelineMarkers';
@@ -46,6 +48,8 @@ function Timeline(props: TimelineProps) {
const { selectedEventId } = props;
const { width: screenWidth } = useViewportSize();
const timelineData = useTimeline();
+ const [searchParams] = useSearchParams();
+ const fullHeight = isStringBoolean(searchParams.get('fullHeight'));
if (timelineData === null) {
return null;
@@ -62,6 +66,7 @@ function Timeline(props: TimelineProps) {
return (
+
{order.map((eventId) => {
// for now we dont render delays and blocks
@@ -92,7 +97,8 @@ function Timeline(props: TimelineProps) {
event.duration,
screenWidth,
);
- const estimatedRightPosition = elementLeftPosition + getEstimatedWidth(event.title);
+ const estimatedWidth = getEstimatedWidth(event.title);
+ const estimatedRightPosition = elementLeftPosition + estimatedWidth;
const laneLevel = getLaneLevel(rightMostElements, elementLeftPosition);
if (rightMostElements[laneLevel] === undefined || rightMostElements[laneLevel] < estimatedRightPosition) {
@@ -111,11 +117,12 @@ function Timeline(props: TimelineProps) {
start={event.timeStart}
title={event.title}
width={elementWidth}
+ mayGrow={elementWidth < estimatedWidth}
+ fullHeight={fullHeight}
/>
);
})}
-
);
}
diff --git a/apps/client/src/features/timeline/Timeline/TimelineEntry.tsx b/apps/client/src/features/timeline/Timeline/TimelineEntry.tsx
index 5e155b30b7..0aff694d77 100644
--- a/apps/client/src/features/timeline/Timeline/TimelineEntry.tsx
+++ b/apps/client/src/features/timeline/Timeline/TimelineEntry.tsx
@@ -1,5 +1,5 @@
import { useClock } from '../../../common/hooks/useSocket';
-import { cx } from '../../../common/utils/styleUtils';
+import { alpha, cx } from '../../../common/utils/styleUtils';
import { formatDuration, formatTime } from '../../../common/utils/time';
import { getStatusLabel } from './timelineUtils';
@@ -18,6 +18,9 @@ interface TimelineEntry {
start: number;
title: string;
width: number;
+
+ mayGrow: boolean;
+ fullHeight: boolean;
}
const laneHeight = 120;
@@ -27,39 +30,48 @@ const formatOptions = {
};
export function TimelineEntry(props: TimelineEntry) {
- const { colour, duration, isLast, lane, left, status, start, title, width } = props;
+ const { colour, duration, isLast, lane, left, status, start, title, width, mayGrow, fullHeight } = props;
const formattedStartTime = formatTime(start, formatOptions);
- const formattedDuration = `Dur ${formatDuration(duration)}`;
+ const formattedDuration = formatDuration(duration);
+ const lighterColour = alpha(colour, 0.7);
+ const alphaColour = alpha(colour, 0.6);
+ const columnClasses = cx([style.entryColumn, fullHeight && style.fullHeight]);
const contentClasses = cx([style.entryContent, isLast && style.lastElement]);
+ const textBgClasses = cx([style.entryText, mayGrow && style.textBg]);
return (
- <>
-
+
-
{formattedStartTime}
-
{title}
-
{formattedDuration}
-
+
+
{formattedStartTime}
+
{title}
+
{formattedDuration}
+
+
- >
+
);
}
diff --git a/apps/client/src/features/timeline/Timeline/TimelineMarkers.module.scss b/apps/client/src/features/timeline/Timeline/TimelineMarkers.module.scss
index fd4b933ee3..01df098391 100644
--- a/apps/client/src/features/timeline/Timeline/TimelineMarkers.module.scss
+++ b/apps/client/src/features/timeline/Timeline/TimelineMarkers.module.scss
@@ -1,19 +1,15 @@
.markers {
width: 100%;
color: $ui-white;
- background-color: $white-10;
display: flex;
height: 1rem;
line-height: 1rem;
font-size: calc(1rem - 2px);
justify-content: space-evenly;
- text-align: center;
- & > * {
+ & > span {
flex-grow: 1;
- }
-
- :nth-child(odd) {
- background-color: $white-20;
+ border-left: 1px solid black;
+ height: 100vh;
}
}
diff --git a/apps/client/src/features/timeline/Timeline/TimelineProgressBar.module.scss b/apps/client/src/features/timeline/Timeline/TimelineProgressBar.module.scss
index be77e72855..8cc36e013e 100644
--- a/apps/client/src/features/timeline/Timeline/TimelineProgressBar.module.scss
+++ b/apps/client/src/features/timeline/Timeline/TimelineProgressBar.module.scss
@@ -1,8 +1,13 @@
.progressBar {
- position: relative;
- height: 100%;
- border-right: 2px solid $active-red;
+ width: 100%;
+ height: 0.75rem;
transition-duration: 0.3s;
transition-property: left;
+ background-color: $gray-900;
+
+ .progress {
+ height: 100%;
+ background-color: $active-red;;
+ }
}
diff --git a/apps/client/src/features/timeline/Timeline/TimelineProgressBar.tsx b/apps/client/src/features/timeline/Timeline/TimelineProgressBar.tsx
index f619ea5be7..35779a00a4 100644
--- a/apps/client/src/features/timeline/Timeline/TimelineProgressBar.tsx
+++ b/apps/client/src/features/timeline/Timeline/TimelineProgressBar.tsx
@@ -13,7 +13,11 @@ export function ProgressBar(props: ProgressBarProps) {
const { startHour, endHour } = props;
const { clock } = useClock();
- const left = getRelativePositionX(startHour, endHour, clock);
+ const width = getRelativePositionX(startHour, endHour, clock);
- return ;
+ return (
+
+ );
}
diff --git a/apps/client/src/features/timeline/TimelinePage.module.scss b/apps/client/src/features/timeline/TimelinePage.module.scss
index a2f93dfdb5..62ab87d77f 100644
--- a/apps/client/src/features/timeline/TimelinePage.module.scss
+++ b/apps/client/src/features/timeline/TimelinePage.module.scss
@@ -4,7 +4,6 @@
background-color: $ui-black;
color: $ui-white;
- text-transform: uppercase;
display: flex;
flex-direction: column;
@@ -38,11 +37,13 @@
font-weight: 600;
&.now {
- color: $green-500;
+ color: $red-500;
+
}
&.next {
- color: $red-500;
+ color: $green-500;
+
}
&.subdue {
diff --git a/apps/electron/package.json b/apps/electron/package.json
index e4d603bffd..a936658218 100644
--- a/apps/electron/package.json
+++ b/apps/electron/package.json
@@ -1,6 +1,6 @@
{
"name": "ontime",
- "version": "3.3.2",
+ "version": "3.4.0-alpha-timeline.2",
"author": "Carlos Valente",
"description": "Time keeping for live events",
"repository": "https://github.com/cpvalente/ontime",
diff --git a/apps/server/package.json b/apps/server/package.json
index ad7d3fe257..02b492f6ab 100644
--- a/apps/server/package.json
+++ b/apps/server/package.json
@@ -2,7 +2,7 @@
"name": "ontime-server",
"type": "module",
"main": "src/index.ts",
- "version": "3.3.2",
+ "version": "3.4.0-alpha-timeline.2",
"exports": "./src/index.js",
"dependencies": {
"@googleapis/sheets": "^5.0.5",
diff --git a/package.json b/package.json
index a44211186c..dc6325a4d7 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ontime",
- "version": "3.3.2",
+ "version": "3.4.0-alpha-timeline.2",
"description": "Time keeping for live events",
"keywords": [
"ontime",