From 770d12888d322c7af4f04fcb1ee26d8989c9f3d1 Mon Sep 17 00:00:00 2001 From: Carlos Valente <34649812+cpvalente@users.noreply.github.com> Date: Fri, 14 Apr 2023 10:13:46 +0200 Subject: [PATCH] V2 beta3 (#338) * chore: upgrade local build documentation * style: keep scrolling event in screen * feat: delay is time entry * refactor: remove unused * refactor: remove unused * refactor: batch store updates * refactor: virtually remove cap on events * refactor: style and behaviour tweaks to event block * style: tweaks on schedules * chore: remove sentry from server * style: reorder menu * chore: update docs --- DEVELOPMENT.md | 2 +- README.md | 13 +- apps/client/package.json | 1 - .../input/delay-input/DelayInput.module.scss | 19 ++- .../input/delay-input/DelayInput.tsx | 156 ++++++++++++------ .../components/input/time-input/TimeInput.tsx | 28 ++-- .../common/components/schedule/Schedule.scss | 2 +- .../components/schedule/ScheduleContext.tsx | 22 ++- apps/client/src/common/hooks/useSocket.ts | 1 + .../common/utils/__tests__/dateConfig.test.js | 140 +++++++--------- apps/client/src/common/utils/dateConfig.ts | 33 ++-- apps/client/src/common/utils/time.ts | 8 +- .../src/features/editors/Editor.module.scss | 4 +- .../event-editor/EventEditor.module.scss | 2 +- .../composite/EventEditorTimes.tsx | 21 +-- apps/client/src/features/menu/MenuBar.tsx | 52 +++--- apps/client/src/features/rundown/Rundown.tsx | 3 +- .../src/features/rundown/RundownEntry.tsx | 16 +- .../src/features/rundown/_blockMixins.scss | 2 +- .../rundown/delay-block/DelayBlock.tsx | 21 +-- .../event-block/EventBlock.module.scss | 25 ++- .../rundown/event-block/EventBlock.tsx | 4 + .../rundown/event-block/EventBlockInner.tsx | 25 ++- .../composite/EventBlockPlayback.tsx | 60 ++++++- .../EventBlockProgressBar.module.scss | 10 +- .../composite/EventBlockTimers.tsx | 12 +- .../client/src/features/table/OntimeTable.jsx | 8 +- .../features/viewers/backstage/Backstage.scss | 6 +- .../src/features/viewers/public/Public.scss | 5 +- apps/client/src/theme/_ontimeColours.scss | 1 + apps/client/src/theme/ontimeButton.ts | 12 ++ apps/client/src/theme/ontimeCheckbox.ts | 10 +- apps/client/src/theme/ontimeRadio.ts | 27 +++ apps/client/src/theme/theme.ts | 6 + apps/server/package.json | 2 - apps/server/src/app.ts | 9 +- .../src/classes/event-loader/EventLoader.ts | 8 +- apps/server/src/modules/loadDb.ts | 5 +- apps/server/src/modules/loadStyles.ts | 5 +- apps/server/src/modules/sentry.js | 19 --- apps/server/src/services/RundownService.ts | 35 ++-- apps/server/src/services/TimerService.ts | 24 ++- apps/server/src/settings.js | 1 - apps/server/src/settings.ts | 1 + apps/server/src/stores/EventStore.ts | 10 ++ packages/utils/index.ts | 1 + .../utils/src/date-utils/formatFromMillis.ts | 11 ++ pnpm-lock.yaml | 19 +-- 48 files changed, 531 insertions(+), 376 deletions(-) create mode 100644 apps/client/src/theme/ontimeRadio.ts delete mode 100644 apps/server/src/modules/sentry.js delete mode 100644 apps/server/src/settings.js create mode 100644 apps/server/src/settings.ts create mode 100644 packages/utils/src/date-utils/formatFromMillis.ts diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index cc575cdf1..38346a629 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -27,7 +27,7 @@ You can generate a distribution for your OS by running the following steps. From the project root, run the following commands - __Install the project dependencies__ by running `pnpm i` -- __Build the UI and server__ by running `turbo build` +- __Build the UI and server__ by running `turbo build:local` - __Create the package__ by running `turbo dist-win`, `turbo dist-mac` or `turbo dist-linux` The build distribution assets will be at `.apps/electron/dist` diff --git a/README.md b/README.md index 5074f534c..2a059dd77 100644 --- a/README.md +++ b/README.md @@ -65,6 +65,7 @@ More documentation is available [in our docs](https://cpvalente.gitbook.io/ontim - Backstage Info - Public Info - Studio Clock + - Countdown - [Make your own?](#make-your-own-viewer) - [x] Configurable Lower Thirds - [x] Cuesheets with user definable fields @@ -109,11 +110,11 @@ Taking advantage of the integrations, we currently use Ontime with: ### Make your own viewer -Ontime broadcasts its data over WebSockets. This allows you to consume its data outside of the application. +Ontime broadcasts its data over WebSockets. This allows you to consume its data outside the application. Writing a new view for the browser can be done with basic knowledge of HTML + CSS + Javascript (or any other language that can run in the browser).
-See [this repository](https://github.com/cpvalente/ontime-viewer-template) with a small template on +See [this repository](https://github.com/cpvalente/ontime-viewer-template-v2) with a small template on how to get you started and read the docs about the [Websocket API](https://app.gitbook.com/s/-Mc0giSOToAhq0ROd0CR/control-and-feedback/websocket-api) @@ -132,13 +133,7 @@ in [available Docker Hub at getontime/ontime](https://hub.docker.com/r/getontime docker pull getontime/ontime ``` -```bash -# Port 4001 - ontime server port -# Port 8888 - OSC input, bound to localhost IP Address -docker run -p 4001:4001 -p 127.0.0.1:8888:8888/udp --mount type=bind,source="$(pwd)/ontime-db",target=/server/preloaded-db getontime/ontime -``` - -or if running from the docker compose +and use the included docker compose to get started ```bash docker-compose up diff --git a/apps/client/package.json b/apps/client/package.json index 80070172e..1e4a7c2e7 100644 --- a/apps/client/package.json +++ b/apps/client/package.json @@ -20,7 +20,6 @@ "csv-stringify": "^6.2.3", "deepmerge": "^4.3.0", "framer-motion": "^10.10.0", - "luxon": "^3.3.0", "react": "^18.2.0", "react-dom": "^18.2.0", "react-fast-compare": "^3.2.0", diff --git a/apps/client/src/common/components/input/delay-input/DelayInput.module.scss b/apps/client/src/common/components/input/delay-input/DelayInput.module.scss index edad5c2d9..a7cb4f03f 100644 --- a/apps/client/src/common/components/input/delay-input/DelayInput.module.scss +++ b/apps/client/src/common/components/input/delay-input/DelayInput.module.scss @@ -1,13 +1,24 @@ @use '../../../../theme/v2Styles' as *; +$input-font-size: 15px; + .delayInput { display: flex; gap: $element-spacing; align-items: center; - color: $ontime-delay-text; font-size: $text-body-size; + + + .inputField { + font-size: $input-font-size; + letter-spacing: 1px; + max-width: 7em; + padding-left: 16px; + color: $ontime-delay-text + } } -.inputField { - text-align: center; -} \ No newline at end of file +.delayOptions { + display: flex; + flex-direction: column; +} diff --git a/apps/client/src/common/components/input/delay-input/DelayInput.tsx b/apps/client/src/common/components/input/delay-input/DelayInput.tsx index c53ef0994..a9b6681ed 100644 --- a/apps/client/src/common/components/input/delay-input/DelayInput.tsx +++ b/apps/client/src/common/components/input/delay-input/DelayInput.tsx @@ -1,88 +1,134 @@ -import { useCallback, useEffect, useRef, useState } from 'react'; -import { Input } from '@chakra-ui/react'; +import { KeyboardEvent, useEffect, useRef, useState } from 'react'; +import { Input, Radio, RadioGroup } from '@chakra-ui/react'; +import { millisToString } from 'ontime-utils'; -import { clamp } from '../../../utils/math'; +import { useEventAction } from '../../../hooks/useEventAction'; +import { forgivingStringToMillis } from '../../../utils/dateConfig'; import style from './DelayInput.module.scss'; -const inputStyleProps = { - width: 20, - placeholder: '-', - size: 'sm', - color: '#E69056', - variant: 'ontime-filled', - fontSize: '15px', - letterSpacing: '0.3px', -}; - interface DelayInputProps { - submitHandler: (value: number) => void; - value?: number; + eventId: string; + duration: number; } export default function DelayInput(props: DelayInputProps) { - const { submitHandler, value = 0 } = props; - const [_value, setValue] = useState(value); + const { eventId, duration } = props; + const { updateEvent } = useEventAction(); + + const [value, setValue] = useState(''); const inputRef = useRef(null); + // avoid wrong submit on cancel + let ignoreChange = false; useEffect(() => { - if (!value) { + if (typeof duration === undefined) { return; } - setValue(value); - }, [value]); + setValue(millisToString(duration)); + }, [duration]); /** * @description Prepare delay value for update - * @param {string} value string to be parsed + * @param {string} newValue string to be parsed */ - const validate = useCallback( - (newValue?: string) => { - if (newValue === '') setValue(0); - const delayValue = clamp(Number(newValue), -60, 60); - if (delayValue === value) return; - setValue(delayValue); + const validateAndSubmit = (newValue: string) => { + if (ignoreChange) { + ignoreChange = false; + return; + } - submitHandler(delayValue); - }, - [submitHandler, value], - ); + const isNegative = newValue.startsWith('-'); + let newMillis = forgivingStringToMillis(newValue); + + if (isNegative) { + newMillis = newMillis * -1; + } + + if (newMillis === duration) { + return; + } + + submitChange(newMillis); + setValue(millisToString(newMillis)); + }; + + const submitChange = (value: number) => { + updateEvent({ + id: eventId, + duration: value, + }); + }; + + /** + * @description Selects input text on focus + */ + const handleFocus = () => inputRef.current?.select(); /** * @description Handles common keys for submit and cancel * @param {KeyboardEvent} event */ - const onKeyDownHandler = useCallback( - (key: string) => { - if (key === 'Enter') { - inputRef.current?.blur(); - validate(inputRef.current?.value); - } else if (key === 'Escape') { - inputRef.current?.blur(); - setValue(value); - } - }, - [validate, value], - ); + const onKeyDownHandler = (event: KeyboardEvent) => { + if (event.key === 'Enter') { + inputRef.current?.blur(); + validateAndSubmit((event.target as HTMLInputElement).value); + } else if (event.key === 'Tab') { + validateAndSubmit((event.target as HTMLInputElement).value); + } else if (event.key === 'Escape') { + ignoreChange = true; + setValue(millisToString(duration)); + inputRef.current?.blur(); + } + }; - const labelText = `${Math.abs(value) !== 1 ? 'minutes' : 'minute'} ${ - value !== undefined && value >= 0 ? 'delayed' : 'ahead' - }`; + /** + * @description handles direction change to delay + * @param newDirection + */ + const handleSlipChange = (newDirection: 'add' | 'subtract') => { + if (newDirection === 'add') { + // add time + if (duration < 0) { + submitChange(duration * -1); + } + } else if (newDirection === 'subtract') { + // subtract time + if (duration > 0) { + submitChange(duration * -1); + } + } + }; + + const checkedOption = value.startsWith('-') ? 'subtract' : 'add'; return ( -