From 3a65f75d2190c464712fd4ee5c47f7255423da13 Mon Sep 17 00:00:00 2001 From: Andrew Henry Date: Mon, 3 Jan 2022 14:21:19 -0800 Subject: [PATCH] Move all support for the legacy API into a plugin (#4614) * Make legacy support optional * Fix order of legacy plugin registration * Added 'supportComposition' function * Add composition policy to check that parent supports composition * Fix memory leaks in timer --- index.html | 2 + src/MCT.js | 141 +++--------------- src/MCTSpec.js | 15 +- src/api/composition/CompositionAPI.js | 4 + src/api/composition/CompositionAPISpec.js | 6 + .../composition/DefaultCompositionProvider.js | 9 ++ src/plugins/LADTable/LADTableViewProvider.js | 2 +- src/plugins/charts/pluginSpec.js | 8 - src/plugins/clock/pluginSpec.js | 1 + .../condition/ConditionSetViewPolicy.js | 34 ----- src/plugins/condition/plugin.js | 5 - .../legacySupport}/BundleRegistry.js | 0 .../legacySupport}/BundleRegistrySpec.js | 0 .../legacySupport}/installDefaultBundles.js | 72 ++++----- .../legacySupport}/legacyRegistry.js | 0 .../legacySupport}/legacyRegistrySpec.js | 0 src/plugins/legacySupport/plugin.js | 126 ++++++++++++++++ .../notificationIndicator/pluginSpec.js | 8 +- src/plugins/plot/pluginSpec.js | 7 - src/plugins/plugins.js | 10 +- src/plugins/timer/components/Timer.vue | 2 +- src/plugins/timer/pluginSpec.js | 8 + src/utils/clock/Ticker.js | 12 +- 23 files changed, 231 insertions(+), 241 deletions(-) delete mode 100644 src/plugins/condition/ConditionSetViewPolicy.js rename src/{ => plugins/legacySupport}/BundleRegistry.js (100%) rename src/{ => plugins/legacySupport}/BundleRegistrySpec.js (100%) rename src/{ => plugins/legacySupport}/installDefaultBundles.js (60%) rename src/{ => plugins/legacySupport}/legacyRegistry.js (100%) rename src/{ => plugins/legacySupport}/legacyRegistrySpec.js (100%) create mode 100644 src/plugins/legacySupport/plugin.js diff --git a/index.html b/index.html index 2cf730de0e..9035469bf2 100644 --- a/index.html +++ b/index.html @@ -75,6 +75,8 @@ const TWO_HOURS = ONE_HOUR * 2; const ONE_DAY = ONE_HOUR * 24; + openmct.install(openmct.plugins.LegacySupport()); + [ 'example/eventGenerator' ].forEach( diff --git a/src/MCT.js b/src/MCT.js index 90a282aa1e..0630991dbb 100644 --- a/src/MCT.js +++ b/src/MCT.js @@ -22,24 +22,17 @@ define([ 'EventEmitter', - './BundleRegistry', - './installDefaultBundles', './api/api', './api/overlays/OverlayAPI', './selection/Selection', - 'objectUtils', './plugins/plugins', - './adapter/indicators/legacy-indicators-plugin', './ui/registries/ViewRegistry', './plugins/imagery/plugin', './ui/registries/InspectorViewRegistry', './ui/registries/ToolbarRegistry', './ui/router/ApplicationRouter', './ui/router/Browse', - '../platform/framework/src/Main', './ui/layout/Layout.vue', - '../platform/core/src/objects/DomainObjectImpl', - '../platform/core/src/capabilities/ContextualDomainObject', './ui/preview/plugin', './api/Branding', './plugins/licenses/plugin', @@ -52,24 +45,17 @@ define([ 'vue' ], function ( EventEmitter, - BundleRegistry, - installDefaultBundles, api, OverlayAPI, Selection, - objectUtils, plugins, - LegacyIndicatorsPlugin, ViewRegistry, ImageryPlugin, InspectorViewRegistry, ToolbarRegistry, ApplicationRouter, Browse, - Main, Layout, - DomainObjectImpl, - ContextualDomainObject, PreviewPlugin, BrandingAPI, LicensesPlugin, @@ -106,23 +92,6 @@ define([ revision: __OPENMCT_REVISION__, branch: __OPENMCT_BUILD_BRANCH__ }; - /* eslint-enable no-undef */ - - this.legacyBundle = { - extensions: { - services: [ - { - key: "openmct", - implementation: function ($injector) { - this.$injector = $injector; - - return this; - }.bind(this), - depends: ['$injector'] - } - ] - } - }; this.destroy = this.destroy.bind(this); /** @@ -262,16 +231,12 @@ define([ this.branding = BrandingAPI.default; - this.legacyRegistry = new BundleRegistry(); - installDefaultBundles(this.legacyRegistry); - // Plugins that are installed by default this.install(this.plugins.Plot()); this.install(this.plugins.Chart()); this.install(this.plugins.TelemetryTable.default()); this.install(PreviewPlugin.default()); - this.install(LegacyIndicatorsPlugin()); this.install(LicensesPlugin.default()); this.install(RemoveActionPlugin.default()); this.install(MoveActionPlugin.default()); @@ -303,51 +268,6 @@ define([ MCT.prototype.MCT = MCT; - MCT.prototype.legacyExtension = function (category, extension) { - this.legacyBundle.extensions[category] = - this.legacyBundle.extensions[category] || []; - this.legacyBundle.extensions[category].push(extension); - }; - - /** - * Return a legacy object, for compatibility purposes only. This method - * will be deprecated and removed in the future. - * @private - */ - MCT.prototype.legacyObject = function (domainObject) { - let capabilityService = this.$injector.get('capabilityService'); - - function instantiate(model, keyString) { - const capabilities = capabilityService.getCapabilities(model, keyString); - model.id = keyString; - - return new DomainObjectImpl(keyString, model, capabilities); - } - - if (Array.isArray(domainObject)) { - // an array of domain objects. [object, ...ancestors] representing - // a single object with a given chain of ancestors. We instantiate - // as a single contextual domain object. - return domainObject - .map((o) => { - let keyString = objectUtils.makeKeyString(o.identifier); - let oldModel = objectUtils.toOldFormat(o); - - return instantiate(oldModel, keyString); - }) - .reverse() - .reduce((parent, child) => { - return new ContextualDomainObject(child, parent); - }); - - } else { - let keyString = objectUtils.makeKeyString(domainObject.identifier); - let oldModel = objectUtils.toOldFormat(domainObject); - - return instantiate(oldModel, keyString); - } - }; - /** * Set path to where assets are hosted. This should be the path to main.js. * @memberof module:openmct.MCT# @@ -393,25 +313,6 @@ define([ this.element = domElement; - this.legacyExtension('runs', { - depends: ['navigationService'], - implementation: function (navigationService) { - navigationService - .addListener(this.emit.bind(this, 'navigation')); - }.bind(this) - }); - - // TODO: remove with legacy types. - this.types.listKeys().forEach(function (typeKey) { - const type = this.types.get(typeKey); - const legacyDefinition = type.toLegacyDefinition(); - legacyDefinition.key = typeKey; - this.legacyExtension('types', legacyDefinition); - }.bind(this)); - - this.legacyRegistry.register('adapter', this.legacyBundle); - this.legacyRegistry.enable('adapter'); - this.router.route(/^\/$/, () => { this.router.setPath('/browse/'); }); @@ -422,35 +323,27 @@ define([ * @event start * @memberof module:openmct.MCT~ */ - const startPromise = new Main(); - startPromise.run(this) - .then(function (angular) { - this.$angular = angular; - // OpenMCT Object provider doesn't operate properly unless - // something has depended upon objectService. Cool, right? - this.$injector.get('objectService'); - if (!isHeadlessMode) { - const appLayout = new Vue({ - components: { - 'Layout': Layout.default - }, - provide: { - openmct: this - }, - template: '' - }); - domElement.appendChild(appLayout.$mount().$el); + if (!isHeadlessMode) { + const appLayout = new Vue({ + components: { + 'Layout': Layout.default + }, + provide: { + openmct: this + }, + template: '' + }); + domElement.appendChild(appLayout.$mount().$el); - this.layout = appLayout.$refs.layout; - Browse(this); - } + this.layout = appLayout.$refs.layout; + Browse(this); + } - window.addEventListener('beforeunload', this.destroy); + window.addEventListener('beforeunload', this.destroy); - this.router.start(); - this.emit('start'); - }.bind(this)); + this.router.start(); + this.emit('start'); }; MCT.prototype.startHeadless = function () { diff --git a/src/MCTSpec.js b/src/MCTSpec.js index 0c2237534a..89900a796f 100644 --- a/src/MCTSpec.js +++ b/src/MCTSpec.js @@ -22,21 +22,18 @@ define([ './plugins/plugins', - 'legacyRegistry', 'utils/testing' -], function (plugins, legacyRegistry, testUtils) { +], function (plugins, testUtils) { describe("MCT", function () { let openmct; let mockPlugin; let mockPlugin2; let mockListener; - let oldBundles; beforeEach(function () { mockPlugin = jasmine.createSpy('plugin'); mockPlugin2 = jasmine.createSpy('plugin2'); mockListener = jasmine.createSpy('listener'); - oldBundles = legacyRegistry.list(); openmct = testUtils.createOpenMct(); @@ -47,12 +44,6 @@ define([ // Clean up the dirty singleton. afterEach(function () { - legacyRegistry.list().forEach(function (bundle) { - if (oldBundles.indexOf(bundle) === -1) { - legacyRegistry.delete(bundle); - } - }); - return testUtils.resetApplicationState(openmct); }); @@ -111,10 +102,6 @@ define([ describe("setAssetPath", function () { let testAssetPath; - beforeEach(function () { - openmct.legacyExtension = jasmine.createSpy('legacyExtension'); - }); - it("configures the path for assets", function () { testAssetPath = "some/path/"; openmct.setAssetPath(testAssetPath); diff --git a/src/api/composition/CompositionAPI.js b/src/api/composition/CompositionAPI.js index 2b9425a100..8e23faa81d 100644 --- a/src/api/composition/CompositionAPI.js +++ b/src/api/composition/CompositionAPI.js @@ -133,5 +133,9 @@ define([ }); }; + CompositionAPI.prototype.supportsComposition = function (domainObject) { + return this.get(domainObject) !== undefined; + }; + return CompositionAPI; }); diff --git a/src/api/composition/CompositionAPISpec.js b/src/api/composition/CompositionAPISpec.js index 2d0c1d47df..822e3fd020 100644 --- a/src/api/composition/CompositionAPISpec.js +++ b/src/api/composition/CompositionAPISpec.js @@ -87,6 +87,12 @@ define([ expect(composition).toEqual(jasmine.any(CompositionCollection)); }); + it('correctly reflects composability', function () { + expect(compositionAPI.supportsComposition(domainObject)).toBe(true); + delete domainObject.composition; + expect(compositionAPI.supportsComposition(domainObject)).toBe(false); + }); + it('loads composition from domain object', function () { const listener = jasmine.createSpy('addListener'); composition.on('add', listener); diff --git a/src/api/composition/DefaultCompositionProvider.js b/src/api/composition/DefaultCompositionProvider.js index 13eb4f52bd..99a60cf51b 100644 --- a/src/api/composition/DefaultCompositionProvider.js +++ b/src/api/composition/DefaultCompositionProvider.js @@ -49,8 +49,10 @@ define([ this.onMutation = this.onMutation.bind(this); this.cannotContainItself = this.cannotContainItself.bind(this); + this.supportsComposition = this.supportsComposition.bind(this); compositionAPI.addPolicy(this.cannotContainItself); + compositionAPI.addPolicy(this.supportsComposition); } /** @@ -61,6 +63,13 @@ define([ && parent.identifier.key === child.identifier.key); }; + /** + * @private + */ + DefaultCompositionProvider.prototype.supportsComposition = function (parent, child) { + return this.publicAPI.composition.supportsComposition(parent); + }; + /** * Check if this provider should be used to load composition for a * particular domain object. diff --git a/src/plugins/LADTable/LADTableViewProvider.js b/src/plugins/LADTable/LADTableViewProvider.js index a1255695e6..ebe2f32945 100644 --- a/src/plugins/LADTable/LADTableViewProvider.js +++ b/src/plugins/LADTable/LADTableViewProvider.js @@ -31,7 +31,7 @@ export default class LADTableViewProvider { } canView(domainObject) { - const supportsComposition = this.openmct.composition.get(domainObject) !== undefined; + const supportsComposition = this.openmct.composition.supportsComposition(domainObject); const providesTelemetry = this.openmct.telemetry.isTelemetryObject(domainObject); return domainObject.type === 'LadTable' diff --git a/src/plugins/charts/pluginSpec.js b/src/plugins/charts/pluginSpec.js index ba74c7a67a..ff412485d3 100644 --- a/src/plugins/charts/pluginSpec.js +++ b/src/plugins/charts/pluginSpec.js @@ -130,14 +130,6 @@ describe("the plugin", function () { let mockComposition; beforeEach(async () => { - const getFunc = openmct.$injector.get; - spyOn(openmct.$injector, "get") - .withArgs("exportImageService").and.returnValue({ - exportPNG: () => {}, - exportJPG: () => {} - }) - .and.callFake(getFunc); - barGraphObject = { identifier: { namespace: "", diff --git a/src/plugins/clock/pluginSpec.js b/src/plugins/clock/pluginSpec.js index a80ad1f397..8befeea099 100644 --- a/src/plugins/clock/pluginSpec.js +++ b/src/plugins/clock/pluginSpec.js @@ -87,6 +87,7 @@ describe("Clock plugin:", () => { spyOn(openmct.objects, 'get').and.returnValue(Promise.resolve(clockViewObject)); spyOn(openmct.objects, 'save').and.returnValue(Promise.resolve(true)); + spyOn(openmct.objects, 'supportsMutation').and.returnValue(true); const applicableViews = openmct.objectViews.get(clockViewObject, [clockViewObject]); clockViewProvider = applicableViews.find(viewProvider => viewProvider.key === 'clock.view'); diff --git a/src/plugins/condition/ConditionSetViewPolicy.js b/src/plugins/condition/ConditionSetViewPolicy.js deleted file mode 100644 index 55df5629b9..0000000000 --- a/src/plugins/condition/ConditionSetViewPolicy.js +++ /dev/null @@ -1,34 +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. - *****************************************************************************/ - -function ConditionSetViewPolicy() { -} - -ConditionSetViewPolicy.prototype.allow = function (view, domainObject) { - if (domainObject.getModel().type === 'conditionSet') { - return view.key === 'conditionSet.view'; - } - - return true; -}; - -export default ConditionSetViewPolicy; diff --git a/src/plugins/condition/plugin.js b/src/plugins/condition/plugin.js index bf3b99bf16..2719cbbf33 100644 --- a/src/plugins/condition/plugin.js +++ b/src/plugins/condition/plugin.js @@ -23,7 +23,6 @@ import ConditionSetViewProvider from './ConditionSetViewProvider.js'; import ConditionSetCompositionPolicy from "./ConditionSetCompositionPolicy"; import ConditionSetMetadataProvider from './ConditionSetMetadataProvider'; import ConditionSetTelemetryProvider from './ConditionSetTelemetryProvider'; -import ConditionSetViewPolicy from './ConditionSetViewPolicy'; import uuid from "uuid"; export default function ConditionPlugin() { @@ -55,10 +54,6 @@ export default function ConditionPlugin() { domainObject.telemetry = {}; } }); - openmct.legacyExtension('policies', { - category: 'view', - implementation: ConditionSetViewPolicy - }); openmct.composition.addPolicy(new ConditionSetCompositionPolicy(openmct).allow); openmct.telemetry.addProvider(new ConditionSetMetadataProvider(openmct)); openmct.telemetry.addProvider(new ConditionSetTelemetryProvider(openmct)); diff --git a/src/BundleRegistry.js b/src/plugins/legacySupport/BundleRegistry.js similarity index 100% rename from src/BundleRegistry.js rename to src/plugins/legacySupport/BundleRegistry.js diff --git a/src/BundleRegistrySpec.js b/src/plugins/legacySupport/BundleRegistrySpec.js similarity index 100% rename from src/BundleRegistrySpec.js rename to src/plugins/legacySupport/BundleRegistrySpec.js diff --git a/src/installDefaultBundles.js b/src/plugins/legacySupport/installDefaultBundles.js similarity index 60% rename from src/installDefaultBundles.js rename to src/plugins/legacySupport/installDefaultBundles.js index e11e654f47..0083c9bdaf 100644 --- a/src/installDefaultBundles.js +++ b/src/plugins/legacySupport/installDefaultBundles.js @@ -43,42 +43,42 @@ const DEFAULTS = [ ]; define([ - '../src/adapter/bundle', - '../example/eventGenerator/bundle', - '../example/export/bundle', - '../example/forms/bundle', - '../example/identity/bundle', - '../example/mobile/bundle', - '../example/msl/bundle', - '../example/notifications/bundle', - '../example/persistence/bundle', - '../example/policy/bundle', - '../example/profiling/bundle', - '../example/scratchpad/bundle', - '../example/styleguide/bundle', - '../platform/commonUI/browse/bundle', - '../platform/commonUI/dialog/bundle', - '../platform/commonUI/edit/bundle', - '../platform/commonUI/general/bundle', - '../platform/commonUI/inspect/bundle', - '../platform/commonUI/mobile/bundle', - '../platform/commonUI/notification/bundle', - '../platform/commonUI/regions/bundle', - '../platform/containment/bundle', - '../platform/core/bundle', - '../platform/entanglement/bundle', - '../platform/exporters/bundle', - '../platform/features/static-markup/bundle', - '../platform/framework/bundle', - '../platform/framework/src/load/Bundle', - '../platform/identity/bundle', - '../platform/persistence/aggregator/bundle', - '../platform/persistence/elastic/bundle', - '../platform/persistence/queue/bundle', - '../platform/policy/bundle', - '../platform/representation/bundle', - '../platform/status/bundle', - '../platform/telemetry/bundle' + '../../adapter/bundle', + '../../../example/eventGenerator/bundle', + '../../../example/export/bundle', + '../../../example/forms/bundle', + '../../../example/identity/bundle', + '../../../example/mobile/bundle', + '../../../example/msl/bundle', + '../../../example/notifications/bundle', + '../../../example/persistence/bundle', + '../../../example/policy/bundle', + '../../../example/profiling/bundle', + '../../../example/scratchpad/bundle', + '../../../example/styleguide/bundle', + '../../../platform/commonUI/browse/bundle', + '../../../platform/commonUI/dialog/bundle', + '../../../platform/commonUI/edit/bundle', + '../../../platform/commonUI/general/bundle', + '../../../platform/commonUI/inspect/bundle', + '../../../platform/commonUI/mobile/bundle', + '../../../platform/commonUI/notification/bundle', + '../../../platform/commonUI/regions/bundle', + '../../../platform/containment/bundle', + '../../../platform/core/bundle', + '../../../platform/entanglement/bundle', + '../../../platform/exporters/bundle', + '../../../platform/features/static-markup/bundle', + '../../../platform/framework/bundle', + '../../../platform/framework/src/load/Bundle', + '../../../platform/identity/bundle', + '../../../platform/persistence/aggregator/bundle', + '../../../platform/persistence/elastic/bundle', + '../../../platform/persistence/queue/bundle', + '../../../platform/policy/bundle', + '../../../platform/representation/bundle', + '../../../platform/status/bundle', + '../../../platform/telemetry/bundle' ], function () { const LEGACY_BUNDLES = Array.from(arguments); diff --git a/src/legacyRegistry.js b/src/plugins/legacySupport/legacyRegistry.js similarity index 100% rename from src/legacyRegistry.js rename to src/plugins/legacySupport/legacyRegistry.js diff --git a/src/legacyRegistrySpec.js b/src/plugins/legacySupport/legacyRegistrySpec.js similarity index 100% rename from src/legacyRegistrySpec.js rename to src/plugins/legacySupport/legacyRegistrySpec.js diff --git a/src/plugins/legacySupport/plugin.js b/src/plugins/legacySupport/plugin.js new file mode 100644 index 0000000000..a1d853f688 --- /dev/null +++ b/src/plugins/legacySupport/plugin.js @@ -0,0 +1,126 @@ +/***************************************************************************** + * 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 installDefaultBundles from './installDefaultBundles'; +import BundleRegistry from './BundleRegistry'; +import Main from '../../../platform/framework/src/Main'; +import objectUtils from '../../api/objects/object-utils'; +import DomainObjectImpl from '../../../platform/core/src/objects/DomainObjectImpl'; +import ContextualDomainObject from '../../../platform/core/src/capabilities/ContextualDomainObject'; + +export default function LegacySupportPlugin() { + return function install(openmct) { + openmct.legacyBundle = { + extensions: { + services: [ + { + key: "openmct", + implementation: function ($injector) { + openmct.$injector = $injector; + + return openmct; + }, + depends: ['$injector'] + } + ] + } + }; + + openmct.legacyExtension = function (category, extension) { + this.legacyBundle.extensions[category] = + this.legacyBundle.extensions[category] || []; + this.legacyBundle.extensions[category].push(extension); + }.bind(openmct); + + /** + * Return a legacy object, for compatibility purposes only. This method + * will be deprecated and removed in the future. + * @private + */ + openmct.legacyObject = function (domainObject) { + let capabilityService = this.$injector.get('capabilityService'); + + function instantiate(model, keyString) { + const capabilities = capabilityService.getCapabilities(model, keyString); + model.id = keyString; + + return new DomainObjectImpl(keyString, model, capabilities); + } + + if (Array.isArray(domainObject)) { + // an array of domain objects. [object, ...ancestors] representing + // a single object with a given chain of ancestors. We instantiate + // as a single contextual domain object. + return domainObject + .map((o) => { + let keyString = objectUtils.makeKeyString(o.identifier); + let oldModel = objectUtils.toOldFormat(o); + + return instantiate(oldModel, keyString); + }) + .reverse() + .reduce((parent, child) => { + return new ContextualDomainObject(child, parent); + }); + + } else { + let keyString = objectUtils.makeKeyString(domainObject.identifier); + let oldModel = objectUtils.toOldFormat(domainObject); + + return instantiate(oldModel, keyString); + } + }.bind(openmct); + + openmct.legacyRegistry = new BundleRegistry(); + installDefaultBundles(openmct.legacyRegistry); + + const patchedStart = openmct.start.bind(openmct); + openmct.start = async () => { + openmct.legacyRegistry.register('adapter', openmct.legacyBundle); + openmct.legacyRegistry.enable('adapter'); + + openmct.legacyExtension('runs', { + depends: ['navigationService'], + implementation: function (navigationService) { + navigationService + .addListener(openmct.emit.bind(openmct, 'navigation')); + } + }); + + // TODO: remove with legacy types. + openmct.types.listKeys().forEach(function (typeKey) { + const type = openmct.types.get(typeKey); + const legacyDefinition = type.toLegacyDefinition(); + legacyDefinition.key = typeKey; + openmct.legacyExtension('types', legacyDefinition); + }); + + const main = new Main(); + const angularInstance = await main.run(openmct); + + openmct.$angular = angularInstance; + openmct.$injector.get('objectService'); + + return patchedStart(); + }; + + }; +} diff --git a/src/plugins/notificationIndicator/pluginSpec.js b/src/plugins/notificationIndicator/pluginSpec.js index 5a308b5afd..69b9ad0748 100644 --- a/src/plugins/notificationIndicator/pluginSpec.js +++ b/src/plugins/notificationIndicator/pluginSpec.js @@ -30,7 +30,6 @@ import { describe('the plugin', () => { let notificationIndicatorPlugin; let openmct; - let indicatorObject; let indicatorElement; let parentElement; let mockMessages = ['error', 'test', 'notifications']; @@ -43,9 +42,6 @@ describe('the plugin', () => { parentElement = document.createElement('div'); - indicatorObject = openmct.indicators.indicatorObjects.find(indicator => indicator.key === 'notifications-indicator'); - indicatorElement = indicatorObject.element; - openmct.on('start', () => { mockMessages.forEach(message => { openmct.notifications.error(message); @@ -53,7 +49,7 @@ describe('the plugin', () => { done(); }); - openmct.startHeadless(); + openmct.start(); }); afterEach(() => { @@ -68,7 +64,7 @@ describe('the plugin', () => { }); it('notifies the user of the number of notifications', () => { - let notificationCountElement = parentElement.querySelector('.c-indicator__count'); + let notificationCountElement = document.querySelector('.c-indicator__count'); expect(notificationCountElement.innerText).toEqual(mockMessages.length.toString()); }); diff --git a/src/plugins/plot/pluginSpec.js b/src/plugins/plot/pluginSpec.js index 7903108f94..19d9e53677 100644 --- a/src/plugins/plot/pluginSpec.js +++ b/src/plugins/plot/pluginSpec.js @@ -533,13 +533,6 @@ describe("the plugin", function () { let plotViewComponentObject; beforeEach(() => { - const getFunc = openmct.$injector.get; - spyOn(openmct.$injector, "get") - .withArgs("exportImageService").and.returnValue({ - exportPNG: () => {}, - exportJPG: () => {} - }) - .and.callFake(getFunc); stackedPlotObject = { identifier: { diff --git a/src/plugins/plugins.js b/src/plugins/plugins.js index a146aefcc1..c9cb1f05c8 100644 --- a/src/plugins/plugins.js +++ b/src/plugins/plugins.js @@ -74,7 +74,9 @@ define([ './clock/plugin', './DeviceClassifier/plugin', './timer/plugin', - './localStorage/plugin' + './localStorage/plugin', + './legacySupport/plugin.js', + '../adapter/indicators/legacy-indicators-plugin' ], function ( _, UTCTimeSystem, @@ -129,7 +131,9 @@ define([ Clock, DeviceClassifier, Timer, - LocalStorage + LocalStorage, + LegacySupportPlugin, + LegacyIndicatorsPlugin ) { const bundleMap = { Elasticsearch: 'platform/persistence/elastic' @@ -237,6 +241,8 @@ define([ plugins.Timer = Timer.default; plugins.DeviceClassifier = DeviceClassifier.default; plugins.LocalStorage = LocalStorage.default; + plugins.LegacySupport = LegacySupportPlugin.default; + plugins.LegacyIndicators = LegacyIndicatorsPlugin; return plugins; }); diff --git a/src/plugins/timer/components/Timer.vue b/src/plugins/timer/components/Timer.vue index 517c243cd3..ee5210229e 100644 --- a/src/plugins/timer/components/Timer.vue +++ b/src/plugins/timer/components/Timer.vue @@ -191,7 +191,7 @@ export default { }); }); }, - destroyed() { + beforeDestroy() { this.active = false; if (this.unlisten) { this.unlisten(); diff --git a/src/plugins/timer/pluginSpec.js b/src/plugins/timer/pluginSpec.js index 0bf0070633..5d1715224d 100644 --- a/src/plugins/timer/pluginSpec.js +++ b/src/plugins/timer/pluginSpec.js @@ -60,6 +60,8 @@ describe("Timer plugin:", () => { timerDefinition = openmct.types.get('timer').definition; timerDefinition.initialize(timerDomainObject); + spyOn(openmct.objects, 'supportsMutation').and.returnValue(true); + openmct.on('start', resolve); openmct.start(appHolder); }); @@ -93,6 +95,8 @@ describe("Timer plugin:", () => { const applicableViews = openmct.objectViews.get(timerViewObject, [timerViewObject]); timerViewProvider = applicableViews.find(viewProvider => viewProvider.key === 'timer.view'); + spyOn(openmct.objects, 'get').and.returnValue(Promise.resolve(timerViewObject)); + mutableTimerObject = await openmct.objects.getMutable(timerViewObject.identifier); timerObjectPath = [mutableTimerObject]; @@ -102,6 +106,10 @@ describe("Timer plugin:", () => { await Vue.nextTick(); }); + afterEach(() => { + timerView.destroy(); + }); + it("should migrate old object properties to the configuration section", () => { openmct.objects.applyGetInterceptors(timerViewObject.identifier, timerViewObject); expect(timerViewObject.configuration.timerFormat).toBe('short'); diff --git a/src/utils/clock/Ticker.js b/src/utils/clock/Ticker.js index 671664f7ed..f536f65400 100644 --- a/src/utils/clock/Ticker.js +++ b/src/utils/clock/Ticker.js @@ -24,8 +24,6 @@ class Ticker { constructor() { this.callbacks = []; this.last = new Date() - 1000; - - this.tick(); } /** @@ -47,7 +45,7 @@ class Ticker { } // Try to update at exactly the next second - setTimeout(() => { + this.timeoutHandle = setTimeout(() => { this.tick(); }, 1000 - millis, true); } @@ -62,6 +60,10 @@ class Ticker { * @returns {Function} a function to unregister this listener */ listen(callback) { + if (this.callbacks.length === 0) { + this.tick(); + } + this.callbacks.push(callback); // Provide immediate feedback @@ -72,6 +74,10 @@ class Ticker { this.callbacks = this.callbacks.filter(function (cb) { return cb !== callback; }); + + if (this.callbacks.length === 0) { + clearTimeout(this.timeoutHandle); + } }; } }