From 8c796b4e5708e28dfaf3fa2796d796d6d739803b Mon Sep 17 00:00:00 2001 From: Joshi Date: Mon, 6 Jan 2020 10:09:47 -0800 Subject: [PATCH 01/59] Allows adding new conditions and associated criteria. Stub for evaluating conditions. --- src/plugins/condition/Condition.js | 178 +++++++++++++++++++++++ src/plugins/condition/utils/constants.js | 4 + src/plugins/condition/utils/evaluator.js | 7 + 3 files changed, 189 insertions(+) create mode 100644 src/plugins/condition/Condition.js create mode 100644 src/plugins/condition/utils/constants.js create mode 100644 src/plugins/condition/utils/evaluator.js diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js new file mode 100644 index 0000000000..94f4b98c68 --- /dev/null +++ b/src/plugins/condition/Condition.js @@ -0,0 +1,178 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2019, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +import * as EventEmitter from 'eventemitter3'; +import UUID from 'uuid'; +import TelemetryCriterion from "@/plugins/condition/criterion/TelemetryCriterion"; +import {computeConditionForAll, computeConditionForAny} from 'utils/evaluator' +import { TRIGGER } from "@/plugins/condition/utils/constants"; + +/* +* conditionDefinition = { +* trigger: 'any'/'all', +* criteria: [ +* { +* object: { +* operator: '', +* input: '', +* metaDataKey: '', +* telemetryObjectKey: 'someTelemetryObjectKey' +* } +* } +* ] +* } +*/ +export default class Condition extends EventEmitter { + + constructor(conditionDefinition, openmct) { + super(); + + this.openmct = openmct; + this.id = new UUID(); + this.criteriaMap = conditionDefinition.criteria ? this.createCriteria(conditionDefinition.criteria) : {}; + this.trigger = conditionDefinition.trigger; + this.result = null; + } + + updateTrigger(conditionDefinition) { + if (this.trigger !== conditionDefinition.trigger) { + this.trigger = conditionDefinition.trigger; + this.handleConditionUpdated(); + } + } + + generateNewCriterion() { + return { + id: new UUID(), + object: '', + key: '', + operation: '', + values: [] + }; + } + + createCriteria(criterionDefinitions) { + criterionDefinitions.forEach((criterionDefinition) => { + this.addCriterion(criterionDefinition); + }); + } + + updateCriteria(criterionDefinitions) { + this.destroyCriteria(); + this.createCriteria(criterionDefinitions); + } + + /** + * adds criterion to the condition. + */ + addCriterion(criterionDefinition) { + if (!criterionDefinition) { + criterionDefinition = this.generateNewCriterion(); + } + let criterion = new TelemetryCriterion(criterionDefinition.object, this.openmct); + criterion.on('criterion::Update', this.handleCriterionUpdated); + this.criteriaMap[criterionDefinition.id] = criterion; + this.handleConditionUpdated(); + return criterionDefinition.id; + } + + findCriterion(id) { + return this.criteriaMap[id] || null; + } + + updateCriterion(id, criterionDefinition) { + if (this.destroyCriterion(id)) { + this.criteriaMap[id] = new TelemetryCriterion(criterionDefinition.object, this.openmct); + this.handleConditionUpdated(); + } + } + + removeCriterion(id) { + if (this.destroyCriterion(id)) { + this.handleConditionUpdated(); + } + } + + destroyCriterion(id) { + let criterion = this.findCriterion(id); + const criterionId = id; + if (criterion) { + criterion.unsubscribe(); + criterion.off('criterion::Update', (result) => { + this.handleCriterionUpdated(criterionId, result); + }); + delete this.criteriaMap[id]; + return true; + } + return false; + } + + handleCriterionUpdated(id, result) { + // reevaluate the condition's output + // TODO: should we save the result of a criterion here or in the criterion object itself? + this.evaluate(); + this.handleConditionUpdated(); + } + + handleConditionUpdated() { + // trigger an updated event so that consumers can react accordingly + } + + getCriteria() { + let criteria = []; + for(let id in this.criteriaMap) { + if (this.criteriaMap.hasOwnProperty(id) && this.criteriaMap[id]) { + criteria.push(this.criteriaMap[id]); + } + } + + return criteria; + } + + destroyCriteria() { + let success = true; + for(let id in this.criteriaMap) { + if (this.criteriaMap.hasOwnProperty(id) && this.criteriaMap[id]) { + success = success && this.destroyCriterion(this.criteriaMap[id]); + } + } + + return success; + } + + evaluate() { + let criteria = this.getCriteria(); + if (this.trigger === TRIGGER.ANY) { + this.result = computeConditionForAny(criteria); + } else if (this.trigger === TRIGGER.ALL) { + this.result = computeConditionForAll(criteria); + } + } + + emitResult(data, error) { + this.emit('condition::Update', { + identifier: this.id, + data: data, + error: error + }); + } +} diff --git a/src/plugins/condition/utils/constants.js b/src/plugins/condition/utils/constants.js new file mode 100644 index 0000000000..968c6168bf --- /dev/null +++ b/src/plugins/condition/utils/constants.js @@ -0,0 +1,4 @@ +export const TRIGGER = { + ANY: 'any', + ALL: 'all' +}; diff --git a/src/plugins/condition/utils/evaluator.js b/src/plugins/condition/utils/evaluator.js new file mode 100644 index 0000000000..51bd7173f6 --- /dev/null +++ b/src/plugins/condition/utils/evaluator.js @@ -0,0 +1,7 @@ +export const computeConditionForAny = (args) => { + return false; +}; + +export const computeConditionForAll = (args) => { + return false; +}; From 097fa2e655336494d42056ba222c819580992994 Mon Sep 17 00:00:00 2001 From: Joshi Date: Tue, 7 Jan 2020 08:44:30 -0800 Subject: [PATCH 02/59] condition collection add to composition --- .../components/ConditionCollection.vue | 38 ++++++++++++++----- 1 file changed, 28 insertions(+), 10 deletions(-) diff --git a/src/plugins/condition/components/ConditionCollection.vue b/src/plugins/condition/components/ConditionCollection.vue index ddc1ff3ad5..0801258c9d 100644 --- a/src/plugins/condition/components/ConditionCollection.vue +++ b/src/plugins/condition/components/ConditionCollection.vue @@ -75,24 +75,42 @@ export default { }; }, destroyed() { - this.composition.off('add', this.addCondition); - this.composition.off('remove', this.removeCondition); - this.composition.off('reorder', this.reorder); + this.composition.off('add', this.added); + // this.composition.off('remove', this.removeCondition); + // this.composition.off('reorder', this.reorder); }, mounted() { + this.instantiate = this.openmct.$injector.get('instantiate'); this.composition = this.openmct.composition.get(this.domainObject); - this.composition.on('add', this.addCondition); - this.composition.on('remove', this.removeCondition); - this.composition.on('reorder', this.reorder); + this.composition.on('add', this.added); + // this.composition.on('remove', this.removeCondition); + // this.composition.on('reorder', this.reorder); this.composition.load(); }, methods: { + added(dobj) { + console.log(dobj.composition); + }, addCondition() { - let condition = {}; - condition.domainObject = this.domainObject; - condition.key = this.openmct.objects.makeKeyString(this.domainObject.identifier); + let conditionObj = { + "composition": [], + "modified": 1578373933245, + "persisted": 1578373933245, + "name": "Condition1", + "type": "condition", + "id": "12345"+this.conditions.length, + "location": "mine", + "identifier": { + "namespace": "", + "key": "12345"+this.conditions.length + } + }; - this.conditions.unshift(condition); + let newDO = this.instantiate(conditionObj, conditionObj.identifier.key); + let newStyleRootObj = newDO.useCapability('adapter'); + + this.conditions.unshift(newStyleRootObj); + this.composition.add(newStyleRootObj); }, removeCondition(identifier) { console.log(`remove condition`); From 63f8fb54d4f11a4e878c2151122e542e2aa7d816 Mon Sep 17 00:00:00 2001 From: Joshi Date: Tue, 7 Jan 2020 11:42:31 -0800 Subject: [PATCH 03/59] conditions added to conditioncollection --- .../components/ConditionCollection.vue | 28 ++++++++++--------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/src/plugins/condition/components/ConditionCollection.vue b/src/plugins/condition/components/ConditionCollection.vue index 0801258c9d..a85b1b381c 100644 --- a/src/plugins/condition/components/ConditionCollection.vue +++ b/src/plugins/condition/components/ConditionCollection.vue @@ -49,6 +49,7 @@ diff --git a/src/plugins/condition/plugin.js b/src/plugins/condition/plugin.js index ced6477808..6c4bba0005 100644 --- a/src/plugins/condition/plugin.js +++ b/src/plugins/condition/plugin.js @@ -20,6 +20,7 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ import ConditionSetViewProvider from './ConditionSetViewProvider.js'; +// import Condition from './Condition.js'; export default function ConditionPlugin() { @@ -41,6 +42,9 @@ export default function ConditionPlugin() { creatable: true, cssClass: 'icon-summary-widget', // TODO: replace with class for new icon initialize: function (domainObject) { + domainObject.configuration = { + conditionCollection: [] + }; domainObject.composition = []; } }); From d0e8f650be3e186adbf507a1b52f354e6fd6bd46 Mon Sep 17 00:00:00 2001 From: Joel McKinnon Date: Fri, 10 Jan 2020 12:59:43 -0800 Subject: [PATCH 07/59] remove condition with persistance --- .../components/ConditionCollection.vue | 3 ++- .../condition/components/ConditionEdit.vue | 23 +++++++++++-------- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/plugins/condition/components/ConditionCollection.vue b/src/plugins/condition/components/ConditionCollection.vue index 50808dd27b..a9cfe62c8a 100644 --- a/src/plugins/condition/components/ConditionCollection.vue +++ b/src/plugins/condition/components/ConditionCollection.vue @@ -31,6 +31,7 @@
-
@@ -94,16 +94,19 @@ export default { }, methods: { removeCondition(ev) { - let conditionDiv = ev.target.closest('.conditionArea'); - let conditionCollectionDiv = conditionDiv.closest('.condition-collection'); - let index = Array.from(conditionDiv.parentNode.children).indexOf(conditionDiv) + const conditionDiv = ev.target.closest('.conditionArea'); + const conditionCollectionDiv = conditionDiv.closest('.condition-collection'); + const index = Array.from(conditionCollectionDiv.children).indexOf(conditionDiv); - //Array.from(element.parentNode.children).indexOf(element) - //console.log(`conditionDiv.nodeName: ${conditionDiv.nodeName}`); - console.log(`index: ${index}`); - console.log(`conditionCollectionDiv.children.length: ${conditionCollectionDiv.childNodes.length}`); - console.log(this.domainObject.configuration.conditionCollection.length); - // this.conditions.splice(index, 1); + this.domainObject.configuration.conditionCollection.splice(index, 1); + this.persist() + }, + persist(index) { + if (index) { + this.openmct.objects.mutate(this.domainObject, `configuration.conditionCollection[${index}]`, this.domainObject.configuration.conditionCollection[index]); + } else { + this.openmct.objects.mutate(this.domainObject, 'configuration.conditionCollection', this.domainObject.configuration.conditionCollection); + } } } } From d79402c56832dafe8ea16615677faba60ce7d0d8 Mon Sep 17 00:00:00 2001 From: Joel McKinnon Date: Fri, 10 Jan 2020 15:58:16 -0800 Subject: [PATCH 08/59] name property WIP --- .../components/ConditionCollection.vue | 3 ++- .../condition/components/ConditionEdit.vue | 19 +++++++++++++------ 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/src/plugins/condition/components/ConditionCollection.vue b/src/plugins/condition/components/ConditionCollection.vue index a9cfe62c8a..b80b00919c 100644 --- a/src/plugins/condition/components/ConditionCollection.vue +++ b/src/plugins/condition/components/ConditionCollection.vue @@ -35,6 +35,7 @@ >
@@ -85,7 +86,7 @@ export default { let conditionObjId = uuid(); let conditionObj = { "composition": [], - "name": "condition" + this.conditionCollection.length, + "name": "Unnamed Condition", "type": "condition", "id": conditionObjId, "location": this.parentKeyString, diff --git a/src/plugins/condition/components/ConditionEdit.vue b/src/plugins/condition/components/ConditionEdit.vue index 0e70a9b7e5..56d3af6e8f 100644 --- a/src/plugins/condition/components/ConditionEdit.vue +++ b/src/plugins/condition/components/ConditionEdit.vue @@ -20,7 +20,7 @@ [condition name] + >{{ name }} [condition description] + >{{ description }}
- @@ -80,12 +81,18 @@ export default { props: { isEditing: Boolean, isCurrent: Boolean, - isDefault: Boolean + isDefault: Boolean, + condition: { + type: Object, + required: true + } }, data() { - // console.log(`domainObject: ${domainObject}`); + console.log(`this.condition.name: ${this.condition.name}`); return { - expanded: true + expanded: true, + name: this.condition.name, + description: this.condition.description }; }, mounted() { From 68a2b9f3a895196b8fcaaeef72e579e1ccf2cf66 Mon Sep 17 00:00:00 2001 From: Joel McKinnon Date: Fri, 10 Jan 2020 16:45:20 -0800 Subject: [PATCH 09/59] added Default name --- src/plugins/condition/components/ConditionEdit.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/condition/components/ConditionEdit.vue b/src/plugins/condition/components/ConditionEdit.vue index 56d3af6e8f..38eb8c4618 100644 --- a/src/plugins/condition/components/ConditionEdit.vue +++ b/src/plugins/condition/components/ConditionEdit.vue @@ -91,7 +91,7 @@ export default { console.log(`this.condition.name: ${this.condition.name}`); return { expanded: true, - name: this.condition.name, + name: this.condition.name || 'Default', description: this.condition.description }; }, From 4f7345563fa7a4ab55f8ff49b65fb95071a6cd9f Mon Sep 17 00:00:00 2001 From: Joel McKinnon Date: Mon, 13 Jan 2020 13:40:43 -0800 Subject: [PATCH 10/59] temp --- .../components/ConditionCollection.vue | 2 ++ .../condition/components/ConditionEdit.vue | 20 +++---------------- 2 files changed, 5 insertions(+), 17 deletions(-) diff --git a/src/plugins/condition/components/ConditionCollection.vue b/src/plugins/condition/components/ConditionCollection.vue index b80b00919c..bec76ac52d 100644 --- a/src/plugins/condition/components/ConditionCollection.vue +++ b/src/plugins/condition/components/ConditionCollection.vue @@ -103,6 +103,8 @@ export default { this.conditionCollection.unshift(conditionDO); + console.log(conditionDO.name) + this.persist(); }, removeCondition(identifier) { diff --git a/src/plugins/condition/components/ConditionEdit.vue b/src/plugins/condition/components/ConditionEdit.vue index 38eb8c4618..5aac002257 100644 --- a/src/plugins/condition/components/ConditionEdit.vue +++ b/src/plugins/condition/components/ConditionEdit.vue @@ -14,22 +14,8 @@ @click="expanded = !expanded" >
- Default - - {{ name }} - - When all else fails - - {{ description }} - + {{ name }} + {{ description }}
Date: Mon, 13 Jan 2020 13:52:26 -0800 Subject: [PATCH 11/59] temp --- src/plugins/condition/components/ConditionCollection.vue | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/plugins/condition/components/ConditionCollection.vue b/src/plugins/condition/components/ConditionCollection.vue index bec76ac52d..9f99d7f62d 100644 --- a/src/plugins/condition/components/ConditionCollection.vue +++ b/src/plugins/condition/components/ConditionCollection.vue @@ -103,6 +103,8 @@ export default { this.conditionCollection.unshift(conditionDO); + this.$set(this.domainObject.configuration.conditionCollection, 0, conditionDO); + console.log(conditionDO.name) this.persist(); From 5d8252bb079201a725b2f8e392b1b613b976e8b9 Mon Sep 17 00:00:00 2001 From: Joshi Date: Mon, 13 Jan 2020 13:55:54 -0800 Subject: [PATCH 12/59] Adds tests for condition class --- src/plugins/condition/Condition.js | 1 + src/plugins/condition/ConditionSpec.js | 9 ++++++++- src/plugins/condition/StyleRuleManager.js | 0 3 files changed, 9 insertions(+), 1 deletion(-) create mode 100644 src/plugins/condition/StyleRuleManager.js diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index 5a5bb3e790..d16352bef9 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -175,6 +175,7 @@ export default class Condition extends EventEmitter { //TODO: implement as part of the evaluator class task. evaluate() { if (this.trigger === TRIGGER.ANY) { + criteria.evaluate(); this.result = false; } else if (this.trigger === TRIGGER.ALL) { this.result = false; diff --git a/src/plugins/condition/ConditionSpec.js b/src/plugins/condition/ConditionSpec.js index efb19d6fbe..c4d29545ac 100644 --- a/src/plugins/condition/ConditionSpec.js +++ b/src/plugins/condition/ConditionSpec.js @@ -57,8 +57,9 @@ describe("The condition", function () { openmct.objects = jasmine.createSpyObj('objects', ['get', 'makeKeyString']); openmct.objects.get.and.returnValue(testTelemetryObject); openmct.objects.makeKeyString.and.returnValue(testTelemetryObject.identifier.key); - openmct.telemetry = jasmine.createSpyObj('telemetry', ['isTelemetryObject']); + openmct.telemetry = jasmine.createSpyObj('telemetry', ['isTelemetryObject', 'subscribe']); openmct.telemetry.isTelemetryObject.and.returnValue(true); + openmct.telemetry.subscribe.and.returnValue(function () {}); testConditionDefinition = { trigger: TRIGGER.ANY, @@ -108,4 +109,10 @@ describe("The condition", function () { it("initializes with the trigger from the condition definition", function () { expect(conditionObj.trigger).toEqual(testConditionDefinition.trigger); }); + + it("destroys all criteria for a condition", function () { + const result = conditionObj.destroyCriteria(); + expect(result).toBeTrue(); + expect(conditionObj.criteria.length).toEqual(0); + }); }); diff --git a/src/plugins/condition/StyleRuleManager.js b/src/plugins/condition/StyleRuleManager.js new file mode 100644 index 0000000000..e69de29bb2 From a6825f530c6a483e4ee974f823c68d32293e756d Mon Sep 17 00:00:00 2001 From: Joshi Date: Mon, 13 Jan 2020 14:05:43 -0800 Subject: [PATCH 13/59] Fixes failing test. --- src/plugins/condition/criterion/TelemetryCriterion.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/plugins/condition/criterion/TelemetryCriterion.js b/src/plugins/condition/criterion/TelemetryCriterion.js index 9f02851a6e..09846bf36a 100644 --- a/src/plugins/condition/criterion/TelemetryCriterion.js +++ b/src/plugins/condition/criterion/TelemetryCriterion.js @@ -73,7 +73,9 @@ export default class TelemetryCriterion extends EventEmitter { */ unsubscribe() { //unsubscribe from telemetry source - this.subscription(); + if (typeof this.subscription === 'function') { + this.subscription(); + } delete this.subscription; this.emit('criterion::Remove', this.telemetryObjectIdAsString); delete this.telemetryObjectIdAsString; From d15244043627e7b07456285ee7aa333601a3d6c4 Mon Sep 17 00:00:00 2001 From: Joshi Date: Mon, 13 Jan 2020 14:12:05 -0800 Subject: [PATCH 14/59] Fixes careless mistake - undefined object. --- src/plugins/condition/Condition.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/plugins/condition/Condition.js b/src/plugins/condition/Condition.js index d16352bef9..5a5bb3e790 100644 --- a/src/plugins/condition/Condition.js +++ b/src/plugins/condition/Condition.js @@ -175,7 +175,6 @@ export default class Condition extends EventEmitter { //TODO: implement as part of the evaluator class task. evaluate() { if (this.trigger === TRIGGER.ANY) { - criteria.evaluate(); this.result = false; } else if (this.trigger === TRIGGER.ALL) { this.result = false; From ea6f8c9a50d467b5dff8fd22dd51e9d61e51d361 Mon Sep 17 00:00:00 2001 From: Nikhil Mandlik Date: Mon, 13 Jan 2020 14:45:00 -0800 Subject: [PATCH 15/59] small fixes --- .../condition/components/Condition.vue | 33 +++-------- .../components/ConditionCollection.vue | 57 +++++++++++++------ .../condition/components/ConditionEdit.vue | 29 ++++------ 3 files changed, 59 insertions(+), 60 deletions(-) diff --git a/src/plugins/condition/components/Condition.vue b/src/plugins/condition/components/Condition.vue index f8e527cf7b..cd3bcfd2cb 100644 --- a/src/plugins/condition/components/Condition.vue +++ b/src/plugins/condition/components/Condition.vue @@ -1,34 +1,19 @@