diff --git a/apps/client/src/features/rundown/_blockMixins.scss b/apps/client/src/features/rundown/_blockMixins.scss
index f981f3b1a..b2227793d 100644
--- a/apps/client/src/features/rundown/_blockMixins.scss
+++ b/apps/client/src/features/rundown/_blockMixins.scss
@@ -22,6 +22,7 @@ $block-cursor-color: $orange-400;
border-radius: $block-border-radius;
position: relative;
color: $block-text-color;
+ overflow: hidden;
min-width: $block-width;
}
diff --git a/apps/client/src/features/rundown/entry-editor/composite/EventEditorTimes.tsx b/apps/client/src/features/rundown/entry-editor/composite/EventEditorTimes.tsx
index 4db9a8d0d..1c3b31a14 100644
--- a/apps/client/src/features/rundown/entry-editor/composite/EventEditorTimes.tsx
+++ b/apps/client/src/features/rundown/entry-editor/composite/EventEditorTimes.tsx
@@ -1,6 +1,5 @@
import { memo } from 'react';
import { IoInformationCircle } from 'react-icons/io5';
-import { Tooltip } from '@chakra-ui/react';
import { EndAction, TimerType, TimeStrategy } from 'ontime-types';
import { millisToString, parseUserTime } from 'ontime-utils';
@@ -8,6 +7,7 @@ import * as Editor from '../../../../common/components/editor-utils/EditorUtils'
import TimeInput from '../../../../common/components/input/time-input/TimeInput';
import Select from '../../../../common/components/select/Select';
import Switch from '../../../../common/components/switch/Switch';
+import Tooltip from '../../../../common/components/tooltip/Tooltip';
import { useEntryActions } from '../../../../common/hooks/useEntryAction';
import { millisToDelayString } from '../../../../common/utils/dateConfig';
import TimeInputFlow from '../../time-input-flow/TimeInputFlow';
@@ -126,11 +126,12 @@ function EventEditorTimes({
-
-
- Display Options
-
-
+ }
+ >
+ Display Options
+
diff --git a/apps/client/src/features/rundown/entry-editor/composite/EventEditorTriggers.tsx b/apps/client/src/features/rundown/entry-editor/composite/EventEditorTriggers.tsx
index a52539a9b..abafc2786 100644
--- a/apps/client/src/features/rundown/entry-editor/composite/EventEditorTriggers.tsx
+++ b/apps/client/src/features/rundown/entry-editor/composite/EventEditorTriggers.tsx
@@ -1,6 +1,5 @@
import { Fragment, useCallback, useMemo, useState } from 'react';
import { IoAlertCircle, IoCheckmarkCircle, IoTrash } from 'react-icons/io5';
-import { Tooltip } from '@chakra-ui/react';
import { TimerLifeCycle, timerLifecycleValues, Trigger } from 'ontime-types';
import { generateId } from 'ontime-utils';
@@ -8,6 +7,7 @@ import Button from '../../../../common/components/buttons/Button';
import IconButton from '../../../../common/components/buttons/IconButton';
import Select from '../../../../common/components/select/Select';
import Tag from '../../../../common/components/tag/Tag';
+import Tooltip from '../../../../common/components/tooltip/Tooltip';
import { useEntryActions } from '../../../../common/hooks/useEntryAction';
import useAutomationSettings from '../../../../common/hooks-query/useAutomationSettings';
@@ -107,7 +107,7 @@ function EventTriggerForm({ eventId, triggers }: EventTriggerFormProps) {
Add
{validationError !== undefined ? (
-
+ }>
) : (
diff --git a/apps/client/src/features/rundown/rundown-block/RundownBlock.module.scss b/apps/client/src/features/rundown/rundown-block/RundownBlock.module.scss
index c43aff0dc..51cad5024 100644
--- a/apps/client/src/features/rundown/rundown-block/RundownBlock.module.scss
+++ b/apps/client/src/features/rundown/rundown-block/RundownBlock.module.scss
@@ -2,21 +2,21 @@
.block {
@include block-styling;
- overflow: hidden;
+ margin-block: 1rem 0.25rem;
display: grid;
grid-template-columns: 2rem 1fr;
grid-template-areas: 'binder header';
align-items: center;
- // TODO(style fix): groups have an extra bottom margin which interrupt colour
- margin-block: 0.25rem;
&.hasCursor {
outline: 1px solid $block-cursor-color;
}
&.expanded {
+ margin-block: 1rem 0;
border-radius: $block-border-radius $block-border-radius 0 0;
+ border-bottom: 0.25rem solid color-mix(in srgb, transparent 90%, var(--user-bg, transparent) 10%);
}
.binder {
@@ -29,8 +29,12 @@
place-content: center;
position: relative;
cursor: pointer;
- }
+ &:focus {
+ outline: 1px solid $blue-500;
+ outline-offset: -1px;
+ }
+ }
.header {
grid-area: header;
diff --git a/apps/client/src/features/rundown/rundown-block/RundownBlock.tsx b/apps/client/src/features/rundown/rundown-block/RundownBlock.tsx
index 8fff87166..c2220ea35 100644
--- a/apps/client/src/features/rundown/rundown-block/RundownBlock.tsx
+++ b/apps/client/src/features/rundown/rundown-block/RundownBlock.tsx
@@ -102,8 +102,9 @@ export default function RundownBlock({ data, hasCursor, collapsed, onCollapse }:
onClick={handleFocusClick}
onContextMenu={onContextMenu}
style={{
- ...(binderColours ? { '--user-bg': binderColours.backgroundColor } : {}),
+ // ...(binderColours ? { '--user-bg': binderColours.backgroundColor } : {}),
...dragStyle,
+ '--user-bg': data.colour || '#929292',
}}
data-testid='rundown-block'
>
diff --git a/apps/client/src/features/rundown/rundown-delay/RundownDelay.module.scss b/apps/client/src/features/rundown/rundown-delay/RundownDelay.module.scss
index bebb4d1da..d38aacdd0 100644
--- a/apps/client/src/features/rundown/rundown-delay/RundownDelay.module.scss
+++ b/apps/client/src/features/rundown/rundown-delay/RundownDelay.module.scss
@@ -4,12 +4,11 @@
@include block-styling;
margin-block: 0.25rem;
+ padding-right: 0.25rem;
background-color: $block-bg2;
- padding-right: 0.5rem;
display: grid;
- grid-template-columns: 2rem 1fr auto;
- grid-template-areas: 'drag inpt btns';
+ grid-template-columns: 2rem 1fr auto auto;
align-items: center;
height: $secondary-block-height;
gap: 0.5rem;
@@ -21,12 +20,4 @@
.drag {
@include drag-style;
- grid-area: drag;
}
-
-.actionButtons {
- grid-area: btns;
- display: flex;
- align-items: center;
- gap: 0.5rem;
-}
\ No newline at end of file
diff --git a/apps/client/src/features/rundown/rundown-delay/RundownDelay.tsx b/apps/client/src/features/rundown/rundown-delay/RundownDelay.tsx
index 1812e1b62..b3ae36237 100644
--- a/apps/client/src/features/rundown/rundown-delay/RundownDelay.tsx
+++ b/apps/client/src/features/rundown/rundown-delay/RundownDelay.tsx
@@ -55,23 +55,24 @@ export default function RundownDelay({ data, hasCursor }: RundownDelayProps) {
deleteEntry([data.id]);
};
- const blockClasses = cx([style.delay, hasCursor ? style.hasCursor : null]);
-
return (
-
+
-
-
-
-
+
+
);
}
diff --git a/apps/client/src/features/rundown/rundown-event/RundownEvent.module.scss b/apps/client/src/features/rundown/rundown-event/RundownEvent.module.scss
index 225c3478c..dac3c67d8 100644
--- a/apps/client/src/features/rundown/rundown-event/RundownEvent.module.scss
+++ b/apps/client/src/features/rundown/rundown-event/RundownEvent.module.scss
@@ -6,6 +6,7 @@ $skip-opacity: 0.2;
@include block-styling;
background-color: $block-bg;
margin-block: 0.25rem;
+ overflow: initial;
display: grid;
grid-template-areas:
@@ -15,7 +16,7 @@ $skip-opacity: 0.2;
'binder pb-actions estatus estatus'
'binder ... ... ...';
- grid-template-columns: $block-binder-width 3rem 1fr auto;
+ grid-template-columns: $block-binder-width 3rem 1fr 3rem;
grid-template-rows: 0.125rem 2rem 2rem auto 0.125rem;
align-items: center;
padding-right: $block-clearance;
@@ -92,11 +93,10 @@ $skip-opacity: 0.2;
position: relative;
cursor: pointer;
- border-radius: $block-border-radius 0 0 $block-border-radius;
-
background-color: $gray-1050; // to override inline
color: $section-white;
font-size: 1rem;
+ border-radius: 3px 0 0 3px;
.drag {
@include drag-style;
diff --git a/apps/client/src/features/rundown/rundown-event/RundownEventInner.tsx b/apps/client/src/features/rundown/rundown-event/RundownEventInner.tsx
index e038230cd..67c2868b1 100644
--- a/apps/client/src/features/rundown/rundown-event/RundownEventInner.tsx
+++ b/apps/client/src/features/rundown/rundown-event/RundownEventInner.tsx
@@ -10,11 +10,10 @@ import {
IoPlaySkipForward,
IoTime,
} from 'react-icons/io5';
-import { Tooltip } from '@chakra-ui/react';
import { EndAction, Playback, TimerType, TimeStrategy } from 'ontime-types';
+import Tooltip from '../../../common/components/tooltip/Tooltip';
import { cx } from '../../../common/utils/styleUtils';
-import { tooltipDelayMid } from '../../../ontimeConfig';
import EditableBlockTitle from '../common/EditableBlockTitle';
import TimeInputFlow from '../time-input-flow/TimeInputFlow';
@@ -137,25 +136,17 @@ function RundownEventInner({
{loaded &&
}
-
-
-
-
+ }>
+
-
-
-
-
+ }>
+
-
-
-
-
+ }>
+
-
-
-
-
+ }>
+
diff --git a/apps/client/src/features/rundown/rundown-event/RundownIndicators.module.scss b/apps/client/src/features/rundown/rundown-event/RundownIndicators.module.scss
index 094825564..5ceff61d6 100644
--- a/apps/client/src/features/rundown/rundown-event/RundownIndicators.module.scss
+++ b/apps/client/src/features/rundown/rundown-event/RundownIndicators.module.scss
@@ -5,7 +5,7 @@ $gap-left: calc(2rem + 0.25rem + 3rem);
font-size: calc(1rem - 5px);
position: absolute;
top: -1em;
- z-index: $zindex-floating;;
+ z-index: $zindex-floating;
margin-left: $gap-left;
display: flex;
diff --git a/apps/client/src/features/rundown/rundown-event/composite/RundownEventChip.module.scss b/apps/client/src/features/rundown/rundown-event/composite/RundownEventChip.module.scss
index d59e42736..1d636bd1a 100644
--- a/apps/client/src/features/rundown/rundown-event/composite/RundownEventChip.module.scss
+++ b/apps/client/src/features/rundown/rundown-event/composite/RundownEventChip.module.scss
@@ -1,11 +1,9 @@
.chip {
- background-color: $gray-1100;
white-space: nowrap;
font-size: calc(1rem - 3px);
color: $label-gray;
- padding: 0.125rem 0.5rem;
- border-radius: 2px;
+ justify-self: end;
&.over {
color: $ontime-delay-text;
diff --git a/apps/client/src/features/rundown/rundown-event/composite/RundownEventChip.tsx b/apps/client/src/features/rundown/rundown-event/composite/RundownEventChip.tsx
index 772ac593f..415370f96 100644
--- a/apps/client/src/features/rundown/rundown-event/composite/RundownEventChip.tsx
+++ b/apps/client/src/features/rundown/rundown-event/composite/RundownEventChip.tsx
@@ -1,13 +1,12 @@
import { useMemo } from 'react';
import { IoCheckmarkCircle } from 'react-icons/io5';
-import { Tooltip } from '@chakra-ui/react';
import { isPlaybackActive, MILLIS_PER_MINUTE, MILLIS_PER_SECOND } from 'ontime-utils';
+import Tooltip from '../../../../common/components/tooltip/Tooltip';
import { usePlayback } from '../../../../common/hooks/useSocket';
import useReport from '../../../../common/hooks-query/useReport';
import { cx } from '../../../../common/utils/styleUtils';
import { formatDuration, formatTime, useTimeUntilStart } from '../../../../common/utils/time';
-import { tooltipDelayFast } from '../../../../ontimeConfig';
import style from './RundownEventChip.module.scss';
@@ -39,7 +38,7 @@ export default function RundownEventChip({
const { playback } = usePlayback();
if (isLoaded) {
- return null; //TODO: the is a small flash of 'DUE' on the loaded event as clock data arrives before isLoaded propagates
+ return null;
}
const playbackActive = isPlaybackActive(playback);
@@ -51,16 +50,14 @@ export default function RundownEventChip({
if (playbackActive) {
// we extracted the component to avoid unnecessary calculations and re-renders
return (
-
-
-
-
+ } className={className}>
+
);
}
@@ -113,7 +110,7 @@ function EventReport(props: EventReportProps) {
const absDifference = Math.abs(difference);
if (absDifference < MILLIS_PER_SECOND) {
- return ['ontime', 'ontime', 'Event finished ontime'];
+ return ['ontime', 'under', 'Event finished on time'];
}
const isOver = difference > 0;
@@ -131,10 +128,8 @@ function EventReport(props: EventReportProps) {
}
return (
-
-
- {value === 'ontime' ? : value}
-
+ } className={cx([style.chip, style[overUnderStyle], className])}>
+ {value === 'ontime' ? : value}
);
}
diff --git a/apps/client/src/features/rundown/rundown-event/composite/RundownEventPlayback.tsx b/apps/client/src/features/rundown/rundown-event/composite/RundownEventPlayback.tsx
index 3d55841c2..21514b0dc 100644
--- a/apps/client/src/features/rundown/rundown-event/composite/RundownEventPlayback.tsx
+++ b/apps/client/src/features/rundown/rundown-event/composite/RundownEventPlayback.tsx
@@ -1,28 +1,13 @@
import { memo, MouseEvent } from 'react';
import { IoPause, IoPlay, IoReload, IoRemoveCircle, IoRemoveCircleOutline } from 'react-icons/io5';
-import TooltipActionBtn from '../../../../common/components/buttons/TooltipActionBtn';
+import IconButton from '../../../../common/components/buttons/IconButton';
+import Tooltip from '../../../../common/components/tooltip/Tooltip';
import { useEntryActions } from '../../../../common/hooks/useEntryAction';
import { setEventPlayback } from '../../../../common/hooks/useSocket';
-import { tooltipDelayMid } from '../../../../ontimeConfig';
import style from '../RundownEvent.module.scss';
-const blockBtnStyle = {
- size: 'sm',
-};
-
-type StyleVariant = {
- 'aria-label': string;
- tooltip: string;
- backgroundColor: string;
- _hover: { backgroundColor?: string };
-};
-
-const tooltipProps = {
- openDelay: tooltipDelayMid,
-};
-
interface RundownEventPlaybackProps {
eventId: string;
skip: boolean;
@@ -67,67 +52,66 @@ function RundownEventPlayback({
setEventPlayback.loadEvent(eventId);
};
- const buttonVariant: Partial
= {};
-
- if (isPaused) {
- // continue
- buttonVariant['aria-label'] = 'Continue event';
- buttonVariant.tooltip = 'Continue event';
- buttonVariant.backgroundColor = '#339E4E';
- buttonVariant._hover = { backgroundColor: '#339E4Eee' };
- } else if (isPlaying) {
- // pause
- buttonVariant['aria-label'] = 'Pause event';
- buttonVariant.tooltip = 'Pause event';
- buttonVariant.backgroundColor = '#c05621';
- buttonVariant._hover = { backgroundColor: '#c05621ee' };
- } else {
- // start
- buttonVariant['aria-label'] = 'Start event';
- buttonVariant.tooltip = 'Start event';
- if (!disablePlayback) {
- buttonVariant._hover = { backgroundColor: '#339E4E' };
+ const playButtonStyles: { tooltip: string; backgroundColor: string | undefined } = (() => {
+ if (isPaused) {
+ return {
+ tooltip: 'Continue event',
+ backgroundColor: '#339E4E',
+ };
}
- }
+
+ if (isPlaying) {
+ return {
+ tooltip: 'Pause event',
+ backgroundColor: '#c05621',
+ };
+ }
+ return {
+ tooltip: 'Start event',
+ backgroundColor: undefined,
+ };
+ })();
return (
- }
+ onClick={toggleSkip}
+ tabIndex={-1}
+ disabled={loaded}
+ style={{
+ background: skip ? '#9A0000' : undefined,
+ }}
aria-label='Skip event'
- tooltip='Skip event'
- icon={skip ? : }
- backgroundColor={skip ? '#B20000' : undefined}
- _hover={{ backgroundColor: '#FF7878' }}
- {...tooltipProps}
- {...blockBtnStyle}
- clickHandler={toggleSkip}
+ >
+ {skip ? : }
+
+
+ }
+ onClick={load}
tabIndex={-1}
- isDisabled={loaded}
- />
- }
- isDisabled={disablePlayback}
- {...tooltipProps}
- {...blockBtnStyle}
- clickHandler={load}
+ >
+
+
+
+ }
+ onClick={actionHandler}
tabIndex={-1}
- />
- : }
- isDisabled={disablePlayback}
- {...tooltipProps}
- {...blockBtnStyle}
- {...buttonVariant}
- clickHandler={actionHandler}
- tabIndex={-1}
- />
+ disabled={disablePlayback}
+ style={{
+ backgroundColor: playButtonStyles.backgroundColor,
+ }}
+ aria-label={isPlaying ? 'Pause event' : 'Start event'}
+ >
+ {!isPlaying ? : }
+
);
}
diff --git a/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.module.scss b/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.module.scss
index 4d19e180a..c27e8ce55 100644
--- a/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.module.scss
+++ b/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.module.scss
@@ -1,30 +1,63 @@
-.timeLabel {
- position: absolute;
- z-index: $zindex-floating;
- font-size: 0.75rem;
- font-weight: 600;
- top: 2px;
- right: 4px;
- color: inherit;
-}
-
.timeAction {
- opacity: 0.4;
+ background: $gray-1050;
+ color: $gray-500;
cursor: pointer;
- padding-right: 0.5em;
+ height: 2rem;
+ width: 2rem;
+ display: grid;
+ place-content: center;
+ aspect-ratio: 1;
+
+ &:hover:not(:disabled):not(:active) {
+ background: $gray-1000;
+ }
+
+ &:active:not(:disabled) {
+ background: $gray-1300;
+ }
+
+ &:focus {
+ outline: 1px solid $blue-500;
+ outline-offset: -1px;
+ }
&.active {
- opacity: 1;
color: var(--status-color-active-override, $active-indicator);
}
- .fourtyfive {
- transform: rotate(-45deg);
- }
+}
+
+.fourtyfive {
+ transform: rotate(-45deg);
}
.timerNote {
+ width: 1.25em;
color: $blue-500;
- margin-right: 0.5rem;
font-size: 1.5em;
- display: grid;
+}
+
+.inputGroup {
+ border: 1px solid transparent;
+ width: fit-content;
+ display: flex;
+ align-items: center;
+ border-radius: $component-border-radius-md;
+
+ &.delayed {
+ border: 1px solid $ontime-delay-text;
+ }
+
+ input {
+ max-width: 6.5em;
+ border-radius: $component-border-radius-md 0 0 $component-border-radius-md;
+ border: none;
+ padding-right: 0;
+ }
+
+ button {
+ width: 1.5rem;
+ height: 2rem;
+ border-radius: 0 $component-border-radius-md $component-border-radius-md 0;
+ border: none;
+ }
}
diff --git a/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.tsx b/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.tsx
index f26796133..55accc706 100644
--- a/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.tsx
+++ b/apps/client/src/features/rundown/time-input-flow/TimeInputFlow.tsx
@@ -1,14 +1,13 @@
import { memo } from 'react';
import { IoAlertCircleOutline, IoLink, IoLockClosed, IoLockOpenOutline, IoUnlink } from 'react-icons/io5';
-import { InputRightElement, Tooltip } from '@chakra-ui/react';
import { TimeField, TimeStrategy } from 'ontime-types';
import { dayInMs } from 'ontime-utils';
import * as Editor from '../../../common/components/editor-utils/EditorUtils';
-import TimeInputWithButton from '../../../common/components/input/time-input/TimeInputWithButton';
+import TimeInput from '../../../common/components/input/time-input/TimeInput';
+import Tooltip from '../../../common/components/tooltip/Tooltip';
import { useEntryActions } from '../../../common/hooks/useEntryAction';
import { cx } from '../../../common/utils/styleUtils';
-import { tooltipDelayFast, tooltipDelayMid } from '../../../ontimeConfig';
import style from './TimeInputFlow.module.scss';
@@ -25,8 +24,17 @@ interface EventBlockTimerProps {
}
export default memo(TimeInputFlow);
-function TimeInputFlow(props: EventBlockTimerProps) {
- const { eventId, countToEnd, timeStart, timeEnd, duration, timeStrategy, linkStart, delay, showLabels } = props;
+function TimeInputFlow({
+ eventId,
+ countToEnd,
+ timeStart,
+ timeEnd,
+ duration,
+ timeStrategy,
+ linkStart,
+ delay,
+ showLabels,
+}: EventBlockTimerProps) {
const { updateEntry, updateTimer } = useEntryActions();
// In sync with EventEditorTimes
@@ -52,86 +60,80 @@ function TimeInputFlow(props: EventBlockTimerProps) {
}
const hasDelay = delay !== 0;
-
const isLockedEnd = timeStrategy === TimeStrategy.LockEnd;
const isLockedDuration = timeStrategy === TimeStrategy.LockDuration;
- const activeStart = cx([style.timeAction, linkStart && style.active]);
- const activeEnd = cx([style.timeAction, isLockedEnd && style.active]);
- const activeDuration = cx([style.timeAction, isLockedDuration && style.active]);
-
return (
<>
{showLabels &&
Start time}
-
- name='timeStart'
- submitHandler={handleSubmit}
- time={timeStart}
- hasDelay={hasDelay}
- placeholder='Start'
- disabled={linkStart}
- >
-
- handleLink(!linkStart)}>
- S
- {linkStart ? : }
-
+
+
+ handleLink(!linkStart)}
+ >
+ {linkStart ? : }
-
+
{showLabels &&
End time}
-
- name='timeEnd'
- submitHandler={handleSubmit}
- time={timeEnd}
- hasDelay={hasDelay}
- disabled={isLockedDuration}
- placeholder='End'
- >
-
- handleChangeStrategy(TimeStrategy.LockEnd)}
- data-testid='lock__end'
- >
- E
- {isLockedEnd ? : }
-
+
+
+ handleChangeStrategy(TimeStrategy.LockEnd)}
+ data-testid='lock__end'
+ >
+ {isLockedEnd ? : }
-
+
{showLabels &&
Duration}
-
- name='duration'
- submitHandler={handleSubmit}
- time={duration}
- disabled={isLockedEnd}
- placeholder='Duration'
- >
-
- handleChangeStrategy(TimeStrategy.LockDuration)}
- data-testid='lock__duration'
- >
- D
- {isLockedDuration ? : }
-
+
+
+ handleChangeStrategy(TimeStrategy.LockDuration)}
+ data-testid='lock__duration'
+ >
+ {isLockedDuration ? : }
-
+
{warnings.length > 0 && (
-
-
-
-
-
+ }>
+
+
)}
>
);
diff --git a/apps/client/src/views/cuesheet/cuesheet-table/CuesheetTable.tsx b/apps/client/src/views/cuesheet/cuesheet-table/CuesheetTable.tsx
index 53d8b619c..d1ceea187 100644
--- a/apps/client/src/views/cuesheet/cuesheet-table/CuesheetTable.tsx
+++ b/apps/client/src/views/cuesheet/cuesheet-table/CuesheetTable.tsx
@@ -6,7 +6,7 @@ import { OntimeEntry, TimeField } from 'ontime-types';
import { useEntryActions } from '../../../common/hooks/useEntryAction';
import { useFollowSelected } from '../../../common/hooks/useFollowComponent';
-import { AppMode,sessionKeys } from '../../../ontimeConfig';
+import { AppMode, sessionKeys } from '../../../ontimeConfig';
import { usePersistedCuesheetOptions } from '../cuesheet.options';
import CuesheetBody from './cuesheet-table-elements/CuesheetBody';
diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.module.scss b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.module.scss
index deefcf803..815458b0d 100644
--- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.module.scss
+++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.module.scss
@@ -1,7 +1,6 @@
@import "../CuesheetTable.module.scss";
.eventRow {
- vertical-align: top;
background: color-mix(in srgb, transparent 92%, var(--user-bg, $gray-500) 8%);
border-left: 4px solid var(--user-bg, $gray-500);
diff --git a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.tsx b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.tsx
index 796bcce9d..0c366ac9c 100644
--- a/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.tsx
+++ b/apps/client/src/views/cuesheet/cuesheet-table/cuesheet-table-elements/EventRow.tsx
@@ -49,7 +49,8 @@ export default function EventRow({
const [cuesheetMode] = useSessionStorage({
key: sessionKeys.cuesheetMode,
defaultValue: AppMode.Edit,
- }); const ownRef = useRef(null);
+ });
+ const ownRef = useRef(null);
const isVisible = useVisibleRowsStore((state) => state.visibleRows.has(rowId));
diff --git a/apps/client/src/views/editor/welcome/Welcome.module.scss b/apps/client/src/views/editor/welcome/Welcome.module.scss
index efdee592e..a71781fd0 100644
--- a/apps/client/src/views/editor/welcome/Welcome.module.scss
+++ b/apps/client/src/views/editor/welcome/Welcome.module.scss
@@ -13,7 +13,8 @@
.about {
@extend .column;
- font-size: calc(1rem - 2px);
+ font-size: calc(1rem - 3px);
+ padding-inline: 0.25rem;
}
.inline {
diff --git a/apps/client/src/views/editor/welcome/Welcome.tsx b/apps/client/src/views/editor/welcome/Welcome.tsx
index 55474b032..26e79ed09 100644
--- a/apps/client/src/views/editor/welcome/Welcome.tsx
+++ b/apps/client/src/views/editor/welcome/Welcome.tsx
@@ -24,17 +24,12 @@ interface WelcomeProps {
export default function Welcome({ onClose }: WelcomeProps) {
const navigate = useNavigate();
- /** handle cleanup actions before request closing the modal */
- const handleClose = () => {
- onClose();
- };
-
/** handle loading a selected project */
const handleLoadProject = async (filename: string) => {
try {
await loadProject(filename);
await invalidateAllCaches();
- handleClose();
+ onClose();
} catch (_error) {
/** no error handling for now */
}
@@ -45,7 +40,7 @@ export default function Welcome({ onClose }: WelcomeProps) {
try {
await loadDemo();
await invalidateAllCaches();
- handleClose();
+ onClose();
} catch (_error) {
/** no error handling for now */
}
@@ -54,13 +49,13 @@ export default function Welcome({ onClose }: WelcomeProps) {
/** handle redirect to create modal */
const handleCallCreate = () => {
navigate('/editor?settings=project__create');
- handleClose();
+ onClose();
};
return (
onClose()}
showBackdrop
bodyElements={
@@ -74,7 +69,7 @@ export default function Welcome({ onClose }: WelcomeProps) {
Welcome to Ontime
-
+ onClose()}>
@@ -87,7 +82,7 @@ export default function Welcome({ onClose }: WelcomeProps) {
Last Used |
-
+
onClose()} />
@@ -97,7 +92,7 @@ export default function Welcome({ onClose }: WelcomeProps) {
-
+ onClose()} />
diff --git a/apps/server/src/adapters/WebsocketAdapter.ts b/apps/server/src/adapters/WebsocketAdapter.ts
index 3b26ff103..6954ac017 100644
--- a/apps/server/src/adapters/WebsocketAdapter.ts
+++ b/apps/server/src/adapters/WebsocketAdapter.ts
@@ -35,13 +35,14 @@ import { dispatchFromAdapter } from '../api-integration/integration.controller.j
import { generateId } from 'ontime-utils';
import { authenticateSocket } from '../middleware/authenticate.js';
+type ClientId = string;
let instance: SocketServer | null = null;
class SocketServer implements IAdapter {
private readonly MAX_PAYLOAD = 1024 * 256; // 256Kb
private wss: WebSocketServer | null;
- private readonly clients: Map;
+ private readonly clients: Map;
private lastConnection: Date | null = null;
private shouldShowWelcome = true;
@@ -52,7 +53,7 @@ class SocketServer implements IAdapter {
// eslint-disable-next-line @typescript-eslint/no-this-alias -- this logic is used to ensure singleton
instance = this;
- this.clients = new Map();
+ this.clients = new Map();
this.wss = null;
}
@@ -165,7 +166,7 @@ class SocketServer implements IAdapter {
};
}
- private getOrCreateClient(clientId: string): Client {
+ private getOrCreateClient(clientId: ClientId): Client {
if (!this.clients.has(clientId)) {
this.clients.set(clientId, {
type: 'unknown',
@@ -183,11 +184,11 @@ class SocketServer implements IAdapter {
this.sendAsJson(MessageTag.ClientList, payload);
}
- public getClientList(): string[] {
+ public getClientList(): ClientId[] {
return Array.from(this.clients.keys());
}
- public renameClient(target: string, name: string) {
+ public renameClient(target: ClientId, name: string) {
const previousData = this.clients.get(target);
if (!previousData) {
throw new Error(`Client "${target}" not found`);
@@ -198,7 +199,7 @@ class SocketServer implements IAdapter {
this.sendClientList();
}
- public redirectClient(target: string, path: string) {
+ public redirectClient(target: ClientId, path: string) {
const previousData = this.clients.get(target);
if (!previousData) {
throw new Error(`Client "${target}" not found`);
@@ -206,7 +207,7 @@ class SocketServer implements IAdapter {
this.sendAsJson(MessageTag.ClientRedirect, { target, path });
}
- public identifyClient(target: string, identify: boolean) {
+ public identifyClient(target: ClientId, identify: boolean) {
const previousData = this.clients.get(target);
if (!previousData) {
throw new Error(`Client "${target}" not found`);
diff --git a/apps/server/src/services/sheet-service/SheetService.ts b/apps/server/src/services/sheet-service/SheetService.ts
index 3d1981452..c552addb4 100644
--- a/apps/server/src/services/sheet-service/SheetService.ts
+++ b/apps/server/src/services/sheet-service/SheetService.ts
@@ -15,10 +15,10 @@ import { parseRundowns } from '../../api-data/rundown/rundown.parser.js';
import { getCurrentRundown, getProjectCustomFields } from '../../api-data/rundown/rundown.dao.js';
import { parseExcel } from '../../api-data/excel/excel.parser.js';
import { parseCustomFields } from '../../api-data/custom-fields/customFields.parser.js';
+import { consoleSubdued } from '../../utils/console.js';
import { cellRequestFromEvent, type ClientSecret, getA1Notation, isClientSecret } from './sheetUtils.js';
import { catchCommonImportXlsxError } from './googleApi.utils.js';
-import { consoleError, consoleSubdued } from '../../utils/console.js';
const sheetScope = 'https://www.googleapis.com/auth/spreadsheets';
const codesUrl = 'https://oauth2.googleapis.com/device/code';
diff --git a/e2e/tests/features/208-auxtimer.spec.ts b/e2e/tests/features/208-auxtimer.spec.ts
index a54c8fd4e..2654a5550 100644
--- a/e2e/tests/features/208-auxtimer.spec.ts
+++ b/e2e/tests/features/208-auxtimer.spec.ts
@@ -7,13 +7,13 @@ test('Aux timer buttons', async ({ page }) => {
await page.getByTestId('time-input-aux1').press('Enter');
await expect(page.getByTestId('time-input-aux1')).toHaveValue('12:34:56');
await page.getByTestId('aux-timer-start-1').click();
- await expect(page.getByTestId('time-input-aux1')).toHaveValue('12:34:53', { timeout: 4000 });
+ await expect(page.getByTestId('time-label-aux1')).toHaveText('12:34:53', { timeout: 4000 });
await page.getByTestId('aux-timer-pause-1').click();
- await expect(page.getByTestId('time-input-aux1')).toHaveValue('12:34:53');
+ await expect(page.getByTestId('time-label-aux1')).toHaveText('12:34:53');
await page.getByTestId('aux-timer-stop-1').click();
await expect(page.getByTestId('time-input-aux1')).toHaveValue('12:34:56');
await page.getByTestId('aux-timer-direction-1').click();
await page.getByTestId('aux-timer-start-1').click();
- await expect(page.getByTestId('time-input-aux1')).toHaveValue('12:34:59', { timeout: 4000 });
+ await expect(page.getByTestId('time-label-aux1')).toHaveText('12:34:59', { timeout: 4000 });
await page.getByTestId('aux-timer-stop-1').click();
});
diff --git a/e2e/tests/features/209-rundown-shortcuts.spec.ts b/e2e/tests/features/209-rundown-shortcuts.spec.ts
index cc08e2b76..ba996c496 100644
--- a/e2e/tests/features/209-rundown-shortcuts.spec.ts
+++ b/e2e/tests/features/209-rundown-shortcuts.spec.ts
@@ -19,9 +19,9 @@ test('Copy-paste', async ({ page }) => {
await page.getByTestId('block__title').press('Enter');
// copy paste below
- await page.locator('div').filter({ hasText: /^4$/ }).click();
- await page.locator('div').filter({ hasText: /^4$/ }).press('Control+c');
- await page.locator('div').filter({ hasText: /^4$/ }).press('Control+v');
+ await page.getByTestId('rundown-event').locator('div').filter({ hasText: '4' }).click();
+ await page.getByTestId('rundown-event').locator('div').filter({ hasText: '4' }).press('Control+c');
+ await page.getByTestId('rundown-event').locator('div').filter({ hasText: '4' }).press('Control+v');
// assert
await expect(page.getByTestId('entry-2')).toBeVisible();
@@ -29,9 +29,9 @@ test('Copy-paste', async ({ page }) => {
await expect(page.getByTestId('entry-2').getByTestId('rundown-event')).toContainText('5');
// copy paste above
- await page.locator('div').filter({ hasText: /^5$/ }).click();
- await page.locator('div').filter({ hasText: /^5$/ }).press('Control+c');
- await page.locator('div').filter({ hasText: /^5$/ }).press('Control+Shift+v');
+ await page.getByTestId('rundown-event').locator('div').filter({ hasText: '5' }).click();
+ await page.getByTestId('rundown-event').locator('div').filter({ hasText: '5' }).press('Control+c');
+ await page.getByTestId('rundown-event').locator('div').filter({ hasText: '5' }).press('Control+Shift+v');
// assert
await expect(page.getByTestId('entry-2')).toBeVisible();
@@ -63,7 +63,7 @@ test('Move', async ({ page }) => {
// copy move up
await page.getByTestId('entry-3').getByTestId('rundown-event').getByText('3').click();
await page.getByTestId('entry-3').getByTestId('rundown-event').filter({ hasText: '3' }).press('Alt+Control+ArrowUp');
- await page.getByTestId('entry-2').locator('div').filter({ hasText: /^3$/ }).press('Alt+Control+ArrowUp');
+ await page.getByTestId('entry-3').getByTestId('rundown-event').filter({ hasText: '3' }).press('Alt+Control+ArrowUp');
await expect(page.getByTestId('entry-1').getByTestId('rundown-event')).toContainText('3');
});
diff --git a/e2e/tests/features/211-report-data.spec.ts b/e2e/tests/features/211-report-data.spec.ts
index b46180748..5fbddae64 100644
--- a/e2e/tests/features/211-report-data.spec.ts
+++ b/e2e/tests/features/211-report-data.spec.ts
@@ -28,7 +28,7 @@ test('show warning when event starts next day midnight', async ({ page }) => {
await page.getByRole('button', { name: 'Create Event' }).click();
await page.getByRole('button', { name: 'Event' }).nth(4).click();
- await page.getByTestId('entry-2').getByText('E').click();
+ await page.getByTestId('entry-2').getByTestId('lock__end').click();
await page.getByTestId('entry-2').getByTestId('time-input-timeEnd').click();
await page.getByTestId('entry-2').getByTestId('time-input-timeEnd').fill('0');
await page.getByTestId('entry-2').getByTestId('time-input-timeEnd').press('Enter');
diff --git a/e2e/tests/features/212-time-until.spec.ts b/e2e/tests/features/212-time-until.spec.ts
index a40aec894..daf296408 100644
--- a/e2e/tests/features/212-time-until.spec.ts
+++ b/e2e/tests/features/212-time-until.spec.ts
@@ -7,7 +7,7 @@ test('time until absolute', async ({ page }) => {
await page.getByRole('button', { name: 'Delete all' }).click();
await page.getByRole('button', { name: 'Create Event' }).click();
- await page.getByRole('button', { name: 'Event' }).nth(4).click();
+ await page.getByRole('button', { name: 'Event', exact: true }).nth(1).click();
await page.getByRole('button', { name: 'Event', exact: true }).nth(1).click();
await page.getByRole('button', { name: 'Event', exact: true }).nth(1).click();
diff --git a/e2e/tests/features/301-spreadsheet-import.spec.ts b/e2e/tests/features/301-spreadsheet-import.spec.ts
index dc7cade75..742b00913 100644
--- a/e2e/tests/features/301-spreadsheet-import.spec.ts
+++ b/e2e/tests/features/301-spreadsheet-import.spec.ts
@@ -24,6 +24,8 @@ test('sheet file upload', async ({ page }) => {
await page.getByRole('button', { name: 'Import preview' }).click();
await page.getByRole('button', { name: 'Apply' }).click();
await page.getByRole('button', { name: 'Return' }).click();
+
+ await page.getByRole('button', { name: 'Close settings' }).scrollIntoViewIfNeeded();
await page.getByRole('button', { name: 'Close settings' }).click();
// asset test events