mirror of
https://github.com/nasa/openmct.git
synced 2024-12-19 21:27:52 +00:00
Limit lines handle plot resizing (#7151)
* Fix error when removing staleness subscription due to incorrect parameter * On resize, clear the drawing API to reset the height and width for point calculation. * Add e2e test to test limit lines after resizing the plot view. * We need to update viewport when drawing limits in case there is no data for plots. * Address review comments. change event naming convention and reduce debounce time. * Use limit line and label seriesKeys to make ids unique * Improve locator for limit lines checkbox * Add a check for network requests when limit lines are redrawn
This commit is contained in:
parent
eae51356c8
commit
0bdd0963a4
@ -189,6 +189,57 @@ test.describe('Overlay Plot', () => {
|
||||
await assertLimitLinesExistAndAreVisible(page);
|
||||
});
|
||||
|
||||
test('Limit lines adjust when series is resized', async ({ page }) => {
|
||||
test.info().annotations.push({
|
||||
type: 'issue',
|
||||
description: 'https://github.com/nasa/openmct/issues/6987'
|
||||
});
|
||||
// Create an Overlay Plot with a default SWG
|
||||
overlayPlot = await createDomainObjectWithDefaults(page, {
|
||||
type: 'Overlay Plot'
|
||||
});
|
||||
|
||||
await createDomainObjectWithDefaults(page, {
|
||||
type: 'Sine Wave Generator',
|
||||
parent: overlayPlot.uuid
|
||||
});
|
||||
|
||||
await page.goto(overlayPlot.url);
|
||||
|
||||
// Assert that no limit lines are shown by default
|
||||
await page.waitForSelector('.js-limit-area', { state: 'attached' });
|
||||
expect(await page.locator('.c-plot-limit-line').count()).toBe(0);
|
||||
|
||||
// Enter edit mode
|
||||
await page.getByLabel('Edit Object').click();
|
||||
|
||||
// Expand the "Sine Wave Generator" plot series options and enable limit lines
|
||||
await page.getByRole('tab', { name: 'Config' }).click();
|
||||
await page
|
||||
.getByRole('list', { name: 'Plot Series Properties' })
|
||||
.locator('span')
|
||||
.first()
|
||||
.click();
|
||||
await page
|
||||
.getByRole('list', { name: 'Plot Series Properties' })
|
||||
.getByRole('checkbox', { name: 'Limit lines' })
|
||||
.check();
|
||||
|
||||
await assertLimitLinesExistAndAreVisible(page);
|
||||
|
||||
// Save (exit edit mode)
|
||||
await page.locator('button[title="Save"]').click();
|
||||
await page.locator('li[title="Save and Finish Editing"]').click();
|
||||
|
||||
const initialCoords = await assertLimitLinesExistAndAreVisible(page);
|
||||
// Resize the chart container by showing the snapshot pane.
|
||||
await page.getByLabel('Show Snapshots').click();
|
||||
|
||||
const newCoords = await assertLimitLinesExistAndAreVisible(page);
|
||||
// We just need to know that the first limit line redrew somewhere lower than the initial y position.
|
||||
expect(newCoords.y).toBeGreaterThan(initialCoords.y);
|
||||
});
|
||||
|
||||
test('The elements pool supports dragging series into multiple y-axis buckets', async ({
|
||||
page
|
||||
}) => {
|
||||
@ -337,4 +388,7 @@ async function assertLimitLinesExistAndAreVisible(page) {
|
||||
for (let i = 0; i < limitLineCount; i++) {
|
||||
await expect(page.locator('.c-plot-limit-line').nth(i)).toBeVisible();
|
||||
}
|
||||
|
||||
const firstLimitLineCoords = await page.locator('.c-plot-limit-line').first().boundingBox();
|
||||
return firstLimitLineCoords;
|
||||
}
|
||||
|
@ -201,10 +201,15 @@ export default {
|
||||
|
||||
if (this.compositionCollection) {
|
||||
this.compositionCollection.on('add', this.subscribeToStaleness);
|
||||
this.compositionCollection.on('remove', this.triggerUnsubscribeFromStaleness);
|
||||
this.compositionCollection.on('remove', this.removeSubscription);
|
||||
this.compositionCollection.load();
|
||||
}
|
||||
},
|
||||
removeSubscription(identifier) {
|
||||
this.triggerUnsubscribeFromStaleness({
|
||||
identifier
|
||||
});
|
||||
},
|
||||
loadingUpdated(loading) {
|
||||
this.loading = loading;
|
||||
this.$emit('loading-updated', ...arguments);
|
||||
@ -212,7 +217,7 @@ export default {
|
||||
destroy() {
|
||||
if (this.compositionCollection) {
|
||||
this.compositionCollection.off('add', this.subscribeToStaleness);
|
||||
this.compositionCollection.off('remove', this.triggerUnsubscribeFromStaleness);
|
||||
this.compositionCollection.off('remove', this.removeSubscription);
|
||||
}
|
||||
|
||||
this.imageExporter = null;
|
||||
|
@ -39,13 +39,13 @@
|
||||
<div ref="limitArea" class="js-limit-area" aria-hidden="true">
|
||||
<limit-label
|
||||
v-for="(limitLabel, index) in visibleLimitLabels"
|
||||
:key="index"
|
||||
:key="`limitLabel-${limitLabel.limit.seriesKey}-${index}`"
|
||||
:point="limitLabel.point"
|
||||
:limit="limitLabel.limit"
|
||||
></limit-label>
|
||||
<limit-line
|
||||
v-for="(limitLine, index) in visibleLimitLines"
|
||||
:key="index"
|
||||
:key="`limitLine-${limitLine.limit.seriesKey}${index}`"
|
||||
:point="limitLine.point"
|
||||
:limit="limitLine.limit"
|
||||
></limit-line>
|
||||
@ -201,9 +201,8 @@ export default {
|
||||
handler() {
|
||||
this.hiddenYAxisIds.forEach((id) => {
|
||||
this.resetYOffsetAndSeriesDataForYAxis(id);
|
||||
this.updateLimitLines();
|
||||
});
|
||||
this.scheduleDraw();
|
||||
this.scheduleDraw(true);
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
@ -271,12 +270,19 @@ export default {
|
||||
this.listenTo(this.config.xAxis, 'change', this.redrawIfNotAlreadyHandled);
|
||||
this.config.series.forEach(this.onSeriesAdd, this);
|
||||
this.$emit('chart-loaded');
|
||||
|
||||
this.handleWindowResize = _.debounce(this.handleWindowResize, 250);
|
||||
this.chartResizeObserver = new ResizeObserver(this.handleWindowResize);
|
||||
this.chartResizeObserver.observe(this.$parent.$refs.chartContainer);
|
||||
},
|
||||
beforeUnmount() {
|
||||
this.destroy();
|
||||
this.visibilityObserver.unobserve(this.chartContainer);
|
||||
},
|
||||
methods: {
|
||||
handleWindowResize() {
|
||||
this.scheduleDraw(true);
|
||||
},
|
||||
getConfig() {
|
||||
const configId = this.openmct.objects.makeKeyString(this.domainObject.identifier);
|
||||
let config = configStore.get(configId);
|
||||
@ -445,7 +451,6 @@ export default {
|
||||
|
||||
this.makeLimitLines(series);
|
||||
this.updateLimitLines();
|
||||
this.scheduleDraw();
|
||||
},
|
||||
resetAxisAndRedraw(newYAxisId, oldYAxisId, series) {
|
||||
if (!oldYAxisId) {
|
||||
@ -459,8 +464,7 @@ export default {
|
||||
//Make the chart elements again for the new y-axis and offset
|
||||
this.makeChartElement(series);
|
||||
this.makeLimitLines(series);
|
||||
this.updateLimitLines();
|
||||
this.scheduleDraw();
|
||||
this.scheduleDraw(true);
|
||||
},
|
||||
destroy() {
|
||||
this.destroyCanvas();
|
||||
@ -469,6 +473,10 @@ export default {
|
||||
this.limitLines.forEach((line) => line.destroy());
|
||||
this.pointSets.forEach((pointSet) => pointSet.destroy());
|
||||
this.alarmSets.forEach((alarmSet) => alarmSet.destroy());
|
||||
DrawLoader.releaseDrawAPI(this.drawAPI);
|
||||
if (this.chartResizeObserver) {
|
||||
this.chartResizeObserver.disconnect();
|
||||
}
|
||||
},
|
||||
resetYOffsetAndSeriesDataForYAxis(yAxisId) {
|
||||
delete this.offset[yAxisId].y;
|
||||
@ -703,12 +711,11 @@ export default {
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateLimitLines();
|
||||
this.scheduleDraw();
|
||||
this.scheduleDraw(true);
|
||||
},
|
||||
scheduleDraw() {
|
||||
scheduleDraw(updateLimitLines) {
|
||||
if (!this.drawScheduled) {
|
||||
const called = this.renderWhenVisible(this.draw);
|
||||
const called = this.renderWhenVisible(this.draw.bind(this, updateLimitLines));
|
||||
this.drawScheduled = called;
|
||||
if (!this.drawnOnce && called) {
|
||||
this.drawnOnce = true;
|
||||
@ -716,7 +723,7 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
draw() {
|
||||
draw(updateLimitLines) {
|
||||
this.drawScheduled = false;
|
||||
if (this.isDestroyed || !this.chartVisible) {
|
||||
return;
|
||||
@ -744,6 +751,11 @@ export default {
|
||||
this.prepareToDrawAnnotationSelections(id);
|
||||
}
|
||||
});
|
||||
// We must do the limit line drawing after the drawAPI has been cleared (which sets the height and width of the draw API)
|
||||
// and the viewport is updated so that we have the right height/width for limit line x and y calculations
|
||||
if (updateLimitLines) {
|
||||
this.updateLimitLines();
|
||||
}
|
||||
},
|
||||
updateViewport(yAxisId) {
|
||||
if (!this.chartVisible) {
|
||||
@ -799,9 +811,12 @@ export default {
|
||||
pointSets.forEach(this.drawPoints, this);
|
||||
const alarmSets = this.alarmSets.filter(this.matchByYAxisId.bind(this, id));
|
||||
alarmSets.forEach(this.drawAlarmPoints, this);
|
||||
//console.timeEnd('📈 drawSeries');
|
||||
},
|
||||
updateLimitLines() {
|
||||
//reset
|
||||
this.visibleLimitLabels = [];
|
||||
this.visibleLimitLines = [];
|
||||
|
||||
this.config.series.models.forEach((series) => {
|
||||
const yAxisId = series.get('yAxisId');
|
||||
|
||||
@ -820,11 +835,7 @@ export default {
|
||||
if (!this.drawAPI.origin) {
|
||||
return;
|
||||
}
|
||||
|
||||
let limitPointOverlap = [];
|
||||
//reset
|
||||
this.visibleLimitLabels = [];
|
||||
this.visibleLimitLines = [];
|
||||
|
||||
this.limitLines.forEach((limitLine) => {
|
||||
limitLine.limits.forEach((limit) => {
|
||||
|
@ -91,9 +91,16 @@
|
||||
</div>
|
||||
</li>
|
||||
<li class="grid-row">
|
||||
<div class="grid-cell label" title="Display limit lines">Limit lines</div>
|
||||
<div id="limit-lines-checkbox" class="grid-cell label" title="Display limit lines">
|
||||
Limit lines
|
||||
</div>
|
||||
<div class="grid-cell value">
|
||||
<input v-model="limitLines" type="checkbox" @change="updateForm('limitLines')" />
|
||||
<input
|
||||
v-model="limitLines"
|
||||
aria-labelledby="limit-lines-checkbox"
|
||||
type="checkbox"
|
||||
@change="updateForm('limitLines')"
|
||||
/>
|
||||
</div>
|
||||
</li>
|
||||
<li v-show="markers || alarmMarkers" class="grid-row">
|
||||
|
@ -135,7 +135,7 @@ export default {
|
||||
this.openmct.editor.off('isEditing', this.setEditState);
|
||||
if (this.composition) {
|
||||
this.composition.off('add', this.subscribeToStaleness);
|
||||
this.composition.off('remove', this.triggerUnsubscribeFromStaleness);
|
||||
this.composition.off('remove', this.removeSubscription);
|
||||
}
|
||||
|
||||
if (this.removeSelectable) {
|
||||
@ -161,6 +161,11 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
removeSubscription(identifier) {
|
||||
this.triggerUnsubscribeFromStaleness({
|
||||
identifier
|
||||
});
|
||||
},
|
||||
updateView() {
|
||||
//If this object is not persistable, then package it with it's parent
|
||||
const plotObject = this.getPlotObject();
|
||||
@ -172,7 +177,7 @@ export default {
|
||||
this.composition = this.openmct.composition.get(plotObject);
|
||||
|
||||
this.composition.on('add', this.subscribeToStaleness);
|
||||
this.composition.on('remove', this.triggerUnsubscribeFromStaleness);
|
||||
this.composition.on('remove', this.removeSubscription);
|
||||
this.composition.load();
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user