mirror of
https://github.com/nasa/openmct.git
synced 2024-12-18 20:57:53 +00:00
[Plugin] Add imported root plugin (#1784)
* [Plugin] Add static root plugin Add StaticRootPlugin, which allows a file exported with the ImportExport plugin to be mounted as a static root in Open MCT. Allows deployers to configure standard displays for deployments by exporting displays they have already created. * Include all src files
This commit is contained in:
parent
39a7f43cd0
commit
f9060a485d
@ -37,14 +37,13 @@ module.exports = function(config) {
|
||||
{pattern: 'bower_components/**/*.js', included: false},
|
||||
{pattern: 'node_modules/d3-*/**/*.js', included: false},
|
||||
{pattern: 'node_modules/vue/**/*.js', included: false},
|
||||
{pattern: 'src/**/*.js', included: false},
|
||||
{pattern: 'src/**/*', included: false},
|
||||
{pattern: 'example/**/*.html', included: false},
|
||||
{pattern: 'example/**/*.js', included: false},
|
||||
{pattern: 'example/**/*.json', included: false},
|
||||
{pattern: 'platform/**/*.js', included: false},
|
||||
{pattern: 'warp/**/*.js', included: false},
|
||||
{pattern: 'platform/**/*.html', included: false},
|
||||
{pattern: 'src/**/*.html', included: false},
|
||||
'test-main.js'
|
||||
],
|
||||
|
||||
|
@ -31,7 +31,8 @@ define([
|
||||
'./summaryWidget/plugin',
|
||||
'./URLIndicatorPlugin/URLIndicatorPlugin',
|
||||
'./telemetryMean/plugin',
|
||||
'./plot/plugin'
|
||||
'./plot/plugin',
|
||||
'./staticRootPlugin/plugin'
|
||||
], function (
|
||||
_,
|
||||
UTCTimeSystem,
|
||||
@ -43,7 +44,8 @@ define([
|
||||
SummaryWidget,
|
||||
URLIndicatorPlugin,
|
||||
TelemetryMean,
|
||||
PlotPlugin
|
||||
PlotPlugin,
|
||||
StaticRootPlugin
|
||||
) {
|
||||
var bundleMap = {
|
||||
CouchDB: 'platform/persistence/couch',
|
||||
@ -66,6 +68,8 @@ define([
|
||||
|
||||
plugins.ImportExport = ImportExport;
|
||||
|
||||
plugins.StaticRootPlugin = StaticRootPlugin;
|
||||
|
||||
/**
|
||||
* A tabular view showing the latest values of multiple telemetry points at
|
||||
* once. Formatted so that labels and values are aligned.
|
||||
|
78
src/plugins/staticRootPlugin/StaticModelProvider.js
Normal file
78
src/plugins/staticRootPlugin/StaticModelProvider.js
Normal file
@ -0,0 +1,78 @@
|
||||
define([
|
||||
'../../api/objects/object-utils'
|
||||
], function (
|
||||
objectUtils
|
||||
) {
|
||||
/**
|
||||
* Transforms an import json blob into a object map that can be used to
|
||||
* provide objects. Rewrites root identifier in import data with provided
|
||||
* rootIdentifier, and rewrites all child object identifiers so that they
|
||||
* exist in the same namespace as the rootIdentifier.
|
||||
*/
|
||||
function rewriteObjectIdentifiers(importData, rootIdentifier) {
|
||||
var rootId = importData.rootId;
|
||||
var objectString = JSON.stringify(importData.openmct);
|
||||
|
||||
Object.keys(importData.openmct).forEach(function (originalId, i) {
|
||||
var newId;
|
||||
if (originalId === rootId) {
|
||||
newId = objectUtils.makeKeyString(rootIdentifier);
|
||||
} else {
|
||||
newId = objectUtils.makeKeyString({
|
||||
namespace: rootIdentifier.namespace,
|
||||
key: i
|
||||
});
|
||||
}
|
||||
while (objectString.indexOf(originalId) !== -1) {
|
||||
objectString = objectString.replace(
|
||||
'"' + originalId + '"',
|
||||
'"' + newId + '"'
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
return JSON.parse(objectString);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convets all objects in an object make from old format objects to new
|
||||
* format objects.
|
||||
*/
|
||||
function convertToNewObjects(oldObjectMap) {
|
||||
return Object.keys(oldObjectMap)
|
||||
.reduce(function (newObjectMap, key) {
|
||||
newObjectMap[key] = objectUtils.toNewFormat(oldObjectMap[key], key);
|
||||
return newObjectMap;
|
||||
}, {});
|
||||
}
|
||||
|
||||
/* Set the root location correctly for a top-level object */
|
||||
function setRootLocation(objectMap, rootIdentifier) {
|
||||
objectMap[objectUtils.makeKeyString(rootIdentifier)].location = 'ROOT';
|
||||
return objectMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes importData (as provided by the ImportExport plugin) and exposes
|
||||
* an object provider to fetch those objects.
|
||||
*/
|
||||
function StaticModelProvider(importData, rootIdentifier) {
|
||||
var oldFormatObjectMap = rewriteObjectIdentifiers(importData, rootIdentifier);
|
||||
var newFormatObjectMap = convertToNewObjects(oldFormatObjectMap);
|
||||
this.objectMap = setRootLocation(newFormatObjectMap, rootIdentifier);
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard "Get".
|
||||
*/
|
||||
StaticModelProvider.prototype.get = function (identifier) {
|
||||
var keyString = objectUtils.makeKeyString(identifier);
|
||||
if (this.objectMap[keyString]) {
|
||||
return this.objectMap[keyString];
|
||||
}
|
||||
throw new Error(keyString + ' not found in import models.');
|
||||
};
|
||||
|
||||
return StaticModelProvider;
|
||||
|
||||
});
|
133
src/plugins/staticRootPlugin/StaticModelProviderSpec.js
Normal file
133
src/plugins/staticRootPlugin/StaticModelProviderSpec.js
Normal file
@ -0,0 +1,133 @@
|
||||
define([
|
||||
'./StaticModelProvider',
|
||||
'text!./static-provider-test.json'
|
||||
], function (
|
||||
StaticModelProvider,
|
||||
testStaticDataText
|
||||
) {
|
||||
|
||||
describe('StaticModelProvider', function () {
|
||||
|
||||
var staticProvider;
|
||||
|
||||
beforeEach(function () {
|
||||
var staticData = JSON.parse(testStaticDataText);
|
||||
staticProvider = new StaticModelProvider(staticData, {
|
||||
namespace: 'my-import',
|
||||
key: 'root'
|
||||
});
|
||||
});
|
||||
|
||||
describe('rootObject', function () {
|
||||
var rootModel;
|
||||
|
||||
beforeEach(function () {
|
||||
rootModel = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: 'root'
|
||||
});
|
||||
});
|
||||
|
||||
it('is located at top level', function () {
|
||||
expect(rootModel.location).toBe('ROOT');
|
||||
});
|
||||
|
||||
it('has new-format identifier', function () {
|
||||
expect(rootModel.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: 'root'
|
||||
});
|
||||
});
|
||||
|
||||
it('has new-format composition', function () {
|
||||
expect(rootModel.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
expect(rootModel.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '2'
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('childObjects', function () {
|
||||
var swg;
|
||||
var layout;
|
||||
var fixed;
|
||||
|
||||
beforeEach(function () {
|
||||
swg = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
layout = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: '2'
|
||||
});
|
||||
fixed = staticProvider.get({
|
||||
namespace: 'my-import',
|
||||
key: '3'
|
||||
});
|
||||
});
|
||||
|
||||
it('match expected ordering', function () {
|
||||
// this is a sanity check to make sure the identifiers map in
|
||||
// the correct order.
|
||||
expect(swg.type).toBe('generator');
|
||||
expect(layout.type).toBe('layout');
|
||||
expect(fixed.type).toBe('telemetry.fixed');
|
||||
});
|
||||
|
||||
it('have new-style identifiers', function () {
|
||||
expect(swg.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
expect(layout.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: '2'
|
||||
});
|
||||
expect(fixed.identifier).toEqual({
|
||||
namespace: 'my-import',
|
||||
key: '3'
|
||||
});
|
||||
});
|
||||
|
||||
it('have new-style composition', function () {
|
||||
expect(layout.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
expect(layout.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '3'
|
||||
});
|
||||
expect(fixed.composition).toContain({
|
||||
namespace: 'my-import',
|
||||
key: '1'
|
||||
});
|
||||
});
|
||||
|
||||
it('rewrites locations', function () {
|
||||
expect(swg.location).toBe('my-import:root');
|
||||
expect(layout.location).toBe('my-import:root');
|
||||
expect(fixed.location).toBe('my-import:2');
|
||||
});
|
||||
|
||||
it('rewrites matched identifiers in objects', function () {
|
||||
expect(layout.configuration.layout.panels['my-import:1'])
|
||||
.toBeDefined();
|
||||
expect(layout.configuration.layout.panels['my-import:3'])
|
||||
.toBeDefined();
|
||||
expect(layout.configuration.layout.panels['483c00d4-bb1d-4b42-b29a-c58e06b322a0'])
|
||||
.not.toBeDefined();
|
||||
expect(layout.configuration.layout.panels['20273193-f069-49e9-b4f7-b97a87ed755d'])
|
||||
.not.toBeDefined();
|
||||
expect(fixed.configuration['fixed-display'].elements[0].id)
|
||||
.toBe('my-import:1');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
});
|
51
src/plugins/staticRootPlugin/plugin.js
Normal file
51
src/plugins/staticRootPlugin/plugin.js
Normal file
@ -0,0 +1,51 @@
|
||||
define([
|
||||
'./StaticModelProvider'
|
||||
], function (
|
||||
StaticModelProvider
|
||||
) {
|
||||
/**
|
||||
* Static Root Plugin: takes an export file and exposes it as a new root
|
||||
* object.
|
||||
*/
|
||||
function StaticRootPlugin(namespace, exportUrl) {
|
||||
|
||||
var rootIdentifier = {
|
||||
namespace: namespace,
|
||||
key: 'root'
|
||||
};
|
||||
|
||||
var cachedProvider;
|
||||
|
||||
var loadProvider = function () {
|
||||
return fetch(exportUrl)
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function (importData) {
|
||||
cachedProvider = new StaticModelProvider(importData, rootIdentifier);
|
||||
return cachedProvider;
|
||||
});
|
||||
|
||||
};
|
||||
|
||||
var getProvider = function () {
|
||||
if (!cachedProvider) {
|
||||
cachedProvider = loadProvider();
|
||||
}
|
||||
return Promise.resolve(cachedProvider);
|
||||
};
|
||||
|
||||
return function install(openmct) {
|
||||
openmct.objects.addRoot(rootIdentifier);
|
||||
openmct.objects.addProvider(namespace, {
|
||||
get: function (identifier) {
|
||||
return getProvider().then(function (provider) {
|
||||
return provider.get(identifier);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
return StaticRootPlugin;
|
||||
});
|
1
src/plugins/staticRootPlugin/static-provider-test.json
Normal file
1
src/plugins/staticRootPlugin/static-provider-test.json
Normal file
@ -0,0 +1 @@
|
||||
{"openmct":{"a9122832-4b6e-43ea-8219-5359c14c5de8":{"composition":["483c00d4-bb1d-4b42-b29a-c58e06b322a0","d2ac3ae4-0af2-49fe-81af-adac09936215"],"name":"import-provider-test","type":"folder","notes":"test data for import provider.","modified":1508522673278,"location":"mine","persisted":1508522673278},"483c00d4-bb1d-4b42-b29a-c58e06b322a0":{"telemetry":{"period":10,"amplitude":1,"offset":0,"dataRateInHz":1,"values":[{"key":"utc","name":"Time","format":"utc","hints":{"domain":1,"priority":0},"source":"utc"},{"key":"yesterday","name":"Yesterday","format":"utc","hints":{"domain":2,"priority":1},"source":"yesterday"},{"key":"sin","name":"Sine","hints":{"range":1,"priority":2},"source":"sin"},{"key":"cos","name":"Cosine","hints":{"range":2,"priority":3},"source":"cos"}]},"name":"SWG-10","type":"generator","modified":1508522652874,"location":"a9122832-4b6e-43ea-8219-5359c14c5de8","persisted":1508522652874},"d2ac3ae4-0af2-49fe-81af-adac09936215":{"composition":["483c00d4-bb1d-4b42-b29a-c58e06b322a0","20273193-f069-49e9-b4f7-b97a87ed755d"],"name":"Layout","type":"layout","configuration":{"layout":{"panels":{"483c00d4-bb1d-4b42-b29a-c58e06b322a0":{"position":[0,0],"dimensions":[17,8]},"20273193-f069-49e9-b4f7-b97a87ed755d":{"position":[0,8],"dimensions":[17,1],"hasFrame":false}}}},"modified":1508522745580,"location":"a9122832-4b6e-43ea-8219-5359c14c5de8","persisted":1508522745580},"20273193-f069-49e9-b4f7-b97a87ed755d":{"layoutGrid":[64,16],"composition":["483c00d4-bb1d-4b42-b29a-c58e06b322a0"],"name":"FP Test","type":"telemetry.fixed","configuration":{"fixed-display":{"elements":[{"type":"fixed.telemetry","x":0,"y":0,"id":"483c00d4-bb1d-4b42-b29a-c58e06b322a0","stroke":"transparent","color":"","titled":true,"width":8,"height":2,"useGrid":true,"size":"24px"}]}},"modified":1508522717619,"location":"d2ac3ae4-0af2-49fe-81af-adac09936215","persisted":1508522717619}},"rootId":"a9122832-4b6e-43ea-8219-5359c14c5de8"}
|
Loading…
Reference in New Issue
Block a user