Remove large series models from reactive data in plots (#6961)

* remove series object from highlights

* remove series models from legend reactive data

* drawing all annotations at once is way faster

* fix multi annotations

* lots of reactive things depending on config

* make annotation lookup faster

* lint

* readd perf test

* address PR comments

* fix highlight typo

---------

Co-authored-by: Jesse Mazzella <ozyx@users.noreply.github.com>
Co-authored-by: Shefali Joshi <simplyrender@gmail.com>
This commit is contained in:
Scott Bell 2023-09-06 18:32:36 +02:00 committed by GitHub
parent 0be106f29e
commit 8e917b2679
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 265 additions and 180 deletions

View File

@ -32,7 +32,7 @@ const {
waitForPlotsToRender
} = require('../../appActions');
test.describe.fixme('Plot Tagging Performance', () => {
test.describe('Plot Tagging Performance', () => {
/**
* Given a canvas and a set of points, tags the points on the canvas.
* @param {import('@playwright/test').Page} page

View File

@ -78,8 +78,8 @@
:rectangles="rectangles"
:highlights="highlights"
:show-limit-line-labels="limitLineLabels"
:annotated-points="annotatedPoints"
:annotation-selections="annotationSelections"
:annotated-points-by-series="annotatedPointsBySeries"
:annotation-selections-by-series="annotationSelectionsBySeries"
:hidden-y-axis-ids="hiddenYAxisIds"
:annotation-viewing-and-editing-allowed="annotationViewingAndEditingAllowed"
@plotReinitializeCanvas="initCanvas"
@ -245,9 +245,9 @@ export default {
data() {
return {
altPressed: false,
annotatedPointsBySeries: {},
highlights: [],
annotatedPoints: [],
annotationSelections: [],
annotationSelectionsBySeries: {},
annotationsEverLoaded: false,
lockHighlightPoint: false,
yKeyOptions: [],
@ -256,8 +256,6 @@ export default {
plotHistory: [],
selectedXKeyOption: {},
xKeyOptions: [],
seriesModels: [],
legend: {},
pending: 0,
isRealTime: this.openmct.time.isRealTime(),
loaded: false,
@ -346,6 +344,8 @@ export default {
this.abortController = new AbortController();
},
mounted() {
this.seriesModels = [];
this.config = {};
this.yAxisIdVisibility = {};
this.offsetWidth = 0;
@ -357,7 +357,6 @@ export default {
this.setTimeContext = this.setTimeContext.bind(this);
this.config = this.getConfig();
this.legend = this.config.legend;
this.yAxes = [
{
id: this.config.yAxis.id,
@ -455,7 +454,7 @@ export default {
const clickedOption = event.target.closest('.js-autocomplete-options') !== null;
if (!clickedInsidePlot && !clickedInsideInspector && !clickedOption) {
this.rectangles = [];
this.annotationSelections = [];
this.annotationSelectionsBySeries = {};
this.selectPlot();
document.body.removeEventListener('click', this.cancelSelection);
}
@ -639,7 +638,7 @@ export default {
})
);
if (rawAnnotationsForPlot) {
this.annotatedPoints = this.findAnnotationPoints(rawAnnotationsForPlot);
this.annotatedPointsBySeries = this.findAnnotationPoints(rawAnnotationsForPlot);
}
this.annotationsEverLoaded = true;
},
@ -795,7 +794,7 @@ export default {
};
this.config.xAxis.set('range', newRange);
if (!isTick) {
this.annotatedPoints = [];
this.annotatedPointsBySeries = {};
this.clearPanZoomHistory();
this.synchronizeIfBoundsMatch();
this.loadMoreData(newRange, true);
@ -1157,7 +1156,7 @@ export default {
series.closest = series.nearestPoint(point);
return {
series: series,
seriesKeyString: series.keyString,
point: series.closest
};
});
@ -1245,7 +1244,7 @@ export default {
startMarquee(event, annotationEvent) {
this.rectangles = [];
this.annotationSelections = [];
this.annotationSelectionsBySeries = {};
this.canvas.classList.remove('plot-drag');
this.canvas.classList.add('plot-marquee');
@ -1273,7 +1272,10 @@ export default {
const nearbyAnnotations = this.gatherNearbyAnnotations();
if (this.annotationViewingAndEditingAllowed && this.annotationSelections.length) {
if (
this.annotationViewingAndEditingAllowed &&
Object.keys(this.annotationSelectionsBySeries).length
) {
//no annotations were found, but we are adding some now
return;
}
@ -1353,20 +1355,18 @@ export default {
document.body.addEventListener('click', this.cancelSelection);
},
selectNewPlotAnnotations(boundingBoxPerYAxis, pointsInBox, event) {
selectNewPlotAnnotations(boundingBoxPerYAxis, pointsInBoxBySeries, event) {
let targetDomainObjects = {};
let targetDetails = {};
let annotations = [];
pointsInBox.forEach((pointInBox) => {
if (pointInBox.length) {
const seriesID = pointInBox[0].series.keyString;
const boundingBoxWithId = boundingBoxPerYAxis.find(
(box) => box.id === pointInBox[0].series.get('yAxisId')
);
targetDetails[seriesID] = boundingBoxWithId?.boundingBox;
Object.keys(pointsInBoxBySeries).forEach((seriesKey) => {
const seriesModel = this.getSeries(seriesKey);
const boundingBoxWithId = boundingBoxPerYAxis.find(
(box) => box.id === seriesModel.get('yAxisId')
);
targetDetails[seriesKey] = boundingBoxWithId?.boundingBox;
targetDomainObjects[seriesID] = pointInBox[0].series.domainObject;
}
targetDomainObjects[seriesKey] = seriesModel.domainObject;
});
this.selectPlotAnnotations({
targetDetails,
@ -1375,7 +1375,7 @@ export default {
});
},
findAnnotationPoints(rawAnnotations) {
const annotationsByPoints = [];
const annotationsBySeries = {};
rawAnnotations.forEach((rawAnnotation) => {
if (rawAnnotation.targets) {
const targetValues = Object.values(rawAnnotation.targets);
@ -1390,6 +1390,9 @@ export default {
if (!series) {
return;
}
if (!annotationsBySeries[seriesId]) {
annotationsBySeries[seriesId] = [];
}
boundingBoxPerYAxis.push({
id: series.get('yAxisId'),
@ -1397,15 +1400,23 @@ export default {
});
});
const pointsInBox = this.getPointsInBox(boundingBoxPerYAxis, rawAnnotation);
if (pointsInBox && pointsInBox.length) {
annotationsByPoints.push(pointsInBox.flat());
const pointsInBoxBySeries = this.getPointsInBoxBySeries(
boundingBoxPerYAxis,
rawAnnotation
);
if (pointsInBoxBySeries && Object.values(pointsInBoxBySeries).length) {
Object.keys(pointsInBoxBySeries).forEach((seriesKeyString) => {
const pointsInBox = pointsInBoxBySeries[seriesKeyString];
if (pointsInBox && pointsInBox.length) {
annotationsBySeries[seriesKeyString].push(...pointsInBox);
}
});
}
}
}
});
return annotationsByPoints.flat();
return annotationsBySeries;
},
searchWithFlatbush(seriesData, seriesModel, boundingBox) {
const flatbush = new Flatbush(seriesData.length);
@ -1425,9 +1436,15 @@ export default {
return rangeResults;
},
getPointsInBox(boundingBoxPerYAxis, rawAnnotation) {
getSeries(keyStringToFind) {
const foundSeries = this.seriesModels.find((series) => {
return series.keyString === keyStringToFind;
});
return foundSeries;
},
getPointsInBoxBySeries(boundingBoxPerYAxis, rawAnnotation) {
// load series models in KD-Trees
const seriesKDTrees = [];
const searchResultsBySeries = {};
this.seriesModels.forEach((seriesModel) => {
const boundingBoxWithId = boundingBoxPerYAxis.find(
(box) => box.id === seriesModel.get('yAxisId')
@ -1440,16 +1457,15 @@ export default {
const seriesData = seriesModel.getSeriesData();
if (seriesData && seriesData.length) {
const searchResults = [];
searchResultsBySeries[seriesModel.keyString] = [];
const rangeResults = this.searchWithFlatbush(seriesData, seriesModel, boundingBox);
rangeResults.forEach((id) => {
const seriesDatum = seriesData[id];
if (seriesDatum) {
const result = {
series: seriesModel,
point: seriesDatum
};
searchResults.push(result);
searchResultsBySeries[seriesModel.keyString].push(result);
}
if (rawAnnotation) {
@ -1463,13 +1479,10 @@ export default {
seriesDatum.annotationsById[annotationKeyString] = rawAnnotation;
}
});
if (searchResults.length) {
seriesKDTrees.push(searchResults);
}
}
});
return seriesKDTrees;
return searchResultsBySeries;
},
endAnnotationMarquee(event) {
const boundingBoxPerYAxis = [];
@ -1490,13 +1503,13 @@ export default {
});
});
const pointsInBox = this.getPointsInBox(boundingBoxPerYAxis);
if (!pointsInBox) {
const pointsInBoxBySeries = this.getPointsInBoxBySeries(boundingBoxPerYAxis);
if (!pointsInBoxBySeries || Object.values(pointsInBoxBySeries).length === 0) {
return;
}
this.annotationSelections = pointsInBox.flat();
this.selectNewPlotAnnotations(boundingBoxPerYAxis, pointsInBox, event);
this.annotationSelectionsBySeries = pointsInBoxBySeries;
this.selectNewPlotAnnotations(boundingBoxPerYAxis, this.annotationSelectionsBySeries, event);
},
endZoomMarquee() {
const startPixels = this.marquee.startPixels;

View File

@ -101,16 +101,16 @@ export default {
return [];
}
},
annotatedPoints: {
type: Array,
annotatedPointsBySeries: {
type: Object,
default() {
return [];
return {};
}
},
annotationSelections: {
type: Array,
annotationSelectionsBySeries: {
type: Object,
default() {
return [];
return {};
}
},
showLimitLineLabels: {
@ -143,17 +143,15 @@ export default {
},
deep: true
},
annotatedPoints: {
annotatedPointsBySeries: {
handler() {
this.scheduleDraw();
},
deep: true
}
},
annotationSelections: {
annotationSelectionsBySeries: {
handler() {
this.scheduleDraw();
},
deep: true
}
},
rectangles: {
handler() {
@ -177,6 +175,7 @@ export default {
},
mounted() {
eventHelpers.extend(this);
this.seriesModels = [];
this.config = this.getConfig();
this.isDestroyed = false;
this.lines = [];
@ -256,7 +255,8 @@ export default {
this.changeAlarmMarkers(newXKey, oldXKey, series);
this.changeLimitLines(newXKey, oldXKey, series);
},
onSeriesAdd(series) {
onSeriesAdd(series, index) {
this.seriesModels[index] = series;
this.listenTo(series, `change:${HANDLED_ATTRIBUTES.xKey}`, this.reDraw, this);
this.listenTo(
series,
@ -280,10 +280,15 @@ export default {
this.makeChartElement(series);
this.makeLimitLines(series);
},
onSeriesRemove(series) {
this.stopListening(series);
this.removeChartElement(series);
onSeriesRemove(seriesToRemove) {
this.stopListening(seriesToRemove);
this.removeChartElement(seriesToRemove);
this.scheduleDraw();
const seriesIndexToRemove = this.seriesModels.findIndex(
(series) => series.keyString === seriesToRemove.keyString
);
this.seriesModels.splice(seriesIndexToRemove, 1);
},
onAddPoint(point, insertIndex, series) {
const mainYAxisId = this.config.yAxis.get('id');
@ -642,8 +647,8 @@ export default {
this.drawHighlights(id);
// only draw these in fixed time mode or plot is paused
if (this.annotationViewingAndEditingAllowed) {
this.drawAnnotatedPoints(id);
this.drawAnnotationSelections(id);
this.prepareToDrawAnnotatedPoints(id);
this.prepareToDrawAnnotationSelections(id);
}
});
},
@ -698,6 +703,7 @@ 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() {
Array.from(this.$refs.limitArea.children).forEach((el) => el.remove());
@ -827,82 +833,110 @@ export default {
);
}
},
drawAnnotatedPoints(yAxisId) {
// we should do this by series, and then plot all the points at once instead
// of doing it one by one
if (this.annotatedPoints && this.annotatedPoints.length) {
const uniquePointsToDraw = [];
prepareToDrawAnnotatedPoints(yAxisId) {
if (this.annotatedPointsBySeries && Object.values(this.annotatedPointsBySeries).length) {
const uniquePointsToDraw = new Set();
const annotatedPoints = this.annotatedPoints.filter(
this.matchByYAxisId.bind(this, yAxisId)
);
annotatedPoints.forEach((annotatedPoint) => {
Object.keys(this.annotatedPointsBySeries).forEach((seriesKeyString) => {
const seriesModel = this.getSeries(seriesKeyString);
const matchesYAxis = this.matchByYAxisId(yAxisId, { series: seriesModel });
if (!matchesYAxis) {
return;
}
// annotation points are all within range (checked in MctPlot with FlatBush), so we don't need to check
const canvasXValue = this.offset[yAxisId].xVal(
annotatedPoint.point,
annotatedPoint.series
const annotatedPointBuffer = new Float32Array(
this.annotatedPointsBySeries[seriesKeyString].length * 2
);
const canvasYValue = this.offset[yAxisId].yVal(
annotatedPoint.point,
annotatedPoint.series
Object.values(this.annotatedPointsBySeries[seriesKeyString]).forEach(
(annotatedPoint, index) => {
const canvasXValue = this.offset[yAxisId].xVal(annotatedPoint.point, seriesModel);
const canvasYValue = this.offset[yAxisId].yVal(annotatedPoint.point, seriesModel);
const drawnPointKey = `${canvasXValue}|${canvasYValue}`;
if (!uniquePointsToDraw.has(drawnPointKey)) {
annotatedPointBuffer[index * 2] = canvasXValue;
annotatedPointBuffer[index * 2 + 1] = canvasYValue;
uniquePointsToDraw.add(drawnPointKey);
}
}
);
const pointToDraw = new Float32Array([canvasXValue, canvasYValue]);
const drawnPoint = uniquePointsToDraw.some((rawPoint) => {
return rawPoint[0] === pointToDraw[0] && rawPoint[1] === pointToDraw[1];
});
if (!drawnPoint) {
uniquePointsToDraw.push(pointToDraw);
this.drawAnnotatedPoint(annotatedPoint, pointToDraw);
this.drawAnnotatedPoints(seriesModel, annotatedPointBuffer);
});
}
},
drawAnnotatedPoints(seriesModel, annotatedPointBuffer) {
if (annotatedPointBuffer && seriesModel) {
const color = seriesModel.get('color').asRGBAArray();
// set transparency
color[3] = 0.15;
const pointCount = annotatedPointBuffer.length / 2;
const shape = seriesModel.get('markerShape');
this.drawAPI.drawPoints(annotatedPointBuffer, color, pointCount, ANNOTATION_SIZE, shape);
}
},
prepareToDrawAnnotationSelections(yAxisId) {
if (
this.annotationSelectionsBySeries &&
Object.keys(this.annotationSelectionsBySeries).length
) {
Object.keys(this.annotationSelectionsBySeries).forEach((seriesKeyString) => {
const seriesModel = this.getSeries(seriesKeyString);
const matchesYAxis = this.matchByYAxisId(yAxisId, { series: seriesModel });
if (matchesYAxis) {
const annotationSelectionBuffer = new Float32Array(
this.annotationSelectionsBySeries[seriesKeyString].length * 2
);
Object.values(this.annotationSelectionsBySeries[seriesKeyString]).forEach(
(annotatedSelectedPoint, index) => {
const canvasXValue = this.offset[yAxisId].xVal(
annotatedSelectedPoint.point,
seriesModel
);
const canvasYValue = this.offset[yAxisId].yVal(
annotatedSelectedPoint.point,
seriesModel
);
annotationSelectionBuffer[index * 2] = canvasXValue;
annotationSelectionBuffer[index * 2 + 1] = canvasYValue;
}
);
this.drawAnnotationSelections(seriesModel, annotationSelectionBuffer);
}
});
}
},
drawAnnotatedPoint(annotatedPoint, pointToDraw) {
if (annotatedPoint.point && annotatedPoint.series) {
const color = annotatedPoint.series.get('color').asRGBAArray();
// set transparency
color[3] = 0.15;
const pointCount = 1;
const shape = annotatedPoint.series.get('markerShape');
this.drawAPI.drawPoints(pointToDraw, color, pointCount, ANNOTATION_SIZE, shape);
}
},
drawAnnotationSelections(yAxisId) {
if (this.annotationSelections && this.annotationSelections.length) {
const annotationSelections = this.annotationSelections.filter(
this.matchByYAxisId.bind(this, yAxisId)
);
annotationSelections.forEach(this.drawAnnotationSelection.bind(this, yAxisId), this);
}
},
drawAnnotationSelection(yAxisId, annotationSelection) {
const points = new Float32Array([
this.offset[yAxisId].xVal(annotationSelection.point, annotationSelection.series),
this.offset[yAxisId].yVal(annotationSelection.point, annotationSelection.series)
]);
drawAnnotationSelections(seriesModel, annotationSelectionBuffer) {
const color = [255, 255, 255, 1]; // white
const pointCount = 1;
const shape = annotationSelection.series.get('markerShape');
const pointCount = annotationSelectionBuffer.length / 2;
const shape = seriesModel.get('markerShape');
this.drawAPI.drawPoints(points, color, pointCount, ANNOTATION_SIZE, shape);
this.drawAPI.drawPoints(annotationSelectionBuffer, color, pointCount, ANNOTATION_SIZE, shape);
},
drawHighlights(yAxisId) {
if (this.highlights && this.highlights.length) {
const highlights = this.highlights.filter(this.matchByYAxisId.bind(this, yAxisId));
const highlights = this.highlights.filter((highlight) => {
const series = this.getSeries(highlight.seriesKeyString);
return this.matchByYAxisId.bind(yAxisId, { series });
});
highlights.forEach(this.drawHighlight.bind(this, yAxisId), this);
}
},
getSeries(keyStringToFind) {
const foundSeries = this.seriesModels.find((series) => {
return series.keyString === keyStringToFind;
});
return foundSeries;
},
drawHighlight(yAxisId, highlight) {
const series = this.getSeries(highlight.seriesKeyString);
const points = new Float32Array([
this.offset[yAxisId].xVal(highlight.point, highlight.series),
this.offset[yAxisId].yVal(highlight.point, highlight.series)
this.offset[yAxisId].xVal(highlight.point, series),
this.offset[yAxisId].yVal(highlight.point, series)
]);
const color = highlight.series.get('color').asRGBAArray();
const color = series.get('color').asRGBAArray();
const pointCount = 1;
const shape = highlight.series.get('markerShape');
const shape = series.get('markerShape');
this.drawAPI.drawPoints(points, color, pointCount, HIGHLIGHT_SIZE, shape);
},

View File

@ -45,7 +45,7 @@
:key="`${seriesObject.keyString}-${seriesIndex}-collapsed`"
:highlights="highlights"
:value-to-show-when-collapsed="valueToShowWhenCollapsed"
:series-object="seriesObject"
:series-key-string="seriesObject.keyString"
@legendHoverChanged="legendHoverChanged"
/>
</div>
@ -72,7 +72,7 @@
<plot-legend-item-expanded
v-for="(seriesObject, seriesIndex) in seriesModels"
:key="`${seriesObject.keyString}-${seriesIndex}-expanded`"
:series-object="seriesObject"
:series-key-string="seriesObject.keyString"
:highlights="highlights"
@legendHoverChanged="legendHoverChanged"
/>

View File

@ -71,12 +71,9 @@ export default {
mixins: [stalenessMixin, tooltipHelpers],
inject: ['openmct', 'domainObject'],
props: {
seriesObject: {
type: Object,
required: true,
default() {
return {};
}
seriesKeyString: {
type: String,
required: true
},
highlights: {
type: Array,
@ -112,7 +109,7 @@ export default {
highlights: {
handler(newHighlights) {
const highlightedObject = newHighlights.find(
(highlight) => highlight.series.keyString === this.seriesObject.keyString
(highlight) => highlight.seriesKeyString === this.seriesKeyString
);
if (newHighlights.length === 0 || highlightedObject) {
this.initialize(highlightedObject);
@ -122,28 +119,14 @@ export default {
}
},
mounted() {
this.seriesModels = [];
eventHelpers.extend(this);
this.config = this.getConfig();
this.listenTo(this.config.series, 'add', this.onSeriesAdd, this);
this.listenTo(this.config.series, 'remove', this.onSeriesRemove, this);
this.config.series.forEach(this.onSeriesAdd, this);
this.legend = this.config.legend;
this.loaded = true;
this.listenTo(
this.seriesObject,
'change:color',
(newColor) => {
this.updateColor(newColor);
},
this
);
this.listenTo(
this.seriesObject,
'change:name',
() => {
this.updateName();
},
this
);
this.subscribeToStaleness(this.seriesObject.domainObject);
this.initialize();
},
beforeUnmount() {
this.stopListening();
@ -154,8 +137,44 @@ export default {
return configStore.get(configId);
},
onSeriesAdd(series, index) {
this.seriesModels[index] = series;
if (series.keyString === this.seriesKeyString) {
this.listenTo(
series,
'change:color',
(newColor) => {
this.updateColor(newColor);
},
this
);
this.listenTo(
series,
'change:name',
() => {
this.updateName();
},
this
);
this.subscribeToStaleness(series.domainObject);
this.initialize();
}
},
onSeriesRemove(seriesToRemove) {
const seriesIndexToRemove = this.seriesModels.findIndex(
(series) => series.keyString === seriesToRemove.keyString
);
this.seriesModels.splice(seriesIndexToRemove, 1);
},
getSeries(keyStringToFind) {
const foundSeries = this.seriesModels.find((series) => {
return series.keyString === keyStringToFind;
});
return foundSeries;
},
initialize(highlightedObject) {
const seriesObject = highlightedObject?.series || this.seriesObject;
const seriesKeyStringToUse = highlightedObject?.seriesKeyString || this.seriesKeyString;
const seriesObject = this.getSeries(seriesKeyStringToUse);
this.isMissing = seriesObject.domainObject.status === 'missing';
this.colorAsHexString = seriesObject.get('color').asHexString();
@ -187,7 +206,8 @@ export default {
this.colorAsHexString = newColor.asHexString();
},
updateName() {
this.nameWithUnit = this.seriesObject.nameWithUnit();
const seriesObject = this.getSeries(this.seriesKeyString);
this.nameWithUnit = seriesObject.nameWithUnit();
},
toggleHover(hover) {
this.hover = hover;
@ -195,15 +215,16 @@ export default {
'legendHoverChanged',
this.hover
? {
seriesKey: this.seriesObject.keyString
seriesKey: this.seriesKeyString
}
: undefined
);
},
async showToolTip() {
const seriesObject = this.getSeries(this.seriesKeyString);
const { BELOW } = this.openmct.tooltips.TOOLTIP_LOCATIONS;
this.buildToolTip(
await this.getTelemetryPathString(this.seriesObject.domainObject.identifier),
await this.getTelemetryPathString(seriesObject.domainObject.identifier),
BELOW,
'series'
);

View File

@ -86,12 +86,9 @@ export default {
mixins: [stalenessMixin, tooltipHelpers],
inject: ['openmct', 'domainObject'],
props: {
seriesObject: {
type: Object,
required: true,
default() {
return {};
}
seriesKeyString: {
type: String,
required: true
},
highlights: {
type: Array,
@ -135,7 +132,7 @@ export default {
highlights: {
handler(newHighlights) {
const highlightedObject = newHighlights.find(
(highlight) => highlight.series.keyString === this.seriesObject.keyString
(highlight) => highlight.seriesKeyString === this.seriesKeyString
);
if (newHighlights.length === 0 || highlightedObject) {
this.initialize(highlightedObject);
@ -145,40 +142,62 @@ export default {
}
},
mounted() {
this.seriesModels = [];
eventHelpers.extend(this);
this.config = this.getConfig();
this.listenTo(this.config.series, 'add', this.onSeriesAdd, this);
this.listenTo(this.config.series, 'remove', this.onSeriesRemove, this);
this.config.series.forEach(this.onSeriesAdd, this);
this.legend = this.config.legend;
this.loaded = true;
this.listenTo(
this.seriesObject,
'change:color',
(newColor) => {
this.updateColor(newColor);
},
this
);
this.listenTo(
this.seriesObject,
'change:name',
() => {
this.updateName();
},
this
);
this.subscribeToStaleness(this.seriesObject.domainObject);
this.initialize();
},
beforeUnmount() {
this.stopListening();
},
methods: {
onSeriesAdd(series, index) {
this.seriesModels[index] = series;
if (series.keyString === this.seriesKeyString) {
this.listenTo(
series,
'change:color',
(newColor) => {
this.updateColor(newColor);
},
this
);
this.listenTo(
series,
'change:name',
() => {
this.updateName();
},
this
);
this.subscribeToStaleness(series.domainObject);
this.initialize();
}
},
onSeriesRemove(seriesToRemove) {
const seriesIndexToRemove = this.seriesModels.findIndex(
(series) => series.keyString === seriesToRemove.keyString
);
this.seriesModels.splice(seriesIndexToRemove, 1);
},
getSeries(keyStringToFind) {
const foundSeries = this.seriesModels.find((series) => {
return series.keyString === keyStringToFind;
});
return foundSeries;
},
getConfig() {
const configId = this.openmct.objects.makeKeyString(this.domainObject.identifier);
return configStore.get(configId);
},
initialize(highlightedObject) {
const seriesObject = highlightedObject?.series || this.seriesObject;
const seriesKeyStringToUse = highlightedObject?.seriesKeyString || this.seriesKeyString;
const seriesObject = this.getSeries(seriesKeyStringToUse);
this.isMissing = seriesObject.domainObject.status === 'missing';
this.colorAsHexString = seriesObject.get('color').asHexString();
@ -209,22 +228,20 @@ export default {
updateColor(newColor) {
this.colorAsHexString = newColor.asHexString();
},
updateName(newName) {
this.nameWithUnit = this.seriesObject.nameWithUnit();
updateName() {
const seriesObject = this.getSeries(this.seriesKeyString);
this.nameWithUnit = seriesObject.nameWithUnit();
},
toggleHover(hover) {
this.hover = hover;
this.$emit('legendHoverChanged', {
seriesKey: this.hover ? this.seriesObject.keyString : ''
seriesKey: this.hover ? this.seriesKeyString : ''
});
},
async showToolTip() {
const { BELOW } = this.openmct.tooltips.TOOLTIP_LOCATIONS;
this.buildToolTip(
await this.getTelemetryPathString(this.seriesObject.domainObject.identifier),
BELOW,
'seriesName'
);
const seriesIdentifier = this.openmct.objects.parseKeyString(this.seriesKeyString);
this.buildToolTip(await this.getTelemetryPathString(seriesIdentifier), BELOW, 'seriesName');
}
}
};