From 54def8b8208363f9d0b08a4fc4e8c1e0c3e5d307 Mon Sep 17 00:00:00 2001 From: Carlos Valente <34649812+cpvalente@users.noreply.github.com> Date: Wed, 15 Nov 2023 20:20:05 +0100 Subject: [PATCH] feat: small improvements to instance info (#591) * refactor: add typings to backend info * refactor: write current version to project file * feat: show location of css override --- apps/client/src/common/api/ontimeApi.ts | 4 +- apps/client/src/common/hooks-query/useInfo.ts | 5 ++- apps/client/src/common/models/Info.ts | 38 +++++++++++-------- .../src/common/models/OntimeSettings.ts | 2 +- .../settings-modal/SettingsModal.module.scss | 11 ++++-- .../settings-modal/ViewSettingsForm.tsx | 21 +++++++++- .../__test__/DataProvider.test.ts | 6 +-- .../src/controllers/ontimeController.ts | 12 +++--- apps/server/src/models/dataModel.ts | 3 +- .../server/src/utils/__tests__/parser.test.ts | 26 ++++++------- apps/server/src/utils/parser.ts | 5 +-- apps/server/src/utils/parserFunctions.ts | 1 + apps/server/test-db/db.json | 2 +- apps/test-db/db.json | 2 +- demo-db/db.json | 2 +- e2e/tests/fixtures/test-db.json | 2 +- .../ontime-controller/BackendResponse.type.ts | 14 +++++++ .../src/definitions/core/Settings.type.ts | 4 +- packages/types/src/index.ts | 3 ++ 19 files changed, 105 insertions(+), 58 deletions(-) create mode 100644 packages/types/src/api/ontime-controller/BackendResponse.type.ts diff --git a/apps/client/src/common/api/ontimeApi.ts b/apps/client/src/common/api/ontimeApi.ts index 1cb33ea23..05c787d9d 100644 --- a/apps/client/src/common/api/ontimeApi.ts +++ b/apps/client/src/common/api/ontimeApi.ts @@ -2,6 +2,7 @@ import axios, { AxiosResponse } from 'axios'; import { Alias, DatabaseModel, + GetInfo, OntimeRundown, OSCSettings, OscSubscription, @@ -13,7 +14,6 @@ import { import { ExcelImportMap } from 'ontime-utils'; import { apiRepoLatest } from '../../externals'; -import { InfoType } from '../models/Info'; import fileDownload from '../utils/fileDownload'; import { ontimeURL } from './apiConstants'; @@ -39,7 +39,7 @@ export async function postSettings(data: Settings) { * @description HTTP request to retrieve application info * @return {Promise} */ -export async function getInfo(): Promise { +export async function getInfo(): Promise { const res = await axios.get(`${ontimeURL}/info`); return res.data; } diff --git a/apps/client/src/common/hooks-query/useInfo.ts b/apps/client/src/common/hooks-query/useInfo.ts index 3cf946c24..c600e0def 100644 --- a/apps/client/src/common/hooks-query/useInfo.ts +++ b/apps/client/src/common/hooks-query/useInfo.ts @@ -1,4 +1,5 @@ import { useQuery } from '@tanstack/react-query'; +import { GetInfo } from 'ontime-types'; import { queryRefetchIntervalSlow } from '../../ontimeConfig'; import { APP_INFO } from '../api/apiConstants'; @@ -6,7 +7,7 @@ import { getInfo } from '../api/ontimeApi'; import { ontimePlaceholderInfo } from '../models/Info'; export default function useInfo() { - const { data, status, isError, refetch } = useQuery({ + const { data, status, isError, refetch, isFetching } = useQuery({ queryKey: APP_INFO, queryFn: getInfo, placeholderData: ontimePlaceholderInfo, @@ -16,5 +17,5 @@ export default function useInfo() { networkMode: 'always', }); - return { data, status, isError, refetch }; + return { data, status, isError, refetch, isFetching }; } diff --git a/apps/client/src/common/models/Info.ts b/apps/client/src/common/models/Info.ts index 6051cd115..f066f3290 100644 --- a/apps/client/src/common/models/Info.ts +++ b/apps/client/src/common/models/Info.ts @@ -1,19 +1,25 @@ -import { Settings } from 'ontime-types'; +import { GetInfo, OSCSettings } from 'ontime-types'; -type NetworkInterfaceType = { - name: string; - address: string; -}; - -export type InfoType = { - networkInterfaces: NetworkInterfaceType[]; - settings: Pick; -}; - -export const ontimePlaceholderInfo: InfoType = { - networkInterfaces: [], - settings: { - version: 2, - serverPort: 4001, +export const oscPlaceholderSettings: OSCSettings = { + portIn: 0, + portOut: 0, + targetIP: '', + enabledIn: false, + enabledOut: false, + subscriptions: { + onLoad: [], + onStart: [], + onPause: [], + onStop: [], + onUpdate: [], + onFinish: [], }, }; + +export const ontimePlaceholderInfo: GetInfo = { + networkInterfaces: [], + version: '2.0.0', + serverPort: 4001, + osc: oscPlaceholderSettings, + cssOverride: '', +}; diff --git a/apps/client/src/common/models/OntimeSettings.ts b/apps/client/src/common/models/OntimeSettings.ts index f234defc1..bb26409da 100644 --- a/apps/client/src/common/models/OntimeSettings.ts +++ b/apps/client/src/common/models/OntimeSettings.ts @@ -2,7 +2,7 @@ import { Settings } from 'ontime-types'; export const ontimePlaceholderSettings: Settings = { app: 'ontime', - version: 2, + version: '2.0.0', serverPort: 4001, editorKey: null, operatorKey: null, diff --git a/apps/client/src/features/modals/settings-modal/SettingsModal.module.scss b/apps/client/src/features/modals/settings-modal/SettingsModal.module.scss index 12110a1f1..c21969f6a 100644 --- a/apps/client/src/features/modals/settings-modal/SettingsModal.module.scss +++ b/apps/client/src/features/modals/settings-modal/SettingsModal.module.scss @@ -3,19 +3,24 @@ .aliases { display: flex; align-items: center; - gap: 8px; + gap: 0.5rem; flex-direction: column; width: 100%; - padding: 8px 0; + padding: 0.5rem 0; .aliasRow { width: 100%; display: flex; align-items: center; - gap: 8px; + gap: 0.5rem; } .grow { flex: 1; } } + +.url { + font-size: calc(1rem - 2px); + user-select: text; +} diff --git a/apps/client/src/features/modals/settings-modal/ViewSettingsForm.tsx b/apps/client/src/features/modals/settings-modal/ViewSettingsForm.tsx index 3ab21dd32..ed1008ad0 100644 --- a/apps/client/src/features/modals/settings-modal/ViewSettingsForm.tsx +++ b/apps/client/src/features/modals/settings-modal/ViewSettingsForm.tsx @@ -1,16 +1,18 @@ import { useEffect } from 'react'; import { useForm } from 'react-hook-form'; -import { Input, Switch } from '@chakra-ui/react'; +import { Alert, AlertDescription, AlertIcon, AlertTitle, Input, Switch } from '@chakra-ui/react'; import { ViewSettings } from 'ontime-types'; import { logAxiosError } from '../../../common/api/apiUtils'; import { postViewSettings } from '../../../common/api/ontimeApi'; import { PopoverPickerRHF } from '../../../common/components/input/popover-picker/PopoverPicker'; +import useInfo from '../../../common/hooks-query/useInfo'; import useViewSettings from '../../../common/hooks-query/useViewSettings'; import { mtm } from '../../../common/utils/timeConstants'; import ModalLoader from '../modal-loader/ModalLoader'; import { inputProps } from '../modalHelper'; import ModalInput from '../ModalInput'; +import ModalLink from '../ModalLink'; import ModalSplitInput from '../ModalSplitInput'; import OntimeModalFooter from '../OntimeModalFooter'; @@ -18,8 +20,12 @@ import InputMillisWithString from './InputMillisWithString'; import style from './SettingsModal.module.scss'; +const cssOverrideDocsUrl = 'https://ontime.gitbook.io/v2/features/custom-styling'; + export default function ViewSettingsForm() { const { data, status, refetch, isFetching } = useViewSettings(); + const { data: info, isFetching: isFetchingInfo } = useInfo(); + const { control, handleSubmit, @@ -75,13 +81,24 @@ export default function ViewSettingsForm() { const disableInputs = status === 'loading'; - if (isFetching) { + if (isFetching || isFetchingInfo) { return ; } return (
General view settings + + +
+ CSS Override + + Ontime will use the CSS file at its install location.
+ {info.cssOverride} + For more information, see the docs +
+
+
{ }, settings: { app: 'ontime', - version: 2, + version: '2.0.0', serverPort: 4001, editorKey: null, operatorKey: null, @@ -84,7 +84,7 @@ describe('safeMerge', () => { const mergedData = safeMerge(existing, newData); expect(mergedData.settings).toEqual({ app: 'ontime', - version: 2, + version: '2.0.0', serverPort: 3000, operatorKey: null, editorKey: null, @@ -144,7 +144,7 @@ describe('safeMerge', () => { }, settings: { app: 'ontime', - version: 2, + version: '2.0.0', serverPort: 4001, operatorKey: null, editorKey: null, diff --git a/apps/server/src/controllers/ontimeController.ts b/apps/server/src/controllers/ontimeController.ts index d481e245a..9ebb2ae1f 100644 --- a/apps/server/src/controllers/ontimeController.ts +++ b/apps/server/src/controllers/ontimeController.ts @@ -1,6 +1,6 @@ -import { Alias, DatabaseModel, LogOrigin, ProjectData } from 'ontime-types'; +import { Alias, DatabaseModel, GetInfo, LogOrigin, ProjectData } from 'ontime-types'; -import { RequestHandler } from 'express'; +import { RequestHandler, Request, Response } from 'express'; import fs from 'fs'; import { networkInterfaces } from 'os'; @@ -9,7 +9,7 @@ import { DataProvider } from '../classes/data-provider/DataProvider.js'; import { failEmptyObjects, failIsNotArray } from '../utils/routerUtils.js'; import { PlaybackService } from '../services/PlaybackService.js'; import { eventStore } from '../stores/EventStore.js'; -import { isDocker, resolveDbPath } from '../setup.js'; +import { isDocker, pathToStartStyles, resolveDbPath } from '../setup.js'; import { oscIntegration } from '../services/integration-service/OscIntegration.js'; import { logger } from '../classes/Logger.js'; import { deleteAllEvents, notifyChanges } from '../services/rundown-service/RundownService.js'; @@ -105,15 +105,16 @@ const getNetworkInterfaces = () => { return results; }; -// Create controller for POST request to '/ontime/info' +// Create controller for GET request to '/ontime/info' // Returns - -export const getInfo = async (req, res) => { +export const getInfo = async (req: Request, res: Response) => { const { version, serverPort } = DataProvider.getSettings(); const osc = DataProvider.getOsc(); // get nif and inject localhost const ni = getNetworkInterfaces(); ni.unshift({ name: 'localhost', address: '127.0.0.1' }); + const cssOverride = pathToStartStyles; // send object with network information res.status(200).send({ @@ -121,6 +122,7 @@ export const getInfo = async (req, res) => { version, serverPort, osc, + cssOverride, }); }; diff --git a/apps/server/src/models/dataModel.ts b/apps/server/src/models/dataModel.ts index 68fa10c6a..749e1e120 100644 --- a/apps/server/src/models/dataModel.ts +++ b/apps/server/src/models/dataModel.ts @@ -1,4 +1,5 @@ import { DatabaseModel } from 'ontime-types'; +import { ONTIME_VERSION } from '../ONTIME_VERSION.js'; export const dbModel: DatabaseModel = { rundown: [], @@ -12,7 +13,7 @@ export const dbModel: DatabaseModel = { }, settings: { app: 'ontime', - version: 2, + version: ONTIME_VERSION, serverPort: 4001, editorKey: null, operatorKey: null, diff --git a/apps/server/src/utils/__tests__/parser.test.ts b/apps/server/src/utils/__tests__/parser.test.ts index f30734ddb..6a396b757 100644 --- a/apps/server/src/utils/__tests__/parser.test.ts +++ b/apps/server/src/utils/__tests__/parser.test.ts @@ -201,7 +201,7 @@ describe('test json parser with valid def', () => { }, settings: { app: 'ontime', - version: 2, + version: '2.0.0', timeFormat: '24', }, viewSettings: {}, @@ -260,7 +260,7 @@ describe('test json parser with valid def', () => { it('settings are for right app and version', () => { const settings = parseResponse?.settings; expect(settings.app).toBe('ontime'); - expect(settings.version).toBe(2); + expect(settings.version).toEqual(expect.any(String)); }); it('missing settings', () => { @@ -387,7 +387,7 @@ describe('test corrupt data', () => { }, settings: { app: 'ontime', - version: 2, + version: '2.0.0', serverPort: 4001, lock: null, timeFormat: '24', @@ -410,7 +410,7 @@ describe('test corrupt data', () => { }, settings: { app: 'ontime', - version: 2, + version: '2.0.0', serverPort: 4001, lock: null, timeFormat: '24', @@ -427,7 +427,7 @@ describe('test corrupt data', () => { project: {}, settings: { app: 'ontime', - version: 2, + version: '2.0.0', serverPort: 4001, lock: null, timeFormat: '24', @@ -444,7 +444,7 @@ describe('test corrupt data', () => { event: {}, settings: { app: 'ontime', - version: 2, + version: '2.0.0', }, }; @@ -734,7 +734,7 @@ describe('test aliases import', () => { rundown: [], settings: { app: 'ontime', - version: 2, + version: '2.0.0', }, aliases: [ { @@ -773,7 +773,7 @@ describe('test userFields import', () => { rundown: [], settings: { app: 'ontime', - version: 2, + version: '2.0.0', }, userFields: testUserFields, }; @@ -800,7 +800,7 @@ describe('test userFields import', () => { rundown: [], settings: { app: 'ontime', - version: 2, + version: '2.0.0', }, userFields: testUserFields, }; @@ -814,7 +814,7 @@ describe('test userFields import', () => { rundown: [], settings: { app: 'ontime', - version: 2, + version: '2.0.0', }, }; @@ -828,7 +828,7 @@ describe('test userFields import', () => { rundown: [], settings: { app: 'ontime', - version: 2, + version: '2.0.0', }, userFields: { notThis: 'this shouldng be accepted', @@ -847,7 +847,7 @@ describe('test views import', () => { rundown: [], settings: { app: 'ontime', - version: 2, + version: '2.0.0', }, viewSettings: { normalColor: '#ffffffcc', @@ -881,7 +881,7 @@ describe('test views import', () => { rundown: [], settings: { app: 'ontime', - version: 2, + version: '2.0.0', }, }; const parsed = parseViewSettings(testData); diff --git a/apps/server/src/utils/parser.ts b/apps/server/src/utils/parser.ts index bd2459869..4c28acd10 100644 --- a/apps/server/src/utils/parser.ts +++ b/apps/server/src/utils/parser.ts @@ -241,7 +241,7 @@ export const parseExcel = (excelData: unknown[][], options?: Partial { console.log('ERROR: unknown app version, skipping'); } else { const settings = { + version: dbModel.settings.version, serverPort: s.serverPort || dbModel.settings.serverPort, editorKey: s.editorKey || null, operatorKey: s.operatorKey || null, diff --git a/apps/server/test-db/db.json b/apps/server/test-db/db.json index 295f3f5a5..3cbd679f6 100644 --- a/apps/server/test-db/db.json +++ b/apps/server/test-db/db.json @@ -237,7 +237,7 @@ }, "settings": { "app": "ontime", - "version": 2, + "version": "2.0.0", "serverPort": 4001, "editorKey": null, "operatorKey": null, diff --git a/apps/test-db/db.json b/apps/test-db/db.json index 63c4dc6ea..e30ef9560 100644 --- a/apps/test-db/db.json +++ b/apps/test-db/db.json @@ -99,7 +99,7 @@ }, "settings": { "app": "ontime", - "version": 2, + "version": "2.0.0", "serverPort": 4001, "editorKey": null, "operatorKey": null, diff --git a/demo-db/db.json b/demo-db/db.json index 457e77606..eab76a7dc 100644 --- a/demo-db/db.json +++ b/demo-db/db.json @@ -413,7 +413,7 @@ }, "settings": { "app": "ontime", - "version": 2, + "version": "2.0.0", "serverPort": 4001, "editorKey": null, "operatorKey": null, diff --git a/e2e/tests/fixtures/test-db.json b/e2e/tests/fixtures/test-db.json index 6c7fb209b..66186be3b 100644 --- a/e2e/tests/fixtures/test-db.json +++ b/e2e/tests/fixtures/test-db.json @@ -103,7 +103,7 @@ }, "settings": { "app": "ontime", - "version": 2, + "version": "2.0.0", "serverPort": 4001, "editorKey": null, "operatorKey": null, diff --git a/packages/types/src/api/ontime-controller/BackendResponse.type.ts b/packages/types/src/api/ontime-controller/BackendResponse.type.ts new file mode 100644 index 000000000..6bfe2fa02 --- /dev/null +++ b/packages/types/src/api/ontime-controller/BackendResponse.type.ts @@ -0,0 +1,14 @@ +import { OSCSettings } from '../../definitions/core/OscSettings.type.js'; + +export type NetworkInterface = { + name: string; + address: string; +}; + +export interface GetInfo { + networkInterfaces: NetworkInterface[]; + version: string; + serverPort: number; + osc: OSCSettings; + cssOverride: string; +} diff --git a/packages/types/src/definitions/core/Settings.type.ts b/packages/types/src/definitions/core/Settings.type.ts index 4d4527989..a717c288b 100644 --- a/packages/types/src/definitions/core/Settings.type.ts +++ b/packages/types/src/definitions/core/Settings.type.ts @@ -1,8 +1,8 @@ -import { TimeFormat } from './TimeFormat.type'; +import { TimeFormat } from './TimeFormat.type.js'; export type Settings = { app: 'ontime'; - version: 2; + version: string; serverPort: number; editorKey: null | string; operatorKey: null | string; diff --git a/packages/types/src/index.ts b/packages/types/src/index.ts index daee8f60c..20f74c16b 100644 --- a/packages/types/src/index.ts +++ b/packages/types/src/index.ts @@ -33,6 +33,9 @@ export type { OSCSettings, OscSubscription, OscSubscriptionOptions } from './def // ---> HTTP +// SERVER RESPONSES +export type { NetworkInterface, GetInfo } from './api/ontime-controller/BackendResponse.type.js'; + // SERVER RUNTIME export { type Log, LogLevel, type LogMessage, LogOrigin } from './definitions/runtime/Logger.type.js'; export { Playback } from './definitions/runtime/Playback.type.js';