diff --git a/src/plugins/clearData/clearDataAction.js b/src/plugins/clearData/ClearDataAction.js similarity index 53% rename from src/plugins/clearData/clearDataAction.js rename to src/plugins/clearData/ClearDataAction.js index 7eb61a494c..ce488e0dd8 100644 --- a/src/plugins/clearData/clearDataAction.js +++ b/src/plugins/clearData/ClearDataAction.js @@ -20,6 +20,18 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ +function inSelectionPath(openmct, domainObject) { + const domainObjectIdentifier = domainObject.identifier; + + return openmct.selection.get().some(selectionPath => { + return selectionPath.some(objectInPath => { + const objectInPathIdentifier = objectInPath.context.item.identifier; + + return openmct.objects.areIdsEqual(objectInPathIdentifier, domainObjectIdentifier); + }); + }); +} + export default class ClearDataAction { constructor(openmct, appliesToObjects) { this.name = 'Clear Data for Object'; @@ -31,11 +43,36 @@ export default class ClearDataAction { this._appliesToObjects = appliesToObjects; } invoke(objectPath) { - this._openmct.objectViews.emit('clearData', objectPath[0]); + let domainObject = null; + if (objectPath) { + domainObject = objectPath[0]; + } + + this._openmct.objectViews.emit('clearData', domainObject); } appliesTo(objectPath) { - let contextualDomainObject = objectPath[0]; + if (!objectPath) { + return false; + } - return this._appliesToObjects.filter(type => contextualDomainObject.type === type).length; + const contextualDomainObject = objectPath[0]; + // first check to see if this action applies to this sort of object at all + const appliesToThisObject = this._appliesToObjects.some(type => { + return contextualDomainObject.type === type; + }); + if (!appliesToThisObject) { + // we've selected something not applicable + return false; + } + + const objectInSelectionPath = inSelectionPath(this._openmct, contextualDomainObject); + if (objectInSelectionPath) { + return true; + } else { + // if this it doesn't match up, check to see if we're in a composition (i.e., layout) + const routerPath = this._openmct.router.path[0]; + + return routerPath.type === 'layout'; + } } } diff --git a/src/plugins/clearData/plugin.js b/src/plugins/clearData/plugin.js index 8febcd47f5..34b31c7018 100644 --- a/src/plugins/clearData/plugin.js +++ b/src/plugins/clearData/plugin.js @@ -22,7 +22,7 @@ define([ './components/globalClearIndicator.vue', - './clearDataAction', + './ClearDataAction', 'vue' ], function ( GlobaClearIndicator, diff --git a/src/plugins/clearData/test/ClearDataActionSpec.js b/src/plugins/clearData/test/ClearDataActionSpec.js new file mode 100644 index 0000000000..ce68f69507 --- /dev/null +++ b/src/plugins/clearData/test/ClearDataActionSpec.js @@ -0,0 +1,140 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2021, 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 ClearDataActionPlugin from '../plugin.js'; +import ClearDataAction from '../ClearDataAction.js'; + +describe('When the Clear Data Plugin is installed,', () => { + const mockObjectViews = jasmine.createSpyObj('objectViews', ['emit']); + const mockIndicatorProvider = jasmine.createSpyObj('indicators', ['add']); + const mockActionsProvider = jasmine.createSpyObj('actions', ['register']); + const goodMockSelectionPath = [[{ + context: { + item: { + identifier: { + key: 'apple', + namespace: '' + } + } + } + }]]; + + const openmct = { + objectViews: mockObjectViews, + indicators: mockIndicatorProvider, + actions: mockActionsProvider, + install: function (plugin) { + plugin(this); + }, + selection: { + get: function () { + return goodMockSelectionPath; + } + }, + objects: { + areIdsEqual: function (obj1, obj2) { + return true; + } + } + }; + + const mockObjectPath = [ + { + name: 'mockObject1', + type: 'apple' + }, + { + name: 'mockObject2', + type: 'banana' + } + ]; + + it('Global Clear Indicator is installed', () => { + openmct.install(ClearDataActionPlugin([])); + + expect(mockIndicatorProvider.add).toHaveBeenCalled(); + }); + + it('Clear Data context menu action is installed', () => { + openmct.install(ClearDataActionPlugin([])); + + expect(mockActionsProvider.register).toHaveBeenCalled(); + }); + + it('clear data action emits a clearData event when invoked', () => { + const action = new ClearDataAction(openmct); + + action.invoke(mockObjectPath); + + expect(mockObjectViews.emit).toHaveBeenCalledWith('clearData', mockObjectPath[0]); + }); + + it('clears data on applicable objects', () => { + let action = new ClearDataAction(openmct, ['apple']); + + const actionApplies = action.appliesTo(mockObjectPath); + + expect(actionApplies).toBe(true); + }); + + it('does not clear data on inapplicable objects', () => { + let action = new ClearDataAction(openmct, ['pineapple']); + + const actionApplies = action.appliesTo(mockObjectPath); + + expect(actionApplies).toBe(false); + }); + + it('does not clear data if not in the selection path and not a layout', () => { + openmct.objects = { + areIdsEqual: function (obj1, obj2) { + return false; + } + }; + openmct.router = { + path: [{type: 'not-a-layout'}] + }; + + let action = new ClearDataAction(openmct, ['apple']); + + const actionApplies = action.appliesTo(mockObjectPath); + + expect(actionApplies).toBe(false); + }); + + it('does clear data if not in the selection path and is a layout', () => { + openmct.objects = { + areIdsEqual: function (obj1, obj2) { + return false; + } + }; + openmct.router = { + path: [{type: 'layout'}] + }; + + let action = new ClearDataAction(openmct, ['apple']); + + const actionApplies = action.appliesTo(mockObjectPath); + + expect(actionApplies).toBe(true); + }); +}); diff --git a/src/plugins/clearData/test/clearDataActionSpec.js b/src/plugins/clearData/test/clearDataActionSpec.js deleted file mode 100644 index 95d372d4c8..0000000000 --- a/src/plugins/clearData/test/clearDataActionSpec.js +++ /dev/null @@ -1,64 +0,0 @@ -/***************************************************************************** - * Open MCT, Copyright (c) 2014-2021, 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 ClearDataActionPlugin from '../plugin.js'; -import ClearDataAction from '../clearDataAction.js'; - -describe('When the Clear Data Plugin is installed,', function () { - const mockObjectViews = jasmine.createSpyObj('objectViews', ['emit']); - const mockIndicatorProvider = jasmine.createSpyObj('indicators', ['add']); - const mockActionsProvider = jasmine.createSpyObj('actions', ['register']); - - const openmct = { - objectViews: mockObjectViews, - indicators: mockIndicatorProvider, - actions: mockActionsProvider, - install: function (plugin) { - plugin(this); - } - }; - - const mockObjectPath = [ - {name: 'mockObject1'}, - {name: 'mockObject2'} - ]; - - it('Global Clear Indicator is installed', function () { - openmct.install(ClearDataActionPlugin([])); - - expect(mockIndicatorProvider.add).toHaveBeenCalled(); - }); - - it('Clear Data context menu action is installed', function () { - openmct.install(ClearDataActionPlugin([])); - - expect(mockActionsProvider.register).toHaveBeenCalled(); - }); - - it('clear data action emits a clearData event when invoked', function () { - let action = new ClearDataAction(openmct); - - action.invoke(mockObjectPath); - - expect(mockObjectViews.emit).toHaveBeenCalledWith('clearData', mockObjectPath[0]); - }); -}); diff --git a/src/plugins/plot/MctPlot.vue b/src/plugins/plot/MctPlot.vue index 2e8eb796de..4d6b6e0b75 100644 --- a/src/plugins/plot/MctPlot.vue +++ b/src/plugins/plot/MctPlot.vue @@ -393,12 +393,31 @@ export default { }); }, - clearData() { + clearSeries() { this.config.series.forEach(function (series) { series.reset(); }); }, + compositionPathContainsId(domainObjectToClear) { + return domainObjectToClear.composition.some((compositionIdentifier) => { + return this.openmct.objects.areIdsEqual(compositionIdentifier, this.domainObject.identifier); + }); + }, + + clearData(domainObjectToClear) { + // If we don't have an object to clear (global), or the IDs are equal, just clear the data. + // If we have an object to clear, but the IDs don't match, we need to check the composition + // of the object we've been asked to clear to see if it contains the id we're looking for. + // This happens with stacked plots for example. + // If we find the ID, clear the plot. + if (!domainObjectToClear + || this.openmct.objects.areIdsEqual(domainObjectToClear.identifier, this.domainObject.identifier) + || this.compositionPathContainsId(domainObjectToClear)) { + this.clearSeries(); + } + }, + setDisplayRange(series, xKey) { if (this.config.series.length !== 1) { return;