From 8756b396cc9b22573e919beff471a89fb9cdafa5 Mon Sep 17 00:00:00 2001 From: Alex Christoffer Rasmussen Date: Thu, 14 Dec 2023 13:27:18 +0100 Subject: [PATCH] feat: minimal demo page (#644) * minimal * eslint-browser * dynamic port, reconnect socket, msTo string without Date * 404 on external not found --- apps/server/src/app.ts | 3 ++ apps/server/src/external/demo/app.js | 67 ++++++++++++++++++++++++ apps/server/src/external/demo/index.html | 14 +++++ apps/server/src/external/demo/styles.css | 16 ++++++ 4 files changed, 100 insertions(+) create mode 100644 apps/server/src/external/demo/app.js create mode 100644 apps/server/src/external/demo/index.html create mode 100644 apps/server/src/external/demo/styles.css diff --git a/apps/server/src/app.ts b/apps/server/src/app.ts index c6cfb7187..98a90b0e6 100644 --- a/apps/server/src/app.ts +++ b/apps/server/src/app.ts @@ -65,6 +65,9 @@ app.use('/playback', playbackRouter); // serve static - css app.use('/external', express.static(externalsStartDirectory)); +app.use('/external', (req, res) => { + res.status(404).send(`${req.originalUrl} not found`); +}); // serve static - react, in dev/test mode we fetch the React app from module const reactAppPath = join(currentDirectory, resolvedPath()); diff --git a/apps/server/src/external/demo/app.js b/apps/server/src/external/demo/app.js new file mode 100644 index 000000000..0af53bb92 --- /dev/null +++ b/apps/server/src/external/demo/app.js @@ -0,0 +1,67 @@ +/*eslint-env browser*/ +/** + * This is a very minimal example for a websocket client + * You could use this as a starting point to creating your own interfaces + */ + +const mts = 1000; // millis to seconds +const mtm = 1000 * 60; // millis to minutes +const mth = 1000 * 60 * 60; // millis to hours + +const leftPad = (number) => { + return Math.floor(number).toString().padStart(2, '0'); +}; + +let reconnectTimeout; +const reconnectInterval = 1000; +let reconnectAttempts = 0; + +const connectSocket = () => { + const websocket = new WebSocket(`ws://${window.location.hostname}:${window.location.port}/ws`); + + websocket.onopen = () => { + clearTimeout(reconnectTimeout); + reconnectAttempts = 0; + console.info('WebSocket connected'); + }; + + websocket.onclose = () => { + console.warn('WebSocket disconnected'); + reconnectTimeout = setTimeout(() => { + console.warn(`WebSocket: attempting reconnect ${reconnectAttempts}`); + if (websocket && websocket.readyState === WebSocket.CLOSED) { + reconnectAttempts += 1; + connectSocket(); + } + }, reconnectInterval); + }; + websocket.onerror = (error) => { + console.error('WebSocket error:', error); + }; + + websocket.onmessage = (event) => { + const data = JSON.parse(event.data); + + // all objects from ontime are structured with type and payload + const { type, payload } = data; + + // we only need to read message type of ontime + if (type === 'ontime') { + // destructure known data from ontime + // see https://cpvalente.gitbook.io/ontime/control-and-feedback/websocket-api + const { timer, playback } = payload; + const timerElement = document.getElementById('timer'); + if (playback == 'stop') { + timerElement.innerText = '--:--:--'; + } else { + const millis = Math.abs(timer.current); + const isNegative = timer.current < 0; + timerElement.innerText = `${isNegative ? '-' : ''}${leftPad(millis / mth)}:${leftPad( + (millis % mth) / mtm, + )}:${leftPad((millis % mtm) / mts)}`; + } + } + }; +}; + +connectSocket(); diff --git a/apps/server/src/external/demo/index.html b/apps/server/src/external/demo/index.html new file mode 100644 index 000000000..28b06716f --- /dev/null +++ b/apps/server/src/external/demo/index.html @@ -0,0 +1,14 @@ + + + + + + + ontime demo + + + + +
+ + \ No newline at end of file diff --git a/apps/server/src/external/demo/styles.css b/apps/server/src/external/demo/styles.css new file mode 100644 index 000000000..6d267ceda --- /dev/null +++ b/apps/server/src/external/demo/styles.css @@ -0,0 +1,16 @@ +body { + overflow: hidden; + margin: 0; +} +div { + height: 100vh; + width: 100vw; + display: flex; + justify-content: center; + align-items: center; + + color: azure; + font-family: monospace; + font-size: 20vw; + background-color: black; +} \ No newline at end of file