mirror of
https://github.com/nasa/openmct.git
synced 2025-01-29 15:43:52 +00:00
Ensure previews work for plots (#7459)
* fix large view in tree * remove existing view concept * fix plots in overlays * remove debug and actually remove overlays when dismissed * add test * improve tests * move test
This commit is contained in:
parent
0aceb4b590
commit
eeb8e9704b
88
e2e/tests/functional/plugins/plot/previews.e2e.spec.js
Normal file
88
e2e/tests/functional/plugins/plot/previews.e2e.spec.js
Normal file
@ -0,0 +1,88 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2024, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
import { createDomainObjectWithDefaults } from '../../../../appActions.js';
|
||||
import { expect, test } from '../../../../pluginFixtures.js';
|
||||
|
||||
test.describe('Plots work in Previews', () => {
|
||||
test('We can preview plot in display layouts', async ({ page, openmctConfig }) => {
|
||||
const { myItemsFolderName } = openmctConfig;
|
||||
await page.goto('./', { waitUntil: 'domcontentloaded' });
|
||||
// Create a Sinewave Generator
|
||||
const sineWaveObject = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Sine Wave Generator'
|
||||
});
|
||||
// Create a Display Layout
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Display Layout',
|
||||
name: 'Test Display Layout'
|
||||
});
|
||||
// Edit Display Layout
|
||||
await page.getByLabel('Edit Object').click();
|
||||
|
||||
// Expand the 'My Items' folder in the left tree
|
||||
await page.getByLabel(`Expand ${myItemsFolderName} folder`).click();
|
||||
// Add the Sine Wave Generator to the Display Layout and save changes
|
||||
const treePane = page.getByRole('tree', {
|
||||
name: 'Main Tree'
|
||||
});
|
||||
const sineWaveGeneratorTreeItem = treePane.getByRole('treeitem', {
|
||||
name: new RegExp(sineWaveObject.name)
|
||||
});
|
||||
const layoutGridHolder = page.getByLabel('Test Display Layout Layout Grid');
|
||||
await sineWaveGeneratorTreeItem.dragTo(layoutGridHolder);
|
||||
await page.getByLabel('Save').click();
|
||||
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
|
||||
|
||||
// right click on the plot and select view large
|
||||
await page.getByLabel('Sine', { exact: true }).click({ button: 'right' });
|
||||
await page.getByLabel('View Historical Data').click();
|
||||
await expect(page.getByLabel('Preview Container').getByLabel('Plot Canvas')).toBeVisible();
|
||||
await page.getByLabel('Close').click();
|
||||
await page.getByLabel('Expand Test Display Layout layout').click();
|
||||
|
||||
// change to a plot and ensure embiggen works
|
||||
await page.getByLabel('Edit Object').click();
|
||||
await page.getByLabel('Move Sub-object Frame').click();
|
||||
await page.getByText('View type').click();
|
||||
await page.getByText('Overlay Plot').click();
|
||||
await page.getByLabel('Save').click();
|
||||
await page.getByRole('listitem', { name: 'Save and Finish Editing' }).click();
|
||||
await expect(
|
||||
page.getByLabel('Test Display Layout Layout', { exact: true }).getByLabel('Plot Canvas')
|
||||
).toBeVisible();
|
||||
await expect(page.getByLabel('Preview Container')).toBeHidden();
|
||||
await page.getByLabel('Large View').click();
|
||||
await expect(page.getByLabel('Preview Container').getByLabel('Plot Canvas')).toBeVisible();
|
||||
await page.getByLabel('Close').click();
|
||||
|
||||
// get last sinewave tree item (in the display layout)
|
||||
await page
|
||||
.getByRole('treeitem', { name: /Sine Wave Generator/ })
|
||||
.locator('a')
|
||||
.last()
|
||||
.click({ button: 'right' });
|
||||
await page.getByLabel('View', { exact: true }).click();
|
||||
await expect(page.getByLabel('Preview Container').getByLabel('Plot Canvas')).toBeVisible();
|
||||
await page.getByLabel('Close').click();
|
||||
});
|
||||
});
|
@ -61,6 +61,7 @@ class Overlay extends EventEmitter {
|
||||
dismiss() {
|
||||
this.emit('destroy');
|
||||
this.destroy();
|
||||
this.container.remove();
|
||||
}
|
||||
|
||||
//Ensures that any callers are notified that the overlay is dismissed
|
||||
|
@ -22,8 +22,20 @@
|
||||
|
||||
<template>
|
||||
<div ref="chart" class="gl-plot-chart-area">
|
||||
<canvas id="2dContext" :style="canvasStyle" class="js-overlay-canvas" role="img"></canvas>
|
||||
<canvas id="webglContext" :style="canvasStyle" class="js-main-canvas" role="img"></canvas>
|
||||
<canvas
|
||||
id="2dContext"
|
||||
:style="canvasStyle"
|
||||
class="js-overlay-canvas"
|
||||
role="img"
|
||||
aria-label="Overlay Canvas"
|
||||
></canvas>
|
||||
<canvas
|
||||
id="webglContext"
|
||||
:style="canvasStyle"
|
||||
class="js-main-canvas"
|
||||
role="img"
|
||||
aria-label="Plot Canvas"
|
||||
></canvas>
|
||||
<div ref="limitArea" class="js-limit-area" aria-hidden="true">
|
||||
<limit-label
|
||||
v-for="(limitLabel, index) in visibleLimitLabels"
|
||||
@ -202,9 +214,7 @@ export default {
|
||||
this.drawnOnce = false;
|
||||
const rootContainer = this.openmct.element;
|
||||
const options = {
|
||||
root: rootContainer,
|
||||
rootMargin: '0px',
|
||||
threshold: 1.0
|
||||
root: rootContainer
|
||||
};
|
||||
this.visibilityObserver = new IntersectionObserver(this.visibilityChanged, options);
|
||||
eventHelpers.extend(this);
|
||||
@ -286,11 +296,16 @@ export default {
|
||||
// and we need to use the Open MCT root element as the root of the intersection observer.
|
||||
if (entry.target === this.chartContainer) {
|
||||
const wasVisible = this.chartVisible;
|
||||
this.chartVisible = entry.isIntersecting;
|
||||
if (!this.chartVisible) {
|
||||
// destroy the chart
|
||||
const isNowVisible = entry.isIntersecting;
|
||||
const chartInOverlayWindow = this.chartContainer?.closest('.js-overlay') !== null;
|
||||
|
||||
if (!isNowVisible && !chartInOverlayWindow) {
|
||||
this.chartVisible = false;
|
||||
this.destroyCanvas();
|
||||
} else if (!wasVisible && this.chartVisible) {
|
||||
} else if (!isNowVisible && chartInOverlayWindow) {
|
||||
this.chartVisible = true;
|
||||
} else if (!wasVisible && isNowVisible) {
|
||||
this.chartVisible = true;
|
||||
// rebuild the chart
|
||||
this.buildCanvasElements();
|
||||
const canvasInitialized = this.readyCanvasForDrawing();
|
||||
@ -298,8 +313,8 @@ export default {
|
||||
this.draw();
|
||||
}
|
||||
this.$emit('plot-reinitialize-canvas');
|
||||
} else if (wasVisible && this.chartVisible) {
|
||||
// ignore, moving on
|
||||
} else {
|
||||
this.chartVisible = isNowVisible;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -228,8 +228,8 @@ DrawWebGL.prototype.setDimensions = function (dimensions, origin) {
|
||||
}
|
||||
|
||||
if (dimensions && dimensions.length > 0 && origin && origin.length > 0) {
|
||||
this.gl.uniform2fv(this.uDimensions, dimensions);
|
||||
this.gl.uniform2fv(this.uOrigin, origin);
|
||||
this.gl?.uniform2fv(this.uDimensions, dimensions);
|
||||
this.gl?.uniform2fv(this.uOrigin, origin);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -75,6 +75,7 @@
|
||||
class="c-icon-button"
|
||||
:class="item.cssClass"
|
||||
:title="item.name"
|
||||
:aria-label="item.name"
|
||||
@click="item.onItemClicked"
|
||||
>
|
||||
<span class="c-icon-button__label">{{ item.name }}</span>
|
||||
|
@ -69,20 +69,23 @@ export default class PreviewAction extends EventEmitter {
|
||||
}
|
||||
);
|
||||
|
||||
let overlay = this._openmct.overlays.overlay({
|
||||
const overlay = this._openmct.overlays.overlay({
|
||||
element: vNode.el,
|
||||
size: 'large',
|
||||
autoHide: false,
|
||||
buttons: [
|
||||
{
|
||||
label: 'Done',
|
||||
callback: () => overlay.dismiss()
|
||||
callback: () => {
|
||||
overlay.dismiss();
|
||||
}
|
||||
}
|
||||
],
|
||||
onDestroy: () => {
|
||||
PreviewAction.isVisible = false;
|
||||
destroy();
|
||||
this.emit('isVisible', false);
|
||||
overlay.dismiss();
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -43,18 +43,24 @@ export default class VisibilityObserver {
|
||||
this.isIntersecting = true;
|
||||
this.calledOnce = false;
|
||||
const options = {
|
||||
root: rootContainer,
|
||||
rootMargin: '0px',
|
||||
threshold: 1.0
|
||||
root: rootContainer
|
||||
};
|
||||
this.#observer = new IntersectionObserver(this.#observerCallback, options);
|
||||
this.lastUnfiredFunc = null;
|
||||
this.renderWhenVisible = this.renderWhenVisible.bind(this);
|
||||
}
|
||||
|
||||
#inOverlay() {
|
||||
return this.#element.closest('.js-overlay') !== null;
|
||||
}
|
||||
|
||||
#observerCallback = ([entry]) => {
|
||||
if (entry.target === this.#element) {
|
||||
this.isIntersecting = entry.isIntersecting;
|
||||
if (this.#inOverlay() && !entry.isIntersecting) {
|
||||
this.isIntersecting = true;
|
||||
} else {
|
||||
this.isIntersecting = entry.isIntersecting;
|
||||
}
|
||||
if (this.isIntersecting && this.lastUnfiredFunc) {
|
||||
window.requestAnimationFrame(this.lastUnfiredFunc);
|
||||
this.lastUnfiredFunc = null;
|
||||
|
Loading…
x
Reference in New Issue
Block a user