diff --git a/example/generator/SinewaveStalenessProvider.js b/example/generator/SinewaveStalenessProvider.js index 0fafcc14c2..c517747a1c 100644 --- a/example/generator/SinewaveStalenessProvider.js +++ b/example/generator/SinewaveStalenessProvider.js @@ -43,10 +43,7 @@ export default class SinewaveLimitProvider extends EventEmitter { isStale(domainObject, options) { if (!this.#providingStaleness(domainObject)) { - return Promise.resolve({ - isStale: false, - utc: 0 - }); + return; } const id = this.#getObjectKeyString(domainObject); @@ -55,7 +52,10 @@ export default class SinewaveLimitProvider extends EventEmitter { this.#createObserver(id); } - return Promise.resolve(this.#observingStaleness[id].isStale); + return Promise.resolve({ + isStale: this.#observingStaleness[id].isStale, + utc: Date.now() + }); } subscribeToStaleness(domainObject, callback) { diff --git a/src/plugins/LADTable/components/LadTableSet.vue b/src/plugins/LADTable/components/LadTableSet.vue index 3a3b000553..3520a4d379 100644 --- a/src/plugins/LADTable/components/LadTableSet.vue +++ b/src/plugins/LADTable/components/LadTableSet.vue @@ -48,11 +48,11 @@ @@ -160,10 +160,18 @@ export default { removeCallback }); }, + combineKeys(ladKey, telemetryObjectKey) { + return `${ladKey}-${telemetryObjectKey}`; + }, removeLadTable(identifier) { let index = this.ladTableObjects.findIndex(ladTable => this.openmct.objects.makeKeyString(identifier) === ladTable.key); let ladTable = this.ladTableObjects[index]; + this.ladTelemetryObjects[ladTable.key].forEach(telemetryObject => { + let combinedKey = this.combineKeys(ladTable.key, telemetryObject.key); + this.unwatchStaleness(combinedKey); + }); + this.$delete(this.ladTelemetryObjects, ladTable.key); this.ladTableObjects.splice(index, 1); }, @@ -178,60 +186,58 @@ export default { let telemetryObject = {}; telemetryObject.key = this.openmct.objects.makeKeyString(domainObject.identifier); telemetryObject.domainObject = domainObject; + const combinedKey = this.combineKeys(ladTable.key, telemetryObject.key); - let telemetryObjects = this.ladTelemetryObjects[ladTable.key]; + const telemetryObjects = this.ladTelemetryObjects[ladTable.key]; telemetryObjects.push(telemetryObject); this.$set(this.ladTelemetryObjects, ladTable.key, telemetryObjects); - // if tracking already, possibly in another table, return - if (this.stalenessSubscription[telemetryObject.key]) { - return; - } else { - this.stalenessSubscription[telemetryObject.key] = {}; - this.stalenessSubscription[telemetryObject.key].stalenessUtils = new StalenessUtils(this.openmct, domainObject); - } + this.stalenessSubscription[combinedKey] = {}; + this.stalenessSubscription[combinedKey].stalenessUtils = new StalenessUtils(this.openmct, domainObject); this.openmct.telemetry.isStale(domainObject).then((stalenessResponse) => { if (stalenessResponse !== undefined) { - this.handleStaleness(telemetryObject.key, stalenessResponse); + this.handleStaleness(combinedKey, stalenessResponse); } }); const stalenessSubscription = this.openmct.telemetry.subscribeToStaleness(domainObject, (stalenessResponse) => { - this.handleStaleness(telemetryObject.key, stalenessResponse); + this.handleStaleness(combinedKey, stalenessResponse); }); - this.stalenessSubscription[telemetryObject.key].unsubscribe = stalenessSubscription; + this.stalenessSubscription[combinedKey].unsubscribe = stalenessSubscription; }; }, removeTelemetryObject(ladTable) { return (identifier) => { - const SKIP_CHECK = true; const keystring = this.openmct.objects.makeKeyString(identifier); - let telemetryObjects = this.ladTelemetryObjects[ladTable.key]; + const telemetryObjects = this.ladTelemetryObjects[ladTable.key]; + const combinedKey = this.combineKeys(ladTable.key, keystring); let index = telemetryObjects.findIndex(telemetryObject => keystring === telemetryObject.key); + this.unwatchStaleness(combinedKey); + telemetryObjects.splice(index, 1); - this.$set(this.ladTelemetryObjects, ladTable.key, telemetryObjects); - - this.stalenessSubscription[keystring].unsubscribe(); - this.stalenessSubscription[keystring].stalenessUtils.destroy(); - this.handleStaleness(keystring, { isStale: false }, SKIP_CHECK); - delete this.stalenessSubscription[keystring]; }; }, - handleStaleness(id, stalenessResponse, skipCheck = false) { - if (skipCheck || this.stalenessSubscription[id].stalenessUtils.shouldUpdateStaleness(stalenessResponse)) { - const index = this.staleObjects.indexOf(id); - if (stalenessResponse.isStale) { - if (index === -1) { - this.staleObjects.push(id); - } - } else { - if (index !== -1) { - this.staleObjects.splice(index, 1); - } + unwatchStaleness(combinedKey) { + const SKIP_CHECK = true; + + this.stalenessSubscription[combinedKey].unsubscribe(); + this.stalenessSubscription[combinedKey].stalenessUtils.destroy(); + this.handleStaleness(combinedKey, { isStale: false }, SKIP_CHECK); + + delete this.stalenessSubscription[combinedKey]; + }, + handleStaleness(combinedKey, stalenessResponse, skipCheck = false) { + if (skipCheck || this.stalenessSubscription[combinedKey].stalenessUtils.shouldUpdateStaleness(stalenessResponse)) { + const index = this.staleObjects.indexOf(combinedKey); + const foundStaleObject = index > -1; + if (stalenessResponse.isStale && !foundStaleObject) { + this.staleObjects.push(combinedKey); + } else if (!stalenessResponse.isStale && foundStaleObject) { + this.staleObjects.splice(index, 1); } } }, diff --git a/src/plugins/condition/components/ConditionCollection.vue b/src/plugins/condition/components/ConditionCollection.vue index f5336952c7..fb62f9ab19 100644 --- a/src/plugins/condition/components/ConditionCollection.vue +++ b/src/plugins/condition/components/ConditionCollection.vue @@ -233,11 +233,11 @@ export default { this.openmct.telemetry.isStale(domainObject).then((stalenessResponse) => { if (stalenessResponse !== undefined) { - this.hanldeStaleness(keyString, stalenessResponse); + this.handleStaleness(keyString, stalenessResponse); } }); const stalenessSubscription = this.openmct.telemetry.subscribeToStaleness(domainObject, (stalenessResponse) => { - this.hanldeStaleness(keyString, stalenessResponse); + this.handleStaleness(keyString, stalenessResponse); }); this.stalenessSubscription[keyString].unsubscribe = stalenessSubscription; @@ -264,7 +264,7 @@ export default { delete this.stalenessSubscription[keyString]; } }, - hanldeStaleness(keyString, stalenessResponse) { + handleStaleness(keyString, stalenessResponse) { if (this.stalenessSubscription[keyString].stalenessUtils.shouldUpdateStaleness(stalenessResponse)) { this.emitStaleness({ keyString, diff --git a/src/plugins/plot/stackedPlot/StackedPlotItem.vue b/src/plugins/plot/stackedPlot/StackedPlotItem.vue index 248c66f56e..29ad2cc420 100644 --- a/src/plugins/plot/stackedPlot/StackedPlotItem.vue +++ b/src/plugins/plot/stackedPlot/StackedPlotItem.vue @@ -30,6 +30,7 @@ import MctPlot from '../MctPlot.vue'; import Vue from "vue"; import conditionalStylesMixin from "./mixins/objectStyles-mixin"; import stalenessMixin from '@/ui/mixins/staleness-mixin'; +import StalenessUtils from '@/utils/staleness'; import configStore from "@/plugins/plot/configuration/ConfigStore"; import PlotConfigurationModel from "@/plugins/plot/configuration/PlotConfigurationModel"; import ProgressBar from "../../../ui/components/ProgressBar.vue"; @@ -85,6 +86,11 @@ export default { } } }, + data() { + return { + staleObjects: [] + }; + }, watch: { gridLines(newGridLines) { this.updateComponentProp('gridLines', newGridLines); @@ -100,9 +106,14 @@ export default { this.updateComponentProp('limitLineLabels', data); }, deep: true + }, + staleObjects() { + this.isStale = this.staleObjects.length > 0; + this.updateComponentProp('isStale', this.isStale); } }, mounted() { + this.stalenessSubscription = {}; this.updateView(); this.isEditing = this.openmct.editor.isEditing(); this.openmct.editor.on('isEditing', this.setEditState); @@ -117,6 +128,8 @@ export default { if (this.component) { this.component.$destroy(); } + + this.destroyStalenessListeners(); }, methods: { setEditState(isEditing) { @@ -139,11 +152,11 @@ export default { updateView() { this.isStale = false; - this.triggerUnsubscribeFromStaleness(); + this.destroyStalenessListeners(); if (this.component) { this.component.$destroy(); - this.component = undefined; + this.component = null; this.$el.innerHTML = ''; } @@ -166,9 +179,18 @@ export default { let viewContainer = document.createElement('div'); this.$el.append(viewContainer); - this.subscribeToStaleness(object, (isStale) => { - this.updateComponentProp('isStale', isStale); - }); + if (this.openmct.telemetry.isTelemetryObject(object)) { + this.subscribeToStaleness(object, (isStale) => { + this.updateComponentProp('isStale', isStale); + }); + } else { + // possibly overlay or other composition based plot + this.composition = this.openmct.composition.get(object); + + this.composition.on('add', this.watchStaleness); + this.composition.on('remove', this.unwatchStaleness); + this.composition.load(); + } this.component = new Vue({ el: viewContainer, @@ -230,6 +252,43 @@ export default { this.setSelection(); } }, + watchStaleness(domainObject) { + const keyString = this.openmct.objects.makeKeyString(domainObject.identifier); + this.stalenessSubscription[keyString] = {}; + this.stalenessSubscription[keyString].stalenessUtils = new StalenessUtils(this.openmct, domainObject); + + this.openmct.telemetry.isStale(domainObject).then((stalenessResponse) => { + if (stalenessResponse !== undefined) { + this.handleStaleness(keyString, stalenessResponse); + } + }); + const stalenessSubscription = this.openmct.telemetry.subscribeToStaleness(domainObject, (stalenessResponse) => { + this.handleStaleness(keyString, stalenessResponse); + }); + + this.stalenessSubscription[keyString].unsubscribe = stalenessSubscription; + }, + unwatchStaleness(domainObject) { + const SKIP_CHECK = true; + const keyString = this.openmct.objects.makeKeyString(domainObject.identifier); + + this.stalenessSubscription[keyString].unsubscribe(); + this.stalenessSubscription[keyString].stalenessUtils.destroy(); + this.handleStaleness(keyString, { isStale: false }, SKIP_CHECK); + + delete this.stalenessSubscription[keyString]; + }, + handleStaleness(keyString, stalenessResponse, skipCheck = false) { + if (skipCheck || this.stalenessSubscription[keyString].stalenessUtils.shouldUpdateStaleness(stalenessResponse)) { + const index = this.staleObjects.indexOf(keyString); + const foundStaleObject = index > -1; + if (stalenessResponse.isStale && !foundStaleObject) { + this.staleObjects.push(keyString); + } else if (!stalenessResponse.isStale && foundStaleObject) { + this.staleObjects.splice(index, 1); + } + } + }, onLockHighlightPointUpdated() { this.$emit('lockHighlightPoint', ...arguments); }, @@ -328,6 +387,20 @@ export default { return this.childObject; } + }, + destroyStalenessListeners() { + this.triggerUnsubscribeFromStaleness(); + + if (this.composition) { + this.composition.off('add', this.watchStaleness); + this.composition.off('remove', this.unwatchStaleness); + this.composition = null; + } + + Object.values(this.stalenessSubscription).forEach(stalenessSubscription => { + stalenessSubscription.unsubscribe(); + stalenessSubscription.stalenessUtils.destroy(); + }); } } };