mirror of
https://github.com/cpvalente/ontime.git
synced 2026-08-19 14:14:17 +00:00
ae15f3cdc5
* refactor: align header columns * refactor: improve scrollbar visibility * refactor: center align table elements * refactor: make param elements stateful * fix: issue with collapsed elements not loosing value * fix: prevent search params containing multiple alias references * fix: the issue where a file disappears if it is both migrated and recovered in the same load operation (#1744) * refactor: disable group action for elements in groups * refactor: move context menu items into the event element (#1747) * feat: sheet import new features for v4 (#1730) * import milestone * fixup! import milestone * test: milestone import * add entries to group stop on new group or on group-end type * fixup! add entries to group * cleanup * add event target duration * link start if undefined * add skip import type * extract some to the excel paresing functions * tweaks to presentation * move file --------- Co-authored-by: Carlos Valente <carlosvalente@pm.me> * fix: notify runtimeStore of events bieng groupd * fix: improve authentication and stage detection in demo * chore: ship logo with project * fix: client is referenced by name * fix: prevent reflow in event editor * fix: stale render on selected event due to ref mismatch * Create/Load/Delete multiple rundowns (#1696) * refactor: restore last loaded rundown * refactor: initialise rundown in ProjectService * feat: allow switching rundowns ensure on coordination between the db object and the working object server provide list of rundowns implement switch in the UI implement delete implement new rundown button * fix: render order for floating button * refactor: appropriate names to service * refactor: rundown endpoints * refactor: save last loaded rundown ID * refactor: rundown management UI * refactor: emit refetch all on project load --------- Co-authored-by: Carlos Valente <carlosvalente@pm.me> * feat: recover single event subscription * fixup! feat: sheet import new features for v4 (#1730) * fix: prevent dropping a group inside another * fixup! refactor: move context menu items into the event element (#1747) * fix: prevent stale references to custom fields * fix: propagate updates to all rundowns * refactor: client rundown metadata (#1728) * generate metadata in the hook * move test * ensure there is always a last element * use for-loop * update metadata in useEfect * fully extract metadata generation * use direct assignment * cleanup --------- Co-authored-by: Carlos Valente <carlosvalente@pm.me> * refactor: small imporvement and tests for coerce functions (#1752) * refactor: small imporvement and tests for coerce functions add test `coerceString` add test `coerceBoolean` add test `coerceColour` * remove old todo * fix: consistent quick add behaviour * refactor: create flat rundown with metadata * fix: show add buttons on top * feat: allow editing milestones * refactor: style tweaks to rundown elements refactor: milestones are full width refactor: cuesheet header alignment fix: editor styling in cuesheet * refactor: virtualise table * refactor: improve overscan (#1758) * bump version to 4.0.0-alpha.5 --------- Co-authored-by: Alex Christoffer Rasmussen <ac@omnivox.dk>
287 lines
9.8 KiB
TypeScript
287 lines
9.8 KiB
TypeScript
import { EntryId, OntimeEvent, OntimeGroup, RundownEntries, SupportedEntry } from 'ontime-types';
|
|
|
|
import { makeSortableList, moveDown, moveUp, orderEntries } from '../rundown.utils';
|
|
|
|
describe('makeSortableList()', () => {
|
|
it('generates a list with group ends', () => {
|
|
const order = ['group-1', '2', 'group-3', 'group-4'];
|
|
const entries: RundownEntries = {
|
|
'group-1': { type: SupportedEntry.Group, id: 'group-1', entries: ['11'] } as OntimeGroup,
|
|
'11': { type: SupportedEntry.Event, id: '11', parent: 'group-1' } as OntimeEvent,
|
|
'2': { type: SupportedEntry.Event, id: '2', parent: null } as OntimeEvent,
|
|
'group-3': { type: SupportedEntry.Group, id: 'group-3', entries: ['31'] } as OntimeGroup,
|
|
'31': { type: SupportedEntry.Event, id: '31', parent: 'group-3' } as OntimeEvent,
|
|
'group-4': { type: SupportedEntry.Group, id: 'group-4', entries: [] as string[] } as OntimeGroup,
|
|
};
|
|
|
|
const sortableList = makeSortableList(order, entries);
|
|
expect(sortableList).toStrictEqual([
|
|
'group-1',
|
|
'11',
|
|
'end-group-1',
|
|
'2',
|
|
'group-3',
|
|
'31',
|
|
'end-group-3',
|
|
'group-4',
|
|
'end-group-4',
|
|
]);
|
|
});
|
|
|
|
it('closes dangling group', () => {
|
|
const order = ['group'];
|
|
const entries: RundownEntries = {
|
|
group: { type: SupportedEntry.Group, id: 'group-1', entries: ['11', '12'] } as OntimeGroup,
|
|
'11': { type: SupportedEntry.Event, id: '11', parent: 'group-1' } as OntimeEvent,
|
|
'12': { type: SupportedEntry.Event, id: '12', parent: 'group-1' } as OntimeEvent,
|
|
};
|
|
|
|
const sortableList = makeSortableList(order, entries);
|
|
expect(sortableList).toStrictEqual(['group-1', '11', '12', 'end-group-1']);
|
|
});
|
|
|
|
it('handles a list with just groups', () => {
|
|
const order = ['group-1', 'group-2'];
|
|
const entries: RundownEntries = {
|
|
'group-1': { type: SupportedEntry.Group, id: 'group-1', entries: [] as string[] } as OntimeGroup,
|
|
'group-2': { type: SupportedEntry.Group, id: 'group-2', entries: [] as string[] } as OntimeGroup,
|
|
};
|
|
|
|
const sortableList = makeSortableList(order, entries);
|
|
expect(sortableList).toStrictEqual(['group-1', 'end-group-1', 'group-2', 'end-group-2']);
|
|
});
|
|
});
|
|
|
|
describe('moveUp()', () => {
|
|
const rundown = {
|
|
entries: {
|
|
'1': { id: '1', type: 'event', parent: null } as OntimeEvent,
|
|
'2': { id: '2', type: 'event', parent: null } as OntimeEvent,
|
|
'3': { id: '3', type: 'event', parent: null } as OntimeEvent,
|
|
group: { id: 'group', type: 'group', entries: ['11', '12'] } as OntimeGroup,
|
|
'11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent,
|
|
'12': { id: '12', type: 'event', parent: 'group' } as OntimeEvent,
|
|
'4': { id: '4', type: 'event', parent: null } as OntimeEvent,
|
|
group2: { id: 'group2', type: 'group', entries: [] as EntryId[] } as OntimeGroup,
|
|
'5': { id: '5', type: 'event', parent: null } as OntimeEvent,
|
|
},
|
|
order: ['1', '2', '3', 'group', '4', 'group2', '5'],
|
|
flatOrder: ['1', '2', '3', 'group', '11', '12', '4', 'group2', '5'],
|
|
};
|
|
|
|
it('moving the first event is a noop', () => {
|
|
expect(moveUp('1', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: null,
|
|
order: 'before',
|
|
});
|
|
});
|
|
|
|
it('moves an entry up in the rundown', () => {
|
|
expect(moveUp('2', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: '1',
|
|
order: 'before',
|
|
});
|
|
});
|
|
|
|
it('moves an entry up inside a group', () => {
|
|
expect(moveUp('12', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: '11',
|
|
order: 'before',
|
|
});
|
|
});
|
|
|
|
it('moves an entry up into an empty group', () => {
|
|
expect(moveUp('5', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: 'group2',
|
|
order: 'insert',
|
|
});
|
|
});
|
|
|
|
it('moves an entry up into a group', () => {
|
|
expect(moveUp('4', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: '12',
|
|
order: 'after',
|
|
});
|
|
});
|
|
|
|
it('moves an entry up out of a group', () => {
|
|
expect(moveUp('11', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: 'group',
|
|
order: 'before',
|
|
});
|
|
});
|
|
|
|
it('moves a group in the rundown', () => {
|
|
expect(moveUp('group', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: '3',
|
|
order: 'before',
|
|
});
|
|
});
|
|
|
|
it('swaps two groups', () => {
|
|
const rundown = {
|
|
entries: {
|
|
group: { id: 'group', type: 'group', entries: ['11'] } as OntimeGroup,
|
|
'11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent,
|
|
group2: { id: 'group2', type: 'group', entries: [] as EntryId[] } as OntimeGroup,
|
|
},
|
|
order: ['group', 'group2'],
|
|
flatOrder: ['group', '11', 'group2'],
|
|
};
|
|
expect(moveUp('group2', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: 'group',
|
|
order: 'before',
|
|
});
|
|
});
|
|
|
|
it('moves before a group', () => {
|
|
const rundown = {
|
|
entries: {
|
|
group: { id: 'group', type: 'group', entries: ['11'] } as OntimeGroup,
|
|
'11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent,
|
|
},
|
|
order: ['group'],
|
|
flatOrder: ['group', '11'],
|
|
};
|
|
expect(moveUp('11', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: 'group',
|
|
order: 'before',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('moveDown()', () => {
|
|
const rundown = {
|
|
entries: {
|
|
'1': { id: '1', type: 'event', parent: null } as OntimeEvent,
|
|
'2': { id: '2', type: 'event', parent: null } as OntimeEvent,
|
|
'3': { id: '3', type: 'event', parent: null } as OntimeEvent,
|
|
group: { id: 'group', type: 'group', entries: ['11', '12'] } as OntimeGroup,
|
|
'11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent,
|
|
'12': { id: '12', type: 'event', parent: 'group' } as OntimeEvent,
|
|
'4': { id: '4', type: 'event', parent: null } as OntimeEvent,
|
|
group2: { id: 'group2', type: 'group', entries: [] as EntryId[] } as OntimeGroup,
|
|
'5': { id: '5', type: 'event', parent: null } as OntimeEvent,
|
|
},
|
|
order: ['1', '2', '3', 'group', '4', 'group2', '5'],
|
|
flatOrder: ['1', '2', '3', 'group', '11', '12', '4', 'group2', '5'],
|
|
};
|
|
|
|
it('moving the last event is a noop', () => {
|
|
expect(moveDown('5', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: null,
|
|
order: 'after',
|
|
});
|
|
});
|
|
|
|
it('moves an entry down in the rundown', () => {
|
|
expect(moveDown('2', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: '3',
|
|
order: 'after',
|
|
});
|
|
});
|
|
|
|
it('moves an entry down inside a group', () => {
|
|
expect(moveDown('11', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: '12',
|
|
order: 'after',
|
|
});
|
|
});
|
|
|
|
it('moves an entry down into an empty group', () => {
|
|
expect(moveDown('4', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: 'group2',
|
|
order: 'insert',
|
|
});
|
|
});
|
|
|
|
it('moves an entry down out of a group', () => {
|
|
expect(moveDown('12', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: 'group',
|
|
order: 'after',
|
|
});
|
|
});
|
|
|
|
it('moves an entry down into a group', () => {
|
|
expect(moveDown('3', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: '11',
|
|
order: 'before',
|
|
});
|
|
});
|
|
|
|
it('moves a group in the rundown', () => {
|
|
expect(moveDown('group', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: '4',
|
|
order: 'after',
|
|
});
|
|
});
|
|
|
|
it('swaps two groups', () => {
|
|
const rundown = {
|
|
entries: {
|
|
group: { id: 'group', type: 'group', entries: ['11'] } as OntimeGroup,
|
|
'11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent,
|
|
group2: { id: 'group2', type: 'group', entries: [] as EntryId[] } as OntimeGroup,
|
|
},
|
|
order: ['group', 'group2'],
|
|
flatOrder: ['group', '11', 'group2'],
|
|
};
|
|
expect(moveDown('group', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: 'group2',
|
|
order: 'after',
|
|
});
|
|
});
|
|
|
|
it('moves after a group', () => {
|
|
const rundown = {
|
|
entries: {
|
|
group: { id: 'group', type: 'group', entries: ['11'] } as OntimeGroup,
|
|
'11': { id: '11', type: 'event', parent: 'group' } as OntimeEvent,
|
|
},
|
|
order: ['group'],
|
|
flatOrder: ['group', '11'],
|
|
};
|
|
expect(moveDown('11', rundown.flatOrder, rundown.entries)).toStrictEqual({
|
|
destinationId: 'group',
|
|
order: 'after',
|
|
});
|
|
});
|
|
});
|
|
|
|
describe('orderEntries()', () => {
|
|
it('should return an empty array when both inputs are empty', () => {
|
|
const unorderedArray: string[] = [];
|
|
const flatOrder: string[] = [];
|
|
const result = orderEntries(unorderedArray, flatOrder);
|
|
expect(result).toEqual([]);
|
|
});
|
|
|
|
it('should return an ordered array based on flatOrder', () => {
|
|
const unorderedArray = ['b', 'a', 'c'];
|
|
const flatOrder = ['a', 'b', 'c'];
|
|
const result = orderEntries(unorderedArray, flatOrder);
|
|
expect(result).toEqual(['a', 'b', 'c']);
|
|
});
|
|
|
|
it('should ignore elements in unorderedArray not present in flatOrder', () => {
|
|
const unorderedArray = ['b', 'a', 'c', 'd'];
|
|
const flatOrder = ['a', 'b', 'c'];
|
|
const result = orderEntries(unorderedArray, flatOrder);
|
|
expect(result).toEqual(['a', 'b', 'c']);
|
|
});
|
|
|
|
it('should handle cases where flatOrder has elements not in unorderedArray', () => {
|
|
const unorderedArray = ['b', 'a'];
|
|
const flatOrder = ['a', 'b', 'c'];
|
|
const result = orderEntries(unorderedArray, flatOrder);
|
|
expect(result).toEqual(['a', 'b']);
|
|
});
|
|
|
|
it('should return an empty array if unorderedArray has no matching elements in flatOrder', () => {
|
|
const unorderedArray = ['x', 'y', 'z'];
|
|
const flatOrder = ['a', 'b', 'c'];
|
|
const result = orderEntries(unorderedArray, flatOrder);
|
|
expect(result).toEqual([]);
|
|
});
|
|
});
|