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('––:––:––');
+});