feat: unlock changing port in UI (#476)

* refactor: unlock changing port in UI

* Change server port (#464)

* Ability to save custom port

* Launch server on custom port & pass that port to electron

* Add serverPort validation

* Prevent changing port in docker

---------

Co-authored-by: Snehanshu Phukon <snehanshu@mamboemm.com>

---------

Co-authored-by: স্নেহাংশু ফুকন <hello@snehanshu.com>
Co-authored-by: Snehanshu Phukon <snehanshu@mamboemm.com>
This commit is contained in:
Carlos Valente
2023-08-23 22:31:57 +02:00
committed by GitHub
parent e5fdf27f6c
commit 1d4dc3a26f
11 changed files with 40 additions and 37 deletions
+2 -3
View File
@@ -1,5 +1,3 @@
export const STATIC_PORT = 4001;
// REST stuff
export const EVENT_DATA = ['eventdata'];
export const ALIASES = ['aliases'];
@@ -15,8 +13,9 @@ export const RUNTIME = ['runtimeStore'];
const location = window.location;
const socketProtocol = location.protocol === 'https:' ? 'wss' : 'ws';
const STATIC_PORT = 4001;
export const serverPort = import.meta.env.DEV ? STATIC_PORT : location.port;
export const serverURL = import.meta.env.DEV ? `http://${location.hostname}:${serverPort}` : location.origin;
export const serverURL = `${location.protocol}//${location.hostname}:${serverPort}`;
export const websocketUrl = `${socketProtocol}://${location.hostname}:${serverPort}/ws`;
export const eventURL = `${serverURL}/eventdata`;
+1 -9
View File
@@ -1,13 +1,5 @@
import axios from 'axios';
import {
Alias,
EventData,
OSCSettings,
OscSubscription,
Settings,
UserFields,
ViewSettings,
} from 'ontime-types';
import { Alias, EventData, OSCSettings, OscSubscription, Settings, UserFields, ViewSettings } from 'ontime-types';
import { apiRepoLatest } from '../../externals';
import { InfoType } from '../models/Info';
+2 -1
View File
@@ -1,5 +1,6 @@
import { IoArrowUp } from '@react-icons/all-files/io5/IoArrowUp';
import { serverPort } from '../../common/api/apiConstants';
import useInfo from '../../common/hooks-query/useInfo';
import { openLink } from '../../common/utils/linkUtils';
@@ -9,7 +10,7 @@ export default function InfoNif() {
const { data } = useInfo();
const handleClick = (address: string) => {
const baseURL = 'http://__IP__:4001';
const baseURL = `http://__IP__:${serverPort}`;
openLink(baseURL.replace('__IP__', address));
};
@@ -61,7 +61,7 @@ export default function AppSettingsModal() {
<ModalSplitInput
field='serverPort'
title='Ontime is available on port'
description='Default 4001'
description='Default 4001 (needs app restart to change)'
error={errors.serverPort?.message}
>
<Input
@@ -69,7 +69,6 @@ export default function AppSettingsModal() {
size='sm'
textAlign='right'
maxLength={5}
disabled
variant='ontime-filled-on-light'
{...register('serverPort', {
required: { value: true, message: 'Required field' },
+4 -4
View File
@@ -3,13 +3,13 @@ module.exports = {
shutdownCode: 99,
},
reactAppUrl: {
development: 'http://localhost:3000/editor',
production: 'http://localhost:4001/editor',
development: (port = 4001) => `http://localhost:${port}/editor`,
production: (port = 4001) => `http://localhost:${port}/editor`,
},
server: {
pathToEntrypoint: '../extraResources/server/index.cjs'
pathToEntrypoint: '../extraResources/server/index.cjs',
},
assets: {
pathToAssets: './assets/',
}
},
};
+18 -14
View File
@@ -30,21 +30,23 @@ let splash;
let tray = null;
async function startBackend() {
await (async () => {
// in dev mode, we expect both UI and server to be running
if (!isProduction) {
return;
}
// in dev mode, we expect both UI and server to be running
if (!isProduction) {
return;
}
const ontimeServer = require(nodePath);
const { initAssets, startServer, startOSCServer, startIntegrations } = ontimeServer;
const ontimeServer = require(nodePath);
const { initAssets, startServer, startOSCServer, startIntegrations } = ontimeServer;
await initAssets();
await initAssets();
loaded = await startServer();
await startOSCServer();
await startIntegrations();
})();
const result = await startServer();
loaded = result.message;
await startOSCServer();
await startIntegrations();
return result.serverPort;
}
/**
@@ -155,9 +157,11 @@ app.whenReady().then(() => {
});
startBackend()
.then(() => {
.then((port) => {
// Load page served by node or use React dev run
const clientUrl = isProduction ? electronConfig.reactAppUrl.production : electronConfig.reactAppUrl.development;
const clientUrl = isProduction
? electronConfig.reactAppUrl.production(port)
: electronConfig.reactAppUrl.development(port);
win
.loadURL(clientUrl)
+2 -2
View File
@@ -131,7 +131,7 @@ export const initAssets = async () => {
export const startServer = async () => {
checkStart(OntimeStartOrder.InitServer);
const serverPort = 4001; // hardcoded for now
const { serverPort } = DataProvider.getSettings();
const returnMessage = `Ontime is listening on port ${serverPort}`;
expressServer = http.createServer(app);
@@ -144,7 +144,7 @@ export const startServer = async () => {
expressServer.listen(serverPort, '0.0.0.0');
return returnMessage;
return { message: returnMessage, serverPort };
};
/**
@@ -10,7 +10,7 @@ import { failEmptyObjects, failIsNotArray } from '../utils/routerUtils.js';
import { mergeObject } from '../utils/parserUtils.js';
import { PlaybackService } from '../services/PlaybackService.js';
import { eventStore } from '../stores/EventStore.js';
import { resolveDbPath } from '../setup.js';
import { isDocker, resolveDbPath } from '../setup.js';
import { oscIntegration } from '../services/integration-service/OscIntegration.js';
import { logger } from '../classes/Logger.js';
import { deleteAllEvents, forceReset } from '../services/rundown-service/RundownService.js';
@@ -208,6 +208,11 @@ export const postSettings = async (req, res) => {
const editorKey = extractPin(req.body?.editorKey, settings.editorKey);
const operatorKey = extractPin(req.body?.operatorKey, settings.operatorKey);
if (isDocker && req.body?.serverPort) {
return res.status(403).json({ message: `Can't change port when running inside docker` });
}
const serverPort = parseInt(req.body?.serverPort ?? settings.serverPort, 10);
let timeFormat = settings.timeFormat;
if (req.body?.timeFormat === '12' || req.body?.timeFormat === '24') {
timeFormat = req.body.timeFormat;
@@ -221,6 +226,7 @@ export const postSettings = async (req, res) => {
operatorKey,
timeFormat,
language,
serverPort,
};
await DataProvider.setSettings(newData);
res.status(200).send(newData);
@@ -63,6 +63,7 @@ export const validateSettings = [
body('operatorKey').isString().isLength({ min: 0, max: 4 }).optional({ nullable: true }),
body('timeFormat').isString().isIn(['12', '24']),
body('language').isString(),
body('serverPort').isPort().optional(),
(req, res, next) => {
const errors = validationResult(req);
if (!errors.isEmpty()) return res.status(422).json({ errors: errors.array() });
+1
View File
@@ -130,6 +130,7 @@ export const parseSettings = (data, enforce): Settings => {
console.log('ERROR: unknown app version, skipping');
} else {
const settings = {
serverPort: s.serverPort || dbModel.settings.serverPort,
editorKey: s.editorKey || null,
operatorKey: s.operatorKey || null,
timeFormat: s.timeFormat || '24',
@@ -3,7 +3,7 @@ import { TimeFormat } from './TimeFormat.type';
export type Settings = {
app: 'ontime';
version: 2;
serverPort: 4001;
serverPort: number;
editorKey: null | string;
operatorKey: null | string;
timeFormat: TimeFormat;