Skip to content

Commit 90668a1

Browse files
Cherry pick 7737 - Independent Time Conductor interfering with plots behavior even if not enabled (#7956) (#8044)
Independent time conductor related handling for plot synchronization. (#7956) * Ensure that the mode set when independent time conductor is enabled/disabled is propagated correctly. Co-authored-by: Shefali Joshi <[email protected]>
1 parent 20a6e7e commit 90668a1

File tree

5 files changed

+75
-4
lines changed

5 files changed

+75
-4
lines changed

e2e/tests/functional/plugins/plot/plotControls.e2e.spec.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,4 +108,42 @@ test.describe('Plot Controls', () => {
108108
// Expect before and after plot points to match
109109
await expect(plotPixelSizeAtPause).toEqual(plotPixelSizeAfterWait);
110110
});
111+
112+
/*
113+
Test to verify that switching a plot's time context from global to
114+
its own independent time context and then back to global context works correctly.
115+
116+
After switching from fixed time mode (ITC) to real time mode (global context),
117+
the pause control for the plot should be available, indicating that it is following the right context.
118+
*/
119+
test('Plots follow the right time context', async ({ page }) => {
120+
// Set global time conductor to real-time mode
121+
await setRealTimeMode(page);
122+
123+
// hover over plot for plot controls
124+
await page.getByLabel('Plot Canvas').hover();
125+
// Ensure pause control is visible since global time conductor is in Real time mode.
126+
await expect(page.getByTitle('Pause incoming real-time data')).toBeVisible();
127+
128+
// Toggle independent time conductor ON
129+
await page.getByLabel('Enable Independent Time Conductor').click();
130+
131+
// Bring up the independent time conductor popup and switch to fixed time mode
132+
await page.getByLabel('Independent Time Conductor Settings').click();
133+
await page.getByLabel('Independent Time Conductor Mode Menu').click();
134+
await page.getByRole('menuitem', { name: /Fixed Timespan/ }).click();
135+
136+
// hover over plot for plot controls
137+
await page.getByLabel('Plot Canvas').hover();
138+
// Ensure pause control is no longer visible since the plot is following the independent time context
139+
await expect(page.getByTitle('Pause incoming real-time data')).toBeHidden();
140+
141+
// Toggle independent time conductor OFF - Note that the global time conductor is still in Real time mode
142+
await page.getByLabel('Disable Independent Time Conductor').click();
143+
144+
// hover over plot for plot controls
145+
await page.getByLabel('Plot Canvas').hover();
146+
// Ensure pause control is visible since the global time conductor is in real time mode
147+
await expect(page.getByTitle('Pause incoming real-time data')).toBeVisible();
148+
});
111149
});

src/api/time/IndependentTimeContext.js

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -359,6 +359,18 @@ class IndependentTimeContext extends TimeContext {
359359
}
360360
}
361361

362+
/**
363+
* @returns {boolean}
364+
* @override
365+
*/
366+
isFixed() {
367+
if (this.upstreamTimeContext) {
368+
return this.upstreamTimeContext.isFixed(...arguments);
369+
} else {
370+
return super.isFixed(...arguments);
371+
}
372+
}
373+
362374
/**
363375
* @returns {number}
364376
* @override
@@ -400,7 +412,7 @@ class IndependentTimeContext extends TimeContext {
400412
}
401413

402414
/**
403-
* Reset the time context to the global time context
415+
* Reset the time context from the global time context
404416
*/
405417
resetContext() {
406418
if (this.upstreamTimeContext) {
@@ -428,6 +440,10 @@ class IndependentTimeContext extends TimeContext {
428440
// Emit bounds so that views that are changing context get the upstream bounds
429441
this.emit('bounds', this.getBounds());
430442
this.emit(TIME_CONTEXT_EVENTS.boundsChanged, this.getBounds());
443+
// Also emit the mode in case it's different from previous time context
444+
if (this.getMode()) {
445+
this.emit(TIME_CONTEXT_EVENTS.modeChanged, this.#copy(this.getMode()));
446+
}
431447
}
432448

433449
/**
@@ -502,6 +518,10 @@ class IndependentTimeContext extends TimeContext {
502518
// Emit bounds so that views that are changing context get the upstream bounds
503519
this.emit('bounds', this.getBounds());
504520
this.emit(TIME_CONTEXT_EVENTS.boundsChanged, this.getBounds());
521+
// Also emit the mode in case it's different from the global time context
522+
if (this.getMode()) {
523+
this.emit(TIME_CONTEXT_EVENTS.modeChanged, this.#copy(this.getMode()));
524+
}
505525
// now that the view's context is set, tell others to check theirs in case they were following this view's context.
506526
this.globalTimeContext.emit('refreshContext', viewKey);
507527
}

src/api/time/TimeAPI.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import { FIXED_MODE_KEY, REALTIME_MODE_KEY } from '@/api/time/constants';
2424
import IndependentTimeContext from '@/api/time/IndependentTimeContext';
2525

26+
import { TIME_CONTEXT_EVENTS } from './constants';
2627
import GlobalTimeContext from './GlobalTimeContext.js';
2728

2829
/**
@@ -142,7 +143,7 @@ class TimeAPI extends GlobalTimeContext {
142143
addIndependentContext(key, value, clockKey) {
143144
let timeContext = this.getIndependentContext(key);
144145

145-
//stop following upstream time context since the view has it's own
146+
//stop following upstream time context since the view has its own
146147
timeContext.resetContext();
147148

148149
if (clockKey) {
@@ -152,6 +153,9 @@ class TimeAPI extends GlobalTimeContext {
152153
timeContext.setMode(FIXED_MODE_KEY, value);
153154
}
154155

156+
// Also emit the mode in case it's different from the previous time context
157+
timeContext.emit(TIME_CONTEXT_EVENTS.modeChanged, structuredClone(timeContext.getMode()));
158+
155159
// Notify any nested views to update, pass in the viewKey so that particular view can skip getting an upstream context
156160
this.emit('refreshContext', key);
157161

src/plugins/plot/MctPlot.vue

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,7 @@ export default {
537537
this.followTimeContext();
538538
},
539539
followTimeContext() {
540+
this.updateMode();
540541
this.updateDisplayBounds(this.timeContext.getBounds());
541542
this.timeContext.on('modeChanged', this.updateMode);
542543
this.timeContext.on('boundsChanged', this.updateDisplayBounds);

src/plugins/timeConductor/independent/IndependentTimeConductor.vue

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -243,12 +243,20 @@ export default {
243243
this.timeContext.off(TIME_CONTEXT_EVENTS.modeChanged, this.setTimeOptionsMode);
244244
},
245245
setTimeOptionsClock(clock) {
246+
// If the user has persisted any time options, then don't override them with global settings.
247+
if (this.independentTCEnabled) {
248+
return;
249+
}
246250
this.setTimeOptionsOffsets();
247251
this.timeOptions.clock = clock.key;
248252
},
249253
setTimeOptionsMode(mode) {
250-
this.setTimeOptionsOffsets();
251-
this.timeOptions.mode = mode;
254+
// If the user has persisted any time options, then don't override them with global settings.
255+
if (this.independentTCEnabled) {
256+
this.setTimeOptionsOffsets();
257+
this.timeOptions.mode = mode;
258+
this.isFixed = this.timeOptions.mode === FIXED_MODE_KEY;
259+
}
252260
},
253261
setTimeOptionsOffsets() {
254262
this.timeOptions.clockOffsets =

0 commit comments

Comments
 (0)