Compare commits

...

20 Commits

Author SHA1 Message Date
e52ace77c3 Merge branch 'master' into remove-unused-code 2022-01-05 11:39:00 -08:00
88a94c80be Unable to create domain objects (#4672)
* Run full regression suite on PR
* rename job
* specify new testsuites to run
* use newer objects types
* Limit concurrency to 2 workers
* CI!
Co-authored-by: John Hill <john.c.hill@nasa.gov>
Co-authored-by: John Hill <jchill2.spam@gmail.com>
2022-01-05 09:57:25 -08:00
6f3f43a555 Merge branch 'master' into remove-unused-code 2022-01-04 16:35:30 -08:00
2fc0d34b8f [Root Objects] Order by specified priority (#4658)
* Updated objectAPI to support root priority
* Updated to new ES6 module for root registry and updated docs for new priority API and root object priority
* Set "My Items" to default priority of low, for root object order

Co-authored-by: Andrew Henry <akhenry@gmail.com>
2022-01-04 16:34:48 -08:00
d53ca3ec9a grid toggle (#4632)
Co-authored-by: Nikhil <nikhil.k.mandlik@nasa.gov>
Co-authored-by: Joe Pea <trusktr@gmail.com>
Co-authored-by: John Hill <john.c.hill@nasa.gov>
2022-01-04 15:46:11 -08:00
86e5d10fc1 Add npm badge for the lazy (#4619)
Co-authored-by: Shefali Joshi <simplyrender@gmail.com>
2022-01-04 11:41:19 -08:00
936b88363c Disable legacy support in openmct dev (#4660)
Co-authored-by: Shefali Joshi <simplyrender@gmail.com>
2022-01-04 08:32:47 -08:00
38fec73a33 4588 - Removed summary widget creatability and updated composition policy (#4609)
* Removed summary widget creatability and updated composition policy

Co-authored-by: John Hill <john.c.hill@nasa.gov>
2022-01-04 07:40:09 -08:00
43c2c8543e Fixes for #4623 (#4624)
- New `c-object-view` class;
- Removed CSS class special-casing in ObjectView.vue;
- Removed unused `l-shell__main-object-view` class;
- Fixed CSS selector for Condition Widget display in main view;

Co-authored-by: John Hill <john.c.hill@nasa.gov>
Co-authored-by: Shefali Joshi <simplyrender@gmail.com>
2022-01-04 06:00:14 -08:00
e8e719e7f7 Update Bug Report format to make visual bug distinction clearer (#4662)
Co-authored-by: Shefali Joshi <simplyrender@gmail.com>
2022-01-04 05:49:14 -08:00
26e70d82b7 Move action issue fix #4663 (#4664) 2022-01-03 17:27:14 -08:00
3a65f75d21 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
2022-01-03 14:21:19 -08:00
51e4c0c836 Actually install the correct version of node (#4655)
Co-authored-by: Joe Pea <trusktr@gmail.com>
2022-01-03 13:44:57 -08:00
bb9c225f23 Lock vue-loader to 15.9.8 to fix build issues (#4653)
* Use a fixed version number for vue-loader to avoid a webpack build issue in some system configurations

* Ask dependabot to keep an eye out for vue-loader updates

Co-authored-by: John Hill <john.c.hill@nasa.gov>
2022-01-03 13:39:51 -08:00
19ec98af79 Bump jasmine-core from 3.99.0 to 4.0.0 (#4651)
Bumps [jasmine-core](https://github.com/jasmine/jasmine) from 3.99.0 to 4.0.0.
- [Release notes](https://github.com/jasmine/jasmine/releases)
- [Changelog](https://github.com/jasmine/jasmine/blob/main/RELEASE.md)
- [Commits](https://github.com/jasmine/jasmine/compare/v3.99.0...v4.0.0)

---
updated-dependencies:
- dependency-name: jasmine-core
  dependency-type: direct:development
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-01-03 13:20:45 -08:00
23ead2ceaa [My Items] Make folder name customizable (#4627)
* making my items folder name customizable

Co-authored-by: Nikhil <nikhil.k.mandlik@nasa.gov>
Co-authored-by: John Hill <john.c.hill@nasa.gov>
2021-12-30 16:27:51 -08:00
6a8f4b5d9c webpack stats changed to 'errors-warnings' (#4644) 2021-12-29 17:39:07 -08:00
08792d0113 Merge branch 'master' into remove-unused-code 2021-12-17 11:31:54 -08:00
59a4d05a0b remove ImplementationLoader 2021-12-17 00:06:00 -08:00
f663a6a5b1 remove .frag files 2021-12-17 00:05:43 -08:00
51 changed files with 531 additions and 647 deletions

View File

@ -22,7 +22,7 @@ commands:
node-version: << parameters.node-version >>
- node/install:
install-npm: true
node-version: lts/fermium
node-version: << parameters.node-version >>
- run: npm install
restore_cache_cmd:
description: "Custom command for restoring cache with the ability to bust cache. When BUST_CACHE is set to true, jobs will not restore cache"
@ -153,7 +153,7 @@ workflows:
post-steps:
- upload_code_covio
- e2e-test:
name: e2e-smoke
name: e2e-ci
node-version: lts/fermium
suite: ci
the-nightly: #These jobs do not run on PRs, but against master at night

View File

@ -24,7 +24,7 @@ assignees: ''
- [ ] Regression? Did this used to work or has it always been broken?
- [ ] Is there a workaround available?
- [ ] Does this impact a critical component?
- [ ] Is this just a visual bug?
- [ ] Is this just a visual bug with no functional impact?
#### Steps to Reproduce
<!--- Provide a link to a live example, or an unambiguous set of steps to -->

View File

@ -16,6 +16,7 @@ updates:
- dependency-name: "*jasmine*"
- dependency-name: "*playwright*"
- dependency-name: "*percy*"
- dependency-name: "*vue-loader*"
- package-ecosystem: "github-actions"
directory: "/"

46
API.md
View File

@ -52,6 +52,8 @@
- [The URL Status Indicator](#the-url-status-indicator)
- [Creating a Simple Indicator](#creating-a-simple-indicator)
- [Custom Indicators](#custom-indicators)
- [Priority API](#priority-api)
- [Priority Types](#priority-types)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@ -247,16 +249,24 @@ To do so, use the `addRoot` method of the object API.
eg.
```javascript
openmct.objects.addRoot({
namespace: "example.namespace",
key: "my-key"
});
namespace: "example.namespace",
key: "my-key"
},
openmct.priority.HIGH);
```
The `addRoot` function takes a single [object identifier](#domain-objects-and-identifiers)
as an argument.
The `addRoot` function takes a two arguments, the first can be an [object identifier](#domain-objects-and-identifiers) for a root level object, or an array of identifiers for root
level objects, or a function that returns a promise for an identifier or an array of root level objects, the second is a [priority](#priority-api) or numeric value.
Root objects are loaded just like any other objects, i.e. via an object
provider.
When using the `getAll` method of the object API, they will be returned in order of priority.
eg.
```javascript
openmct.objects.addRoot(identifier, openmct.priority.LOW); // low = -1000, will appear last in composition or tree
openmct.objects.addRoot(otherIdentifier, openmct.priority.HIGH); // high = 1000, will appear first in composition or tree
```
Root objects are loaded just like any other objects, i.e. via an object provider.
## Object Providers
@ -1051,3 +1061,25 @@ A completely custom indicator can be added by simply providing a DOM element to
element: domNode
});
```
## Priority API
Open MCT provides some built-in priority values that can be used in the application for view providers, indicators, root object order, and more.
### Priority Types
Currently, the Open MCT Priority API provides (type: numeric value):
- HIGH: 1000
- Default: 0
- LOW: -1000
View provider Example:
``` javascript
class ViewProvider {
...
priority() {
return openmct.priority.HIGH;
}
}
```

View File

@ -1,4 +1,4 @@
# Open MCT [![license](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/nasa/openmct.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/nasa/openmct/context:javascript) [![codecov](https://codecov.io/gh/nasa/openmct/branch/master/graph/badge.svg?token=7DQIipp3ej)](https://codecov.io/gh/nasa/openmct) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/b2e34b17/openmct)
# Open MCT [![license](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0) [![Language grade: JavaScript](https://img.shields.io/lgtm/grade/javascript/g/nasa/openmct.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/nasa/openmct/context:javascript) [![codecov](https://codecov.io/gh/nasa/openmct/branch/master/graph/badge.svg?token=7DQIipp3ej)](https://codecov.io/gh/nasa/openmct) [![This project is using Percy.io for visual regression testing.](https://percy.io/static/images/percy-badge.svg)](https://percy.io/b2e34b17/openmct) [![npm version](https://img.shields.io/npm/v/openmct.svg)](https://www.npmjs.com/package/openmct)
Open MCT (Open Mission Control Technologies) is a next-generation mission control framework for visualization of data on desktop and mobile devices. It is developed at NASA's Ames Research Center, and is being used by NASA for data analysis of spacecraft missions, as well as planning and operation of experimental rover systems. As a generalizable and open source framework, Open MCT could be used as the basis for building applications for planning, operation, and analysis of any systems producing telemetry data.

View File

@ -13,6 +13,7 @@ const config = {
timeout: 200 * 1000,
reuseExistingServer: !process.env.CI
},
workers: 2, //Limit to 2 for CircleCI Agent
use: {
browserName: "chromium",
baseURL: 'http://localhost:8080/',

View File

@ -75,11 +75,6 @@
const TWO_HOURS = ONE_HOUR * 2;
const ONE_DAY = ONE_HOUR * 24;
[
'example/eventGenerator'
].forEach(
openmct.legacyRegistry.enable.bind(openmct.legacyRegistry)
);
openmct.install(openmct.plugins.LocalStorage());

View File

@ -34,7 +34,7 @@
"html2canvas": "^1.0.0-rc.7",
"imports-loader": "^0.8.0",
"istanbul-instrumenter-loader": "^3.0.1",
"jasmine-core": "^3.7.1",
"jasmine-core": "^4.0.0",
"jsdoc": "^3.3.2",
"karma": "6.3.9",
"karma-chrome-launcher": "3.1.0",
@ -74,7 +74,7 @@
"v8-compile-cache": "^1.1.0",
"vue": "2.5.6",
"vue-eslint-parser": "8.0.1",
"vue-loader": "^15.2.6",
"vue-loader": "15.9.8",
"vue-template-compiler": "2.5.6",
"webpack": "^5.53.0",
"webpack-cli": "^4.0.0",
@ -96,7 +96,7 @@
"test:debug": "cross-env NODE_ENV=debug karma start --no-single-run",
"test:coverage": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" COVERAGE=true karma start --single-run",
"test:coverage:firefox": "cross-env NODE_OPTIONS=\"--max_old_space_size=4096\" karma start --single-run --browsers=FirefoxHeadless",
"test:e2e:ci": "npx playwright test --config=e2e/playwright-ci.config.js smoke",
"test:e2e:ci": "npx playwright test --config=e2e/playwright-ci.config.js smoke default condition.e2e",
"test:e2e:local": "npx playwright test --config=e2e/playwright-local.config.js",
"test:e2e:visual": "percy exec -- npx playwright test --config=e2e/playwright-visual.config.js default",
"test:e2e:full": "npx playwright test --config=e2e/playwright-ci.config.js",

View File

@ -20,12 +20,18 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
// TODO delete me!
class ImplementationLoader {
load() {
return Promise.resolve({});
}
}
define([
'./Constants',
'./FrameworkInitializer',
'./LogLevel',
'./load/BundleLoader',
'./resolve/ImplementationLoader',
'./resolve/ExtensionResolver',
'./resolve/BundleResolver',
'./register/CustomRegistrars',
@ -37,7 +43,6 @@ define([
FrameworkInitializer,
LogLevel,
BundleLoader,
ImplementationLoader,
ExtensionResolver,
BundleResolver,
CustomRegistrars,
@ -62,7 +67,7 @@ define([
loader = new BundleLoader($http, $log, openmct.legacyRegistry),
resolver = new BundleResolver(
new ExtensionResolver(
new ImplementationLoader({}),
new ImplementationLoader(),
$log
),
$log

View File

@ -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.
*****************************************************************************/
/**
* Module defining ImplementationLoader. Created by vwoeltje on 11/3/14.
*/
define(
[],
function () {
/**
* Responsible for loading extension implementations
* (AMD modules.) Acts as a wrapper around RequireJS to
* provide a promise-like API.
* @memberof platform/framework
* @constructor
* @param {*} require RequireJS, or an object with similar API
* @param {*} $log Angular's logging service
*/
function ImplementationLoader(require) {
this.require = require;
}
/**
* Load an extension's implementation; or, equivalently,
* load an AMD module. This is fundamentally similar
* to a call to RequireJS, except that the result is
* wrapped in a promise. The promise will be fulfilled
* with the loaded module, or rejected with the error
* reported by Require.
*
* @param {string} path the path to the module to load
* @returns {Promise} a promise for the specified module.
*/
ImplementationLoader.prototype.load = function loadModule(path) {
var require = this.require;
return new Promise(function (fulfill, reject) {
require([path], fulfill, reject);
});
};
return ImplementationLoader;
}
);

View File

@ -1,88 +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.
*****************************************************************************/
/**
* ImplementationLoaderSpec. Created by vwoeltje on 11/6/14.
*/
define(
["../../src/resolve/ImplementationLoader"],
function (ImplementationLoader) {
describe("The implementation loader", function () {
var required,
loader;
function mockRequire(names, fulfill, reject) {
required = {
names: names,
fulfill: fulfill,
reject: reject
};
}
beforeEach(function () {
required = undefined;
loader = new ImplementationLoader(mockRequire);
});
it("passes script names to require", function () {
loader.load("xyz.js");
expect(required.names).toEqual(["xyz.js"]);
});
it("wraps require results in a Promise that can resolve", function () {
// Load and get the result
var promise = loader.load("xyz.js").then(function (result) {
expect(result).toEqual("test result");
});
required.fulfill("test result");
return promise;
});
it("wraps require results in a Promise that can reject", function () {
var result,
rejection;
// Load and get the result
var promise = loader.load("xyz.js").then(
function (v) {
result = v;
},
function (v) {
rejection = v;
});
expect(result).toBeUndefined();
required.reject("test result");
return promise.then(function () {
expect(result).toBeUndefined();
expect(rejection).toEqual("test result");
});
});
});
}
);

View File

@ -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: '<Layout ref="layout"></Layout>'
});
domElement.appendChild(appLayout.$mount().$el);
if (!isHeadlessMode) {
const appLayout = new Vue({
components: {
'Layout': Layout.default
},
provide: {
openmct: this
},
template: '<Layout ref="layout"></Layout>'
});
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 () {

View File

@ -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);

View File

@ -133,5 +133,9 @@ define([
});
};
CompositionAPI.prototype.supportsComposition = function (domainObject) {
return this.get(domainObject) !== undefined;
};
return CompositionAPI;
});

View File

@ -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);

View File

@ -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.

View File

@ -41,7 +41,7 @@ function ObjectAPI(typeRegistry, openmct) {
this.typeRegistry = typeRegistry;
this.eventEmitter = new EventEmitter();
this.providers = {};
this.rootRegistry = new RootRegistry();
this.rootRegistry = new RootRegistry(openmct);
this.inMemorySearchProvider = new InMemorySearchProvider(openmct);
this.rootProvider = new RootObjectProvider(this.rootRegistry);
@ -367,14 +367,17 @@ ObjectAPI.prototype.endTransaction = function () {
/**
* Add a root-level object.
* @param {module:openmct.ObjectAPI~Identifier|function} an array of
* identifiers for root level objects, or a function that returns a
* @param {module:openmct.ObjectAPI~Identifier|array|function} identifier an identifier or
* an array of identifiers for root level objects, or a function that returns a
* promise for an identifier or an array of root level objects.
* @param {module:openmct.PriorityAPI~priority|Number} priority a number representing
* this item(s) position in the root object's composition (example: order in object tree).
* For arrays, they are treated as blocks.
* @method addRoot
* @memberof module:openmct.ObjectAPI#
*/
ObjectAPI.prototype.addRoot = function (key) {
this.rootRegistry.addRoot(key);
ObjectAPI.prototype.addRoot = function (identifier, priority) {
this.rootRegistry.addRoot(identifier, priority);
};
/**

View File

@ -20,39 +20,43 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([
'lodash'
], function (
_
) {
import utils from './object-utils';
function RootRegistry() {
this.providers = [];
export default class RootRegistry {
constructor(openmct) {
this._rootItems = [];
this._openmct = openmct;
}
RootRegistry.prototype.getRoots = function () {
const promises = this.providers.map(function (provider) {
return provider();
});
getRoots() {
const sortedItems = this._rootItems.sort((a, b) => b.priority - a.priority);
const promises = sortedItems.map((rootItem) => rootItem.provider());
return Promise.all(promises)
.then(_.flatten);
};
function isKey(key) {
return _.isObject(key) && _.has(key, 'key') && _.has(key, 'namespace');
return Promise.all(promises).then(rootItems => rootItems.flat());
}
RootRegistry.prototype.addRoot = function (key) {
if (isKey(key) || (Array.isArray(key) && key.every(isKey))) {
this.providers.push(function () {
return key;
});
} else if (typeof key === "function") {
this.providers.push(key);
addRoot(rootItem, priority) {
if (!this._isValid(rootItem)) {
return;
}
};
return RootRegistry;
this._rootItems.push({
priority: priority || this._openmct.priority.DEFAULT,
provider: typeof rootItem === 'function' ? rootItem : () => rootItem
});
}
});
_isValid(rootItem) {
if (utils.isIdentifier(rootItem) || typeof rootItem === 'function') {
return true;
}
if (Array.isArray(rootItem)) {
return rootItem.every(utils.isIdentifier);
}
return false;
}
}

View File

@ -172,6 +172,7 @@ define([
}
return {
isIdentifier: isIdentifier,
toOldFormat: toOldFormat,
toNewFormat: toNewFormat,
makeKeyString: makeKeyString,

View File

@ -19,83 +19,113 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([
'../RootRegistry'
], function (
RootRegistry
) {
describe('RootRegistry', function () {
let idA;
let idB;
let idC;
let registry;
beforeEach(function () {
idA = {
key: 'keyA',
namespace: 'something'
};
idB = {
key: 'keyB',
namespace: 'something'
};
idC = {
key: 'keyC',
namespace: 'something'
};
registry = new RootRegistry();
});
import { createOpenMct, resetApplicationState } from '../../../utils/testing';
it('can register a root by key', function () {
registry.addRoot(idA);
describe('RootRegistry', () => {
let openmct;
let idA;
let idB;
let idC;
let idD;
return registry.getRoots()
.then(function (roots) {
expect(roots).toEqual([idA]);
});
});
beforeEach((done) => {
openmct = createOpenMct();
idA = {
key: 'keyA',
namespace: 'something'
};
idB = {
key: 'keyB',
namespace: 'something'
};
idC = {
key: 'keyC',
namespace: 'something'
};
idD = {
key: 'keyD',
namespace: 'something'
};
it('can register multiple roots by key', function () {
registry.addRoot([idA, idB]);
openmct.on('start', done);
openmct.startHeadless();
});
return registry.getRoots()
.then(function (roots) {
expect(roots).toEqual([idA, idB]);
});
});
afterEach(async () => {
await resetApplicationState(openmct);
});
it('can register an asynchronous root ', function () {
registry.addRoot(function () {
return Promise.resolve(idA);
it('can register a root by identifier', () => {
openmct.objects.addRoot(idA);
return openmct.objects.getRoot()
.then((rootObject) => {
expect(rootObject.composition).toEqual([idA]);
});
});
return registry.getRoots()
.then(function (roots) {
expect(roots).toEqual([idA]);
});
});
it('can register multiple roots by identifier', () => {
openmct.objects.addRoot([idA, idB]);
it('can register multiple asynchronous roots', function () {
registry.addRoot(function () {
return Promise.resolve([idA, idB]);
return openmct.objects.getRoot()
.then((rootObject) => {
expect(rootObject.composition).toEqual([idA, idB]);
});
});
return registry.getRoots()
.then(function (roots) {
expect(roots).toEqual([idA, idB]);
});
});
it('can register an asynchronous root ', () => {
openmct.objects.addRoot(() => Promise.resolve(idA));
it('can combine different types of registration', function () {
registry.addRoot([idA, idB]);
registry.addRoot(function () {
return Promise.resolve([idC]);
return openmct.objects.getRoot()
.then((rootObject) => {
expect(rootObject.composition).toEqual([idA]);
});
});
return registry.getRoots()
.then(function (roots) {
expect(roots).toEqual([idA, idB, idC]);
});
});
it('can register multiple asynchronous roots', () => {
openmct.objects.addRoot(() => Promise.resolve([idA, idB]));
return openmct.objects.getRoot()
.then((rootObject) => {
expect(rootObject.composition).toEqual([idA, idB]);
});
});
it('can combine different types of registration', () => {
openmct.objects.addRoot([idA, idB]);
openmct.objects.addRoot(() => Promise.resolve([idC]));
return openmct.objects.getRoot()
.then((rootObject) => {
expect(rootObject.composition).toEqual([idA, idB, idC]);
});
});
it('supports priority ordering for identifiers', () => {
openmct.objects.addRoot(idA, openmct.priority.LOW);
openmct.objects.addRoot(idB, openmct.priority.HIGH);
openmct.objects.addRoot(idC); // DEFAULT
return openmct.objects.getRoot()
.then((rootObject) => {
expect(rootObject.composition[0]).toEqual(idB);
expect(rootObject.composition[1]).toEqual(idC);
expect(rootObject.composition[2]).toEqual(idA);
});
});
it('supports priority ordering for different types of registration', () => {
openmct.objects.addRoot(() => Promise.resolve([idC]), openmct.priority.LOW);
openmct.objects.addRoot(idB, openmct.priority.HIGH);
openmct.objects.addRoot([idA, idD]); // default
return openmct.objects.getRoot()
.then((rootObject) => {
expect(rootObject.composition[0]).toEqual(idB);
expect(rootObject.composition[1]).toEqual(idA);
expect(rootObject.composition[2]).toEqual(idD);
expect(rootObject.composition[3]).toEqual(idC);
});
});
});

View File

@ -1,2 +0,0 @@
return require('openmct');
}));

View File

@ -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'

View File

@ -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: "",

View File

@ -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');

View File

@ -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;

View File

@ -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,11 +54,8 @@ export default function ConditionPlugin() {
domainObject.telemetry = {};
}
});
openmct.legacyExtension('policies', {
category: 'view',
implementation: ConditionSetViewPolicy
});
openmct.composition.addPolicy(new ConditionSetCompositionPolicy(openmct).allow);
let compositionPolicy = new ConditionSetCompositionPolicy(openmct);
openmct.composition.addPolicy(compositionPolicy.allow.bind(compositionPolicy));
openmct.telemetry.addProvider(new ConditionSetMetadataProvider(openmct));
openmct.telemetry.addProvider(new ConditionSetTelemetryProvider(openmct));
openmct.objectViews.addProvider(new ConditionSetViewProvider(openmct));

View File

@ -56,7 +56,7 @@ a.c-condition-widget {
}
// When the widget is in the main view, center it in the space
.l-shell__main-container > .c-condition-widget {
.l-shell__main-container > * > .c-condition-widget {
position: absolute;
top: 50%;
left: 50%;

View File

@ -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);

View File

@ -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();
};
};
}

View File

@ -140,11 +140,13 @@ export default class MoveAction {
}
validate(currentParent) {
return (object, data) => {
const parentCandidate = data.value;
return (data) => {
const parentCandidatePath = data.value;
const parentCandidate = parentCandidatePath[0];
let currentParentKeystring = this.openmct.objects.makeKeyString(currentParent.identifier);
let parentCandidateKeystring = this.openmct.objects.makeKeyString(parentCandidate.identifier);
let objectKeystring = this.openmct.objects.makeKeyString(object.identifier);
let objectKeystring = this.openmct.objects.makeKeyString(this.object.identifier);
if (!parentCandidateKeystring || !currentParentKeystring) {
return false;
@ -163,7 +165,7 @@ export default class MoveAction {
return false;
}
return parentCandidate && this.openmct.composition.checkPolicy(parentCandidate, object);
return parentCandidate && this.openmct.composition.checkPolicy(parentCandidate, this.object);
};
}

View File

@ -22,14 +22,14 @@
import { MY_ITEMS_KEY } from "./createMyItemsIdentifier";
function myItemsInterceptor(identifierObject, openmct) {
function myItemsInterceptor(openmct, identifierObject, name) {
const myItemsModel = {
identifier: identifierObject,
"name": "My Items",
"type": "folder",
"composition": [],
"location": "ROOT"
name,
type: "folder",
composition: [],
location: "ROOT"
};
return {

View File

@ -23,11 +23,17 @@
import { createMyItemsIdentifier } from "./createMyItemsIdentifier";
import myItemsInterceptor from "./myItemsInterceptor";
export default function MyItemsPlugin(namespace = '') {
const MY_ITEMS_DEFAULT_NAME = 'My Items';
export default function MyItemsPlugin(name = MY_ITEMS_DEFAULT_NAME, namespace = '', priority = undefined) {
return function install(openmct) {
const identifier = createMyItemsIdentifier(namespace);
openmct.objects.addGetInterceptor(myItemsInterceptor(identifier, openmct));
openmct.objects.addRoot(identifier);
if (priority === undefined) {
priority = openmct.priority.LOW;
}
openmct.objects.addGetInterceptor(myItemsInterceptor(openmct, identifier, name));
openmct.objects.addRoot(identifier, priority);
};
}

View File

@ -30,6 +30,8 @@ import {
} from './createMyItemsIdentifier';
const MISSING_NAME = `Missing: ${MY_ITEMS_KEY}`;
const DEFAULT_NAME = 'My Items';
const FANCY_NAME = 'Fancy Items';
const myItemsIdentifier = createMyItemsIdentifier();
describe("the plugin", () => {
@ -40,53 +42,82 @@ describe("the plugin", () => {
name: MISSING_NAME
};
beforeEach((done) => {
openmct = createOpenMct();
describe('with no arguments passed in', () => {
openmct.install(openmct.plugins.MyItems());
beforeEach((done) => {
openmct = createOpenMct();
openmct.install(openmct.plugins.MyItems());
openmct.on('start', done);
openmct.startHeadless();
});
afterEach(() => {
return resetApplicationState(openmct);
});
it('when installed, adds "My Items" to the root', async () => {
const root = await openmct.objects.get('ROOT');
const rootCompostionCollection = openmct.composition.get(root);
const rootCompostion = await rootCompostionCollection.load();
let myItems = rootCompostion.filter((domainObject) => {
return openmct.objects.areIdsEqual(domainObject.identifier, myItemsIdentifier);
})[0];
expect(myItems).toBeDefined();
});
describe('adds an interceptor that returns a "My Items" model for', () => {
let myItemsMissing;
let mockMissingProvider;
let activeProvider;
beforeEach(async () => {
mockMissingProvider = {
get: () => Promise.resolve(missingObj),
create: () => Promise.resolve(missingObj),
update: () => Promise.resolve(missingObj)
};
activeProvider = mockMissingProvider;
spyOn(openmct.objects, 'getProvider').and.returnValue(activeProvider);
myItemsMissing = await openmct.objects.get(myItemsIdentifier);
openmct.on('start', done);
openmct.startHeadless();
});
it('missing objects', () => {
let idsMatchMissing = openmct.objects.areIdsEqual(myItemsMissing.identifier, myItemsIdentifier);
expect(myItemsMissing).toBeDefined();
expect(idsMatchMissing).toBeTrue();
afterEach(() => {
return resetApplicationState(openmct);
});
it('when installed, adds "My Items" to the root', async () => {
const root = await openmct.objects.get('ROOT');
const rootCompostionCollection = openmct.composition.get(root);
const rootCompostion = await rootCompostionCollection.load();
let myItems = rootCompostion.filter((domainObject) => {
return openmct.objects.areIdsEqual(domainObject.identifier, myItemsIdentifier);
})[0];
expect(myItems.name).toBe(DEFAULT_NAME);
expect(myItems).toBeDefined();
});
describe('adds an interceptor that returns a "My Items" model for', () => {
let myItemsMissing;
let mockMissingProvider;
let activeProvider;
beforeEach(async () => {
mockMissingProvider = {
get: () => Promise.resolve(missingObj),
create: () => Promise.resolve(missingObj),
update: () => Promise.resolve(missingObj)
};
activeProvider = mockMissingProvider;
spyOn(openmct.objects, 'getProvider').and.returnValue(activeProvider);
myItemsMissing = await openmct.objects.get(myItemsIdentifier);
});
it('missing objects', () => {
let idsMatchMissing = openmct.objects.areIdsEqual(myItemsMissing.identifier, myItemsIdentifier);
expect(myItemsMissing).toBeDefined();
expect(idsMatchMissing).toBeTrue();
});
});
});
describe('with a name argument passed in', () => {
beforeEach((done) => {
openmct = createOpenMct();
openmct.install(openmct.plugins.MyItems(FANCY_NAME));
spyOn(openmct.objects, 'isMissing').and.returnValue(true);
openmct.on('start', done);
openmct.startHeadless();
});
afterEach(() => {
return resetApplicationState(openmct);
});
it('when installed, uses the passed in name', async () => {
let myItems = await openmct.objects.get(myItemsIdentifier);
expect(myItems.name).toBe(FANCY_NAME);
expect(myItems).toBeDefined();
});
});
});

View File

@ -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());
});

View File

@ -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: {

View File

@ -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;
});

View File

@ -29,10 +29,7 @@ define(
}
SummaryWidgetsCompositionPolicy.prototype.allow = function (parent, child) {
const parentType = parent.getCapability('type');
const newStyleChild = child.useCapability('adapter');
if (parentType.instanceOf('summary-widget') && !this.openmct.telemetry.isTelemetryObject(newStyleChild)) {
if (parent.type === 'summary-widget' && !this.openmct.telemetry.isTelemetryObject(child)) {
return false;
}

View File

@ -17,7 +17,6 @@ define([
const widgetType = {
name: 'Summary Widget',
description: 'A compact status update for collections of telemetry-producing items',
creatable: true,
cssClass: 'icon-summary-widget',
initialize: function (domainObject) {
domainObject.composition = [];
@ -85,16 +84,8 @@ define([
return function install(openmct) {
openmct.types.addType('summary-widget', widgetType);
openmct.legacyExtension('policies', {
category: 'composition',
implementation: SummaryWidgetsCompositionPolicy,
depends: ['openmct']
});
openmct.legacyExtension('policies', {
category: 'view',
implementation: SummaryWidgetViewPolicy,
depends: ['openmct']
});
let compositionPolicy = new SummaryWidgetsCompositionPolicy(openmct);
openmct.composition.addPolicy(compositionPolicy.allow.bind(compositionPolicy));
openmct.telemetry.addProvider(new SummaryWidgetMetadataProvider(openmct));
openmct.telemetry.addProvider(new SummaryWidgetTelemetryProvider(openmct));
openmct.objectViews.addProvider(new SummaryWidgetViewProvider(openmct));

View File

@ -80,7 +80,6 @@ define([
this.addHyperlink(domainObject.url, domainObject.openNewTab);
this.watchForChanges(openmct, domainObject);
const id = objectUtils.makeKeyString(this.domainObject.identifier);
const self = this;
/**
@ -105,8 +104,6 @@ define([
this.listenTo(this.toggleRulesControl, 'click', toggleRules);
openmct.$injector.get('objectService')
.getObjects([id]);
}
/**

View File

@ -191,7 +191,7 @@ export default {
});
});
},
destroyed() {
beforeDestroy() {
this.active = false;
if (this.unlisten) {
this.unlisten();

View File

@ -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');

View File

@ -1,45 +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.
*
* Open MCT https://nasa.github.io/openmct/
* Version: @@version
* Built: @@timestamp
* Revision: @@revision
* Branch: @@branch
*
* @preserve
*****************************************************************************/
(function (root, factory) {
if (typeof define === 'function' && define.amd) {
define([], factory);
} else if (typeof exports === 'object') {
module.exports = factory();
} else {
root.openmct = factory();
}
}(this, function() {
var BUILD_CONSTANTS = {
version: "@@version",
timestamp: "@@timestamp",
revision: "@@revision",
branch: "@@branch"
};

View File

@ -229,7 +229,7 @@ body.desktop .has-local-controls {
@include abs();
}
.c-grid {
.c-grid .c-grid {
pointer-events: none;
&__x { @include bgTicks($editUIGridColorFg, 'x'); }

View File

@ -9,7 +9,7 @@
/>
</div>
<div ref="objectViewWrapper"
:class="objectViewStyle"
class="c-object-view"
></div>
</div>
</template>
@ -64,13 +64,6 @@ export default {
},
font() {
return this.objectFontStyle ? this.objectFontStyle.font : this.layoutFont;
},
objectViewStyle() {
if (this.domainObject && this.domainObject.type === 'time-strip') {
return 'l-shell__main-object-view';
} else {
return 'u-contents';
}
}
},
destroyed() {

View File

@ -233,7 +233,6 @@
/******************************* MAIN AREA */
&__main-container {
// Wrapper for main views
//display: flex; NEEDS REGRESSION TESTING!!!
display: flex;
flex-direction: column;
flex: 1 1 auto !important;
@ -243,11 +242,11 @@
> * + * {
margin-top: $interiorMargin;
}
}
&__main-object-view {
flex: 1 1 auto;
overflow: auto;
> .c-object-view {
flex: 1 1 auto;
overflow: auto;
}
}
&__tree {
@ -317,6 +316,12 @@
}
}
.c-object-view {
display: block;
height: 100%;
overflow: auto;
}
.is-editing {
.l-shell__main-container {
$m: 3px;

View File

@ -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);
}
};
}
}

View File

@ -127,5 +127,5 @@ module.exports = {
}
]
},
stats: 'detailed'
stats: 'errors-warnings'
};