From 8ff82b2cc02fa86dbb1725b094a29bbacd0bd475 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Wed, 3 May 2023 21:23:47 +0200 Subject: [PATCH 01/22] refactor: folder structure --- apps/client/src/features/editors/Editor.tsx | 4 ++-- .../modals/{ => settings}/AliasesModal.jsx | 17 ++++++++--------- .../modals/{ => settings}/AppSettingsModal.jsx | 14 +++++++------- .../{ => settings}/EventSettingsModal.jsx | 13 ++++++------- .../Settings.tsx} | 2 +- .../modals/{ => settings}/SubmitContainer.jsx | 2 +- .../{ => settings}/TableOptionsModal.jsx | 13 ++++++------- .../{ => settings}/ViewsSettingsModal.tsx | 18 +++++++++--------- 8 files changed, 40 insertions(+), 43 deletions(-) rename apps/client/src/features/modals/{ => settings}/AliasesModal.jsx (95%) rename apps/client/src/features/modals/{ => settings}/AppSettingsModal.jsx (94%) rename apps/client/src/features/modals/{ => settings}/EventSettingsModal.jsx (93%) rename apps/client/src/features/modals/{ModalManager.tsx => settings/Settings.tsx} (96%) rename apps/client/src/features/modals/{ => settings}/SubmitContainer.jsx (94%) rename apps/client/src/features/modals/{ => settings}/TableOptionsModal.jsx (91%) rename apps/client/src/features/modals/{ => settings}/ViewsSettingsModal.tsx (92%) diff --git a/apps/client/src/features/editors/Editor.tsx b/apps/client/src/features/editors/Editor.tsx index 94db948d15..824b93b511 100644 --- a/apps/client/src/features/editors/Editor.tsx +++ b/apps/client/src/features/editors/Editor.tsx @@ -6,8 +6,8 @@ import UploadModal from '../../common/components/upload-modal/UploadModal'; import MenuBar from '../menu/MenuBar'; import AboutModal from '../modals/about-modal/AboutModal'; import IntegrationModal from '../modals/integration-modal/IntegrationModal'; -import ModalManager from '../modals/ModalManager'; import QuickStart from '../modals/quick-start/QuickStart'; +import Settings from '../modals/settings/Settings'; import styles from './Editor.module.scss'; @@ -40,7 +40,7 @@ export default function Editor() { - +
diff --git a/apps/client/src/features/modals/AliasesModal.jsx b/apps/client/src/features/modals/settings/AliasesModal.jsx similarity index 95% rename from apps/client/src/features/modals/AliasesModal.jsx rename to apps/client/src/features/modals/settings/AliasesModal.jsx index 92222d9f14..838d716f2c 100644 --- a/apps/client/src/features/modals/AliasesModal.jsx +++ b/apps/client/src/features/modals/settings/AliasesModal.jsx @@ -5,18 +5,17 @@ import { IoInformationCircleOutline } from '@react-icons/all-files/io5/IoInforma import { IoRemove } from '@react-icons/all-files/io5/IoRemove'; import { IoSunny } from '@react-icons/all-files/io5/IoSunny'; -import { useEmitLog } from '@/common/stores/logger'; - -import { viewerLocations } from '../../appConstants'; -import { postAliases } from '../../common/api/ontimeApi'; -import useAliases from '../../common/hooks-query/useAliases'; -import { validateAlias } from '../../common/utils/aliases'; -import { handleLinks, host } from '../../common/utils/linkUtils'; -import { tooltipDelayFast } from '../../ontimeConfig'; +import { viewerLocations } from '../../../appConstants'; +import { postAliases } from '../../../common/api/ontimeApi'; +import useAliases from '../../../common/hooks-query/useAliases'; +import { useEmitLog } from '../../../common/stores/logger'; +import { validateAlias } from '../../../common/utils/aliases'; +import { handleLinks, host } from '../../../common/utils/linkUtils'; +import { tooltipDelayFast } from '../../../ontimeConfig'; import SubmitContainer from './SubmitContainer'; -import style from './Modals.module.scss'; +import style from '../Modals.module.scss'; export default function AliasesModal() { const { data, status, refetch } = useAliases(); diff --git a/apps/client/src/features/modals/AppSettingsModal.jsx b/apps/client/src/features/modals/settings/AppSettingsModal.jsx similarity index 94% rename from apps/client/src/features/modals/AppSettingsModal.jsx rename to apps/client/src/features/modals/settings/AppSettingsModal.jsx index 35bd0ccd7b..eb54de6c37 100644 --- a/apps/client/src/features/modals/AppSettingsModal.jsx +++ b/apps/client/src/features/modals/settings/AppSettingsModal.jsx @@ -16,16 +16,16 @@ import { FiX } from '@react-icons/all-files/fi/FiX'; import { useEmitLog } from '@/common/stores/logger'; -import { postSettings } from '../../common/api/ontimeApi'; -import TooltipActionBtn from '../../common/components/buttons/TooltipActionBtn'; -import useSettings from '../../common/hooks-query/useSettings'; -import { ontimePlaceholderSettings } from '../../common/models/OntimeSettings'; -import { useLocalEvent } from '../../common/stores/localEvent'; +import { postSettings } from '../../../common/api/ontimeApi'; +import TooltipActionBtn from '../../../common/components/buttons/TooltipActionBtn'; +import useSettings from '../../../common/hooks-query/useSettings'; +import { ontimePlaceholderSettings } from '../../../common/models/OntimeSettings'; +import { useLocalEvent } from '../../../common/stores/localEvent'; +import { inputProps } from '../modalHelper'; -import { inputProps } from './modalHelper'; import SubmitContainer from './SubmitContainer'; -import style from './Modals.module.scss'; +import style from '../Modals.module.scss'; export default function AppSettingsModal() { const { data, status, refetch } = useSettings(); diff --git a/apps/client/src/features/modals/EventSettingsModal.jsx b/apps/client/src/features/modals/settings/EventSettingsModal.jsx similarity index 93% rename from apps/client/src/features/modals/EventSettingsModal.jsx rename to apps/client/src/features/modals/settings/EventSettingsModal.jsx index ee0bb472e8..882265dd2a 100644 --- a/apps/client/src/features/modals/EventSettingsModal.jsx +++ b/apps/client/src/features/modals/settings/EventSettingsModal.jsx @@ -1,16 +1,15 @@ import { useCallback, useEffect, useState } from 'react'; import { FormLabel, Input, ModalBody, Textarea } from '@chakra-ui/react'; -import { useEmitLog } from '@/common/stores/logger'; +import { postEventData } from '../../../common/api/eventDataApi'; +import useEventData from '../../../common/hooks-query/useEventData'; +import { eventDataPlaceholder } from '../../../common/models/EventData'; +import { useEmitLog } from '../../../common/stores/logger'; +import { inputProps } from '../modalHelper'; -import { postEventData } from '../../common/api/eventDataApi'; -import useEventData from '../../common/hooks-query/useEventData'; -import { eventDataPlaceholder } from '../../common/models/EventData'; - -import { inputProps } from './modalHelper'; import SubmitContainer from './SubmitContainer'; -import style from './Modals.module.scss'; +import style from '../Modals.module.scss'; export default function SettingsModal() { const { data, status, refetch } = useEventData(); diff --git a/apps/client/src/features/modals/ModalManager.tsx b/apps/client/src/features/modals/settings/Settings.tsx similarity index 96% rename from apps/client/src/features/modals/ModalManager.tsx rename to apps/client/src/features/modals/settings/Settings.tsx index 866c18bfa2..0a2d00d1a4 100644 --- a/apps/client/src/features/modals/ModalManager.tsx +++ b/apps/client/src/features/modals/settings/Settings.tsx @@ -22,7 +22,7 @@ interface ModalManagerProps { onClose: () => void; } -export default function ModalManager(props: ModalManagerProps) { +export default function Settings(props: ModalManagerProps) { const { isOpen, onClose } = props; return ( Date: Wed, 3 May 2023 21:25:05 +0200 Subject: [PATCH 02/22] refactor: folder structure --- apps/client/src/features/editors/Editor.tsx | 4 ++-- .../modals/{settings => settings-modal}/AliasesModal.jsx | 0 .../modals/{settings => settings-modal}/AppSettingsModal.jsx | 0 .../{settings => settings-modal}/EventSettingsModal.jsx | 0 .../Settings.tsx => settings-modal/SettingsModal.tsx} | 2 +- .../modals/{settings => settings-modal}/SubmitContainer.jsx | 0 .../modals/{settings => settings-modal}/TableOptionsModal.jsx | 0 .../{settings => settings-modal}/ViewsSettingsModal.tsx | 0 8 files changed, 3 insertions(+), 3 deletions(-) rename apps/client/src/features/modals/{settings => settings-modal}/AliasesModal.jsx (100%) rename apps/client/src/features/modals/{settings => settings-modal}/AppSettingsModal.jsx (100%) rename apps/client/src/features/modals/{settings => settings-modal}/EventSettingsModal.jsx (100%) rename apps/client/src/features/modals/{settings/Settings.tsx => settings-modal/SettingsModal.tsx} (96%) rename apps/client/src/features/modals/{settings => settings-modal}/SubmitContainer.jsx (100%) rename apps/client/src/features/modals/{settings => settings-modal}/TableOptionsModal.jsx (100%) rename apps/client/src/features/modals/{settings => settings-modal}/ViewsSettingsModal.tsx (100%) diff --git a/apps/client/src/features/editors/Editor.tsx b/apps/client/src/features/editors/Editor.tsx index 824b93b511..8031bd6ceb 100644 --- a/apps/client/src/features/editors/Editor.tsx +++ b/apps/client/src/features/editors/Editor.tsx @@ -7,7 +7,7 @@ import MenuBar from '../menu/MenuBar'; import AboutModal from '../modals/about-modal/AboutModal'; import IntegrationModal from '../modals/integration-modal/IntegrationModal'; import QuickStart from '../modals/quick-start/QuickStart'; -import Settings from '../modals/settings/Settings'; +import SettingsModal from '../modals/settings-modal/SettingsModal'; import styles from './Editor.module.scss'; @@ -40,7 +40,7 @@ export default function Editor() { - +
diff --git a/apps/client/src/features/modals/settings/AliasesModal.jsx b/apps/client/src/features/modals/settings-modal/AliasesModal.jsx similarity index 100% rename from apps/client/src/features/modals/settings/AliasesModal.jsx rename to apps/client/src/features/modals/settings-modal/AliasesModal.jsx diff --git a/apps/client/src/features/modals/settings/AppSettingsModal.jsx b/apps/client/src/features/modals/settings-modal/AppSettingsModal.jsx similarity index 100% rename from apps/client/src/features/modals/settings/AppSettingsModal.jsx rename to apps/client/src/features/modals/settings-modal/AppSettingsModal.jsx diff --git a/apps/client/src/features/modals/settings/EventSettingsModal.jsx b/apps/client/src/features/modals/settings-modal/EventSettingsModal.jsx similarity index 100% rename from apps/client/src/features/modals/settings/EventSettingsModal.jsx rename to apps/client/src/features/modals/settings-modal/EventSettingsModal.jsx diff --git a/apps/client/src/features/modals/settings/Settings.tsx b/apps/client/src/features/modals/settings-modal/SettingsModal.tsx similarity index 96% rename from apps/client/src/features/modals/settings/Settings.tsx rename to apps/client/src/features/modals/settings-modal/SettingsModal.tsx index 0a2d00d1a4..3da90dc8de 100644 --- a/apps/client/src/features/modals/settings/Settings.tsx +++ b/apps/client/src/features/modals/settings-modal/SettingsModal.tsx @@ -22,7 +22,7 @@ interface ModalManagerProps { onClose: () => void; } -export default function Settings(props: ModalManagerProps) { +export default function SettingsModal(props: ModalManagerProps) { const { isOpen, onClose } = props; return ( Date: Wed, 3 May 2023 21:31:26 +0200 Subject: [PATCH 03/22] style: modal wrapper --- .../modals/settings-modal/SettingsModal.tsx | 38 +++++-------------- 1 file changed, 9 insertions(+), 29 deletions(-) diff --git a/apps/client/src/features/modals/settings-modal/SettingsModal.tsx b/apps/client/src/features/modals/settings-modal/SettingsModal.tsx index 3da90dc8de..a95da52742 100644 --- a/apps/client/src/features/modals/settings-modal/SettingsModal.tsx +++ b/apps/client/src/features/modals/settings-modal/SettingsModal.tsx @@ -1,15 +1,6 @@ -import { - Modal, - ModalCloseButton, - ModalContent, - ModalHeader, - ModalOverlay, - Tab, - TabList, - TabPanel, - TabPanels, - Tabs, -} from '@chakra-ui/react'; +import { ModalBody, Tab, TabList, TabPanel, TabPanels, Tabs } from '@chakra-ui/react'; + +import ModalWrapper from '../ModalWrapper'; import AliasesModal from './AliasesModal'; import AppSettingsModal from './AppSettingsModal'; @@ -25,23 +16,12 @@ interface ModalManagerProps { export default function SettingsModal(props: ModalManagerProps) { const { isOpen, onClose } = props; return ( - - - - Ontime Settings - - - + + + App Settings - Viewers + Views Event Data URL Aliases Cuesheet @@ -64,7 +44,7 @@ export default function SettingsModal(props: ModalManagerProps) { - - + + ); } From 896f1a5baebd01aa2fe6bedc0e458fccf58f86df Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Wed, 3 May 2023 21:33:02 +0200 Subject: [PATCH 04/22] chore: typescript --- .../settings-modal/{AppSettingsModal.jsx => AppSettings.tsx} | 3 +-- .../src/features/modals/settings-modal/SettingsModal.tsx | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) rename apps/client/src/features/modals/settings-modal/{AppSettingsModal.jsx => AppSettings.tsx} (99%) diff --git a/apps/client/src/features/modals/settings-modal/AppSettingsModal.jsx b/apps/client/src/features/modals/settings-modal/AppSettings.tsx similarity index 99% rename from apps/client/src/features/modals/settings-modal/AppSettingsModal.jsx rename to apps/client/src/features/modals/settings-modal/AppSettings.tsx index eb54de6c37..891a48937e 100644 --- a/apps/client/src/features/modals/settings-modal/AppSettingsModal.jsx +++ b/apps/client/src/features/modals/settings-modal/AppSettings.tsx @@ -14,13 +14,12 @@ import { import { FiEye } from '@react-icons/all-files/fi/FiEye'; import { FiX } from '@react-icons/all-files/fi/FiX'; -import { useEmitLog } from '@/common/stores/logger'; - import { postSettings } from '../../../common/api/ontimeApi'; import TooltipActionBtn from '../../../common/components/buttons/TooltipActionBtn'; import useSettings from '../../../common/hooks-query/useSettings'; import { ontimePlaceholderSettings } from '../../../common/models/OntimeSettings'; import { useLocalEvent } from '../../../common/stores/localEvent'; +import { useEmitLog } from '../../../common/stores/logger'; import { inputProps } from '../modalHelper'; import SubmitContainer from './SubmitContainer'; diff --git a/apps/client/src/features/modals/settings-modal/SettingsModal.tsx b/apps/client/src/features/modals/settings-modal/SettingsModal.tsx index a95da52742..f1354ae82e 100644 --- a/apps/client/src/features/modals/settings-modal/SettingsModal.tsx +++ b/apps/client/src/features/modals/settings-modal/SettingsModal.tsx @@ -3,7 +3,7 @@ import { ModalBody, Tab, TabList, TabPanel, TabPanels, Tabs } from '@chakra-ui/r import ModalWrapper from '../ModalWrapper'; import AliasesModal from './AliasesModal'; -import AppSettingsModal from './AppSettingsModal'; +import AppSettingsModal from './AppSettings'; import EventSettingsModal from './EventSettingsModal'; import TableOptionsModal from './TableOptionsModal'; import ViewsSettingsModal from './ViewsSettingsModal'; From e714434f63a071da67ef1dfd34978a83c363a8b1 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Thu, 4 May 2023 21:10:40 +0200 Subject: [PATCH 05/22] docs: reword views --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index c0c894b352..f0d5a4dbd5 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ Ontime is an application for managing event rundowns and running stage timers. A single, locally hosted central application distributes your event information over the local network. -This enables the distribution of the data to a series of viewers and allows integration into video and control workflows, including OBS and d3. +This enables the distribution of the data to a series of views and allows integration into video and control workflows, including OBS and d3. ![App Window](https://github.com/cpvalente/ontime/blob/master/.github/aux-images/app.jpg) From b1d2da794188019d6f77be37bab35eedc887aaf7 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Thu, 4 May 2023 21:10:58 +0200 Subject: [PATCH 06/22] refactor: share footer component --- .../modals/{integration-modal => }/OntimeModalFooter.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename apps/client/src/features/modals/{integration-modal => }/OntimeModalFooter.tsx (95%) diff --git a/apps/client/src/features/modals/integration-modal/OntimeModalFooter.tsx b/apps/client/src/features/modals/OntimeModalFooter.tsx similarity index 95% rename from apps/client/src/features/modals/integration-modal/OntimeModalFooter.tsx rename to apps/client/src/features/modals/OntimeModalFooter.tsx index c178ee2ae3..ea9110863b 100644 --- a/apps/client/src/features/modals/integration-modal/OntimeModalFooter.tsx +++ b/apps/client/src/features/modals/OntimeModalFooter.tsx @@ -1,6 +1,6 @@ import { Button, ModalFooter } from '@chakra-ui/react'; -import styles from '../Modal.module.scss'; +import styles from './Modal.module.scss'; interface OntimeModalFooterProps { formId: string; From ea4a7e0da08996a846b765d5fde317dc65b7ad2b Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Thu, 4 May 2023 21:19:40 +0200 Subject: [PATCH 07/22] refactor: share footer component --- .../src/features/modals/integration-modal/OscIntegration.tsx | 2 +- .../src/features/modals/integration-modal/OscSettings.tsx | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/apps/client/src/features/modals/integration-modal/OscIntegration.tsx b/apps/client/src/features/modals/integration-modal/OscIntegration.tsx index ee369ca6b2..6e671c81c0 100644 --- a/apps/client/src/features/modals/integration-modal/OscIntegration.tsx +++ b/apps/client/src/features/modals/integration-modal/OscIntegration.tsx @@ -7,8 +7,8 @@ import { generateId } from 'ontime-utils'; import useOscSettings, { useOscSettingsMutation } from '../../../common/hooks-query/useOscSettings'; import { oscPlaceholderSettings, PlaceholderSettings } from '../../../common/models/OscSettings'; import { useEmitLog } from '../../../common/stores/logger'; +import OntimeModalFooter from '../OntimeModalFooter'; -import OntimeModalFooter from './OntimeModalFooter'; import OscSubscriptionRow from './OscSubscriptionRow'; import styles from '../Modal.module.scss'; diff --git a/apps/client/src/features/modals/integration-modal/OscSettings.tsx b/apps/client/src/features/modals/integration-modal/OscSettings.tsx index 5b87b3ad59..dffbf26698 100644 --- a/apps/client/src/features/modals/integration-modal/OscSettings.tsx +++ b/apps/client/src/features/modals/integration-modal/OscSettings.tsx @@ -5,8 +5,7 @@ import useOscSettings, { useOscSettingsMutation } from '../../../common/hooks-qu import { PlaceholderSettings } from '../../../common/models/OscSettings'; import { useEmitLog } from '../../../common/stores/logger'; import { isIPAddress, isOnlyNumbers } from '../../../common/utils/regex'; - -import OntimeModalFooter from './OntimeModalFooter'; +import OntimeModalFooter from '../OntimeModalFooter'; import styles from '../Modal.module.scss'; From 4dcfa0d0bafa50d20678f815bbe57d4b107545f6 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Thu, 4 May 2023 21:41:07 +0200 Subject: [PATCH 08/22] feat: add nordic translations --- .../src/translation/TranslationProvider.jsx | 5 +++++ apps/client/src/translation/languages/no.ts | 18 ++++++++++++++++++ apps/client/src/translation/languages/sv.ts | 18 ++++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 apps/client/src/translation/languages/no.ts create mode 100644 apps/client/src/translation/languages/sv.ts diff --git a/apps/client/src/translation/TranslationProvider.jsx b/apps/client/src/translation/TranslationProvider.jsx index 814f9666c3..fe8c9308a6 100644 --- a/apps/client/src/translation/TranslationProvider.jsx +++ b/apps/client/src/translation/TranslationProvider.jsx @@ -2,11 +2,16 @@ import React, { createContext, useCallback, useContext, useState } from 'react'; import { langDe } from '@/translation/languages/de'; import { langEn } from '@/translation/languages/en'; +import { langNo } from '@/translation/languages/no'; +import { langSv } from '@/translation/languages/sv'; const translationsList = { en: langEn, de: langDe, + no: langNo, + sv: langSv, }; + const ALLOWED_LANGUAGES = Object.keys(translationsList); const DEFAULT_LANGUAGE = 'en'; export const TranslationContext = createContext(undefined); diff --git a/apps/client/src/translation/languages/no.ts b/apps/client/src/translation/languages/no.ts new file mode 100644 index 0000000000..2d2795d64f --- /dev/null +++ b/apps/client/src/translation/languages/no.ts @@ -0,0 +1,18 @@ +import { TranslationObject } from '../Translation.types'; + +export const langNo: TranslationObject = { + 'common.end_time': 'Sluttid', + 'common.expected_finish': 'Forventet slutt', + 'common.now': 'Nå', + 'common.next': 'Neste', + 'common.public_message': 'Offentlig beskjed', + 'common.start_time': 'Starttid', + 'common.stage_timer': 'Scenetimer', + 'common.started_at': 'Startet', + 'common.time_now': 'Tid nå', + 'countdown.ended': 'Hendelse avsluttet', + 'countdown.running': 'Hendelse pågår', + 'countdown.select_event': 'Velg en hendelse å følge', + 'countdown.to_start': 'Tid til start', + 'countdown.waiting': 'Venter på start', +}; diff --git a/apps/client/src/translation/languages/sv.ts b/apps/client/src/translation/languages/sv.ts new file mode 100644 index 0000000000..5ad271c693 --- /dev/null +++ b/apps/client/src/translation/languages/sv.ts @@ -0,0 +1,18 @@ +import { TranslationObject } from '../Translation.types'; + +export const langSv: TranslationObject = { + 'common.end_time': 'Sluttid', + 'common.expected_finish': 'Förväntat slut', + 'common.now': 'Nu', + 'common.next': 'Nästa', + 'common.public_message': 'Offentligt meddelande', + 'common.start_time': 'Starttid', + 'common.stage_timer': 'Timer för scenen', + 'common.started_at': 'Började vid', + 'common.time_now': 'Tid nu', + 'countdown.ended': 'Evenemanget avslutades vid', + 'countdown.running': 'Evenemang pågår', + 'countdown.select_event': 'Välj ett evenemang att följa', + 'countdown.to_start': 'Tid till start', + 'countdown.waiting': '"Väntar på att evenemanget ska starta', +}; From d42ebc6293825cd88e6e54f7c366e9d7343129b5 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Thu, 4 May 2023 21:51:27 +0200 Subject: [PATCH 09/22] refactor: update data models --- apps/server/src/models/dataModel.ts | 36 ++----------------- apps/server/src/utils/parserFunctions.ts | 22 +++--------- .../types/src/definitions/DataModel.type.ts | 1 - .../src/definitions/core/Settings.type.ts | 5 +-- 4 files changed, 10 insertions(+), 54 deletions(-) diff --git a/apps/server/src/models/dataModel.ts b/apps/server/src/models/dataModel.ts index 1e895ac73e..9938216105 100644 --- a/apps/server/src/models/dataModel.ts +++ b/apps/server/src/models/dataModel.ts @@ -13,9 +13,10 @@ export const dbModel: DatabaseModel = { app: 'ontime', version: 2, serverPort: 4001, - lock: null, - pinCode: null, + editorKey: null, + operatorKey: null, timeFormat: '24', + language: 'en', }, viewSettings: { overrideStyles: false, @@ -54,35 +55,4 @@ export const dbModel: DatabaseModel = { onFinish: [], }, }, - http: { - user: null, - pwd: null, - messages: { - onLoad: { - url: '', - enabled: false, - }, - onStart: { - url: '', - enabled: false, - }, - onUpdate: { - url: '', - enabled: false, - }, - onPause: { - url: '', - enabled: false, - }, - onStop: { - url: '', - enabled: false, - }, - onFinish: { - url: '', - enabled: false, - }, - }, - enabled: true, - }, }; diff --git a/apps/server/src/utils/parserFunctions.ts b/apps/server/src/utils/parserFunctions.ts index ef0210731a..7d5d44cfed 100644 --- a/apps/server/src/utils/parserFunctions.ts +++ b/apps/server/src/utils/parserFunctions.ts @@ -112,9 +112,10 @@ export const parseSettings = (data, enforce): Settings => { console.log('ERROR: unknown app version, skipping'); } else { const settings = { - lock: s.lock || null, - pinCode: s.pinCode || null, + editorKey: s.editorKey || null, + operatorKey: s.operatorKey || null, timeFormat: s.timeFormat || '24', + language: s.timeFormat || 'en', }; // write to db @@ -221,23 +222,8 @@ export const parseHttp = (data, enforce) => { const newHttp = {}; if ('http' in data) { console.log('Found HTTP definition, importing...'); - const h = data.http; - const http = {}; - - // @ts-expect-error -- not yet - if (h.user) http.user = h.user; - // @ts-expect-error -- not yet - if (h.pwd) http.pwd = h.pwd; - - // @ts-expect-error -- not yet - newHttp.http = { - ...dbModel.http, - ...http, - }; } else if (enforce) { - // @ts-expect-error -- not yet - newHttp.http = { ...dbModel.http }; - console.log('Created http object in db'); + /* Not yet */ } return newHttp; }; diff --git a/packages/types/src/definitions/DataModel.type.ts b/packages/types/src/definitions/DataModel.type.ts index c5a95f78bd..3b4945cabe 100644 --- a/packages/types/src/definitions/DataModel.type.ts +++ b/packages/types/src/definitions/DataModel.type.ts @@ -14,5 +14,4 @@ export type DatabaseModel = { aliases: Alias[]; userFields: UserFields; osc: OSCSettings; - http: any; }; diff --git a/packages/types/src/definitions/core/Settings.type.ts b/packages/types/src/definitions/core/Settings.type.ts index 0986e88d93..7443358cb9 100644 --- a/packages/types/src/definitions/core/Settings.type.ts +++ b/packages/types/src/definitions/core/Settings.type.ts @@ -4,7 +4,8 @@ export type Settings = { app: 'ontime'; version: 2; serverPort: 4001; - lock: null | boolean; - pinCode: null | number | string; + editorKey: null | number | string; + operatorKey: null | number | string; timeFormat: TimeFormat; + language: string; }; From 5b51e37577578f11e7fbcccba3b0ae030e2497c6 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Sun, 7 May 2023 22:27:16 +0200 Subject: [PATCH 10/22] refactor: app settings --- .../modals/settings-modal/AppSettings.tsx | 337 +++++------------- 1 file changed, 96 insertions(+), 241 deletions(-) diff --git a/apps/client/src/features/modals/settings-modal/AppSettings.tsx b/apps/client/src/features/modals/settings-modal/AppSettings.tsx index 891a48937e..e04b85d26d 100644 --- a/apps/client/src/features/modals/settings-modal/AppSettings.tsx +++ b/apps/client/src/features/modals/settings-modal/AppSettings.tsx @@ -1,256 +1,111 @@ -import { useEffect, useState } from 'react'; -import isEqual from 'react-fast-compare'; -import { - Checkbox, - FormControl, - FormLabel, - IconButton, - Input, - ModalBody, - PinInput, - PinInputField, - Select, -} from '@chakra-ui/react'; -import { FiEye } from '@react-icons/all-files/fi/FiEye'; -import { FiX } from '@react-icons/all-files/fi/FiX'; +import { useForm } from 'react-hook-form'; +import { Input, Select } from '@chakra-ui/react'; +import type { Settings } from 'ontime-types'; import { postSettings } from '../../../common/api/ontimeApi'; -import TooltipActionBtn from '../../../common/components/buttons/TooltipActionBtn'; import useSettings from '../../../common/hooks-query/useSettings'; -import { ontimePlaceholderSettings } from '../../../common/models/OntimeSettings'; -import { useLocalEvent } from '../../../common/stores/localEvent'; -import { useEmitLog } from '../../../common/stores/logger'; -import { inputProps } from '../modalHelper'; +import { isOnlyNumbers } from '../../../common/utils/regex'; +import ModalSplitInput from '../ModalSplitInput'; +import OntimeModalFooter from '../OntimeModalFooter'; -import SubmitContainer from './SubmitContainer'; - -import style from '../Modals.module.scss'; +import ModalPinInput from './ModalPinInput'; export default function AppSettingsModal() { const { data, status, refetch } = useSettings(); - const { emitError, emitWarning } = useEmitLog(); - const [formData, setFormData] = useState(ontimePlaceholderSettings); - const [changed, setChanged] = useState(false); - const [submitting, setSubmitting] = useState(false); - const [hidePin, setHidePin] = useState(true); - - const eventSettings = useLocalEvent((state) => state.eventSettings); - const setLocalEventSettings = useLocalEvent((state) => state.setLocalEventSettings); - - const [formSettings, setFormSettings] = useState(eventSettings); - - /** - * Set formdata from server state - */ - useEffect(() => { - if (data == null) return; - if (changed) return; - setFormData({ - pinCode: data.pinCode, - timeFormat: data.timeFormat, - }); - }, [changed, data]); - - /** - * Validate and submit data - */ - const submitHandler = async (event) => { - event.preventDefault(); - setSubmitting(true); - const validation = { isValid: false, message: '' }; - - const hasChanged = !isEqual(formSettings, eventSettings); - if (hasChanged) { - setLocalEventSettings(formSettings); - validation.isValid = true; - } - - // we might not have changed this - if (formData.pinCode !== data.pinCode) { - // Validate fields - if (formData.pinCode === '' || formData.pinCode == null) { - validation.isValid = true; - validation.message += 'App pin code removed'; - } else { - validation.isValid = true; - validation.message += 'App pin code added'; - } - } - - if (formData.timeFormat !== data.timeFormat) { - if (formData.timeFormat === '12' || formData.timeFormat === '24') { - validation.isValid = true; - } else { - validation.isValue = false; - } - } - - let resetChange = hasChanged; - // set fields with error - if (!validation.isValid) { - emitError(`Invalid Input: ${validation.message}`); - } else { - try { - await postSettings(formData); - } catch (error) { - emitError(`Error saving settings: ${error}`); - } finally { - await refetch(); - resetChange = true; - } - validation?.message && emitWarning(validation.message); - } - if (resetChange) { - setChanged(false); - } - setSubmitting(false); - }; - - /** - * Reverts local state equals to server state - */ - const revert = async () => { - setChanged(false); - // set from context - setFormSettings(eventSettings); - await refetch(); + const { + handleSubmit, + register, + reset, + formState: { errors, isSubmitting, isDirty, isValid }, + } = useForm({ + defaultValues: data, + values: data, + }); + + const onSubmit = async (formData: Settings) => { + await postSettings(formData); + refetch(); }; - /** - * Handles change of input field in local state - * @param {string} field - object parameter to update - * @param {string} value - new object parameter value - */ - const handleChange = (field, value) => { - const temp = { ...formData }; - temp[field] = value; - setFormData(temp); - setChanged(true); + const onReset = () => { + reset(data); }; - const disableModal = status !== 'success'; + const disableInputs = status === 'loading'; return ( - -

- Options related to the application -
- 🔥 Changes take effect on save 🔥 -

-
-
-
General App Settings
-
- - - Viewer Port - -
- Ontime is available at port -
-
- -
- - - Editor Pincode - -
- Protect the editor with a Pincode -
-
-
- handleChange('pinCode', value)} - > - - - - - - } - aria-label='Editor pin code' - onMouseDown={() => setHidePin(false)} - onMouseUp={() => setHidePin(true)} - isDisabled={disableModal} - /> - } - clickHandler={() => handleChange('pinCode', '')} - isDisabled={disableModal} - /> -
-
-
-
- - - Time format - -
- 12 / 24 hour format (viewers only for now) -
-
- -
-
-
Create Event Default Settings
-
- { - setFormSettings((prev) => ({ ...prev, showQuickEntry: e.target.checked })); - setChanged(true); - }} - > - Show quick entry on cursor - - { - setFormSettings((prev) => ({ ...prev, startTimeIsLastEnd: e.target.checked })); - setChanged(true); - }} - > - Start time is last end - - { - setFormSettings((prev) => ({ ...prev, defaultPublic: e.target.checked })); - setChanged(true); - }} - > - Event default public - -
-
- - -
+
+ + + + + + + + + +
+ + + + + + + + ); } From e3e77b2d77bc97de1707aa02575b8642658baf17 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Sun, 7 May 2023 22:41:07 +0200 Subject: [PATCH 11/22] refactor: editor settings --- .../modals/settings-modal/EditorSettings.tsx | 44 +++++++++++++++++++ 1 file changed, 44 insertions(+) create mode 100644 apps/client/src/features/modals/settings-modal/EditorSettings.tsx diff --git a/apps/client/src/features/modals/settings-modal/EditorSettings.tsx b/apps/client/src/features/modals/settings-modal/EditorSettings.tsx new file mode 100644 index 0000000000..cbf2d37738 --- /dev/null +++ b/apps/client/src/features/modals/settings-modal/EditorSettings.tsx @@ -0,0 +1,44 @@ +import { Switch } from '@chakra-ui/react'; + +import { useLocalEvent } from '../../../common/stores/localEvent'; +import ModalSplitInput from '../ModalSplitInput'; + +import style from './SettingsModal.module.scss'; + +export default function EditorSettings() { + const eventSettings = useLocalEvent((state) => state.eventSettings); + const setShowQuickEntry = useLocalEvent((state) => state.setShowQuickEntry); + const setStartTimeIsLastEnd = useLocalEvent((state) => state.setStartTimeIsLastEnd); + const setDefaultPublic = useLocalEvent((state) => state.setDefaultPublic); + + return ( +
+ Rundown settings + + setShowQuickEntry(event.target.checked)} + /> + + + setStartTimeIsLastEnd(event.target.checked)} + /> + + + setDefaultPublic(event.target.checked)} + /> + +
+ ); +} From dd8f7b470eb6b9205355c598cfa74953b3454272 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Sun, 7 May 2023 22:44:24 +0200 Subject: [PATCH 12/22] refactor: remove unused dataset --- apps/server/src/classes/data-provider/DataProvider.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/apps/server/src/classes/data-provider/DataProvider.ts b/apps/server/src/classes/data-provider/DataProvider.ts index fcf34c0761..b727d8d818 100644 --- a/apps/server/src/classes/data-provider/DataProvider.ts +++ b/apps/server/src/classes/data-provider/DataProvider.ts @@ -44,8 +44,12 @@ export class DataProvider { } static async deleteEvent(eventId) { - data.rundown = Array.from(data.rundown).filter((e) => e.id !== eventId); - await this.persist(); + const eventIndex = data.rundown.findIndex((e) => e.id === eventId); + + if (eventIndex !== -1) { + data.rundown.splice(eventIndex, 1); + await this.persist(); + } } static getRundownLength() { @@ -165,7 +169,6 @@ export class DataProvider { data.settings = mergedData.settings; data.viewSettings = mergedData.viewSettings; data.osc = mergedData.osc; - data.http = mergedData.http; data.aliases = mergedData.aliases; data.userFields = mergedData.userFields; data.rundown = mergedData.rundown; From 1f55c34aa2b47f10922cea189254f7651703250a Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Sun, 7 May 2023 22:45:40 +0200 Subject: [PATCH 13/22] refactor: app settings --- .../src/common/models/OntimeSettings.ts | 5 +- .../src/features/modals/Modal.module.scss | 13 ++++- .../src/features/modals/ModalSplitInput.tsx | 29 +++++++++++ .../modals/settings-modal/ModalPinInput.tsx | 39 +++++++++++++++ .../settings-modal/SettingsModal.module.scss | 7 +++ .../modals/settings-modal/SettingsModal.tsx | 17 ++++--- .../src/controllers/ontimeController.ts | 49 ++++++++++--------- .../controllers/ontimeController.validate.js | 4 +- .../src/definitions/core/Settings.type.ts | 4 +- 9 files changed, 131 insertions(+), 36 deletions(-) create mode 100644 apps/client/src/features/modals/ModalSplitInput.tsx create mode 100644 apps/client/src/features/modals/settings-modal/ModalPinInput.tsx create mode 100644 apps/client/src/features/modals/settings-modal/SettingsModal.module.scss diff --git a/apps/client/src/common/models/OntimeSettings.ts b/apps/client/src/common/models/OntimeSettings.ts index 2839cdc4e6..f234defc1e 100644 --- a/apps/client/src/common/models/OntimeSettings.ts +++ b/apps/client/src/common/models/OntimeSettings.ts @@ -4,7 +4,8 @@ export const ontimePlaceholderSettings: Settings = { app: 'ontime', version: 2, serverPort: 4001, - lock: null, - pinCode: null, + editorKey: null, + operatorKey: null, timeFormat: '24', + language: 'en', }; diff --git a/apps/client/src/features/modals/Modal.module.scss b/apps/client/src/features/modals/Modal.module.scss index ace41df490..4855713b3a 100644 --- a/apps/client/src/features/modals/Modal.module.scss +++ b/apps/client/src/features/modals/Modal.module.scss @@ -13,7 +13,7 @@ $el-padding-with-compensation: 24px; // 16 + 8 } } -.headerNotes { +.headerNotes { font-size: $text-body-size; width: 100%; padding: 0 $el-padding-with-compensation; @@ -26,7 +26,7 @@ $el-padding-with-compensation: 24px; // 16 + 8 } } -.footerNotes { +.footerNotes { font-size: $inner-section-text-size; padding: 0 $el-padding-with-compensation; color: $modal-note-color; @@ -38,6 +38,14 @@ $el-padding-with-compensation: 24px; // 16 + 8 border-top: 1px solid $gray-100; } +.title { + font-size: $inner-section-text-size; + color: $gray-500; + padding-left: 8px; + margin: 8px 0; + text-transform: uppercase; +} + .sectionContainer { padding: 8px 16px; display: flex; @@ -70,6 +78,7 @@ $el-padding-with-compensation: 24px; // 16 + 8 font-size: $inner-section-text-size; display: block; width: 100%; + &.main { font-weight: 600; } diff --git a/apps/client/src/features/modals/ModalSplitInput.tsx b/apps/client/src/features/modals/ModalSplitInput.tsx new file mode 100644 index 0000000000..6e0b0f181b --- /dev/null +++ b/apps/client/src/features/modals/ModalSplitInput.tsx @@ -0,0 +1,29 @@ +import { PropsWithChildren } from 'react'; +import { FormControl } from '@chakra-ui/react'; + +import style from './settings-modal/SettingsModal.module.scss'; + +interface ModalSplitInputProps { + field: string; + title: string; + description: string; + error?: string; +} + +export default function ModalSplitInput(props: PropsWithChildren) { + const { field, title, description, error, children } = props; + + return ( + + + {children} + + ); +} diff --git a/apps/client/src/features/modals/settings-modal/ModalPinInput.tsx b/apps/client/src/features/modals/settings-modal/ModalPinInput.tsx new file mode 100644 index 0000000000..56cfbab3ff --- /dev/null +++ b/apps/client/src/features/modals/settings-modal/ModalPinInput.tsx @@ -0,0 +1,39 @@ +import { useState } from 'react'; +import { UseFormRegister } from 'react-hook-form'; +import { IconButton, Input } from '@chakra-ui/react'; +import { IoEyeOutline } from '@react-icons/all-files/io5/IoEyeOutline'; + +import style from './SettingsModal.module.scss'; + +interface ModalPinInputProps { + register: UseFormRegister; + formName: string; + isDisabled?: boolean; +} + +export default function ModalPinInput({ register, formName, isDisabled }: ModalPinInputProps) { + const [isVisible, setVisible] = useState(false); + return ( +
+ + setVisible(true)} + onMouseUp={() => setVisible(false)} + size='sm' + variant='ghost' + icon={} + aria-label='Show pin code' + isDisabled={false} + /> +
+ ); +} diff --git a/apps/client/src/features/modals/settings-modal/SettingsModal.module.scss b/apps/client/src/features/modals/settings-modal/SettingsModal.module.scss new file mode 100644 index 0000000000..ce6851bab1 --- /dev/null +++ b/apps/client/src/features/modals/settings-modal/SettingsModal.module.scss @@ -0,0 +1,7 @@ +@import "../Modal.module.scss"; + +.pin { + display: flex; + gap: 0.5em; + border-radius: 50%; +} diff --git a/apps/client/src/features/modals/settings-modal/SettingsModal.tsx b/apps/client/src/features/modals/settings-modal/SettingsModal.tsx index f1354ae82e..346e38d5c3 100644 --- a/apps/client/src/features/modals/settings-modal/SettingsModal.tsx +++ b/apps/client/src/features/modals/settings-modal/SettingsModal.tsx @@ -4,6 +4,7 @@ import ModalWrapper from '../ModalWrapper'; import AliasesModal from './AliasesModal'; import AppSettingsModal from './AppSettings'; +import EditorSettings from './EditorSettings'; import EventSettingsModal from './EventSettingsModal'; import TableOptionsModal from './TableOptionsModal'; import ViewsSettingsModal from './ViewsSettingsModal'; @@ -21,27 +22,31 @@ export default function SettingsModal(props: ModalManagerProps) { App Settings - Views Event Data - URL Aliases + Editor Cuesheet + Views + URL Aliases - - - - + + + + + + + diff --git a/apps/server/src/controllers/ontimeController.ts b/apps/server/src/controllers/ontimeController.ts index ba2dd38b82..d941b43c3c 100644 --- a/apps/server/src/controllers/ontimeController.ts +++ b/apps/server/src/controllers/ontimeController.ts @@ -178,16 +178,23 @@ export const postUserFields = async (req, res) => { // Create controller for POST request to '/ontime/settings' // Returns - export const getSettings = async (req, res) => { - const { version, serverPort, pinCode, timeFormat } = DataProvider.getSettings(); - - res.status(200).send({ - version, - serverPort, - pinCode, - timeFormat, - }); + const settings = DataProvider.getSettings(); + res.status(200).send(settings); }; +function extractPin(value: string | undefined | null, fallback: string | null): string | null { + if (value === null) { + return value; + } + if (typeof value === 'undefined') { + return fallback; + } + if (value.length === 0) { + return null; + } + return value; +} + // Create controller for POST request to '/ontime/settings' // Returns ACK message export const postSettings = async (req, res) => { @@ -196,26 +203,22 @@ export const postSettings = async (req, res) => { } try { const settings = DataProvider.getSettings(); - let pin = settings.pinCode; - if (typeof req.body?.pinCode === 'string') { - if (req.body?.pinCode.length === 0) { - pin = null; - } else if (req.body?.pinCode.length <= 4) { - pin = req.body?.pinCode; - } - } + const editorKey = extractPin(req.body?.editorKey, settings.editorKey); + const operatorKey = extractPin(req.body?.operatorKey, settings.operatorKey); - let format = settings.timeFormat; - if (typeof req.body?.timeFormat === 'string') { - if (req.body?.timeFormat === '12' || req.body?.timeFormat === '24') { - format = req.body.timeFormat; - } + let timeFormat = settings.timeFormat; + if (req.body?.timeFormat === '12' || req.body?.timeFormat === '24') { + timeFormat = req.body.timeFormat; } + const language = req.body?.language || 'en'; + const newData = { ...settings, - pinCode: pin, - timeFormat: format, + editorKey, + operatorKey, + timeFormat, + language, }; await DataProvider.setSettings(newData); res.status(200).send(newData); diff --git a/apps/server/src/controllers/ontimeController.validate.js b/apps/server/src/controllers/ontimeController.validate.js index b65881483f..16ad59b354 100644 --- a/apps/server/src/controllers/ontimeController.validate.js +++ b/apps/server/src/controllers/ontimeController.validate.js @@ -54,8 +54,10 @@ export const validateUserFields = [ * @description Validates object for POST /ontime/settings */ export const validateSettings = [ - body('pinCode').isString().isLength({ min: 0, max: 4 }).optional({ nullable: true }), + body('editorKey').isString().isLength({ min: 0, max: 4 }).optional({ nullable: true }), + body('operatorKey').isString().isLength({ min: 0, max: 4 }).optional({ nullable: true }), body('timeFormat').isString().isIn(['12', '24']), + body('language').isString(), (req, res, next) => { const errors = validationResult(req); if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() }); diff --git a/packages/types/src/definitions/core/Settings.type.ts b/packages/types/src/definitions/core/Settings.type.ts index 7443358cb9..9e7b1d0ffa 100644 --- a/packages/types/src/definitions/core/Settings.type.ts +++ b/packages/types/src/definitions/core/Settings.type.ts @@ -4,8 +4,8 @@ export type Settings = { app: 'ontime'; version: 2; serverPort: 4001; - editorKey: null | number | string; - operatorKey: null | number | string; + editorKey: null | string; + operatorKey: null | string; timeFormat: TimeFormat; language: string; }; From 78ee7a63acd3c3ed54620ff06688322dc0db3916 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Tue, 9 May 2023 11:25:41 +0200 Subject: [PATCH 14/22] refactor: app settings --- apps/server/src/utils/parserFunctions.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apps/server/src/utils/parserFunctions.ts b/apps/server/src/utils/parserFunctions.ts index 7d5d44cfed..41cf9e5069 100644 --- a/apps/server/src/utils/parserFunctions.ts +++ b/apps/server/src/utils/parserFunctions.ts @@ -115,7 +115,7 @@ export const parseSettings = (data, enforce): Settings => { editorKey: s.editorKey || null, operatorKey: s.operatorKey || null, timeFormat: s.timeFormat || '24', - language: s.timeFormat || 'en', + language: s.language || 'en', }; // write to db From 39ef8104d99a156376e7d1f8993678f72dc7d898 Mon Sep 17 00:00:00 2001 From: cv <34649812+cpvalente@users.noreply.github.com> Date: Tue, 9 May 2023 12:53:08 +0200 Subject: [PATCH 15/22] refactor: event data --- .../src/features/modals/Modal.module.scss | 7 ++ .../client/src/features/modals/ModalInput.tsx | 29 +++++ .../client/src/features/modals/modalHelper.js | 1 - .../modals/settings-modal/AppSettings.tsx | 11 +- .../modals/settings-modal/EventDataForm.tsx | 108 ++++++++++++++++++ .../modals/settings-modal/SettingsModal.tsx | 4 +- 6 files changed, 155 insertions(+), 5 deletions(-) create mode 100644 apps/client/src/features/modals/ModalInput.tsx create mode 100644 apps/client/src/features/modals/settings-modal/EventDataForm.tsx diff --git a/apps/client/src/features/modals/Modal.module.scss b/apps/client/src/features/modals/Modal.module.scss index 4855713b3a..7528efe977 100644 --- a/apps/client/src/features/modals/Modal.module.scss +++ b/apps/client/src/features/modals/Modal.module.scss @@ -64,6 +64,13 @@ $el-padding-with-compensation: 24px; // 16 + 8 } } +.columnSection { + @include sectionSpacing; + flex-direction: column; + align-items: flex-start; + gap: $element-inner-spacing; +} + .splitSection { @include sectionSpacing; justify-content: space-between; diff --git a/apps/client/src/features/modals/ModalInput.tsx b/apps/client/src/features/modals/ModalInput.tsx new file mode 100644 index 0000000000..d0ac283538 --- /dev/null +++ b/apps/client/src/features/modals/ModalInput.tsx @@ -0,0 +1,29 @@ +import { PropsWithChildren } from 'react'; +import { FormControl } from '@chakra-ui/react'; + +import style from './settings-modal/SettingsModal.module.scss'; + +interface ModalInputProps { + field: string; + title: string; + description: string; + error?: string; +} + +export default function ModalInput(props: PropsWithChildren) { + const { field, title, description, error, children } = props; + + return ( + + + {children} + + ); +} diff --git a/apps/client/src/features/modals/modalHelper.js b/apps/client/src/features/modals/modalHelper.js index c8ab3e8b40..cbb4e70b89 100644 --- a/apps/client/src/features/modals/modalHelper.js +++ b/apps/client/src/features/modals/modalHelper.js @@ -1,7 +1,6 @@ export const inputProps = { size: 'sm', autoComplete: 'off', - variant: 'outline', }; export const portInputProps = { diff --git a/apps/client/src/features/modals/settings-modal/AppSettings.tsx b/apps/client/src/features/modals/settings-modal/AppSettings.tsx index e04b85d26d..22f8bdf6a6 100644 --- a/apps/client/src/features/modals/settings-modal/AppSettings.tsx +++ b/apps/client/src/features/modals/settings-modal/AppSettings.tsx @@ -4,6 +4,7 @@ import type { Settings } from 'ontime-types'; import { postSettings } from '../../../common/api/ontimeApi'; import useSettings from '../../../common/hooks-query/useSettings'; +import { useEmitLog } from '../../../common/stores/logger'; import { isOnlyNumbers } from '../../../common/utils/regex'; import ModalSplitInput from '../ModalSplitInput'; import OntimeModalFooter from '../OntimeModalFooter'; @@ -12,6 +13,7 @@ import ModalPinInput from './ModalPinInput'; export default function AppSettingsModal() { const { data, status, refetch } = useSettings(); + const { emitError } = useEmitLog(); const { handleSubmit, register, @@ -23,8 +25,13 @@ export default function AppSettingsModal() { }); const onSubmit = async (formData: Settings) => { - await postSettings(formData); - refetch(); + try { + await postSettings(formData); + } catch (error) { + emitError(`Error saving settings: ${error}`); + } finally { + await refetch(); + } }; const onReset = () => { diff --git a/apps/client/src/features/modals/settings-modal/EventDataForm.tsx b/apps/client/src/features/modals/settings-modal/EventDataForm.tsx new file mode 100644 index 0000000000..b55bddec61 --- /dev/null +++ b/apps/client/src/features/modals/settings-modal/EventDataForm.tsx @@ -0,0 +1,108 @@ +import { useForm } from 'react-hook-form'; +import { Input, Textarea } from '@chakra-ui/react'; +import { EventData } from 'ontime-types'; + +import { postEventData } from '../../../common/api/eventDataApi'; +import useEventData from '../../../common/hooks-query/useEventData'; +import { useEmitLog } from '../../../common/stores/logger'; +import { inputProps } from '../modalHelper'; +import ModalInput from '../ModalInput'; +import OntimeModalFooter from '../OntimeModalFooter'; + +export default function EventDataForm() { + const { data, status, refetch } = useEventData(); + const { emitError } = useEmitLog(); + const { + handleSubmit, + register, + reset, + formState: { errors, isSubmitting, isDirty, isValid }, + } = useForm({ + defaultValues: data, + values: data, + }); + + const onSubmit = async (formData: EventData) => { + try { + await postEventData(formData); + } catch (error) { + emitError(`Error saving event settings: ${error}`); + } finally { + await refetch(); + } + }; + + const onReset = () => { + reset(data); + }; + + const disableInputs = status === 'loading'; + + return ( +
+ + + +
+ +