Merge branch 'master' into iso-date-format

This commit is contained in:
Andrew Henry
2020-08-03 14:34:38 -07:00
committed by GitHub
746 changed files with 5320 additions and 2400 deletions

View File

@ -31,6 +31,7 @@ define(function () {
if (this.knownBundles.hasOwnProperty(path)) {
throw new Error('Cannot register bundle with duplicate path', path);
}
this.knownBundles[path] = definition;
};
@ -38,6 +39,7 @@ define(function () {
if (!this.knownBundles[path]) {
throw new Error('Unknown bundle ' + path);
}
this.bundles[path] = this.knownBundles[path];
};
@ -45,11 +47,12 @@ define(function () {
if (!this.bundles[path]) {
throw new Error('Tried to disable inactive bundle ' + path);
}
delete this.bundles[path];
};
BundleRegistry.prototype.contains = function (path) {
return !!this.bundles[path];
return Boolean(this.bundles[path]);
};
BundleRegistry.prototype.get = function (path) {
@ -66,6 +69,7 @@ define(function () {
if (!this.knownBundles[path]) {
throw new Error('Cannot remove Unknown Bundle ' + path);
}
delete this.bundles[path];
delete this.knownBundles[path];
};

View File

@ -102,19 +102,21 @@ define([
};
/* eslint-enable no-undef */
this.legacyBundle = {
extensions: {
services: [
{
key: "openmct",
implementation: function ($injector) {
this.$injector = $injector;
this.legacyBundle = { extensions: {
services: [
{
key: "openmct",
implementation: function ($injector) {
this.$injector = $injector;
return this;
}.bind(this),
depends: ['$injector']
}
]
} };
return this;
}.bind(this),
depends: ['$injector']
}
]
}
};
/**
* Tracks current selection state of the application.
@ -292,6 +294,7 @@ define([
function instantiate(model, keyString) {
var capabilities = capabilityService.getCapabilities(model, keyString);
model.id = keyString;
return new DomainObjectImpl(keyString, model, capabilities);
}
@ -303,6 +306,7 @@ define([
.map((o) => {
let keyString = objectUtils.makeKeyString(o.identifier);
let oldModel = objectUtils.toOldFormat(o);
return instantiate(oldModel, keyString);
})
.reverse()
@ -313,6 +317,7 @@ define([
} else {
let keyString = objectUtils.makeKeyString(domainObject.identifier);
let oldModel = objectUtils.toOldFormat(domainObject);
return instantiate(oldModel, keyString);
}
};
@ -391,7 +396,7 @@ define([
* @event start
* @memberof module:openmct.MCT~
*/
const startPromise = new Main()
const startPromise = new Main();
startPromise.run(this)
.then(function (angular) {
this.$angular = angular;
@ -414,6 +419,7 @@ define([
this.layout = appLayout.$refs.layout;
Browse(this);
}
this.router.start();
this.emit('start');
}.bind(this));
@ -421,8 +427,9 @@ define([
MCT.prototype.startHeadless = function () {
let unreachableNode = document.createElement('div');
return this.start(unreachableNode, true);
}
};
/**
* Install a plugin in MCT.

View File

@ -49,6 +49,7 @@ define([
};
}
}
return action;
});
};

View File

@ -27,7 +27,9 @@ export default function LegacyActionAdapter(openmct, legacyActions) {
if (action.category === 'contextual' || (Array.isArray(action.category) && action.category.includes('contextual'))) {
return true;
}
console.warn(`DEPRECATION WARNING: Action ${action.definition.key} in bundle ${action.bundle.path} is non-contextual and should be migrated.`);
return false;
}

View File

@ -41,7 +41,7 @@ export default class LegacyContextMenuAction {
let context = {
category: 'contextual',
domainObject: this.openmct.legacyObject(pathWithRoot)
}
};
let legacyAction = new this.LegacyAction(context);
if (!legacyAction.getMetadata) {
@ -51,6 +51,7 @@ export default class LegacyContextMenuAction {
return metadata;
}.bind(legacyAction);
}
legacyAction.perform();
});
}
@ -58,9 +59,9 @@ export default class LegacyContextMenuAction {
appliesTo(objectPath) {
let legacyObject = this.openmct.legacyObject(objectPath);
return (this.LegacyAction.appliesTo === undefined ||
this.LegacyAction.appliesTo({domainObject: legacyObject})) &&
!this.isBlacklisted(objectPath);
return (this.LegacyAction.appliesTo === undefined
|| this.LegacyAction.appliesTo({domainObject: legacyObject}))
&& !this.isBlacklisted(objectPath);
}
/**
@ -84,6 +85,7 @@ export default class LegacyContextMenuAction {
return OUTSIDE_EDIT_PATH_BLACKLIST.some(actionKey => this.LegacyAction.key === actionKey);
}
}
return false;
}
}

View File

@ -202,5 +202,5 @@ define([
]
}
}
}
};
});

View File

@ -48,9 +48,11 @@ define([
capabilities.mutation =
synchronizeMutationCapability(capabilities.mutation);
}
if (capabilities.view) {
capabilities.view = patchViewCapability(capabilities.view);
}
if (AlternateCompositionCapability.appliesTo(model, id)) {
capabilities.composition = function (domainObject) {
return new AlternateCompositionCapability(this.$injector, domainObject);

View File

@ -74,6 +74,7 @@ define([
var keyString = objectUtils.makeKeyString(child.identifier);
var oldModel = objectUtils.toOldFormat(child);
var newDO = this.instantiate(oldModel, keyString);
return new ContextualDomainObject(newDO, this.domainObject);
};

View File

@ -47,6 +47,7 @@ define([
if (v.provider && v.provider.priority) {
vd.priority = v.provider.priority(newDomainObject);
}
return vd;
})
.sortBy('priority')

View File

@ -41,6 +41,7 @@ define([
listener(newModel);
});
};
return capability;
};
}

View File

@ -21,11 +21,11 @@
*****************************************************************************/
define([], function () {
var LEGACY_INDICATOR_TEMPLATE =
'<mct-include ' +
' ng-model="indicator" ' +
' class="h-indicator" ' +
' key="template">' +
' </mct-include>';
'<mct-include '
+ ' ng-model="indicator" '
+ ' class="h-indicator" '
+ ' key="template">'
+ ' </mct-include>';
return function () {
return function (openmct) {
@ -51,6 +51,7 @@ define([], function () {
} else {
legacyIndicator = LegacyIndicatorDef;
}
return legacyIndicator;
}

View File

@ -85,7 +85,7 @@ define(
}
it("Displays any legacy indicators ", function () {
var legacyIndicators = [{},{},{},{}];
var legacyIndicators = [{}, {}, {}, {}];
legacyIndicatorsRunsFunction(legacyIndicators);
renderIndicators();

View File

@ -31,8 +31,10 @@ define([], function () {
) {
if (view.hasOwnProperty('provider')) {
var domainObject = legacyObject.useCapability('adapter');
return view.provider.canView(domainObject);
}
return true;
};

View File

@ -33,7 +33,8 @@ define([
function AlternateCompositionInitializer(openmct) {
AlternateCompositionCapability.appliesTo = function (model, id) {
model = objectUtils.toNewFormat(model, id || '');
return !!openmct.composition.get(model);
return Boolean(openmct.composition.get(model));
};
}

View File

@ -137,6 +137,7 @@ define([
function callbackWrapper(series) {
callback(createDatum(domainObject, metadata, series, series.getPointCount() - 1));
}
return capability.subscribe(callbackWrapper, request) || function () {};
};
@ -145,6 +146,7 @@ define([
utils.toOldFormat(domainObject),
utils.makeKeyString(domainObject.identifier)
);
return oldObject.hasCapability("limit");
};

View File

@ -30,10 +30,10 @@ define([
function checkForDeprecatedFunctionality(typeDef) {
if (typeDef.hasOwnProperty('telemetry')) {
console.warn(
'DEPRECATION WARNING: Telemetry data on type ' +
'registrations will be deprecated in a future version, ' +
'please convert to a custom telemetry metadata provider ' +
'for type: ' + typeDef.key
'DEPRECATION WARNING: Telemetry data on type '
+ 'registrations will be deprecated in a future version, '
+ 'please convert to a custom telemetry metadata provider '
+ 'for type: ' + typeDef.key
);
}
}

View File

@ -40,6 +40,7 @@ define(
var capabilities = capabilityService.getCapabilities(model, id);
model.id = old_id;
cacheService.put(id, model);
return new DomainObjectImpl(id, model, capabilities);
};
}

View File

@ -77,7 +77,8 @@ define([
object.identifier.key,
model
);
}
};
ObjectServiceProvider.prototype.update = async function (object) {
let model = utils.toOldFormat(object);
@ -86,7 +87,7 @@ define([
object.identifier.key,
model
);
}
};
/**
* Get the space in which this domain object is persisted;
@ -106,6 +107,7 @@ define([
if (this.identifierService === undefined) {
this.identifierService = this.$injector.get('identifierService');
}
return this.identifierService;
};
@ -113,8 +115,9 @@ define([
if (this.persistenceService === undefined) {
this.persistenceService = this.$injector.get('persistenceService');
}
return this.persistenceService;
}
};
ObjectServiceProvider.prototype.delete = function (object) {
// TODO!
@ -122,9 +125,11 @@ define([
ObjectServiceProvider.prototype.get = function (key) {
var keyString = utils.makeKeyString(key);
return this.objectService.getObjects([keyString])
.then(function (results) {
var model = results[keyString].getModel();
return utils.toNewFormat(model, key);
});
};
@ -138,6 +143,7 @@ define([
var results = {},
promises = keys.map(function (keyString) {
var key = utils.parseKeyString(keyString);
return openmct.objects.get(key)
.then(function (object) {
object = utils.toOldFormat(object);

View File

@ -51,6 +51,7 @@ define([
if (this.apiFetching[id]) {
return Promise.resolve();
}
this.apiFetching[id] = true;
return this.api.objects.get(objectUtils.parseKeyString(id))
@ -84,6 +85,7 @@ define([
Object.keys(apiResults).forEach(function (k) {
models[k] = apiResults[k];
});
return models;
});
}.bind(this));

View File

@ -16,6 +16,7 @@ define([
function LegacyViewProvider(legacyView, openmct, convertToLegacyObject) {
console.warn(`DEPRECATION WARNING: Migrate ${legacyView.key} from ${legacyView.bundle.path} to use the new View APIs. Legacy view support will be removed soon.`);
return {
key: legacyView.key,
name: legacyView.name,
@ -28,9 +29,11 @@ define([
if (!domainObject || !domainObject.identifier) {
return false;
}
if (legacyView.type) {
return domainObject.type === legacyView.type;
}
let legacyObject = convertToLegacyObject(domainObject);
if (legacyView.needs) {
let meetsNeeds = legacyView.needs.every(k => legacyObject.hasCapability(k));
@ -38,6 +41,7 @@ define([
return false;
}
}
return openmct.$injector.get('policyService').allow(
'view', legacyView, legacyObject
);
@ -79,6 +83,7 @@ define([
results[i] = r;
}));
}
return result;
});
@ -86,6 +91,7 @@ define([
if (isDestroyed) {
return;
}
uses.forEach(function (key, i) {
scope[key] = results[i];
});
@ -119,13 +125,14 @@ define([
scope = null;
unlistenToStatus();
}
}
};
},
priority: function () {
let priority = legacyView.priority || DEFAULT_VIEW_PRIORITY;
if (typeof priority === 'string') {
priority = PRIORITY_LEVELS[priority];
}
return priority;
}
};

View File

@ -37,7 +37,6 @@ define([
scope.domainObject = legacyObject;
scope.model = legacyObject.getModel();
return {
show: function (container) {
let child = document.createElement('div');
@ -52,6 +51,7 @@ define([
results[i] = r;
}));
}
return result;
});
@ -59,10 +59,11 @@ define([
if (isDestroyed) {
return;
}
uses.forEach(function (key, i) {
scope[key] = results[i];
});
element = openmct.$angular.element(child)
element = openmct.$angular.element(child);
templateLinker.link(
scope,
element,
@ -88,7 +89,7 @@ define([
element = null;
scope = null;
}
}
};
}
};
}

View File

@ -12,6 +12,7 @@ define([
function convertToLegacyObject(domainObject) {
let keyString = objectUtils.makeKeyString(domainObject.identifier);
let oldModel = objectUtils.toOldFormat(domainObject);
return instantiate(oldModel, keyString);
}

View File

@ -41,5 +41,6 @@ export default function Branding(options) {
if (arguments.length === 1) {
brandingOptions = options;
}
return brandingOptions;
}

View File

@ -40,6 +40,7 @@ export default class Editor extends EventEmitter {
if (this.editing === true) {
throw "Already editing";
}
this.editing = true;
this.getTransactionService().startTransaction();
this.emit('isEditing', true);
@ -59,11 +60,12 @@ export default class Editor extends EventEmitter {
* @private
*/
save() {
return this.getTransactionService().commit().then((result)=>{
return this.getTransactionService().commit().then((result) => {
this.editing = false;
this.emit('isEditing', false);
return result
}).catch((error)=>{
return result;
}).catch((error) => {
throw error;
});
}
@ -88,6 +90,7 @@ export default class Editor extends EventEmitter {
if (!this.transactionService) {
this.transactionService = this.openmct.$injector.get('transactionService');
}
return this.transactionService;
}
}

View File

@ -94,7 +94,10 @@ define([
return composition.load().then(function () {
expect(listener.calls.count()).toBe(3);
expect(listener).toHaveBeenCalledWith({
identifier: {namespace: 'test', key: 'a'}
identifier: {
namespace: 'test',
key: 'a'
}
});
});
});
@ -129,12 +132,15 @@ define([
expect(newComposition[0].key).toEqual('b');
expect(newComposition[1].key).toEqual('c');
expect(newComposition[2].key).toEqual('a');
})
});
});
it('supports adding an object to composition', function () {
let addListener = jasmine.createSpy('addListener');
let mockChildObject = {
identifier: {key: 'mock-key', namespace: ''}
identifier: {
key: 'mock-key',
namespace: ''
}
};
composition.on('add', addListener);
composition.add(mockChildObject);
@ -191,7 +197,10 @@ define([
listenObject = addListener.calls.mostRecent().args[0];
expect(listenObject).toEqual(loadedObject);
expect(loadedObject).toEqual({
identifier: {namespace: 'custom', key: 'thing'}
identifier: {
namespace: 'custom',
key: 'thing'
}
});
});
});
@ -200,7 +209,10 @@ define([
beforeEach(function () {
mockChildObject = {
identifier: {key: 'mock-key', namespace: ''}
identifier: {
key: 'mock-key',
namespace: ''
}
};
composition.add(mockChildObject);
});
@ -277,17 +289,28 @@ define([
.then(function () {
expect(addListener).not.toHaveBeenCalled();
expect(removeListener).not.toHaveBeenCalled();
add({namespace: 'custom', key: 'thing'});
add({
namespace: 'custom',
key: 'thing'
});
return addPromise;
}).then(function () {
expect(addListener).toHaveBeenCalledWith({
identifier: {namespace: 'custom', key: 'thing'}
identifier: {
namespace: 'custom',
key: 'thing'
}
});
remove(addListener.calls.mostRecent().args[0]);
return removePromise;
}).then(function () {
expect(removeListener).toHaveBeenCalledWith({
identifier: {namespace: 'custom', key: 'thing'}
identifier: {
namespace: 'custom',
key: 'thing'
}
});
});
});

View File

@ -74,9 +74,11 @@ define([
if (!this.listeners[event]) {
throw new Error('Event not supported by composition: ' + event);
}
if (!this.mutationListener) {
this._synchronize();
}
if (this.provider.on && this.provider.off) {
if (event === 'add') {
this.provider.on(
@ -85,20 +87,24 @@ define([
this.onProviderAdd,
this
);
} if (event === 'remove') {
}
if (event === 'remove') {
this.provider.on(
this.domainObject,
'remove',
this.onProviderRemove,
this
);
} if (event === 'reorder') {
}
if (event === 'reorder') {
this.provider.on(
this.domainObject,
'reorder',
this.onProviderReorder,
this
)
);
}
}
@ -180,6 +186,7 @@ define([
if (!this.publicAPI.composition.checkPolicy(this.domainObject, child)) {
throw `Object of type ${child.type} cannot be added to object of type ${this.domainObject.type}`;
}
this.provider.add(this.domainObject, child.identifier);
} else {
this.emit('add', child);
@ -201,10 +208,12 @@ define([
}.bind(this))
.then(function (childObjects) {
childObjects.forEach(c => this.add(c, true));
return childObjects;
}.bind(this))
.then(function (children) {
this.emit('load');
return children;
}.bind(this));
};
@ -259,6 +268,7 @@ define([
CompositionCollection.prototype.onProviderAdd = function (childId) {
return this.publicAPI.objects.get(childId).then(function (child) {
this.add(child, true);
return child;
}.bind(this));
};

View File

@ -57,9 +57,9 @@ define([
* @private
*/
DefaultCompositionProvider.prototype.cannotContainItself = function (parent, child) {
return !(parent.identifier.namespace === child.identifier.namespace &&
parent.identifier.key === child.identifier.key);
}
return !(parent.identifier.namespace === child.identifier.namespace
&& parent.identifier.key === child.identifier.key);
};
/**
* Check if this provider should be used to load composition for a
@ -72,7 +72,7 @@ define([
* @method appliesTo
*/
DefaultCompositionProvider.prototype.appliesTo = function (domainObject) {
return !!domainObject.composition;
return Boolean(domainObject.composition);
};
/**
@ -167,8 +167,8 @@ define([
*/
DefaultCompositionProvider.prototype.remove = function (domainObject, childId) {
let composition = domainObject.composition.filter(function (child) {
return !(childId.namespace === child.namespace &&
childId.key === child.key);
return !(childId.namespace === child.namespace
&& childId.key === child.key);
});
this.publicAPI.objects.mutate(domainObject, 'composition', composition);
@ -192,6 +192,7 @@ define([
this.publicAPI.objects.mutate(parent, 'composition', parent.composition);
}
};
/**
* @private
*/
@ -228,6 +229,7 @@ define([
});
}
}
this.publicAPI.objects.mutate(domainObject, 'composition', newComposition);
let id = objectUtils.makeKeyString(domainObject.identifier);
@ -258,9 +260,10 @@ define([
if (this.topicListener) {
return;
}
this.publicAPI.objects.eventEmitter.on('mutation', this.onMutation);
this.topicListener = () => {
this.publicAPI.objects.eventEmitter.off('mutation', this.onMutation)
this.publicAPI.objects.eventEmitter.off('mutation', this.onMutation);
};
};
@ -304,7 +307,6 @@ define([
listeners.remove.forEach(notify(removedChild));
});
};
return DefaultCompositionProvider;

View File

@ -20,5 +20,5 @@
<script>
export default {
inject: ['actions', 'objectPath']
}
};
</script>

View File

@ -83,11 +83,13 @@ class ContextMenuAPI {
if (action.appliesTo === undefined && actionsToBeIncluded.includes(action.key)) {
return true;
}
return action.appliesTo(objectPath, actionsToBeIncluded) && actionsToBeIncluded.includes(action.key);
} else {
if (action.appliesTo === undefined) {
return true;
}
return action.appliesTo(objectPath) && !action.hideInDefaultMenu;
}
});
@ -126,7 +128,7 @@ class ContextMenuAPI {
return {
x: eventPosX,
y: eventPosY
}
};
}
/**
* @private

View File

@ -68,9 +68,11 @@ define(['zepto', './res/indicator-template.html'],
if (this.iconClassValue) {
this.element.classList.remove(this.iconClassValue);
}
if (iconClass) {
this.element.classList.add(iconClass);
}
this.iconClassValue = iconClass;
}
@ -82,9 +84,11 @@ define(['zepto', './res/indicator-template.html'],
if (this.statusClassValue) {
this.element.classList.remove(this.statusClassValue);
}
if (statusClass) {
this.element.classList.add(statusClass);
}
this.statusClassValue = statusClass;
}

View File

@ -82,7 +82,8 @@ export default class NotificationAPI extends EventEmitter {
message: message,
autoDismiss: true,
severity: "info"
}
};
return this._notify(notificationModel);
}
@ -95,7 +96,8 @@ export default class NotificationAPI extends EventEmitter {
let notificationModel = {
message: message,
severity: "alert"
}
};
return this._notify(notificationModel);
}
@ -108,7 +110,8 @@ export default class NotificationAPI extends EventEmitter {
let notificationModel = {
message: message,
severity: "error"
}
};
return this._notify(notificationModel);
}
@ -124,7 +127,8 @@ export default class NotificationAPI extends EventEmitter {
progressPerc: progressPerc,
progressText: progressText,
severity: "info"
}
};
return this._notify(notificationModel);
}
@ -200,6 +204,7 @@ export default class NotificationAPI extends EventEmitter {
if (index >= 0) {
this.notifications.splice(index, 1);
}
this._setActiveNotification(this._selectNextNotification());
this._setHighestSeverity();
notification.emit('destroy');
@ -299,7 +304,7 @@ export default class NotificationAPI extends EventEmitter {
notification.model.progressPerc = progressPerc;
notification.model.progressText = progressText;
notification.emit('progress', progressPerc, progressText);
}
};
}
return notification;
@ -313,8 +318,10 @@ export default class NotificationAPI extends EventEmitter {
if (!notification) {
delete this.activeTimeout;
return;
}
this.emit('notification', notification);
if (notification.model.autoDismiss || this._selectNextNotification()) {
@ -342,8 +349,8 @@ export default class NotificationAPI extends EventEmitter {
for (; i < this.notifications.length; i++) {
notification = this.notifications[i];
if (!notification.model.minimized &&
notification !== this.activeNotification) {
if (!notification.model.minimized
&& notification !== this.activeNotification) {
return notification;
}
}

View File

@ -36,7 +36,6 @@ define([
EventEmitter
) {
/**
* Utilities for loading, saving, and manipulating domain objects.
* @interface ObjectAPI
@ -66,6 +65,7 @@ define([
if (identifier.key === 'ROOT') {
return this.rootProvider;
}
return this.providers[identifier.namespace] || this.fallbackProvider;
};
@ -174,10 +174,11 @@ define([
ObjectAPI.prototype.isPersistable = function (domainObject) {
let provider = this.getProvider(domainObject.identifier);
return provider !== undefined &&
provider.create !== undefined &&
provider.update !== undefined;
}
return provider !== undefined
&& provider.create !== undefined
&& provider.update !== undefined;
};
/**
* Save this domain object in its current state. EXPERIMENTAL
@ -206,6 +207,7 @@ define([
result = provider.update(domainObject);
}
}
return result;
};
@ -232,6 +234,7 @@ define([
ObjectAPI.prototype.mutate = function (domainObject, path, value) {
var mutableObject =
new MutableObject(this.eventEmitter, domainObject);
return mutableObject.set(path, value);
};
@ -248,6 +251,7 @@ define([
var mutableObject =
new MutableObject(this.eventEmitter, domainObject);
mutableObject.on(path, callback);
return mutableObject.stopListening.bind(mutableObject);
};
@ -266,9 +270,9 @@ define([
ObjectAPI.prototype.areIdsEqual = function (...identifiers) {
return identifiers.map(utils.parseKeyString)
.every(identifier => {
return identifier === identifiers[0] ||
(identifier.namespace === identifiers[0].namespace &&
identifier.key === identifiers[0].key);
return identifier === identifiers[0]
|| (identifier.namespace === identifiers[0].namespace
&& identifier.key === identifiers[0].key);
});
};
@ -321,8 +325,9 @@ define([
*/
function hasAlreadyBeenPersisted(domainObject) {
return domainObject.persisted !== undefined &&
domainObject.persisted === domainObject.modified;
return domainObject.persisted !== undefined
&& domainObject.persisted === domainObject.modified;
}
return ObjectAPI;
});

View File

@ -16,10 +16,11 @@ describe("The Object API", () => {
name: "test object",
type: "test-type"
};
})
});
describe("The save function", () => {
it("Rejects if no provider available", () => {
let rejected = false;
return objectAPI.save(mockDomainObject)
.catch(() => rejected = true)
.then(() => expect(rejected).toBe(true));
@ -32,7 +33,7 @@ describe("The Object API", () => {
"update"
]);
objectAPI.addProvider(TEST_NAMESPACE, mockProvider);
})
});
it("Calls 'create' on provider if object is new", () => {
objectAPI.save(mockDomainObject);
expect(mockProvider.create).toHaveBeenCalled();
@ -56,5 +57,5 @@ describe("The Object API", () => {
expect(mockProvider.update).not.toHaveBeenCalled();
});
});
})
});
});

View File

@ -34,6 +34,7 @@ define([
var promises = this.providers.map(function (provider) {
return provider();
});
return Promise.all(promises)
.then(_.flatten);
};

View File

@ -31,9 +31,9 @@ define([
* @private
*/
function isIdentifier(thing) {
return typeof thing === 'object' &&
thing.hasOwnProperty('key') &&
thing.hasOwnProperty('namespace');
return typeof thing === 'object'
&& thing.hasOwnProperty('key')
&& thing.hasOwnProperty('namespace');
}
/**
@ -57,6 +57,7 @@ define([
if (isIdentifier(keyString)) {
return keyString;
}
var namespace = '',
key = keyString;
for (var i = 0; i < key.length; i++) {
@ -66,6 +67,7 @@ define([
key = key.slice(i + 1);
break;
}
namespace += key[i];
}
@ -79,7 +81,6 @@ define([
};
}
/**
* Convert an Open MCT Identifier into a keyString, ex:
* {namespace: 'scratch', key: 'root'} ==> 'scratch:root'
@ -93,9 +94,11 @@ define([
if (isKeyString(identifier)) {
return identifier;
}
if (!identifier.namespace) {
return identifier.key;
}
return [
identifier.namespace.replace(/:/g, '\\:'),
identifier.key
@ -116,6 +119,7 @@ define([
if (model.composition) {
model.composition = model.composition.map(makeKeyString);
}
return model;
}
@ -134,6 +138,7 @@ define([
if (model.composition) {
model.composition = model.composition.map(parseKeyString);
}
return model;
}

View File

@ -31,14 +31,24 @@ define([
registry;
beforeEach(function () {
idA = {key: 'keyA', namespace: 'something'};
idB = {key: 'keyB', namespace: 'something'};
idC = {key: 'keyC', namespace: 'something'};
idA = {
key: 'keyA',
namespace: 'something'
};
idB = {
key: 'keyB',
namespace: 'something'
};
idC = {
key: 'keyC',
namespace: 'something'
};
registry = new RootRegistry();
});
it('can register a root by key', function () {
registry.addRoot(idA);
return registry.getRoots()
.then(function (roots) {
expect(roots).toEqual([idA]);
@ -47,6 +57,7 @@ define([
it('can register multiple roots by key', function () {
registry.addRoot([idA, idB]);
return registry.getRoots()
.then(function (roots) {
expect(roots).toEqual([idA, idB]);
@ -57,6 +68,7 @@ define([
registry.addRoot(function () {
return Promise.resolve(idA);
});
return registry.getRoots()
.then(function (roots) {
expect(roots).toEqual([idA]);
@ -67,6 +79,7 @@ define([
registry.addRoot(function () {
return Promise.resolve([idA, idB]);
});
return registry.getRoots()
.then(function (roots) {
expect(roots).toEqual([idA, idB]);
@ -78,6 +91,7 @@ define([
registry.addRoot(function () {
return Promise.resolve([idC]);
});
return registry.getRoots()
.then(function (roots) {
expect(roots).toEqual([idA, idB, idC]);

View File

@ -5,7 +5,6 @@ define([
) {
describe('objectUtils', function () {
describe('keyString util', function () {
var EXPECTATIONS = {
'ROOT': {

View File

@ -13,7 +13,7 @@ class Overlay extends EventEmitter {
constructor(options) {
super();
this.dismissable = options.dismissable !== false ? true : false;
this.dismissable = options.dismissable !== false;
this.container = document.createElement('div');
this.container.classList.add('l-overlay-wrapper', cssClasses[options.size]);

View File

@ -101,7 +101,6 @@ class OverlayAPI {
return dialog;
}
/**
* Displays a blocking (modal) progress dialog. This dialog can be used for
* displaying messages that require the user's attention, and show progress

View File

@ -23,7 +23,7 @@ class ProgressDialog extends Overlay {
progressPerc: progressPerc || 0,
progressText
}
}
};
},
template: '<progress-dialog-component :model="model"></progress-dialog-component>'
}).$mount();

View File

@ -35,6 +35,6 @@
<script>
export default {
inject:['iconClass', 'title', 'hint', 'timestamp', 'message']
}
inject: ['iconClass', 'title', 'hint', 'timestamp', 'message']
};
</script>

View File

@ -72,6 +72,7 @@ export default {
if (this.buttons[index].emphasis) {
this.focusIndex = index;
}
return this.buttons[index].emphasis;
});
@ -82,5 +83,5 @@ export default {
return focusButton[0];
}
}
}
};
</script>

View File

@ -13,12 +13,12 @@ export default {
DialogComponent: DialogComponent,
ProgressComponent: ProgressComponent
},
inject:['iconClass', 'title', 'hint', 'timestamp', 'message'],
inject: ['iconClass', 'title', 'hint', 'timestamp', 'message'],
props: {
model: {
type: Object,
required: true
}
}
}
};
</script>

View File

@ -44,7 +44,7 @@ define([
* definition has a telemetry property.
*/
DefaultMetadataProvider.prototype.supportsMetadata = function (domainObject) {
return !!domainObject.telemetry || !!this.typeHasTelemetry(domainObject);
return Boolean(domainObject.telemetry) || Boolean(this.typeHasTelemetry(domainObject));
};
/**
@ -82,7 +82,7 @@ define([
_.sortBy(valueMetadata.enumerations.map(function (e) {
return {
string: e.string,
value: +e.value
value: Number(e.value)
};
}), 'e.value');
valueMetadata.values = valueMetadata.enumerations.map(e => e.value);
@ -119,9 +119,9 @@ define([
if (!this.typeService) {
this.typeService = this.openmct.$injector.get('typeService');
}
return !!this.typeService.getType(domainObject.type).typeDef.telemetry;
};
return Boolean(this.typeService.getType(domainObject.type).typeDef.telemetry);
};
return DefaultMetadataProvider;

View File

@ -123,7 +123,6 @@ define([
* @memberof module:openmct.TelemetryAPI~
*/
/**
* An interface for retrieving telemetry data associated with a domain
* object.
@ -152,7 +151,7 @@ define([
* @returns {boolean} true if the object is a telemetry object.
*/
TelemetryAPI.prototype.isTelemetryObject = function (domainObject) {
return !!this.findMetadataProvider(domainObject);
return Boolean(this.findMetadataProvider(domainObject));
};
/**
@ -167,12 +166,13 @@ define([
*/
TelemetryAPI.prototype.canProvideTelemetry = function (domainObject) {
console.warn(
'DEPRECATION WARNING: openmct.telemetry.canProvideTelemetry ' +
'will not be supported in future versions of Open MCT. Please ' +
'use openmct.telemetry.isTelemetryObject instead.'
'DEPRECATION WARNING: openmct.telemetry.canProvideTelemetry '
+ 'will not be supported in future versions of Open MCT. Please '
+ 'use openmct.telemetry.isTelemetryObject instead.'
);
return !!this.findSubscriptionProvider(domainObject) ||
!!this.findRequestProvider(domainObject);
return Boolean(this.findSubscriptionProvider(domainObject))
|| Boolean(this.findRequestProvider(domainObject));
};
/**
@ -187,12 +187,15 @@ define([
if (provider.supportsRequest) {
this.requestProviders.unshift(provider);
}
if (provider.supportsSubscribe) {
this.subscriptionProviders.unshift(provider);
}
if (provider.supportsMetadata) {
this.metadataProviders.unshift(provider);
}
if (provider.supportsLimits) {
this.limitProviders.unshift(provider);
}
@ -247,9 +250,11 @@ define([
if (!options.hasOwnProperty('start')) {
options.start = this.openmct.time.bounds().start;
}
if (!options.hasOwnProperty('end')) {
options.end = this.openmct.time.bounds().end;
}
if (!options.hasOwnProperty('domain')) {
options.domain = this.openmct.time.timeSystem().key;
}
@ -275,14 +280,17 @@ define([
arguments.length = 2;
arguments[1] = {};
}
this.standardizeRequestOptions(arguments[1]);
var provider = this.findRequestProvider.apply(this, arguments);
if (!provider) {
return Promise.reject('No provider found');
}
return provider.request.apply(provider, arguments).catch((rejected) => {
this.openmct.notifications.error('Error requesting telemetry data, see console for details');
console.error(rejected);
return Promise.reject(rejected);
});
};
@ -307,6 +315,7 @@ define([
if (!this.subscribeCache) {
this.subscribeCache = {};
}
var keyString = objectUtils.makeKeyString(domainObject.identifier);
var subscriber = this.subscribeCache[keyString];
@ -352,6 +361,7 @@ define([
if (!metadataProvider) {
return;
}
var metadata = metadataProvider.getMetadata(domainObject);
this.metadataCache.set(
@ -359,6 +369,7 @@ define([
new TelemetryMetadataManager(metadata)
);
}
return this.metadataCache.get(domainObject);
};
@ -370,6 +381,7 @@ define([
TelemetryAPI.prototype.commonValuesForHints = function (metadatas, hints) {
var options = metadatas.map(function (metadata) {
var values = metadata.valuesForHints(hints);
return _.keyBy(values, 'key');
}).reduce(function (a, b) {
var results = {};
@ -378,11 +390,13 @@ define([
results[key] = a[key];
}
});
return results;
});
var sortKeys = hints.map(function (h) {
return 'hints.' + h;
});
return _.sortBy(options, sortKeys);
};
@ -396,11 +410,13 @@ define([
if (!this.formatService) {
this.formatService = this.openmct.$injector.get('formatService');
}
this.valueFormatterCache.set(
valueMetadata,
new TelemetryValueFormatter(valueMetadata, this.formatService)
);
}
return this.valueFormatterCache.get(valueMetadata);
};
@ -414,10 +430,12 @@ define([
if (!this.formatMapCache.has(metadata)) {
var formatMap = metadata.values().reduce(function (map, valueMetadata) {
map[valueMetadata.key] = this.getValueFormatter(valueMetadata);
return map;
}.bind(this), {});
this.formatMapCache.set(metadata, formatMap);
}
return this.formatMapCache.get(metadata);
};
@ -477,6 +495,7 @@ define([
evaluate: function () {}
};
}
return provider.getLimitEvaluator(domainObject);
};

View File

@ -45,7 +45,10 @@ define([
]);
openmct.$injector.get.and.returnValue(mockTypeService);
openmct.time.timeSystem.and.returnValue({key: 'system'});
openmct.time.bounds.and.returnValue({start: 0, end: 1});
openmct.time.bounds.and.returnValue({
start: 0,
end: 1
});
telemetryAPI = new TelemetryAPI(openmct);
});
@ -203,6 +206,7 @@ define([
var unsubFunc = jasmine.createSpy('unsubscribe ' + unsubFuncs.length);
unsubFuncs.push(unsubFunc);
notifiers.push(cb);
return unsubFunc;
});
telemetryAPI.addProvider(telemetryProvider);
@ -343,7 +347,7 @@ define([
}
});
mockTypeService.getType.and.returnValue(mockObjectType);
})
});
it('respects explicit priority', function () {
mockMetadata.values = [
{
@ -554,6 +558,6 @@ define([
expect(values[index].key).toBe(key);
});
});
})
});
});
});

View File

@ -33,25 +33,27 @@ define([
if (valueMetadata.hints.hasOwnProperty('x')) {
console.warn(
'DEPRECATION WARNING: `x` hints should be replaced with ' +
'`domain` hints moving forward. ' +
'https://github.com/nasa/openmct/issues/1546'
'DEPRECATION WARNING: `x` hints should be replaced with '
+ '`domain` hints moving forward. '
+ 'https://github.com/nasa/openmct/issues/1546'
);
if (!valueMetadata.hints.hasOwnProperty('domain')) {
valueMetadata.hints.domain = valueMetadata.hints.x;
}
delete valueMetadata.hints.x;
}
if (valueMetadata.hints.hasOwnProperty('y')) {
console.warn(
'DEPRECATION WARNING: `y` hints should be replaced with ' +
'`range` hints moving forward. ' +
'https://github.com/nasa/openmct/issues/1546'
'DEPRECATION WARNING: `y` hints should be replaced with '
+ '`range` hints moving forward. '
+ 'https://github.com/nasa/openmct/issues/1546'
);
if (!valueMetadata.hints.hasOwnProperty('range')) {
valueMetadata.hints.range = valueMetadata.hints.y;
}
delete valueMetadata.hints.y;
}
@ -59,9 +61,11 @@ define([
if (!valueMetadata.values) {
valueMetadata.values = valueMetadata.enumerations.map(e => e.value);
}
if (!valueMetadata.hasOwnProperty('max')) {
valueMetadata.max = Math.max(valueMetadata.values) + 1;
}
if (!valueMetadata.hasOwnProperty('min')) {
valueMetadata.min = Math.min(valueMetadata.values) - 1;
}
@ -70,6 +74,7 @@ define([
if (!valueMetadata.hints.hasOwnProperty('priority')) {
valueMetadata.hints.priority = index;
}
return valueMetadata;
}
@ -112,21 +117,24 @@ define([
/*jshint validthis: true */
return this.hints.hasOwnProperty(hint);
}
function hasHints(metadata) {
return hints.every(hasHint, metadata);
}
var matchingMetadata = this.valueMetadatas.filter(hasHints);
let iteratees = hints.map(hint => {
return (metadata) => {
return metadata.hints[hint];
}
};
});
return _.sortBy(matchingMetadata, ...iteratees);
};
TelemetryMetadataManager.prototype.getFilterableValues = function () {
return this.valueMetadatas.filter(metadatum => metadatum.filters && metadatum.filters.length > 0);
}
};
TelemetryMetadataManager.prototype.getDefaultDisplayValue = function () {
let valueMetadata = this.valuesForHints(['range'])[0];
@ -144,7 +152,6 @@ define([
return valueMetadata.key;
};
return TelemetryMetadataManager;
});

View File

@ -56,12 +56,17 @@ define([
this.enumerations = valueMetadata.enumerations.reduce(function (vm, e) {
vm.byValue[e.value] = e.string;
vm.byString[e.string] = e.value;
return vm;
}, {byValue: {}, byString: {}});
}, {
byValue: {},
byString: {}
});
this.formatter.format = function (value) {
if (this.enumerations.byValue.hasOwnProperty(value)) {
return this.enumerations.byValue[value];
}
return value;
}.bind(this);
this.formatter.parse = function (string) {
@ -70,9 +75,11 @@ define([
return this.enumerations.byString[string];
}
}
return Number(string);
}.bind(this);
}
// Check for formatString support once instead of per format call.
if (valueMetadata.formatString) {
var baseFormat = this.formatter.format;
@ -81,20 +88,24 @@ define([
return printj.sprintf(formatString, baseFormat.call(this, value));
};
}
if (valueMetadata.format === 'string') {
this.formatter.parse = function (value) {
if (value === undefined) {
return '';
}
if (typeof value === 'string') {
return value;
} else {
return value.toString();
}
};
this.formatter.format = function (value) {
return value;
};
this.formatter.validate = function (value) {
return typeof value === 'string';
};
@ -105,6 +116,7 @@ define([
if (_.isObject(datum)) {
return this.formatter.parse(datum[this.valueMetadata.source]);
}
return this.formatter.parse(datum);
};
@ -112,6 +124,7 @@ define([
if (_.isObject(datum)) {
return this.formatter.format(datum[this.valueMetadata.source]);
}
return this.formatter.format(datum);
};

View File

@ -148,15 +148,16 @@ define(['EventEmitter'], function (EventEmitter) {
* @method validateBounds
*/
TimeAPI.prototype.validateBounds = function (bounds) {
if ((bounds.start === undefined) ||
(bounds.end === undefined) ||
isNaN(bounds.start) ||
isNaN(bounds.end)
if ((bounds.start === undefined)
|| (bounds.end === undefined)
|| isNaN(bounds.start)
|| isNaN(bounds.end)
) {
return "Start and end must be specified as integer values";
} else if (bounds.start > bounds.end) {
return "Specified start date exceeds end bound";
}
return true;
};
@ -169,15 +170,16 @@ define(['EventEmitter'], function (EventEmitter) {
* @method validateBounds
*/
TimeAPI.prototype.validateOffsets = function (offsets) {
if ((offsets.start === undefined) ||
(offsets.end === undefined) ||
isNaN(offsets.start) ||
isNaN(offsets.end)
if ((offsets.start === undefined)
|| (offsets.end === undefined)
|| isNaN(offsets.start)
|| isNaN(offsets.end)
) {
return "Start and end offsets must be specified as integer values";
} else if (offsets.start >= offsets.end) {
return "Specified start offset must be < end offset";
}
return true;
};
@ -207,6 +209,7 @@ define(['EventEmitter'], function (EventEmitter) {
if (validationResult !== true) {
throw new Error(validationResult);
}
//Create a copy to avoid direct mutation of conductor bounds
this.boundsVal = JSON.parse(JSON.stringify(newBounds));
/**
@ -225,6 +228,7 @@ define(['EventEmitter'], function (EventEmitter) {
this.timeOfInterest(undefined);
}
}
//Return a copy to prevent direct mutation of time conductor bounds.
return JSON.parse(JSON.stringify(this.boundsVal));
};
@ -242,10 +246,11 @@ define(['EventEmitter'], function (EventEmitter) {
if (arguments.length >= 1) {
if (arguments.length === 1 && !this.activeClock) {
throw new Error(
"Must specify bounds when changing time system without " +
"an active clock."
"Must specify bounds when changing time system without "
+ "an active clock."
);
}
var timeSystem;
if (timeSystemOrKey === undefined) {
@ -312,6 +317,7 @@ define(['EventEmitter'], function (EventEmitter) {
*/
this.emit('timeOfInterest', this.toi);
}
return this.toi;
};
@ -440,6 +446,7 @@ define(['EventEmitter'], function (EventEmitter) {
*/
this.emit("clockOffsets", offsets);
}
return this.offsets;
};

View File

@ -43,7 +43,10 @@ define(['./TimeAPI'], function (TimeAPI) {
]);
clock.currentValue.and.returnValue(100);
clock.key = clockKey;
bounds = {start: 0, end: 1};
bounds = {
start: 0,
end: 1
};
eventListener = jasmine.createSpy("eventListener");
toi = 111;
});
@ -55,14 +58,20 @@ define(['./TimeAPI'], function (TimeAPI) {
});
it("Allows setting of valid bounds", function () {
bounds = {start: 0, end: 1};
bounds = {
start: 0,
end: 1
};
expect(api.bounds()).not.toBe(bounds);
expect(api.bounds.bind(api, bounds)).not.toThrow();
expect(api.bounds()).toEqual(bounds);
});
it("Disallows setting of invalid bounds", function () {
bounds = {start: 1, end: 0};
bounds = {
start: 1,
end: 0
};
expect(api.bounds()).not.toEqual(bounds);
expect(api.bounds.bind(api, bounds)).toThrow();
expect(api.bounds()).not.toEqual(bounds);
@ -94,7 +103,10 @@ define(['./TimeAPI'], function (TimeAPI) {
it("allows setting of timesystem without bounds with clock", function () {
api.addTimeSystem(timeSystem);
api.addClock(clock);
api.clock(clockKey, {start: 0, end: 1});
api.clock(clockKey, {
start: 0,
end: 1
});
expect(api.timeSystem()).not.toBe(timeSystem);
expect(function () {
api.timeSystem(timeSystemKey);
@ -127,20 +139,25 @@ define(['./TimeAPI'], function (TimeAPI) {
it("If bounds are set and TOI lies inside them, do not change TOI", function () {
api.timeOfInterest(6);
api.bounds({start: 1, end: 10});
api.bounds({
start: 1,
end: 10
});
expect(api.timeOfInterest()).toEqual(6);
});
it("If bounds are set and TOI lies outside them, reset TOI", function () {
api.timeOfInterest(11);
api.bounds({start: 1, end: 10});
api.bounds({
start: 1,
end: 10
});
expect(api.timeOfInterest()).toBeUndefined();
});
it("Maintains delta during tick", function () {
});
it("Allows registered time system to be activated", function () {
});
@ -184,7 +201,10 @@ define(['./TimeAPI'], function (TimeAPI) {
it("sets bounds based on current value", function () {
api.clock("mts", mockOffsets);
expect(api.bounds()).toEqual({start: 10, end: 11});
expect(api.bounds()).toEqual({
start: 10,
end: 11
});
});
it("a new tick listener is registered", function () {

View File

@ -87,7 +87,7 @@ define(function () {
for (let [k, v] of Object.entries(legacyDefinition.model)) {
model[k] = JSON.parse(JSON.stringify(v));
}
}
};
}
if (legacyDefinition.features && legacyDefinition.features.includes("creation")) {

View File

@ -65,14 +65,15 @@ define(['./Type'], function (Type) {
TypeRegistry.prototype.standardizeType = function (typeDef) {
if (typeDef.hasOwnProperty('label')) {
console.warn(
'DEPRECATION WARNING typeDef: ' + typeDef.label + '. ' +
'`label` is deprecated in type definitions. Please use ' +
'`name` instead. This will cause errors in a future version ' +
'of Open MCT. For more information, see ' +
'https://github.com/nasa/openmct/issues/1568');
'DEPRECATION WARNING typeDef: ' + typeDef.label + '. '
+ '`label` is deprecated in type definitions. Please use '
+ '`name` instead. This will cause errors in a future version '
+ 'of Open MCT. For more information, see '
+ 'https://github.com/nasa/openmct/issues/1568');
if (!typeDef.name) {
typeDef.name = typeDef.label;
}
delete typeDef.label;
}
};
@ -104,9 +105,8 @@ define(['./Type'], function (Type) {
let def = Type.definitionFromLegacyDefinition(type);
this.addType(type.key, def);
});
}
};
return TypeRegistry;
});

View File

@ -25,8 +25,8 @@ import {saveAs} from 'file-saver/FileSaver';
class CSVExporter {
export(rows, options) {
let headers = (options && options.headers) ||
(Object.keys((rows[0] || {})).sort());
let headers = (options && options.headers)
|| (Object.keys((rows[0] || {})).sort());
let filename = (options && options.filename) || "export.csv";
let csvText = new CSV(rows, { header: headers }).encode();
let blob = new Blob([csvText], { type: "text/csv" });

View File

@ -22,11 +22,12 @@
export default function ladTableCompositionPolicy(openmct) {
return function (parent, child) {
if(parent.type === 'LadTable') {
if (parent.type === 'LadTable') {
return openmct.telemetry.isTelemetryObject(child);
} else if(parent.type === 'LadTableSet') {
} else if (parent.type === 'LadTableSet') {
return child.type === 'LadTable';
}
return true;
}
};
}

View File

@ -38,7 +38,7 @@ export default function LADTableSetViewProvider(openmct) {
return {
show: function (element) {
component = new Vue({
component = new Vue({
el: element,
components: {
LadTableSet: LadTableSet

View File

@ -38,7 +38,7 @@ export default function LADTableViewProvider(openmct) {
return {
show: function (element) {
component = new Vue({
component = new Vue({
el: element,
components: {
LadTableComponent: LadTable

View File

@ -32,6 +32,12 @@
class="js-third-data"
:class="valueClass"
>{{ value }}</td>
<td
v-if="hasUnits"
class="js-units"
>
{{ unit }}
</td>
</tr>
</template>
@ -48,6 +54,10 @@ export default {
domainObject: {
type: Object,
required: true
},
hasUnits: {
type: Boolean,
requred: true
}
},
data() {
@ -59,8 +69,9 @@ export default {
timestamp: undefined,
value: '---',
valueClass: '',
currentObjectPath
}
currentObjectPath,
unit: ''
};
},
computed: {
formattedTimestamp() {
@ -94,13 +105,17 @@ export default {
.metadata
.valuesForHints(['range'])[0];
this.valueKey = this.valueMetadata.key
this.valueKey = this.valueMetadata.key;
this.unsubscribe = this.openmct
.telemetry
.subscribe(this.domainObject, this.updateValues);
this.requestHistory();
if (this.hasUnits) {
this.setUnit();
}
},
destroyed() {
this.stopWatchingMutation();
@ -113,7 +128,7 @@ export default {
let newTimestamp = this.getParsedTimestamp(datum),
limit;
if(this.shouldUpdate(newTimestamp)) {
if (this.shouldUpdate(newTimestamp)) {
this.timestamp = newTimestamp;
this.value = this.formats[this.valueKey].format(datum);
limit = this.limitEvaluator.evaluate(datum, this.valueMetadata);
@ -129,8 +144,8 @@ export default {
noExistingTimestamp = this.timestamp === undefined,
newTimestampIsLatest = newTimestamp > this.timestamp;
return newTimestampInBounds &&
(noExistingTimestamp || newTimestampIsLatest);
return newTimestampInBounds
&& (noExistingTimestamp || newTimestampIsLatest);
},
requestHistory() {
this.openmct
@ -148,7 +163,7 @@ export default {
},
updateBounds(bounds, isTick) {
this.bounds = bounds;
if(!isTick) {
if (!isTick) {
this.resetValues();
this.requestHistory();
}
@ -169,24 +184,28 @@ export default {
this.valueClass = '';
},
getParsedTimestamp(timestamp) {
if(this.timeSystemFormat()) {
if (this.timeSystemFormat()) {
return this.formats[this.timestampKey].parse(timestamp);
}
},
getFormattedTimestamp(timestamp) {
if(this.timeSystemFormat()) {
if (this.timeSystemFormat()) {
return this.formats[this.timestampKey].format(timestamp);
}
},
timeSystemFormat() {
if(this.formats[this.timestampKey]) {
if (this.formats[this.timestampKey]) {
return true;
} else {
console.warn(`No formatter for ${this.timestampKey} time system for ${this.domainObject.name}.`);
return false;
}
},
setUnit() {
this.unit = this.valueMetadata.unit || '';
}
}
}
};
</script>

View File

@ -28,6 +28,7 @@
<th>Name</th>
<th>Timestamp</th>
<th>Value</th>
<th v-if="hasUnits">Unit</th>
</tr>
</thead>
<tbody>
@ -35,6 +36,7 @@
v-for="item in items"
:key="item.key"
:domain-object="item.domainObject"
:has-units="hasUnits"
/>
</tbody>
</table>
@ -52,6 +54,18 @@ export default {
data() {
return {
items: []
};
},
computed: {
hasUnits() {
let itemsWithUnits = this.items.filter((item) => {
let metadata = this.openmct.telemetry.getMetadata(item.domainObject);
return this.metadataHasUnits(metadata.valueMetadatas);
});
return itemsWithUnits.length !== 0;
}
},
mounted() {
@ -84,7 +98,12 @@ export default {
reorderPlan.forEach((reorderEvent) => {
this.$set(this.items, reorderEvent.newIndex, oldItems[reorderEvent.oldIndex]);
});
},
metadataHasUnits(valueMetadatas) {
let metadataWithUnits = valueMetadatas.filter(metadatum => metadatum.unit);
return metadataWithUnits.length > 0;
}
}
}
};
</script>

View File

@ -27,6 +27,7 @@
<th>Name</th>
<th>Timestamp</th>
<th>Value</th>
<th v-if="hasUnits">Unit</th>
</tr>
</thead>
<tbody>
@ -45,6 +46,7 @@
v-for="secondary in secondaryTelemetryObjects[primary.key]"
:key="secondary.key"
:domain-object="secondary.domainObject"
:has-units="hasUnits"
/>
</template>
</tbody>
@ -64,6 +66,23 @@ export default {
primaryTelemetryObjects: [],
secondaryTelemetryObjects: {},
compositions: []
};
},
computed: {
hasUnits() {
let ladTables = Object.values(this.secondaryTelemetryObjects);
for (let ladTable of ladTables) {
for (let telemetryObject of ladTable) {
let metadata = this.openmct.telemetry.getMetadata(telemetryObject.domainObject);
for (let metadatum of metadata.valueMetadatas) {
if (metadatum.unit) {
return true;
}
}
}
}
return false;
}
},
mounted() {
@ -99,15 +118,18 @@ export default {
composition.on('remove', removeCallback);
composition.load();
this.compositions.push({composition, addCallback, removeCallback});
this.compositions.push({
composition,
addCallback,
removeCallback
});
},
removePrimary(identifier) {
let index = this.primaryTelemetryObjects.findIndex(primary => this.openmct.objects.makeKeyString(identifier) === primary.key),
primary = this.primaryTelemetryObjects[index];
this.$set(this.secondaryTelemetryObjects, primary.key, undefined);
this.primaryTelemetryObjects.splice(index,1);
primary = undefined;
this.$delete(this.secondaryTelemetryObjects, primary.key);
this.primaryTelemetryObjects.splice(index, 1);
},
reorderPrimary(reorderPlan) {
let oldComposition = this.primaryTelemetryObjects.slice();
@ -125,7 +147,7 @@ export default {
array.push(secondary);
this.$set(this.secondaryTelemetryObjects, primary.key, array);
}
};
},
removeSecondary(primary) {
return (identifier) => {
@ -135,8 +157,8 @@ export default {
array.splice(index, 1);
this.$set(this.secondaryTelemetryObjects, primary.key, array);
}
};
}
}
}
};
</script>

View File

@ -37,7 +37,7 @@ const TABLE_BODY_FIRST_ROW_THIRD_DATA = TABLE_BODY_FIRST_ROW + ' .js-third-data'
const LAD_SET_TABLE_HEADERS = '.js-lad-table-set__table-headers';
function utcTimeFormat(value) {
return new Date(value).toISOString().replace('T', ' ')
return new Date(value).toISOString().replace('T', ' ');
}
describe("The LAD Table", () => {
@ -49,7 +49,10 @@ describe("The LAD Table", () => {
child,
telemetryCount = 3,
timeFormat = 'utc',
mockTelemetry = getMockTelemetry({ count: telemetryCount, format: timeFormat }),
mockTelemetry = getMockTelemetry({
count: telemetryCount,
format: timeFormat
}),
mockObj = getMockObjects({
objectKeyStrings: ['ladTable', 'telemetry'],
format: timeFormat
@ -81,7 +84,10 @@ describe("The LAD Table", () => {
spyOn(openmct.objects, 'get').and.returnValue(Promise.resolve({}));
openmct.time.bounds({ start: bounds.start, end: bounds.end });
openmct.time.bounds({
start: bounds.start,
end: bounds.end
});
openmct.on('start', done);
openmct.startHeadless(appHolder);
@ -116,7 +122,7 @@ describe("The LAD Table", () => {
});
it("should reject non-telemtry producing objects", () => {
expect(()=> {
expect(() => {
ladTableCompositionCollection.add(mockObj.ladTable);
}).toThrow();
});
@ -131,7 +137,10 @@ describe("The LAD Table", () => {
overwrite: {
telemetry: {
name: "New Telemetry Object",
identifier: { namespace: "", key: "another-telemetry-object" }
identifier: {
namespace: "",
key: "another-telemetry-object"
}
}
}
}).telemetry;
@ -151,22 +160,28 @@ describe("The LAD Table", () => {
}),
anotherTelemetryObjectPromise = new Promise((resolve) => {
anotherTelemetryObjectResolve = resolve;
})
});
openmct.telemetry.request.and.callFake(() => {
telemetryRequestResolve(mockTelemetry);
return telemetryRequestPromise;
});
openmct.objects.get.and.callFake((obj) => {
if(obj.key === 'telemetry-object') {
if (obj.key === 'telemetry-object') {
telemetryObjectResolve(mockObj.telemetry);
return telemetryObjectPromise;
} else {
anotherTelemetryObjectResolve(anotherTelemetryObj);
return anotherTelemetryObjectPromise;
}
});
openmct.time.bounds({ start: bounds.start, end: bounds.end });
openmct.time.bounds({
start: bounds.start,
end: bounds.end
});
applicableViews = openmct.objectViews.get(mockObj.ladTable);
ladTableViewProvider = applicableViews.find((viewProvider) => viewProvider.key === ladTableKey);
@ -175,6 +190,7 @@ describe("The LAD Table", () => {
await Promise.all([telemetryRequestPromise, telemetryObjectPromise, anotherTelemetryObjectPromise]);
await Vue.nextTick();
return;
});
@ -225,7 +241,10 @@ describe("The LAD Table Set", () => {
child,
telemetryCount = 3,
timeFormat = 'utc',
mockTelemetry = getMockTelemetry({ count: telemetryCount, format: timeFormat }),
mockTelemetry = getMockTelemetry({
count: telemetryCount,
format: timeFormat
}),
mockObj = getMockObjects({
objectKeyStrings: ['ladTable', 'ladTableSet', 'telemetry']
}),
@ -255,7 +274,10 @@ describe("The LAD Table Set", () => {
spyOn(openmct.objects, 'get').and.returnValue(Promise.resolve({}));
openmct.time.bounds({ start: bounds.start, end: bounds.end });
openmct.time.bounds({
start: bounds.start,
end: bounds.end
});
openmct.on('start', done);
openmct.start(appHolder);
@ -290,7 +312,7 @@ describe("The LAD Table Set", () => {
});
it("should reject non lad table objects", () => {
expect(()=> {
expect(() => {
ladTableSetCompositionCollection.add(mockObj.telemetry);
}).toThrow();
});
@ -305,7 +327,10 @@ describe("The LAD Table Set", () => {
overwrite: {
ladTable: {
name: "New LAD Table Object",
identifier: { namespace: "", key: "another-lad-object" }
identifier: {
namespace: "",
key: "another-lad-object"
}
}
}
});
@ -326,24 +351,30 @@ describe("The LAD Table Set", () => {
}),
anotherLadObjectPromise = new Promise((resolve) => {
anotherLadObjectResolve = resolve;
})
});
openmct.telemetry.request.and.callFake(() => {
telemetryRequestResolve(mockTelemetry);
return telemetryRequestPromise;
});
openmct.objects.get.and.callFake((obj) => {
if(obj.key === 'lad-object') {
if (obj.key === 'lad-object') {
ladObjectResolve(mockObj.ladObject);
return ladObjectPromise;
} else if(obj.key === 'another-lad-object') {
} else if (obj.key === 'another-lad-object') {
anotherLadObjectResolve(otherObj.ladObject);
return anotherLadObjectPromise;
}
return Promise.resolve({});
});
openmct.time.bounds({ start: bounds.start, end: bounds.end });
openmct.time.bounds({
start: bounds.start,
end: bounds.end
});
applicableViews = openmct.objectViews.get(mockObj.ladTableSet);
ladTableSetViewProvider = applicableViews.find((viewProvider) => viewProvider.key === ladTableSetKey);
@ -352,6 +383,7 @@ describe("The LAD Table Set", () => {
await Promise.all([telemetryRequestPromise, ladObjectPromise, anotherLadObjectPromise]);
await Vue.nextTick();
return;
});

View File

@ -57,11 +57,13 @@ define(
this.indicator.description(this.label + " is online, checking status every " + this.interval + " milliseconds.");
break;
}
case PENDING: {
this.indicator.text("Checking status of " + this.label + " please stand by...");
this.indicator.description("Checking status of " + this.label + " please stand by...");
break;
}
case DISCONNECTED: {
this.indicator.text(this.label + " is offline");
this.indicator.description(this.label + " is offline, checking status every " + this.interval + " milliseconds");

View File

@ -122,18 +122,20 @@ export default class URLTimeSettingsSynchronizer {
} else if (!this.areStartAndEndEqual(this.openmct.time.bounds(), timeParameters.bounds)) {
this.openmct.time.bounds(timeParameters.bounds);
}
if (this.openmct.time.clock()) {
this.openmct.time.stopClock();
}
} else {
if (!this.openmct.time.clock() ||
this.openmct.time.clock().key !== timeParameters.mode) {
if (!this.openmct.time.clock()
|| this.openmct.time.clock().key !== timeParameters.mode) {
this.openmct.time.clock(timeParameters.mode, timeParameters.clockOffsets);
} else if (!this.areStartAndEndEqual(this.openmct.time.clockOffsets(), timeParameters.clockOffsets)) {
this.openmct.time.clockOffsets(timeParameters.clockOffsets);
}
if (!this.openmct.time.timeSystem() ||
this.openmct.time.timeSystem().key !== timeParameters.timeSystem) {
if (!this.openmct.time.timeSystem()
|| this.openmct.time.timeSystem().key !== timeParameters.timeSystem) {
this.openmct.time.timeSystem(timeParameters.timeSystem);
}
}
@ -168,6 +170,7 @@ export default class URLTimeSettingsSynchronizer {
searchParams.delete(SEARCH_START_DELTA);
searchParams.delete(SEARCH_END_DELTA);
}
searchParams.delete(SEARCH_START_BOUND);
searchParams.delete(SEARCH_END_BOUND);
}
@ -180,8 +183,8 @@ export default class URLTimeSettingsSynchronizer {
areTimeParametersValid(timeParameters) {
let isValid = false;
if (this.isModeValid(timeParameters.mode) &&
this.isTimeSystemValid(timeParameters.timeSystem)) {
if (this.isModeValid(timeParameters.mode)
&& this.isTimeSystemValid(timeParameters.timeSystem)) {
if (timeParameters.mode === 'fixed') {
isValid = this.areStartAndEndValid(timeParameters.bounds);
@ -194,13 +197,13 @@ export default class URLTimeSettingsSynchronizer {
}
areStartAndEndValid(bounds) {
return bounds !== undefined &&
bounds.start !== undefined &&
bounds.start !== null &&
bounds.end !== undefined &&
bounds.start !== null &&
!isNaN(bounds.start) &&
!isNaN(bounds.end);
return bounds !== undefined
&& bounds.start !== undefined
&& bounds.start !== null
&& bounds.end !== undefined
&& bounds.start !== null
&& !isNaN(bounds.start)
&& !isNaN(bounds.end);
}
isTimeSystemValid(timeSystem) {
@ -209,14 +212,15 @@ export default class URLTimeSettingsSynchronizer {
let timeSystemObject = this.openmct.time.timeSystems.get(timeSystem);
isValid = timeSystemObject !== undefined;
}
return isValid;
}
isModeValid(mode) {
let isValid = false;
if (mode !== undefined &&
mode !== null) {
if (mode !== undefined
&& mode !== null) {
isValid = true;
}
@ -227,11 +231,12 @@ export default class URLTimeSettingsSynchronizer {
isValid = this.openmct.time.clocks.get(mode) !== undefined;
}
}
return isValid;
}
areStartAndEndEqual(firstBounds, secondBounds) {
return firstBounds.start === secondBounds.start &&
firstBounds.end === secondBounds.end;
return firstBounds.start === secondBounds.start
&& firstBounds.end === secondBounds.end;
}
}

View File

@ -24,5 +24,5 @@ import URLTimeSettingsSynchronizer from "./URLTimeSettingsSynchronizer.js";
export default function () {
return function install(openmct) {
return new URLTimeSettingsSynchronizer(openmct);
}
};
}

View File

@ -49,7 +49,10 @@ describe("The URLTimeSettingsSynchronizer", () => {
//Test expected initial conditions
expect(window.location.hash.includes('tc.mode=fixed')).toBe(true);
openmct.time.clock('local', {start: -1000, end: 100});
openmct.time.clock('local', {
start: -1000,
end: 100
});
expect(window.location.hash.includes('tc.mode=local')).toBe(true);
@ -61,11 +64,17 @@ describe("The URLTimeSettingsSynchronizer", () => {
expect(window.location.hash.includes('tc.startDelta')).toBe(false);
expect(window.location.hash.includes('tc.endDelta')).toBe(false);
openmct.time.clock('local', {start: -1000, end: 100});
openmct.time.clock('local', {
start: -1000,
end: 100
});
expect(window.location.hash.includes('tc.startDelta=1000')).toBe(true);
expect(window.location.hash.includes('tc.endDelta=100')).toBe(true);
openmct.time.clockOffsets({start: -2000, end: 200});
openmct.time.clockOffsets({
start: -2000,
end: 200
});
expect(window.location.hash.includes('tc.startDelta=2000')).toBe(true);
expect(window.location.hash.includes('tc.endDelta=200')).toBe(true);
@ -75,6 +84,7 @@ describe("The URLTimeSettingsSynchronizer", () => {
describe("when set in the url", () => {
it("will change from fixed to realtime mode when the mode changes", () => {
expectLocationToBeInFixedMode();
return switchToRealtimeMode().then(() => {
let clock = openmct.time.clock();
@ -85,6 +95,7 @@ describe("The URLTimeSettingsSynchronizer", () => {
it("the clock is correctly set in the API from the URL parameters", () => {
return switchToRealtimeMode().then(() => {
let resolveFunction;
return new Promise((resolve) => {
resolveFunction = resolve;
@ -105,6 +116,7 @@ describe("The URLTimeSettingsSynchronizer", () => {
it("the clock offsets are correctly set in the API from the URL parameters", () => {
return switchToRealtimeMode().then(() => {
let resolveFunction;
return new Promise((resolve) => {
resolveFunction = resolve;
//The 'hashchange' event appears to be asynchronous, so we need to wait until a clock change has been
@ -126,6 +138,7 @@ describe("The URLTimeSettingsSynchronizer", () => {
it("the time system is correctly set in the API from the URL parameters", () => {
return switchToRealtimeMode().then(() => {
let resolveFunction;
return new Promise((resolve) => {
resolveFunction = resolve;
@ -148,15 +161,21 @@ describe("The URLTimeSettingsSynchronizer", () => {
describe("fixed timespan mode", () => {
beforeEach(() => {
openmct.time.stopClock();
openmct.time.timeSystem('utc', {start: 0, end: 1});
openmct.time.timeSystem('utc', {
start: 0,
end: 1
});
});
it("when bounds are set via the time API, they are immediately reflected in the URL", ()=>{
it("when bounds are set via the time API, they are immediately reflected in the URL", () => {
//Test expected initial conditions
expect(window.location.hash.includes('tc.startBound=0')).toBe(true);
expect(window.location.hash.includes('tc.endBound=1')).toBe(true);
openmct.time.bounds({start: 10, end: 20});
openmct.time.bounds({
start: 10,
end: 20
});
expect(window.location.hash.includes('tc.startBound=10')).toBe(true);
expect(window.location.hash.includes('tc.endBound=20')).toBe(true);
@ -166,11 +185,14 @@ describe("The URLTimeSettingsSynchronizer", () => {
expect(window.location.hash.includes('tc.endBound=1')).toBe(false);
});
it("when time system is set via the time API, it is immediately reflected in the URL", ()=>{
it("when time system is set via the time API, it is immediately reflected in the URL", () => {
//Test expected initial conditions
expect(window.location.hash.includes('tc.timeSystem=utc')).toBe(true);
openmct.time.timeSystem('local', {start: 20, end: 30});
openmct.time.timeSystem('local', {
start: 20,
end: 30
});
expect(window.location.hash.includes('tc.timeSystem=local')).toBe(true);
@ -269,6 +291,7 @@ describe("The URLTimeSettingsSynchronizer", () => {
function switchToRealtimeMode() {
let resolveFunction;
return new Promise((resolve) => {
resolveFunction = resolve;
openmct.time.on('clock', resolveFunction);
@ -280,6 +303,7 @@ describe("The URLTimeSettingsSynchronizer", () => {
function switchToFixedMode() {
let resolveFunction;
return new Promise((resolve) => {
resolveFunction = resolve;
//The 'hashchange' event appears to be asynchronous, so we need to wait until a clock change has been

View File

@ -102,7 +102,10 @@ define([
testKeys = ['abc', 'def', 'xyz'];
testChildren = testKeys.map(function (key) {
return {
identifier: { namespace: "test", key: key },
identifier: {
namespace: "test",
key: key
},
name: "Object " + key
};
});
@ -110,7 +113,12 @@ define([
domObserver = new DOMObserver(testContainer);
testHistories = testKeys.reduce(function (histories, key, index) {
histories[key] = { key: key, range: index + 10, domain: key + index };
histories[key] = {
key: key,
range: index + 10,
domain: key + index
};
return histories;
}, {});
@ -122,12 +130,14 @@ define([
mockEvaluator = jasmine.createSpyObj('evaluator', ['evaluate']);
mockUnsubscribes = testKeys.reduce(function (map, key) {
map[key] = jasmine.createSpy('unsubscribe-' + key);
return map;
}, {});
mockmct.composition.get.and.returnValue(mockComposition);
mockComposition.load.and.callFake(function () {
testChildren.forEach(emitEvent.bind(null, mockComposition, 'add'));
return Promise.resolve(testChildren);
});
@ -137,16 +147,19 @@ define([
mockFormatter.format.and.callFake(function (datum) {
return datum[metadatum.hint];
});
return mockFormatter;
});
mockmct.telemetry.limitEvaluator.and.returnValue(mockEvaluator);
mockmct.telemetry.subscribe.and.callFake(function (obj, callback) {
var key = obj.identifier.key;
callbacks[key] = callback;
return mockUnsubscribes[key];
});
mockmct.telemetry.request.and.callFake(function (obj, request) {
var key = obj.identifier.key;
return Promise.resolve([testHistories[key]]);
});
mockMetadata.valuesForHints.and.callFake(function (hints) {
@ -170,6 +183,7 @@ define([
describe("when rows have been populated", function () {
function rowsMatch() {
var rows = $(testContainer).find(".l-autoflow-row").length;
return rows === testChildren.length;
}
@ -179,17 +193,22 @@ define([
it("adds rows on composition change", function () {
var child = {
identifier: { namespace: "test", key: "123" },
identifier: {
namespace: "test",
key: "123"
},
name: "Object 123"
};
testChildren.push(child);
emitEvent(mockComposition, 'add', child);
return domObserver.when(rowsMatch);
});
it("removes rows on composition change", function () {
var child = testChildren.pop();
emitEvent(mockComposition, 'remove', child.identifier);
return domObserver.when(rowsMatch);
});
});
@ -216,6 +235,7 @@ define([
function widthHasChanged() {
var width = $(testContainer).find('.l-autoflow-col').css('width');
return width !== initialWidth + 'px';
}
@ -236,6 +256,7 @@ define([
function rowTextDefined() {
return $(testContainer).find(".l-autoflow-item").filter(".r").text() !== "";
}
return domObserver.when(rowTextDefined).then(function () {
testKeys.forEach(function (key, index) {
var datum = testHistories[key];
@ -247,7 +268,11 @@ define([
it("displays incoming telemetry", function () {
var testData = testKeys.map(function (key, index) {
return { key: key, range: index * 100, domain: key + index };
return {
key: key,
range: index * 100,
domain: key + index
};
});
testData.forEach(function (datum) {
@ -266,7 +291,10 @@ define([
var testClass = "some-limit-violation";
mockEvaluator.evaluate.and.returnValue({ cssClass: testClass });
testKeys.forEach(function (key) {
callbacks[key]({ range: 'foo', domain: 'bar' });
callbacks[key]({
range: 'foo',
domain: 'bar'
});
});
return waitsForChange().then(function () {
@ -306,12 +334,14 @@ define([
function setHeight(height) {
$container.css('height', height + 'px');
return domObserver.when(columnsHaveAutoflowed);
}
for (var height = 0; height < rowHeight * count * 2; height += rowHeight / 2) {
promiseChain = promiseChain.then(setHeight.bind(this, height));
}
return promiseChain.then(function () {
$container.remove();
});

View File

@ -58,8 +58,8 @@ define([
methods: {
increaseColumnWidth: function () {
data.width += COLUMN_WIDTH_STEP;
data.width = data.width > MAX_COLUMN_WIDTH ?
INITIAL_COLUMN_WIDTH : data.width;
data.width = data.width > MAX_COLUMN_WIDTH
? INITIAL_COLUMN_WIDTH : data.width;
},
reflow: function () {
var column = [];

View File

@ -26,6 +26,7 @@ define(['vue'], function (Vue) {
this.show = function (container) {
container.appendChild(vm.$mount().$el);
};
this.destroy = vm.$destroy.bind(vm);
}

View File

@ -33,7 +33,11 @@ define([], function () {
resolve();
} else {
//Latch condition not true yet, create observer on DOM and test again on change.
var config = { attributes: true, childList: true, subtree: true };
var config = {
attributes: true,
childList: true,
subtree: true
};
var observer = new MutationObserver(function () {
if (latchFunction()) {
resolve();

View File

@ -29,7 +29,10 @@ define([
beforeEach(function () {
mockmct = jasmine.createSpyObj('openmct', ['legacyExtension']);
testInfo = { foo: 123, bar: "baz" };
testInfo = {
foo: 123,
bar: "baz"
};
plugin(testInfo)(mockmct);
});

View File

@ -14,5 +14,5 @@ export default {
this.openmct.objectViews.emit('clearData');
}
}
}
};
</script>

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import ClearDataActionPlugin from '../plugin.js';
import ClearDataActionPlugin from '../plugin.js';
import ClearDataAction from '../clearDataAction.js';
describe('When the Clear Data Plugin is installed,', function () {

View File

@ -63,6 +63,7 @@ export default class Condition extends EventEmitter {
if (conditionConfiguration.configuration.criteria) {
this.createCriteria(conditionConfiguration.configuration.criteria);
}
this.trigger = conditionConfiguration.configuration.trigger;
this.description = '';
}
@ -70,6 +71,7 @@ export default class Condition extends EventEmitter {
getResult(datum) {
if (!datum || !datum.id) {
console.log('no data received');
return;
}
@ -149,24 +151,27 @@ export default class Condition extends EventEmitter {
} else {
criterion = new TelemetryCriterion(criterionConfigurationWithId, this.openmct);
}
criterion.on('criterionUpdated', (obj) => this.handleCriterionUpdated(obj));
criterion.on('telemetryIsStale', (obj) => this.handleStaleCriterion(obj));
if (!this.criteria) {
this.criteria = [];
}
this.criteria.push(criterion);
return criterionConfigurationWithId.id;
}
findCriterion(id) {
let criterion;
for (let i=0, ii=this.criteria.length; i < ii; i ++) {
for (let i = 0, ii = this.criteria.length; i < ii; i++) {
if (this.criteria[i].id === id) {
criterion = {
item: this.criteria[i],
index: i
}
};
}
}
@ -206,6 +211,7 @@ export default class Condition extends EventEmitter {
return true;
}
return false;
}
@ -236,6 +242,7 @@ export default class Condition extends EventEmitter {
if (!index) {
description = `Match if ${triggerDescription.prefix}`;
}
description = `${description} ${criterion.getDescription()} ${(index < this.criteria.length - 1) ? triggerDescription.conjunction : ''}`;
});
this.description = description;
@ -260,8 +267,9 @@ export default class Condition extends EventEmitter {
results.forEach(resultObj => {
const { id, data, data: { result } } = resultObj;
if (this.findCriterion(id)) {
criteriaResults[id] = !!result;
criteriaResults[id] = Boolean(result);
}
latestTimestamp = getLatestTimestamp(
latestTimestamp,
data,
@ -269,6 +277,7 @@ export default class Condition extends EventEmitter {
this.openmct.time.timeSystem()
);
});
return {
id: this.id,
data: Object.assign(
@ -287,9 +296,10 @@ export default class Condition extends EventEmitter {
destroyCriteria() {
let success = true;
//looping through the array backwards since destroyCriterion modifies the criteria array
for (let i=this.criteria.length-1; i >= 0; i--) {
for (let i = this.criteria.length - 1; i >= 0; i--) {
success = success && this.destroyCriterion(this.criteria[i].id);
}
return success;
}

View File

@ -37,7 +37,10 @@ export default class ConditionManager extends EventEmitter {
this.compositionLoad = this.composition.load();
this.subscriptions = {};
this.telemetryObjects = {};
this.testData = {conditionTestData: [], applied: false};
this.testData = {
conditionTestData: [],
applied: false
};
this.initialize();
this.stopObservingForChanges = this.openmct.objects.observe(this.conditionSetDomainObject, '*', (newDomainObject) => {
@ -50,8 +53,10 @@ export default class ConditionManager extends EventEmitter {
const id = this.openmct.objects.makeKeyString(endpoint.identifier);
if (this.subscriptions[id]) {
console.log('subscription already exists');
return;
}
this.telemetryObjects[id] = Object.assign({}, endpoint, {telemetryMetaData: this.openmct.telemetry.getMetadata(endpoint).valueMetadatas});
this.subscriptions[id] = this.openmct.telemetry.subscribe(
endpoint,
@ -64,6 +69,7 @@ export default class ConditionManager extends EventEmitter {
const id = this.openmct.objects.makeKeyString(endpointIdentifier);
if (!this.subscriptions[id]) {
console.log('no subscription to remove');
return;
}
@ -189,6 +195,7 @@ export default class ConditionManager extends EventEmitter {
} else {
this.conditionSetDomainObject.configuration.conditionCollection.unshift(newCondition);
}
this.initCondition(newCondition, index);
this.persistConditions();
}
@ -218,10 +225,10 @@ export default class ConditionManager extends EventEmitter {
getCurrentCondition() {
const conditionCollection = this.conditionSetDomainObject.configuration.conditionCollection;
let currentCondition = conditionCollection[conditionCollection.length-1];
let currentCondition = conditionCollection[conditionCollection.length - 1];
for (let i = 0; i < conditionCollection.length - 1; i++) {
const condition = this.findConditionById(conditionCollection[i].id)
const condition = this.findConditionById(conditionCollection[i].id);
if (condition.result) {
//first condition to be true wins
currentCondition = conditionCollection[i];
@ -234,7 +241,7 @@ export default class ConditionManager extends EventEmitter {
getCurrentConditionLAD(conditionResults) {
const conditionCollection = this.conditionSetDomainObject.configuration.conditionCollection;
let currentCondition = conditionCollection[conditionCollection.length-1];
let currentCondition = conditionCollection[conditionCollection.length - 1];
for (let i = 0; i < conditionCollection.length - 1; i++) {
if (conditionResults[conditionCollection[i].id]) {
@ -243,6 +250,7 @@ export default class ConditionManager extends EventEmitter {
break;
}
}
return currentCondition;
}
@ -262,8 +270,9 @@ export default class ConditionManager extends EventEmitter {
results.forEach(resultObj => {
const { id, data, data: { result } } = resultObj;
if (this.findConditionById(id)) {
conditionResults[id] = !!result;
conditionResults[id] = Boolean(result);
}
latestTimestamp = getLatestTimestamp(
latestTimestamp,
data,
@ -294,7 +303,7 @@ export default class ConditionManager extends EventEmitter {
isTelemetryUsed(endpoint) {
const id = this.openmct.objects.makeKeyString(endpoint.identifier);
for(const condition of this.conditions) {
for (const condition of this.conditions) {
if (condition.isTelemetryUsed(id)) {
return true;
}
@ -332,7 +341,7 @@ export default class ConditionManager extends EventEmitter {
},
timestamp
)
)
);
}
getTestData(metadatum) {
@ -343,6 +352,7 @@ export default class ConditionManager extends EventEmitter {
data = found.value;
}
}
return data;
}
@ -353,7 +363,8 @@ export default class ConditionManager extends EventEmitter {
const normalizedDatum = Object.values(metadata).reduce((datum, metadatum) => {
const testValue = this.getTestData(metadatum);
const formatter = this.openmct.telemetry.getValueFormatter(metadatum);
datum[metadatum.key] = testValue !== undefined ? formatter.parse(testValue) : formatter.parse(telemetryDatum[metadatum.source]);
datum[metadatum.key] = testValue !== undefined ? formatter.parse(testValue) : formatter.parse(telemetryDatum[metadatum.source]);
return datum;
}, {});
@ -377,12 +388,12 @@ export default class ConditionManager extends EventEmitter {
Object.values(this.subscriptions).forEach(unsubscribe => unsubscribe());
delete this.subscriptions;
if(this.stopObservingForChanges) {
if (this.stopObservingForChanges) {
this.stopObservingForChanges();
}
this.conditions.forEach((condition) => {
condition.destroy();
})
});
}
}

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import ConditionManager from './ConditionManager';
import ConditionManager from './ConditionManager';
describe('ConditionManager', () => {
@ -93,6 +93,7 @@ describe('ConditionManager', () => {
setTimeout(() => {
loader.resolve();
});
return loader.promise;
});
mockComposition.on('add', mockListener);

View File

@ -29,5 +29,5 @@ export default function ConditionSetCompositionPolicy(openmct) {
return true;
}
}
};
}

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import ConditionSetCompositionPolicy from './ConditionSetCompositionPolicy';
import ConditionSetCompositionPolicy from './ConditionSetCompositionPolicy';
describe('ConditionSetCompositionPolicy', () => {
@ -31,7 +31,10 @@ describe('ConditionSetCompositionPolicy', () => {
beforeAll(function () {
testTelemetryObject = {
identifier:{ namespace: "", key: "test-object"},
identifier: {
namespace: "",
key: "test-object"
},
type: "test-object",
name: "Test Object",
telemetry: {

View File

@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
import ConditionManager from './ConditionManager'
import ConditionManager from './ConditionManager';
export default class ConditionSetTelemetryProvider {
constructor(openmct) {

View File

@ -27,7 +27,8 @@ ConditionSetViewPolicy.prototype.allow = function (view, domainObject) {
if (domainObject.getModel().type === 'conditionSet') {
return view.key === 'conditionSet.view';
}
return true;
}
};
export default ConditionSetViewPolicy;

View File

@ -44,6 +44,7 @@ export default class ConditionSetViewProvider {
view(domainObject, objectPath) {
let component;
const openmct = this.openmct;
return {
show: (container, isEditing) => {
component = new Vue({
@ -59,7 +60,7 @@ export default class ConditionSetViewProvider {
data() {
return {
isEditing
}
};
},
template: '<condition-set :isEditing="isEditing"></condition-set>'
});

View File

@ -43,7 +43,10 @@ describe("The condition", function () {
conditionManager.updateConditionDescription.and.returnValue(function () {});
testTelemetryObject = {
identifier:{ namespace: "", key: "test-object"},
identifier: {
namespace: "",
key: "test-object"
},
type: "test-object",
name: "Test Object",
telemetry: {
@ -75,7 +78,7 @@ describe("The condition", function () {
openmct.objects = jasmine.createSpyObj('objects', ['get', 'makeKeyString']);
openmct.objects.get.and.returnValue(new Promise(function (resolve, reject) {
resolve(testTelemetryObject);
})); openmct.objects.makeKeyString.and.returnValue(testTelemetryObject.identifier.key);
})); openmct.objects.makeKeyString.and.returnValue(testTelemetryObject.identifier.key);
openmct.telemetry = jasmine.createSpyObj('telemetry', ['isTelemetryObject', 'subscribe', 'getMetadata']);
openmct.telemetry.isTelemetryObject.and.returnValue(true);
openmct.telemetry.subscribe.and.returnValue(function () {});

View File

@ -31,6 +31,7 @@ export default class StyleRuleManager extends EventEmitter {
this.openmct.editor.on('isEditing', this.toggleSubscription.bind(this));
this.isEditing = this.openmct.editor.editing;
}
if (styleConfiguration) {
this.initialize(styleConfiguration);
if (styleConfiguration.conditionSetIdentifier) {
@ -48,6 +49,7 @@ export default class StyleRuleManager extends EventEmitter {
this.stopProvidingTelemetry();
delete this.stopProvidingTelemetry;
}
if (this.conditionSetIdentifier) {
this.applySelectedConditionStyle();
}
@ -69,6 +71,7 @@ export default class StyleRuleManager extends EventEmitter {
this.stopProvidingTelemetry();
delete this.stopProvidingTelemetry;
}
this.openmct.objects.get(this.conditionSetIdentifier).then((conditionSetDomainObject) => {
this.openmct.telemetry.request(conditionSetDomainObject)
.then(output => {
@ -85,8 +88,8 @@ export default class StyleRuleManager extends EventEmitter {
this.initialize(styleConfiguration || {});
this.destroy();
} else {
let isNewConditionSet = !this.conditionSetIdentifier ||
!this.openmct.objects.areIdsEqual(this.conditionSetIdentifier, styleConfiguration.conditionSetIdentifier);
let isNewConditionSet = !this.conditionSetIdentifier
|| !this.openmct.objects.areIdsEqual(this.conditionSetIdentifier, styleConfiguration.conditionSetIdentifier);
this.initialize(styleConfiguration);
if (this.isEditing) {
this.applySelectedConditionStyle();
@ -117,6 +120,7 @@ export default class StyleRuleManager extends EventEmitter {
if (foundStyle !== this.currentStyle) {
this.currentStyle = foundStyle;
}
this.updateDomainObjectStyle();
} else {
this.applyStaticStyle();
@ -149,6 +153,7 @@ export default class StyleRuleManager extends EventEmitter {
});
}
}
this.updateDomainObjectStyle();
}
@ -158,6 +163,7 @@ export default class StyleRuleManager extends EventEmitter {
this.stopProvidingTelemetry();
delete this.stopProvidingTelemetry;
}
this.conditionSetIdentifier = undefined;
}

View File

@ -253,20 +253,22 @@ export default {
label: `when ${TRIGGER_LABEL[TRIGGER[trigger]]}`
});
});
return triggerOptions;
},
canEvaluateCriteria: function () {
let criteria = this.condition.configuration.criteria;
if (criteria.length) {
let lastCriterion = criteria[criteria.length - 1];
if (lastCriterion.telemetry &&
lastCriterion.operation &&
(lastCriterion.input.length ||
lastCriterion.operation === 'isDefined' ||
lastCriterion.operation === 'isUndefined')) {
if (lastCriterion.telemetry
&& lastCriterion.operation
&& (lastCriterion.input.length
|| lastCriterion.operation === 'isDefined'
|| lastCriterion.operation === 'isUndefined')) {
return true;
}
}
return false;
}
},
@ -293,6 +295,7 @@ export default {
} else {
this.condition.configuration.output = this.selectedOutputSelection;
}
this.persist();
},
addCriteria() {
@ -317,8 +320,14 @@ export default {
this.$emit('dragComplete');
},
dropCondition(event, targetIndex) {
if (!this.isDragging) { return }
if (targetIndex > this.moveIndex) { targetIndex-- } // for 'downward' move
if (!this.isDragging) {
return;
}
if (targetIndex > this.moveIndex) {
targetIndex--;
} // for 'downward' move
if (this.isValidTarget(targetIndex)) {
this.dragElement = undefined;
this.draggingOver = false;
@ -326,8 +335,14 @@ export default {
}
},
dragEnter(event, targetIndex) {
if (!this.isDragging) { return }
if (targetIndex > this.moveIndex) { targetIndex-- } // for 'downward' move
if (!this.isDragging) {
return;
}
if (targetIndex > this.moveIndex) {
targetIndex--;
} // for 'downward' move
if (this.isValidTarget(targetIndex)) {
this.dragElement = event.target.parentElement;
this.draggingOver = true;
@ -370,8 +385,8 @@ export default {
});
},
initCap(str) {
return str.charAt(0).toUpperCase() + str.slice(1)
return str.charAt(0).toUpperCase() + str.slice(1);
}
}
}
};
</script>

View File

@ -94,7 +94,7 @@ export default {
return {
applied: false,
conditionTestInputs: []
}
};
}
}
},
@ -126,10 +126,11 @@ export default {
destroyed() {
this.composition.off('add', this.addTelemetryObject);
this.composition.off('remove', this.removeTelemetryObject);
if(this.conditionManager) {
if (this.conditionManager) {
this.conditionManager.off('conditionSetResultUpdated', this.handleConditionSetResultUpdated);
this.conditionManager.destroy();
}
if (this.stopObservingForChanges) {
this.stopObservingForChanges();
}
@ -148,7 +149,7 @@ export default {
methods: {
handleConditionSetResultUpdated(data) {
this.currentConditionId = data.conditionId;
this.$emit('conditionSetResultUpdated', data)
this.$emit('conditionSetResultUpdated', data);
},
observeForChanges() {
this.stopObservingForChanges = this.openmct.objects.observe(this.domainObject, 'configuration.conditionCollection', (newConditionCollection) => {
@ -172,23 +173,31 @@ export default {
while (old_index < 0) {
old_index += arr.length;
}
while (new_index < 0) {
new_index += arr.length;
}
if (new_index >= arr.length) {
var k = new_index - arr.length;
while ((k--) + 1) {
arr.push(undefined);
}
}
arr.splice(new_index, 0, arr.splice(old_index, 1)[0]);
return arr;
}
};
const newIndexArr = move(oldIndexArr, this.moveIndex, targetIndex);
const reorderPlan = [];
for (let i = 0; i < oldIndexArr.length; i++) {
reorderPlan.push({oldIndex: Number(newIndexArr[i]), newIndex: i});
reorderPlan.push({
oldIndex: Number(newIndexArr[i]),
newIndex: i
});
}
this.reorder(reorderPlan);
@ -204,6 +213,7 @@ export default {
let index = this.telemetryObjs.findIndex(obj => {
let objId = this.openmct.objects.makeKeyString(obj.identifier);
let id = this.openmct.objects.makeKeyString(identifier);
return objId === id;
});
if (index > -1) {
@ -229,5 +239,5 @@ export default {
this.conditionManager.updateTestData(this.testData);
}
}
}
};
</script>

View File

@ -64,5 +64,5 @@ export default {
return this.condition ? this.condition.summary : '';
}
}
}
};
</script>

View File

@ -52,7 +52,7 @@ export default {
data() {
return {
conditionErrors: []
}
};
},
mounted() {
this.getConditionErrors();
@ -76,5 +76,5 @@ export default {
}
}
}
}
};
</script>

View File

@ -72,7 +72,7 @@ export default {
defaultConditionOutput: '',
telemetryObjs: [],
testData: {}
}
};
},
mounted() {
this.conditionSetIdentifier = this.openmct.objects.makeKeyString(this.domainObject.identifier);

View File

@ -142,11 +142,12 @@ export default {
operationFormat: '',
enumerations: [],
inputTypes: INPUT_TYPES
}
};
},
computed: {
setRowLabel: function () {
let operator = TRIGGER_CONJUNCTION[this.trigger];
return (this.index !== 0 ? operator : '') + ' when';
},
filteredOps: function () {
@ -163,11 +164,13 @@ export default {
if (this.filteredOps[i].appliesTo.length) {
type = this.inputTypes[this.filteredOps[i].appliesTo[0]];
} else {
type = 'text'
type = 'text';
}
break;
}
}
return type;
}
},
@ -184,11 +187,11 @@ export default {
},
methods: {
checkTelemetry() {
if(this.criterion.telemetry) {
if (this.criterion.telemetry) {
const isAnyAllTelemetry = this.criterion.telemetry === 'any' || this.criterion.telemetry === 'all';
const telemetryForCriterionExists = this.telemetry.find((telemetryObj) => this.openmct.objects.areIdsEqual(this.criterion.telemetry, telemetryObj.identifier));
if (!isAnyAllTelemetry &&
!telemetryForCriterionExists) {
if (!isAnyAllTelemetry
&& !telemetryForCriterionExists) {
//telemetry being used was removed. So reset this criterion.
this.criterion.telemetry = '';
this.criterion.metadata = '';
@ -223,6 +226,7 @@ export default {
} else if (this.criterion.metadata === 'dataReceived') {
this.operationFormat = 'number';
}
this.updateInputVisibilityAndValues();
},
updateMetadataOptions(ev) {
@ -230,12 +234,14 @@ export default {
this.clearDependentFields(ev.target);
this.persist();
}
if (this.criterion.telemetry) {
let telemetryObjects = this.telemetry;
if (this.criterion.telemetry !== 'all' && this.criterion.telemetry !== 'any') {
const found = this.telemetry.find(telemetryObj => (this.openmct.objects.areIdsEqual(telemetryObj.identifier, this.criterion.telemetry)));
telemetryObjects = found ? [found] : [];
}
this.telemetryMetadataOptions = [];
telemetryObjects.forEach(telemetryObject => {
let telemetryMetadata = this.openmct.telemetry.getMetadata(telemetryObject);
@ -248,9 +254,10 @@ export default {
if (!this.telemetryMetadataOptions) {
this.telemetryMetadataOptions = options;
}
options.forEach((option) => {
const found = this.telemetryMetadataOptions.find((metadataOption) => {
return (metadataOption.key && (metadataOption.key === option.key)) && (metadataOption.name && (metadataOption.name === option.name))
return (metadataOption.key && (metadataOption.key === option.key)) && (metadataOption.name && (metadataOption.name === option.name));
});
if (!found) {
this.telemetryMetadataOptions.push(option);
@ -275,6 +282,7 @@ export default {
this.inputCount = this.filteredOps[i].inputCount;
}
}
if (!this.inputCount) {
this.criterion.input = [];
}
@ -292,6 +300,7 @@ export default {
if (this.enumerations.length && !this.criterion.input.length) {
this.criterion.input = [this.enumerations[0].value.toString()];
}
this.inputCount = 0;
}
},

View File

@ -136,7 +136,7 @@ export default {
return {
applied: false,
conditionTestInputs: []
}
};
}
}
},
@ -183,6 +183,7 @@ export default {
if (this.testData && this.testData.conditionTestInputs) {
this.testInputs = this.testData.conditionTestInputs;
}
if (!this.testInputs.length) {
this.addTestInput();
}
@ -209,14 +210,16 @@ export default {
if (identifier) {
return this.openmct.objects.makeKeyString(identifier);
}
return [];
},
updateMetadata(testInput) {
if (testInput.telemetry) {
const id = this.openmct.objects.makeKeyString(testInput.telemetry);
if(this.telemetryMetadataOptions[id]) {
if (this.telemetryMetadataOptions[id]) {
return;
}
let telemetryMetadata = this.openmct.telemetry.getMetadata(testInput);
this.telemetryMetadataOptions[id] = telemetryMetadata.values().slice();
}
@ -232,5 +235,5 @@ export default {
});
}
}
}
};
</script>

View File

@ -98,7 +98,7 @@ export default {
loaded: false,
children: [],
expanded: false
}
};
},
computed: {
navigated() {
@ -106,8 +106,10 @@ export default {
const isSelectedObject = itemId && this.openmct.objects.areIdsEqual(this.node.object.identifier, itemId);
if (isSelectedObject && this.node.objectPath && this.node.objectPath.length > 1) {
const isParent = this.openmct.objects.areIdsEqual(this.node.objectPath[1].identifier, this.selectedItem.parentId);
return isSelectedObject && isParent;
}
return isSelectedObject;
},
isAlias() {
@ -115,7 +117,9 @@ export default {
if (!parent) {
return false;
}
let parentKeyString = this.openmct.objects.makeKeyString(parent.identifier);
return parentKeyString !== this.node.object.location;
},
typeClass() {
@ -123,6 +127,7 @@ export default {
if (!type) {
return 'icon-object-unknown';
}
return type.definition.cssClass;
}
},
@ -131,6 +136,7 @@ export default {
if (!this.hasChildren) {
return;
}
if (!this.loaded && !this.isLoading) {
this.composition = this.openmct.composition.get(this.domainObject);
this.composition.on('add', this.addChild);
@ -181,5 +187,5 @@ export default {
this.loaded = true;
}
}
}
};
</script>

View File

@ -98,7 +98,7 @@ export default {
filteredTreeItems: [],
isLoading: false,
selectedItem: undefined
}
};
},
mounted() {
this.searchService = this.openmct.$injector.get('searchService');
@ -109,7 +109,7 @@ export default {
this.isLoading = true;
this.openmct.objects.get('ROOT')
.then(root => {
return this.openmct.composition.get(root).load()
return this.openmct.composition.get(root).load();
})
.then(children => {
this.isLoading = false;
@ -146,7 +146,7 @@ export default {
object,
objectPath,
navigateToParent
}
};
});
});
},
@ -168,5 +168,5 @@ export default {
}
}
}
}
};
</script>

View File

@ -131,7 +131,7 @@ export default {
conditionsLoaded: false,
navigateToPath: '',
selectedConditionId: ''
}
};
},
destroyed() {
this.removeListeners();
@ -150,6 +150,7 @@ export default {
} else {
this.initializeStaticStyle();
}
this.openmct.editor.on('isEditing', this.setEditState);
},
methods: {
@ -166,8 +167,8 @@ export default {
layoutItem = this.selection[0][0].context.layoutItem;
const item = this.selection[0][0].context.item;
this.canHide = true;
if (item &&
(!layoutItem || (this.isItemType('subobject-view', layoutItem)))) {
if (item
&& (!layoutItem || (this.isItemType('subobject-view', layoutItem)))) {
domainObject = item;
} else {
domainObject = this.selection[0][1].context.item;
@ -178,6 +179,7 @@ export default {
} else {
domainObject = this.selection[0][0].context.item;
}
this.domainObject = domainObject;
this.initialStyles = getApplicableStylesForItem(domainObject, layoutItem);
this.$nextTick(() => {
@ -192,9 +194,11 @@ export default {
if (this.stopObserving) {
this.stopObserving();
}
if (this.stopObservingItems) {
this.stopObservingItems();
}
if (this.stopProvidingTelemetry) {
this.stopProvidingTelemetry();
delete this.stopProvidingTelemetry;
@ -224,6 +228,7 @@ export default {
conditionSetDomainObject = item;
}
};
const dismissDialog = (overlay, initialize) => {
overlay.dismiss();
if (initialize && conditionSetDomainObject) {
@ -232,6 +237,7 @@ export default {
this.initializeConditionalStyles();
}
};
let vm = new Vue({
provide: {
openmct: this.openmct
@ -240,7 +246,7 @@ export default {
data() {
return {
handleItemSelection
}
};
},
template: '<condition-set-selector-dialog @conditionSetSelected="handleItemSelection"></condition-set-selector-dialog>'
}).$mount();
@ -283,7 +289,7 @@ export default {
removeConditionSet() {
this.conditionSetDomainObject = undefined;
this.conditionalStyles = [];
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
if (this.itemId) {
domainObjectStyles[this.itemId].conditionSetIdentifier = undefined;
domainObjectStyles[this.itemId].selectedConditionId = undefined;
@ -302,6 +308,7 @@ export default {
domainObjectStyles.styles = undefined;
delete domainObjectStyles.styles;
}
if (isEmpty(domainObjectStyles)) {
domainObjectStyles = undefined;
}
@ -314,16 +321,16 @@ export default {
},
updateDomainObjectItemStyles(newItems) {
//check that all items that have been styles still exist. Otherwise delete those styles
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
let itemsToRemove = [];
let keys = Object.keys(domainObjectStyles);
//TODO: Need an easier way to find which properties are itemIds
keys.forEach((key) => {
const keyIsItemId = (key !== 'styles') &&
(key !== 'staticStyle') &&
(key !== 'defaultConditionId') &&
(key !== 'selectedConditionId') &&
(key !== 'conditionSetIdentifier');
const keyIsItemId = (key !== 'styles')
&& (key !== 'staticStyle')
&& (key !== 'defaultConditionId')
&& (key !== 'selectedConditionId')
&& (key !== 'conditionSetIdentifier');
if (keyIsItemId) {
if (!(newItems.find(item => item.id === key))) {
itemsToRemove.push(key);
@ -344,17 +351,20 @@ export default {
if (isEmpty(domainObjectStyles)) {
domainObjectStyles = undefined;
}
this.persist(domainObjectStyles);
},
initializeConditionalStyles() {
if (!this.conditions) {
this.conditions = {};
}
let conditionalStyles = [];
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration, index) => {
if (conditionConfiguration.isDefault) {
this.selectedConditionId = conditionConfiguration.id;
}
this.conditions[conditionConfiguration.id] = conditionConfiguration;
let foundStyle = this.findStyleByConditionId(conditionConfiguration.id);
if (foundStyle) {
@ -380,6 +390,7 @@ export default {
this.stopProvidingTelemetry();
delete this.stopProvidingTelemetry;
}
if (this.conditionSetDomainObject) {
this.openmct.telemetry.request(this.conditionSetDomainObject)
.then(output => {
@ -429,11 +440,12 @@ export default {
if (defaultConditionId) {
objectStyle.defaultConditionId = defaultConditionId;
}
if (this.conditionSetDomainObject) {
objectStyle.conditionSetIdentifier = this.conditionSetDomainObject.identifier;
}
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
if (this.itemId) {
domainObjectStyles[this.itemId] = objectStyle;
@ -442,7 +454,7 @@ export default {
domainObjectStyles = {
...domainObjectStyles,
...objectStyle
}
};
}
return domainObjectStyles;
@ -458,5 +470,5 @@ export default {
this.openmct.objects.mutate(this.domainObject, 'configuration.objectStyles', style);
}
}
}
};
</script>

View File

@ -67,7 +67,7 @@ export default {
isEditing: this.openmct.editor.isEditing(),
mixedStyles: [],
isStaticAndConditionalStyles: false
}
};
},
destroyed() {
this.removeListeners();
@ -113,6 +113,7 @@ export default {
this.isStaticAndConditionalStyles = this.hasConditionalStyles(domainObject, layoutItem.id);
}
}
itemInitialStyles.push(itemStyle);
});
const {styles, mixedStyles} = getConsolidatedStyleValues(itemInitialStyles);
@ -132,9 +133,9 @@ export default {
//check that all items that have been styles still exist. Otherwise delete those styles
let keys = Object.keys(this.domainObject.configuration.objectStyles || {});
keys.forEach((key) => {
if ((key !== 'styles') &&
(key !== 'staticStyle') &&
(key !== 'conditionSetIdentifier')) {
if ((key !== 'styles')
&& (key !== 'staticStyle')
&& (key !== 'conditionSetIdentifier')) {
if (!(newItems.find(item => item.id === key))) {
this.removeItemStyles(key);
}
@ -163,18 +164,21 @@ export default {
if (this.stopObserving) {
this.stopObserving();
}
if (this.stopObservingItems) {
this.stopObservingItems();
}
if (this.unObserveObjects) {
this.unObserveObjects.forEach((unObserveObject) => {
unObserveObject();
});
}
this.unObserveObjects = [];
},
removeItemStyles(itemId) {
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
if (itemId && domainObjectStyles[itemId]) {
domainObjectStyles[itemId] = undefined;
delete domainObjectStyles[this.itemId];
@ -182,6 +186,7 @@ export default {
if (isEmpty(domainObjectStyles)) {
domainObjectStyles = undefined;
}
this.persist(this.domainObject, domainObjectStyles);
}
},
@ -217,6 +222,7 @@ export default {
this.persist(domainObject, this.getDomainObjectStyle(domainObject, property));
});
}
this.isStaticAndConditionalStyles = false;
let foundIndex = this.mixedStyles.indexOf(property);
if (foundIndex > -1) {
@ -224,7 +230,7 @@ export default {
}
},
getDomainObjectStyle(domainObject, property, items) {
let domainObjectStyles = (domainObject.configuration && domainObject.configuration.objectStyles) || {};
let domainObjectStyles = (domainObject.configuration && domainObject.configuration.objectStyles) || {};
if (items) {
items.forEach(item => {
@ -232,6 +238,7 @@ export default {
if (domainObjectStyles[item.id] && domainObjectStyles[item.id].staticStyle) {
itemStaticStyle = domainObjectStyles[item.id].staticStyle.style;
}
Object.keys(item.applicableStyles).forEach(key => {
if (property === key) {
itemStaticStyle[key] = this.staticStyle.style[key];
@ -240,6 +247,7 @@ export default {
if (this.isStaticAndConditionalStyles) {
this.removeConditionalStyles(domainObjectStyles, item.id);
}
if (isEmpty(itemStaticStyle)) {
itemStaticStyle = undefined;
domainObjectStyles[item.id] = undefined;
@ -251,11 +259,13 @@ export default {
if (!domainObjectStyles.staticStyle) {
domainObjectStyles.staticStyle = {
style: {}
}
};
}
if (this.isStaticAndConditionalStyles) {
this.removeConditionalStyles(domainObjectStyles);
}
domainObjectStyles.staticStyle.style[property] = this.staticStyle.style[property];
}
@ -266,5 +276,5 @@ export default {
this.openmct.objects.mutate(domainObject, 'configuration.objectStyles', style);
}
}
}
};
</script>

View File

@ -104,6 +104,7 @@ export default {
},
borderColorOption() {
let value = this.styleItem.style.border.replace('1px solid ', '');
return {
icon: 'icon-line-horz',
title: STYLE_CONSTANTS.borderColorTitle,
@ -111,10 +112,11 @@ export default {
property: 'border',
isEditing: this.isEditing,
nonSpecific: this.mixedStyles.indexOf('border') > -1
}
};
},
backgroundColorOption() {
let value = this.styleItem.style.backgroundColor;
return {
icon: 'icon-paint-bucket',
title: STYLE_CONSTANTS.backgroundColorTitle,
@ -122,10 +124,11 @@ export default {
property: 'backgroundColor',
isEditing: this.isEditing,
nonSpecific: this.mixedStyles.indexOf('backgroundColor') > -1
}
};
},
colorOption() {
let value = this.styleItem.style.color;
return {
icon: 'icon-font',
title: STYLE_CONSTANTS.textColorTitle,
@ -133,7 +136,7 @@ export default {
property: 'color',
isEditing: this.isEditing,
nonSpecific: this.mixedStyles.indexOf('color') > -1
}
};
},
imageUrlOption() {
return {
@ -159,7 +162,7 @@ export default {
value: {url: this.styleItem.style.imageUrl},
isEditing: this.isEditing,
nonSpecific: this.mixedStyles.indexOf('imageUrl') > -1
}
};
},
isStyleInvisibleOption() {
return {
@ -178,7 +181,7 @@ export default {
title: STYLE_CONSTANTS.visibilityVisible
}
]
}
};
}
},
@ -190,12 +193,14 @@ export default {
if (value && value.indexOf('__no_value') > -1) {
return value.replace('__no_value', 'transparent');
}
return value;
},
normalizeValueForStyle(value) {
if (value && value === 'transparent') {
return '__no_value';
}
return value;
},
updateStyleValue(value, item) {
@ -203,13 +208,15 @@ export default {
if (item.property === 'border') {
value = '1px solid ' + value;
}
if (value && (value.url !== undefined)) {
this.styleItem.style[item.property] = value.url;
} else {
this.styleItem.style[item.property] = value;
}
this.$emit('persist', this.styleItem, item.property);
}
}
}
};
</script>

View File

@ -140,7 +140,7 @@ export default {
navigateToPath: '',
selectedConditionId: '',
locked: false
}
};
},
computed: {
allowEditing() {
@ -165,6 +165,7 @@ export default {
} else {
this.initializeStaticStyle();
}
this.openmct.editor.on('isEditing', this.setEditState);
},
methods: {
@ -183,6 +184,7 @@ export default {
} else if (this.domainObject.configuration && this.domainObject.configuration.objectStyles) {
objectStyles = this.domainObject.configuration.objectStyles;
}
return objectStyles;
},
setEditState(isEditing) {
@ -219,6 +221,7 @@ export default {
},
hasConditionalStyle(domainObject, layoutItem) {
const id = layoutItem ? layoutItem.id : undefined;
return getConditionSetIdentifierForItem(domainObject, id) !== undefined;
},
getObjectsAndItemsFromSelection() {
@ -265,6 +268,7 @@ export default {
}
}
}
itemInitialStyles.push(itemStyle);
});
this.isStaticAndConditionalStyles = this.isMultipleSelection && itemsWithConditionalStyles;
@ -292,11 +296,11 @@ export default {
});
},
isKeyItemId(key) {
return (key !== 'styles') &&
(key !== 'staticStyle') &&
(key !== 'defaultConditionId') &&
(key !== 'selectedConditionId') &&
(key !== 'conditionSetIdentifier');
return (key !== 'styles')
&& (key !== 'staticStyle')
&& (key !== 'defaultConditionId')
&& (key !== 'selectedConditionId')
&& (key !== 'conditionSetIdentifier');
},
registerListener(domainObject) {
let id = this.openmct.objects.makeKeyString(domainObject.identifier);
@ -320,6 +324,7 @@ export default {
if (this.stopObserving) {
this.stopObserving();
}
if (this.stopObservingItems) {
this.stopObservingItems();
}
@ -334,6 +339,7 @@ export default {
unObserveObject();
});
}
this.unObserveObjects = [];
},
subscribeToConditionSet() {
@ -341,6 +347,7 @@ export default {
this.stopProvidingTelemetry();
delete this.stopProvidingTelemetry;
}
if (this.conditionSetDomainObject) {
this.openmct.telemetry.request(this.conditionSetDomainObject)
.then(output => {
@ -364,11 +371,13 @@ export default {
if (!this.conditions) {
this.conditions = {};
}
let conditionalStyles = [];
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration, index) => {
if (conditionConfiguration.isDefault) {
this.selectedConditionId = conditionConfiguration.id;
}
this.conditions[conditionConfiguration.id] = conditionConfiguration;
let foundStyle = this.findStyleByConditionId(conditionConfiguration.id);
if (foundStyle) {
@ -403,13 +412,14 @@ export default {
}
},
removeItemStyles(itemId) {
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
if (itemId && domainObjectStyles[itemId]) {
delete domainObjectStyles[itemId];
if (Object.keys(domainObjectStyles).length <= 0) {
domainObjectStyles = undefined;
}
this.persist(this.domainObject, domainObjectStyles);
}
},
@ -426,6 +436,7 @@ export default {
conditionSetDomainObject = item;
}
};
const dismissDialog = (overlay, initialize) => {
overlay.dismiss();
if (initialize && conditionSetDomainObject) {
@ -434,6 +445,7 @@ export default {
this.initializeConditionalStyles();
}
};
let vm = new Vue({
provide: {
openmct: this.openmct
@ -442,7 +454,7 @@ export default {
data() {
return {
handleItemSelection
}
};
},
template: '<condition-set-selector-dialog @conditionSetSelected="handleItemSelection"></condition-set-selector-dialog>'
}).$mount();
@ -467,18 +479,20 @@ export default {
removeConditionSet() {
this.conditionSetDomainObject = undefined;
this.conditionalStyles = [];
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
let domainObjectStyles = (this.domainObject.configuration && this.domainObject.configuration.objectStyles) || {};
if (this.domainObjectsById) {
const domainObjects = Object.values(this.domainObjectsById);
domainObjects.forEach(domainObject => {
let objectStyles = (domainObject.configuration && domainObject.configuration.objectStyles) || {};
let objectStyles = (domainObject.configuration && domainObject.configuration.objectStyles) || {};
this.removeConditionalStyles(objectStyles);
if (objectStyles && Object.keys(objectStyles).length <= 0) {
objectStyles = undefined;
}
this.persist(domainObject, objectStyles);
});
}
if (this.items.length) {
this.items.forEach((item) => {
const itemId = item.id;
@ -487,12 +501,14 @@ export default {
delete domainObjectStyles[itemId];
}
});
} else {
} else {
this.removeConditionalStyles(domainObjectStyles);
}
if (domainObjectStyles && Object.keys(domainObjectStyles).length <= 0) {
domainObjectStyles = undefined;
}
this.persist(this.domainObject, domainObjectStyles);
if (this.stopProvidingTelemetry) {
@ -539,9 +555,11 @@ export default {
this.persist(domainObject, this.getDomainObjectStyle(domainObject, property, null, defaultConditionId));
});
}
if (!this.items.length && !this.domainObjectsById) {
this.persist(this.domainObject, this.getDomainObjectStyle(this.domainObject, property, null, defaultConditionId));
}
this.isStaticAndConditionalStyles = false;
if (property) {
let foundIndex = this.mixedStyles.indexOf(property);
@ -559,10 +577,12 @@ export default {
if (defaultConditionId) {
objectStyle.defaultConditionId = defaultConditionId;
}
if (this.conditionSetDomainObject) {
objectStyle.conditionSetIdentifier = this.conditionSetDomainObject.identifier;
}
let domainObjectStyles = (domainObject.configuration && domainObject.configuration.objectStyles) || {};
let domainObjectStyles = (domainObject.configuration && domainObject.configuration.objectStyles) || {};
if (items) {
items.forEach(item => {
@ -572,12 +592,15 @@ export default {
if (domainObjectStyles[item.id] && domainObjectStyles[item.id].staticStyle) {
itemStaticStyle = Object.assign({}, domainObjectStyles[item.id].staticStyle.style);
}
if (item.applicableStyles[property] !== undefined) {
itemStaticStyle[property] = this.staticStyle.style[property];
}
if (Object.keys(itemStaticStyle).length <= 0) {
itemStaticStyle = undefined;
}
domainObjectStyles[item.id] = { staticStyle: { style: itemStaticStyle } };
} else {
objectStyle.styles.forEach((conditionalStyle, index) => {
@ -614,5 +637,5 @@ export default {
this.openmct.objects.mutate(domainObject, 'configuration.objectStyles', style);
}
}
}
};
</script>

View File

@ -51,14 +51,15 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
if (!this.stalenessSubscription) {
this.stalenessSubscription = {};
}
Object.values(telemetryObjects).forEach((telemetryObject) => {
const id = this.openmct.objects.makeKeyString(telemetryObject.identifier);
if (!this.stalenessSubscription[id]) {
this.stalenessSubscription[id] = subscribeForStaleness((data) => {
this.handleStaleTelemetry(id, data);
}, this.input[0]*1000);
}, this.input[0] * 1000);
}
})
});
}
handleStaleTelemetry(id, data) {
@ -66,6 +67,7 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
this.telemetryDataCache[id] = true;
this.result = evaluateResults(Object.values(this.telemetryDataCache), this.telemetry);
}
this.emitEvent('telemetryIsStale', data);
}
@ -116,9 +118,10 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
if (data) {
this.openmct.time.getAllTimeSystems().forEach(timeSystem => {
datum[timeSystem.key] = data[timeSystem.key]
datum[timeSystem.key] = data[timeSystem.key];
});
}
return datum;
}
@ -130,6 +133,7 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
if (this.stalenessSubscription && this.stalenessSubscription[validatedData.id]) {
this.stalenessSubscription[validatedData.id].update(validatedData);
}
this.telemetryDataCache[validatedData.id] = false;
} else {
this.telemetryDataCache[validatedData.id] = this.computeResult(validatedData);
@ -164,6 +168,7 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
));
let telemetryDataCache = {};
return Promise.all(telemetryRequests)
.then(telemetryRequestsResults => {
let latestTimestamp;
@ -203,7 +208,7 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
let inputValue = this.input;
if (this.metadata) {
const telemetryObjects = Object.values(this.telemetryObjects);
for (let i=0; i < telemetryObjects.length; i++) {
for (let i = 0; i < telemetryObjects.length; i++) {
const telemetryObject = telemetryObjects[i];
const metadataObject = this.getMetaDataObject(telemetryObject, this.metadata);
if (metadataObject) {
@ -213,6 +218,7 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
}
}
}
return `${telemetryDescription} ${metadataValue} ${getOperatorText(this.operation, inputValue)}`;
}

View File

@ -54,7 +54,7 @@ export default class TelemetryCriterion extends EventEmitter {
this.telemetryObjectIdAsString = this.openmct.objects.makeKeyString(this.telemetryDomainObjectDefinition.telemetry);
this.updateTelemetryObjects(this.telemetryDomainObjectDefinition.telemetryObjects);
if (this.isValid() && this.isStalenessCheck() && this.isValidInput()) {
this.subscribeForStaleData()
this.subscribeForStaleData();
}
}
@ -62,7 +62,8 @@ export default class TelemetryCriterion extends EventEmitter {
if (this.stalenessSubscription) {
this.stalenessSubscription.clear();
}
this.stalenessSubscription = subscribeForStaleness(this.handleStaleTelemetry.bind(this), this.input[0]*1000);
this.stalenessSubscription = subscribeForStaleness(this.handleStaleTelemetry.bind(this), this.input[0] * 1000);
}
handleStaleTelemetry(data) {
@ -85,7 +86,7 @@ export default class TelemetryCriterion extends EventEmitter {
updateTelemetryObjects(telemetryObjects) {
this.telemetryObject = telemetryObjects[this.telemetryObjectIdAsString];
if (this.isValid() && this.isStalenessCheck() && this.isValidInput()) {
this.subscribeForStaleData()
this.subscribeForStaleData();
}
}
@ -96,6 +97,7 @@ export default class TelemetryCriterion extends EventEmitter {
const normalizedDatum = Object.values(metadata).reduce((datum, metadatum) => {
const formatter = this.openmct.telemetry.getValueFormatter(metadatum);
datum[metadatum.key] = formatter.parse(telemetryDatum[metadatum.source]);
return datum;
}, {});
@ -111,9 +113,10 @@ export default class TelemetryCriterion extends EventEmitter {
if (data) {
this.openmct.time.getAllTimeSystems().forEach(timeSystem => {
datum[timeSystem.key] = data[timeSystem.key]
datum[timeSystem.key] = data[timeSystem.key];
});
}
return datum;
}
@ -123,6 +126,7 @@ export default class TelemetryCriterion extends EventEmitter {
if (this.stalenessSubscription) {
this.stalenessSubscription.update(validatedData);
}
this.result = false;
} else {
this.result = this.computeResult(validatedData);
@ -159,11 +163,12 @@ export default class TelemetryCriterion extends EventEmitter {
}
findOperation(operation) {
for (let i=0, ii=OPERATIONS.length; i < ii; i++) {
for (let i = 0, ii = OPERATIONS.length; i < ii; i++) {
if (operation === OPERATIONS[i].name) {
return OPERATIONS[i].operation;
}
}
return null;
}
@ -176,10 +181,12 @@ export default class TelemetryCriterion extends EventEmitter {
if (this.isValidInput()) {
this.input.forEach(input => params.push(input));
}
if (typeof comparator === 'function') {
result = !!comparator(params);
result = Boolean(comparator(params));
}
}
return result;
}
@ -196,19 +203,21 @@ export default class TelemetryCriterion extends EventEmitter {
const telemetryMetadata = this.openmct.telemetry.getMetadata(telemetryObject);
metadataObject = telemetryMetadata.valueMetadatas.find((valueMetadata) => valueMetadata.key === metadata);
}
return metadataObject;
}
getInputValueFromMetaData(metadataObject, input) {
let inputValue;
if (metadataObject) {
if(metadataObject.enumerations && input.length) {
if (metadataObject.enumerations && input.length) {
const enumeration = metadataObject.enumerations[input[0]];
if (enumeration !== undefined && enumeration.string) {
inputValue = [enumeration.string];
}
}
}
return inputValue;
}
@ -219,6 +228,7 @@ export default class TelemetryCriterion extends EventEmitter {
metadataValue = metadataObject.name;
}
}
return metadataValue;
}

View File

@ -34,7 +34,10 @@ describe("The telemetry criterion", function () {
beforeEach (() => {
testTelemetryObject = {
identifier:{ namespace: "", key: "test-object"},
identifier: {
namespace: "",
key: "test-object"
},
type: "test-object",
name: "Test Object",
telemetry: {
@ -76,7 +79,10 @@ describe("The telemetry criterion", function () {
['timeSystem', 'bounds', 'getAllTimeSystems']
);
openmct.time.timeSystem.and.returnValue({key: 'system'});
openmct.time.bounds.and.returnValue({start: 0, end: 1});
openmct.time.bounds.and.returnValue({
start: 0,
end: 1
});
openmct.time.getAllTimeSystems.and.returnValue([{key: 'system'}]);
testCriterionDefinition = {
@ -122,6 +128,7 @@ describe("The telemetry criterion", function () {
setTimeout(() => {
telemetryRequestResolve(mockTelemetry);
}, 100);
return telemetryRequestPromise;
});
});

View File

@ -64,5 +64,5 @@ export default function ConditionPlugin() {
openmct.telemetry.addProvider(new ConditionSetTelemetryProvider(openmct));
openmct.objectViews.addProvider(new ConditionSetViewProvider(openmct));
}
};
}

View File

@ -42,7 +42,10 @@ describe('the plugin', function () {
beforeEach((done) => {
testTelemetryObject = {
identifier:{ namespace: "", key: "test-object"},
identifier: {
namespace: "",
key: "test-object"
},
type: "test-object",
name: "Test Object",
telemetry: {
@ -121,7 +124,7 @@ describe('the plugin', function () {
it('provides a view', () => {
const testViewObject = {
id:"test-object",
id: "test-object",
type: "conditionSet",
configuration: {
conditionCollection: []
@ -143,142 +146,142 @@ describe('the plugin', function () {
let component;
let styleViewComponentObject;
const conditionSetDomainObject = {
"configuration":{
"conditionTestData":[
"configuration": {
"conditionTestData": [
{
"telemetry":"",
"metadata":"",
"input":""
"telemetry": "",
"metadata": "",
"input": ""
}
],
"conditionCollection":[
"conditionCollection": [
{
"id":"39584410-cbf9-499e-96dc-76f27e69885d",
"configuration":{
"name":"Unnamed Condition",
"output":"Sine > 0",
"trigger":"all",
"criteria":[
"id": "39584410-cbf9-499e-96dc-76f27e69885d",
"configuration": {
"name": "Unnamed Condition",
"output": "Sine > 0",
"trigger": "all",
"criteria": [
{
"id":"85fbb2f7-7595-42bd-9767-a932266c5225",
"telemetry":{
"namespace":"",
"key":"be0ba97f-b510-4f40-a18d-4ff121d5ea1a"
"id": "85fbb2f7-7595-42bd-9767-a932266c5225",
"telemetry": {
"namespace": "",
"key": "be0ba97f-b510-4f40-a18d-4ff121d5ea1a"
},
"operation":"greaterThan",
"input":[
"operation": "greaterThan",
"input": [
"0"
],
"metadata":"sin"
"metadata": "sin"
},
{
"id":"35400132-63b0-425c-ac30-8197df7d5862",
"telemetry":"any",
"operation":"enumValueIs",
"input":[
"id": "35400132-63b0-425c-ac30-8197df7d5862",
"telemetry": "any",
"operation": "enumValueIs",
"input": [
"0"
],
"metadata":"state"
"metadata": "state"
}
]
},
"summary":"Match if all criteria are met: Sine Wave Generator Sine > 0 and any telemetry State is OFF "
"summary": "Match if all criteria are met: Sine Wave Generator Sine > 0 and any telemetry State is OFF "
},
{
"isDefault":true,
"id":"2532d90a-e0d6-4935-b546-3123522da2de",
"configuration":{
"name":"Default",
"output":"Default",
"trigger":"all",
"criteria":[
"isDefault": true,
"id": "2532d90a-e0d6-4935-b546-3123522da2de",
"configuration": {
"name": "Default",
"output": "Default",
"trigger": "all",
"criteria": [
]
},
"summary":""
"summary": ""
}
]
},
"composition":[
"composition": [
{
"namespace":"",
"key":"be0ba97f-b510-4f40-a18d-4ff121d5ea1a"
"namespace": "",
"key": "be0ba97f-b510-4f40-a18d-4ff121d5ea1a"
},
{
"namespace":"",
"key":"077ffa67-e78f-4e99-80e0-522ac33a3888"
"namespace": "",
"key": "077ffa67-e78f-4e99-80e0-522ac33a3888"
}
],
"telemetry":{
"telemetry": {
},
"name":"Condition Set",
"type":"conditionSet",
"identifier":{
"namespace":"",
"key":"863012c1-f6ca-4ab0-aed7-fd43d5e4cd12"
"name": "Condition Set",
"type": "conditionSet",
"identifier": {
"namespace": "",
"key": "863012c1-f6ca-4ab0-aed7-fd43d5e4cd12"
}
};
const staticStyle = {
"style":{
"backgroundColor":"#717171",
"border":"1px solid #00ffff"
"style": {
"backgroundColor": "#717171",
"border": "1px solid #00ffff"
}
};
const conditionalStyle = {
"conditionId":"39584410-cbf9-499e-96dc-76f27e69885d",
"style":{
"isStyleInvisible":"",
"backgroundColor":"#717171",
"border":"1px solid #ffff00"
"conditionId": "39584410-cbf9-499e-96dc-76f27e69885d",
"style": {
"isStyleInvisible": "",
"backgroundColor": "#717171",
"border": "1px solid #ffff00"
}
};
beforeEach(() => {
displayLayoutItem = {
"composition":[
"composition": [
],
"configuration":{
"items":[
"configuration": {
"items": [
{
"fill":"#717171",
"stroke":"",
"x":1,
"y":1,
"width":10,
"height":5,
"type":"box-view",
"id":"89b88746-d325-487b-aec4-11b79afff9e8"
"fill": "#717171",
"stroke": "",
"x": 1,
"y": 1,
"width": 10,
"height": 5,
"type": "box-view",
"id": "89b88746-d325-487b-aec4-11b79afff9e8"
},
{
"x":18,
"y":9,
"x2":23,
"y2":4,
"stroke":"#717171",
"type":"line-view",
"id":"57d49a28-7863-43bd-9593-6570758916f0"
"x": 18,
"y": 9,
"x2": 23,
"y2": 4,
"stroke": "#717171",
"type": "line-view",
"id": "57d49a28-7863-43bd-9593-6570758916f0"
}
],
"layoutGrid":[
"layoutGrid": [
10,
10
]
},
"name":"Display Layout",
"type":"layout",
"identifier":{
"namespace":"",
"key":"c5e636c1-6771-4c9c-b933-8665cab189b3"
"name": "Display Layout",
"type": "layout",
"identifier": {
"namespace": "",
"key": "c5e636c1-6771-4c9c-b933-8665cab189b3"
}
};
lineLayoutItem = {
"x":18,
"y":9,
"x2":23,
"y2":4,
"stroke":"#717171",
"type":"line-view",
"id":"57d49a28-7863-43bd-9593-6570758916f0"
"x": 18,
"y": 9,
"x2": 23,
"y2": 4,
"stroke": "#717171",
"type": "line-view",
"id": "57d49a28-7863-43bd-9593-6570758916f0"
};
boxLayoutItem = {
"fill": "#717171",
@ -294,13 +297,13 @@ describe('the plugin', function () {
[{
context: {
"layoutItem": lineLayoutItem,
"index":1
"index": 1
}
},
{
context: {
"item": displayLayoutItem,
"supportsMultiSelect":true
"supportsMultiSelect": true
}
}],
[{
@ -312,7 +315,7 @@ describe('the plugin', function () {
{
context: {
item: displayLayoutItem,
"supportsMultiSelect":true
"supportsMultiSelect": true
}
}]
];
@ -329,6 +332,7 @@ describe('the plugin', function () {
},
template: '<styles-view/>'
});
return Vue.nextTick().then(() => {
styleViewComponentObject = component.$root.$children[0];
styleViewComponentObject.setEditState(true);
@ -352,6 +356,7 @@ describe('the plugin', function () {
styleViewComponentObject.initializeConditionalStyles();
expect(styleViewComponentObject.conditionalStyles.length).toBe(2);
styleViewComponentObject.updateConditionalStyle(conditionalStyle, 'border');
return Vue.nextTick().then(() => {
expect(styleViewComponentObject.domainObject.configuration.objectStyles).toBeDefined();
[boxLayoutItem, lineLayoutItem].forEach((item) => {
@ -373,6 +378,7 @@ describe('the plugin', function () {
it('updates applicable static styles', () => {
styleViewComponentObject.updateStaticStyle(staticStyle, 'border');
return Vue.nextTick().then(() => {
expect(styleViewComponentObject.domainObject.configuration.objectStyles).toBeDefined();
[boxLayoutItem, lineLayoutItem].forEach((item) => {
@ -393,64 +399,64 @@ describe('the plugin', function () {
describe('the condition check for staleness', () => {
let conditionSetDomainObject;
beforeEach(()=>{
beforeEach(() => {
conditionSetDomainObject = {
"configuration":{
"conditionTestData":[
"configuration": {
"conditionTestData": [
{
"telemetry":"",
"metadata":"",
"input":""
"telemetry": "",
"metadata": "",
"input": ""
}
],
"conditionCollection":[
"conditionCollection": [
{
"id":"39584410-cbf9-499e-96dc-76f27e69885d",
"configuration":{
"name":"Unnamed Condition",
"output":"Any stale telemetry",
"trigger":"all",
"criteria":[
"id": "39584410-cbf9-499e-96dc-76f27e69885d",
"configuration": {
"name": "Unnamed Condition",
"output": "Any stale telemetry",
"trigger": "all",
"criteria": [
{
"id":"35400132-63b0-425c-ac30-8197df7d5862",
"telemetry":"any",
"operation":"isStale",
"input":[
"1"
"id": "35400132-63b0-425c-ac30-8197df7d5862",
"telemetry": "any",
"operation": "isStale",
"input": [
"0.2"
],
"metadata":"dataReceived"
"metadata": "dataReceived"
}
]
},
"summary":"Match if all criteria are met: Any telemetry is stale after 5 seconds"
"summary": "Match if all criteria are met: Any telemetry is stale after 5 seconds"
},
{
"isDefault":true,
"id":"2532d90a-e0d6-4935-b546-3123522da2de",
"configuration":{
"name":"Default",
"output":"Default",
"trigger":"all",
"criteria":[
"isDefault": true,
"id": "2532d90a-e0d6-4935-b546-3123522da2de",
"configuration": {
"name": "Default",
"output": "Default",
"trigger": "all",
"criteria": [
]
},
"summary":""
"summary": ""
}
]
},
"composition":[
"composition": [
{
"namespace":"",
"key":"test-object"
"namespace": "",
"key": "test-object"
}
],
"telemetry":{
"telemetry": {
},
"name":"Condition Set",
"type":"conditionSet",
"identifier":{
"namespace":"",
"key":"cf4456a9-296a-4e6b-b182-62ed29cd15b9"
"name": "Condition Set",
"type": "conditionSet",
"identifier": {
"namespace": "",
"key": "cf4456a9-296a-4e6b-b182-62ed29cd15b9"
}
};
@ -467,17 +473,20 @@ describe('the plugin', function () {
setTimeout(() => {
expect(mockListener).toHaveBeenCalledWith({
output: 'Any stale telemetry',
id: { namespace: '', key: 'cf4456a9-296a-4e6b-b182-62ed29cd15b9' },
id: {
namespace: '',
key: 'cf4456a9-296a-4e6b-b182-62ed29cd15b9'
},
conditionId: '39584410-cbf9-499e-96dc-76f27e69885d',
utc: undefined
});
done();
}, 1500);
}, 300);
});
it('should not evaluate as stale when telemetry is received in the allotted time', (done) => {
const date = Date.now();
conditionSetDomainObject.configuration.conditionCollection[0].configuration.criteria[0].input = ["2"];
conditionSetDomainObject.configuration.conditionCollection[0].configuration.criteria[0].input = ["0.4"];
let conditionMgr = new ConditionManager(conditionSetDomainObject, openmct);
conditionMgr.on('conditionSetResultUpdated', mockListener);
conditionMgr.telemetryObjects = {
@ -490,12 +499,15 @@ describe('the plugin', function () {
setTimeout(() => {
expect(mockListener).toHaveBeenCalledWith({
output: 'Default',
id: { namespace: '', key: 'cf4456a9-296a-4e6b-b182-62ed29cd15b9' },
id: {
namespace: '',
key: 'cf4456a9-296a-4e6b-b182-62ed29cd15b9'
},
conditionId: '2532d90a-e0d6-4935-b546-3123522da2de',
utc: undefined
});
done();
}, 1500);
}, 300);
});
});
});

View File

@ -31,7 +31,7 @@ export const evaluateResults = (results, trigger) => {
} else {
return matchAny(results);
}
}
};
function matchAll(results) {
for (const result of results) {
@ -59,6 +59,7 @@ function matchExact(results, target) {
if (result === true) {
matches++;
}
if (matches > target) {
return false;
}

Some files were not shown because too many files have changed in this diff Show More