refactor: restructure model to contain an object of rundowns

This commit is contained in:
Carlos Valente
2025-03-15 09:04:33 +01:00
committed by arc-alex
parent 0a80d6db31
commit abd9b127db
111 changed files with 4357 additions and 4515 deletions
@@ -1,12 +1,13 @@
import {
ProjectData,
OntimeRundown,
ViewSettings,
DatabaseModel,
Settings,
CustomFields,
URLPreset,
AutomationSettings,
Rundown,
ProjectRundowns,
} from 'ontime-types';
import type { Low } from 'lowdb';
@@ -45,6 +46,7 @@ export function getDataProvider() {
setCustomFields,
getCustomFields,
setRundown,
mergeRundown,
getSettings,
setSettings,
getUrlPresets,
@@ -78,14 +80,28 @@ async function setCustomFields(newData: CustomFields): ReadonlyPromise<CustomFie
return db.data.customFields;
}
async function mergeRundown(
newCustomFields: CustomFields,
newRundowns: ProjectRundowns,
): ReadonlyPromise<{ rundowns: ProjectRundowns; customFields: CustomFields }> {
db.data.customFields = { ...db.data.customFields, ...newCustomFields };
Object.entries(newRundowns).forEach(([id, rundown]) => {
// Note that entries with the same key will be overridden
db.data.rundowns[id] = rundown;
});
await persist();
return { rundowns: db.data.rundowns, customFields: db.data.customFields };
}
function getCustomFields(): Readonly<CustomFields> {
return db.data.customFields;
}
async function setRundown(newData: OntimeRundown): ReadonlyPromise<OntimeRundown> {
db.data.rundown = newData;
async function setRundown(rundownKey: string, newData: Rundown): ReadonlyPromise<Rundown> {
db.data.rundowns[rundownKey] = newData;
await persist();
return db.data.rundown;
return db.data.rundowns[rundownKey];
}
function getSettings(): Readonly<Settings> {
@@ -128,8 +144,9 @@ async function setAutomation(newData: AutomationSettings): ReadonlyPromise<Autom
return db.data.automation;
}
function getRundown(): Readonly<OntimeRundown> {
return db.data.rundown;
function getRundown(): Readonly<Rundown> {
const firstRundown = Object.keys(db.data.rundowns)[0];
return db.data.rundowns[firstRundown];
}
async function mergeIntoData(newData: Partial<DatabaseModel>): ReadonlyPromise<DatabaseModel> {
@@ -140,7 +157,7 @@ async function mergeIntoData(newData: Partial<DatabaseModel>): ReadonlyPromise<D
db.data.automation = mergedData.automation;
db.data.urlPresets = mergedData.urlPresets;
db.data.customFields = mergedData.customFields;
db.data.rundown = mergedData.rundown;
db.data.rundowns = mergedData.rundowns;
await persist();
return db.data;
@@ -8,7 +8,7 @@ export function safeMerge(existing: DatabaseModel, newData: Partial<DatabaseMode
const deepNewData = structuredClone(newData);
const {
rundown = deepExisting.rundown,
rundowns = {},
project = {},
settings = {},
viewSettings = {},
@@ -19,7 +19,7 @@ export function safeMerge(existing: DatabaseModel, newData: Partial<DatabaseMode
return {
...deepExisting,
rundown,
rundowns: { ...existing.rundowns, ...rundowns },
project: { ...deepExisting.project, ...project },
settings: { ...deepExisting.settings, ...settings },
viewSettings: { ...deepExisting.viewSettings, ...viewSettings },
@@ -1,4 +1,8 @@
import { DatabaseModel, OntimeRundown, Settings, URLPreset, ViewSettings } from 'ontime-types';
import { DatabaseModel, Settings, URLPreset } from 'ontime-types';
import { demoDb } from '../../../models/demoProject.js';
import { makeOntimeEvent, makeRundown } from '../../../services/rundown-service/__mocks__/rundown.mocks.js';
import { safeMerge } from '../DataProvider.utils.js';
describe('safeMerge', () => {
@@ -51,23 +55,43 @@ describe('safeMerge', () => {
} as DatabaseModel;
it('returns existing data if new data is not provided', () => {
const mergedData = safeMerge(existing, {});
expect(mergedData).toEqual(existing);
const mergedData = safeMerge(demoDb, {});
expect(mergedData).toEqual(demoDb);
});
it('merges the rundown key', () => {
const newData = {
rundown: [{ title: 'item 1' }, { title: 'item 2' }] as OntimeRundown,
};
const mergedData = safeMerge(existing, newData);
expect(mergedData.rundown).toEqual(newData.rundown);
it('overrides a rundown with the same key', () => {
const newData = makeRundown({
id: 'demo',
entries: {
'1': makeOntimeEvent({ id: '1', title: 'new title' }),
'2': makeOntimeEvent({ id: '1', title: 'new title' }),
},
order: ['1', '2'],
});
const mergedData = safeMerge(demoDb, { rundowns: { demo: newData } });
expect(mergedData.rundowns.demo).toStrictEqual(newData);
});
it('merges a rundown with a new key', () => {
const newData = makeRundown({
id: 'rundown',
entries: {
'1': makeOntimeEvent({ id: '1', title: 'new title' }),
'2': makeOntimeEvent({ id: '1', title: 'new title' }),
},
order: ['1', '2'],
});
const mergedData = safeMerge(demoDb, { rundowns: { rundown: newData } });
expect(mergedData.rundowns.demo).toStrictEqual(demoDb.rundowns.demo);
expect(mergedData.rundowns.rundown).toStrictEqual(newData);
});
it('merges the project key', () => {
const newData = {
const mergedData = safeMerge(demoDb, {
project: {
title: 'new title',
publicInfo: 'new public info',
backstageInfo: 'new backstage info',
custom: [
{
title: 'new custom title',
@@ -75,16 +99,15 @@ describe('safeMerge', () => {
},
],
},
};
// @ts-expect-error -- just testing
const mergedData = safeMerge(existing, newData);
expect(mergedData.project).toEqual({
} as Partial<DatabaseModel>);
expect(mergedData.project).toStrictEqual({
title: 'new title',
description: 'existing description',
publicUrl: 'existing public URL',
description: 'Turin 2022',
publicUrl: 'www.getontime.no',
publicInfo: 'new public info',
backstageUrl: 'existing backstageUrl',
backstageInfo: 'existing backstageInfo',
backstageUrl: 'www.github.com/cpvalente/ontime',
backstageInfo: 'new backstage info',
projectLogo: null,
custom: [
{
@@ -96,16 +119,16 @@ describe('safeMerge', () => {
});
it('merges the settings key', () => {
const newData = {
const mergedData = safeMerge(demoDb, {
settings: {
serverPort: 3000,
language: 'pt',
version: 'new',
} as Settings,
};
const mergedData = safeMerge(existing, newData);
expect(mergedData.settings).toEqual({
});
expect(mergedData.settings).toStrictEqual({
app: 'ontime',
version: '2.0.0',
version: 'new',
serverPort: 3000,
operatorKey: null,
editorKey: null,
@@ -158,9 +181,9 @@ describe('safeMerge', () => {
] as URLPreset[],
};
const mergedData = safeMerge(existingData, newData);
const mergedData = safeMerge(demoDb, newData);
expect(mergedData.urlPresets).toEqual(newData.urlPresets);
expect(mergedData.urlPresets).toStrictEqual(newData.urlPresets);
});
it('merges customFields into existing object', () => {