mirror of
https://github.com/nasa/openmct.git
synced 2025-06-26 11:09:22 +00:00
Compare commits
7 Commits
vue-hack
...
bar-graph-
Author | SHA1 | Date | |
---|---|---|---|
b3a774ffa6 | |||
225d3883d1 | |||
bef5fc2e47 | |||
77663ac2b3 | |||
90b98a5c97 | |||
e056b79033 | |||
5362344529 |
@ -28,15 +28,6 @@ define([
|
||||
domain: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "cos",
|
||||
name: "Cosine",
|
||||
unit: "deg",
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
domain: 3
|
||||
}
|
||||
},
|
||||
// Need to enable "LocalTimeSystem" plugin to make use of this
|
||||
// {
|
||||
// key: "local",
|
||||
@ -118,100 +109,6 @@ define([
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
'example.spectral-generator': {
|
||||
values: [
|
||||
{
|
||||
key: "name",
|
||||
name: "Name",
|
||||
format: "string"
|
||||
},
|
||||
{
|
||||
key: "utc",
|
||||
name: "Time",
|
||||
format: "utc",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "wavelength",
|
||||
name: "Wavelength",
|
||||
unit: "Hz",
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
domain: 2,
|
||||
spectralAttribute: true
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "cos",
|
||||
name: "Cosine",
|
||||
unit: "deg",
|
||||
formatString: '%0.2f',
|
||||
hints: {
|
||||
range: 2,
|
||||
spectralAttribute: true
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
'example.spectral-aggregate-generator': {
|
||||
values: [
|
||||
{
|
||||
key: "name",
|
||||
name: "Name",
|
||||
format: "string"
|
||||
},
|
||||
{
|
||||
key: "utc",
|
||||
name: "Time",
|
||||
format: "utc",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "ch1",
|
||||
name: "Channel 1",
|
||||
format: "string",
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "ch2",
|
||||
name: "Channel 2",
|
||||
format: "string",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "ch3",
|
||||
name: "Channel 3",
|
||||
format: "string",
|
||||
hints: {
|
||||
range: 3
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "ch4",
|
||||
name: "Channel 4",
|
||||
format: "string",
|
||||
hints: {
|
||||
range: 4
|
||||
}
|
||||
},
|
||||
{
|
||||
key: "ch5",
|
||||
name: "Channel 5",
|
||||
format: "string",
|
||||
hints: {
|
||||
range: 5
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -1,86 +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.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
|
||||
], function (
|
||||
|
||||
) {
|
||||
|
||||
function SpectralAggregateGeneratorProvider() {
|
||||
|
||||
}
|
||||
|
||||
function pointForTimestamp(timestamp, count, name) {
|
||||
return {
|
||||
name: name,
|
||||
utc: String(Math.floor(timestamp / count) * count),
|
||||
ch1: String(Math.floor(timestamp / count) % 1),
|
||||
ch2: String(Math.floor(timestamp / count) % 2),
|
||||
ch3: String(Math.floor(timestamp / count) % 3),
|
||||
ch4: String(Math.floor(timestamp / count) % 4),
|
||||
ch5: String(Math.floor(timestamp / count) % 5)
|
||||
};
|
||||
}
|
||||
|
||||
SpectralAggregateGeneratorProvider.prototype.supportsSubscribe = function (domainObject) {
|
||||
return domainObject.type === 'example.spectral-aggregate-generator';
|
||||
};
|
||||
|
||||
SpectralAggregateGeneratorProvider.prototype.subscribe = function (domainObject, callback) {
|
||||
var count = 5000;
|
||||
|
||||
var interval = setInterval(function () {
|
||||
var now = Date.now();
|
||||
var datum = pointForTimestamp(now, count, domainObject.name);
|
||||
callback(datum);
|
||||
}, count);
|
||||
|
||||
return function () {
|
||||
clearInterval(interval);
|
||||
};
|
||||
};
|
||||
|
||||
SpectralAggregateGeneratorProvider.prototype.supportsRequest = function (domainObject, options) {
|
||||
return domainObject.type === 'example.spectral-aggregate-generator';
|
||||
};
|
||||
|
||||
SpectralAggregateGeneratorProvider.prototype.request = function (domainObject, options) {
|
||||
var start = options.start;
|
||||
var end = Math.min(Date.now(), options.end); // no future values
|
||||
var count = 5000;
|
||||
if (options.strategy === 'latest' || options.size === 1) {
|
||||
start = end;
|
||||
}
|
||||
|
||||
var data = [];
|
||||
while (start <= end && data.length < 5000) {
|
||||
data.push(pointForTimestamp(start, count, domainObject.name));
|
||||
start += count;
|
||||
}
|
||||
|
||||
return Promise.resolve(data);
|
||||
};
|
||||
|
||||
return SpectralAggregateGeneratorProvider;
|
||||
|
||||
});
|
@ -1,102 +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.
|
||||
*****************************************************************************/
|
||||
|
||||
define([
|
||||
'./WorkerInterface'
|
||||
], function (
|
||||
WorkerInterface
|
||||
) {
|
||||
|
||||
var REQUEST_DEFAULTS = {
|
||||
amplitude: 1,
|
||||
wavelength: 1,
|
||||
period: 10,
|
||||
offset: 0,
|
||||
dataRateInHz: 1,
|
||||
randomness: 0,
|
||||
phase: 0
|
||||
};
|
||||
|
||||
function SpectralGeneratorProvider() {
|
||||
this.workerInterface = new WorkerInterface();
|
||||
}
|
||||
|
||||
SpectralGeneratorProvider.prototype.canProvideTelemetry = function (domainObject) {
|
||||
return domainObject.type === 'example.spectral-generator';
|
||||
};
|
||||
|
||||
SpectralGeneratorProvider.prototype.supportsRequest =
|
||||
SpectralGeneratorProvider.prototype.supportsSubscribe =
|
||||
SpectralGeneratorProvider.prototype.canProvideTelemetry;
|
||||
|
||||
SpectralGeneratorProvider.prototype.makeWorkerRequest = function (domainObject, request = {}) {
|
||||
var props = [
|
||||
'amplitude',
|
||||
'wavelength',
|
||||
'period',
|
||||
'offset',
|
||||
'dataRateInHz',
|
||||
'phase',
|
||||
'randomness'
|
||||
];
|
||||
|
||||
var workerRequest = {};
|
||||
|
||||
props.forEach(function (prop) {
|
||||
if (domainObject.telemetry && Object.prototype.hasOwnProperty.call(domainObject.telemetry, prop)) {
|
||||
workerRequest[prop] = domainObject.telemetry[prop];
|
||||
}
|
||||
|
||||
if (request && Object.prototype.hasOwnProperty.call(request, prop)) {
|
||||
workerRequest[prop] = request[prop];
|
||||
}
|
||||
|
||||
if (!Object.prototype.hasOwnProperty.call(workerRequest, prop)) {
|
||||
workerRequest[prop] = REQUEST_DEFAULTS[prop];
|
||||
}
|
||||
|
||||
workerRequest[prop] = Number(workerRequest[prop]);
|
||||
});
|
||||
|
||||
workerRequest.name = domainObject.name;
|
||||
|
||||
return workerRequest;
|
||||
};
|
||||
|
||||
SpectralGeneratorProvider.prototype.request = function (domainObject, request) {
|
||||
var workerRequest = this.makeWorkerRequest(domainObject, request);
|
||||
workerRequest.start = request.start;
|
||||
workerRequest.end = request.end;
|
||||
workerRequest.spectra = true;
|
||||
|
||||
return this.workerInterface.request(workerRequest);
|
||||
};
|
||||
|
||||
SpectralGeneratorProvider.prototype.subscribe = function (domainObject, callback) {
|
||||
var workerRequest = this.makeWorkerRequest(domainObject, {});
|
||||
workerRequest.spectra = true;
|
||||
|
||||
return this.workerInterface.subscribe(workerRequest, callback);
|
||||
};
|
||||
|
||||
return SpectralGeneratorProvider;
|
||||
});
|
@ -54,38 +54,23 @@
|
||||
var start = Date.now();
|
||||
var step = 1000 / data.dataRateInHz;
|
||||
var nextStep = start - (start % step) + step;
|
||||
let work;
|
||||
if (data.spectra) {
|
||||
work = function (now) {
|
||||
while (nextStep < now) {
|
||||
const messageCopy = Object.create(message);
|
||||
message.data.start = nextStep - (60 * 1000);
|
||||
message.data.end = nextStep;
|
||||
onRequest(messageCopy);
|
||||
nextStep += step;
|
||||
}
|
||||
|
||||
return nextStep;
|
||||
};
|
||||
} else {
|
||||
work = function (now) {
|
||||
while (nextStep < now) {
|
||||
self.postMessage({
|
||||
id: message.id,
|
||||
data: {
|
||||
name: data.name,
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness),
|
||||
wavelength: wavelength(start, nextStep),
|
||||
cos: cos(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness)
|
||||
}
|
||||
});
|
||||
nextStep += step;
|
||||
}
|
||||
function work(now) {
|
||||
while (nextStep < now) {
|
||||
self.postMessage({
|
||||
id: message.id,
|
||||
data: {
|
||||
name: data.name,
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness),
|
||||
cos: cos(nextStep, data.period, data.amplitude, data.offset, data.phase, data.randomness)
|
||||
}
|
||||
});
|
||||
nextStep += step;
|
||||
}
|
||||
|
||||
return nextStep;
|
||||
};
|
||||
return nextStep;
|
||||
}
|
||||
|
||||
subscriptions[message.id] = work;
|
||||
@ -126,21 +111,13 @@
|
||||
utc: nextStep,
|
||||
yesterday: nextStep - 60 * 60 * 24 * 1000,
|
||||
sin: sin(nextStep, period, amplitude, offset, phase, randomness),
|
||||
wavelength: wavelength(start, nextStep),
|
||||
cos: cos(nextStep, period, amplitude, offset, phase, randomness)
|
||||
});
|
||||
}
|
||||
|
||||
self.postMessage({
|
||||
id: message.id,
|
||||
data: request.spectra ? {
|
||||
wavelength: data.map((item) => {
|
||||
return item.wavelength;
|
||||
}),
|
||||
cos: data.map((item) => {
|
||||
return item.cos;
|
||||
})
|
||||
} : data
|
||||
data: data
|
||||
});
|
||||
}
|
||||
|
||||
@ -154,10 +131,6 @@
|
||||
* Math.sin(phase + (timestamp / period / 1000 * Math.PI * 2)) + (amplitude * Math.random() * randomness) + offset;
|
||||
}
|
||||
|
||||
function wavelength(start, nextStep) {
|
||||
return (nextStep - start) / 10;
|
||||
}
|
||||
|
||||
function sendError(error, message) {
|
||||
self.postMessage({
|
||||
error: error.name + ': ' + error.message,
|
||||
|
@ -24,15 +24,11 @@ define([
|
||||
"./GeneratorProvider",
|
||||
"./SinewaveLimitProvider",
|
||||
"./StateGeneratorProvider",
|
||||
"./SpectralGeneratorProvider",
|
||||
"./SpectralAggregateGeneratorProvider",
|
||||
"./GeneratorMetadataProvider"
|
||||
], function (
|
||||
GeneratorProvider,
|
||||
SinewaveLimitProvider,
|
||||
StateGeneratorProvider,
|
||||
SpectralGeneratorProvider,
|
||||
SpectralAggregateGeneratorProvider,
|
||||
GeneratorMetadataProvider
|
||||
) {
|
||||
|
||||
@ -65,37 +61,6 @@ define([
|
||||
|
||||
openmct.telemetry.addProvider(new StateGeneratorProvider());
|
||||
|
||||
openmct.types.addType("example.spectral-generator", {
|
||||
name: "Spectral Generator",
|
||||
description: "For development use. Generates example streaming telemetry data using a simple sine wave algorithm.",
|
||||
cssClass: "icon-generator-telemetry",
|
||||
creatable: true,
|
||||
initialize: function (object) {
|
||||
object.telemetry = {
|
||||
period: 10,
|
||||
amplitude: 1,
|
||||
wavelength: 1,
|
||||
frequency: 1,
|
||||
offset: 0,
|
||||
dataRateInHz: 1,
|
||||
phase: 0,
|
||||
randomness: 0
|
||||
};
|
||||
}
|
||||
});
|
||||
openmct.telemetry.addProvider(new SpectralGeneratorProvider());
|
||||
|
||||
openmct.types.addType("example.spectral-aggregate-generator", {
|
||||
name: "Spectral Aggregate Generator",
|
||||
description: "For development use. Generates example streaming telemetry data using a simple state algorithm.",
|
||||
cssClass: "icon-generator-telemetry",
|
||||
creatable: true,
|
||||
initialize: function (object) {
|
||||
object.telemetry = {};
|
||||
}
|
||||
});
|
||||
openmct.telemetry.addProvider(new SpectralAggregateGeneratorProvider());
|
||||
|
||||
openmct.types.addType("generator", {
|
||||
name: "Sine Wave Generator",
|
||||
description: "For development use. Generates example streaming telemetry data using a simple sine wave algorithm.",
|
||||
|
@ -44,11 +44,9 @@ define(
|
||||
setText(result.name);
|
||||
scope.ngModel[scope.field] = result;
|
||||
control.$setValidity("file-input", true);
|
||||
scope.$digest();
|
||||
}, function () {
|
||||
setText('Select File');
|
||||
control.$setValidity("file-input", false);
|
||||
scope.$digest();
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -263,6 +263,7 @@ define([
|
||||
// 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());
|
||||
@ -288,8 +289,6 @@ define([
|
||||
this.install(this.plugins.ObjectInterceptors());
|
||||
this.install(this.plugins.NonEditableFolder());
|
||||
this.install(this.plugins.DeviceClassifier());
|
||||
|
||||
this._isVue = true;
|
||||
}
|
||||
|
||||
MCT.prototype = Object.create(EventEmitter.prototype);
|
||||
|
@ -81,8 +81,14 @@ define([
|
||||
return models;
|
||||
}
|
||||
|
||||
//Temporary fix for missing models - don't retry using this.apiFetch
|
||||
return models;
|
||||
return this.apiFetch(missingIds)
|
||||
.then(function (apiResults) {
|
||||
Object.keys(apiResults).forEach(function (k) {
|
||||
models[k] = apiResults[k];
|
||||
});
|
||||
|
||||
return models;
|
||||
});
|
||||
}.bind(this));
|
||||
};
|
||||
|
||||
|
@ -110,7 +110,7 @@ class ActionsAPI extends EventEmitter {
|
||||
return actionsObject;
|
||||
}
|
||||
|
||||
_groupAndSortActions(actionsArray = []) {
|
||||
_groupAndSortActions(actionsArray) {
|
||||
if (!Array.isArray(actionsArray) && typeof actionsArray === 'object') {
|
||||
actionsArray = Object.keys(actionsArray).map(key => actionsArray[key]);
|
||||
}
|
||||
|
@ -1,2 +0,0 @@
|
||||
export default class ConflictError extends Error {
|
||||
}
|
@ -26,7 +26,6 @@ import RootRegistry from './RootRegistry';
|
||||
import RootObjectProvider from './RootObjectProvider';
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import InterceptorRegistry from './InterceptorRegistry';
|
||||
import ConflictError from './ConflictError';
|
||||
|
||||
/**
|
||||
* Utilities for loading, saving, and manipulating domain objects.
|
||||
@ -35,7 +34,6 @@ import ConflictError from './ConflictError';
|
||||
*/
|
||||
|
||||
function ObjectAPI(typeRegistry, openmct) {
|
||||
this.openmct = openmct;
|
||||
this.typeRegistry = typeRegistry;
|
||||
this.eventEmitter = new EventEmitter();
|
||||
this.providers = {};
|
||||
@ -49,10 +47,6 @@ function ObjectAPI(typeRegistry, openmct) {
|
||||
this.interceptorRegistry = new InterceptorRegistry();
|
||||
|
||||
this.SYNCHRONIZED_OBJECT_TYPES = ['notebook', 'plan'];
|
||||
|
||||
this.errors = {
|
||||
Conflict: ConflictError
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@ -187,17 +181,8 @@ ObjectAPI.prototype.get = function (identifier, abortSignal) {
|
||||
|
||||
let objectPromise = provider.get(identifier, abortSignal).then(result => {
|
||||
delete this.cache[keystring];
|
||||
|
||||
result = this.applyGetInterceptors(identifier, result);
|
||||
|
||||
return result;
|
||||
}).catch((result) => {
|
||||
console.warn(`Failed to retrieve ${keystring}:`, result);
|
||||
|
||||
delete this.cache[keystring];
|
||||
|
||||
result = this.applyGetInterceptors(identifier);
|
||||
|
||||
return result;
|
||||
});
|
||||
|
||||
@ -300,7 +285,6 @@ ObjectAPI.prototype.isPersistable = function (idOrKeyString) {
|
||||
ObjectAPI.prototype.save = function (domainObject) {
|
||||
let provider = this.getProvider(domainObject.identifier);
|
||||
let savedResolve;
|
||||
let savedReject;
|
||||
let result;
|
||||
|
||||
if (!this.isPersistable(domainObject.identifier)) {
|
||||
@ -310,18 +294,14 @@ ObjectAPI.prototype.save = function (domainObject) {
|
||||
} else {
|
||||
const persistedTime = Date.now();
|
||||
if (domainObject.persisted === undefined) {
|
||||
result = new Promise((resolve, reject) => {
|
||||
result = new Promise((resolve) => {
|
||||
savedResolve = resolve;
|
||||
savedReject = reject;
|
||||
});
|
||||
domainObject.persisted = persistedTime;
|
||||
provider.create(domainObject)
|
||||
.then((response) => {
|
||||
this.mutate(domainObject, 'persisted', persistedTime);
|
||||
savedResolve(response);
|
||||
}).catch((error) => {
|
||||
savedReject(error);
|
||||
});
|
||||
provider.create(domainObject).then((response) => {
|
||||
this.mutate(domainObject, 'persisted', persistedTime);
|
||||
savedResolve(response);
|
||||
});
|
||||
} else {
|
||||
domainObject.persisted = persistedTime;
|
||||
this.mutate(domainObject, 'persisted', persistedTime);
|
||||
|
@ -483,10 +483,6 @@ define([
|
||||
* @returns {Object<String, {TelemetryValueFormatter}>}
|
||||
*/
|
||||
TelemetryAPI.prototype.getFormatMap = function (metadata) {
|
||||
if (!metadata) {
|
||||
return {};
|
||||
}
|
||||
|
||||
if (!this.formatMapCache.has(metadata)) {
|
||||
const formatMap = metadata.values().reduce(function (map, valueMetadata) {
|
||||
map[valueMetadata.key] = this.getValueFormatter(valueMetadata);
|
||||
|
@ -130,13 +130,8 @@ export class TelemetryCollection extends EventEmitter {
|
||||
this.options.onPartialResponse = this._processNewTelemetry.bind(this);
|
||||
|
||||
try {
|
||||
if (this.requestAbort) {
|
||||
this.requestAbort.abort();
|
||||
}
|
||||
|
||||
this.requestAbort = new AbortController();
|
||||
this.options.signal = this.requestAbort.signal;
|
||||
this.emit('requestStarted');
|
||||
historicalData = await this.historicalProvider.request(this.domainObject, this.options);
|
||||
} catch (error) {
|
||||
if (error.name !== 'AbortError') {
|
||||
@ -145,7 +140,6 @@ export class TelemetryCollection extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
this.emit('requestEnded');
|
||||
this.requestAbort = undefined;
|
||||
|
||||
this._processNewTelemetry(historicalData);
|
||||
|
@ -41,6 +41,7 @@ const DEFAULTS = [
|
||||
'platform/forms',
|
||||
'platform/identity',
|
||||
'platform/persistence/aggregator',
|
||||
'platform/persistence/queue',
|
||||
'platform/policy',
|
||||
'platform/entanglement',
|
||||
'platform/search',
|
||||
|
@ -32,7 +32,7 @@ describe('the plugin', function () {
|
||||
let openmct;
|
||||
let composition;
|
||||
|
||||
beforeEach(() => {
|
||||
beforeEach((done) => {
|
||||
|
||||
openmct = createOpenMct();
|
||||
|
||||
@ -47,6 +47,11 @@ describe('the plugin', function () {
|
||||
}
|
||||
}));
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
|
||||
composition = openmct.composition.get({identifier});
|
||||
|
||||
spyOn(couchPlugin.couchProvider, 'getObjectsByFilter').and.returnValue(Promise.resolve([
|
||||
{
|
||||
identifier: {
|
||||
@ -61,19 +66,6 @@ describe('the plugin', function () {
|
||||
}
|
||||
}
|
||||
]));
|
||||
|
||||
spyOn(couchPlugin.couchProvider, "get").and.callFake((id) => {
|
||||
return Promise.resolve({
|
||||
identifier: id
|
||||
});
|
||||
});
|
||||
|
||||
return new Promise((resolve) => {
|
||||
openmct.once('start', resolve);
|
||||
openmct.startHeadless();
|
||||
}).then(() => {
|
||||
composition = openmct.composition.get({identifier});
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
|
@ -96,11 +96,11 @@ export default {
|
||||
|
||||
this.timestampKey = this.openmct.time.timeSystem().key;
|
||||
|
||||
this.valueMetadata = this.metadata ? this
|
||||
this.valueMetadata = this
|
||||
.metadata
|
||||
.valuesForHints(['range'])[0] : undefined;
|
||||
.valuesForHints(['range'])[0];
|
||||
|
||||
this.valueKey = this.valueMetadata ? this.valueMetadata.key : undefined;
|
||||
this.valueKey = this.valueMetadata.key;
|
||||
|
||||
this.unsubscribe = this.openmct
|
||||
.telemetry
|
||||
@ -151,10 +151,7 @@ export default {
|
||||
size: 1,
|
||||
strategy: 'latest'
|
||||
})
|
||||
.then((array) => this.updateValues(array[array.length - 1]))
|
||||
.catch((error) => {
|
||||
console.warn('Error fetching data', error);
|
||||
});
|
||||
.then((array) => this.updateValues(array[array.length - 1]));
|
||||
},
|
||||
updateBounds(bounds, isTick) {
|
||||
this.bounds = bounds;
|
||||
|
@ -73,9 +73,8 @@ export default {
|
||||
hasUnits() {
|
||||
let itemsWithUnits = this.items.filter((item) => {
|
||||
let metadata = this.openmct.telemetry.getMetadata(item.domainObject);
|
||||
const valueMetadatas = metadata ? metadata.valueMetadatas : [];
|
||||
|
||||
return this.metadataHasUnits(valueMetadatas);
|
||||
return this.metadataHasUnits(metadata.valueMetadatas);
|
||||
|
||||
});
|
||||
|
||||
|
@ -23,24 +23,20 @@
|
||||
import { BAR_GRAPH_KEY } from './BarGraphConstants';
|
||||
|
||||
export default function BarGraphCompositionPolicy(openmct) {
|
||||
function hasAggregateDomainAndRange(metadata) {
|
||||
function hasRange(metadata) {
|
||||
const rangeValues = metadata.valuesForHints(['range']);
|
||||
|
||||
return rangeValues.length > 0;
|
||||
}
|
||||
|
||||
function hasBarGraphTelemetry(domainObject) {
|
||||
if (!Object.prototype.hasOwnProperty.call(domainObject, 'telemetry')) {
|
||||
if (!openmct.telemetry.isTelemetryObject(domainObject)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let metadata = openmct.telemetry.getMetadata(domainObject);
|
||||
|
||||
return metadata.values().length > 0 && hasAggregateDomainAndRange(metadata);
|
||||
}
|
||||
|
||||
function hasNoChildren(parentObject) {
|
||||
return parentObject.composition && parentObject.composition.length < 1;
|
||||
return metadata.values().length > 0 && hasRange(metadata);
|
||||
}
|
||||
|
||||
return {
|
@ -1,5 +1,3 @@
|
||||
export const BAR_GRAPH_VIEW = 'bar-graph.view';
|
||||
export const BAR_GRAPH_KEY = 'telemetry.plot.bar-graph';
|
||||
export const BAR_GRAPH_INSPECTOR_KEY = 'telemetry.plot.bar-graph.inspector';
|
||||
export const SUBSCRIBE = 'subscribe';
|
||||
export const UNSUBSCRIBE = 'unsubscribe';
|
@ -12,6 +12,7 @@
|
||||
</div>
|
||||
<div ref="plot"
|
||||
class="c-bar-chart"
|
||||
@plotly_relayout="zoom"
|
||||
></div>
|
||||
<div v-if="false"
|
||||
ref="localControl"
|
||||
@ -28,8 +29,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Plotly from 'plotly.js-basic-dist';
|
||||
import { SUBSCRIBE, UNSUBSCRIBE } from './BarGraphConstants';
|
||||
import Plotly from 'plotly-basic';
|
||||
|
||||
const MULTI_AXES_X_PADDING_PERCENT = {
|
||||
LEFT: 8,
|
||||
@ -79,8 +79,6 @@ export default {
|
||||
this.registerListeners();
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$refs.plot.removeAllListeners();
|
||||
|
||||
if (this.plotResizeObserver) {
|
||||
this.plotResizeObserver.unobserve(this.$refs.plotWrapper);
|
||||
clearTimeout(this.resizeTimer);
|
||||
@ -203,8 +201,6 @@ export default {
|
||||
return yaxis;
|
||||
},
|
||||
registerListeners() {
|
||||
this.$refs.plot.on('plotly_relayout', this.zoom);
|
||||
|
||||
this.removeBarColorListener = this.openmct.objects.observe(
|
||||
this.domainObject,
|
||||
'configuration.barStyles',
|
||||
@ -226,7 +222,7 @@ export default {
|
||||
this.updatePlot();
|
||||
|
||||
this.isZoomed = false;
|
||||
this.$emit(SUBSCRIBE);
|
||||
this.$emit('subscribe');
|
||||
},
|
||||
barColorChanged() {
|
||||
const colors = [];
|
||||
@ -285,7 +281,7 @@ export default {
|
||||
}
|
||||
|
||||
this.isZoomed = true;
|
||||
this.$emit(UNSUBSCRIBE);
|
||||
this.$emit('unsubscribe');
|
||||
}
|
||||
}
|
||||
};
|
@ -25,12 +25,13 @@
|
||||
class="c-plot c-bar-chart-view"
|
||||
:data="trace"
|
||||
:plot-axis-title="plotAxisTitle"
|
||||
@subscribe="subscribeToAll"
|
||||
@unsubscribe="removeAllSubscriptions"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import * as SPECTRAL_AGGREGATE from './BarGraphConstants';
|
||||
import ColorPalette from '../lib/ColorPalette';
|
||||
import ColorPalette from '../../plot/lib/ColorPalette';
|
||||
import BarGraph from './BarGraphPlot.vue';
|
||||
import Color from "@/plugins/plot/lib/Color";
|
||||
|
||||
@ -40,18 +41,16 @@ export default {
|
||||
},
|
||||
inject: ['openmct', 'domainObject'],
|
||||
data() {
|
||||
this.telemetryObjects = {};
|
||||
this.telemetryObjectFormats = {};
|
||||
this.subscriptions = [];
|
||||
this.composition = {};
|
||||
|
||||
return {
|
||||
composition: {},
|
||||
currentDomainObject: this.domainObject,
|
||||
subscriptions: [],
|
||||
telemetryObjects: {},
|
||||
trace: []
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
activeClock() {
|
||||
return this.openmct.time.activeClock;
|
||||
},
|
||||
plotAxisTitle() {
|
||||
const { xAxisMetadata = {}, yAxisMetadata = {} } = this.trace[0] || {};
|
||||
const xAxisUnit = xAxisMetadata.units ? `(${xAxisMetadata.units})` : '';
|
||||
@ -68,20 +67,11 @@ export default {
|
||||
this.loadComposition();
|
||||
|
||||
this.openmct.time.on('bounds', this.refreshData);
|
||||
this.openmct.time.on('clock', this.clockChanged);
|
||||
|
||||
this.$refs.barGraph.$on(SPECTRAL_AGGREGATE.SUBSCRIBE, this.subscribeToAll);
|
||||
this.$refs.barGraph.$on(SPECTRAL_AGGREGATE.UNSUBSCRIBE, this.removeAllSubscriptions);
|
||||
|
||||
this.unobserve = this.openmct.objects.observe(this.currentDomainObject, '*', this.updateDomainObject);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.$refs.barGraph.$off();
|
||||
this.openmct.time.off('bounds', this.refreshData);
|
||||
this.openmct.time.off('clock', this.clockChanged);
|
||||
|
||||
this.removeAllSubscriptions();
|
||||
this.unobserve();
|
||||
|
||||
if (!this.composition) {
|
||||
return;
|
||||
@ -94,21 +84,16 @@ export default {
|
||||
addTelemetryObject(telemetryObject) {
|
||||
const key = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||
|
||||
if (!this.domainObject.configuration.barStyles) {
|
||||
this.domainObject.configuration.barStyles = {};
|
||||
}
|
||||
|
||||
// check to see if we've set a bar color
|
||||
if (!this.domainObject.configuration.barStyles[key] || !this.domainObject.configuration.barStyles[key].color) {
|
||||
const color = this.colorPalette.getNextColor().asHexString();
|
||||
this.domainObject.configuration.barStyles[key] = {
|
||||
name: telemetryObject.name,
|
||||
color
|
||||
};
|
||||
this.openmct.objects.mutate(
|
||||
this.domainObject,
|
||||
`configuration.barStyles[${key}]`,
|
||||
this.domainObject.configuration.barStyles[key]
|
||||
{
|
||||
name: telemetryObject.name,
|
||||
color
|
||||
}
|
||||
);
|
||||
} else {
|
||||
let color = this.domainObject.configuration.barStyles[key].color;
|
||||
@ -120,6 +105,9 @@ export default {
|
||||
}
|
||||
|
||||
this.telemetryObjects[key] = telemetryObject;
|
||||
const metadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
const formats = this.openmct.telemetry.getFormatMap(metadata);
|
||||
this.telemetryObjectFormats[key] = formats;
|
||||
|
||||
this.requestDataFor(telemetryObject);
|
||||
this.subscribeToObject(telemetryObject);
|
||||
@ -144,16 +132,8 @@ export default {
|
||||
|
||||
this.trace = isInTrace ? newTrace : newTrace.concat([trace]);
|
||||
},
|
||||
clockChanged() {
|
||||
this.removeAllSubscriptions();
|
||||
this.subscribeToAll();
|
||||
},
|
||||
getAxisMetadata(telemetryObject) {
|
||||
const metadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
if (!metadata) {
|
||||
return {};
|
||||
}
|
||||
|
||||
const yAxisMetadata = metadata.valuesForHints(['range'])[0];
|
||||
//Exclude 'name' and 'time' based metadata specifically, from the x-Axis values by using range hints only
|
||||
const xAxisMetadata = metadata.valuesForHints(['range']);
|
||||
@ -163,21 +143,19 @@ export default {
|
||||
yAxisMetadata
|
||||
};
|
||||
},
|
||||
getOptions(telemetryObject) {
|
||||
getOptions() {
|
||||
const { start, end } = this.openmct.time.bounds();
|
||||
|
||||
return {
|
||||
end,
|
||||
start,
|
||||
startTime: null,
|
||||
spectra: true
|
||||
start
|
||||
};
|
||||
},
|
||||
loadComposition() {
|
||||
this.composition = this.openmct.composition.get(this.currentDomainObject);
|
||||
this.composition = this.openmct.composition.get(this.domainObject);
|
||||
|
||||
if (!this.composition) {
|
||||
this.addTelemetryObject(this.currentDomainObject);
|
||||
this.addTelemetryObject(this.domainObject);
|
||||
|
||||
return;
|
||||
}
|
||||
@ -206,6 +184,7 @@ export default {
|
||||
removeTelemetryObject(identifier) {
|
||||
const key = this.openmct.objects.makeKeyString(identifier);
|
||||
delete this.telemetryObjects[key];
|
||||
delete this.this.telemetryObjectFormats[key];
|
||||
if (this.domainObject.configuration.barStyles[key]) {
|
||||
delete this.domainObject.configuration.barStyles[key];
|
||||
}
|
||||
@ -214,13 +193,17 @@ export default {
|
||||
|
||||
this.trace = this.trace.filter(t => t.key !== key);
|
||||
},
|
||||
processData(telemetryObject, data, axisMetadata) {
|
||||
addDataToGraph(telemetryObject, data, axisMetadata) {
|
||||
const key = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||
|
||||
if (data.message) {
|
||||
this.openmct.notifications.alert(data.message);
|
||||
}
|
||||
|
||||
if (!this.isDataInTimeRange(data)) {
|
||||
return;
|
||||
}
|
||||
|
||||
let xValues = [];
|
||||
let yValues = [];
|
||||
|
||||
@ -228,10 +211,10 @@ export default {
|
||||
axisMetadata.xAxisMetadata.forEach((metadata) => {
|
||||
xValues.push(metadata.name);
|
||||
if (data[metadata.key]) {
|
||||
//TODO: Format the data?
|
||||
yValues.push(data[metadata.key]);
|
||||
const formattedValue = this.format(key, metadata.key, data);
|
||||
yValues.push(formattedValue);
|
||||
} else {
|
||||
yValues.push('');
|
||||
yValues.push(null);
|
||||
}
|
||||
});
|
||||
|
||||
@ -252,16 +235,24 @@ export default {
|
||||
|
||||
this.addTrace(trace, key);
|
||||
},
|
||||
isDataInTimeRange(data) {
|
||||
const timeSystemKey = this.openmct.time.timeSystem().key;
|
||||
const currentTimestamp = data[timeSystemKey];
|
||||
|
||||
return currentTimestamp && this.openmct.time.bounds().end >= currentTimestamp;
|
||||
},
|
||||
format(telemetryObjectKey, metadataKey, data) {
|
||||
const formats = this.telemetryObjectFormats[telemetryObjectKey];
|
||||
|
||||
return formats[metadataKey].format(data);
|
||||
},
|
||||
requestDataFor(telemetryObject) {
|
||||
const axisMetadata = this.getAxisMetadata(telemetryObject);
|
||||
this.openmct.telemetry.request(telemetryObject, this.getOptions(telemetryObject))
|
||||
this.openmct.telemetry.request(telemetryObject)
|
||||
.then(data => {
|
||||
data.forEach((datum) => {
|
||||
this.processData(telemetryObject, datum, axisMetadata);
|
||||
this.addDataToGraph(telemetryObject, datum, axisMetadata);
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
console.warn(`Error fetching data`, error);
|
||||
});
|
||||
},
|
||||
subscribeToObject(telemetryObject) {
|
||||
@ -269,10 +260,10 @@ export default {
|
||||
|
||||
this.removeSubscription(key);
|
||||
|
||||
const options = this.getOptions(telemetryObject);
|
||||
const options = this.getOptions();
|
||||
const axisMetadata = this.getAxisMetadata(telemetryObject);
|
||||
const unsubscribe = this.openmct.telemetry.subscribe(telemetryObject,
|
||||
data => this.processData(telemetryObject, data, axisMetadata)
|
||||
data => this.addDataToGraph(telemetryObject, data, axisMetadata)
|
||||
, options);
|
||||
|
||||
this.subscriptions.push({
|
||||
@ -283,9 +274,6 @@ export default {
|
||||
subscribeToAll() {
|
||||
const telemetryObjects = Object.values(this.telemetryObjects);
|
||||
telemetryObjects.forEach(this.subscribeToObject);
|
||||
},
|
||||
updateDomainObject(newDomainObject) {
|
||||
this.currentDomainObject = newDomainObject;
|
||||
}
|
||||
}
|
||||
};
|
@ -33,9 +33,9 @@
|
||||
</li>
|
||||
<ColorSwatch v-if="expanded"
|
||||
:current-color="currentColor"
|
||||
title="Manually set the color for this bar graph series."
|
||||
edit-title="Manually set the color for this bar graph series"
|
||||
view-title="The color for this bar graph series."
|
||||
title="Manually set the color for this bar graph."
|
||||
edit-title="Manually set the color for this bar graph"
|
||||
view-title="The color for this bar graph."
|
||||
short-label="Color"
|
||||
class="grid-properties"
|
||||
@colorSet="setColor"
|
||||
@ -44,7 +44,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ColorSwatch from '../../ColorSwatch.vue';
|
||||
import ColorSwatch from '../../../plot/ColorSwatch.vue';
|
||||
|
||||
export default {
|
||||
components: {
|
@ -20,13 +20,15 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<template>
|
||||
<ul class="c-tree">
|
||||
<h2 title="Display properties for this object">Bar Graph Series</h2>
|
||||
<bar-graph-options v-for="series in domainObject.composition"
|
||||
:key="series.key"
|
||||
:item="series"
|
||||
/>
|
||||
</ul>
|
||||
<div>
|
||||
<ul class="c-tree">
|
||||
<li v-for="series in domainObject.composition"
|
||||
:key="series.key"
|
||||
>
|
||||
<bar-graph-options :item="series" />
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
49
src/plugins/charts/plugin.js
Normal file
49
src/plugins/charts/plugin.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*****************************************************************************
|
||||
* 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 { BAR_GRAPH_KEY } from '../charts/barGraph/BarGraphConstants';
|
||||
import BarGraphViewProvider from '../charts/barGraph/BarGraphViewProvider';
|
||||
import BarGraphInspectorViewProvider from '../charts/barGraph/inspector/BarGraphInspectorViewProvider';
|
||||
import BarGraphCompositionPolicy from '../charts/barGraph/BarGraphCompositionPolicy';
|
||||
|
||||
export default function () {
|
||||
return function install(openmct) {
|
||||
openmct.types.addType(BAR_GRAPH_KEY, {
|
||||
key: BAR_GRAPH_KEY,
|
||||
name: "Bar Graph",
|
||||
cssClass: "icon-bar-chart",
|
||||
description: "View data as a bar graph. Can be added to Display Layouts.",
|
||||
creatable: true,
|
||||
initialize: function (domainObject) {
|
||||
domainObject.composition = [];
|
||||
domainObject.configuration = {
|
||||
barStyles: {}
|
||||
};
|
||||
},
|
||||
priority: 891
|
||||
});
|
||||
|
||||
openmct.objectViews.addProvider(new BarGraphViewProvider(openmct));
|
||||
openmct.inspectorViews.addProvider(new BarGraphInspectorViewProvider(openmct));
|
||||
openmct.composition.addPolicy(new BarGraphCompositionPolicy(openmct).allow);
|
||||
};
|
||||
}
|
||||
|
151
src/plugins/charts/pluginSpec.js
Normal file
151
src/plugins/charts/pluginSpec.js
Normal file
@ -0,0 +1,151 @@
|
||||
/*****************************************************************************
|
||||
* 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 {createOpenMct, resetApplicationState} from "utils/testing";
|
||||
import { BAR_GRAPH_VIEW, BAR_GRAPH_KEY } from '../charts/barGraph/BarGraphConstants';
|
||||
import BarGraphPlugin from './plugin';
|
||||
|
||||
describe("the plugin", function () {
|
||||
let element;
|
||||
let child;
|
||||
let openmct;
|
||||
let telemetryPromise;
|
||||
let telemetryPromiseResolve;
|
||||
let mockObjectPath;
|
||||
|
||||
beforeEach((done) => {
|
||||
mockObjectPath = [
|
||||
{
|
||||
name: 'mock folder',
|
||||
type: 'fake-folder',
|
||||
identifier: {
|
||||
key: 'mock-folder',
|
||||
namespace: ''
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'mock parent folder',
|
||||
type: 'time-strip',
|
||||
identifier: {
|
||||
key: 'mock-parent-folder',
|
||||
namespace: ''
|
||||
}
|
||||
}
|
||||
];
|
||||
const testTelemetry = [
|
||||
{
|
||||
'utc': 1,
|
||||
'some-key': 'some-value 1',
|
||||
'some-other-key': 'some-other-value 1'
|
||||
},
|
||||
{
|
||||
'utc': 2,
|
||||
'some-key': 'some-value 2',
|
||||
'some-other-key': 'some-other-value 2'
|
||||
},
|
||||
{
|
||||
'utc': 3,
|
||||
'some-key': 'some-value 3',
|
||||
'some-other-key': 'some-other-value 3'
|
||||
}
|
||||
];
|
||||
|
||||
openmct = createOpenMct();
|
||||
|
||||
telemetryPromise = new Promise((resolve) => {
|
||||
telemetryPromiseResolve = resolve;
|
||||
});
|
||||
|
||||
spyOn(openmct.telemetry, 'request').and.callFake(() => {
|
||||
telemetryPromiseResolve(testTelemetry);
|
||||
|
||||
return telemetryPromise;
|
||||
});
|
||||
|
||||
openmct.install(new BarGraphPlugin());
|
||||
|
||||
element = document.createElement("div");
|
||||
element.style.width = "640px";
|
||||
element.style.height = "480px";
|
||||
child = document.createElement("div");
|
||||
child.style.width = "640px";
|
||||
child.style.height = "480px";
|
||||
element.appendChild(child);
|
||||
document.body.appendChild(element);
|
||||
|
||||
spyOn(window, 'ResizeObserver').and.returnValue({
|
||||
observe() {},
|
||||
disconnect() {}
|
||||
});
|
||||
|
||||
openmct.time.timeSystem("utc", {
|
||||
start: 0,
|
||||
end: 4
|
||||
});
|
||||
|
||||
openmct.types.addType("test-object", {
|
||||
creatable: true
|
||||
});
|
||||
|
||||
openmct.on("start", done);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
||||
afterEach((done) => {
|
||||
openmct.time.timeSystem('utc', {
|
||||
start: 0,
|
||||
end: 1
|
||||
});
|
||||
resetApplicationState(openmct).then(done).catch(done);
|
||||
});
|
||||
|
||||
describe("the bar graph", () => {
|
||||
const mockObject = {
|
||||
name: 'A bar graph',
|
||||
key: BAR_GRAPH_KEY,
|
||||
creatable: true
|
||||
};
|
||||
|
||||
it('defines a bar graph type with the correct key', () => {
|
||||
const objectDef = openmct.types.get(BAR_GRAPH_KEY).definition;
|
||||
expect(objectDef.key).toEqual(mockObject.key);
|
||||
});
|
||||
|
||||
it('is creatable', () => {
|
||||
const objectDef = openmct.types.get(BAR_GRAPH_KEY).definition;
|
||||
expect(objectDef.creatable).toEqual(mockObject.creatable);
|
||||
});
|
||||
});
|
||||
|
||||
describe("the bar graph view", () => {
|
||||
it("provides view for objects with telemetry", () => {
|
||||
const testObject = {
|
||||
id: "test-object",
|
||||
type: BAR_GRAPH_KEY
|
||||
};
|
||||
|
||||
const applicableViews = openmct.objectViews.get(testObject, mockObjectPath);
|
||||
let plotView = applicableViews.find((viewProvider) => viewProvider.key === BAR_GRAPH_VIEW);
|
||||
expect(plotView).toBeDefined();
|
||||
});
|
||||
});
|
||||
});
|
@ -98,8 +98,6 @@ describe('the plugin', function () {
|
||||
|
||||
conditionSetDefinition.initialize(mockConditionSetDomainObject);
|
||||
|
||||
spyOn(openmct.objects, "save").and.returnValue(Promise.resolve(true));
|
||||
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
|
@ -101,7 +101,7 @@ export default {
|
||||
addChildren(domainObject) {
|
||||
let keyString = this.openmct.objects.makeKeyString(domainObject.identifier);
|
||||
let metadata = this.openmct.telemetry.getMetadata(domainObject);
|
||||
let metadataWithFilters = metadata ? metadata.valueMetadatas.filter(value => value.filters) : [];
|
||||
let metadataWithFilters = metadata.valueMetadatas.filter(value => value.filters);
|
||||
let hasFiltersWithKeyString = this.persistedFilters[keyString] !== undefined;
|
||||
let mutateFilters = false;
|
||||
let childObject = {
|
||||
|
@ -159,7 +159,7 @@ export default {
|
||||
let image = { ...datum };
|
||||
image.formattedTime = this.formatTime(datum);
|
||||
image.url = this.formatImageUrl(datum);
|
||||
image.time = this.parseTime(image.formattedTime);
|
||||
image.time = datum[this.timeKey];
|
||||
image.imageDownloadName = this.getImageDownloadName(datum);
|
||||
|
||||
return image;
|
||||
|
@ -180,13 +180,9 @@ export default {
|
||||
this.openmct.notifications.alert(message);
|
||||
}
|
||||
|
||||
if (this.openmct.editor.isEditing()) {
|
||||
this.previewEmbed();
|
||||
} else {
|
||||
const relativeHash = hash.slice(hash.indexOf('#'));
|
||||
const url = new URL(relativeHash, `${location.protocol}//${location.host}${location.pathname}`);
|
||||
this.openmct.router.navigate(url.hash);
|
||||
}
|
||||
const relativeHash = hash.slice(hash.indexOf('#'));
|
||||
const url = new URL(relativeHash, `${location.protocol}//${location.host}${location.pathname}`);
|
||||
this.openmct.router.navigate(url.hash);
|
||||
},
|
||||
formatTime(unixTime, timeFormat) {
|
||||
return Moment.utc(unixTime).format(timeFormat);
|
||||
|
@ -1,72 +0,0 @@
|
||||
import {NOTEBOOK_TYPE} from './notebook-constants';
|
||||
|
||||
export default function (openmct) {
|
||||
const apiSave = openmct.objects.save.bind(openmct.objects);
|
||||
|
||||
openmct.objects.save = async (domainObject) => {
|
||||
if (domainObject.type !== NOTEBOOK_TYPE) {
|
||||
return apiSave(domainObject);
|
||||
}
|
||||
|
||||
const localMutable = openmct.objects._toMutable(domainObject);
|
||||
let result;
|
||||
|
||||
try {
|
||||
result = await apiSave(localMutable);
|
||||
} catch (error) {
|
||||
if (error instanceof openmct.objects.errors.Conflict) {
|
||||
result = resolveConflicts(localMutable, openmct);
|
||||
} else {
|
||||
result = Promise.reject(error);
|
||||
}
|
||||
} finally {
|
||||
openmct.objects.destroyMutable(localMutable);
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
}
|
||||
|
||||
function resolveConflicts(localMutable, openmct) {
|
||||
return openmct.objects.getMutable(localMutable.identifier).then((remoteMutable) => {
|
||||
const localEntries = localMutable.configuration.entries;
|
||||
remoteMutable.$refresh(remoteMutable);
|
||||
applyLocalEntries(remoteMutable, localEntries);
|
||||
|
||||
openmct.objects.destroyMutable(remoteMutable);
|
||||
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
function applyLocalEntries(mutable, entries) {
|
||||
Object.entries(entries).forEach(([sectionKey, pagesInSection]) => {
|
||||
Object.entries(pagesInSection).forEach(([pageKey, localEntries]) => {
|
||||
const remoteEntries = mutable.configuration.entries[sectionKey][pageKey];
|
||||
const mergedEntries = [].concat(remoteEntries);
|
||||
let shouldMutate = false;
|
||||
|
||||
const locallyAddedEntries = _.differenceBy(localEntries, remoteEntries, 'id');
|
||||
const locallyModifiedEntries = _.differenceWith(localEntries, remoteEntries, (localEntry, remoteEntry) => {
|
||||
return localEntry.id === remoteEntry.id && localEntry.text === remoteEntry.text;
|
||||
});
|
||||
|
||||
locallyAddedEntries.forEach((localEntry) => {
|
||||
mergedEntries.push(localEntry);
|
||||
shouldMutate = true;
|
||||
});
|
||||
|
||||
locallyModifiedEntries.forEach((locallyModifiedEntry) => {
|
||||
let mergedEntry = mergedEntries.find(entry => entry.id === locallyModifiedEntry.id);
|
||||
if (mergedEntry !== undefined) {
|
||||
mergedEntry.text = locallyModifiedEntry.text;
|
||||
shouldMutate = true;
|
||||
}
|
||||
});
|
||||
|
||||
if (shouldMutate) {
|
||||
mutable.$set(`configuration.entries.${sectionKey}.${pageKey}`, mergedEntries);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
@ -2,7 +2,6 @@ import CopyToNotebookAction from './actions/CopyToNotebookAction';
|
||||
import Notebook from './components/Notebook.vue';
|
||||
import NotebookSnapshotIndicator from './components/NotebookSnapshotIndicator.vue';
|
||||
import SnapshotContainer from './snapshot-container';
|
||||
import monkeyPatchObjectAPIForNotebooks from './monkeyPatchObjectAPIForNotebooks.js';
|
||||
|
||||
import { notebookImageMigration } from '../notebook/utils/notebook-migration';
|
||||
import { NOTEBOOK_TYPE } from './notebook-constants';
|
||||
@ -166,7 +165,5 @@ export default function NotebookPlugin() {
|
||||
return domainObject;
|
||||
}
|
||||
});
|
||||
|
||||
monkeyPatchObjectAPIForNotebooks(openmct);
|
||||
};
|
||||
}
|
||||
|
@ -154,8 +154,6 @@ describe("Notebook plugin:", () => {
|
||||
testObjectProvider.get.and.returnValue(Promise.resolve(notebookViewObject));
|
||||
openmct.objects.addProvider('test-namespace', testObjectProvider);
|
||||
testObjectProvider.observe.and.returnValue(() => {});
|
||||
testObjectProvider.create.and.returnValue(Promise.resolve(true));
|
||||
testObjectProvider.update.and.returnValue(Promise.resolve(true));
|
||||
|
||||
return openmct.objects.getMutable(notebookViewObject.identifier).then((mutableObject) => {
|
||||
mutableNotebookObject = mutableObject;
|
||||
|
@ -125,7 +125,7 @@ export function addNotebookEntry(openmct, domainObject, notebookStorage, embed =
|
||||
const newEntries = addEntryIntoPage(notebookStorage, entries, entry);
|
||||
|
||||
addDefaultClass(domainObject, openmct);
|
||||
domainObject.configuration.entries = newEntries;
|
||||
openmct.objects.mutate(domainObject, 'configuration.entries', newEntries);
|
||||
|
||||
return id;
|
||||
}
|
||||
|
@ -15,16 +15,12 @@
|
||||
|
||||
port.onmessage = async function (event) {
|
||||
if (event.data.request === 'close') {
|
||||
console.log('Closing connection');
|
||||
connections.splice(event.data.connectionId - 1, 1);
|
||||
if (connections.length <= 0) {
|
||||
// abort any outstanding requests if there's nobody listening to it.
|
||||
controller.abort();
|
||||
}
|
||||
|
||||
console.log('Closed.');
|
||||
connected = false;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@ -33,9 +29,68 @@
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
await self.listenForChanges(event.data.url, event.data.body, port);
|
||||
} while (connected);
|
||||
connected = true;
|
||||
|
||||
let url = event.data.url;
|
||||
let body = event.data.body;
|
||||
let error = false;
|
||||
// feed=continuous maintains an indefinitely open connection with a keep-alive of HEARTBEAT milliseconds until this client closes the connection
|
||||
// style=main_only returns only the current winning revision of the document
|
||||
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": 'application/json'
|
||||
},
|
||||
signal,
|
||||
body
|
||||
});
|
||||
|
||||
let reader;
|
||||
|
||||
if (response.body === undefined) {
|
||||
error = true;
|
||||
} else {
|
||||
reader = response.body.getReader();
|
||||
}
|
||||
|
||||
while (!error) {
|
||||
const {done, value} = await reader.read();
|
||||
//done is true when we lose connection with the provider
|
||||
if (done) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
let chunk = new Uint8Array(value.length);
|
||||
chunk.set(value, 0);
|
||||
const decodedChunk = new TextDecoder("utf-8").decode(chunk).split('\n');
|
||||
if (decodedChunk.length && decodedChunk[decodedChunk.length - 1] === '') {
|
||||
decodedChunk.forEach((doc, index) => {
|
||||
try {
|
||||
if (doc) {
|
||||
const objectChanges = JSON.parse(doc);
|
||||
connections.forEach(function (connection) {
|
||||
connection.postMessage({
|
||||
objectChanges
|
||||
});
|
||||
});
|
||||
}
|
||||
} catch (decodeError) {
|
||||
//do nothing;
|
||||
console.log(decodeError);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (error) {
|
||||
port.postMessage({
|
||||
error
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@ -48,64 +103,4 @@
|
||||
console.log('Error on feed');
|
||||
};
|
||||
|
||||
self.listenForChanges = async function (url, body, port) {
|
||||
connected = true;
|
||||
let error = false;
|
||||
// feed=continuous maintains an indefinitely open connection with a keep-alive of HEARTBEAT milliseconds until this client closes the connection
|
||||
// style=main_only returns only the current winning revision of the document
|
||||
|
||||
console.log('Opening changes feed connection.');
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
"Content-Type": 'application/json'
|
||||
},
|
||||
signal,
|
||||
body
|
||||
});
|
||||
|
||||
let reader;
|
||||
|
||||
if (response.body === undefined) {
|
||||
error = true;
|
||||
} else {
|
||||
reader = response.body.getReader();
|
||||
}
|
||||
|
||||
while (!error) {
|
||||
const {done, value} = await reader.read();
|
||||
//done is true when we lose connection with the provider
|
||||
if (done) {
|
||||
error = true;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
let chunk = new Uint8Array(value.length);
|
||||
chunk.set(value, 0);
|
||||
const decodedChunk = new TextDecoder("utf-8").decode(chunk).split('\n');
|
||||
console.log('Received chunk');
|
||||
if (decodedChunk.length && decodedChunk[decodedChunk.length - 1] === '') {
|
||||
decodedChunk.forEach((doc, index) => {
|
||||
try {
|
||||
if (doc) {
|
||||
const objectChanges = JSON.parse(doc);
|
||||
connections.forEach(function (connection) {
|
||||
connection.postMessage({
|
||||
objectChanges
|
||||
});
|
||||
});
|
||||
}
|
||||
} catch (decodeError) {
|
||||
//do nothing;
|
||||
console.log(decodeError);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
console.log('Done reading changes feed');
|
||||
};
|
||||
|
||||
}());
|
||||
|
@ -29,7 +29,7 @@ const ID = "_id";
|
||||
const HEARTBEAT = 50000;
|
||||
const ALL_DOCS = "_all_docs?include_docs=true";
|
||||
|
||||
class CouchObjectProvider {
|
||||
export default class CouchObjectProvider {
|
||||
constructor(openmct, options, namespace) {
|
||||
options = this._normalize(options);
|
||||
this.openmct = openmct;
|
||||
@ -74,6 +74,13 @@ class CouchObjectProvider {
|
||||
if (event.data.type === 'connection') {
|
||||
this.changesFeedSharedWorkerConnectionId = event.data.connectionId;
|
||||
} else {
|
||||
const error = event.data.error;
|
||||
if (error && Object.keys(this.observers).length > 0) {
|
||||
this.observeObjectChanges();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
let objectChanges = event.data.objectChanges;
|
||||
objectChanges.identifier = {
|
||||
namespace: this.namespace,
|
||||
@ -119,12 +126,11 @@ class CouchObjectProvider {
|
||||
}
|
||||
|
||||
return fetch(this.url + '/' + subPath, fetchOptions)
|
||||
.then((response) => {
|
||||
if (response.status === CouchObjectProvider.HTTP_CONFLICT) {
|
||||
throw new this.openmct.objects.errors.Conflict(`Conflict persisting ${fetchOptions.body.name}`);
|
||||
}
|
||||
|
||||
return response.json();
|
||||
.then(response => response.json())
|
||||
.then(function (response) {
|
||||
return response;
|
||||
}, function () {
|
||||
return undefined;
|
||||
});
|
||||
}
|
||||
|
||||
@ -555,18 +561,12 @@ class CouchObjectProvider {
|
||||
let intermediateResponse = this.getIntermediateResponse();
|
||||
const key = model.identifier.key;
|
||||
this.enqueueObject(key, model, intermediateResponse);
|
||||
if (!this.objectQueue[key].pending) {
|
||||
this.objectQueue[key].pending = true;
|
||||
const queued = this.objectQueue[key].dequeue();
|
||||
let document = new CouchDocument(key, queued.model);
|
||||
this.request(key, "PUT", document).then((response) => {
|
||||
console.log('create check response', key);
|
||||
this.checkResponse(response, queued.intermediateResponse, key);
|
||||
}).catch(error => {
|
||||
queued.intermediateResponse.reject(error);
|
||||
this.objectQueue[key].pending = false;
|
||||
});
|
||||
}
|
||||
this.objectQueue[key].pending = true;
|
||||
const queued = this.objectQueue[key].dequeue();
|
||||
let document = new CouchDocument(key, queued.model);
|
||||
this.request(key, "PUT", document).then((response) => {
|
||||
this.checkResponse(response, queued.intermediateResponse, key);
|
||||
});
|
||||
|
||||
return intermediateResponse.promise;
|
||||
}
|
||||
@ -581,9 +581,6 @@ class CouchObjectProvider {
|
||||
let document = new CouchDocument(key, queued.model, this.objectQueue[key].rev);
|
||||
this.request(key, "PUT", document).then((response) => {
|
||||
this.checkResponse(response, queued.intermediateResponse, key);
|
||||
}).catch((error) => {
|
||||
queued.intermediateResponse.reject(error);
|
||||
this.objectQueue[key].pending = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -597,7 +594,3 @@ class CouchObjectProvider {
|
||||
return intermediateResponse.promise;
|
||||
}
|
||||
}
|
||||
|
||||
CouchObjectProvider.HTTP_CONFLICT = 409;
|
||||
|
||||
export default CouchObjectProvider;
|
||||
|
@ -21,57 +21,67 @@
|
||||
-->
|
||||
<template>
|
||||
<div class="u-contents">
|
||||
<div v-if="canEdit"
|
||||
class="grid-row"
|
||||
<ul v-if="canEdit"
|
||||
class="l-inspector-part"
|
||||
>
|
||||
<div class="grid-cell label"
|
||||
:title="editTitle"
|
||||
>{{ shortLabel }}</div>
|
||||
<div class="grid-cell value">
|
||||
<div class="c-click-swatch c-click-swatch--menu"
|
||||
@click="toggleSwatch()"
|
||||
>
|
||||
<span class="c-color-swatch"
|
||||
:style="{ background: currentColor }"
|
||||
<h2 v-if="heading"
|
||||
:title="heading"
|
||||
>{{ heading }}</h2>
|
||||
<li class="grid-row">
|
||||
<div class="grid-cell label"
|
||||
:title="editTitle"
|
||||
>{{ shortLabel }}</div>
|
||||
<div class="grid-cell value">
|
||||
<div class="c-click-swatch c-click-swatch--menu"
|
||||
@click="toggleSwatch()"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
<div class="c-palette c-palette--color">
|
||||
<div v-show="swatchActive"
|
||||
class="c-palette__items"
|
||||
>
|
||||
<div v-for="group in colorPaletteGroups"
|
||||
:key="group.id"
|
||||
class="u-contents"
|
||||
<span class="c-color-swatch"
|
||||
:style="{ background: currentColor }"
|
||||
>
|
||||
<div v-for="color in group"
|
||||
:key="color.id"
|
||||
class="c-palette__item"
|
||||
:class="{ 'selected': currentColor === color.hexString }"
|
||||
:style="{ background: color.hexString }"
|
||||
@click="setColor(color)"
|
||||
</span>
|
||||
</div>
|
||||
<div class="c-palette c-palette--color">
|
||||
<div v-show="swatchActive"
|
||||
class="c-palette__items"
|
||||
>
|
||||
<div v-for="group in colorPaletteGroups"
|
||||
:key="group.id"
|
||||
class="u-contents"
|
||||
>
|
||||
<div v-for="color in group"
|
||||
:key="color.id"
|
||||
class="c-palette__item"
|
||||
:class="{ 'selected': currentColor === color.hexString }"
|
||||
:style="{ background: color.hexString }"
|
||||
@click="setColor(color)"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div v-else
|
||||
class="grid-row"
|
||||
</li>
|
||||
</ul>
|
||||
<ul v-else
|
||||
class="l-inspector-part"
|
||||
>
|
||||
<div class="grid-cell label"
|
||||
:title="viewTitle"
|
||||
>{{ shortLabel }}</div>
|
||||
<div class="grid-cell value">
|
||||
<span class="c-color-swatch"
|
||||
:style="{
|
||||
'background': currentColor
|
||||
}"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<h2 v-if="heading"
|
||||
:title="heading"
|
||||
>{{ heading }}</h2>
|
||||
<li class="grid-row">
|
||||
<div class="grid-cell label"
|
||||
:title="viewTitle"
|
||||
>{{ shortLabel }}</div>
|
||||
<div class="grid-cell value">
|
||||
<span class="c-color-swatch"
|
||||
:style="{
|
||||
'background': currentColor
|
||||
}"
|
||||
>
|
||||
</span>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
@ -104,6 +114,12 @@ export default {
|
||||
default() {
|
||||
return 'Color';
|
||||
}
|
||||
},
|
||||
heading: {
|
||||
type: String,
|
||||
default() {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
|
@ -82,17 +82,12 @@ export default class PlotSeries extends Model {
|
||||
.openmct
|
||||
.telemetry
|
||||
.getMetadata(options.domainObject);
|
||||
|
||||
this.formats = options
|
||||
.openmct
|
||||
.telemetry
|
||||
.getFormatMap(this.metadata);
|
||||
|
||||
//if the object is missing or doesn't have metadata for some reason
|
||||
let range = {};
|
||||
if (this.metadata) {
|
||||
range = this.metadata.valuesForHints(['range'])[0];
|
||||
}
|
||||
const range = this.metadata.valuesForHints(['range'])[0];
|
||||
|
||||
return {
|
||||
name: options.domainObject.name,
|
||||
@ -196,10 +191,7 @@ export default class PlotSeries extends Model {
|
||||
.uniq(true, point => [this.getXVal(point), this.getYVal(point)].join())
|
||||
.value();
|
||||
this.reset(newPoints);
|
||||
}.bind(this))
|
||||
.catch((error) => {
|
||||
console.warn('Error fetching data', error);
|
||||
});
|
||||
}.bind(this));
|
||||
/* eslint-enable you-dont-need-lodash-underscore/concat */
|
||||
}
|
||||
/**
|
||||
@ -207,9 +199,7 @@ export default class PlotSeries extends Model {
|
||||
*/
|
||||
onXKeyChange(xKey) {
|
||||
const format = this.formats[xKey];
|
||||
if (format) {
|
||||
this.getXVal = format.parse.bind(format);
|
||||
}
|
||||
this.getXVal = format.parse.bind(format);
|
||||
}
|
||||
/**
|
||||
* Update y formatter on change, default to stepAfter interpolation if
|
||||
|
@ -184,7 +184,7 @@ export default class YAxisModel extends Model {
|
||||
this.set('values', yMetadata.values);
|
||||
if (!label) {
|
||||
const labelName = series.map(function (s) {
|
||||
return s.metadata ? s.metadata.value(s.get('yKey')).name : '';
|
||||
return s.metadata.value(s.get('yKey')).name;
|
||||
}).reduce(function (a, b) {
|
||||
if (a === undefined) {
|
||||
return b;
|
||||
@ -204,7 +204,7 @@ export default class YAxisModel extends Model {
|
||||
}
|
||||
|
||||
const labelUnits = series.map(function (s) {
|
||||
return s.metadata ? s.metadata.value(s.get('yKey')).units : '';
|
||||
return s.metadata.value(s.get('yKey')).units;
|
||||
}).reduce(function (a, b) {
|
||||
if (a === undefined) {
|
||||
return b;
|
||||
|
@ -19,18 +19,12 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
import { BAR_GRAPH_KEY } from './barGraph/BarGraphConstants';
|
||||
import PlotViewProvider from './PlotViewProvider';
|
||||
import SpectralPlotViewProvider from './spectralPlot/SpectralPlotViewProvider';
|
||||
import BarGraphViewProvider from './barGraph/BarGraphViewProvider';
|
||||
import OverlayPlotViewProvider from './overlayPlot/OverlayPlotViewProvider';
|
||||
import StackedPlotViewProvider from './stackedPlot/StackedPlotViewProvider';
|
||||
import PlotsInspectorViewProvider from './inspector/PlotsInspectorViewProvider';
|
||||
import BarGraphInspectorViewProvider from './barGraph/inspector/BarGraphInspectorViewProvider';
|
||||
import OverlayPlotCompositionPolicy from './overlayPlot/OverlayPlotCompositionPolicy';
|
||||
import StackedPlotCompositionPolicy from './stackedPlot/StackedPlotCompositionPolicy';
|
||||
import SpectralPlotCompositionPolicy from './spectralPlot/SpectralPlotCompositionPolicy';
|
||||
import BarGraphCompositionPolicy from './barGraph/BarGraphCompositionPolicy';
|
||||
|
||||
export default function () {
|
||||
return function install(openmct) {
|
||||
@ -64,48 +58,15 @@ export default function () {
|
||||
},
|
||||
priority: 890
|
||||
});
|
||||
openmct.types.addType('telemetry.plot.spectral', {
|
||||
key: "telemetry.plot.spectral",
|
||||
name: "Spectral Plot",
|
||||
cssClass: "icon-plot-stacked",
|
||||
description: "View Spectra on Y Axes with non-time domain on the X axis. Can be added to Display Layouts.",
|
||||
//Temporarily disabling spectral plots
|
||||
creatable: false,
|
||||
initialize: function (domainObject) {
|
||||
domainObject.composition = [];
|
||||
domainObject.configuration = {};
|
||||
},
|
||||
priority: 890
|
||||
});
|
||||
|
||||
openmct.types.addType(BAR_GRAPH_KEY, {
|
||||
key: BAR_GRAPH_KEY,
|
||||
name: "Bar Graph",
|
||||
cssClass: "icon-bar-chart",
|
||||
description: "View data as a bar graph. Can be added to Display Layouts.",
|
||||
creatable: true,
|
||||
initialize: function (domainObject) {
|
||||
domainObject.composition = [];
|
||||
domainObject.configuration = {
|
||||
plotType: 'bar'
|
||||
};
|
||||
},
|
||||
priority: 891
|
||||
});
|
||||
|
||||
openmct.objectViews.addProvider(new StackedPlotViewProvider(openmct));
|
||||
openmct.objectViews.addProvider(new OverlayPlotViewProvider(openmct));
|
||||
openmct.objectViews.addProvider(new PlotViewProvider(openmct));
|
||||
openmct.objectViews.addProvider(new SpectralPlotViewProvider(openmct));
|
||||
openmct.objectViews.addProvider(new BarGraphViewProvider(openmct));
|
||||
|
||||
openmct.inspectorViews.addProvider(new PlotsInspectorViewProvider(openmct));
|
||||
openmct.inspectorViews.addProvider(new BarGraphInspectorViewProvider(openmct));
|
||||
|
||||
openmct.composition.addPolicy(new OverlayPlotCompositionPolicy(openmct).allow);
|
||||
openmct.composition.addPolicy(new StackedPlotCompositionPolicy(openmct).allow);
|
||||
openmct.composition.addPolicy(new SpectralPlotCompositionPolicy(openmct).allow);
|
||||
openmct.composition.addPolicy(new BarGraphCompositionPolicy(openmct).allow);
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -24,12 +24,10 @@ import {createMouseEvent, createOpenMct, resetApplicationState, spyOnBuiltins} f
|
||||
import PlotVuePlugin from "./plugin";
|
||||
import Vue from "vue";
|
||||
import StackedPlot from "./stackedPlot/StackedPlot.vue";
|
||||
// import SpectralPlot from "./spectralPlot/SpectralPlot.vue";
|
||||
import configStore from "./configuration/ConfigStore";
|
||||
import EventEmitter from "EventEmitter";
|
||||
import PlotOptions from "./inspector/PlotOptions.vue";
|
||||
import PlotConfigurationModel from "./configuration/PlotConfigurationModel";
|
||||
import { BAR_GRAPH_VIEW, BAR_GRAPH_KEY } from './barGraph/BarGraphConstants';
|
||||
|
||||
describe("the plugin", function () {
|
||||
let element;
|
||||
@ -314,38 +312,6 @@ describe("the plugin", function () {
|
||||
let plotView = applicableViews.find((viewProvider) => viewProvider.key === "plot-stacked");
|
||||
expect(plotView).toBeDefined();
|
||||
});
|
||||
|
||||
it("provides a spectral plot view for objects with telemetry", () => {
|
||||
const testTelemetryObject = {
|
||||
id: "test-object",
|
||||
type: "telemetry.plot.spectral",
|
||||
telemetry: {
|
||||
values: [{
|
||||
key: "a-very-fine-key"
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
const applicableViews = openmct.objectViews.get(testTelemetryObject, mockObjectPath);
|
||||
let plotView = applicableViews.find((viewProvider) => viewProvider.key === "plot-spectral");
|
||||
expect(plotView).toBeDefined();
|
||||
});
|
||||
|
||||
it("provides a spectral aggregate plot view for objects with telemetry", () => {
|
||||
const testTelemetryObject = {
|
||||
id: "test-object",
|
||||
type: BAR_GRAPH_KEY,
|
||||
telemetry: {
|
||||
values: [{
|
||||
key: "lots-of-aggregate-telemetry"
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
const applicableViews = openmct.objectViews.get(testTelemetryObject, mockObjectPath);
|
||||
let plotView = applicableViews.find((viewProvider) => viewProvider.key === BAR_GRAPH_VIEW);
|
||||
expect(plotView).toBeDefined();
|
||||
});
|
||||
});
|
||||
|
||||
describe("The single plot view", () => {
|
||||
@ -496,146 +462,6 @@ describe("the plugin", function () {
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* disabling this until we develop the plot view
|
||||
describe("The spectral plot view", () => {
|
||||
let testTelemetryObject;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let testTelemetryObject2;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let config;
|
||||
let spectralPlotObject;
|
||||
let component;
|
||||
let mockComposition;
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
let plotViewComponentObject;
|
||||
|
||||
beforeEach(() => {
|
||||
const getFunc = openmct.$injector.get;
|
||||
spyOn(openmct.$injector, "get")
|
||||
.withArgs("exportImageService").and.returnValue({
|
||||
exportPNG: () => {},
|
||||
exportJPG: () => {}
|
||||
})
|
||||
.and.callFake(getFunc);
|
||||
|
||||
spectralPlotObject = {
|
||||
identifier: {
|
||||
namespace: "",
|
||||
key: "test-spectral-plot"
|
||||
},
|
||||
type: "telemetry.plot.spectral",
|
||||
name: "Test Spectral Plot"
|
||||
};
|
||||
|
||||
testTelemetryObject = {
|
||||
identifier: {
|
||||
namespace: "",
|
||||
key: "test-object"
|
||||
},
|
||||
type: "test-object",
|
||||
name: "Test Object",
|
||||
telemetry: {
|
||||
values: [{
|
||||
key: "utc",
|
||||
format: "utc",
|
||||
name: "Time",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
}, {
|
||||
key: "some-key",
|
||||
name: "Some attribute",
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
}, {
|
||||
key: "some-other-key",
|
||||
name: "Another attribute",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
testTelemetryObject2 = {
|
||||
identifier: {
|
||||
namespace: "",
|
||||
key: "test-object2"
|
||||
},
|
||||
type: "test-object",
|
||||
name: "Test Object2",
|
||||
telemetry: {
|
||||
values: [{
|
||||
key: "utc",
|
||||
format: "utc",
|
||||
name: "Time",
|
||||
hints: {
|
||||
domain: 1
|
||||
}
|
||||
}, {
|
||||
key: "wavelength",
|
||||
name: "Wavelength",
|
||||
hints: {
|
||||
range: 1
|
||||
}
|
||||
}, {
|
||||
key: "some-other-key2",
|
||||
name: "Another attribute2",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
}]
|
||||
}
|
||||
};
|
||||
|
||||
mockComposition = new EventEmitter();
|
||||
mockComposition.load = () => {
|
||||
mockComposition.emit('add', testTelemetryObject);
|
||||
|
||||
return [testTelemetryObject];
|
||||
};
|
||||
|
||||
spyOn(openmct.composition, 'get').and.returnValue(mockComposition);
|
||||
|
||||
let viewContainer = document.createElement("div");
|
||||
child.append(viewContainer);
|
||||
component = new Vue({
|
||||
el: viewContainer,
|
||||
components: {
|
||||
SpectralPlot
|
||||
},
|
||||
provide: {
|
||||
openmct: openmct,
|
||||
domainObject: spectralPlotObject,
|
||||
composition: openmct.composition.get(spectralPlotObject)
|
||||
},
|
||||
template: "<spectral-plot></spectral-plot>"
|
||||
});
|
||||
|
||||
cleanupFirst.push(() => {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
});
|
||||
|
||||
return telemetryPromise
|
||||
.then(Vue.nextTick())
|
||||
.then(() => {
|
||||
plotViewComponentObject = component.$root.$children[0];
|
||||
const configId = openmct.objects.makeKeyString(testTelemetryObject.identifier);
|
||||
config = configStore.get(configId);
|
||||
});
|
||||
});
|
||||
|
||||
it("Renders a collapsed legend for every telemetry", () => {
|
||||
let legend = element.querySelectorAll(".plot-wrapper-collapsed-legend .plot-series-name");
|
||||
expect(legend.length).toBe(1);
|
||||
expect(legend[0].innerHTML).toEqual("Test Object");
|
||||
});
|
||||
|
||||
}); */
|
||||
|
||||
describe("The stacked plot view", () => {
|
||||
let testTelemetryObject;
|
||||
let testTelemetryObject2;
|
||||
@ -1165,39 +991,4 @@ describe("the plugin", function () {
|
||||
});
|
||||
});
|
||||
|
||||
describe("the spectral plot", () => {
|
||||
const mockObject = {
|
||||
name: 'A Very Nice Spectral Plot',
|
||||
key: 'telemetry.plot.spectral',
|
||||
creatable: true
|
||||
};
|
||||
|
||||
it('defines a spectral plot object type with the correct key', () => {
|
||||
const objectDef = openmct.types.get('telemetry.plot.spectral').definition;
|
||||
expect(objectDef.key).toEqual(mockObject.key);
|
||||
});
|
||||
|
||||
xit('is creatable', () => {
|
||||
const objectDef = openmct.types.get('telemetry.plot.spectral').definition;
|
||||
expect(objectDef.creatable).toEqual(mockObject.creatable);
|
||||
});
|
||||
});
|
||||
|
||||
describe("the aggregate spectral plot", () => {
|
||||
const mockObject = {
|
||||
name: 'An Even Nicer Aggregate Spectral Plot',
|
||||
key: BAR_GRAPH_KEY,
|
||||
creatable: true
|
||||
};
|
||||
|
||||
it('defines a spectral plot object type with the correct key', () => {
|
||||
const objectDef = openmct.types.get(BAR_GRAPH_KEY).definition;
|
||||
expect(objectDef.key).toEqual(mockObject.key);
|
||||
});
|
||||
|
||||
it('is creatable', () => {
|
||||
const objectDef = openmct.types.get(BAR_GRAPH_KEY).definition;
|
||||
expect(objectDef.creatable).toEqual(mockObject.creatable);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -36,6 +36,7 @@ define([
|
||||
'./URLIndicatorPlugin/URLIndicatorPlugin',
|
||||
'./telemetryMean/plugin',
|
||||
'./plot/plugin',
|
||||
'./charts/plugin',
|
||||
'./telemetryTable/plugin',
|
||||
'./staticRootPlugin/plugin',
|
||||
'./notebook/plugin',
|
||||
@ -87,6 +88,7 @@ define([
|
||||
URLIndicatorPlugin,
|
||||
TelemetryMean,
|
||||
PlotPlugin,
|
||||
ChartPlugin,
|
||||
TelemetryTablePlugin,
|
||||
StaticRootPlugin,
|
||||
Notebook,
|
||||
@ -189,6 +191,7 @@ define([
|
||||
plugins.ExampleImagery = ExampleImagery;
|
||||
plugins.ImageryPlugin = ImageryPlugin;
|
||||
plugins.Plot = PlotPlugin.default;
|
||||
plugins.Chart = ChartPlugin.default;
|
||||
plugins.TelemetryTable = TelemetryTablePlugin;
|
||||
|
||||
plugins.SummaryWidget = SummaryWidget;
|
||||
|
@ -60,17 +60,18 @@ define([
|
||||
this.addTelemetryObject = this.addTelemetryObject.bind(this);
|
||||
this.removeTelemetryObject = this.removeTelemetryObject.bind(this);
|
||||
this.removeTelemetryCollection = this.removeTelemetryCollection.bind(this);
|
||||
this.incrementOutstandingRequests = this.incrementOutstandingRequests.bind(this);
|
||||
this.decrementOutstandingRequests = this.decrementOutstandingRequests.bind(this);
|
||||
this.resetRowsFromAllData = this.resetRowsFromAllData.bind(this);
|
||||
this.isTelemetryObject = this.isTelemetryObject.bind(this);
|
||||
this.refreshData = this.refreshData.bind(this);
|
||||
this.updateFilters = this.updateFilters.bind(this);
|
||||
this.clearData = this.clearData.bind(this);
|
||||
this.buildOptionsFromConfiguration = this.buildOptionsFromConfiguration.bind(this);
|
||||
|
||||
this.filterObserver = undefined;
|
||||
|
||||
this.createTableRowCollections();
|
||||
|
||||
openmct.time.on('bounds', this.refreshData);
|
||||
openmct.time.on('timeSystem', this.refreshData);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -140,6 +141,8 @@ define([
|
||||
let columnMap = this.getColumnMapForObject(keyString);
|
||||
let limitEvaluator = this.openmct.telemetry.limitEvaluator(telemetryObject);
|
||||
|
||||
this.incrementOutstandingRequests();
|
||||
|
||||
const telemetryProcessor = this.getTelemetryProcessor(keyString, columnMap, limitEvaluator);
|
||||
const telemetryRemover = this.getTelemetryRemover();
|
||||
|
||||
@ -148,13 +151,13 @@ define([
|
||||
this.telemetryCollections[keyString] = this.openmct.telemetry
|
||||
.requestCollection(telemetryObject, requestOptions);
|
||||
|
||||
this.telemetryCollections[keyString].on('requestStarted', this.incrementOutstandingRequests);
|
||||
this.telemetryCollections[keyString].on('requestEnded', this.decrementOutstandingRequests);
|
||||
this.telemetryCollections[keyString].on('remove', telemetryRemover);
|
||||
this.telemetryCollections[keyString].on('add', telemetryProcessor);
|
||||
this.telemetryCollections[keyString].on('clear', this.clearData);
|
||||
this.telemetryCollections[keyString].on('clear', this.tableRows.clear);
|
||||
this.telemetryCollections[keyString].load();
|
||||
|
||||
this.decrementOutstandingRequests();
|
||||
|
||||
this.telemetryObjects[keyString] = {
|
||||
telemetryObject,
|
||||
keyString,
|
||||
@ -265,6 +268,17 @@ define([
|
||||
this.emit('object-removed', objectIdentifier);
|
||||
}
|
||||
|
||||
refreshData(bounds, isTick) {
|
||||
if (!isTick && this.tableRows.outstandingRequests === 0) {
|
||||
this.tableRows.clear();
|
||||
this.tableRows.sortBy({
|
||||
key: this.openmct.time.timeSystem().key,
|
||||
direction: 'asc'
|
||||
});
|
||||
this.tableRows.resubscribe();
|
||||
}
|
||||
}
|
||||
|
||||
clearData() {
|
||||
this.tableRows.clear();
|
||||
this.emit('refresh');
|
||||
@ -364,6 +378,9 @@ define([
|
||||
let keystrings = Object.keys(this.telemetryCollections);
|
||||
keystrings.forEach(this.removeTelemetryCollection);
|
||||
|
||||
this.openmct.time.off('bounds', this.refreshData);
|
||||
this.openmct.time.off('timeSystem', this.refreshData);
|
||||
|
||||
if (this.filterObserver) {
|
||||
this.filterObserver();
|
||||
}
|
||||
|
@ -131,8 +131,7 @@ export default {
|
||||
objects.forEach(object => this.addColumnsForObject(object, false));
|
||||
},
|
||||
addColumnsForObject(telemetryObject) {
|
||||
const metadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
let metadataValues = metadata ? metadata.values() : [];
|
||||
let metadataValues = this.openmct.telemetry.getMetadata(telemetryObject).values();
|
||||
metadataValues.forEach(metadatum => {
|
||||
let column = new TelemetryTableColumn(this.openmct, metadatum);
|
||||
this.tableConfiguration.addSingleColumnForObject(telemetryObject, column);
|
||||
|
@ -105,8 +105,7 @@ export default {
|
||||
composition.load().then((domainObjects) => {
|
||||
domainObjects.forEach(telemetryObject => {
|
||||
let keyString = this.openmct.objects.makeKeyString(telemetryObject.identifier);
|
||||
const metadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
let metadataValues = metadata ? metadata.values() : [];
|
||||
let metadataValues = this.openmct.telemetry.getMetadata(telemetryObject).values();
|
||||
let filters = this.filteredTelemetry[keyString];
|
||||
|
||||
if (filters !== undefined) {
|
||||
|
@ -125,6 +125,7 @@
|
||||
<div
|
||||
class="c-table c-telemetry-table c-table--filterable c-table--sortable has-control-bar u-style-receiver js-style-receiver"
|
||||
:class="{
|
||||
'loading': loading,
|
||||
'is-paused' : paused
|
||||
}"
|
||||
>
|
||||
@ -361,7 +362,7 @@ export default {
|
||||
autoScroll: true,
|
||||
sortOptions: {},
|
||||
filters: {},
|
||||
loading: false,
|
||||
loading: true,
|
||||
scrollable: undefined,
|
||||
tableEl: undefined,
|
||||
headersHolderEl: undefined,
|
||||
@ -421,14 +422,6 @@ export default {
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
loading: {
|
||||
handler(isLoading) {
|
||||
if (this.viewActionsCollection) {
|
||||
let action = isLoading ? 'disable' : 'enable';
|
||||
this.viewActionsCollection[action](['export-csv-all']);
|
||||
}
|
||||
}
|
||||
},
|
||||
markedRows: {
|
||||
handler(newVal, oldVal) {
|
||||
this.$emit('marked-rows-updated', newVal, oldVal);
|
||||
@ -1027,12 +1020,6 @@ export default {
|
||||
this.viewActionsCollection.disable(['export-csv-marked', 'unmark-all-rows']);
|
||||
}
|
||||
|
||||
if (this.loading) {
|
||||
this.viewActionsCollection.disable(['export-csv-all']);
|
||||
} else {
|
||||
this.viewActionsCollection.enable(['export-csv-all']);
|
||||
}
|
||||
|
||||
if (this.paused) {
|
||||
this.viewActionsCollection.hide(['pause-data']);
|
||||
this.viewActionsCollection.show(['play-data']);
|
||||
|
@ -151,23 +151,30 @@ export default {
|
||||
this.stopFollowingTimeContext();
|
||||
this.timeContext = this.openmct.time.getContextForView([this.domainObject]);
|
||||
this.timeContext.on('timeContext', this.setTimeContext);
|
||||
this.timeContext.on('clock', this.setTimeOptions);
|
||||
this.timeContext.on('clock', this.setViewFromClock);
|
||||
},
|
||||
stopFollowingTimeContext() {
|
||||
if (this.timeContext) {
|
||||
this.timeContext.off('timeContext', this.setTimeContext);
|
||||
this.timeContext.off('clock', this.setTimeOptions);
|
||||
this.timeContext.off('clock', this.setViewFromClock);
|
||||
}
|
||||
},
|
||||
setTimeOptions(clock) {
|
||||
this.timeOptions.clockOffsets = this.timeOptions.clockOffsets || this.timeContext.clockOffsets();
|
||||
this.timeOptions.fixedOffsets = this.timeOptions.fixedOffsets || this.timeContext.bounds();
|
||||
|
||||
setViewFromClock(clock) {
|
||||
if (!this.timeOptions.mode) {
|
||||
this.mode = this.timeContext.clock() === undefined ? {key: 'fixed'} : {key: Object.create(this.timeContext.clock()).key};
|
||||
this.registerIndependentTimeOffsets();
|
||||
this.setTimeOptions(clock);
|
||||
}
|
||||
},
|
||||
setTimeOptions() {
|
||||
if (!this.timeOptions || !this.timeOptions.mode) {
|
||||
this.mode = this.timeContext.clock() === undefined ? { key: 'fixed' } : { key: Object.create(this.timeContext.clock()).key};
|
||||
this.timeOptions = {
|
||||
clockOffsets: this.timeContext.clockOffsets(),
|
||||
fixedOffsets: this.timeContext.bounds()
|
||||
};
|
||||
}
|
||||
|
||||
this.registerIndependentTimeOffsets();
|
||||
},
|
||||
saveFixedOffsets(offsets) {
|
||||
const newOptions = Object.assign({}, this.timeOptions, {
|
||||
fixedOffsets: offsets
|
||||
|
@ -20,8 +20,7 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
<template>
|
||||
<div v-if="modes.length > 1"
|
||||
ref="modeMenuButton"
|
||||
<div ref="modeMenuButton"
|
||||
class="c-ctrl-wrapper c-ctrl-wrapper--menus-up"
|
||||
>
|
||||
<div class="c-menu-button c-ctrl-wrapper c-ctrl-wrapper--menus-left">
|
||||
|
@ -88,7 +88,7 @@ export default {
|
||||
this.mutablePromise.then(() => {
|
||||
this.openmct.objects.destroyMutable(this.domainObject);
|
||||
});
|
||||
} else if (this.domainObject.isMutable) {
|
||||
} else {
|
||||
this.openmct.objects.destroyMutable(this.domainObject);
|
||||
}
|
||||
},
|
||||
|
@ -160,9 +160,7 @@ export default {
|
||||
this.status = this.openmct.status.get(this.domainObject.identifier);
|
||||
this.removeStatusListener = this.openmct.status.observe(this.domainObject.identifier, this.setStatus);
|
||||
const provider = this.openmct.objectViews.get(this.domainObject, this.objectPath)[0];
|
||||
if (provider) {
|
||||
this.$refs.objectView.show(this.domainObject, provider.key, false, this.objectPath);
|
||||
}
|
||||
this.$refs.objectView.show(this.domainObject, provider.key, false, this.objectPath);
|
||||
},
|
||||
beforeDestroy() {
|
||||
this.removeStatusListener();
|
||||
@ -195,10 +193,8 @@ export default {
|
||||
},
|
||||
showMenuItems(event) {
|
||||
const sortedActions = this.openmct.actions._groupAndSortActions(this.menuActionItems);
|
||||
if (sortedActions.length) {
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(sortedActions, this.actionCollection.objectPath, this.actionCollection.view);
|
||||
this.openmct.menus.showMenu(event.x, event.y, menuItems);
|
||||
}
|
||||
const menuItems = this.openmct.menus.actionsToMenuItems(sortedActions, this.actionCollection.objectPath, this.actionCollection.view);
|
||||
this.openmct.menus.showMenu(event.x, event.y, menuItems);
|
||||
},
|
||||
setStatus(status) {
|
||||
this.status = status;
|
||||
|
@ -49,7 +49,6 @@ describe("the inspector", () => {
|
||||
|
||||
beforeEach((done) => {
|
||||
openmct = createOpenMct();
|
||||
spyOn(openmct.objects, 'save').and.returnValue(Promise.resolve(true));
|
||||
openmct.on('start', done);
|
||||
openmct.startHeadless();
|
||||
});
|
||||
@ -78,12 +77,12 @@ describe("the inspector", () => {
|
||||
expect(savedStylesViewComponent.$children[0].$children.length).toBe(0);
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
|
||||
return stylesViewComponent.$nextTick().then(() => {
|
||||
stylesViewComponent.$nextTick().then(() => {
|
||||
expect(savedStylesViewComponent.$children[0].$children.length).toBe(1);
|
||||
});
|
||||
});
|
||||
|
||||
xit("should allow a saved style to be applied", () => {
|
||||
it("should allow a saved style to be applied", () => {
|
||||
spyOn(openmct.editor, 'isEditing').and.returnValue(true);
|
||||
|
||||
selection = mockTelemetryTableSelection;
|
||||
@ -92,12 +91,12 @@ describe("the inspector", () => {
|
||||
|
||||
stylesViewComponent.$children[0].saveStyle(mockStyle);
|
||||
|
||||
return stylesViewComponent.$nextTick().then(() => {
|
||||
stylesViewComponent.$nextTick().then(() => {
|
||||
const styleSelectorComponent = savedStylesViewComponent.$children[0].$children[0];
|
||||
|
||||
styleSelectorComponent.selectStyle();
|
||||
|
||||
return savedStylesViewComponent.$nextTick().then(() => {
|
||||
savedStylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent = stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const styles = styleEditorComponent.$children.filter(component => component.options.value === mockStyle.color);
|
||||
@ -148,7 +147,7 @@ describe("the inspector", () => {
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
return stylesViewComponent.$nextTick().then(() => {
|
||||
stylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent = stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const saveStyleButtonIndex = styleEditorComponent.$children.length - 1;
|
||||
@ -169,7 +168,7 @@ describe("the inspector", () => {
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
return stylesViewComponent.$nextTick().then(() => {
|
||||
stylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent = stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const saveStyleButtonIndex = styleEditorComponent.$children.length - 1;
|
||||
@ -186,7 +185,7 @@ describe("the inspector", () => {
|
||||
stylesViewComponent = createViewComponent(StylesView, selection, openmct);
|
||||
savedStylesViewComponent = createViewComponent(SavedStylesView, selection, openmct);
|
||||
|
||||
return stylesViewComponent.$nextTick().then(() => {
|
||||
stylesViewComponent.$nextTick().then(() => {
|
||||
const styleEditorComponentIndex = stylesViewComponent.$children[0].$children.length - 1;
|
||||
const styleEditorComponent = stylesViewComponent.$children[0].$children[styleEditorComponentIndex];
|
||||
const saveStyleButtonIndex = styleEditorComponent.$children.length - 1;
|
||||
|
@ -42,6 +42,8 @@ const webpackConfig = {
|
||||
"csv": "comma-separated-values",
|
||||
"EventEmitter": "eventemitter3",
|
||||
"bourbon": "bourbon.scss",
|
||||
"plotly-basic": "plotly.js-basic-dist",
|
||||
"plotly-gl2d": "plotly.js-gl2d-dist",
|
||||
"vue": vueFile,
|
||||
"d3-scale": path.join(__dirname, "node_modules/d3-scale/build/d3-scale.min.js"),
|
||||
"printj": path.join(__dirname, "node_modules/printj/dist/printj.min.js"),
|
||||
|
Reference in New Issue
Block a user