) => {
- const { children, disabled, onClick, theme = 'neutral', square, active } = props;
- return (
-
- );
-});
-
-TapButton.displayName = "TabButton";
-export default TapButton;
diff --git a/apps/client/src/features/control/playback/Transport.tsx b/apps/client/src/features/control/playback/Transport.tsx
deleted file mode 100644
index 918a037f2..000000000
--- a/apps/client/src/features/control/playback/Transport.tsx
+++ /dev/null
@@ -1,49 +0,0 @@
-import { Tooltip } from '@chakra-ui/react';
-import { IoPlaySkipBack } from '@react-icons/all-files/io5/IoPlaySkipBack';
-import { IoPlaySkipForward } from '@react-icons/all-files/io5/IoPlaySkipForward';
-import { IoReload } from '@react-icons/all-files/io5/IoReload';
-import { IoStop } from '@react-icons/all-files/io5/IoStop';
-import { Playback } from 'ontime-types';
-
-import { setPlayback } from '../../../common/hooks/useSocket';
-import { tooltipDelayMid } from '../../../ontimeConfig';
-
-import TapButton from './TapButton';
-
-import style from './PlaybackControl.module.scss';
-
-interface TransportProps {
- playback: Playback;
- noEvents: boolean;
-}
-
-export default function Transport(props: TransportProps) {
- const { playback, noEvents } = props;
- const isRolling = playback === Playback.Roll;
- const isStopped = playback === Playback.Stop;
-
- return (
-
-
- setPlayback.previous()} disabled={isRolling || noEvents}>
-
-
-
-
- setPlayback.next()} disabled={isRolling || noEvents}>
-
-
-
-
- setPlayback.reload()} disabled={isStopped || isRolling}>
-
-
-
-
- setPlayback.stop()} disabled={isStopped && !isRolling} theme={Playback.Stop}>
-
-
-
-
- );
-}
diff --git a/apps/client/src/features/control/playback/playback-buttons/PlaybackButtons.module.scss b/apps/client/src/features/control/playback/playback-buttons/PlaybackButtons.module.scss
new file mode 100644
index 000000000..fd7c39347
--- /dev/null
+++ b/apps/client/src/features/control/playback/playback-buttons/PlaybackButtons.module.scss
@@ -0,0 +1,43 @@
+@use '../../../../theme/v2Styles' as *;
+
+.buttonContainer {
+ padding-top: $element-spacing;
+ display: grid;
+ grid-template-areas:
+ "go playback"
+ "go transport"
+ "extra extra";
+ grid-template-rows: repeat(3, 32px);
+ gap: $element-spacing;
+}
+
+.go {
+ grid-area: go;
+ font-size: 5em;
+}
+
+@mixin spaced-flex {
+ display: flex;
+ justify-content: space-evenly;
+ gap: $element-spacing;
+}
+
+.playbackContainer {
+ grid-area: playback;
+ @include spaced-flex;
+}
+
+.transportContainer {
+ grid-area: transport;
+ @include spaced-flex;
+}
+
+.extra {
+ grid-area: extra;
+ @include spaced-flex;
+}
+
+.invertX {
+ transform: rotateY(180deg);
+}
+
diff --git a/apps/client/src/features/control/playback/playback-buttons/PlaybackButtons.tsx b/apps/client/src/features/control/playback/playback-buttons/PlaybackButtons.tsx
new file mode 100644
index 000000000..674e3e424
--- /dev/null
+++ b/apps/client/src/features/control/playback/playback-buttons/PlaybackButtons.tsx
@@ -0,0 +1,90 @@
+import { Tooltip } from '@chakra-ui/react';
+import { IoPause } from '@react-icons/all-files/io5/IoPause';
+import { IoPlay } from '@react-icons/all-files/io5/IoPlay';
+import { IoPlaySkipBack } from '@react-icons/all-files/io5/IoPlaySkipBack';
+import { IoPlaySkipForward } from '@react-icons/all-files/io5/IoPlaySkipForward';
+import { IoReload } from '@react-icons/all-files/io5/IoReload';
+import { IoStop } from '@react-icons/all-files/io5/IoStop';
+import { IoTimeOutline } from '@react-icons/all-files/io5/IoTimeOutline';
+import { Playback } from 'ontime-types';
+
+import { setPlayback } from '../../../../common/hooks/useSocket';
+import { tooltipDelayMid } from '../../../../ontimeConfig';
+import TapButton from '../tap-button/TapButton';
+
+import styles from './PlaybackButtons.module.scss';
+import style from './PlaybackButtons.module.scss';
+
+interface PlaybackButtonsProps {
+ playback: Playback;
+ noEvents: boolean;
+}
+
+export default function PlaybackButtons(props: PlaybackButtonsProps) {
+ const { playback, noEvents } = props;
+
+ const isRolling = playback === Playback.Roll;
+ const isPlaying = playback === Playback.Play;
+ const isPaused = playback === Playback.Pause;
+ const isArmed = playback === Playback.Armed;
+ const isStopped = playback === Playback.Stop;
+
+ return (
+
+
setPlayback.startNext()} aspect='fill' className={styles.go}>
+ GO
+
+
+ setPlayback.start()}
+ disabled={isStopped || isRolling}
+ theme={Playback.Play}
+ active={isPlaying}
+ >
+
+
+
+ setPlayback.pause()}
+ disabled={isStopped || isRolling || isArmed}
+ theme={Playback.Pause}
+ active={isPaused}
+ >
+
+
+
+
+
+ setPlayback.previous()} disabled={isRolling || noEvents}>
+
+
+
+
+ setPlayback.next()} disabled={isRolling || noEvents}>
+
+
+
+
+
+ setPlayback.roll()}
+ disabled={!isStopped || noEvents}
+ theme={Playback.Roll}
+ active={isRolling}
+ >
+
+
+
+ setPlayback.reload()} disabled={isStopped || isRolling}>
+
+
+
+
+ setPlayback.stop()} disabled={isStopped && !isRolling} theme={Playback.Stop}>
+
+
+
+
+
+ );
+}
diff --git a/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.module.scss b/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.module.scss
new file mode 100644
index 000000000..b25c9d0ad
--- /dev/null
+++ b/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.module.scss
@@ -0,0 +1,111 @@
+@use '../../../../theme/v2Styles' as *;
+@use '../../../../theme/ontimeColours' as *;
+
+.timeContainer {
+ display: grid;
+ grid-template-areas:
+ 'ind clk clk btn'
+ '... sta fin btn';
+ grid-template-rows: 1fr auto;
+ grid-template-columns: 1.5em 1fr 1fr 5em;
+ gap: $element-inner-spacing;
+ justify-items: start;
+}
+
+.timer {
+ grid-area: clk;
+ white-space: nowrap;
+ max-width: 300px;
+}
+
+.indicators {
+ grid-area: ind;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ flex-direction: column;
+ justify-content: space-evenly;
+}
+
+.indRoll,
+.indDelay,
+.indNegative {
+ background-color: $black-10;
+}
+
+.indRoll,
+.indRollActive,
+.indDelay,
+.indDelayActive {
+ margin: 0 auto;
+ border-radius: 6px;
+ width: 12px;
+ height: 12px;
+}
+
+.indRollActive {
+ background-color: $ontime-roll;
+}
+
+.indNegative,
+.indNegativeActive {
+ margin: 0 auto;
+ width: 90%;
+ height: 4px;
+}
+
+.indNegativeActive {
+ background-color: $playback-negative;
+}
+
+.indDelayActive {
+ background-color: $ontime-delay;
+}
+
+.btn {
+ grid-area: btn;
+ display: grid;
+ grid-template-columns: 1fr 1fr;
+ grid-template-rows: 1fr 1fr;
+ width: 100%;
+ gap: $element-inner-spacing;
+}
+
+.minus {
+ grid-area: min;
+ display: flex;
+ flex-direction: column;
+}
+
+.start,
+.finish,
+.roll {
+ height: 24px;
+}
+
+.start {
+ grid-area: sta;
+}
+
+.finish {
+ grid-area: fin;
+}
+
+.roll {
+ grid-area: 2 / 2 / 2 / 4 ;
+}
+
+.time {
+ color: $section-white;
+ font-size: $text-body-size;
+}
+
+.tag {
+ color: $label-gray;
+ font-size: 13px;
+}
+
+.rolltag {
+ color: $ontime-roll;
+ font-size: $text-body-size;
+}
diff --git a/apps/client/src/features/control/playback/PlaybackTimer.tsx b/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.tsx
similarity index 85%
rename from apps/client/src/features/control/playback/PlaybackTimer.tsx
rename to apps/client/src/features/control/playback/playback-timer/PlaybackTimer.tsx
index 207e64ffd..47f14ae03 100644
--- a/apps/client/src/features/control/playback/PlaybackTimer.tsx
+++ b/apps/client/src/features/control/playback/playback-timer/PlaybackTimer.tsx
@@ -2,14 +2,13 @@ import { Tooltip } from '@chakra-ui/react';
import { Playback } from 'ontime-types';
import { millisToString } from 'ontime-utils';
-import TimerDisplay from '../../../common/components/timer-display/TimerDisplay';
-import { setPlayback, useTimer } from '../../../common/hooks/useSocket';
-import { millisToMinutes, millisToSeconds } from '../../../common/utils/dateConfig';
-import { tooltipDelayMid } from '../../../ontimeConfig';
+import TimerDisplay from '../../../../common/components/timer-display/TimerDisplay';
+import { setPlayback, useTimer } from '../../../../common/hooks/useSocket';
+import { millisToMinutes, millisToSeconds } from '../../../../common/utils/dateConfig';
+import { tooltipDelayMid } from '../../../../ontimeConfig';
+import TapButton from '../tap-button/TapButton';
-import TapButton from './TapButton';
-
-import style from './PlaybackControl.module.scss';
+import style from './PlaybackTimer.module.scss';
interface PlaybackTimerProps {
playback: Playback;
@@ -36,7 +35,7 @@ export default function PlaybackTimer(props: PlaybackTimerProps) {
if (ms < 6000) {
return `${millisToSeconds(ms)} seconds`;
} else if (ms < 12000) {
- return `1 minute`;
+ return '1 minute';
} else {
return `${millisToMinutes(ms)} minutes`;
}
@@ -87,22 +86,22 @@ export default function PlaybackTimer(props: PlaybackTimerProps) {
)}
- setPlayback.delay(-1)} disabled={disableButtons} square>
+ setPlayback.delay(-1)} disabled={disableButtons} aspect='square'>
-1
- setPlayback.delay(1)} disabled={disableButtons} square>
+ setPlayback.delay(1)} disabled={disableButtons} aspect='square'>
+1
- setPlayback.delay(-5)} disabled={disableButtons} square>
+ setPlayback.delay(-5)} disabled={disableButtons} aspect='square'>
-5
- setPlayback.delay(+5)} disabled={disableButtons} square>
+ setPlayback.delay(+5)} disabled={disableButtons} aspect='square'>
+5
diff --git a/apps/client/src/features/control/playback/TapButton.module.scss b/apps/client/src/features/control/playback/tap-button/TapButton.module.scss
similarity index 88%
rename from apps/client/src/features/control/playback/TapButton.module.scss
rename to apps/client/src/features/control/playback/tap-button/TapButton.module.scss
index 6134ae132..473f4ccc7 100644
--- a/apps/client/src/features/control/playback/TapButton.module.scss
+++ b/apps/client/src/features/control/playback/tap-button/TapButton.module.scss
@@ -1,15 +1,14 @@
-@use '../../../theme/v2Styles' as *;
-@use '../../../theme/ontimeColours' as *;
+@use '../../../../theme/v2Styles' as *;
+@use '../../../../theme/ontimeColours' as *;
$button-bg-gray: $gray-1050;
$button-color-white: $gray-50;
@mixin tap-factory($theme-color) {
font-family: $ontime-font-family;
- font-size: 22px;
+ font-size: 18px;
border-radius: $component-border-radius-md;
width: 100%;
- aspect-ratio: 3/1;
transition-property: color, background-color;
transition-duration: $transition-time-feedback;
display: grid;
@@ -78,7 +77,17 @@ $button-color-white: $gray-50;
@include tap-factory($ontime-stop);
}
+.tapButton.normal {
+ aspect-ratio: 3/1;
+}
+
.tapButton.square {
aspect-ratio: 1;
font-size: 14px;
}
+
+.tapButton.fill {
+ aspect-ratio: unset;
+ height: 100%;
+ font-size: 1.5em;
+}
diff --git a/apps/client/src/features/control/playback/tap-button/TapButton.tsx b/apps/client/src/features/control/playback/tap-button/TapButton.tsx
new file mode 100644
index 000000000..3417d43df
--- /dev/null
+++ b/apps/client/src/features/control/playback/tap-button/TapButton.tsx
@@ -0,0 +1,31 @@
+import { ForwardedRef, forwardRef, PropsWithChildren } from 'react';
+import { Playback } from 'ontime-types';
+
+import { cx } from '../../../../common/utils/styleUtils';
+
+import style from './TapButton.module.scss';
+
+interface TapButtonProps {
+ disabled?: boolean;
+ aspect?: 'normal' | 'square' | 'fill';
+ square?: boolean;
+ free?: boolean;
+ onClick: () => void;
+ theme?: Playback | 'neutral';
+ active?: boolean;
+ className?: string;
+}
+
+const TapButton = forwardRef((props: PropsWithChildren, ref: ForwardedRef) => {
+ const { children, disabled, onClick, theme = 'neutral', aspect = 'normal', active, className } = props;
+ const classes = cx([style.tapButton, className, style[theme], style[aspect], active ? style.active : null]);
+
+ return (
+
+ );
+});
+
+TapButton.displayName = 'TabButton';
+export default TapButton;
diff --git a/apps/client/src/features/editors/Editor.module.scss b/apps/client/src/features/editors/Editor.module.scss
index d290cf919..2f3415de6 100644
--- a/apps/client/src/features/editors/Editor.module.scss
+++ b/apps/client/src/features/editors/Editor.module.scss
@@ -37,11 +37,11 @@ $playback-width: 450px;
grid-template-rows: auto 1fr;
grid-template-columns: $menu-width $rundown-width $playback-width auto;
grid-template-areas:
- 'sett even play info'
- 'sett even mess info';
+ 'sett rundown play info'
+ 'sett rundown mess info';
gap: 8px;
- .editor,
+ .rundown,
.playback,
.messages,
.info,
@@ -98,7 +98,7 @@ $playback-width: 450px;
visibility: visible;
}
- .editor,
+ .rundown,
.info,
.settings {
visibility: hidden;
@@ -117,7 +117,7 @@ $playback-width: 450px;
visibility: visible;
}
- .editor,
+ .rundown,
.messages,
.info,
.settings {
@@ -128,7 +128,7 @@ $playback-width: 450px;
.mainContainer {
.settings,
- .editor,
+ .rundown,
.messages,
.playback,
.info {
@@ -171,8 +171,9 @@ $playback-width: 450px;
}
}
-.editor {
- grid-area: even;
+.rundown {
+ grid-area: rundown;
+ height: 100%;
.content {
height: calc(100% - 24px);
@@ -183,6 +184,7 @@ $playback-width: 450px;
.info {
grid-area: info;
min-width: 17em;
+ max-width: 800px;
.content {
display: flex;
diff --git a/apps/client/src/features/event-editor/composite/EventEditorTimes.tsx b/apps/client/src/features/event-editor/composite/EventEditorTimes.tsx
index 46aa746ba..7eeed35cb 100644
--- a/apps/client/src/features/event-editor/composite/EventEditorTimes.tsx
+++ b/apps/client/src/features/event-editor/composite/EventEditorTimes.tsx
@@ -131,7 +131,7 @@ const EventEditorTimes = (props: EventEditorTimesProps) => {
onChange={(event) => handleSubmit('endAction', event.target.value)}
variant='ontime'
>
-
+
diff --git a/apps/client/src/features/menu/MenuBar.tsx b/apps/client/src/features/menu/MenuBar.tsx
index 74a0c34fa..fb54920e6 100644
--- a/apps/client/src/features/menu/MenuBar.tsx
+++ b/apps/client/src/features/menu/MenuBar.tsx
@@ -4,7 +4,7 @@ import { FiSave } from '@react-icons/all-files/fi/FiSave';
import { FiUpload } from '@react-icons/all-files/fi/FiUpload';
import { IoExtensionPuzzle } from '@react-icons/all-files/io5/IoExtensionPuzzle';
import { IoExtensionPuzzleOutline } from '@react-icons/all-files/io5/IoExtensionPuzzleOutline';
-import { IoHelpCircleOutline } from '@react-icons/all-files/io5/IoHelpCircleOutline';
+import { IoHelp } from '@react-icons/all-files/io5/IoHelp';
import { IoOptions } from '@react-icons/all-files/io5/IoOptions';
import { IoPlay } from '@react-icons/all-files/io5/IoPlay';
import { IoSettingsOutline } from '@react-icons/all-files/io5/IoSettingsOutline';
@@ -30,7 +30,7 @@ interface MenuBarProps {
}
const buttonStyle = {
- fontSize: '1.5em',
+ fontSize: '1.25em',
size: 'lg',
colorScheme: 'white',
_hover: {
@@ -155,7 +155,7 @@ export default function MenuBar(props: MenuBarProps) {
}
+ icon={}
clickHandler={onAboutOpen}
tooltip='About'
aria-label='About'
diff --git a/apps/client/src/features/rundown/Rundown.tsx b/apps/client/src/features/rundown/Rundown.tsx
index f42827a12..df58f5191 100644
--- a/apps/client/src/features/rundown/Rundown.tsx
+++ b/apps/client/src/features/rundown/Rundown.tsx
@@ -30,6 +30,8 @@ export default function Rundown(props: RundownProps) {
const startTimeIsLastEnd = eventSettings.startTimeIsLastEnd;
const showQuickEntry = eventSettings.showQuickEntry;
+ const isExtracted = window.location.pathname.includes('/rundown');
+
// cursor
const cursor = useAppMode((state) => state.cursor);
const appMode = useAppMode((state) => state.mode);
@@ -238,6 +240,7 @@ export default function Rundown(props: RundownProps) {
previousEventId={previousEventId}
playback={isSelected ? featureData.playback : undefined}
isRolling={featureData.playback === Playback.Roll}
+ disableEdit={isExtracted}
/>
{((showQuickEntry && hasCursor) || isLast) && (
);
} else if (data.type === SupportedEvent.Block) {
diff --git a/apps/client/src/features/rundown/RundownExport.tsx b/apps/client/src/features/rundown/RundownExport.tsx
index 1684de707..8f6c7c966 100644
--- a/apps/client/src/features/rundown/RundownExport.tsx
+++ b/apps/client/src/features/rundown/RundownExport.tsx
@@ -11,7 +11,7 @@ import style from '../editors/Editor.module.scss';
const RundownExport = () => {
return (
-
+
handleLinks(event, 'rundown')} />
diff --git a/apps/client/src/features/rundown/_blockMixins.scss b/apps/client/src/features/rundown/_blockMixins.scss
index fbd464860..1ee71a1f5 100644
--- a/apps/client/src/features/rundown/_blockMixins.scss
+++ b/apps/client/src/features/rundown/_blockMixins.scss
@@ -20,6 +20,7 @@ $block-cursor-color: $blue-400;
border-radius: $block-border-radius;
margin: 4px 2px;
position: relative;
+ color: $block-text-color;
}
@mixin block-spacing() {
diff --git a/apps/client/src/features/rundown/block-block/BlockBlock.tsx b/apps/client/src/features/rundown/block-block/BlockBlock.tsx
index e85f28661..e4f5bce99 100644
--- a/apps/client/src/features/rundown/block-block/BlockBlock.tsx
+++ b/apps/client/src/features/rundown/block-block/BlockBlock.tsx
@@ -7,7 +7,7 @@ import { OntimeBlock, OntimeEvent } from 'ontime-types';
import { cx } from '../../../common/utils/styleUtils';
import EditableBlockTitle from '../common/EditableBlockTitle';
import BlockActionMenu from '../event-block/composite/BlockActionMenu';
-import { EventItemActions } from '../RundownEntry';
+import type { EventItemActions } from '../RundownEntry';
import style from './BlockBlock.module.scss';
diff --git a/apps/client/src/features/rundown/delay-block/DelayBlock.tsx b/apps/client/src/features/rundown/delay-block/DelayBlock.tsx
index 7893eba7b..384310221 100644
--- a/apps/client/src/features/rundown/delay-block/DelayBlock.tsx
+++ b/apps/client/src/features/rundown/delay-block/DelayBlock.tsx
@@ -11,7 +11,7 @@ import DelayInput from '../../../common/components/input/delay-input/DelayInput'
import { useEventAction } from '../../../common/hooks/useEventAction';
import { cx } from '../../../common/utils/styleUtils';
import BlockActionMenu from '../event-block/composite/BlockActionMenu';
-import { EventItemActions } from '../RundownEntry';
+import type { EventItemActions } from '../RundownEntry';
import style from './DelayBlock.module.scss';
diff --git a/apps/client/src/features/rundown/event-block/EventBlock.module.scss b/apps/client/src/features/rundown/event-block/EventBlock.module.scss
index 2e3d36386..9a1a9c0d7 100644
--- a/apps/client/src/features/rundown/event-block/EventBlock.module.scss
+++ b/apps/client/src/features/rundown/event-block/EventBlock.module.scss
@@ -22,6 +22,9 @@ $skip-opacity: 0.1;
padding-right: $block-clearance;
gap: 2px;
+ transition-property: background-color;
+ transition-duration: $transition-time-feedback;
+
@mixin declare-overrides(){
--status-color-override: #{$gray-200};
--status-color-active-override: #{$green-400};
diff --git a/apps/client/src/features/rundown/event-block/EventBlock.tsx b/apps/client/src/features/rundown/event-block/EventBlock.tsx
index 0b05c65a7..e5b5d0373 100644
--- a/apps/client/src/features/rundown/event-block/EventBlock.tsx
+++ b/apps/client/src/features/rundown/event-block/EventBlock.tsx
@@ -6,7 +6,7 @@ import { EndAction, OntimeEvent, Playback, TimerType } from 'ontime-types';
import { useAppMode } from '../../../common/stores/appModeStore';
import { cx, getAccessibleColour } from '../../../common/utils/styleUtils';
-import { EventItemActions } from '../RundownEntry';
+import type { EventItemActions } from '../RundownEntry';
import EventBlockInner from './EventBlockInner';
@@ -41,6 +41,7 @@ interface EventBlockProps {
value: unknown;
},
) => void;
+ disableEdit: boolean;
}
export default function EventBlock(props: EventBlockProps) {
@@ -65,6 +66,7 @@ export default function EventBlock(props: EventBlockProps) {
playback,
isRolling,
actionHandler,
+ disableEdit,
} = props;
const moveCursorTo = useAppMode((state) => state.setCursor);
@@ -164,6 +166,7 @@ export default function EventBlock(props: EventBlockProps) {
playback={playback}
isRolling={isRolling}
actionHandler={actionHandler}
+ disableEdit={disableEdit}
/>
)}
diff --git a/apps/client/src/features/rundown/event-block/EventBlockInner.tsx b/apps/client/src/features/rundown/event-block/EventBlockInner.tsx
index 0c593f4f1..d44e20a72 100644
--- a/apps/client/src/features/rundown/event-block/EventBlockInner.tsx
+++ b/apps/client/src/features/rundown/event-block/EventBlockInner.tsx
@@ -51,6 +51,7 @@ interface EventBlockInnerProps {
playback?: Playback;
isRolling: boolean;
actionHandler: (action: EventItemActions, payload?: any) => void;
+ disableEdit: boolean;
}
const EventBlockInner = (props: EventBlockInnerProps) => {
@@ -73,6 +74,7 @@ const EventBlockInner = (props: EventBlockInnerProps) => {
playback,
isRolling,
actionHandler,
+ disableEdit,
} = props;
const [renderInner, setRenderInner] = useState(false);
@@ -159,6 +161,7 @@ const EventBlockInner = (props: EventBlockInnerProps) => {
tabIndex={-1}
backgroundColor={isOpen ? '#2B5ABC' : undefined}
color={isOpen ? 'white' : '#f6f6f6'}
+ isDisabled={disableEdit}
/>
diff --git a/apps/client/src/features/rundown/event-block/composite/BlockActionMenu.tsx b/apps/client/src/features/rundown/event-block/composite/BlockActionMenu.tsx
index f7a4b7e2a..6af87948b 100644
--- a/apps/client/src/features/rundown/event-block/composite/BlockActionMenu.tsx
+++ b/apps/client/src/features/rundown/event-block/composite/BlockActionMenu.tsx
@@ -59,7 +59,7 @@ export default function BlockActionMenu(props: BlockActionMenuProps) {
)}
} onClick={handleDelete} isDisabled={!enableDelete} color='#D20300'>
- Delete event
+ Delete
diff --git a/apps/client/src/features/viewers/clock/Clock.tsx b/apps/client/src/features/viewers/clock/Clock.tsx
index 95d6bc86d..1da514f76 100644
--- a/apps/client/src/features/viewers/clock/Clock.tsx
+++ b/apps/client/src/features/viewers/clock/Clock.tsx
@@ -36,8 +36,8 @@ export default function Clock(props: ClockProps) {
return null;
}
- // get config from url: key, text, font, size, hidenav, hideovertime
- // eg. http://localhost:3000/minimal?key=f00&text=fff
+ // get config from url: key, text, font, size, hidenav
+ // eg. http://localhost:3000/clock?key=f00&text=fff
// Check for user options
const userOptions: OverridableOptions = {
size: 1,
@@ -126,7 +126,6 @@ export default function Clock(props: ClockProps) {
className={`clock-view ${isMirrored ? 'mirror' : ''}`}
style={{
backgroundColor: userOptions.keyColour,
- color: userOptions.textColour,
justifyContent: userOptions.justifyContent,
alignItems: userOptions.alignItems,
}}
@@ -136,6 +135,7 @@ export default function Clock(props: ClockProps) {
= {
subtitle: '',
presenter: '',
note: '',
- endAction: EndAction.Continue,
+ endAction: EndAction.None,
timerType: TimerType.CountDown,
timeStart: 0,
timeEnd: 0,
diff --git a/apps/server/src/services/PlaybackService.ts b/apps/server/src/services/PlaybackService.ts
index f2f00c70d..8f92199c2 100644
--- a/apps/server/src/services/PlaybackService.ts
+++ b/apps/server/src/services/PlaybackService.ts
@@ -116,15 +116,15 @@ export class PlaybackService {
return true;
}
} else if (fallbackAction === 'stop') {
- logger.info('PLAYBACK', `No next event found! Stopping playback`);
+ logger.info('PLAYBACK', 'No next event found! Stopping playback');
PlaybackService.stop();
return false;
} else if (fallbackAction === 'pause') {
- logger.info('PLAYBACK', `No next event found! Pausing playback`);
+ logger.info('PLAYBACK', 'No next event found! Pausing playback');
PlaybackService.pause();
return false;
} else {
- logger.info('PLAYBACK', `No next event found! Continuing playback`);
+ logger.info('PLAYBACK', 'No next event found! Continuing playback');
return false;
}
}
diff --git a/apps/server/src/utils/parser.ts b/apps/server/src/utils/parser.ts
index 84df30ca5..a773cc272 100644
--- a/apps/server/src/utils/parser.ts
+++ b/apps/server/src/utils/parser.ts
@@ -371,10 +371,11 @@ export const fileHandler = async (file) => {
res.data.userFields = parseUserFields(dataFromExcel);
res.message = 'success';
} else {
- console.log('Error: No sheets found named ontime or event schedule');
+ const errorMessage = 'No sheet found named ontime or event schedule';
+ console.log(errorMessage);
res = {
error: true,
- message: `No sheets found named ontime or event schedule`,
+ message: errorMessage,
};
}
} catch (error) {
diff --git a/apps/server/src/utils/parserFunctions.ts b/apps/server/src/utils/parserFunctions.ts
index 6fe717209..745d2967c 100644
--- a/apps/server/src/utils/parserFunctions.ts
+++ b/apps/server/src/utils/parserFunctions.ts
@@ -91,7 +91,7 @@ export const parseEventData = (data, enforce): EventData => {
};
} else if (enforce) {
newEventData = { ...dbModel.eventData };
- console.log(`Created event object in db`);
+ console.log('Created event object in db');
}
return newEventData as EventData;
};
@@ -126,7 +126,7 @@ export const parseSettings = (data, enforce): Settings => {
}
} else if (enforce) {
newSettings = dbModel.settings;
- console.log(`Created settings object in db`);
+ console.log('Created settings object in db');
}
return newSettings as Settings;
};
@@ -153,7 +153,7 @@ export const parseViewSettings = (data, enforce): ViewSettings => {
};
} else if (enforce) {
newViews = dbModel.viewSettings;
- console.log(`Created viewSettings object in db`);
+ console.log('Created viewSettings object in db');
}
return newViews as ViewSettings;
};
@@ -201,7 +201,7 @@ export const parseOsc = (data: { osc?: Partial }, enforce: boolean)
subscriptions: validatedSubscriptions,
};
} else if (enforce) {
- console.log(`Created OSC object in db`);
+ console.log('Created OSC object in db');
return { ...dbModel.osc };
} else return {};
};
@@ -232,7 +232,7 @@ export const parseHttp = (data, enforce) => {
} else if (enforce) {
// @ts-expect-error -- not yet
newHttp.http = { ...dbModel.http };
- console.log(`Created http object in db`);
+ console.log('Created http object in db');
}
return newHttp;
};
diff --git a/apps/test-db/db.json b/apps/test-db/db.json
index d40f05e04..3f2f409b7 100644
--- a/apps/test-db/db.json
+++ b/apps/test-db/db.json
@@ -1,5 +1,98 @@
{
- "rundown": [],
+ "rundown": [
+ {
+ "title": "First test event",
+ "subtitle": "",
+ "presenter": "",
+ "note": "",
+ "endAction": "continue",
+ "timerType": "count-down",
+ "timeStart": 32400000,
+ "timeEnd": 36000000,
+ "duration": 3600000,
+ "isPublic": true,
+ "skip": false,
+ "colour": "",
+ "user0": "",
+ "user1": "",
+ "user2": "",
+ "user3": "",
+ "user4": "",
+ "user5": "",
+ "user6": "",
+ "user7": "",
+ "user8": "",
+ "user9": "",
+ "type": "event",
+ "revision": 0,
+ "id": "aa42f"
+ },
+ {
+ "duration": 600000,
+ "type": "delay",
+ "revision": 0,
+ "id": "b1d5a"
+ },
+ {
+ "title": "Second test event",
+ "subtitle": "",
+ "presenter": "",
+ "note": "",
+ "endAction": "continue",
+ "timerType": "count-down",
+ "timeStart": 36000000,
+ "timeEnd": 39600000,
+ "duration": 3600000,
+ "isPublic": true,
+ "skip": false,
+ "colour": "",
+ "user0": "",
+ "user1": "",
+ "user2": "",
+ "user3": "",
+ "user4": "",
+ "user5": "",
+ "user6": "",
+ "user7": "",
+ "user8": "",
+ "user9": "",
+ "type": "event",
+ "revision": 0,
+ "id": "d71bc"
+ },
+ {
+ "title": "Lunch",
+ "type": "block",
+ "id": "91682"
+ },
+ {
+ "title": "Third test event",
+ "subtitle": "",
+ "presenter": "",
+ "note": "",
+ "endAction": "continue",
+ "timerType": "count-down",
+ "timeStart": 39600000,
+ "timeEnd": 720000,
+ "duration": 0,
+ "isPublic": true,
+ "skip": false,
+ "colour": "",
+ "user0": "",
+ "user1": "",
+ "user2": "",
+ "user3": "",
+ "user4": "",
+ "user5": "",
+ "user6": "",
+ "user7": "",
+ "user8": "",
+ "user9": "",
+ "type": "event",
+ "revision": 0,
+ "id": "da5b4"
+ }
+ ],
"eventData": {
"title": "All about Carlos demo event",
"publicUrl": "www.getontime.no",
diff --git a/demo-db/db.json b/demo-db/db.json
index 52292f682..01a663d1f 100644
--- a/demo-db/db.json
+++ b/demo-db/db.json
@@ -2,118 +2,15 @@
"rundown": [
{
"title": "Welcome to Ontime",
- "subtitle": "Subtitles are useful",
- "presenter": "cpvalente",
- "note": "Maybe a running note for the operator?",
- "timeStart": 28800000,
- "timeEnd": 30600000,
- "timeType": "start-end",
- "duration": 1800000,
- "isPublic": false,
- "skip": false,
- "colour": "",
- "user0": "",
- "user1": "",
- "user2": "",
- "user3": "",
- "user4": "",
- "user5": "",
- "user6": "",
- "user7": "",
- "user8": "",
- "user9": "",
- "type": "event",
- "revision": 0,
- "id": "5946"
- },
- {
- "title": "This is your event list",
- "subtitle": "",
- "presenter": "cpvalente",
- "note": "",
- "timeStart": 30600000,
- "timeEnd": 34200000,
- "timeType": "start-end",
- "duration": 3600000,
- "isPublic": false,
- "skip": false,
- "colour": "",
- "user0": "",
- "user1": "",
- "user2": "",
- "user3": "",
- "user4": "",
- "user5": "",
- "user6": "",
- "user7": "",
- "user8": "",
- "user9": "",
- "type": "event",
- "revision": 0,
- "id": "c2e7"
- },
- {
- "title": "Events run in the list order",
"subtitle": "",
"presenter": "",
- "note": "",
- "timeStart": 34200000,
- "timeEnd": 34800000,
- "timeType": "start-end",
- "duration": 600000,
- "isPublic": false,
- "skip": false,
- "colour": "",
- "user0": "",
- "user1": "",
- "user2": "",
- "user3": "",
- "user4": "",
- "user5": "",
- "user6": "",
- "user7": "",
- "user8": "",
- "user9": "",
- "type": "event",
- "revision": 0,
- "id": "cc0f"
- },
- {
- "title": "Unless recalled by the OSC address",
- "subtitle": "",
- "presenter": "",
- "note": "In green, below",
- "timeStart": 34800000,
- "timeEnd": 35400000,
- "timeType": "start-end",
- "duration": 600000,
- "isPublic": false,
- "skip": false,
- "colour": "",
- "user0": "",
- "user1": "",
- "user2": "",
- "user3": "",
- "user4": "",
- "user5": "",
- "user6": "",
- "user7": "",
- "user8": "",
- "user9": "",
- "type": "event",
- "revision": 0,
- "id": "8ee5"
- },
- {
- "title": "Use simpler times to create a timer",
- "subtitle": "",
- "presenter": "",
- "note": "",
+ "note": "Ontime is an app for managing event rundowns",
+ "endAction": "none",
+ "timerType": "count-down",
"timeStart": 0,
"timeEnd": 600000,
- "timeType": "start-end",
"duration": 600000,
- "isPublic": false,
+ "isPublic": true,
"skip": false,
"colour": "",
"user0": "",
@@ -127,100 +24,12 @@
"user8": "",
"user9": "",
"type": "event",
- "revision": 0,
- "id": "8222"
- },
- {
- "duration": 900000,
- "type": "delay",
- "revision": 0,
- "id": "a386"
- },
- {
- "title": "Add delay blocks to affect all events",
- "subtitle": "",
- "presenter": "",
- "note": "* Until a block is found",
- "timeStart": 35400000,
- "timeEnd": 36600000,
- "timeType": "start-end",
- "duration": 1200000,
- "isPublic": false,
- "skip": false,
- "colour": "",
- "user0": "",
- "user1": "",
- "user2": "",
- "user3": "",
- "user4": "",
- "user5": "",
- "user6": "",
- "user7": "",
- "user8": "",
- "user9": "",
- "type": "event",
- "revision": 0,
- "id": "6dce"
- },
- {
- "title": "Add and remove events with [+] and [-]",
- "subtitle": "",
- "presenter": "",
- "note": "Orange and red buttons on the right",
- "timeStart": 36600000,
- "timeEnd": 43200000,
- "timeType": "start-end",
- "duration": 6600000,
- "isPublic": false,
- "skip": false,
- "colour": "",
- "user0": "",
- "user1": "",
- "user2": "",
- "user3": "",
- "user4": "",
- "user5": "",
- "user6": "",
- "user7": "",
- "user8": "",
- "user9": "",
- "type": "event",
- "revision": 0,
- "id": "2651"
- },
- {
- "type": "block",
- "id": "e6a1"
- },
- {
- "title": "And control whether they are public",
- "subtitle": "",
- "presenter": "",
- "note": "Blue button on the right",
- "timeStart": 46800000,
- "timeEnd": 57600000,
- "timeType": "start-end",
- "duration": 10800000,
- "isPublic": false,
- "skip": false,
- "colour": "",
- "user0": "",
- "user1": "",
- "user2": "",
- "user3": "",
- "user4": "",
- "user5": "",
- "user6": "",
- "user7": "",
- "user8": "",
- "user9": "",
- "type": "event",
- "revision": 0,
- "id": "1358"
+ "revision": 1,
+ "id": "5a6e1"
}
],
"eventData": {
- "title": "All about Carlos demo event",
+ "title": "Ontime demo event",
"publicUrl": "www.getontime.no",
"publicInfo": "WiFi: demoproject \nPassword: ontimeproject",
"backstageUrl": "www.getontime.no",
@@ -229,19 +38,55 @@
},
"settings": {
"app": "ontime",
- "version": 1,
+ "version": 2,
"serverPort": 4001,
"lock": null,
- "pinCode": "1234"
+ "pinCode": "1234",
+ "timeFormat": "24"
},
"viewSettings": {
"overrideStyles": false
},
+ "aliases": [
+ {
+ "id": "0b0b3",
+ "enabled": true,
+ "alias": "test",
+ "pathAndParams": "lower?bg=ff2&text=f00&size=0.6&transition=5"
+ }
+ ],
+ "userFields": {
+ "user0": "user0",
+ "user1": "user1",
+ "user2": "user2",
+ "user3": "user3",
+ "user4": "user4",
+ "user5": "user5",
+ "user6": "user6",
+ "user7": "user7",
+ "user8": "user8",
+ "user9": "user9"
+ },
"osc": {
- "port": 8888,
+ "portIn": 8888,
"portOut": 9999,
"targetIP": "127.0.0.1",
- "enabled": true
+ "enabledIn": true,
+ "enabledOut": true,
+ "subscriptions": {
+ "onLoad": [],
+ "onStart": [],
+ "onPause": [],
+ "onStop": [],
+ "onUpdate": [
+ {
+ "id": "10eea",
+ "enabled": true,
+ "message": "/ontime/update/{{timer.current}}"
+ }
+ ],
+ "onFinish": []
+ }
},
"http": {
"http": {
@@ -275,25 +120,5 @@
},
"enabled": true
}
- },
- "aliases": [
- {
- "id": "0b0b3",
- "enabled": true,
- "alias": "test",
- "pathAndParams": "lower?bg=ff2&text=f00&size=0.6&transition=5"
- }
- ],
- "userFields": {
- "user0": "user0",
- "user1": "user1",
- "user2": "user2",
- "user3": "user3",
- "user4": "user4",
- "user5": "user5",
- "user6": "user6",
- "user7": "user7",
- "user8": "user8",
- "user9": "user9"
}
}
\ No newline at end of file
diff --git a/e2e/tests/features/101-minimal-url.spec.ts b/e2e/tests/features/101-minimal-url.spec.ts
deleted file mode 100644
index 0de4b5373..000000000
--- a/e2e/tests/features/101-minimal-url.spec.ts
+++ /dev/null
@@ -1,14 +0,0 @@
-import { expect, test } from '@playwright/test';
-
-test.describe('minimal view behaviour can be changed through params', () => {
- test.use({ viewport: { width: 1920, height: 1080 } });
- test('without overloads', async ({ page }) => {
- await page.goto('http://localhost:4001/minimal');
- await page.getByTestId('minimal-timer').click();
- });
- test('hide nav', async ({ page }) => {
- await page.goto('http://localhost:4001/minimal?hidenav=true');
- const navBar = await page.locator('data-test-id=nav-logo');
- await expect(navBar).toHaveCount(0);
- });
-});
\ No newline at end of file
diff --git a/packages/types/src/definitions/EndAction.type.ts b/packages/types/src/definitions/EndAction.type.ts
index 6f2f670ab..36e63d799 100644
--- a/packages/types/src/definitions/EndAction.type.ts
+++ b/packages/types/src/definitions/EndAction.type.ts
@@ -1,5 +1,5 @@
export enum EndAction {
- Continue = 'continue',
+ None = 'none',
Stop = 'stop',
LoadNext = 'load-next',
PlayNext = 'play-next',