diff --git a/apps/client/src/features/overview/composite/TimeElements.tsx b/apps/client/src/features/overview/composite/TimeElements.tsx index 614662a67..60bfcef48 100644 --- a/apps/client/src/features/overview/composite/TimeElements.tsx +++ b/apps/client/src/features/overview/composite/TimeElements.tsx @@ -144,11 +144,11 @@ function FlagTimes() { {`${title ? title : 'Flag'} `}
} /> - {plannedTimeUntilDisplay} + {plannedTimeUntilDisplay}
} /> - {expectedTimeUntilDisplay} + {expectedTimeUntilDisplay}
); diff --git a/apps/server/src/stores/__tests__/runtimeState.test.ts b/apps/server/src/stores/__tests__/runtimeState.test.ts index 011ef2791..01dd67b59 100644 --- a/apps/server/src/stores/__tests__/runtimeState.test.ts +++ b/apps/server/src/stores/__tests__/runtimeState.test.ts @@ -378,7 +378,7 @@ describe('roll mode', () => { }); describe('loadGroupFlagAndEnd()', () => { - test('from no-group to a group will clear expectedGroupEnd', () => { + test('from no-group to a group will clear groupNow', () => { const rundown = makeRundown({ entries: { 0: makeOntimeEvent({ id: '0', parent: null }), @@ -393,7 +393,6 @@ describe('loadGroupFlagAndEnd()', () => { const state = { groupNow: null, eventNow: rundown.entries[11], - offset: { expectedGroupEnd: 123 }, } as RuntimeState; const metadata = { playableEventOrder: ['0', '11', '3'], flags: ['1'] } as RundownMetadata; @@ -402,12 +401,11 @@ describe('loadGroupFlagAndEnd()', () => { expect(state).toMatchObject({ groupNow: rundown.entries[1], - offset: { expectedGroupEnd: null }, eventNow: rundown.entries[11], }); }); - test('from a group to a different group will clear expectedGroupEnd', () => { + test('from a group to a different group will clear groupNow', () => { const rundown = makeRundown({ entries: { 0: makeOntimeEvent({ id: '0', parent: null }), @@ -421,7 +419,6 @@ describe('loadGroupFlagAndEnd()', () => { const state = { groupNow: rundown.entries[1], - offset: { expectedGroupEnd: 123 }, eventNow: rundown.entries[22], } as RuntimeState; @@ -431,12 +428,11 @@ describe('loadGroupFlagAndEnd()', () => { expect(state).toMatchObject({ groupNow: rundown.entries[2], - offset: { expectedGroupEnd: null }, eventNow: rundown.entries[22], }); }); - test('from group to a no-group will clear expectedGroupEnd', () => { + test('from group to a no-group will clear groupNow', () => { const rundown = makeRundown({ entries: { 0: makeOntimeEvent({ id: '0', parent: null }), @@ -450,7 +446,6 @@ describe('loadGroupFlagAndEnd()', () => { const state = { groupNow: rundown.entries[1], - offset: { expectedGroupEnd: 123 }, eventNow: rundown.entries[0], } as RuntimeState; @@ -460,7 +455,6 @@ describe('loadGroupFlagAndEnd()', () => { expect(state).toMatchObject({ groupNow: null, - offset: { expectedGroupEnd: null }, eventNow: rundown.entries[0], }); }); diff --git a/apps/server/src/stores/runtimeState.ts b/apps/server/src/stores/runtimeState.ts index da655230a..1b4993f0c 100644 --- a/apps/server/src/stores/runtimeState.ts +++ b/apps/server/src/stores/runtimeState.ts @@ -688,15 +688,18 @@ export function roll( * - offset.expectedFlagStart */ function getExpectedTimes(state = runtimeState) { + state.offset.expectedRundownEnd = null; + state.offset.expectedGroupEnd = null; + state.offset.expectedFlagStart = null; + state.offset.expectedRundownEnd = null; + const { offset } = state; const { plannedStart, actualStart } = state.rundown; const { eventNow } = state; if (!eventNow) return; - state.offset.expectedRundownEnd = null; if (state.groupNow) { - state.offset.expectedGroupEnd = null; const { _group } = state; if (_group !== null) { const { event: lastEvent, accumulatedGap, isLinkedToLoaded } = _group; @@ -714,7 +717,6 @@ function getExpectedTimes(state = runtimeState) { } if (state.eventFlag) { - state.offset.expectedFlagStart = null; const { _flag } = state; if (_flag) { const { event, accumulatedGap, isLinkedToLoaded } = _flag; @@ -743,8 +745,6 @@ function getExpectedTimes(state = runtimeState) { actualStart, }); state.offset.expectedRundownEnd = expectedStart + event.duration; - } else { - state.offset.expectedRundownEnd = null; } } @@ -754,8 +754,14 @@ export function loadGroupFlagAndEnd( currentIndex: MaybeNumber, state = runtimeState, ) { - if (currentIndex == null) return resetMetaData(); - if (state.eventNow === null) return resetMetaData(); + state.groupNow = null; + state._group = null; + state.eventFlag = null; + state._flag = null; + state._end = null; + + if (currentIndex == null) return; + if (state.eventNow === null) return; const currentGroupId = state.eventNow.parent; const flagsPresent = metadata.flags.length !== 0; @@ -764,6 +770,7 @@ export function loadGroupFlagAndEnd( const { entries } = rundown; const orderInGroup = currentGroupId ? (entries[currentGroupId] as OntimeGroup).entries : null; + state.groupNow = currentGroupId ? (entries[currentGroupId] as OntimeGroup) : null; const lastEventInGroup = orderInGroup ? getLastEventNormal(rundown.entries, orderInGroup).lastEvent : null; // if we don't have a any flags in the rundown then no need to look for it @@ -803,25 +810,8 @@ export function loadGroupFlagAndEnd( if (lastEvent) { state._end = { event: lastEvent, isLinkedToLoaded, accumulatedGap }; } - - if (!foundFlag) state.eventFlag = null; - - if ((state.groupNow?.id ?? null) !== currentGroupId) { - // we went into a new group - and it is different from the one we might have come from - state.offset.expectedGroupEnd = null; - } - - state.groupNow = currentGroupId ? (entries[currentGroupId] as OntimeGroup) : null; } -const resetMetaData = (state = runtimeState) => { - state.groupNow = null; - state._group = null; - state.eventFlag = null; - state._flag = null; - state._end = null; -}; - export function setOffsetMode(mode: OffsetMode) { runtimeState.offset.mode = mode; } diff --git a/e2e/tests/features/213-arrange-while-playing.spec.ts b/e2e/tests/features/213-arrange-while-playing.spec.ts index ca21926f5..5cd7abfa8 100644 --- a/e2e/tests/features/213-arrange-while-playing.spec.ts +++ b/e2e/tests/features/213-arrange-while-playing.spec.ts @@ -30,3 +30,39 @@ test('Rearrange while playing', async ({ page }) => { // but entry 1 should be the one playing (it will be unlinked as it will be the first event) await expect(page.getByTestId('entry-1').getByTestId('rundown-event')).toHaveAttribute('data-running'); }); + +test('flag and unflag an event while playing', async ({ page }) => { + await page.goto('http://localhost:4001/editor/'); + + await page.getByRole('button', { name: 'Clear all' }).click(); + await page.getByRole('button', { name: 'Delete all' }).click(); + await page.getByRole('button', { name: 'Create Event' }).click(); + await page.getByRole('button', { name: 'Event' }).nth(4).click(); + + //start the the first event + await page.getByTestId('entry-1').getByRole('button', { name: 'Start event' }).click(); + + // there should be no flag times + await expect(page.getByTestId('flag-plannedStart')).toContainText('––:––:––'); + await expect(page.getByTestId('flag-expectedStart')).toContainText('––:––:––'); + + // set the flag + await page.getByTestId('entry-2').getByTestId('rundown-event').getByText('2').click({ + button: 'right', + }); + await page.getByRole('menuitem', { name: 'Add flag' }).click(); + + // now there should be flag times + await expect(page.getByTestId('flag-plannedStart')).not.toContainText('––:––:––'); + await expect(page.getByTestId('flag-expectedStart')).not.toContainText('––:––:––'); + + // remove the flag again + await page.getByTestId('entry-2').getByTestId('rundown-event').getByText('2').click({ + button: 'right', + }); + await page.getByRole('menuitem', { name: 'Remove flag' }).click(); + + // there should be no flag times + await expect(page.getByTestId('flag-plannedStart')).toContainText('––:––:––'); + await expect(page.getByTestId('flag-expectedStart')).toContainText('––:––:––'); +});