mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-20 14:39:06 +00:00
refactor: export rundown placement logic
This commit is contained in:
committed by
Carlos Valente
parent
7c5fdd3b19
commit
80a3b04493
@@ -1,4 +1,4 @@
|
|||||||
import { TimeStrategy, EndAction, TimerType, OntimeEvent, OntimeGroup } from 'ontime-types';
|
import { TimeStrategy, EndAction, TimerType, OntimeEvent } from 'ontime-types';
|
||||||
import { MILLIS_PER_HOUR } from 'ontime-utils';
|
import { MILLIS_PER_HOUR } from 'ontime-utils';
|
||||||
|
|
||||||
import { assertType } from 'vitest';
|
import { assertType } from 'vitest';
|
||||||
@@ -11,7 +11,6 @@ import {
|
|||||||
deleteById,
|
deleteById,
|
||||||
doesInvalidateMetadata,
|
doesInvalidateMetadata,
|
||||||
duplicateRundown,
|
duplicateRundown,
|
||||||
getInsertAfterId,
|
|
||||||
hasChanges,
|
hasChanges,
|
||||||
makeDeepClone,
|
makeDeepClone,
|
||||||
} from '../rundown.utils.js';
|
} from '../rundown.utils.js';
|
||||||
@@ -226,45 +225,6 @@ describe('calculateDayOffset()', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('getInsertAfterId()', () => {
|
|
||||||
const rundown = makeRundown({
|
|
||||||
entries: {
|
|
||||||
'1': makeOntimeEvent({ id: '1', parent: null }),
|
|
||||||
'2': makeOntimeEvent({ id: '2', parent: null }),
|
|
||||||
group: makeOntimeGroup({ id: 'group', entries: ['31', '32'] }),
|
|
||||||
'31': makeOntimeEvent({ id: '31', parent: 'group' }),
|
|
||||||
'32': makeOntimeEvent({ id: '32', parent: 'group' }),
|
|
||||||
'4': makeOntimeEvent({ id: '4', parent: null }),
|
|
||||||
},
|
|
||||||
order: ['1', '2', 'group', '4'],
|
|
||||||
flatOrder: ['1', '2', 'group', '31', '32', '4'],
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns afterId if provided', () => {
|
|
||||||
expect(getInsertAfterId(rundown, null, 'b')).toBe('b');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns null if neither afterId nor beforeId is provided', () => {
|
|
||||||
expect(getInsertAfterId(rundown, null)).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns null if beforeId is not found', () => {
|
|
||||||
expect(getInsertAfterId(rundown, null, undefined, 'z')).toBeNull();
|
|
||||||
expect(getInsertAfterId(rundown, null, undefined, '1')).toBeNull();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns the previous id of an entry in the rundown', () => {
|
|
||||||
expect(getInsertAfterId(rundown, null, undefined, '2')).toBe('1');
|
|
||||||
expect(getInsertAfterId(rundown, null, undefined, '4')).toBe('group');
|
|
||||||
expect(getInsertAfterId(rundown, null, undefined, 'group')).toBe('2');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns the previous id of an event in a group', () => {
|
|
||||||
expect(getInsertAfterId(rundown, rundown.entries.group as OntimeGroup, undefined, '31')).toBeNull();
|
|
||||||
expect(getInsertAfterId(rundown, rundown.entries.group as OntimeGroup, undefined, '32')).toBe('31');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('duplicateRundown', () => {
|
describe('duplicateRundown', () => {
|
||||||
it('duplicates a given rundown', () => {
|
it('duplicates a given rundown', () => {
|
||||||
const demoRundown = demoDb.rundowns['default'];
|
const demoRundown = demoDb.rundowns['default'];
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ import {
|
|||||||
Rundown,
|
Rundown,
|
||||||
InsertOptions,
|
InsertOptions,
|
||||||
} from 'ontime-types';
|
} from 'ontime-types';
|
||||||
import { customFieldLabelToKey, insertAtIndex } from 'ontime-utils';
|
import { addToRundown, customFieldLabelToKey, getInsertAfterId, insertAtIndex } from 'ontime-utils';
|
||||||
|
|
||||||
import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
|
import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
|
||||||
import { consoleError } from '../../utils/console.js';
|
import { consoleError } from '../../utils/console.js';
|
||||||
@@ -38,7 +38,6 @@ import {
|
|||||||
createGroup,
|
createGroup,
|
||||||
deleteById,
|
deleteById,
|
||||||
doesInvalidateMetadata,
|
doesInvalidateMetadata,
|
||||||
getInsertAfterId,
|
|
||||||
getUniqueId,
|
getUniqueId,
|
||||||
makeDeepClone,
|
makeDeepClone,
|
||||||
} from './rundown.utils.js';
|
} from './rundown.utils.js';
|
||||||
@@ -163,50 +162,6 @@ export function createTransaction(options: TransactionOptions): Transaction {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add entry to rundown, handles the following cases:
|
|
||||||
* - 1a. add entry in group, after a given entry
|
|
||||||
* - 1b. add entry in group, at the beginning
|
|
||||||
* - 2a. add entry to the rundown, after a given entry
|
|
||||||
* - 2b. add entry to the rundown, at the beginning
|
|
||||||
*/
|
|
||||||
function add(rundown: Rundown, entry: OntimeEntry, afterId: EntryId | null, parent: OntimeGroup | null): OntimeEntry {
|
|
||||||
if (parent) {
|
|
||||||
// 1. inserting an entry inside a group
|
|
||||||
|
|
||||||
if ('parent' in entry) {
|
|
||||||
entry.parent = parent.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (afterId) {
|
|
||||||
const atEventsIndex = parent.entries.indexOf(afterId) + 1;
|
|
||||||
const atFlatIndex = rundown.flatOrder.indexOf(afterId) + 1;
|
|
||||||
parent.entries = insertAtIndex(atEventsIndex, entry.id, parent.entries);
|
|
||||||
rundown.flatOrder = insertAtIndex(atFlatIndex, entry.id, rundown.flatOrder);
|
|
||||||
} else {
|
|
||||||
parent.entries = insertAtIndex(0, entry.id, parent.entries);
|
|
||||||
const atFlatIndex = rundown.flatOrder.indexOf(parent.id) + 1;
|
|
||||||
rundown.flatOrder = insertAtIndex(atFlatIndex, entry.id, rundown.flatOrder);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// 2. inserting an entry at top level
|
|
||||||
if (afterId) {
|
|
||||||
const atOrderIndex = rundown.order.indexOf(afterId) + 1;
|
|
||||||
const atFlatIndex = rundown.flatOrder.indexOf(afterId) + 1;
|
|
||||||
rundown.order = insertAtIndex(atOrderIndex, entry.id, rundown.order);
|
|
||||||
rundown.flatOrder = insertAtIndex(atFlatIndex, entry.id, rundown.flatOrder);
|
|
||||||
} else {
|
|
||||||
rundown.order = insertAtIndex(0, entry.id, rundown.order);
|
|
||||||
rundown.flatOrder = insertAtIndex(0, entry.id, rundown.flatOrder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// either way, we insert the entry into the rundown
|
|
||||||
rundown.entries[entry.id] = entry;
|
|
||||||
|
|
||||||
return entry;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Applies a patch of changes to an existing entry
|
* Applies a patch of changes to an existing entry
|
||||||
* @returns { entry: OntimeEntry, didInvalidate: boolean } - didInvalidate indicates whether the change warrants a recalculation of the cache
|
* @returns { entry: OntimeEntry, didInvalidate: boolean } - didInvalidate indicates whether the change warrants a recalculation of the cache
|
||||||
@@ -516,7 +471,7 @@ function clone(rundown: Rundown, entry: OntimeEntry, options?: InsertOptions): O
|
|||||||
after = entry.id;
|
after = entry.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
return add(rundown, clonedEntry, after, parent);
|
return addToRundown(rundown, clonedEntry, after, parent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,7 +538,7 @@ function ungroup(rundown: Rundown, group: OntimeGroup) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export const rundownMutation = {
|
export const rundownMutation = {
|
||||||
add,
|
add: addToRundown,
|
||||||
edit,
|
edit,
|
||||||
remove,
|
remove,
|
||||||
removeAll,
|
removeAll,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import {
|
|||||||
ProjectRundowns,
|
ProjectRundowns,
|
||||||
InsertOptions,
|
InsertOptions,
|
||||||
} from 'ontime-types';
|
} from 'ontime-types';
|
||||||
import { customFieldLabelToKey } from 'ontime-utils';
|
import { customFieldLabelToKey, getInsertAfterId } from 'ontime-utils';
|
||||||
|
|
||||||
import { updateRundownData } from '../../stores/runtimeState.js';
|
import { updateRundownData } from '../../stores/runtimeState.js';
|
||||||
import { runtimeService } from '../../services/runtime-service/runtime.service.js';
|
import { runtimeService } from '../../services/runtime-service/runtime.service.js';
|
||||||
@@ -33,7 +33,7 @@ import {
|
|||||||
updateBackgroundRundown,
|
updateBackgroundRundown,
|
||||||
} from './rundown.dao.js';
|
} from './rundown.dao.js';
|
||||||
import type { RundownMetadata } from './rundown.types.js';
|
import type { RundownMetadata } from './rundown.types.js';
|
||||||
import { generateEvent, getInsertAfterId, hasChanges } from './rundown.utils.js';
|
import { generateEvent, hasChanges } from './rundown.utils.js';
|
||||||
import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
|
import { getDataProvider } from '../../classes/data-provider/DataProvider.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -483,31 +483,6 @@ export function calculateDayOffset(
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Receives an insertion order and returns the reference to an event ID
|
|
||||||
* after which we will insert the new event
|
|
||||||
*/
|
|
||||||
export function getInsertAfterId(
|
|
||||||
rundown: Rundown,
|
|
||||||
parent: OntimeGroup | null,
|
|
||||||
afterId?: EntryId,
|
|
||||||
beforeId?: EntryId,
|
|
||||||
): EntryId | null {
|
|
||||||
if (afterId) return afterId;
|
|
||||||
if (!beforeId) return null;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* At this point we know we want to insert before a given ID
|
|
||||||
* We need to check which list we should use to insert and find the event there
|
|
||||||
*/
|
|
||||||
const insertionList = parent ? parent.entries : rundown.order;
|
|
||||||
if (!insertionList || insertionList.length === 0) return null;
|
|
||||||
|
|
||||||
const atIndex = insertionList.findIndex((id) => id === beforeId);
|
|
||||||
if (atIndex < 1) return null;
|
|
||||||
return insertionList[atIndex - 1];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sanitises custom fields in an entry by removing fields
|
* Sanitises custom fields in an entry by removing fields
|
||||||
* - if it does not exist in the project
|
* - if it does not exist in the project
|
||||||
|
|||||||
@@ -8,11 +8,13 @@ export { sanitiseCue } from './src/cue-utils/cueUtils.js';
|
|||||||
export { getCueCandidate } from './src/cue-utils/cueUtils.js';
|
export { getCueCandidate } from './src/cue-utils/cueUtils.js';
|
||||||
export { generateId } from './src/generate-id/generateId.js';
|
export { generateId } from './src/generate-id/generateId.js';
|
||||||
export {
|
export {
|
||||||
|
addToRundown,
|
||||||
getEventWithId,
|
getEventWithId,
|
||||||
getFirstEvent,
|
getFirstEvent,
|
||||||
getFirstEventNormal,
|
getFirstEventNormal,
|
||||||
getFirstNormal,
|
getFirstNormal,
|
||||||
getFirstGroupNormal,
|
getFirstGroupNormal,
|
||||||
|
getInsertAfterId,
|
||||||
getLastEvent,
|
getLastEvent,
|
||||||
getLastEventNormal,
|
getLastEventNormal,
|
||||||
getLastNormal,
|
getLastNormal,
|
||||||
|
|||||||
@@ -2,7 +2,9 @@ import type { OntimeDelay, OntimeEntry, OntimeEvent, OntimeGroup, Rundown } from
|
|||||||
import { SupportedEntry } from 'ontime-types';
|
import { SupportedEntry } from 'ontime-types';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
|
addToRundown,
|
||||||
getFirstGroupNormal,
|
getFirstGroupNormal,
|
||||||
|
getInsertAfterId,
|
||||||
getLastEvent,
|
getLastEvent,
|
||||||
getLastGroupNormal,
|
getLastGroupNormal,
|
||||||
getLastNormal,
|
getLastNormal,
|
||||||
@@ -226,12 +228,126 @@ describe('getLastEvent', () => {
|
|||||||
expect(lastEntry).toBe(null);
|
expect(lastEntry).toBe(null);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
});
|
||||||
|
|
||||||
entries: {
|
describe('getInsertAfterId()', () => {
|
||||||
},
|
const rundown = {
|
||||||
|
id: 'test',
|
||||||
|
title: 'test',
|
||||||
|
entries: {
|
||||||
|
'1': { id: '1', type: SupportedEntry.Event, parent: null } as OntimeEvent,
|
||||||
|
'2': { id: '2', type: SupportedEntry.Event, parent: null } as OntimeEvent,
|
||||||
|
group: { id: 'group', type: SupportedEntry.Group, entries: ['31', '32'] } as unknown as OntimeGroup,
|
||||||
|
'31': { id: '31', type: SupportedEntry.Event, parent: 'group' } as OntimeEvent,
|
||||||
|
'32': { id: '32', type: SupportedEntry.Event, parent: 'group' } as OntimeEvent,
|
||||||
|
'4': { id: '4', type: SupportedEntry.Event, parent: null } as OntimeEvent,
|
||||||
|
},
|
||||||
|
order: ['1', '2', 'group', '4'],
|
||||||
|
flatOrder: ['1', '2', 'group', '31', '32', '4'],
|
||||||
|
revision: 1,
|
||||||
|
} as Rundown;
|
||||||
|
|
||||||
|
it('returns afterId if provided', () => {
|
||||||
|
expect(getInsertAfterId(rundown, null, 'b')).toBe('b');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null if neither afterId nor beforeId is provided', () => {
|
||||||
|
expect(getInsertAfterId(rundown, null)).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns null if beforeId is not found', () => {
|
||||||
|
expect(getInsertAfterId(rundown, null, undefined, 'z')).toBeNull();
|
||||||
|
expect(getInsertAfterId(rundown, null, undefined, '1')).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the previous id of an entry in the rundown', () => {
|
||||||
|
expect(getInsertAfterId(rundown, null, undefined, '2')).toBe('1');
|
||||||
|
expect(getInsertAfterId(rundown, null, undefined, '4')).toBe('group');
|
||||||
|
expect(getInsertAfterId(rundown, null, undefined, 'group')).toBe('2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('returns the previous id of an event in a group', () => {
|
||||||
|
expect(getInsertAfterId(rundown, rundown.entries.group as OntimeGroup, undefined, '31')).toBeNull();
|
||||||
|
expect(getInsertAfterId(rundown, rundown.entries.group as OntimeGroup, undefined, '32')).toBe('31');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addToRundown()', () => {
|
||||||
|
const makeTestRundown = (): Rundown =>
|
||||||
|
({
|
||||||
|
id: 'test',
|
||||||
|
title: 'test',
|
||||||
|
entries: {
|
||||||
|
'1': { id: '1', type: SupportedEntry.Event, parent: null } as OntimeEvent,
|
||||||
|
'2': { id: '2', type: SupportedEntry.Event, parent: null } as OntimeEvent,
|
||||||
|
group: { id: 'group', type: SupportedEntry.Group, entries: ['31', '32'] } as unknown as OntimeGroup,
|
||||||
|
'31': { id: '31', type: SupportedEntry.Event, parent: 'group' } as OntimeEvent,
|
||||||
|
'32': { id: '32', type: SupportedEntry.Event, parent: 'group' } as OntimeEvent,
|
||||||
|
},
|
||||||
|
order: ['1', '2', 'group'],
|
||||||
|
flatOrder: ['1', '2', 'group', '31', '32'],
|
||||||
|
revision: 1,
|
||||||
|
}) as Rundown;
|
||||||
|
|
||||||
|
it('adds an entry to an empty rundown', () => {
|
||||||
|
const rundown = { id: 'test', title: '', entries: {}, order: [], flatOrder: [], revision: 0 } as Rundown;
|
||||||
|
const newEntry = { id: 'new', type: SupportedEntry.Event } as OntimeEvent;
|
||||||
|
|
||||||
|
addToRundown(rundown, newEntry, null, null);
|
||||||
|
|
||||||
|
expect(rundown.order).toEqual(['new']);
|
||||||
|
expect(rundown.flatOrder).toEqual(['new']);
|
||||||
|
expect(rundown.entries['new']).toBe(newEntry);
|
||||||
|
});
|
||||||
|
|
||||||
|
// case 2b: insert at the beginning of the rundown
|
||||||
|
it('adds at the beginning of order and flatOrder when afterId is null', () => {
|
||||||
|
const rundown = makeTestRundown();
|
||||||
|
const newEntry = { id: 'new', type: SupportedEntry.Event } as OntimeEvent;
|
||||||
|
|
||||||
|
addToRundown(rundown, newEntry, null, null);
|
||||||
|
|
||||||
|
expect(rundown.order).toEqual(['new', '1', '2', 'group']);
|
||||||
|
expect(rundown.flatOrder).toEqual(['new', '1', '2', 'group', '31', '32']);
|
||||||
|
});
|
||||||
|
|
||||||
|
// case 2a: insert after a given entry at top level
|
||||||
|
it('inserts after the referenced entry in both order and flatOrder', () => {
|
||||||
|
const rundown = makeTestRundown();
|
||||||
|
const newEntry = { id: 'new', type: SupportedEntry.Event } as OntimeEvent;
|
||||||
|
|
||||||
|
addToRundown(rundown, newEntry, '1', null);
|
||||||
|
|
||||||
|
expect(rundown.order).toEqual(['1', 'new', '2', 'group']);
|
||||||
|
expect(rundown.flatOrder).toEqual(['1', 'new', '2', 'group', '31', '32']);
|
||||||
|
});
|
||||||
|
|
||||||
|
// case 1b: insert at the beginning of a group
|
||||||
|
it('inserts right after the group header in flatOrder and sets parent', () => {
|
||||||
|
const rundown = makeTestRundown();
|
||||||
|
const parent = rundown.entries['group'] as OntimeGroup;
|
||||||
|
const newEntry = { id: 'new', type: SupportedEntry.Event, parent: null } as OntimeEvent;
|
||||||
|
|
||||||
|
addToRundown(rundown, newEntry, null, parent);
|
||||||
|
|
||||||
|
expect(parent.entries).toEqual(['new', '31', '32']);
|
||||||
|
expect(newEntry.parent).toBe('group');
|
||||||
|
expect(rundown.flatOrder).toEqual(['1', '2', 'group', 'new', '31', '32']);
|
||||||
|
// top-level order must not change when inserting into a group
|
||||||
|
expect(rundown.order).toEqual(['1', '2', 'group']);
|
||||||
|
});
|
||||||
|
|
||||||
|
// case 1a: insert after a given entry within a group
|
||||||
|
it('inserts after the referenced entry within the group and in flatOrder', () => {
|
||||||
|
const rundown = makeTestRundown();
|
||||||
|
const parent = rundown.entries['group'] as OntimeGroup;
|
||||||
|
const newEntry = { id: 'new', type: SupportedEntry.Event, parent: null } as OntimeEvent;
|
||||||
|
|
||||||
|
addToRundown(rundown, newEntry, '31', parent);
|
||||||
|
|
||||||
|
expect(parent.entries).toEqual(['31', 'new', '32']);
|
||||||
|
expect(newEntry.parent).toBe('group');
|
||||||
|
expect(rundown.flatOrder).toEqual(['1', '2', 'group', '31', 'new', '32']);
|
||||||
|
expect(rundown.order).toEqual(['1', '2', 'group']);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -9,6 +9,8 @@ import type {
|
|||||||
} from 'ontime-types';
|
} from 'ontime-types';
|
||||||
import { isOntimeEvent, isOntimeGroup, isPlayableEvent } from 'ontime-types';
|
import { isOntimeEvent, isOntimeGroup, isPlayableEvent } from 'ontime-types';
|
||||||
|
|
||||||
|
import { insertAtIndex } from '../common/arrayUtils.js';
|
||||||
|
|
||||||
type IndexAndEntry = { entry: OntimeEntry | null; index: number | null };
|
type IndexAndEntry = { entry: OntimeEntry | null; index: number | null };
|
||||||
type GroupIndexAndEntry = { entry: OntimeGroup | null; index: number | null };
|
type GroupIndexAndEntry = { entry: OntimeGroup | null; index: number | null };
|
||||||
|
|
||||||
@@ -360,11 +362,76 @@ export function getNextGroupNormal(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets relevant group element for a given ID
|
* Receives an insertion order and returns the reference to an entry ID
|
||||||
|
* after which we will insert the new entry
|
||||||
*/
|
*/
|
||||||
|
export function getInsertAfterId(
|
||||||
|
rundown: Rundown,
|
||||||
|
parent: OntimeGroup | null,
|
||||||
|
afterId?: EntryId,
|
||||||
|
beforeId?: EntryId,
|
||||||
|
): EntryId | null {
|
||||||
|
if (afterId) return afterId;
|
||||||
|
if (!beforeId) return null;
|
||||||
|
|
||||||
|
const insertionList = parent ? parent.entries : rundown.order;
|
||||||
|
if (!insertionList || insertionList.length === 0) return null;
|
||||||
|
|
||||||
|
const atIndex = insertionList.findIndex((id) => id === beforeId);
|
||||||
|
if (atIndex < 1) return null;
|
||||||
|
return insertionList[atIndex - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add entry to rundown, mutates the rundown in place.
|
||||||
|
* Handles the following cases:
|
||||||
|
* - 1a. add entry in group, after a given entry
|
||||||
|
* - 1b. add entry in group, at the beginning (right after the group header)
|
||||||
|
* - 2a. add entry to the rundown, after a given entry
|
||||||
|
* - 2b. add entry to the rundown, at the beginning
|
||||||
|
*/
|
||||||
|
export function addToRundown(
|
||||||
|
rundown: Rundown,
|
||||||
|
entry: OntimeEntry,
|
||||||
|
afterId: EntryId | null,
|
||||||
|
parent: OntimeGroup | null,
|
||||||
|
): OntimeEntry {
|
||||||
|
if (parent) {
|
||||||
|
// 1. inserting an entry inside a group
|
||||||
|
|
||||||
|
// assign the parent reference on the entry
|
||||||
|
if ('parent' in entry) {
|
||||||
|
entry.parent = parent.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (afterId) {
|
||||||
|
// 1a. insert after a given entry within the group
|
||||||
|
const atEventsIndex = parent.entries.indexOf(afterId) + 1;
|
||||||
|
const atFlatIndex = rundown.flatOrder.indexOf(afterId) + 1;
|
||||||
|
parent.entries = insertAtIndex(atEventsIndex, entry.id, parent.entries);
|
||||||
|
rundown.flatOrder = insertAtIndex(atFlatIndex, entry.id, rundown.flatOrder);
|
||||||
|
} else {
|
||||||
|
// 1b. insert at the beginning of the group (right after the group header in flatOrder)
|
||||||
|
parent.entries = insertAtIndex(0, entry.id, parent.entries);
|
||||||
|
const atFlatIndex = rundown.flatOrder.indexOf(parent.id) + 1;
|
||||||
|
rundown.flatOrder = insertAtIndex(atFlatIndex, entry.id, rundown.flatOrder);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// 2. inserting an entry at top level
|
||||||
|
if (afterId) {
|
||||||
|
// 2a. insert after a given entry
|
||||||
|
const atOrderIndex = rundown.order.indexOf(afterId) + 1;
|
||||||
|
const atFlatIndex = rundown.flatOrder.indexOf(afterId) + 1;
|
||||||
|
rundown.order = insertAtIndex(atOrderIndex, entry.id, rundown.order);
|
||||||
|
rundown.flatOrder = insertAtIndex(atFlatIndex, entry.id, rundown.flatOrder);
|
||||||
|
} else {
|
||||||
|
// 2b. insert at the beginning
|
||||||
|
rundown.order = insertAtIndex(0, entry.id, rundown.order);
|
||||||
|
rundown.flatOrder = insertAtIndex(0, entry.id, rundown.flatOrder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// either way, we register the entry in the entries map
|
||||||
|
rundown.entries[entry.id] = entry;
|
||||||
|
return entry;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user