mirror of
https://github.com/nasa/openmct.git
synced 2025-06-27 19:38:53 +00:00
Compare commits
15 Commits
Author | SHA1 | Date | |
---|---|---|---|
57abac96b2 | |||
204f6be9d0 | |||
c988c6c43b | |||
c143475f3e | |||
b248f57daa | |||
f4e8c5ecf6 | |||
11ef7c0ccd | |||
9c125e0454 | |||
439a654f6d | |||
9d32a3f1c3 | |||
705e25df8a | |||
787d6887dc | |||
1d516240a8 | |||
90ee0a309f | |||
72d05283da |
146
example/plotOptions/bundle.js
Normal file
146
example/plotOptions/bundle.js
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2017, 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
/*global define*/
|
||||||
|
|
||||||
|
define([
|
||||||
|
'legacyRegistry',
|
||||||
|
'../../platform/commonUI/browse/src/InspectorRegion',
|
||||||
|
'../../platform/commonUI/regions/src/Region'
|
||||||
|
], function (
|
||||||
|
legacyRegistry,
|
||||||
|
InspectorRegion,
|
||||||
|
Region
|
||||||
|
) {
|
||||||
|
"use strict";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a 'plot options' region part to the inspector region for the
|
||||||
|
* Telemetry Plot type only. {@link InspectorRegion} is a default region
|
||||||
|
* implementation that is added automatically to all types. In order to
|
||||||
|
* customize what appears in the inspector region, you can start from a
|
||||||
|
* blank slate by using Region, or customize the default inspector
|
||||||
|
* region by using {@link InspectorRegion}.
|
||||||
|
*/
|
||||||
|
var plotInspector = new InspectorRegion(),
|
||||||
|
/**
|
||||||
|
* Two region parts are defined here. One that appears only in browse
|
||||||
|
* mode, and one that appears only in edit mode. For not they both point
|
||||||
|
* to the same representation, but a different key could be used here to
|
||||||
|
* include a customized representation for edit mode.
|
||||||
|
*/
|
||||||
|
plotOptionsBrowseRegion = new Region({
|
||||||
|
name: "plot-options",
|
||||||
|
title: "Plot Options",
|
||||||
|
modes: ['browse'],
|
||||||
|
content: {
|
||||||
|
key: "plot-options-browse"
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
plotOptionsEditRegion = new Region({
|
||||||
|
name: "plot-options",
|
||||||
|
title: "Plot Options",
|
||||||
|
modes: ['edit'],
|
||||||
|
content: {
|
||||||
|
key: "plot-options-browse"
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Both parts are added, and policies of type 'region' will determine
|
||||||
|
* which is shown based on domain object state. A default policy is
|
||||||
|
* provided which will check the 'modes' attribute of the region part
|
||||||
|
* definition.
|
||||||
|
*/
|
||||||
|
plotInspector.addRegion(plotOptionsBrowseRegion);
|
||||||
|
plotInspector.addRegion(plotOptionsEditRegion);
|
||||||
|
|
||||||
|
legacyRegistry.register("example/plotType", {
|
||||||
|
"name": "Plot Type",
|
||||||
|
"description": "Example illustrating registration of a new object type",
|
||||||
|
"extensions": {
|
||||||
|
"types": [
|
||||||
|
{
|
||||||
|
"key": "plot",
|
||||||
|
"name": "Example Telemetry Plot",
|
||||||
|
"cssClass": "icon-telemetry-panel",
|
||||||
|
"description": "For development use. A plot for displaying telemetry.",
|
||||||
|
"priority": 10,
|
||||||
|
"delegates": [
|
||||||
|
"telemetry"
|
||||||
|
],
|
||||||
|
"features": "creation",
|
||||||
|
"contains": [
|
||||||
|
{
|
||||||
|
"has": "telemetry"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"model": {
|
||||||
|
"composition": []
|
||||||
|
},
|
||||||
|
"inspector": plotInspector,
|
||||||
|
"telemetry": {
|
||||||
|
"source": "generator",
|
||||||
|
"domains": [
|
||||||
|
{
|
||||||
|
"key": "time",
|
||||||
|
"name": "Time"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "yesterday",
|
||||||
|
"name": "Yesterday"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "delta",
|
||||||
|
"name": "Delta",
|
||||||
|
"format": "example.delta"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ranges": [
|
||||||
|
{
|
||||||
|
"key": "sin",
|
||||||
|
"name": "Sine"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "cos",
|
||||||
|
"name": "Cosine"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"properties": [
|
||||||
|
{
|
||||||
|
"name": "Period",
|
||||||
|
"control": "textfield",
|
||||||
|
"cssClass": "l-input-sm l-numeric",
|
||||||
|
"key": "period",
|
||||||
|
"required": true,
|
||||||
|
"property": [
|
||||||
|
"telemetry",
|
||||||
|
"period"
|
||||||
|
],
|
||||||
|
"pattern": "^\\d*(\\.\\d*)?$"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
@ -37,13 +37,14 @@ module.exports = function(config) {
|
|||||||
{pattern: 'bower_components/**/*.js', included: false},
|
{pattern: 'bower_components/**/*.js', included: false},
|
||||||
{pattern: 'node_modules/d3-*/**/*.js', included: false},
|
{pattern: 'node_modules/d3-*/**/*.js', included: false},
|
||||||
{pattern: 'node_modules/vue/**/*.js', included: false},
|
{pattern: 'node_modules/vue/**/*.js', included: false},
|
||||||
{pattern: 'src/**/*', included: false},
|
{pattern: 'src/**/*.js', included: false},
|
||||||
{pattern: 'example/**/*.html', included: false},
|
{pattern: 'example/**/*.html', included: false},
|
||||||
{pattern: 'example/**/*.js', included: false},
|
{pattern: 'example/**/*.js', included: false},
|
||||||
{pattern: 'example/**/*.json', included: false},
|
{pattern: 'example/**/*.json', included: false},
|
||||||
{pattern: 'platform/**/*.js', included: false},
|
{pattern: 'platform/**/*.js', included: false},
|
||||||
{pattern: 'warp/**/*.js', included: false},
|
{pattern: 'warp/**/*.js', included: false},
|
||||||
{pattern: 'platform/**/*.html', included: false},
|
{pattern: 'platform/**/*.html', included: false},
|
||||||
|
{pattern: 'src/**/*.html', included: false},
|
||||||
'test-main.js'
|
'test-main.js'
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "openmct",
|
"name": "openmct",
|
||||||
"version": "0.13.2",
|
"version": "0.12.1-SNAPSHOT",
|
||||||
"description": "The Open MCT core platform",
|
"description": "The Open MCT core platform",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"d3-array": "^1.0.2",
|
"d3-array": "^1.0.2",
|
||||||
@ -28,7 +28,7 @@
|
|||||||
"gulp-jshint-html-reporter": "^0.1.3",
|
"gulp-jshint-html-reporter": "^0.1.3",
|
||||||
"gulp-rename": "^1.2.2",
|
"gulp-rename": "^1.2.2",
|
||||||
"gulp-requirejs-optimize": "^0.3.1",
|
"gulp-requirejs-optimize": "^0.3.1",
|
||||||
"gulp-sass": "^3.1.0",
|
"gulp-sass": "^2.2.0",
|
||||||
"gulp-sourcemaps": "^1.6.0",
|
"gulp-sourcemaps": "^1.6.0",
|
||||||
"jasmine-core": "^2.3.0",
|
"jasmine-core": "^2.3.0",
|
||||||
"jscs-html-reporter": "^0.1.0",
|
"jscs-html-reporter": "^0.1.0",
|
||||||
|
@ -38,7 +38,6 @@
|
|||||||
ng-class="{ last:($index + 1) === contextualParents.length }">
|
ng-class="{ last:($index + 1) === contextualParents.length }">
|
||||||
<mct-representation key="'label'"
|
<mct-representation key="'label'"
|
||||||
mct-object="parent"
|
mct-object="parent"
|
||||||
ng-click="parent.getCapability('action').perform('navigate')"
|
|
||||||
class="location-item">
|
class="location-item">
|
||||||
</mct-representation>
|
</mct-representation>
|
||||||
</span>
|
</span>
|
||||||
@ -50,7 +49,6 @@
|
|||||||
ng-class="{ last:($index + 1) === primaryParents.length }">
|
ng-class="{ last:($index + 1) === primaryParents.length }">
|
||||||
<mct-representation key="'label'"
|
<mct-representation key="'label'"
|
||||||
mct-object="parent"
|
mct-object="parent"
|
||||||
ng-click="parent.getCapability('action').perform('navigate')"
|
|
||||||
class="location-item">
|
class="location-item">
|
||||||
</mct-representation>
|
</mct-representation>
|
||||||
</span>
|
</span>
|
||||||
|
@ -88,15 +88,11 @@ define(
|
|||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ElementsController.prototype.refreshComposition = function (domainObject) {
|
ElementsController.prototype.refreshComposition = function (domainObject) {
|
||||||
var refreshTracker = {};
|
|
||||||
this.currentRefresh = refreshTracker;
|
|
||||||
|
|
||||||
var selectedObjectComposition = domainObject && domainObject.useCapability('composition');
|
var selectedObjectComposition = domainObject && domainObject.useCapability('composition');
|
||||||
|
|
||||||
if (selectedObjectComposition) {
|
if (selectedObjectComposition) {
|
||||||
selectedObjectComposition.then(function (composition) {
|
selectedObjectComposition.then(function (composition) {
|
||||||
if (this.currentRefresh === refreshTracker) {
|
this.scope.composition = composition;
|
||||||
this.scope.composition = composition;
|
|
||||||
}
|
|
||||||
}.bind(this));
|
}.bind(this));
|
||||||
} else {
|
} else {
|
||||||
this.scope.composition = [];
|
this.scope.composition = [];
|
||||||
|
@ -31,34 +31,11 @@ define(
|
|||||||
mockSelection,
|
mockSelection,
|
||||||
mockDomainObject,
|
mockDomainObject,
|
||||||
mockMutationCapability,
|
mockMutationCapability,
|
||||||
mockCompositionCapability,
|
|
||||||
mockCompositionObjects,
|
|
||||||
mockComposition,
|
|
||||||
mockUnlisten,
|
mockUnlisten,
|
||||||
selectable = [],
|
selectable = [],
|
||||||
controller;
|
controller;
|
||||||
|
|
||||||
function mockPromise(value) {
|
|
||||||
return {
|
|
||||||
then: function (thenFunc) {
|
|
||||||
return mockPromise(thenFunc(value));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
function createDomainObject() {
|
|
||||||
return {
|
|
||||||
useCapability: function () {
|
|
||||||
return mockCompositionCapability;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function () {
|
beforeEach(function () {
|
||||||
mockComposition = ["a", "b"];
|
|
||||||
mockCompositionObjects = mockComposition.map(createDomainObject);
|
|
||||||
mockCompositionCapability = mockPromise(mockCompositionObjects);
|
|
||||||
|
|
||||||
mockUnlisten = jasmine.createSpy('unlisten');
|
mockUnlisten = jasmine.createSpy('unlisten');
|
||||||
mockMutationCapability = jasmine.createSpyObj("mutationCapability", [
|
mockMutationCapability = jasmine.createSpyObj("mutationCapability", [
|
||||||
"listen"
|
"listen"
|
||||||
@ -68,7 +45,7 @@ define(
|
|||||||
"getCapability",
|
"getCapability",
|
||||||
"useCapability"
|
"useCapability"
|
||||||
]);
|
]);
|
||||||
mockDomainObject.useCapability.andReturn(mockCompositionCapability);
|
mockDomainObject.useCapability.andCallThrough();
|
||||||
mockDomainObject.getCapability.andReturn(mockMutationCapability);
|
mockDomainObject.getCapability.andReturn(mockMutationCapability);
|
||||||
|
|
||||||
mockScope = jasmine.createSpyObj("$scope", ['$on']);
|
mockScope = jasmine.createSpyObj("$scope", ['$on']);
|
||||||
@ -88,7 +65,7 @@ define(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
spyOn(ElementsController.prototype, 'refreshComposition').andCallThrough();
|
spyOn(ElementsController.prototype, 'refreshComposition');
|
||||||
|
|
||||||
controller = new ElementsController(mockScope, mockOpenMCT);
|
controller = new ElementsController(mockScope, mockOpenMCT);
|
||||||
});
|
});
|
||||||
@ -160,25 +137,6 @@ define(
|
|||||||
|
|
||||||
expect(mockDomainObject.getCapability).not.toHaveBeenCalledWith('mutation');
|
expect(mockDomainObject.getCapability).not.toHaveBeenCalledWith('mutation');
|
||||||
});
|
});
|
||||||
|
|
||||||
it("checks concurrent changes to composition", function () {
|
|
||||||
var secondMockComposition = ["a", "b", "c"],
|
|
||||||
secondMockCompositionObjects = secondMockComposition.map(createDomainObject),
|
|
||||||
firstCompositionCallback,
|
|
||||||
secondCompositionCallback;
|
|
||||||
|
|
||||||
spyOn(mockCompositionCapability, "then").andCallThrough();
|
|
||||||
|
|
||||||
controller.refreshComposition(mockDomainObject);
|
|
||||||
controller.refreshComposition(mockDomainObject);
|
|
||||||
|
|
||||||
firstCompositionCallback = mockCompositionCapability.then.calls[0].args[0];
|
|
||||||
secondCompositionCallback = mockCompositionCapability.then.calls[1].args[0];
|
|
||||||
secondCompositionCallback(secondMockCompositionObjects);
|
|
||||||
firstCompositionCallback(mockCompositionObjects);
|
|
||||||
|
|
||||||
expect(mockScope.composition).toBe(secondMockCompositionObjects);
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -77,14 +77,6 @@
|
|||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
.s-menu {
|
|
||||||
border-radius: $basicCr;
|
|
||||||
@include containerSubtle($colorMenuBg, $colorMenuFg);
|
|
||||||
@include boxShdw($shdwMenu);
|
|
||||||
@include txtShdw($shdwMenuText);
|
|
||||||
padding: $interiorMarginSm 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu {
|
.menu {
|
||||||
border-radius: $basicCr;
|
border-radius: $basicCr;
|
||||||
@include containerSubtle($colorMenuBg, $colorMenuFg);
|
@include containerSubtle($colorMenuBg, $colorMenuFg);
|
||||||
|
@ -373,10 +373,10 @@ define(
|
|||||||
*/
|
*/
|
||||||
FixedController.prototype.updateView = function (telemetryObject, datum) {
|
FixedController.prototype.updateView = function (telemetryObject, datum) {
|
||||||
var metadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
var metadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||||
var valueMetadata = this.chooseValueMetadataToDisplay(metadata);
|
var telemetryKeyToDisplay = this.chooseTelemetryKeyToDisplay(metadata);
|
||||||
var formattedTelemetryValue = this.getFormattedTelemetryValueForKey(valueMetadata, datum);
|
var formattedTelemetryValue = this.getFormattedTelemetryValueForKey(telemetryKeyToDisplay, datum, metadata);
|
||||||
var limitEvaluator = this.openmct.telemetry.limitEvaluator(telemetryObject);
|
var limitEvaluator = this.openmct.telemetry.limitEvaluator(telemetryObject);
|
||||||
var alarm = limitEvaluator && limitEvaluator.evaluate(datum, valueMetadata);
|
var alarm = limitEvaluator && limitEvaluator.evaluate(datum, telemetryKeyToDisplay);
|
||||||
|
|
||||||
this.setDisplayedValue(
|
this.setDisplayedValue(
|
||||||
telemetryObject,
|
telemetryObject,
|
||||||
@ -389,28 +389,29 @@ define(
|
|||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
FixedController.prototype.getFormattedTelemetryValueForKey = function (valueMetadata, datum) {
|
FixedController.prototype.getFormattedTelemetryValueForKey = function (telemetryKeyToDisplay, datum, metadata) {
|
||||||
|
var valueMetadata = metadata.value(telemetryKeyToDisplay);
|
||||||
var formatter = this.openmct.telemetry.getValueFormatter(valueMetadata);
|
var formatter = this.openmct.telemetry.getValueFormatter(valueMetadata);
|
||||||
|
|
||||||
return formatter.format(datum);
|
return formatter.format(datum[valueMetadata.key]);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
FixedController.prototype.chooseValueMetadataToDisplay = function (metadata) {
|
FixedController.prototype.chooseTelemetryKeyToDisplay = function (metadata) {
|
||||||
// If there is a range value, show that preferentially
|
// If there is a range value, show that preferentially
|
||||||
var valueMetadata = metadata.valuesForHints(['range'])[0];
|
var telemetryKeyToDisplay = metadata.valuesForHints(['range'])[0];
|
||||||
|
|
||||||
// If no range is defined, default to the highest priority non time-domain data.
|
// If no range is defined, default to the highest priority non time-domain data.
|
||||||
if (valueMetadata === undefined) {
|
if (telemetryKeyToDisplay === undefined) {
|
||||||
var valuesOrderedByPriority = metadata.values();
|
var valuesOrderedByPriority = metadata.values();
|
||||||
valueMetadata = valuesOrderedByPriority.filter(function (values) {
|
telemetryKeyToDisplay = valuesOrderedByPriority.filter(function (valueMetadata) {
|
||||||
return !(values.hints.domain);
|
return !(valueMetadata.hints.domain);
|
||||||
})[0];
|
})[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return valueMetadata;
|
return telemetryKeyToDisplay.source;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -106,8 +106,8 @@ define(
|
|||||||
'telemetryFormatter',
|
'telemetryFormatter',
|
||||||
['format']
|
['format']
|
||||||
);
|
);
|
||||||
mockFormatter.format.andCallFake(function (valueMetadata) {
|
mockFormatter.format.andCallFake(function (value) {
|
||||||
return "Formatted " + valueMetadata.value;
|
return "Formatted " + value;
|
||||||
});
|
});
|
||||||
|
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
mockDomainObject = jasmine.createSpyObj(
|
||||||
@ -697,7 +697,7 @@ define(
|
|||||||
source: 'range'
|
source: 'range'
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
var key = controller.chooseValueMetadataToDisplay(mockMetadata).source;
|
var key = controller.chooseTelemetryKeyToDisplay(mockMetadata);
|
||||||
expect(key).toEqual('range');
|
expect(key).toEqual('range');
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -719,7 +719,7 @@ define(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
]);
|
]);
|
||||||
var key = controller.chooseValueMetadataToDisplay(mockMetadata).source;
|
var key = controller.chooseTelemetryKeyToDisplay(mockMetadata);
|
||||||
expect(key).toEqual('image');
|
expect(key).toEqual('image');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1,269 +0,0 @@
|
|||||||
define([
|
|
||||||
'./CompositionAPI',
|
|
||||||
'./CompositionCollection'
|
|
||||||
], function (
|
|
||||||
CompositionAPI,
|
|
||||||
CompositionCollection
|
|
||||||
) {
|
|
||||||
|
|
||||||
describe('The Composition API', function () {
|
|
||||||
var publicAPI;
|
|
||||||
var compositionAPI;
|
|
||||||
var topicService;
|
|
||||||
var mutationTopic;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
|
|
||||||
mutationTopic = jasmine.createSpyObj('mutationTopic', [
|
|
||||||
'listen'
|
|
||||||
]);
|
|
||||||
topicService = jasmine.createSpy('topicService');
|
|
||||||
topicService.andReturn(mutationTopic);
|
|
||||||
publicAPI = {};
|
|
||||||
publicAPI.objects = jasmine.createSpyObj('ObjectAPI', [
|
|
||||||
'get'
|
|
||||||
]);
|
|
||||||
publicAPI.objects.get.andCallFake(function (identifier) {
|
|
||||||
return Promise.resolve({identifier: identifier});
|
|
||||||
});
|
|
||||||
publicAPI.$injector = jasmine.createSpyObj('$injector', [
|
|
||||||
'get'
|
|
||||||
]);
|
|
||||||
publicAPI.$injector.get.andReturn(topicService);
|
|
||||||
compositionAPI = new CompositionAPI(publicAPI);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns falsy if an object does not support composition', function () {
|
|
||||||
expect(compositionAPI.get({})).toBeFalsy();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('default composition', function () {
|
|
||||||
var domainObject;
|
|
||||||
var composition;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
domainObject = {
|
|
||||||
name: 'test folder',
|
|
||||||
identifier: {
|
|
||||||
namespace: 'test',
|
|
||||||
key: '1'
|
|
||||||
},
|
|
||||||
composition: [
|
|
||||||
{
|
|
||||||
namespace: 'test',
|
|
||||||
key: 'a'
|
|
||||||
}
|
|
||||||
]
|
|
||||||
};
|
|
||||||
composition = compositionAPI.get(domainObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('returns composition collection', function () {
|
|
||||||
expect(composition).toBeDefined();
|
|
||||||
expect(composition).toEqual(jasmine.any(CompositionCollection));
|
|
||||||
});
|
|
||||||
|
|
||||||
it('loads composition from domain object', function () {
|
|
||||||
var listener = jasmine.createSpy('addListener');
|
|
||||||
var loaded = false;
|
|
||||||
composition.on('add', listener);
|
|
||||||
composition.load()
|
|
||||||
.then(function () {
|
|
||||||
loaded = true;
|
|
||||||
});
|
|
||||||
waitsFor(function () {
|
|
||||||
return loaded;
|
|
||||||
});
|
|
||||||
runs(function () {
|
|
||||||
expect(listener.calls.length).toBe(1);
|
|
||||||
expect(listener).toHaveBeenCalledWith({
|
|
||||||
identifier: {namespace: 'test', key: 'a'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
// TODO: Implement add/removal in new default provider.
|
|
||||||
xit('synchronizes changes between instances', function () {
|
|
||||||
var otherComposition = compositionAPI.get(domainObject);
|
|
||||||
var addListener = jasmine.createSpy('addListener');
|
|
||||||
var removeListener = jasmine.createSpy('removeListener');
|
|
||||||
var otherAddListener = jasmine.createSpy('otherAddListener');
|
|
||||||
var otherRemoveListener = jasmine.createSpy('otherRemoveListener');
|
|
||||||
composition.on('add', addListener);
|
|
||||||
composition.on('remove', removeListener);
|
|
||||||
otherComposition.on('add', otherAddListener);
|
|
||||||
otherComposition.on('remove', otherRemoveListener);
|
|
||||||
var loaded = false;
|
|
||||||
Promise.all([composition.load(), otherComposition.load()])
|
|
||||||
.then(function () {
|
|
||||||
loaded = true;
|
|
||||||
});
|
|
||||||
waitsFor(function () {
|
|
||||||
return loaded;
|
|
||||||
});
|
|
||||||
runs(function () {
|
|
||||||
expect(addListener).toHaveBeenCalled();
|
|
||||||
expect(otherAddListener).toHaveBeenCalled();
|
|
||||||
expect(removeListener).not.toHaveBeenCalled();
|
|
||||||
expect(otherRemoveListener).not.toHaveBeenCalled();
|
|
||||||
|
|
||||||
var object = addListener.mostRecentCall.args[0];
|
|
||||||
composition.remove(object);
|
|
||||||
expect(removeListener).toHaveBeenCalled();
|
|
||||||
expect(otherRemoveListener).toHaveBeenCalled();
|
|
||||||
|
|
||||||
addListener.reset();
|
|
||||||
otherAddListener.reset();
|
|
||||||
composition.add(object);
|
|
||||||
expect(addListener).toHaveBeenCalled();
|
|
||||||
expect(otherAddListener).toHaveBeenCalled();
|
|
||||||
|
|
||||||
removeListener.reset();
|
|
||||||
otherRemoveListener.reset();
|
|
||||||
otherComposition.remove(object);
|
|
||||||
expect(removeListener).toHaveBeenCalled();
|
|
||||||
expect(otherRemoveListener).toHaveBeenCalled();
|
|
||||||
|
|
||||||
addListener.reset();
|
|
||||||
otherAddListener.reset();
|
|
||||||
otherComposition.add(object);
|
|
||||||
expect(addListener).toHaveBeenCalled();
|
|
||||||
expect(otherAddListener).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('static custom composition', function () {
|
|
||||||
var customProvider;
|
|
||||||
var domainObject;
|
|
||||||
var composition;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
// A simple custom provider, returns the same composition for
|
|
||||||
// all objects of a given type.
|
|
||||||
customProvider = {
|
|
||||||
appliesTo: function (object) {
|
|
||||||
return object.type === 'custom-object-type';
|
|
||||||
},
|
|
||||||
load: function (object) {
|
|
||||||
return Promise.resolve([
|
|
||||||
{
|
|
||||||
namespace: 'custom',
|
|
||||||
key: 'thing'
|
|
||||||
}
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
domainObject = {
|
|
||||||
identifier: {
|
|
||||||
namespace: 'test',
|
|
||||||
key: '1'
|
|
||||||
},
|
|
||||||
type: 'custom-object-type'
|
|
||||||
};
|
|
||||||
compositionAPI.addProvider(customProvider);
|
|
||||||
composition = compositionAPI.get(domainObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('supports listening and loading', function () {
|
|
||||||
var listener = jasmine.createSpy('addListener');
|
|
||||||
var loaded = false;
|
|
||||||
composition.on('add', listener);
|
|
||||||
composition.load()
|
|
||||||
.then(function () {
|
|
||||||
loaded = true;
|
|
||||||
});
|
|
||||||
waitsFor(function () {
|
|
||||||
return loaded;
|
|
||||||
});
|
|
||||||
runs(function () {
|
|
||||||
expect(listener.calls.length).toBe(1);
|
|
||||||
expect(listener).toHaveBeenCalledWith({
|
|
||||||
identifier: {namespace: 'custom', key: 'thing'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe('dynamic custom composition', function () {
|
|
||||||
var customProvider;
|
|
||||||
var domainObject;
|
|
||||||
var composition;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
// A dynamic provider, loads an empty composition and exposes
|
|
||||||
// listener functions.
|
|
||||||
customProvider = jasmine.createSpyObj('dynamicProvider', [
|
|
||||||
'appliesTo',
|
|
||||||
'load',
|
|
||||||
'on',
|
|
||||||
'off'
|
|
||||||
]);
|
|
||||||
|
|
||||||
customProvider.appliesTo.andReturn('true');
|
|
||||||
customProvider.load.andReturn(Promise.resolve([]));
|
|
||||||
|
|
||||||
domainObject = {
|
|
||||||
identifier: {
|
|
||||||
namespace: 'test',
|
|
||||||
key: '1'
|
|
||||||
},
|
|
||||||
type: 'custom-object-type'
|
|
||||||
};
|
|
||||||
compositionAPI.addProvider(customProvider);
|
|
||||||
composition = compositionAPI.get(domainObject);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('supports listening and loading', function () {
|
|
||||||
var addListener = jasmine.createSpy('addListener');
|
|
||||||
var removeListener = jasmine.createSpy('removeListener');
|
|
||||||
var loaded = false;
|
|
||||||
composition.on('add', addListener);
|
|
||||||
composition.on('remove', removeListener);
|
|
||||||
expect(customProvider.on).toHaveBeenCalledWith(
|
|
||||||
domainObject,
|
|
||||||
'add',
|
|
||||||
jasmine.any(Function),
|
|
||||||
jasmine.any(CompositionCollection)
|
|
||||||
);
|
|
||||||
expect(customProvider.on).toHaveBeenCalledWith(
|
|
||||||
domainObject,
|
|
||||||
'remove',
|
|
||||||
jasmine.any(Function),
|
|
||||||
jasmine.any(CompositionCollection)
|
|
||||||
);
|
|
||||||
var add = customProvider.on.calls[0].args[2];
|
|
||||||
var remove = customProvider.on.calls[1].args[2];
|
|
||||||
composition.load()
|
|
||||||
.then(function () {
|
|
||||||
loaded = true;
|
|
||||||
});
|
|
||||||
waitsFor(function () {
|
|
||||||
return loaded;
|
|
||||||
});
|
|
||||||
runs(function () {
|
|
||||||
expect(addListener).not.toHaveBeenCalled();
|
|
||||||
expect(removeListener).not.toHaveBeenCalled();
|
|
||||||
add({namespace: 'custom', key: 'thing'});
|
|
||||||
});
|
|
||||||
waitsFor(function () {
|
|
||||||
return addListener.calls.length > 0;
|
|
||||||
});
|
|
||||||
runs(function () {
|
|
||||||
expect(addListener).toHaveBeenCalledWith({
|
|
||||||
identifier: {namespace: 'custom', key: 'thing'}
|
|
||||||
});
|
|
||||||
remove(addListener.mostRecentCall.args[0]);
|
|
||||||
});
|
|
||||||
waitsFor(function () {
|
|
||||||
return removeListener.calls.length > 0;
|
|
||||||
});
|
|
||||||
runs(function () {
|
|
||||||
expect(removeListener).toHaveBeenCalledWith({
|
|
||||||
identifier: {namespace: 'custom', key: 'thing'}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -38,6 +38,7 @@ define([
|
|||||||
'../example/msl/bundle',
|
'../example/msl/bundle',
|
||||||
'../example/notifications/bundle',
|
'../example/notifications/bundle',
|
||||||
'../example/persistence/bundle',
|
'../example/persistence/bundle',
|
||||||
|
'../example/plotOptions/bundle',
|
||||||
'../example/policy/bundle',
|
'../example/policy/bundle',
|
||||||
'../example/profiling/bundle',
|
'../example/profiling/bundle',
|
||||||
'../example/scratchpad/bundle',
|
'../example/scratchpad/bundle',
|
||||||
|
@ -166,6 +166,11 @@
|
|||||||
ng-show="plotHistory.length"
|
ng-show="plotHistory.length"
|
||||||
style="position: absolute; top: 8px; right: 8px;">
|
style="position: absolute; top: 8px; right: 8px;">
|
||||||
|
|
||||||
|
<a class="s-button icon-brackets"
|
||||||
|
ng-click="plot.syncConductor()"
|
||||||
|
title="Synchronize Time Conductor to plot bounds">
|
||||||
|
</a>
|
||||||
|
|
||||||
<a class="s-button icon-arrow-left"
|
<a class="s-button icon-arrow-left"
|
||||||
ng-click="plot.back()"
|
ng-click="plot.back()"
|
||||||
title="Restore previous pan/zoom">
|
title="Restore previous pan/zoom">
|
||||||
|
@ -75,6 +75,7 @@ function (
|
|||||||
this.$scope.$watch('highlights', this.scheduleDraw);
|
this.$scope.$watch('highlights', this.scheduleDraw);
|
||||||
this.$scope.$watch('rectangles', this.scheduleDraw);
|
this.$scope.$watch('rectangles', this.scheduleDraw);
|
||||||
this.config.series.forEach(this.onSeriesAdd, this);
|
this.config.series.forEach(this.onSeriesAdd, this);
|
||||||
|
window.chart = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventHelpers.extend(MCTChartController.prototype);
|
eventHelpers.extend(MCTChartController.prototype);
|
||||||
|
@ -85,19 +85,6 @@ define([
|
|||||||
|
|
||||||
this.listenTo(this, 'destroy', this.onDestroy, this);
|
this.listenTo(this, 'destroy', this.onDestroy, this);
|
||||||
},
|
},
|
||||||
/**
|
|
||||||
* Retrieve the persisted series config for a given identifier.
|
|
||||||
*/
|
|
||||||
getPersistedSeriesConfig: function (identifier) {
|
|
||||||
var domainObject = this.get('domainObject');
|
|
||||||
if (!domainObject.configuration || !domainObject.configuration.series) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
return domainObject.configuration.series.filter(function (seriesConfig) {
|
|
||||||
return seriesConfig.identifier.key === identifier.key &&
|
|
||||||
seriesConfig.identifier.namespace === identifier.namespace;
|
|
||||||
})[0];
|
|
||||||
},
|
|
||||||
/**
|
/**
|
||||||
* Update the domain object with the given value.
|
* Update the domain object with the given value.
|
||||||
*/
|
*/
|
||||||
|
@ -165,13 +165,10 @@ define([
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var valueMetadata = this.metadata.value(newKey);
|
var valueMetadata = this.metadata.value(newKey);
|
||||||
var persistedConfig = this.get('persistedConfiguration');
|
if (valueMetadata.format === 'enum') {
|
||||||
if (!persistedConfig || !persistedConfig.interpolate) {
|
this.set('interpolate', 'stepAfter');
|
||||||
if (valueMetadata.format === 'enum') {
|
} else {
|
||||||
this.set('interpolate', 'stepAfter');
|
this.set('interpolate', 'linear');
|
||||||
} else {
|
|
||||||
this.set('interpolate', 'linear');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.evaluate = function (datum) {
|
this.evaluate = function (datum) {
|
||||||
return this.limitEvaluator.evaluate(datum, valueMetadata);
|
return this.limitEvaluator.evaluate(datum, valueMetadata);
|
||||||
@ -236,6 +233,8 @@ define([
|
|||||||
* @returns {Promise}
|
* @returns {Promise}
|
||||||
*/
|
*/
|
||||||
load: function (options) {
|
load: function (options) {
|
||||||
|
this.resetOnAppend = true;
|
||||||
|
|
||||||
return this.fetch(options)
|
return this.fetch(options)
|
||||||
.then(function (res) {
|
.then(function (res) {
|
||||||
this.emit('load');
|
this.emit('load');
|
||||||
|
@ -41,7 +41,6 @@ define([
|
|||||||
this.palette = new color.ColorPalette();
|
this.palette = new color.ColorPalette();
|
||||||
this.listenTo(this, 'add', this.onSeriesAdd, this);
|
this.listenTo(this, 'add', this.onSeriesAdd, this);
|
||||||
this.listenTo(this, 'remove', this.onSeriesRemove, this);
|
this.listenTo(this, 'remove', this.onSeriesRemove, this);
|
||||||
this.listenTo(this.plot, 'change:domainObject', this.trackPersistedConfig, this);
|
|
||||||
|
|
||||||
var domainObject = this.plot.get('domainObject');
|
var domainObject = this.plot.get('domainObject');
|
||||||
if (domainObject.telemetry) {
|
if (domainObject.telemetry) {
|
||||||
@ -50,14 +49,6 @@ define([
|
|||||||
this.watchTelemetryContainer(domainObject);
|
this.watchTelemetryContainer(domainObject);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
trackPersistedConfig: function (domainObject) {
|
|
||||||
domainObject.configuration.series.forEach(function (seriesConfig) {
|
|
||||||
var series = this.byIdentifier(seriesConfig.identifier);
|
|
||||||
if (series) {
|
|
||||||
series.set('persistedConfiguration', seriesConfig);
|
|
||||||
}
|
|
||||||
}, this);
|
|
||||||
},
|
|
||||||
watchTelemetryContainer: function (domainObject) {
|
watchTelemetryContainer: function (domainObject) {
|
||||||
var composition = this.openmct.composition.get(domainObject);
|
var composition = this.openmct.composition.get(domainObject);
|
||||||
this.listenTo(composition, 'add', this.addTelemetryObject, this);
|
this.listenTo(composition, 'add', this.addTelemetryObject, this);
|
||||||
@ -84,9 +75,6 @@ define([
|
|||||||
seriesConfig = JSON.parse(JSON.stringify(seriesConfig));
|
seriesConfig = JSON.parse(JSON.stringify(seriesConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
seriesConfig.persistedConfiguration =
|
|
||||||
this.plot.getPersistedSeriesConfig(domainObject.identifier);
|
|
||||||
|
|
||||||
this.add(new PlotSeries({
|
this.add(new PlotSeries({
|
||||||
model: seriesConfig,
|
model: seriesConfig,
|
||||||
domainObject: domainObject,
|
domainObject: domainObject,
|
||||||
@ -137,19 +125,12 @@ define([
|
|||||||
},
|
},
|
||||||
updateColorPalette: function (newColor, oldColor) {
|
updateColorPalette: function (newColor, oldColor) {
|
||||||
this.palette.remove(newColor);
|
this.palette.remove(newColor);
|
||||||
var seriesWithColor = this.filter(function (series) {
|
var seriesWithColor = this.series.filter(function (series) {
|
||||||
return series.get('color') === newColor;
|
return series.get('color') === newColor;
|
||||||
})[0];
|
})[0];
|
||||||
if (!seriesWithColor) {
|
if (!seriesWithColor) {
|
||||||
this.palette.return(oldColor);
|
this.palette.return(oldColor);
|
||||||
}
|
}
|
||||||
},
|
|
||||||
byIdentifier: function (identifier) {
|
|
||||||
return this.filter(function (series) {
|
|
||||||
var seriesIdentifier = series.get('identifier');
|
|
||||||
return seriesIdentifier.namespace === identifier.namespace &&
|
|
||||||
seriesIdentifier.key === identifier.key;
|
|
||||||
})[0];
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ define([
|
|||||||
|
|
||||||
this.configId = $scope.domainObject.getId();
|
this.configId = $scope.domainObject.getId();
|
||||||
this.setUpScope();
|
this.setUpScope();
|
||||||
|
window.config = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventHelpers.extend(PlotOptionsController.prototype);
|
eventHelpers.extend(PlotOptionsController.prototype);
|
||||||
|
@ -33,12 +33,13 @@ define([
|
|||||||
* It supports pan and zoom, implements zoom history, and supports locating
|
* It supports pan and zoom, implements zoom history, and supports locating
|
||||||
* values near the cursor.
|
* values near the cursor.
|
||||||
*/
|
*/
|
||||||
function MCTPlotController($scope, $element, $window) {
|
function MCTPlotController($scope, $element, $window, openmct) {
|
||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
this.$scope.config = this.config;
|
this.$scope.config = this.config;
|
||||||
this.$scope.plot = this;
|
this.$scope.plot = this;
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
this.$window = $window;
|
this.$window = $window;
|
||||||
|
this.openmct = openmct;
|
||||||
|
|
||||||
this.xScale = new LinearScale(this.config.xAxis.get('displayRange'));
|
this.xScale = new LinearScale(this.config.xAxis.get('displayRange'));
|
||||||
this.yScale = new LinearScale(this.config.yAxis.get('displayRange'));
|
this.yScale = new LinearScale(this.config.yAxis.get('displayRange'));
|
||||||
@ -53,6 +54,7 @@ define([
|
|||||||
this.listenTo(this.$scope, 'plot:clearHistory', this.clear, this);
|
this.listenTo(this.$scope, 'plot:clearHistory', this.clear, this);
|
||||||
|
|
||||||
this.initialize();
|
this.initialize();
|
||||||
|
window.control = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
MCTPlotController.$inject = ['$scope', '$element', '$window'];
|
MCTPlotController.$inject = ['$scope', '$element', '$window'];
|
||||||
@ -331,6 +333,13 @@ define([
|
|||||||
this.$scope.$emit('user:viewport:change:end');
|
this.$scope.$emit('user:viewport:change:end');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
MCTPlotController.prototype.syncConductor = function () {
|
||||||
|
var xDisplayRange = this.config.xAxis.get('displayRange');
|
||||||
|
this.openmct.time.stopClock();
|
||||||
|
this.openmct.time.bounds({start: xDisplayRange.min, end: xDisplayRange.max});
|
||||||
|
};
|
||||||
|
|
||||||
MCTPlotController.prototype.destroy = function () {
|
MCTPlotController.prototype.destroy = function () {
|
||||||
this.stopListening();
|
this.stopListening();
|
||||||
};
|
};
|
||||||
|
@ -33,7 +33,7 @@ define([
|
|||||||
return {
|
return {
|
||||||
restrict: "E",
|
restrict: "E",
|
||||||
template: PlotTemplate,
|
template: PlotTemplate,
|
||||||
controller: MCTPlotController,
|
controller: ['$scope', '$element', '$window', 'openmct', MCTPlotController],
|
||||||
controllerAs: 'mctPlotController',
|
controllerAs: 'mctPlotController',
|
||||||
bindToController: {
|
bindToController: {
|
||||||
config: "="
|
config: "="
|
||||||
|
@ -117,6 +117,12 @@ define([
|
|||||||
this.$scope = $scope;
|
this.$scope = $scope;
|
||||||
this.$element = $element;
|
this.$element = $element;
|
||||||
|
|
||||||
|
if (!window.ticks) {
|
||||||
|
window.ticks = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
window.ticks.push(this);
|
||||||
|
|
||||||
this.tickCount = 4;
|
this.tickCount = 4;
|
||||||
this.tickUpdate = false;
|
this.tickUpdate = false;
|
||||||
this.listenTo(this.axis, 'change:displayRange', this.updateTicks, this);
|
this.listenTo(this.axis, 'change:displayRange', this.updateTicks, this);
|
||||||
|
@ -71,6 +71,7 @@ define([
|
|||||||
this.config.series.forEach(this.addSeries, this);
|
this.config.series.forEach(this.addSeries, this);
|
||||||
|
|
||||||
this.followTimeConductor();
|
this.followTimeConductor();
|
||||||
|
window.plot = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
eventHelpers.extend(PlotController.prototype);
|
eventHelpers.extend(PlotController.prototype);
|
||||||
|
@ -31,8 +31,7 @@ define([
|
|||||||
'./summaryWidget/plugin',
|
'./summaryWidget/plugin',
|
||||||
'./URLIndicatorPlugin/URLIndicatorPlugin',
|
'./URLIndicatorPlugin/URLIndicatorPlugin',
|
||||||
'./telemetryMean/plugin',
|
'./telemetryMean/plugin',
|
||||||
'./plot/plugin',
|
'./plot/plugin'
|
||||||
'./staticRootPlugin/plugin'
|
|
||||||
], function (
|
], function (
|
||||||
_,
|
_,
|
||||||
UTCTimeSystem,
|
UTCTimeSystem,
|
||||||
@ -44,8 +43,7 @@ define([
|
|||||||
SummaryWidget,
|
SummaryWidget,
|
||||||
URLIndicatorPlugin,
|
URLIndicatorPlugin,
|
||||||
TelemetryMean,
|
TelemetryMean,
|
||||||
PlotPlugin,
|
PlotPlugin
|
||||||
StaticRootPlugin
|
|
||||||
) {
|
) {
|
||||||
var bundleMap = {
|
var bundleMap = {
|
||||||
CouchDB: 'platform/persistence/couch',
|
CouchDB: 'platform/persistence/couch',
|
||||||
@ -68,8 +66,6 @@ define([
|
|||||||
|
|
||||||
plugins.ImportExport = ImportExport;
|
plugins.ImportExport = ImportExport;
|
||||||
|
|
||||||
plugins.StaticRootPlugin = StaticRootPlugin;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A tabular view showing the latest values of multiple telemetry points at
|
* A tabular view showing the latest values of multiple telemetry points at
|
||||||
* once. Formatted so that labels and values are aligned.
|
* once. Formatted so that labels and values are aligned.
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
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;
|
|
||||||
|
|
||||||
});
|
|
@ -1,133 +0,0 @@
|
|||||||
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');
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
@ -1,51 +0,0 @@
|
|||||||
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 +0,0 @@
|
|||||||
{"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"}
|
|
Reference in New Issue
Block a user