diff --git a/e2e/tests/functional/plugins/plot/tagging.e2e.spec.js b/e2e/tests/functional/plugins/plot/tagging.e2e.spec.js index 567de81c4b..81e0f8653b 100644 --- a/e2e/tests/functional/plugins/plot/tagging.e2e.spec.js +++ b/e2e/tests/functional/plugins/plot/tagging.e2e.spec.js @@ -173,6 +173,21 @@ test.describe('Plot Tagging', () => { await basicTagsTests(page, canvas); await testTelemetryItem(page, canvas, alphaSineWave); + + // set to real time mode + await setRealTimeMode(page); + + // Search for Science + await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').click(); + await page.locator('[aria-label="OpenMCT Search"] input[type="search"]').fill('sc'); + // click on the search result + await page.getByRole('searchbox', { name: 'OpenMCT Search' }).getByText('Alpha Sine Wave').first().click(); + // wait for plot progress bar to disappear + await page.locator('.l-view-section.c-progress-bar').waitFor({ state: 'detached' }); + // expect plot to be paused + await expect(page.locator('[title="Resume displaying real-time data"]')).toBeVisible(); + + await setFixedTimeMode(page); }); test('Tags work with Plot View of telemetry items', async ({ page }) => { diff --git a/src/plugins/plot/MctPlot.vue b/src/plugins/plot/MctPlot.vue index f11e463a89..410e5be1e2 100644 --- a/src/plugins/plot/MctPlot.vue +++ b/src/plugins/plot/MctPlot.vue @@ -400,7 +400,7 @@ export default { this.removeStatusListener = this.openmct.status.observe(this.domainObject.identifier, this.updateStatus); this.openmct.objectViews.on('clearData', this.clearData); - this.$on('loadingUpdated', this.loadAnnotations); + this.$on('loadingComplete', this.loadAnnotations); this.openmct.selection.on('change', this.updateSelection); this.setTimeContext(); @@ -415,7 +415,7 @@ export default { this.destroy(); }, methods: { - updateSelection(selection) { + async updateSelection(selection) { const selectionContext = selection?.[0]?.[0]?.context?.item; // on clicking on a search result we highlight the annotation and zoom - we know it's an annotation result when isAnnotationSearchResult === true // We shouldn't zoom when we're selecting existing annotations to view them or creating new annotations. @@ -434,15 +434,7 @@ export default { return; } - const currentXaxis = this.config.xAxis.get('displayRange'); - const currentYaxis = this.config.yAxis.get('displayRange'); - - // when there is no plot data, the ranges can be undefined - // in which case we should not perform selection - if (!currentXaxis || !currentYaxis) { - return; - } - + await this.waitForAxesToLoad(); const selectedAnnotations = selection?.[0]?.[0]?.context?.annotations; //This section is only for the annotations search results entry to displaying annotations if (isAnnotationSearchResult) { @@ -452,10 +444,26 @@ export default { //This section is common to all entry points for annotation display this.prepareExistingAnnotationSelection(selectedAnnotations); }, + waitForAxesToLoad() { + return new Promise(resolve => { + // When there is no plot data, the ranges can be undefined + // in which case we should not perform selection. + const currentXaxis = this.config.xAxis.get('displayRange'); + const currentYaxis = this.config.yAxis.get('displayRange'); + if (!currentXaxis || !currentYaxis) { + this.$once('loadingComplete', () => { + resolve(); + }); + } else { + resolve(); + } + }); + }, showAnnotationsFromSearchResults(selectedAnnotations) { - //Start section - if (selectedAnnotations?.length) { + // pause the plot if we haven't already so we can actually display + // the annotations + this.freeze(); // just use first annotation const boundingBoxes = Object.values(selectedAnnotations[0].targets); let minX = Number.MAX_SAFE_INTEGER; @@ -672,6 +680,9 @@ export default { stopLoading() { this.pending -= 1; this.updateLoading(); + if (this.pending === 0) { + this.$emit('loadingComplete'); + } }, updateLoading() { @@ -1687,6 +1698,9 @@ export default { }, resumeRealtimeData() { + // remove annotation selections + this.rectangles = []; + this.clearPanZoomHistory(); this.userViewportChangeEnd(); }, diff --git a/src/ui/layout/search/AnnotationSearchResult.vue b/src/ui/layout/search/AnnotationSearchResult.vue index cefd58d740..1e62b8a2ee 100644 --- a/src/ui/layout/search/AnnotationSearchResult.vue +++ b/src/ui/layout/search/AnnotationSearchResult.vue @@ -129,9 +129,11 @@ export default { mounted() { this.previewAction = new PreviewAction(this.openmct); this.previewAction.on('isVisible', this.togglePreviewState); + this.clickedPlotAnnotation = this.clickedPlotAnnotation.bind(this); }, destroyed() { this.previewAction.off('isVisible', this.togglePreviewState); + this.openmct.selection.off('change', this.clickedPlotAnnotation); }, methods: { clickedResult(event) { @@ -141,15 +143,19 @@ export default { this.preview(objectPath); } else { const resultUrl = identifierToString(this.openmct, objectPath); + if (!this.openmct.router.isNavigatedObject(objectPath)) { + // if we're not on the correct page, navigate to the object, + // then wait for the selection event to fire before issuing a new selection + if (this.result.annotationType === this.openmct.annotation.ANNOTATION_TYPES.PLOT_SPATIAL) { + this.openmct.selection.on('change', this.clickedPlotAnnotation); + } - this.openmct.router.navigate(resultUrl); - } - - if (this.result.annotationType === this.openmct.annotation.ANNOTATION_TYPES.PLOT_SPATIAL) { - //wait a beat for the navigation - setTimeout(() => { + this.openmct.router.navigate(resultUrl); + } else { + // if this is the navigated object, then we are already on the correct page + // and just need to issue the selection event this.clickedPlotAnnotation(); - }, 100); + } } }, preview(objectPath) { @@ -158,6 +164,8 @@ export default { } }, clickedPlotAnnotation() { + this.openmct.selection.off('change', this.clickedPlotAnnotation); + const targetDetails = {}; const targetDomainObjects = {}; Object.entries(this.result.targets).forEach(([key, value]) => {