fix: reordering out of a block

This commit is contained in:
Carlos Valente
2025-07-04 21:42:18 +02:00
committed by Carlos Valente
parent c32203c759
commit 3790681bec
5 changed files with 54 additions and 12 deletions
@@ -480,7 +480,7 @@ describe('moveDown()', () => {
it('moves an entry down out of a group', () => { it('moves an entry down out of a group', () => {
expect(moveDown('12', rundown.flatOrder, rundown.entries)).toStrictEqual({ expect(moveDown('12', rundown.flatOrder, rundown.entries)).toStrictEqual({
destinationId: '4', destinationId: 'block',
order: 'after', order: 'after',
}); });
}); });
@@ -244,17 +244,20 @@ export function moveDown(
const currentIndex = flatOrder.indexOf(entryId); const currentIndex = flatOrder.indexOf(entryId);
const nextEntryId = flatOrder[currentIndex + 1]; const nextEntryId = flatOrder[currentIndex + 1];
// 1. moving at the top of the list // 1. check if we're the last entry in a block
if (!nextEntryId) { if ('parent' in currentEntry && currentEntry.parent !== null) {
// 1a. we are in a block and need to move outside of it const parentBlock = entries[currentEntry.parent];
if ('parent' in currentEntry && currentEntry.parent !== null) { if (isOntimeBlock(parentBlock) && parentBlock.entries[parentBlock.entries.length - 1] === entryId) {
return { destinationId: currentEntry.parent, order: 'after' }; return { destinationId: currentEntry.parent, order: 'after' };
} }
// 1b. we are at the end of the rundown, no movement possible }
// 2. moving at the end of the list
if (!nextEntryId) {
return { destinationId: null, order: 'after' }; return { destinationId: null, order: 'after' };
} }
// 2. moving a block (always moves at top level) // 3. moving a block (always moves at top level)
if (isOntimeBlock(currentEntry)) { if (isOntimeBlock(currentEntry)) {
// if next entry is inside this block, skip past all children // if next entry is inside this block, skip past all children
if (currentEntry.entries.includes(nextEntryId)) { if (currentEntry.entries.includes(nextEntryId)) {
@@ -275,7 +278,7 @@ export function moveDown(
const nextEntry = entries[nextEntryId]; const nextEntry = entries[nextEntryId];
const currentEntryParent = currentEntry.parent; const currentEntryParent = currentEntry.parent;
// 3. handle moving relative to blocks // 4. handle moving relative to blocks
if (isOntimeBlock(nextEntry)) { if (isOntimeBlock(nextEntry)) {
if (currentEntryParent === null) { if (currentEntryParent === null) {
// we are entering a block // we are entering a block
@@ -289,7 +292,7 @@ export function moveDown(
} }
} }
// 4. handle moving between block and top level // 5. handle moving between block and top level
const nextEntryParent = isOntimeEvent(nextEntry) ? nextEntry.parent : null; const nextEntryParent = isOntimeEvent(nextEntry) ? nextEntry.parent : null;
if (nextEntryParent !== null && currentEntryParent === null) { if (nextEntryParent !== null && currentEntryParent === null) {
return { destinationId: nextEntryId, order: 'after' }; return { destinationId: nextEntryId, order: 'after' };
@@ -926,7 +926,7 @@ describe('rundownMutation.reorder()', () => {
expect(rundown.order).toStrictEqual(['3', '1', '2']); expect(rundown.order).toStrictEqual(['3', '1', '2']);
}); });
it('moves an event out of a block', () => { it('moves an event out and before a block', () => {
const rundown = makeRundown({ const rundown = makeRundown({
order: ['1', '2'], order: ['1', '2'],
flatOrder: ['1', '11', '2'], flatOrder: ['1', '11', '2'],
@@ -943,6 +943,35 @@ describe('rundownMutation.reorder()', () => {
expect(rundown.entries['1']).toMatchObject({ expect(rundown.entries['1']).toMatchObject({
entries: [], entries: [],
}); });
expect(rundown.entries['11']).toMatchObject({
parent: null,
});
expect(rundown.entries['2']).toMatchObject({
parent: null,
});
});
it('moves an event out and after a block', () => {
const rundown = makeRundown({
order: ['1', 'block', '2'],
flatOrder: ['1', 'block', '11', '2'],
entries: {
'1': makeOntimeEvent({ id: '1', parent: null }),
block: makeOntimeBlock({ id: 'block', entries: ['11'] }),
'11': makeOntimeEvent({ id: '11', parent: 'block' }),
'2': makeOntimeEvent({ id: '2', parent: null }),
},
});
rundownMutation.reorder(rundown, rundown.entries['11'], rundown.entries['block'], 'after');
expect(rundown.order).toStrictEqual(['1', 'block', '11', '2']);
expect(rundown.entries['block']).toMatchObject({
entries: [],
});
expect(rundown.entries['11']).toMatchObject({
parent: null,
});
expect(rundown.entries['2']).toMatchObject({ expect(rundown.entries['2']).toMatchObject({
parent: null, parent: null,
}); });
@@ -289,6 +289,10 @@ function reorder(rundown: Rundown, eventFrom: OntimeEntry, eventTo: OntimeEntry,
const fromParent: EntryId | null = (eventFrom as { parent?: EntryId })?.parent ?? null; const fromParent: EntryId | null = (eventFrom as { parent?: EntryId })?.parent ?? null;
const toParent = (() => { const toParent = (() => {
if (isOntimeBlock(eventTo)) { if (isOntimeBlock(eventTo)) {
// Special case: if we're moving relative to our own parent block, remove from block
if ('parent' in eventFrom && eventFrom.parent === eventTo.id) {
return null;
}
if (order === 'insert') { if (order === 'insert') {
// prevent blocks from being inserted into other blocks // prevent blocks from being inserted into other blocks
if (isOntimeBlock(eventFrom)) { if (isOntimeBlock(eventFrom)) {
@@ -313,8 +317,13 @@ function reorder(rundown: Rundown, eventFrom: OntimeEntry, eventTo: OntimeEntry,
const toIndex = (() => { const toIndex = (() => {
const baseIndex = destinationArray.indexOf(eventTo.id); const baseIndex = destinationArray.indexOf(eventTo.id);
if (order === 'before') return baseIndex; if (order === 'before') return baseIndex;
// only add one if we are moving down if (order === 'after') {
if (order === 'after') return baseIndex + (fromIndex < baseIndex ? 0 : 1); // When moving within the same array, we need to consider the source position
if (sourceArray === destinationArray && fromIndex <= baseIndex) {
return baseIndex;
}
return baseIndex + 1;
}
// for insert we add in the end of the array // for insert we add in the end of the array
return destinationArray.length; return destinationArray.length;
})(); })();
@@ -247,6 +247,7 @@ export function reorderEntry(entryId: EntryId, destinationId: EntryId, order: 'b
throw new Error('Event not found'); throw new Error('Event not found');
} }
console.log('reorder', eventFrom.id, eventTo.id, order);
rundownMutation.reorder(rundown, eventFrom, eventTo, order); rundownMutation.reorder(rundown, eventFrom, eventTo, order);
const { rundown: rundownResult, rundownMetadata, revision } = commit(); const { rundown: rundownResult, rundownMetadata, revision } = commit();