mirror of
https://github.com/nasa/openmct.git
synced 2024-12-18 20:57:53 +00:00
[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>
This commit is contained in:
parent
d53ca3ec9a
commit
2fc0d34b8f
46
API.md
46
API.md
@ -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;
|
||||
}
|
||||
}
|
||||
```
|
@ -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);
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -172,6 +172,7 @@ define([
|
||||
}
|
||||
|
||||
return {
|
||||
isIdentifier: isIdentifier,
|
||||
toOldFormat: toOldFormat,
|
||||
toNewFormat: toNewFormat,
|
||||
makeKeyString: makeKeyString,
|
||||
|
@ -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);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -25,11 +25,15 @@ import myItemsInterceptor from "./myItemsInterceptor";
|
||||
|
||||
const MY_ITEMS_DEFAULT_NAME = 'My Items';
|
||||
|
||||
export default function MyItemsPlugin(name = MY_ITEMS_DEFAULT_NAME, namespace = '') {
|
||||
export default function MyItemsPlugin(name = MY_ITEMS_DEFAULT_NAME, namespace = '', priority = undefined) {
|
||||
return function install(openmct) {
|
||||
const identifier = createMyItemsIdentifier(namespace);
|
||||
|
||||
if (priority === undefined) {
|
||||
priority = openmct.priority.LOW;
|
||||
}
|
||||
|
||||
openmct.objects.addGetInterceptor(myItemsInterceptor(openmct, identifier, name));
|
||||
openmct.objects.addRoot(identifier);
|
||||
openmct.objects.addRoot(identifier, priority);
|
||||
};
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user