mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-15 12:23:51 +00:00
V2 ws store (#310)
* Update TimerService.ts * refactor: message service publishes to store * refactor: several type improvements * V2 ws store wss (#309) * refactor: shared logging types * refactor: simplify message service consumption * refactor: create discrete logging system * refactor: move socket.io > websocket
This commit is contained in:
@@ -0,0 +1,18 @@
|
||||
export enum LogLevel {
|
||||
Info = 'INFO',
|
||||
Warn = 'WARN',
|
||||
Error = 'ERROR',
|
||||
}
|
||||
|
||||
export type Log = {
|
||||
id: string;
|
||||
origin: string;
|
||||
time: string;
|
||||
level: LogLevel;
|
||||
text: string;
|
||||
};
|
||||
|
||||
export type LogMessage = {
|
||||
type: 'ontime-log';
|
||||
payload: Log;
|
||||
};
|
||||
@@ -2,9 +2,3 @@ export type Message = {
|
||||
text: string;
|
||||
visible: boolean;
|
||||
};
|
||||
|
||||
export type MessageControl = {
|
||||
presenter: Message;
|
||||
public: Message;
|
||||
lower: Message;
|
||||
};
|
||||
|
||||
@@ -1 +1,7 @@
|
||||
export type Playback = 'roll' | 'play' | 'pause' | 'stop' | 'armed';
|
||||
export enum Playback {
|
||||
Roll = 'roll',
|
||||
Play = 'play',
|
||||
Pause = 'pause',
|
||||
Stop = 'stop',
|
||||
Armed = 'armed',
|
||||
}
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
export type Loaded = {
|
||||
numEvents: number;
|
||||
selectedEventIndex: number | null;
|
||||
selectedEventId: string | null;
|
||||
selectedPublicEventId: string | null;
|
||||
nextEventId: string | null;
|
||||
nextPublicEventId: string | null;
|
||||
};
|
||||
@@ -0,0 +1,22 @@
|
||||
import { Playback } from './Playback.type.js';
|
||||
import { Message } from './MessageControl.type.js';
|
||||
import { TimerState } from './TimerState.type.js';
|
||||
import { TitleBlock } from './TitleBlock.type.js';
|
||||
import { Loaded } from './Playlist.type.js';
|
||||
|
||||
export type RuntimeStore = {
|
||||
// timer service
|
||||
timer: TimerState;
|
||||
playback: Playback;
|
||||
|
||||
// messages service
|
||||
timerMessage: Message;
|
||||
publicMessage: Message;
|
||||
lowerMessage: Message;
|
||||
onAir: boolean;
|
||||
|
||||
// event loader
|
||||
loaded: Loaded;
|
||||
titles: TitleBlock;
|
||||
titlesPublic: TitleBlock;
|
||||
};
|
||||
@@ -0,0 +1,15 @@
|
||||
import { TimerType } from '../TimerType.type.js';
|
||||
|
||||
export type TimerState = {
|
||||
clock: number; // realtime clock
|
||||
current: number | null; // running countdown
|
||||
elapsed: number | null; // elapsed time in current timer
|
||||
expectedFinish: number | null;
|
||||
addedTime: number; // time added by user, can be negative
|
||||
startedAt: number | null;
|
||||
finishedAt: number | null; // only if timer has already finished
|
||||
secondaryTimer: number | null; // used for roll mode
|
||||
selectedEventId: string | null;
|
||||
duration: number | null;
|
||||
timerType: TimerType | null;
|
||||
};
|
||||
@@ -0,0 +1,10 @@
|
||||
export type TitleBlock = {
|
||||
titleNow: string | null;
|
||||
subtitleNow: string | null;
|
||||
presenterNow: string | null;
|
||||
noteNow: string | null;
|
||||
titleNext: string | null;
|
||||
subtitleNext: string | null;
|
||||
presenterNext: string | null;
|
||||
noteNext: string | null;
|
||||
};
|
||||
@@ -1,7 +1,7 @@
|
||||
import { Alias } from './definitions/core/Alias.type.js';
|
||||
import { DatabaseModel } from './definitions/DataModel.type.js';
|
||||
import { EventData } from './definitions/core/EventData.type.js';
|
||||
import { Message, MessageControl } from './definitions/runtime/MessageControl.type.js';
|
||||
import { Message } from './definitions/runtime/MessageControl.type.js';
|
||||
import {
|
||||
OntimeBaseEvent,
|
||||
OntimeBlock,
|
||||
@@ -12,9 +12,14 @@ import {
|
||||
import { OntimeRundown, OntimeRundownEntry } from './definitions/core/Rundown.type.js';
|
||||
import { OSCSettings, OscSubscription } from './definitions/core/OscSettings.type.js';
|
||||
import { Playback } from './definitions/runtime/Playback.type.js';
|
||||
import { Loaded } from './definitions/runtime/Playlist.type.js';
|
||||
import { Log, LogLevel, LogMessage } from './definitions/runtime/Logger.type.js';
|
||||
import { RuntimeStore } from './definitions/runtime/RuntimeStore.type.js';
|
||||
import { Settings } from './definitions/core/Settings.type.js';
|
||||
import { TimerLifeCycle } from './definitions/core/TimerLifecycle.type.js';
|
||||
import { TimerState } from './definitions/runtime/TimerState.type.js';
|
||||
import { TimerType } from './definitions/TimerType.type.js';
|
||||
import { TitleBlock } from './definitions/runtime/TitleBlock.type.js';
|
||||
import { UserFields } from './definitions/core/UserFields.type.js';
|
||||
import { ViewSettings } from './definitions/core/Views.type.js';
|
||||
|
||||
@@ -47,10 +52,16 @@ export type { OscSubscription, OSCSettings };
|
||||
|
||||
// ---> HTTP
|
||||
|
||||
// SERVER
|
||||
// SERVER RUNTIME
|
||||
export { LogLevel };
|
||||
export type { Log, LogMessage };
|
||||
export { Playback };
|
||||
export { TimerLifeCycle };
|
||||
export type { Playback };
|
||||
|
||||
export type { Message };
|
||||
export type { MessageControl };
|
||||
export type { Loaded };
|
||||
export type { RuntimeStore };
|
||||
export type { TimerState };
|
||||
export type { TitleBlock };
|
||||
|
||||
// CLIENT
|
||||
|
||||
@@ -1 +1,2 @@
|
||||
export { millisToString } from './src/date-utils/millisToString.js';
|
||||
export { generateId } from './src/generate-id/generateId.js';
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
"cleanup": "rm -rf .turbo && rm -rf node_modules"
|
||||
},
|
||||
"dependencies": {
|
||||
"luxon": "^3.3.0",
|
||||
"nanoid": "^4.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@types/luxon": "^3.2.0",
|
||||
"@typescript-eslint/eslint-plugin": "^5.48.1",
|
||||
"@typescript-eslint/parser": "^5.48.1",
|
||||
"eslint": "^8.31.0",
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import { expect } from 'vitest';
|
||||
|
||||
import { millisToString } from './millisToString';
|
||||
|
||||
describe('millisToString()', () => {
|
||||
it('returns fallback if millis is null', () => {
|
||||
const fallback = 'testFallback';
|
||||
expect(millisToString(null, true, fallback)).toBe(fallback);
|
||||
});
|
||||
|
||||
it('returns 00:00:00 if 0 is passed', () => {
|
||||
expect(millisToString(0)).toBe('00:00:00');
|
||||
});
|
||||
|
||||
it('shows negative timers', () => {
|
||||
const testScenarios = [
|
||||
{ millis: -300, expected: '-00:00:00' },
|
||||
{ millis: -1000, expected: '-00:00:01' },
|
||||
{ millis: -1500, expected: '-00:00:01' },
|
||||
{ millis: -60000, expected: '-00:01:00' },
|
||||
{ millis: -600000, expected: '-00:10:00' },
|
||||
{ millis: -3600000, expected: '-01:00:00' },
|
||||
{ millis: -36000000, expected: '-10:00:00' },
|
||||
{ millis: -86399000, expected: '-23:59:59' },
|
||||
{ millis: -86400000, expected: '-00:00:00' },
|
||||
{ millis: -86401000, expected: '-00:00:01' },
|
||||
];
|
||||
|
||||
testScenarios.forEach((scenario) => {
|
||||
expect(millisToString(scenario.millis)).toBe(scenario.expected);
|
||||
});
|
||||
});
|
||||
|
||||
test('random properties', () => {
|
||||
const testScenarios = [
|
||||
{ millis: 300, expected: '00:00:00' },
|
||||
{ millis: 1000, expected: '00:00:01' },
|
||||
{ millis: 1500, expected: '00:00:01' },
|
||||
{ millis: 60000, expected: '00:01:00' },
|
||||
{ millis: 600000, expected: '00:10:00' },
|
||||
{ millis: 3600000, expected: '01:00:00' },
|
||||
{ millis: 36000000, expected: '10:00:00' },
|
||||
{ millis: 86399000, expected: '23:59:59' },
|
||||
{ millis: 86400000, expected: '00:00:00' },
|
||||
{ millis: 86401000, expected: '00:00:01' },
|
||||
];
|
||||
|
||||
testScenarios.forEach((scenario) => {
|
||||
expect(millisToString(scenario.millis)).toBe(scenario.expected);
|
||||
});
|
||||
});
|
||||
|
||||
test('random properties without seconds', () => {
|
||||
const testScenarios = [
|
||||
{ millis: 300, expected: '00:00' },
|
||||
{ millis: 1000, expected: '00:00' },
|
||||
{ millis: 1500, expected: '00:00' },
|
||||
{ millis: 60000, expected: '00:01' },
|
||||
{ millis: 600000, expected: '00:10' },
|
||||
{ millis: 3600000, expected: '01:00' },
|
||||
{ millis: 36000000, expected: '10:00' },
|
||||
{ millis: 86399000, expected: '23:59' },
|
||||
{ millis: 86400000, expected: '00:00' },
|
||||
{ millis: 86401000, expected: '00:00' },
|
||||
];
|
||||
|
||||
testScenarios.forEach((scenario) => {
|
||||
expect(millisToString(scenario.millis, false)).toBe(scenario.expected);
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,19 @@
|
||||
import { DateTime } from 'luxon';
|
||||
|
||||
/**
|
||||
* @description Converts milliseconds to string representing time
|
||||
* @param {number | null} millis - time in milliseconds
|
||||
* @param {boolean} showSeconds - weather to show the seconds
|
||||
* @param {string} fallback - what to return if value is null
|
||||
* @returns {string} String representing time 00:12:02
|
||||
*/
|
||||
export function millisToString(millis: number | null, showSeconds = true, fallback = '...') {
|
||||
if (millis === null) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
const isNegative = millis < 0;
|
||||
|
||||
const format = `HH:mm${showSeconds ? ':ss' : ''}`;
|
||||
return `${isNegative ? '-' : ''}${DateTime.fromMillis(Math.abs(millis)).toUTC().toFormat(format)}`;
|
||||
}
|
||||
Reference in New Issue
Block a user