mirror of
https://github.com/nasa/openmct.git
synced 2025-01-31 16:36:13 +00:00
Addresses review comments for conditionals code (#2978)
Conditionals code refactoring Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
parent
e9968e3649
commit
38dbf2ccab
@ -26,6 +26,7 @@ import TelemetryCriterion from "./criterion/TelemetryCriterion";
|
||||
import { evaluateResults } from './utils/evaluator';
|
||||
import { getLatestTimestamp } from './utils/time';
|
||||
import AllTelemetryCriterion from "./criterion/AllTelemetryCriterion";
|
||||
import {TRIGGER_CONJUNCTION, TRIGGER_LABEL} from "./utils/constants";
|
||||
|
||||
/*
|
||||
* conditionConfiguration = {
|
||||
@ -41,13 +42,14 @@ import AllTelemetryCriterion from "./criterion/AllTelemetryCriterion";
|
||||
* ]
|
||||
* }
|
||||
*/
|
||||
export default class ConditionClass extends EventEmitter {
|
||||
export default class Condition extends EventEmitter {
|
||||
|
||||
/**
|
||||
* Manages criteria and emits the result of - true or false - based on criteria evaluated.
|
||||
* @constructor
|
||||
* @param conditionConfiguration: {id: uuid,trigger: enum, criteria: Array of {id: uuid, operation: enum, input: Array, metaDataKey: string, key: {domainObject.identifier} }
|
||||
* @param openmct
|
||||
* @param conditionManager
|
||||
*/
|
||||
constructor(conditionConfiguration, openmct, conditionManager) {
|
||||
super();
|
||||
@ -62,6 +64,7 @@ export default class ConditionClass extends EventEmitter {
|
||||
this.createCriteria(conditionConfiguration.configuration.criteria);
|
||||
}
|
||||
this.trigger = conditionConfiguration.configuration.trigger;
|
||||
this.description = '';
|
||||
}
|
||||
|
||||
getResult(datum) {
|
||||
@ -109,7 +112,7 @@ export default class ConditionClass extends EventEmitter {
|
||||
return {
|
||||
id: criterionConfiguration.id || uuid(),
|
||||
telemetry: criterionConfiguration.telemetry || '',
|
||||
telemetryObject: this.conditionManager.telemetryObjects[this.openmct.objects.makeKeyString(criterionConfiguration.telemetry)],
|
||||
telemetryObjects: this.conditionManager.telemetryObjects,
|
||||
operation: criterionConfiguration.operation || '',
|
||||
input: criterionConfiguration.input === undefined ? [] : criterionConfiguration.input,
|
||||
metadata: criterionConfiguration.metadata || ''
|
||||
@ -120,6 +123,7 @@ export default class ConditionClass extends EventEmitter {
|
||||
criterionConfigurations.forEach((criterionConfiguration) => {
|
||||
this.addCriterion(criterionConfiguration);
|
||||
});
|
||||
this.updateDescription();
|
||||
}
|
||||
|
||||
updateCriteria(criterionConfigurations) {
|
||||
@ -127,10 +131,11 @@ export default class ConditionClass extends EventEmitter {
|
||||
this.createCriteria(criterionConfigurations);
|
||||
}
|
||||
|
||||
updateTelemetry() {
|
||||
updateTelemetryObjects() {
|
||||
this.criteria.forEach((criterion) => {
|
||||
criterion.updateTelemetry(this.conditionManager.telemetryObjects);
|
||||
criterion.updateTelemetryObjects(this.conditionManager.telemetryObjects);
|
||||
});
|
||||
this.updateDescription();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -178,6 +183,7 @@ export default class ConditionClass extends EventEmitter {
|
||||
criterion.unsubscribe();
|
||||
criterion.off('criterionUpdated', (obj) => this.handleCriterionUpdated(obj));
|
||||
this.criteria.splice(found.index, 1, newCriterion);
|
||||
this.updateDescription();
|
||||
}
|
||||
}
|
||||
|
||||
@ -190,6 +196,7 @@ export default class ConditionClass extends EventEmitter {
|
||||
});
|
||||
criterion.destroy();
|
||||
this.criteria.splice(found.index, 1);
|
||||
this.updateDescription();
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -200,9 +207,30 @@ export default class ConditionClass extends EventEmitter {
|
||||
let found = this.findCriterion(criterion.id);
|
||||
if (found) {
|
||||
this.criteria[found.index] = criterion.data;
|
||||
this.updateDescription();
|
||||
}
|
||||
}
|
||||
|
||||
updateDescription() {
|
||||
const triggerDescription = this.getTriggerDescription();
|
||||
let description = '';
|
||||
this.criteria.forEach((criterion, index) => {
|
||||
if (!index) {
|
||||
description = `Match if ${triggerDescription.prefix}`;
|
||||
}
|
||||
description = `${description} ${criterion.getDescription()} ${(index < this.criteria.length - 1) ? triggerDescription.conjunction : ''}`;
|
||||
});
|
||||
this.description = description;
|
||||
this.conditionManager.updateConditionDescription(this);
|
||||
}
|
||||
|
||||
getTriggerDescription() {
|
||||
return {
|
||||
conjunction: TRIGGER_CONJUNCTION[this.trigger],
|
||||
prefix: `${TRIGGER_LABEL[this.trigger]}: `
|
||||
};
|
||||
}
|
||||
|
||||
requestLADConditionResult() {
|
||||
let latestTimestamp;
|
||||
let criteriaResults = {};
|
||||
|
@ -57,7 +57,7 @@ export default class ConditionManager extends EventEmitter {
|
||||
endpoint,
|
||||
this.telemetryReceived.bind(this, endpoint)
|
||||
);
|
||||
this.updateConditionTelemetry();
|
||||
this.updateConditionTelemetryObjects();
|
||||
}
|
||||
|
||||
unsubscribeFromTelemetry(endpointIdentifier) {
|
||||
@ -70,11 +70,11 @@ export default class ConditionManager extends EventEmitter {
|
||||
this.subscriptions[id]();
|
||||
delete this.subscriptions[id];
|
||||
delete this.telemetryObjects[id];
|
||||
this.removeConditionTelemetry();
|
||||
this.removeConditionTelemetryObjects();
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.conditionClassCollection = [];
|
||||
this.conditions = [];
|
||||
if (this.conditionSetDomainObject.configuration.conditionCollection.length) {
|
||||
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration, index) => {
|
||||
this.initCondition(conditionConfiguration, index);
|
||||
@ -82,13 +82,14 @@ export default class ConditionManager extends EventEmitter {
|
||||
}
|
||||
}
|
||||
|
||||
updateConditionTelemetry() {
|
||||
this.conditionClassCollection.forEach((condition) => condition.updateTelemetry());
|
||||
updateConditionTelemetryObjects() {
|
||||
this.conditions.forEach((condition) => condition.updateTelemetryObjects());
|
||||
}
|
||||
|
||||
removeConditionTelemetry() {
|
||||
removeConditionTelemetryObjects() {
|
||||
let conditionsChanged = false;
|
||||
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration) => {
|
||||
this.conditionSetDomainObject.configuration.conditionCollection.forEach((conditionConfiguration, conditionIndex) => {
|
||||
let conditionChanged = false;
|
||||
conditionConfiguration.configuration.criteria.forEach((criterion, index) => {
|
||||
const isAnyAllTelemetry = criterion.telemetry && (criterion.telemetry === 'any' || criterion.telemetry === 'all');
|
||||
if (!isAnyAllTelemetry) {
|
||||
@ -100,10 +101,14 @@ export default class ConditionManager extends EventEmitter {
|
||||
criterion.metadata = '';
|
||||
criterion.input = [];
|
||||
criterion.operation = '';
|
||||
conditionsChanged = true;
|
||||
conditionChanged = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
if (conditionChanged) {
|
||||
this.updateCondition(conditionConfiguration, conditionIndex);
|
||||
conditionsChanged = true;
|
||||
}
|
||||
});
|
||||
if (conditionsChanged) {
|
||||
this.persistConditions();
|
||||
@ -111,18 +116,24 @@ export default class ConditionManager extends EventEmitter {
|
||||
}
|
||||
|
||||
updateCondition(conditionConfiguration, index) {
|
||||
let condition = this.conditionClassCollection[index];
|
||||
condition.update(conditionConfiguration);
|
||||
let condition = this.conditions[index];
|
||||
this.conditionSetDomainObject.configuration.conditionCollection[index] = conditionConfiguration;
|
||||
condition.update(conditionConfiguration);
|
||||
this.persistConditions();
|
||||
}
|
||||
|
||||
updateConditionDescription(condition) {
|
||||
const found = this.conditionSetDomainObject.configuration.conditionCollection.find(conditionConfiguration => (conditionConfiguration.id === condition.id));
|
||||
found.summary = condition.description;
|
||||
this.persistConditions();
|
||||
}
|
||||
|
||||
initCondition(conditionConfiguration, index) {
|
||||
let condition = new Condition(conditionConfiguration, this.openmct, this);
|
||||
if (index !== undefined) {
|
||||
this.conditionClassCollection.splice(index + 1, 0, condition);
|
||||
this.conditions.splice(index + 1, 0, condition);
|
||||
} else {
|
||||
this.conditionClassCollection.unshift(condition);
|
||||
this.conditions.unshift(condition);
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,15 +192,15 @@ export default class ConditionManager extends EventEmitter {
|
||||
}
|
||||
|
||||
removeCondition(index) {
|
||||
let condition = this.conditionClassCollection[index];
|
||||
let condition = this.conditions[index];
|
||||
condition.destroy();
|
||||
this.conditionClassCollection.splice(index, 1);
|
||||
this.conditions.splice(index, 1);
|
||||
this.conditionSetDomainObject.configuration.conditionCollection.splice(index, 1);
|
||||
this.persistConditions();
|
||||
}
|
||||
|
||||
findConditionById(id) {
|
||||
return this.conditionClassCollection.find(conditionClass => conditionClass.id === id);
|
||||
return this.conditions.find(condition => condition.id === id);
|
||||
}
|
||||
|
||||
reorderConditions(reorderPlan) {
|
||||
@ -234,14 +245,14 @@ export default class ConditionManager extends EventEmitter {
|
||||
}
|
||||
|
||||
requestLADConditionSetOutput() {
|
||||
if (!this.conditionClassCollection.length) {
|
||||
if (!this.conditions.length) {
|
||||
return Promise.resolve([]);
|
||||
}
|
||||
|
||||
return this.compositionLoad.then(() => {
|
||||
let latestTimestamp;
|
||||
let conditionResults = {};
|
||||
const conditionRequests = this.conditionClassCollection
|
||||
const conditionRequests = this.conditions
|
||||
.map(condition => condition.requestLADConditionResult());
|
||||
|
||||
return Promise.all(conditionRequests)
|
||||
@ -281,7 +292,7 @@ export default class ConditionManager extends EventEmitter {
|
||||
isTelemetryUsed(endpoint) {
|
||||
const id = this.openmct.objects.makeKeyString(endpoint.identifier);
|
||||
|
||||
for(const condition of this.conditionClassCollection) {
|
||||
for(const condition of this.conditions) {
|
||||
if (condition.isTelemetryUsed(id)) {
|
||||
return true;
|
||||
}
|
||||
@ -300,7 +311,7 @@ export default class ConditionManager extends EventEmitter {
|
||||
let timestamp = {};
|
||||
timestamp[timeSystemKey] = normalizedDatum[timeSystemKey];
|
||||
|
||||
this.conditionClassCollection.forEach(condition => {
|
||||
this.conditions.forEach(condition => {
|
||||
condition.getResult(normalizedDatum);
|
||||
});
|
||||
|
||||
@ -364,7 +375,7 @@ export default class ConditionManager extends EventEmitter {
|
||||
this.stopObservingForChanges();
|
||||
}
|
||||
|
||||
this.conditionClassCollection.forEach((condition) => {
|
||||
this.conditions.forEach((condition) => {
|
||||
condition.destroy();
|
||||
})
|
||||
}
|
||||
|
@ -126,7 +126,7 @@ describe('ConditionManager', () => {
|
||||
|
||||
it('creates a conditionCollection with a default condition', function () {
|
||||
expect(conditionMgr.conditionSetDomainObject.configuration.conditionCollection.length).toEqual(1);
|
||||
let defaultConditionId = conditionMgr.conditionClassCollection[0].id;
|
||||
let defaultConditionId = conditionMgr.conditions[0].id;
|
||||
expect(defaultConditionId).toEqual(mockCondition.id);
|
||||
});
|
||||
|
||||
|
@ -36,19 +36,20 @@ describe("The condition", function () {
|
||||
|
||||
beforeEach (() => {
|
||||
conditionManager = jasmine.createSpyObj('conditionManager',
|
||||
['on']
|
||||
['on', 'updateConditionDescription']
|
||||
);
|
||||
mockTelemetryReceived = jasmine.createSpy('listener');
|
||||
conditionManager.on('telemetryReceived', mockTelemetryReceived);
|
||||
conditionManager.updateConditionDescription.and.returnValue(function () {});
|
||||
|
||||
testTelemetryObject = {
|
||||
identifier:{ namespace: "", key: "test-object"},
|
||||
type: "test-object",
|
||||
name: "Test Object",
|
||||
telemetry: {
|
||||
values: [{
|
||||
key: "value",
|
||||
name: "Value",
|
||||
valueMetadatas: [{
|
||||
key: "some-key",
|
||||
name: "Some attribute",
|
||||
hints: {
|
||||
range: 2
|
||||
}
|
||||
@ -78,7 +79,7 @@ describe("The condition", function () {
|
||||
openmct.telemetry = jasmine.createSpyObj('telemetry', ['isTelemetryObject', 'subscribe', 'getMetadata']);
|
||||
openmct.telemetry.isTelemetryObject.and.returnValue(true);
|
||||
openmct.telemetry.subscribe.and.returnValue(function () {});
|
||||
openmct.telemetry.getMetadata.and.returnValue(testTelemetryObject.telemetry.values);
|
||||
openmct.telemetry.getMetadata.and.returnValue(testTelemetryObject.telemetry);
|
||||
|
||||
mockTimeSystems = {
|
||||
key: 'utc'
|
||||
|
@ -50,7 +50,7 @@
|
||||
|
||||
<span class="c-condition__name">{{ condition.configuration.name }}</span>
|
||||
<span class="c-condition__summary">
|
||||
<template v-if="!canEvaluateCriteria">
|
||||
<template v-if="!condition.isDefault && !canEvaluateCriteria">
|
||||
Define criteria
|
||||
</template>
|
||||
<span v-else>
|
||||
@ -250,7 +250,7 @@ export default {
|
||||
keys.forEach((trigger) => {
|
||||
triggerOptions.push({
|
||||
value: TRIGGER[trigger],
|
||||
label: TRIGGER_LABEL[TRIGGER[trigger]]
|
||||
label: `when ${TRIGGER_LABEL[TRIGGER[trigger]]}`
|
||||
});
|
||||
});
|
||||
return triggerOptions;
|
||||
|
@ -152,7 +152,8 @@ export default {
|
||||
},
|
||||
observeForChanges() {
|
||||
this.stopObservingForChanges = this.openmct.objects.observe(this.domainObject, 'configuration.conditionCollection', (newConditionCollection) => {
|
||||
this.conditionCollection = newConditionCollection;
|
||||
//this forces children to re-render
|
||||
this.conditionCollection = newConditionCollection.map(condition => condition);
|
||||
this.updateDefaultCondition();
|
||||
});
|
||||
},
|
||||
|
@ -27,20 +27,20 @@
|
||||
>
|
||||
{{ condition.configuration.name }}
|
||||
</span>
|
||||
<span v-for="(criterionDescription, index) in criterionDescriptions"
|
||||
:key="criterionDescription"
|
||||
class="c-style__condition-desc__text"
|
||||
<span class="c-style__condition-desc__text"
|
||||
v-if="!condition.isDefault"
|
||||
>
|
||||
<template v-if="!index">When</template>
|
||||
{{ criterionDescription }}
|
||||
<template v-if="index < (criterionDescriptions.length-1)">{{ triggerDescription }}</template>
|
||||
{{ description }}
|
||||
</span>
|
||||
<span class="c-style__condition-desc__text"
|
||||
v-else
|
||||
>
|
||||
Match if no other condition is matched
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { TRIGGER } from "@/plugins/condition/utils/constants";
|
||||
import { OPERATIONS } from "@/plugins/condition/utils/operations";
|
||||
|
||||
export default {
|
||||
name: 'ConditionDescription',
|
||||
@ -59,95 +59,9 @@ export default {
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
criterionDescriptions: [],
|
||||
triggerDescription: ''
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
condition: {
|
||||
handler(val) {
|
||||
this.getConditionDescription();
|
||||
},
|
||||
deep: true
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getConditionDescription();
|
||||
},
|
||||
methods: {
|
||||
getTriggerDescription(trigger) {
|
||||
let description = '';
|
||||
switch(trigger) {
|
||||
case TRIGGER.ANY:
|
||||
case TRIGGER.XOR:
|
||||
description = 'or';
|
||||
break;
|
||||
case TRIGGER.ALL:
|
||||
case TRIGGER.NOT: description = 'and';
|
||||
break;
|
||||
}
|
||||
return description;
|
||||
},
|
||||
getConditionDescription() {
|
||||
if (this.condition) {
|
||||
this.triggerDescription = this.getTriggerDescription(this.condition.configuration.trigger);
|
||||
this.criterionDescriptions = [];
|
||||
this.condition.configuration.criteria.forEach((criterion, index) => {
|
||||
this.getCriterionDescription(criterion, index);
|
||||
});
|
||||
if (this.condition.isDefault) {
|
||||
this.criterionDescriptions.splice(0, 0, 'all else fails');
|
||||
}
|
||||
} else {
|
||||
this.criterionDescriptions = [];
|
||||
}
|
||||
},
|
||||
getCriterionDescription(criterion, index) {
|
||||
if (!criterion.telemetry) {
|
||||
let description = `Unknown ${criterion.metadata} ${this.getOperatorText(criterion.operation, criterion.input)}`;
|
||||
this.criterionDescriptions.splice(index, 0, description);
|
||||
} else if (criterion.telemetry === 'all' || criterion.telemetry === 'any') {
|
||||
const telemetryDescription = criterion.telemetry === 'all' ? 'All telemetry' : 'Any telemetry';
|
||||
let description = `${telemetryDescription} ${criterion.metadata} ${this.getOperatorText(criterion.operation, criterion.input)}`;
|
||||
this.criterionDescriptions.splice(index, 0, description);
|
||||
} else {
|
||||
this.openmct.objects.get(criterion.telemetry).then((telemetryObject) => {
|
||||
if (telemetryObject.type === 'unknown') {
|
||||
let description = `Unknown ${criterion.metadata} ${this.getOperatorText(criterion.operation, criterion.input)}`;
|
||||
this.criterionDescriptions.splice(index, 0, description);
|
||||
} else {
|
||||
let metadataValue = criterion.metadata;
|
||||
let inputValue = criterion.input;
|
||||
if (criterion.metadata) {
|
||||
this.telemetryMetadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
|
||||
const metadataObj = this.telemetryMetadata.valueMetadatas.find((metadata) => metadata.key === criterion.metadata);
|
||||
if (metadataObj) {
|
||||
if (metadataObj.name) {
|
||||
metadataValue = metadataObj.name;
|
||||
}
|
||||
if(metadataObj.enumerations && inputValue.length) {
|
||||
if (metadataObj.enumerations[inputValue[0]] && metadataObj.enumerations[inputValue[0]].string) {
|
||||
inputValue = [metadataObj.enumerations[inputValue[0]].string];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
let description = `${telemetryObject.name} ${metadataValue} ${this.getOperatorText(criterion.operation, inputValue)}`;
|
||||
if (this.criterionDescriptions[index]) {
|
||||
this.criterionDescriptions[index] = description;
|
||||
} else {
|
||||
this.criterionDescriptions.splice(index, 0, description);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
getOperatorText(operationName, values) {
|
||||
const found = OPERATIONS.find((operation) => operation.name === operationName);
|
||||
return found ? found.getDescription(values) : '';
|
||||
computed: {
|
||||
description() {
|
||||
return this.condition ? this.condition.summary : '';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -66,22 +66,13 @@ export default {
|
||||
}
|
||||
},
|
||||
getCriterionErrors(criterion, index) {
|
||||
if (!criterion.telemetry) {
|
||||
//It is sufficient to check for absence of telemetry here since the condition manager ensures that telemetry for a criterion is set if it exists
|
||||
const isInvalidTelemetry = !criterion.telemetry && (criterion.telemetry !== 'all' && criterion.telemetry !== 'any');
|
||||
if (isInvalidTelemetry) {
|
||||
this.conditionErrors.push({
|
||||
message: ERROR.TELEMETRY_NOT_FOUND,
|
||||
additionalInfo: ''
|
||||
});
|
||||
} else {
|
||||
if (criterion.telemetry !== 'all' && criterion.telemetry !== 'any') {
|
||||
this.openmct.objects.get(criterion.telemetry).then((telemetryObject) => {
|
||||
if (telemetryObject.type === 'unknown') {
|
||||
this.conditionErrors.push({
|
||||
message: ERROR.TELEMETRY_NOT_FOUND,
|
||||
additionalInfo: criterion.telemetry ? `Key: ${this.openmct.objects.makeKeyString(criterion.telemetry)}` : ''
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@
|
||||
<input v-model="criterion.input[inputIndex]"
|
||||
class="c-cdef__control__input"
|
||||
:type="setInputType"
|
||||
@blur="persist"
|
||||
@change="persist"
|
||||
>
|
||||
<span v-if="inputIndex < inputCount-1">and</span>
|
||||
</span>
|
||||
@ -108,6 +108,7 @@
|
||||
<script>
|
||||
import { OPERATIONS } from '../utils/operations';
|
||||
import { INPUT_TYPES } from '../utils/operations';
|
||||
import {TRIGGER_CONJUNCTION} from "../utils/constants";
|
||||
|
||||
export default {
|
||||
inject: ['openmct'],
|
||||
@ -143,8 +144,8 @@ export default {
|
||||
},
|
||||
computed: {
|
||||
setRowLabel: function () {
|
||||
let operator = this.trigger === 'all' ? 'and ': 'or ';
|
||||
return (this.index !== 0 ? operator : '') + 'when';
|
||||
let operator = TRIGGER_CONJUNCTION[this.trigger];
|
||||
return (this.index !== 0 ? operator : '') + ' when';
|
||||
},
|
||||
filteredOps: function () {
|
||||
return this.operations.filter(op => op.appliesTo.indexOf(this.operationFormat) !== -1);
|
||||
@ -178,17 +179,18 @@ export default {
|
||||
methods: {
|
||||
checkTelemetry() {
|
||||
if(this.criterion.telemetry) {
|
||||
if (this.criterion.telemetry === 'any' || this.criterion.telemetry === 'all') {
|
||||
this.updateMetadataOptions();
|
||||
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) {
|
||||
//telemetry being used was removed. So reset this criterion.
|
||||
this.criterion.telemetry = '';
|
||||
this.criterion.metadata = '';
|
||||
this.criterion.input = [];
|
||||
this.criterion.operation = '';
|
||||
this.persist();
|
||||
} else {
|
||||
if (!this.telemetry.find((telemetryObj) => this.openmct.objects.areIdsEqual(this.criterion.telemetry, telemetryObj.identifier))) {
|
||||
//telemetry being used was removed. So reset this criterion.
|
||||
this.criterion.telemetry = '';
|
||||
this.criterion.metadata = '';
|
||||
this.criterion.input = [];
|
||||
this.criterion.operation = '';
|
||||
this.persist();
|
||||
}
|
||||
this.updateMetadataOptions();
|
||||
}
|
||||
}
|
||||
},
|
||||
@ -221,19 +223,17 @@ export default {
|
||||
this.persist();
|
||||
}
|
||||
if (this.criterion.telemetry) {
|
||||
const telemetry = (this.criterion.telemetry === 'all' || this.criterion.telemetry === 'any') ? this.telemetry : [{
|
||||
identifier: this.criterion.telemetry
|
||||
}];
|
||||
|
||||
let telemetryPromises = telemetry.map((telemetryObject) => this.openmct.objects.get(telemetryObject.identifier));
|
||||
Promise.all(telemetryPromises).then(telemetryObjects => {
|
||||
this.telemetryMetadataOptions = [];
|
||||
telemetryObjects.forEach(telemetryObject => {
|
||||
let telemetryMetadata = this.openmct.telemetry.getMetadata(telemetryObject);
|
||||
this.addMetaDataOptions(telemetryMetadata.values());
|
||||
});
|
||||
this.updateOperations();
|
||||
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);
|
||||
this.addMetaDataOptions(telemetryMetadata.values());
|
||||
});
|
||||
this.updateOperations();
|
||||
}
|
||||
},
|
||||
addMetaDataOptions(options) {
|
||||
|
@ -23,6 +23,7 @@
|
||||
import TelemetryCriterion from './TelemetryCriterion';
|
||||
import { evaluateResults } from "../utils/evaluator";
|
||||
import { getLatestTimestamp } from '../utils/time';
|
||||
import { getOperatorText } from "@/plugins/condition/utils/operations";
|
||||
|
||||
export default class AllTelemetryCriterion extends TelemetryCriterion {
|
||||
|
||||
@ -46,7 +47,7 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
|
||||
return (this.telemetry === 'any' || this.telemetry === 'all') && this.metadata && this.operation;
|
||||
}
|
||||
|
||||
updateTelemetry(telemetryObjects) {
|
||||
updateTelemetryObjects(telemetryObjects) {
|
||||
this.telemetryObjects = { ...telemetryObjects };
|
||||
this.removeTelemetryDataCache();
|
||||
}
|
||||
@ -159,6 +160,25 @@ export default class AllTelemetryCriterion extends TelemetryCriterion {
|
||||
});
|
||||
}
|
||||
|
||||
getDescription() {
|
||||
const telemetryDescription = this.telemetry === 'all' ? 'all telemetry' : 'any telemetry';
|
||||
let metadataValue = this.metadata;
|
||||
let inputValue = this.input;
|
||||
if (this.metadata) {
|
||||
const telemetryObjects = Object.values(this.telemetryObjects);
|
||||
for (let i=0; i < telemetryObjects.length; i++) {
|
||||
const telemetryObject = telemetryObjects[i];
|
||||
const metadataObject = this.getMetaDataObject(telemetryObject, this.metadata);
|
||||
if (metadataObject) {
|
||||
metadataValue = this.getMetadataValueFromMetaData(metadataObject) || this.metadata;
|
||||
inputValue = this.getInputValueFromMetaData(metadataObject, this.input) || this.input;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return `${telemetryDescription} ${metadataValue} ${getOperatorText(this.operation, inputValue)}`;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
delete this.telemetryObjects;
|
||||
delete this.telemetryDataCache;
|
||||
|
@ -21,7 +21,7 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import EventEmitter from 'EventEmitter';
|
||||
import { OPERATIONS } from '../utils/operations';
|
||||
import { OPERATIONS, getOperatorText } from '../utils/operations';
|
||||
|
||||
export default class TelemetryCriterion extends EventEmitter {
|
||||
|
||||
@ -49,15 +49,15 @@ export default class TelemetryCriterion extends EventEmitter {
|
||||
}
|
||||
|
||||
initialize() {
|
||||
this.telemetryObject = this.telemetryDomainObjectDefinition.telemetryObject;
|
||||
this.telemetryObjectIdAsString = this.openmct.objects.makeKeyString(this.telemetryDomainObjectDefinition.telemetry);
|
||||
this.updateTelemetryObjects(this.telemetryDomainObjectDefinition.telemetryObjects);
|
||||
}
|
||||
|
||||
isValid() {
|
||||
return this.telemetryObject && this.metadata && this.operation;
|
||||
}
|
||||
|
||||
updateTelemetry(telemetryObjects) {
|
||||
updateTelemetryObjects(telemetryObjects) {
|
||||
this.telemetryObject = telemetryObjects[this.telemetryObjectIdAsString];
|
||||
}
|
||||
|
||||
@ -153,6 +153,51 @@ export default class TelemetryCriterion extends EventEmitter {
|
||||
});
|
||||
}
|
||||
|
||||
getMetaDataObject(telemetryObject, metadata) {
|
||||
let metadataObject;
|
||||
if (metadata) {
|
||||
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) {
|
||||
const enumeration = metadataObject.enumerations[input[0]];
|
||||
if (enumeration !== undefined && enumeration.string) {
|
||||
inputValue = [enumeration.string];
|
||||
}
|
||||
}
|
||||
}
|
||||
return inputValue;
|
||||
}
|
||||
|
||||
getMetadataValueFromMetaData(metadataObject) {
|
||||
let metadataValue;
|
||||
if (metadataObject) {
|
||||
if (metadataObject.name) {
|
||||
metadataValue = metadataObject.name;
|
||||
}
|
||||
}
|
||||
return metadataValue;
|
||||
}
|
||||
|
||||
getDescription(criterion, index) {
|
||||
let description;
|
||||
if (!this.telemetry || !this.telemetryObject || (this.telemetryObject.type === 'unknown')) {
|
||||
description = `Unknown ${this.metadata} ${getOperatorText(this.operation, this.input)}`;
|
||||
} else {
|
||||
const metadataObject = this.getMetaDataObject(this.telemetryObject, this.metadata);
|
||||
const metadataValue = this.getMetadataValueFromMetaData(metadataObject) || this.metadata;
|
||||
const inputValue = this.getInputValueFromMetaData(metadataObject, this.input) || this.input;
|
||||
description = `${this.telemetryObject.name} ${metadataValue} ${getOperatorText(this.operation, inputValue)}`;
|
||||
}
|
||||
|
||||
return description;
|
||||
}
|
||||
|
||||
destroy() {
|
||||
delete this.telemetryObject;
|
||||
|
@ -83,7 +83,7 @@ describe("The telemetry criterion", function () {
|
||||
operation: 'textContains',
|
||||
metadata: 'value',
|
||||
input: ['Hell'],
|
||||
telemetryObject: testTelemetryObject
|
||||
telemetryObjects: {[testTelemetryObject.identifier.key]: testTelemetryObject}
|
||||
};
|
||||
|
||||
mockListener = jasmine.createSpy('listener');
|
||||
@ -109,13 +109,4 @@ describe("The telemetry criterion", function () {
|
||||
});
|
||||
expect(telemetryCriterion.result).toBeTrue();
|
||||
});
|
||||
|
||||
// it("does not return a result on new data from irrelavant telemetry providers", function () {
|
||||
// telemetryCriterion.getResult({
|
||||
// value: 'Hello',
|
||||
// utc: 'Hi',
|
||||
// id: '1234'
|
||||
// });
|
||||
// expect(telemetryCriterion.result).toBeFalse();
|
||||
// });
|
||||
});
|
||||
|
@ -28,10 +28,17 @@ export const TRIGGER = {
|
||||
};
|
||||
|
||||
export const TRIGGER_LABEL = {
|
||||
'any': 'when any criteria are met',
|
||||
'all': 'when all criteria are met',
|
||||
'not': 'when no criteria are met',
|
||||
'xor': 'when only one criteria is met'
|
||||
'any': 'any criteria are met',
|
||||
'all': 'all criteria are met',
|
||||
'not': 'no criteria are met',
|
||||
'xor': 'only one criterion is met'
|
||||
};
|
||||
|
||||
export const TRIGGER_CONJUNCTION = {
|
||||
'any': 'or',
|
||||
'all': 'and',
|
||||
'not': 'and',
|
||||
'xor': 'or'
|
||||
};
|
||||
|
||||
export const STYLE_CONSTANTS = {
|
||||
|
@ -35,7 +35,7 @@ export const evaluateResults = (results, trigger) => {
|
||||
|
||||
function matchAll(results) {
|
||||
for (const result of results) {
|
||||
if (!result) {
|
||||
if (result !== true) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -45,7 +45,7 @@ function matchAll(results) {
|
||||
|
||||
function matchAny(results) {
|
||||
for (const result of results) {
|
||||
if (result) {
|
||||
if (result === true) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@ -56,7 +56,7 @@ function matchAny(results) {
|
||||
function matchExact(results, target) {
|
||||
let matches = 0;
|
||||
for (const result of results) {
|
||||
if (result) {
|
||||
if (result === true) {
|
||||
matches++;
|
||||
}
|
||||
if (matches > target) {
|
||||
|
@ -250,12 +250,12 @@ export const OPERATIONS = [
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'valueIs',
|
||||
name: 'isOneOf',
|
||||
operation: function (input) {
|
||||
const lhsValue = input[0] !== undefined ? input[0].toString() : '';
|
||||
if (input[1]) {
|
||||
const values = input[1].split(',');
|
||||
return values.find((value) => lhsValue === value.toString().trim());
|
||||
return values.some((value) => lhsValue === value.toString().trim());
|
||||
}
|
||||
return false;
|
||||
},
|
||||
@ -267,12 +267,12 @@ export const OPERATIONS = [
|
||||
}
|
||||
},
|
||||
{
|
||||
name: 'valueIsNot',
|
||||
name: 'isNotOneOf',
|
||||
operation: function (input) {
|
||||
const lhsValue = input[0] !== undefined ? input[0].toString() : '';
|
||||
if (input[1]) {
|
||||
const values = input[1].split(',');
|
||||
const found = values.find((value) => lhsValue === value.toString().trim());
|
||||
const found = values.some((value) => lhsValue === value.toString().trim());
|
||||
return !found;
|
||||
}
|
||||
return false;
|
||||
@ -290,3 +290,8 @@ export const INPUT_TYPES = {
|
||||
'string': 'text',
|
||||
'number': 'number'
|
||||
};
|
||||
|
||||
export const getOperatorText = (operationName, values) => {
|
||||
const found = OPERATIONS.find((operation) => operation.name === operationName);
|
||||
return found ? found.getDescription(values) : '';
|
||||
};
|
||||
|
@ -21,8 +21,8 @@
|
||||
*****************************************************************************/
|
||||
|
||||
import { OPERATIONS } from "./operations";
|
||||
let isOneOfOperation = OPERATIONS.find((operation) => operation.name === 'valueIs');
|
||||
let isNotOneOfOperation = OPERATIONS.find((operation) => operation.name === 'valueIsNot');
|
||||
let isOneOfOperation = OPERATIONS.find((operation) => operation.name === 'isOneOf');
|
||||
let isNotOneOfOperation = OPERATIONS.find((operation) => operation.name === 'isNotOneOf');
|
||||
let isBetween = OPERATIONS.find((operation) => operation.name === 'between');
|
||||
let isNotBetween = OPERATIONS.find((operation) => operation.name === 'notBetween');
|
||||
let enumIsOperation = OPERATIONS.find((operation) => operation.name === 'enumValueIs');
|
||||
|
Loading…
x
Reference in New Issue
Block a user