Addresses review comments for conditionals code (#2978)

Conditionals code refactoring

Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
Shefali Joshi 2020-06-17 14:56:36 -07:00 committed by GitHub
parent e9968e3649
commit 38dbf2ccab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 208 additions and 194 deletions

View File

@ -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 = {};

View File

@ -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();
})
}

View File

@ -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);
});

View File

@ -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'

View File

@ -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;

View File

@ -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();
});
},

View File

@ -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 : '';
}
}
}

View File

@ -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)}` : ''
});
}
});
}
}
}
}

View File

@ -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) {

View File

@ -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;

View File

@ -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;

View File

@ -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();
// });
});

View File

@ -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 = {

View File

@ -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) {

View File

@ -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) : '';
};

View File

@ -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');