Merge pull request #2665 from nasa/add-criteria

Add multiple criteria and persist inputs
This commit is contained in:
Shefali Joshi 2020-02-20 13:51:31 -08:00 committed by GitHub
commit 2635f085f0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 647 additions and 607 deletions

View File

@ -27,7 +27,7 @@ import { TRIGGER } from "@/plugins/condition/utils/constants";
import {computeCondition} from "@/plugins/condition/utils/evaluator";
/*
* conditionDefinition = {
* conditionConfiguration = {
* identifier: {
* key: '',
* namespace: ''
@ -35,10 +35,10 @@ import {computeCondition} from "@/plugins/condition/utils/evaluator";
* trigger: 'any'/'all',
* criteria: [
* {
* telemetry: '',
* operation: '',
* input: '',
* metaDataKey: '',
* key: 'someTelemetryObjectKey'
* metadata: ''
* }
* ]
* }
@ -48,20 +48,20 @@ export default class ConditionClass extends EventEmitter {
/**
* Manages criteria and emits the result of - true or false - based on criteria evaluated.
* @constructor
* @param conditionDefinition: {identifier: {domainObject.identifier},trigger: enum, criteria: Array of {id: uuid, operation: enum, input: Array, metaDataKey: string, key: {domainObject.identifier} }
* @param conditionConfiguration: {identifier: {domainObject.identifier},trigger: enum, criteria: Array of {id: uuid, operation: enum, input: Array, metaDataKey: string, key: {domainObject.identifier} }
* @param openmct
*/
constructor(conditionDefinition, openmct) {
constructor(conditionConfiguration, openmct) {
super();
this.openmct = openmct;
this.id = this.openmct.objects.makeKeyString(conditionDefinition.identifier);
this.id = this.openmct.objects.makeKeyString(conditionConfiguration.identifier);
this.criteria = [];
this.criteriaResults = {};
if (conditionDefinition.definition.criteria) {
this.createCriteria(conditionDefinition.definition.criteria);
if (conditionConfiguration.configuration.criteria) {
this.createCriteria(conditionConfiguration.configuration.criteria);
}
this.trigger = conditionDefinition.definition.trigger;
this.trigger = conditionConfiguration.configuration.trigger;
this.result = null;
this.openmct.objects.get(this.id).then(obj => this.observeForChanges(obj));
}
@ -71,8 +71,8 @@ export default class ConditionClass extends EventEmitter {
}
update(newDomainObject) {
this.updateTrigger(newDomainObject.definition.trigger);
this.updateCriteria(newDomainObject.definition.criteria);
this.updateTrigger(newDomainObject.configuration.trigger);
this.updateCriteria(newDomainObject.configuration.criteria);
}
updateTrigger(trigger) {
@ -82,42 +82,40 @@ export default class ConditionClass extends EventEmitter {
}
}
generateCriterion(criterionDefinition) {
generateCriterion(criterionConfiguration) {
return {
id: uuid(),
operation: criterionDefinition.operation || '',
input: criterionDefinition.input === undefined ? [] : criterionDefinition.input,
metaDataKey: criterionDefinition.metaDataKey || '',
key: criterionDefinition.key || ''
telemetry: criterionConfiguration.telemetry || '',
operation: criterionConfiguration.operation || '',
input: criterionConfiguration.input === undefined ? [] : criterionConfiguration.input,
metadata: criterionConfiguration.metadata || ''
};
}
createCriteria(criterionDefinitions) {
criterionDefinitions.forEach((criterionDefinition) => {
this.addCriterion(criterionDefinition);
createCriteria(criterionConfigurations) {
criterionConfigurations.forEach((criterionConfiguration) => {
this.addCriterion(criterionConfiguration);
});
}
updateCriteria(criterionDefinitions) {
updateCriteria(criterionConfigurations) {
this.destroyCriteria();
this.createCriteria(criterionDefinitions);
this.createCriteria(criterionConfigurations);
}
/**
* adds criterion to the condition.
*/
addCriterion(criterionDefinition) {
let criterionDefinitionWithId = this.generateCriterion(criterionDefinition || null);
let criterion = new TelemetryCriterion(criterionDefinitionWithId, this.openmct);
addCriterion(criterionConfiguration) {
let criterionConfigurationWithId = this.generateCriterion(criterionConfiguration || null);
let criterion = new TelemetryCriterion(criterionConfigurationWithId, this.openmct);
criterion.on('criterionUpdated', (obj) => this.handleCriterionUpdated(obj));
criterion.on('criterionResultUpdated', (obj) => this.handleCriterionResult(obj));
if (!this.criteria) {
this.criteria = [];
}
this.criteria.push(criterion);
//Do we need this here?
this.handleConditionUpdated();
return criterionDefinitionWithId.id;
return criterionConfigurationWithId.id;
}
findCriterion(id) {
@ -135,11 +133,11 @@ export default class ConditionClass extends EventEmitter {
return criterion;
}
updateCriterion(id, criterionDefinition) {
updateCriterion(id, criterionConfiguration) {
let found = this.findCriterion(id);
if (found) {
const newCriterionDefinition = this.generateCriterion(criterionDefinition);
let newCriterion = new TelemetryCriterion(newCriterionDefinition, this.openmct);
const newCriterionConfiguration = this.generateCriterion(criterionConfiguration);
let newCriterion = new TelemetryCriterion(newCriterionConfiguration, this.openmct);
newCriterion.on('criterionUpdated', (obj) => this.handleCriterionUpdated(obj));
newCriterion.on('criterionResultUpdated', (obj) => this.handleCriterionResult(obj));
@ -151,7 +149,6 @@ export default class ConditionClass extends EventEmitter {
if (this.criteriaResults[criterion.id] !== undefined) {
delete this.criteriaResults[criterion.id];
}
this.handleConditionUpdated();
}
}
@ -182,7 +179,6 @@ export default class ConditionClass extends EventEmitter {
let found = this.findCriterion(criterion.id);
if (found) {
this.criteria[found.index] = criterion.data;
//Most likely don't need this.
this.subscribe();
this.emitEvent('conditionUpdated', {
trigger: this.trigger,
@ -203,7 +199,9 @@ export default class ConditionClass extends EventEmitter {
subscribe() {
this.criteria.forEach((criterion) => {
criterion.subscribe();
if (criterion.isValid()) {
criterion.subscribe();
}
})
}
@ -226,7 +224,6 @@ export default class ConditionClass extends EventEmitter {
return success;
}
//TODO: implement as part of the evaluator class task.
evaluate() {
this.result = computeCondition(this.criteriaResults, this.trigger === TRIGGER.ALL);
}

View File

@ -27,7 +27,7 @@ export default class ConditionSetViewProvider {
constructor(openmct) {
this.openmct = openmct;
this.key = 'conditionSet.view';
this.cssClass = 'icon-summary-widget'; // TODO: replace with class for new icon
this.cssClass = 'icon-conditional'; // TODO: replace with class for new icon
}
canView(domainObject) {

View File

@ -64,14 +64,14 @@ describe("The condition", function () {
openmct.telemetry.getMetadata.and.returnValue(testTelemetryObject.telemetry.values);
testConditionDefinition = {
definition: {
configuration: {
trigger: TRIGGER.ANY,
criteria: [
{
operation: 'equalTo',
input: false,
metaDataKey: 'value',
key: testTelemetryObject.identifier
metadata: 'value',
telemetry: testTelemetryObject.identifier
}
]
}
@ -87,13 +87,13 @@ describe("The condition", function () {
});
it("generates criteria with an id", function () {
const testCriterion = testConditionDefinition.definition.criteria[0];
const testCriterion = testConditionDefinition.configuration.criteria[0];
let criterion = conditionObj.generateCriterion(testCriterion);
expect(criterion.id).toBeDefined();
expect(criterion.operation).toEqual(testCriterion.operation);
expect(criterion.input).toEqual(testCriterion.input);
expect(criterion.metaDataKey).toEqual(testCriterion.metaDataKey);
expect(criterion.key).toEqual(testCriterion.key);
expect(criterion.metadata).toEqual(testCriterion.metadata);
expect(criterion.telemetry).toEqual(testCriterion.telemetry);
});
it("initializes with an id", function () {
@ -104,13 +104,13 @@ describe("The condition", function () {
expect(conditionObj.criteria.length).toEqual(1);
let criterion = conditionObj.criteria[0];
expect(criterion instanceof TelemetryCriterion).toBeTrue();
expect(criterion.operator).toEqual(testConditionDefinition.definition.criteria[0].operator);
expect(criterion.input).toEqual(testConditionDefinition.definition.criteria[0].input);
expect(criterion.metaDataKey).toEqual(testConditionDefinition.definition.criteria[0].metaDataKey);
expect(criterion.operator).toEqual(testConditionDefinition.configuration.criteria[0].operator);
expect(criterion.input).toEqual(testConditionDefinition.configuration.criteria[0].input);
expect(criterion.metadata).toEqual(testConditionDefinition.configuration.criteria[0].metadata);
});
it("initializes with the trigger from the condition definition", function () {
expect(conditionObj.trigger).toEqual(testConditionDefinition.definition.trigger);
expect(conditionObj.trigger).toEqual(testConditionDefinition.configuration.trigger);
});
it("destroys all criteria for a condition", function () {

View File

@ -1,31 +1,153 @@
<template>
<!-- TODO: current condition class should be set using openmct.objects.makeKeyString(<identifier>) -->
<div v-if="condition"
id="conditionArea"
class="c-cs-ui__conditions"
:class="['widget-condition', { 'widget-condition--current': currentConditionIdentifier && (currentConditionIdentifier.key === conditionIdentifier.key) }]"
>
<div class="title-bar">
<span class="condition-name">
{{ condition.definition.name }}
</span>
<span class="condition-output">
Output: {{ condition.definition.output }}
</span>
<div v-if="isEditing">
<div v-if="domainObject"
class="c-c-editui__conditions c-c-container__container c-c__drag-wrapper"
:class="['widget-condition', { 'widget-condition--current': currentConditionIdentifier && (currentConditionIdentifier.key === conditionIdentifier.key) }]"
:data-condition-index="conditionIndex"
:draggable="!domainObject.isDefault"
@dragstart="dragStart"
@dragover.stop
>
<div class="title-bar">
<span
class="c-c__menu-hamburger"
:class="{ 'is-enabled': !domainObject.isDefault }"
></span>
<span
class="is-enabled flex-elem"
:class="['c-c__disclosure-triangle', { 'c-c__disclosure-triangle--expanded': expanded }]"
@click="expanded = !expanded"
></span>
<div class="condition-summary">
<span class="condition-name">{{ domainObject.configuration.name }}</span>
<span class="condition-description">{{ domainObject.configuration.name }}</span>
</div>
<span v-if="!domainObject.isDefault"
class="is-enabled c-c__duplicate"
@click="cloneCondition"
></span>
<span v-if="!domainObject.isDefault"
class="is-enabled c-c__trash"
@click="removeCondition"
></span>
</div>
<div v-if="expanded"
class="condition-config-edit widget-condition-content c-sw-editui__conditions-wrapper holder widget-conditions-wrapper flex-elem expanded"
>
<div id="conditionArea"
class="c-c-editui__condition widget-conditions"
>
<div class="c-c-condition">
<div class="c-c-condition__ui l-compact-form l-widget-condition has-local-controls">
<div>
<ul class="t-widget-condition-config">
<li>
<label>Condition Name</label>
<span class="controls">
<input v-model="domainObject.configuration.name"
class="t-condition-input__name"
type="text"
>
</span>
</li>
<li>
<label>Output</label>
<span class="controls">
<select v-model="selectedOutputKey"
@change="checkInputValue"
>
<option value="">- Select Output -</option>
<option v-for="option in outputOptions"
:key="option"
:value="option"
>
{{ option.charAt(0).toUpperCase() + option.slice(1) }}
</option>
</select>
<input v-if="selectedOutputKey === outputOptions[2]"
v-model="domainObject.configuration.output"
class="t-condition-name-input"
type="text"
@blur="persist"
>
</span>
</li>
</ul>
<div v-if="!domainObject.isDefault"
class="widget-condition-content expanded"
>
<ul class="t-widget-condition-config">
<li class="has-local-controls t-condition">
<label>Match when</label>
<span class="controls">
<select v-model="trigger">
<option value="all">all criteria are met</option>
<option value="any">any criteria are met</option>
</select>
</span>
</li>
</ul>
<ul v-if="telemetry.length"
class="t-widget-condition-config"
>
<Criterion v-for="(criterion, index) in domainObject.configuration.criteria"
:key="index"
:telemetry="telemetry"
:criterion="criterion"
:index="index"
:trigger="trigger"
@persist="persist"
/>
</ul>
<div class="holder c-c-button-wrapper align-left">
<span class="c-c-label-spacer"></span>
<button
class="c-c-button c-c-button--minor add-criteria-button"
@click="addCriteria"
>
<span class="c-c-button__label">Add Criteria</span>
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="condition-config">
<span class="condition-description">
{{ condition.definition.description }}
</span>
</div>
<div v-else>
<div v-if="domainObject"
id="conditionArea"
class="c-cs-ui__conditions"
:class="['widget-condition', { 'widget-condition--current': currentConditionIdentifier && (currentConditionIdentifier.key === conditionIdentifier.key) }]"
>
<div class="title-bar">
<span class="condition-name">
{{ domainObject.configuration.name }}
</span>
<span class="condition-output">
Output: {{ domainObject.configuration.output }}
</span>
</div>
<div class="condition-config">
<span class="condition-description">
{{ domainObject.configuration.description }}
</span>
</div>
</div>
</div>
</template>
<script>
import ConditionClass from "@/plugins/condition/Condition";
import Criterion from '../../condition/components/Criterion.vue';
export default {
inject: ['openmct'],
components: {
Criterion
},
props: {
conditionIdentifier: {
type: Object,
@ -34,33 +156,119 @@ export default {
currentConditionIdentifier: {
type: Object,
required: true
},
conditionIndex: {
type: Number,
required: true
},
isEditing: {
type: Boolean,
required: true
},
telemetry: {
type: Array,
required: true,
default: () => []
}
},
data() {
return {
condition: this.condition
domainObject: this.domainObject,
currentCriteria: this.currentCriteria,
expanded: true,
trigger: 'all',
selectedOutputKey: '',
stringOutputField: false,
outputOptions: ['false', 'true', 'string']
};
},
destroyed() {
this.conditionClass.off('conditionResultUpdated', this.handleConditionResult.bind(this));
if (this.conditionClass && typeof this.conditionClass.destroy === 'function') {
this.conditionClass.destroy();
computed: {
initCap: function (string) {
return string.charAt(0).toUpperCase() + string.slice(1)
}
},
destroyed() {
this.destroy();
},
mounted() {
this.openmct.objects.get(this.conditionIdentifier).then((obj => {
this.condition = obj;
this.conditionClass = new ConditionClass(this.condition, this.openmct);
this.conditionClass.on('conditionResultUpdated', this.handleConditionResult.bind(this));
this.openmct.objects.get(this.conditionIdentifier).then((domainObject => {
this.domainObject = domainObject;
this.initialize();
}));
},
methods: {
initialize() {
this.setOutput();
if (!this.domainObject.isDefault) {
this.conditionClass = new ConditionClass(this.domainObject, this.openmct);
this.conditionClass.on('conditionResultUpdated', this.handleConditionResult.bind(this));
}
},
addCriteria() {
const criteriaObject = {
telemetry: '',
operation: '',
input: '',
metadata: ''
};
this.domainObject.configuration.criteria.push(criteriaObject);
},
dragStart(e) {
this.$emit('set-move-index', Number(e.target.getAttribute('data-condition-index')));
},
destroy() {
if (this.conditionClass) {
this.conditionClass.off('conditionResultUpdated', this.handleConditionResult.bind(this));
if (typeof this.conditionClass.destroy === 'function') {
this.conditionClass.destroy();
}
delete this.conditionClass;
}
},
handleConditionResult(args) {
this.$emit('conditionResultUpdated', {
id: this.conditionIdentifier,
result: args.data.result
})
},
removeCondition(ev) {
this.$emit('removeCondition', this.conditionIdentifier);
},
cloneCondition(ev) {
this.$emit('cloneCondition', {
identifier: this.conditionIdentifier,
index: Number(ev.target.closest('.widget-condition').getAttribute('data-condition-index'))
});
},
setOutput() {
let conditionOutput = this.domainObject.configuration.output;
if (conditionOutput) {
if (conditionOutput !== 'false' && conditionOutput !== 'true') {
this.selectedOutputKey = 'string';
} else {
this.selectedOutputKey = conditionOutput;
}
}
},
persist() {
this.openmct.objects.mutate(this.domainObject, 'configuration', this.domainObject.configuration);
},
checkInputValue() {
if (this.selectedOutputKey === 'string') {
this.domainObject.configuration.output = '';
} else {
this.domainObject.configuration.output = this.selectedOutputKey;
}
},
updateCurrentCondition() {
this.$emit('updateCurrentCondition', this.currentConditionIdentifier);
},
hasTelemetry(identifier) {
// TODO: check parent domainObject.composition.hasTelemetry
return this.currentCriteria && identifier;
}
}
}
</script>

View File

@ -55,29 +55,23 @@
<li v-for="(conditionIdentifier, index) in conditionCollection"
:key="conditionIdentifier.key"
>
<div v-if="isEditing">
<div class="c-c__drag-ghost"
@drop.prevent="dropCondition"
@dragenter="dragEnter"
@dragleave="dragLeave"
@dragover.prevent
></div>
<ConditionEdit :condition-identifier="conditionIdentifier"
:telemetry="telemetryObjs"
:current-condition-identifier="currentConditionIdentifier"
:condition-index="index"
@updateCurrentCondition="updateCurrentCondition"
@removeCondition="removeCondition"
@conditionResultUpdated="handleConditionResult"
@setMoveIndex="setMoveIndex"
/>
</div>
<div v-else>
<Condition :condition-identifier="conditionIdentifier"
:current-condition-identifier="currentConditionIdentifier"
@conditionResultUpdated="handleConditionResult"
/>
</div>
<div v-if="isEditing"
class="c-c__drag-ghost"
@drop.prevent="dropCondition"
@dragenter="dragEnter"
@dragleave="dragLeave"
@dragover.prevent
></div>
<Condition :condition-identifier="conditionIdentifier"
:current-condition-identifier="currentConditionIdentifier"
:condition-index="index"
:telemetry="telemetryObjs"
:is-editing="isEditing"
@updateCurrentCondition="updateCurrentCondition"
@removeCondition="removeCondition"
@conditionResultUpdated="handleConditionResult"
@setMoveIndex="setMoveIndex"
/>
</li>
</ul>
</div>
@ -87,14 +81,13 @@
<script>
import Condition from '../../condition/components/Condition.vue';
import ConditionEdit from '../../condition/components/ConditionEdit.vue';
import uuid from 'uuid';
export default {
inject: ['openmct', 'domainObject'],
components: {
Condition,
ConditionEdit
Condition
},
props: {
isEditing: Boolean
@ -104,23 +97,23 @@ export default {
expanded: true,
parentKeyString: this.openmct.objects.makeKeyString(this.domainObject.identifier),
conditionCollection: [],
conditionResults: {},
conditions: [],
currentConditionIdentifier: this.currentConditionIdentifier || {},
telemetryObjs: this.telemetryObjs,
telemetryObjs: [],
moveIndex: Number,
isDragging: false
};
},
destroyed() {
this.composition.off('add', this.addTelemetry);
this.composition.off('add', this.addTelemetryObject);
this.composition.off('remove', this.removeTelemetryObject);
},
mounted() {
this.telemetryObjs = [];
this.conditionResults = {};
this.instantiate = this.openmct.$injector.get('instantiate');
this.composition = this.openmct.composition.get(this.domainObject);
this.composition.on('add', this.addTelemetry);
this.composition.on('remove', this.removeTelemetry);
this.composition.on('add', this.addTelemetryObject);
this.composition.on('remove', this.removeTelemetryObject);
this.composition.load();
this.conditionCollection = this.domainObject.configuration ? this.domainObject.configuration.conditionCollection : [];
if (!this.conditionCollection.length) {
@ -183,7 +176,7 @@ export default {
},
updateCurrentConditionId() {
let currentConditionIdentifier = this.conditionCollection[this.conditionCollection.length-1];
for (let i=0, ii = this.conditionCollection.length-1; i< ii; i++) {
for (let i = 0; i < this.conditionCollection.length - 1; i++) {
let conditionIdAsString = this.openmct.objects.makeKeyString(this.conditionCollection[i]);
if (this.conditionResults[conditionIdAsString]) {
//first condition to be true wins
@ -193,8 +186,18 @@ export default {
}
this.$emit('currentConditionUpdated', currentConditionIdentifier);
},
addTelemetry(telemetryDomainObject) {
this.telemetryObjs.push(telemetryDomainObject);
addTelemetryObject(domainObject) {
this.telemetryObjs.push(domainObject);
},
removeTelemetryObject(identifier) {
let index = _.findIndex(this.telemetryObjs, (obj) => {
let objId = this.openmct.objects.makeKeyString(obj.identifier);
let id = this.openmct.objects.makeKeyString(identifier);
return objId === id;
});
if (index > -1) {
this.telemetryObjs.splice(index, 1);
}
},
removeTelemetry(telemetryDomainObjectIdentifier) {
let index = _.findIndex(this.telemetryObjs, (obj) => {
@ -207,34 +210,37 @@ export default {
}
},
addCondition(event, isDefault) {
let conditionDomainObject = this.getConditionDomainObject(!!isDefault);
let conditionDomainObject = this.createConditionDomainObject(!!isDefault);
//persist the condition domain object so that we can do an openmct.objects.get on it and only persist the identifier in the conditionCollection of conditionSet
this.openmct.objects.mutate(conditionDomainObject, 'created', new Date());
this.openmct.objects.mutate(conditionDomainObject, 'created', conditionDomainObject.created);
this.conditionCollection.unshift(conditionDomainObject.identifier);
this.persist();
},
updateCurrentCondition(identifier) {
this.currentConditionIdentifier = identifier;
},
getConditionDomainObject(isDefault) {
createConditionDomainObject(isDefault) {
let conditionObj = {
isDefault: isDefault,
type: 'condition',
name: isDefault ? 'Default' : 'Unnamed Condition',
identifier: {
namespace: this.domainObject.identifier.namespace,
key: uuid()
},
definition: {
configuration: {
name: isDefault ? 'Default' : 'Unnamed Condition',
output: 'false',
trigger: 'any',
criteria: isDefault ? [] : [{
telemetry: '',
operation: '',
input: '',
metaDataKey: '',
key: ''
metadata: ''
}]
},
summary: 'summary description'
summary: 'summary description',
created: new Date()
};
let conditionDomainObjectKeyString = this.openmct.objects.makeKeyString(conditionObj.identifier);
let newDomainObject = this.instantiate(conditionObj, conditionDomainObjectKeyString);
@ -242,7 +248,6 @@ export default {
return newDomainObject.useCapability('adapter');
},
updateCondition(updatedCondition) {
//TODO: this should only happen for reordering
let index = _.findIndex(this.conditions, (condition) => condition.id === updatedCondition.id);
this.conditions[index] = updatedCondition;
},

View File

@ -1,382 +0,0 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2020, 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.
*****************************************************************************/
<template>
<!-- TODO: current condition class should be set using openmct.objects.makeKeyString(<identifier>) -->
<div v-if="condition"
class="c-c-editui__conditions c-c-container__container c-c__drag-wrapper"
:class="['widget-condition', { 'widget-condition--current': currentConditionIdentifier && (currentConditionIdentifier.key === conditionIdentifier.key) }]"
>
<div class="title-bar">
<span class="c-c__menu-hamburger"
:class="{ 'is-enabled': !condition.isDefault }"
:draggable="!condition.isDefault"
@dragstart="dragStart"
@dragover.stop
></span>
<span
class="is-enabled flex-elem"
:class="['c-c__disclosure-triangle', { 'c-c__disclosure-triangle--expanded': expanded }]"
@click="expanded = !expanded"
></span>
<div class="condition-summary">
<span class="condition-name">{{ condition.definition.name }}</span>
<!-- TODO: description should be derived from criteria -->
<span class="condition-description">{{ condition.definition.name }}</span>
</div>
<span v-if="!condition.isDefault"
class="is-enabled c-c__duplicate"
></span>
<span v-if="!condition.isDefault"
class="is-enabled c-c__trash"
@click="removeCondition"
></span>
</div>
<div v-if="expanded"
class="condition-config-edit widget-condition-content c-sw-editui__conditions-wrapper holder widget-conditions-wrapper flex-elem expanded"
>
<div id="conditionArea"
class="c-c-editui__condition widget-conditions"
>
<div class="c-c-condition">
<div class="c-c-condition__ui l-compact-form l-widget-condition has-local-controls">
<div>
<ul class="t-widget-condition-config">
<li>
<label>Condition Name</label>
<span class="controls">
<input v-model="condition.definition.name"
class="t-condition-name-input"
type="text"
>
</span>
</li>
<li>
<label>Output</label>
<span class="controls">
<select v-model="selectedOutputKey"
@change="checkInputValue"
>
<option value="">- Select Output -</option>
<option v-for="option in outputOptions"
:key="option.key"
:value="option.key"
>
{{ option.text }}
</option>
</select>
<input v-if="selectedOutputKey === outputOptions[2].key"
v-model="condition.definition.output"
class="t-condition-name-input"
type="text"
>
</span>
</li>
</ul>
<div v-if="!condition.isDefault"
class="widget-condition-content expanded"
>
<ul class="t-widget-condition-config">
<li class="has-local-controls t-condition">
<label>Match when</label>
<span class="controls">
<select>
<option value="all">all criteria are met</option>
<option value="any">any criteria are met</option>
</select>
</span>
</li>
</ul>
<ul class="t-widget-condition-config">
<li v-if="telemetry.length"
class="has-local-controls t-condition"
>
<label>when</label>
<span class="t-configuration">
<span class="controls">
<select v-model="selectedTelemetryKey"
@change="updateTelemetryMetaData"
>
<option value="">- Select Telemetry -</option>
<option v-for="telemetryOption in telemetry"
:key="telemetryOption.identifier.key"
:value="telemetryOption.identifier"
>
{{ telemetryOption.name }}
</option>
</select>
</span>
<span class="controls">
<select v-model="selectedMetaDataKey">
<option value="">- Select Field -</option>
<option v-for="option in telemetryMetadata"
:key="option.key"
:value="option.key"
>
{{ option.name }}
</option>
</select>
</span>
<span class="controls">
<select v-model="selectOperationName"
@change="setInputValueVisibility"
>
<option value="">- Select Comparison -</option>
<option v-for="option in operations"
:key="option.name"
:value="option.name"
>
{{ option.text }}
</option>
</select>
<input v-if="comparisonValueField"
class="t-condition-name-input"
type="text"
v-model="operationValue"
>
</span>
</span>
</li>
</ul>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
import { OPERATIONS } from '../utils/operations';
import ConditionClass from "@/plugins/condition/Condition";
export default {
inject: ['openmct', 'domainObject'],
props: {
conditionIdentifier: {
type: Object,
required: true
},
currentConditionIdentifier: {
type: Object,
required: true
},
telemetry: {
type: Array,
required: true,
default: () => []
},
conditionIndex: {
type: Number,
required: true
}
},
data() {
return {
condition: this.condition,
expanded: true,
telemetryObject: this.telemetryObject,
telemetryMetadata: this.telemetryMetadata,
operations: OPERATIONS,
selectedMetaDataKey: '',
selectedTelemetryKey: '',
selectOperationName: '',
selectedOutputKey: '',
stringOutputField: false,
comparisonValueField: false,
operationValue: this.operationValue,
outputOptions: [
{
key: 'false',
text: 'False'
},
{
key: 'true',
text: 'True'
},
{
key: 'string',
text: 'String'
}
]
};
},
destroyed() {
this.destroy();
},
mounted() {
this.openmct.objects.get(this.conditionIdentifier).then((obj => {
this.condition = obj;
this.initialize();
}));
},
updated() {
//validate telemetry exists, update criteria as needed
this.validate();
this.persist();
},
methods: {
dragStart(e) {
e.dataTransfer.effectAllowed = "copyMove";
e.dataTransfer.setDragImage(e.target.closest('.c-c-container__container'), 0, 0);
this.$emit('setMoveIndex', this.conditionIndex);
},
initialize() {
this.setOutput();
this.setOperation();
this.updateTelemetry();
this.conditionClass = new ConditionClass(this.condition, this.openmct);
this.conditionClass.on('conditionResultUpdated', this.handleConditionResult.bind(this));
},
destroy() {
this.conditionClass.off('conditionResultUpdated', this.handleConditionResult.bind(this));
if (this.conditionClass && typeof this.conditionClass.destroy === 'function') {
this.conditionClass.destroy();
delete this.conditionClass;
}
},
reset() {
this.selectedMetaDataKey = '';
this.selectedTelemetryKey = '';
this.selectOperationName = '';
this.operationValue = '';
},
validate() {
if (this.hasTelemetry() && !this.getTelemetryKey()) {
this.reset();
} else {
if (!this.conditionClass) {
this.initialize();
}
}
},
handleConditionResult(args) {
this.$emit('conditionResultUpdated', {
id: this.conditionIdentifier,
result: args.data.result
})
},
removeCondition(ev) {
this.$emit('removeCondition', this.conditionIdentifier);
},
setOutput() {
let conditionOutput = this.condition.definition.output;
if (conditionOutput !== 'false' && conditionOutput !== 'true') {
this.selectedOutputKey = this.outputOptions[2].key;
} else {
if (conditionOutput === 'true') {
this.selectedOutputKey = this.outputOptions[1].key;
} else {
this.selectedOutputKey = this.outputOptions[0].key;
}
}
},
setOperation() {
if (this.condition.definition.criteria.length && this.condition.definition.criteria[0].operation) {
for (let i=0, ii=this.operations.length; i < ii; i++) {
if (this.condition.definition.criteria[0].operation === this.operations[i].name) {
this.selectOperationName = this.operations[i].name;
this.comparisonValueField = this.operations[i].inputCount > 0;
if (this.comparisonValueField) {
this.operationValue = this.condition.definition.criteria[0].input[0];
}
}
}
}
},
updateTelemetry() {
if (this.hasTelemetry()) {
this.openmct.objects.get(this.condition.definition.criteria[0].key).then((obj) => {
this.telemetryObject = obj;
this.telemetryMetadata = this.openmct.telemetry.getMetadata(this.telemetryObject).values();
this.selectedMetaDataKey = this.getTelemetryMetadataKey();
this.selectedTelemetryKey = this.getTelemetryKey();
});
} else {
this.telemetryObject = null;
}
},
getTelemetryMetadataKey() {
let index = -1;
if (this.condition.definition.criteria[0].metaDataKey) {
index = _.findIndex(this.telemetryMetadata, (metadata) => {
return metadata.key === this.condition.definition.criteria[0].metaDataKey;
});
}
return this.telemetryMetadata.length && index > -1 ? this.telemetryMetadata[index].key : '';
},
getTelemetryKey() {
let index = -1;
if (this.condition.definition.criteria[0].key) {
index = _.findIndex(this.telemetry, (obj) => {
let key = this.openmct.objects.makeKeyString(obj.identifier);
let conditionKey = this.openmct.objects.makeKeyString(this.condition.definition.criteria[0].key);
return key === conditionKey;
});
}
return this.telemetry.length && index > -1 ? this.telemetry[index].identifier : '';
},
hasTelemetry() {
return this.condition.definition.criteria.length && this.condition.definition.criteria[0].key;
},
updateConditionCriteria() {
if (this.condition.definition.criteria.length) {
let criterion = this.condition.definition.criteria[0];
criterion.key = this.selectedTelemetryKey;
criterion.metaDataKey = this.selectedMetaDataKey;
criterion.operation = this.selectOperationName;
criterion.input = [this.operationValue];
}
},
persist() {
this.updateConditionCriteria();
this.openmct.objects.mutate(this.condition, 'definition', this.condition.definition);
},
checkInputValue() {
if (this.selectedOutputKey === this.outputOptions[2].key) {
this.condition.definition.output = '';
} else {
this.condition.definition.output = this.selectedOutputKey;
}
},
setInputValueVisibility(ev) {
for (let i=0, ii=this.operations.length; i < ii; i++) {
if (this.selectOperationName === this.operations[i].name) {
this.comparisonValueField = this.operations[i].inputCount > 0;
break;
}
}
//find the criterion being updated and set the operation property
},
updateTelemetryMetaData() {
this.selectedMetaDataKey = '';
this.updateConditionCriteria();
this.updateTelemetry();
},
updateCurrentCondition() {
this.$emit('updateCurrentCondition', this.conditionIdentifier);
}
}
}
</script>

View File

@ -0,0 +1,121 @@
<template>
<li class="has-local-controls t-condition">
<label>{{ setRowLabel }}</label>
<span class="t-configuration">
<span class="controls">
<select v-model="criterion.telemetry"
@change="updateMetadataOptions"
>
<option value="">- Select Telemetry -</option>
<option v-for="telemetryOption in telemetry"
:key="telemetryOption.identifier.key"
:value="telemetryOption.identifier"
>
{{ telemetryOption.name }}
</option>
</select>
</span>
<span class="controls">
<select v-model="criterion.metadata">
<option value="">- Select Field -</option>
<option v-for="option in telemetryMetadata"
:key="option.key"
:value="option.key"
>
{{ option.name }}
</option>
</select>
</span>
<span class="controls">
<select v-model="criterion.operation"
@change="updateOperationInputVisibility"
>
<option value="">- Select Comparison -</option>
<option v-for="option in operations"
:key="option.name"
:value="option.name"
>
{{ option.text }}
</option>
</select>
<input v-if="isInputOperation"
v-model="criterion.input"
class="t-condition-name-input"
type="text"
@blur="persist"
>
</span>
</span>
</li>
</template>
<script>
import { OPERATIONS } from '../utils/operations';
export default {
inject: ['openmct'],
props: {
criterion: {
type: Object,
required: true
},
telemetry: {
type: Array,
required: true,
default: () => []
},
index: {
type: Number,
required: true
},
trigger: {
type: String,
required: true
}
},
data() {
return {
telemetryMetadata: {},
operations: OPERATIONS,
isInputOperation: false,
rowLabel: ''
}
},
computed: {
setRowLabel: function () {
let operator = this.trigger === 'all' ? 'and ': 'or ';
return (this.index !== 0 ? operator : '') + 'when';
}
},
mounted() {
this.updateMetadataOptions();
this.updateOperationInputVisibility();
},
methods: {
updateMetadataOptions() {
if (this.criterion.telemetry) {
this.openmct.objects.get(this.criterion.telemetry).then((telemetryObject) => {
this.telemetryMetadata = this.openmct.telemetry.getMetadata(telemetryObject).values();
});
}
this.persist();
},
updateOperationInputVisibility() {
for (let i=0; i < this.operations.length; i++) {
if (this.criterion.operation === this.operations[i].name) {
this.isInputOperation = this.operations[i].inputCount > 0;
if (!this.isInputOperation) {this.criterion.input = ''}
}
}
this.persist();
},
updateMetadataSelection() {
this.updateOperationInputVisibility();
},
persist() {
this.$emit('persist', this.criterion);
}
}
};
</script>

View File

@ -36,7 +36,7 @@
class="c-cs__ui_content"
>
<div>
<span class="current-output">{{ condition.definition.output }}</span>
<span class="current-output">{{ condition.configuration.output }}</span>
</div>
</div>
</section>

View File

@ -36,10 +36,13 @@
<div v-if="expanded"
class="c-cs__ui_content"
>
<label class="checkbox custom">
<input type="checkbox"
class="t-test-data-checkbox"
<label class="c-toggle-switch">
<input
type="checkbox"
:checked="isApplied"
@change="applyTestData"
>
<span class="c-toggle-switch__slider"></span>
<span>Apply Test Data</span>
</label>
<div class="t-test-data-config">
@ -80,11 +83,14 @@ export default {
},
data() {
return {
expanded: true
expanded: true,
isApplied: true
};
},
methods: {
applyTestData(ev) {
this.$emit('change', ev.target.checked);
}
}
}
</script>

View File

@ -27,6 +27,10 @@ section {
padding: 0.4em;
}
.c-cs-ui__label {
color: #333;
}
.c-cs__ui_content .help {
font-style: italic;
padding: 0.4em 0;
@ -80,7 +84,7 @@ section {
.c-cs-button[class*='is-active'],
.c-cs-button--menu[class*="--major"],
.c-cs-button--menu[class*='is-active'] {
border: solid 1.5px #0B427C;
border: solid 1px #0B427C;
background-color: #4778A3;
padding: 0.2em 0.6em;
margin: 0.4em;
@ -140,3 +144,4 @@ section {
}
}

View File

@ -13,6 +13,31 @@
margin: 0;
}
.c-c-button-wrapper {
border-top: solid 1px #ccc;
padding: 2px;
}
.c-c-label-spacer {
display: inline-block;
width: 90px;
}
.c-c-button[class*="--minor"],
.c-c-button[class*='is-active'],
.c-c-button--menu[class*="--minor"],
.c-c-button--menu[class*='is-active'] {
border: solid 1px #666;
background-color: #fff;
padding: 0.1em 0.4em;
margin: 0.4em;
font-weight: normal;
color: #666;
border-radius: 6px;
}
.title-bar {
display: flex;
align-items: center;
@ -67,7 +92,7 @@
margin: 0 3px;
}
.widget-condition-content.expanded ul {
.widget-condition-content.expanded ul li {
border-top: solid 1px #ccc;
padding: 2px;
}
@ -171,5 +196,4 @@
background-color: lightblue;
border-radius: 2px;
}
}
}

View File

@ -29,7 +29,7 @@ export default class TelemetryCriterion extends EventEmitter {
* Subscribes/Unsubscribes to telemetry and emits the result
* of operations performed on the telemetry data returned and a given input value.
* @constructor
* @param telemetryDomainObjectDefinition {id: uuid, operation: enum, input: Array, metaDataKey: string, key: {domainObject.identifier} }
* @param telemetryDomainObjectDefinition {id: uuid, operation: enum, input: Array, metadata: string, key: {domainObject.identifier} }
* @param openmct
*/
constructor(telemetryDomainObjectDefinition, openmct) {
@ -39,19 +39,18 @@ export default class TelemetryCriterion extends EventEmitter {
this.objectAPI = this.openmct.objects;
this.telemetryAPI = this.openmct.telemetry;
this.id = telemetryDomainObjectDefinition.id;
this.telemetry = telemetryDomainObjectDefinition.telemetry;
this.operation = telemetryDomainObjectDefinition.operation;
this.input = telemetryDomainObjectDefinition.input;
this.metaDataKey = telemetryDomainObjectDefinition.metaDataKey;
this.metadata = telemetryDomainObjectDefinition.metadata;
this.subscription = null;
this.telemetryMetadata = null;
this.telemetryObjectIdAsString = null;
this.objectAPI.get(this.objectAPI.makeKeyString(telemetryDomainObjectDefinition.key)).then((obj) => this.initialize(obj));
this.objectAPI.get(this.objectAPI.makeKeyString(this.telemetry)).then((obj) => this.initialize(obj));
}
initialize(obj) {
this.telemetryObject = obj;
this.telemetryObjectIdAsString = this.objectAPI.makeKeyString(this.telemetryObject.identifier);
this.telemetryMetadata = this.telemetryAPI.getMetadata(this.telemetryObject.identifier);
this.emitEvent('criterionUpdated', this);
}
@ -76,9 +75,11 @@ export default class TelemetryCriterion extends EventEmitter {
let comparator = this.findOperation(this.operation);
let params = [];
let result = false;
params.push(data[this.metaDataKey]);
params.push(data[this.metadata]);
if (this.input instanceof Array && this.input.length) {
params.push(this.input[0]);
} else if (this.input) {
params.push(this.input);
}
if (typeof comparator === 'function') {
result = comparator(params);
@ -93,6 +94,10 @@ export default class TelemetryCriterion extends EventEmitter {
});
}
isValid() {
return this.telemetryObject && this.metadata && this.operation;
}
/**
* Subscribes to the telemetry object and returns an unsubscribe function
*/
@ -119,6 +124,5 @@ export default class TelemetryCriterion extends EventEmitter {
this.emitEvent('criterionRemoved');
delete this.telemetryObjectIdAsString;
delete this.telemetryObject;
delete this.telemetryMetadata;
}
}

View File

@ -64,7 +64,7 @@ describe("The telemetry criterion", function () {
testCriterionDefinition = {
id: 'test-criterion-id',
key: openmct.objects.makeKeyString(testTelemetryObject.identifier)
telemetry: openmct.objects.makeKeyString(testTelemetryObject.identifier)
};
mockListener = jasmine.createSpy('listener');
@ -85,7 +85,6 @@ describe("The telemetry criterion", function () {
it("initializes with a telemetry objectId as string", function () {
telemetryCriterion.initialize(testTelemetryObject);
expect(telemetryCriterion.telemetryObjectIdAsString).toEqual(testTelemetryObject.identifier.key);
expect(telemetryCriterion.telemetryMetadata.length).toEqual(2);
expect(mockListener2).toHaveBeenCalled();
});
@ -112,7 +111,6 @@ describe("The telemetry criterion", function () {
expect(telemetryCriterion.subscription).toBeUndefined();
expect(telemetryCriterion.telemetryObjectIdAsString).toBeUndefined();
expect(telemetryCriterion.telemetryObject).toBeUndefined();
expect(telemetryCriterion.telemetryMetadata).toBeUndefined();
});
});

View File

@ -40,7 +40,7 @@ export default function ConditionPlugin() {
key: 'conditionSet',
description: 'A set of one or more conditions based on user-specified criteria.',
creatable: true,
cssClass: 'icon-summary-widget', // TODO: replace with class for new icon
cssClass: 'icon-conditional', // TODO: replace with class for new icon
initialize: function (domainObject) {
domainObject.configuration = {
conditionCollection: []

3
src/styles/_constants.scss Normal file → Executable file
View File

@ -147,6 +147,7 @@ $glyph-icon-filter: '\e926';
$glyph-icon-filter-outline: '\e927';
$glyph-icon-suitcase: '\e928';
$glyph-icon-cursor-lock: '\e929';
$glyph-icon-flag: '\e92a';
$glyph-icon-arrows-right-left: '\ea00';
$glyph-icon-arrows-up-down: '\ea01';
$glyph-icon-bullet: '\ea02';
@ -236,6 +237,7 @@ $glyph-icon-gauge: '\eb23';
$glyph-icon-spectra: '\eb24';
$glyph-icon-spectra-telemetry: '\eb25';
$glyph-icon-command: '\eb26';
$glyph-icon-conditional: '\eb27';
/************************** GLYPHS AS DATA URI */
// Only objects have been converted, for use in Create menu and folder views
@ -285,3 +287,4 @@ $bg-icon-gauge: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w
$bg-icon-spectra: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M384 352H128l51.2-89.6L0 288v127c0 53.3 43.7 97 97 97h318c53.4 0 97-43.7 97-97v-31l-162.9-93.1zM415 0H97C43.7 0 0 43.6 0 97v159l200-30.1 56-97.9 54.9 96H512V97a97.2 97.2 0 00-97-97zM512 320v-32l-192-32 192 64z'/%3e%3c/svg%3e");
$bg-icon-spectra-telemetry: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M256 128l54.9 96H510C494.3 97.7 386.5 0 256 0 114.6 0 0 114.6 0 256l200-30.1zM384 352H128l51.2-89.6L2 287.7C17.6 414.1 125.4 512 256 512c100.8 0 188-58.3 229.8-143l-136.7-78.1zM320 256l192 64v-32l-192-32z'/%3e%3c/svg%3e");
$bg-icon-command: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath fill='%23000000' d='M185.1 229.7a96.5 96.5 0 0015.8 11.7A68.5 68.5 0 01192 208c0-19.8 8.9-38.8 25.1-53.7 18.5-17 43.7-26.3 70.9-26.3 20.1 0 39.1 5.1 55.1 14.6a81.3 81.3 0 00-16.2-20.3C308.4 105.3 283.2 96 256 96s-52.4 9.3-70.9 26.3C168.9 137.2 160 156.2 160 176s8.9 38.8 25.1 53.7z'/%3e%3cpath d='M442.7 134.8C422.4 57.5 346.5 0 256 0S89.6 57.5 69.3 134.8C26.3 174.8 0 228.7 0 288c0 123.7 114.6 224 256 224s256-100.3 256-224c0-59.3-26.3-113.2-69.3-153.2zM256 64c70.6 0 128 50.2 128 112s-57.4 112-128 112-128-50.2-128-112S185.4 64 256 64zm0 352c-87.7 0-159.2-63.9-160-142.7 34.4 47.4 93.2 78.7 160 78.7s125.6-31.3 160-78.7c-.8 78.8-72.3 142.7-160 142.7z'/%3e%3c/svg%3e");
$bg-icon-conditional: url("data:image/svg+xml;charset=UTF-8,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 512 512'%3e%3cpath d='M256 0C114.62 0 0 114.62 0 256s114.62 256 256 256 256-114.62 256-256S397.38 0 256 0zm0 384L64 256l192-128 192 128z' fill='%23000000'/%3e%3c/svg%3e");

3
src/styles/_glyphs.scss Normal file → Executable file
View File

@ -81,6 +81,7 @@
.icon-filter-outline { @include glyphBefore($glyph-icon-filter-outline); }
.icon-suitcase { @include glyphBefore($glyph-icon-suitcase); }
.icon-cursor-lock { @include glyphBefore($glyph-icon-cursor-lock); }
.icon-flag { @include glyphBefore($glyph-icon-flag); }
.icon-arrows-right-left { @include glyphBefore($glyph-icon-arrows-right-left); }
.icon-arrows-up-down { @include glyphBefore($glyph-icon-arrows-up-down); }
.icon-bullet { @include glyphBefore($glyph-icon-bullet); }
@ -170,6 +171,7 @@
.icon-spectra { @include glyphBefore($glyph-icon-spectra); }
.icon-spectra-telemetry { @include glyphBefore($glyph-icon-spectra-telemetry); }
.icon-command { @include glyphBefore($glyph-icon-command); }
.icon-conditional { @include glyphBefore($glyph-icon-conditional); }
/************************** 12 PX CLASSES */
// TODO: sync with 16px redo as of 10/25/18
@ -227,3 +229,4 @@
.bg-icon-spectra { @include glyphBg($bg-icon-spectra); }
.bg-icon-spectra-telemetry { @include glyphBg($bg-icon-spectra-telemetry); }
.bg-icon-command { @include glyphBg($bg-icon-command); }
.bg-icon-conditional { @include glyphBg($bg-icon-conditional); }

0
src/styles/fonts/Open MCT Symbols 12px.json Normal file → Executable file
View File

226
src/styles/fonts/Open MCT Symbols 16px.json Normal file → Executable file
View File

@ -2,7 +2,7 @@
"metadata": {
"name": "Open MCT Symbols 16px",
"lastOpened": 0,
"created": 1574106570211
"created": 1581619121103
},
"iconSets": [
{
@ -343,13 +343,21 @@
"code": 59689,
"tempChar": ""
},
{
"order": 176,
"id": 150,
"name": "icon-flag",
"prevSize": 24,
"code": 59690,
"tempChar": ""
},
{
"order": 27,
"id": 105,
"name": "icon-arrows-right-left",
"prevSize": 24,
"code": 59904,
"tempChar": ""
"tempChar": ""
},
{
"order": 26,
@ -357,7 +365,7 @@
"name": "icon-arrows-up-down",
"prevSize": 24,
"code": 59905,
"tempChar": ""
"tempChar": ""
},
{
"order": 68,
@ -365,7 +373,7 @@
"name": "icon-bullet",
"prevSize": 24,
"code": 59906,
"tempChar": ""
"tempChar": ""
},
{
"order": 150,
@ -373,7 +381,7 @@
"prevSize": 24,
"code": 59907,
"name": "icon-calendar",
"tempChar": ""
"tempChar": ""
},
{
"order": 45,
@ -381,7 +389,7 @@
"name": "icon-chain-links",
"prevSize": 24,
"code": 59908,
"tempChar": ""
"tempChar": ""
},
{
"order": 73,
@ -389,7 +397,7 @@
"name": "icon-download",
"prevSize": 24,
"code": 59909,
"tempChar": ""
"tempChar": ""
},
{
"order": 39,
@ -397,7 +405,7 @@
"name": "icon-duplicate",
"prevSize": 24,
"code": 59910,
"tempChar": ""
"tempChar": ""
},
{
"order": 50,
@ -405,7 +413,7 @@
"name": "icon-folder-new",
"prevSize": 24,
"code": 59911,
"tempChar": ""
"tempChar": ""
},
{
"order": 138,
@ -413,7 +421,7 @@
"name": "icon-fullscreen-collapse",
"prevSize": 24,
"code": 59912,
"tempChar": ""
"tempChar": ""
},
{
"order": 139,
@ -421,7 +429,7 @@
"name": "icon-fullscreen-expand",
"prevSize": 24,
"code": 59913,
"tempChar": ""
"tempChar": ""
},
{
"order": 122,
@ -429,7 +437,7 @@
"name": "icon-layers",
"prevSize": 24,
"code": 59914,
"tempChar": ""
"tempChar": ""
},
{
"order": 151,
@ -437,7 +445,7 @@
"name": "icon-line-horz",
"prevSize": 24,
"code": 59915,
"tempChar": ""
"tempChar": ""
},
{
"order": 100,
@ -445,7 +453,7 @@
"name": "icon-magnify",
"prevSize": 24,
"code": 59916,
"tempChar": ""
"tempChar": ""
},
{
"order": 99,
@ -453,7 +461,7 @@
"name": "icon-magnify-in",
"prevSize": 24,
"code": 59917,
"tempChar": ""
"tempChar": ""
},
{
"order": 101,
@ -461,7 +469,7 @@
"name": "icon-magnify-out-v2",
"prevSize": 24,
"code": 59918,
"tempChar": ""
"tempChar": ""
},
{
"order": 103,
@ -469,7 +477,7 @@
"name": "icon-menu",
"prevSize": 24,
"code": 59919,
"tempChar": ""
"tempChar": ""
},
{
"order": 124,
@ -477,7 +485,7 @@
"name": "icon-move",
"prevSize": 24,
"code": 59920,
"tempChar": ""
"tempChar": ""
},
{
"order": 7,
@ -485,7 +493,7 @@
"name": "icon-new-window",
"prevSize": 24,
"code": 59921,
"tempChar": ""
"tempChar": ""
},
{
"order": 63,
@ -493,7 +501,7 @@
"name": "icon-paint-bucket-v2",
"prevSize": 24,
"code": 59922,
"tempChar": ""
"tempChar": ""
},
{
"order": 15,
@ -501,7 +509,7 @@
"name": "icon-pencil",
"prevSize": 24,
"code": 59923,
"tempChar": ""
"tempChar": ""
},
{
"order": 54,
@ -509,7 +517,7 @@
"name": "icon-pencil-edit-in-place",
"prevSize": 24,
"code": 59924,
"tempChar": ""
"tempChar": ""
},
{
"order": 40,
@ -517,7 +525,7 @@
"name": "icon-play",
"prevSize": 24,
"code": 59925,
"tempChar": ""
"tempChar": ""
},
{
"order": 125,
@ -525,7 +533,7 @@
"name": "icon-pause",
"prevSize": 24,
"code": 59926,
"tempChar": ""
"tempChar": ""
},
{
"order": 119,
@ -533,7 +541,7 @@
"name": "icon-plot-resource",
"prevSize": 24,
"code": 59927,
"tempChar": ""
"tempChar": ""
},
{
"order": 48,
@ -541,7 +549,7 @@
"name": "icon-pointer-left",
"prevSize": 24,
"code": 59928,
"tempChar": ""
"tempChar": ""
},
{
"order": 47,
@ -549,7 +557,7 @@
"name": "icon-pointer-right",
"prevSize": 24,
"code": 59929,
"tempChar": ""
"tempChar": ""
},
{
"order": 85,
@ -557,7 +565,7 @@
"name": "icon-refresh",
"prevSize": 24,
"code": 59930,
"tempChar": ""
"tempChar": ""
},
{
"order": 55,
@ -565,7 +573,7 @@
"name": "icon-save",
"prevSize": 24,
"code": 59931,
"tempChar": ""
"tempChar": ""
},
{
"order": 56,
@ -573,7 +581,7 @@
"name": "icon-save-as",
"prevSize": 24,
"code": 59932,
"tempChar": ""
"tempChar": ""
},
{
"order": 58,
@ -581,7 +589,7 @@
"name": "icon-sine",
"prevSize": 24,
"code": 59933,
"tempChar": ""
"tempChar": ""
},
{
"order": 113,
@ -589,7 +597,7 @@
"name": "icon-font",
"prevSize": 24,
"code": 59934,
"tempChar": ""
"tempChar": ""
},
{
"order": 41,
@ -597,7 +605,7 @@
"name": "icon-thumbs-strip",
"prevSize": 24,
"code": 59935,
"tempChar": ""
"tempChar": ""
},
{
"order": 146,
@ -605,7 +613,7 @@
"name": "icon-two-parts-both",
"prevSize": 24,
"code": 59936,
"tempChar": ""
"tempChar": ""
},
{
"order": 145,
@ -613,7 +621,7 @@
"name": "icon-two-parts-one-only",
"prevSize": 24,
"code": 59937,
"tempChar": ""
"tempChar": ""
},
{
"order": 82,
@ -621,7 +629,7 @@
"name": "icon-resync",
"prevSize": 24,
"code": 59938,
"tempChar": ""
"tempChar": ""
},
{
"order": 86,
@ -629,7 +637,7 @@
"name": "icon-reset",
"prevSize": 24,
"code": 59939,
"tempChar": ""
"tempChar": ""
},
{
"order": 61,
@ -637,7 +645,7 @@
"name": "icon-x-in-circle",
"prevSize": 24,
"code": 59940,
"tempChar": ""
"tempChar": ""
},
{
"order": 84,
@ -645,7 +653,7 @@
"name": "icon-brightness",
"prevSize": 24,
"code": 59941,
"tempChar": ""
"tempChar": ""
},
{
"order": 83,
@ -653,7 +661,7 @@
"name": "icon-contrast",
"prevSize": 24,
"code": 59942,
"tempChar": ""
"tempChar": ""
},
{
"order": 87,
@ -661,7 +669,7 @@
"name": "icon-expand",
"prevSize": 24,
"code": 59943,
"tempChar": ""
"tempChar": ""
},
{
"order": 89,
@ -669,7 +677,7 @@
"name": "icon-list-view",
"prevSize": 24,
"code": 59944,
"tempChar": ""
"tempChar": ""
},
{
"order": 133,
@ -677,7 +685,7 @@
"name": "icon-grid-snap-to",
"prevSize": 24,
"code": 59945,
"tempChar": ""
"tempChar": ""
},
{
"order": 132,
@ -685,7 +693,7 @@
"name": "icon-grid-snap-no",
"prevSize": 24,
"code": 59946,
"tempChar": ""
"tempChar": ""
},
{
"order": 94,
@ -693,7 +701,7 @@
"name": "icon-frame-show",
"prevSize": 24,
"code": 59947,
"tempChar": ""
"tempChar": ""
},
{
"order": 95,
@ -701,7 +709,7 @@
"name": "icon-frame-hide",
"prevSize": 24,
"code": 59948,
"tempChar": ""
"tempChar": ""
},
{
"order": 97,
@ -709,7 +717,7 @@
"name": "icon-import",
"prevSize": 24,
"code": 59949,
"tempChar": ""
"tempChar": ""
},
{
"order": 96,
@ -717,7 +725,7 @@
"name": "icon-export",
"prevSize": 24,
"code": 59950,
"tempChar": ""
"tempChar": ""
},
{
"order": 114,
@ -725,7 +733,7 @@
"name": "icon-font-size",
"prevSize": 24,
"code": 59951,
"tempChar": ""
"tempChar": ""
},
{
"order": 163,
@ -733,7 +741,7 @@
"name": "icon-clear-data",
"prevSize": 24,
"code": 59952,
"tempChar": ""
"tempChar": ""
},
{
"order": 173,
@ -741,7 +749,7 @@
"name": "icon-history",
"prevSize": 24,
"code": 59953,
"tempChar": ""
"tempChar": ""
},
{
"order": 144,
@ -749,7 +757,7 @@
"name": "icon-activity",
"prevSize": 24,
"code": 60160,
"tempChar": ""
"tempChar": ""
},
{
"order": 104,
@ -757,7 +765,7 @@
"name": "icon-activity-mode",
"prevSize": 24,
"code": 60161,
"tempChar": ""
"tempChar": ""
},
{
"order": 137,
@ -765,7 +773,7 @@
"name": "icon-autoflow-tabular",
"prevSize": 24,
"code": 60162,
"tempChar": ""
"tempChar": ""
},
{
"order": 115,
@ -773,7 +781,7 @@
"name": "icon-clock",
"prevSize": 24,
"code": 60163,
"tempChar": ""
"tempChar": ""
},
{
"order": 2,
@ -781,7 +789,7 @@
"name": "icon-database",
"prevSize": 24,
"code": 60164,
"tempChar": ""
"tempChar": ""
},
{
"order": 3,
@ -789,7 +797,7 @@
"name": "icon-database-query",
"prevSize": 24,
"code": 60165,
"tempChar": ""
"tempChar": ""
},
{
"order": 67,
@ -797,7 +805,7 @@
"name": "icon-dataset",
"prevSize": 24,
"code": 60166,
"tempChar": ""
"tempChar": ""
},
{
"order": 59,
@ -805,7 +813,7 @@
"name": "icon-datatable",
"prevSize": 24,
"code": 60167,
"tempChar": ""
"tempChar": ""
},
{
"order": 136,
@ -813,7 +821,7 @@
"name": "icon-dictionary",
"prevSize": 24,
"code": 60168,
"tempChar": ""
"tempChar": ""
},
{
"order": 51,
@ -821,7 +829,7 @@
"name": "icon-folder",
"prevSize": 24,
"code": 60169,
"tempChar": ""
"tempChar": ""
},
{
"order": 147,
@ -829,7 +837,7 @@
"name": "icon-image",
"prevSize": 24,
"code": 60170,
"tempChar": ""
"tempChar": ""
},
{
"order": 4,
@ -837,7 +845,7 @@
"name": "icon-layout",
"prevSize": 24,
"code": 60171,
"tempChar": ""
"tempChar": ""
},
{
"order": 24,
@ -845,7 +853,7 @@
"name": "icon-object",
"prevSize": 24,
"code": 60172,
"tempChar": ""
"tempChar": ""
},
{
"order": 52,
@ -853,7 +861,7 @@
"name": "icon-object-unknown",
"prevSize": 24,
"code": 60173,
"tempChar": ""
"tempChar": ""
},
{
"order": 105,
@ -861,7 +869,7 @@
"name": "icon-packet",
"prevSize": 24,
"code": 60174,
"tempChar": ""
"tempChar": ""
},
{
"order": 126,
@ -869,7 +877,7 @@
"name": "icon-page",
"prevSize": 24,
"code": 60175,
"tempChar": ""
"tempChar": ""
},
{
"order": 130,
@ -877,7 +885,7 @@
"name": "icon-plot-overlay",
"prevSize": 24,
"code": 60176,
"tempChar": ""
"tempChar": ""
},
{
"order": 80,
@ -885,7 +893,7 @@
"name": "icon-plot-stacked",
"prevSize": 24,
"code": 60177,
"tempChar": ""
"tempChar": ""
},
{
"order": 134,
@ -893,7 +901,7 @@
"name": "icon-session",
"prevSize": 24,
"code": 60178,
"tempChar": ""
"tempChar": ""
},
{
"order": 109,
@ -901,7 +909,7 @@
"name": "icon-tabular",
"prevSize": 24,
"code": 60179,
"tempChar": ""
"tempChar": ""
},
{
"order": 107,
@ -909,7 +917,7 @@
"name": "icon-tabular-lad",
"prevSize": 24,
"code": 60180,
"tempChar": ""
"tempChar": ""
},
{
"order": 106,
@ -917,7 +925,7 @@
"name": "icon-tabular-lad-set",
"prevSize": 24,
"code": 60181,
"tempChar": ""
"tempChar": ""
},
{
"order": 70,
@ -925,7 +933,7 @@
"name": "icon-tabular-realtime",
"prevSize": 24,
"code": 60182,
"tempChar": ""
"tempChar": ""
},
{
"order": 60,
@ -933,7 +941,7 @@
"name": "icon-tabular-scrolling",
"prevSize": 24,
"code": 60183,
"tempChar": ""
"tempChar": ""
},
{
"order": 131,
@ -941,7 +949,7 @@
"name": "icon-telemetry",
"prevSize": 24,
"code": 60184,
"tempChar": ""
"tempChar": ""
},
{
"order": 108,
@ -949,7 +957,7 @@
"name": "icon-timeline",
"prevSize": 24,
"code": 60185,
"tempChar": ""
"tempChar": ""
},
{
"order": 81,
@ -957,7 +965,7 @@
"name": "icon-timer",
"prevSize": 24,
"code": 60186,
"tempChar": ""
"tempChar": ""
},
{
"order": 69,
@ -965,7 +973,7 @@
"name": "icon-topic",
"prevSize": 24,
"code": 60187,
"tempChar": ""
"tempChar": ""
},
{
"order": 79,
@ -973,7 +981,7 @@
"name": "icon-box-with-dashed-lines-v2",
"prevSize": 24,
"code": 60188,
"tempChar": ""
"tempChar": ""
},
{
"order": 90,
@ -981,7 +989,7 @@
"name": "icon-summary-widget",
"prevSize": 24,
"code": 60189,
"tempChar": ""
"tempChar": ""
},
{
"order": 92,
@ -989,7 +997,7 @@
"name": "icon-notebook",
"prevSize": 24,
"code": 60190,
"tempChar": ""
"tempChar": ""
},
{
"order": 168,
@ -997,7 +1005,7 @@
"name": "icon-tabs-view",
"prevSize": 24,
"code": 60191,
"tempChar": ""
"tempChar": ""
},
{
"order": 117,
@ -1005,7 +1013,7 @@
"name": "icon-flexible-layout",
"prevSize": 24,
"code": 60192,
"tempChar": ""
"tempChar": ""
},
{
"order": 166,
@ -1013,7 +1021,7 @@
"name": "icon-generator-sine",
"prevSize": 24,
"code": 60193,
"tempChar": ""
"tempChar": ""
},
{
"order": 167,
@ -1021,7 +1029,7 @@
"name": "icon-generator-event",
"prevSize": 24,
"code": 60194,
"tempChar": ""
"tempChar": ""
},
{
"order": 165,
@ -1029,7 +1037,7 @@
"name": "icon-gauge-v2",
"prevSize": 24,
"code": 60195,
"tempChar": ""
"tempChar": ""
},
{
"order": 170,
@ -1037,7 +1045,7 @@
"name": "icon-spectra",
"prevSize": 24,
"code": 60196,
"tempChar": ""
"tempChar": ""
},
{
"order": 171,
@ -1045,7 +1053,7 @@
"name": "icon-telemetry-spectra",
"prevSize": 24,
"code": 60197,
"tempChar": ""
"tempChar": ""
},
{
"order": 172,
@ -1053,7 +1061,15 @@
"name": "icon-pushbutton",
"prevSize": 24,
"code": 60198,
"tempChar": ""
"tempChar": ""
},
{
"order": 174,
"id": 151,
"name": "icon-conditional",
"prevSize": 24,
"code": 60199,
"tempChar": ""
}
],
"id": 0,
@ -1613,6 +1629,21 @@
"icon-cursor-locked"
]
},
{
"id": 150,
"paths": [
"M192 640h832l-192-320 192-320h-896c-70.606 0.215-127.785 57.394-128 127.979l-0 0.021v896h192z"
],
"attrs": [
{}
],
"grid": 16,
"tags": [
"icon-flag"
],
"isMulticolor": false,
"isMulticolor2": false
},
{
"id": 105,
"paths": [
@ -2771,6 +2802,21 @@
"tags": [
"icon-pushbutton"
]
},
{
"id": 151,
"paths": [
"M512 0c-282.76 0-512 229.24-512 512s229.24 512 512 512 512-229.24 512-512-229.24-512-512-512zM512 768l-384-256 384-256 384 256z"
],
"attrs": [
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"grid": 16,
"tags": [
"icon-conditional"
]
}
],
"invisible": false,

0
src/styles/fonts/Open-MCT-Symbols-12px.ttf Normal file → Executable file
View File

0
src/styles/fonts/Open-MCT-Symbols-12px.woff Normal file → Executable file
View File

View File

@ -49,6 +49,7 @@
<glyph unicode="&#xe927;" glyph-name="icon-filter-outline" d="M896 832h-768c-70.601-0.227-127.773-57.399-128-127.978v-768.022c0.227-70.601 57.399-127.773 127.978-128h768.022c70.601 0.227 127.773 57.399 128 127.978v768.022c-0.227 70.601-57.399 127.773-127.978 128h-0.022zM896-63.8h-256v383.8l192 192h-640l192-192v-384h-256v767.8h768z" />
<glyph unicode="&#xe928;" glyph-name="icon-suitcase" d="M768 704c-0.080 70.66-57.34 127.92-127.993 128h-256.007c-70.66-0.080-127.92-57.34-128-127.993v-128.007h-64v-768h640v768h-64zM384 703.88l0.12 0.12 255.88-0.12v-127.88h-256zM0 512v-640c0.102-35.305 28.695-63.898 63.99-64h64.010v768h-64c-35.305-0.102-63.898-28.695-64-63.99v-0.010zM960 576h-64v-768h64c35.305 0.102 63.898 28.695 64 63.99v640.010c-0.102 35.305-28.695 63.898-63.99 64h-0.010z" />
<glyph unicode="&#xe929;" glyph-name="icon-cursor-locked" horiz-adv-x="768" d="M704 512h-64v64c0 141.385-114.615 256-256 256s-256-114.615-256-256v0-64h-64c-35.301-0.113-63.887-28.699-64-63.989v-576.011c0.113-35.301 28.699-63.887 63.989-64h640.011c35.301 0.113 63.887 28.699 64 63.989v576.011c-0.113 35.301-28.699 63.887-63.989 64h-0.011zM256 576c0 70.692 57.308 128 128 128s128-57.308 128-128v0-64h-256zM533.4-64l-128 128-43-85-170.4 383.6 383.6-170.2-85-43 128-128z" />
<glyph unicode="&#xe92a;" glyph-name="icon-flag" d="M192 192h832l-192 320 192 320h-896c-70.606-0.215-127.785-57.394-128-127.979v-896.021h192z" />
<glyph unicode="&#xea00;" glyph-name="icon-arrows-right-left" d="M1024 320l-448-512v1024zM448 832l-448-512 448-512z" />
<glyph unicode="&#xea01;" glyph-name="icon-arrows-up-down" d="M512 832l512-448h-1024zM0 256l512-448 512 448z" />
<glyph unicode="&#xea02;" glyph-name="icon-bullet" d="M832 80c0-44-36-80-80-80h-480c-44 0-80 36-80 80v480c0 44 36 80 80 80h480c44 0 80-36 80-80v-480z" />
@ -138,4 +139,5 @@
<glyph unicode="&#xeb24;" glyph-name="icon-spectra" d="M768 128h-512l102.4 179.2-358.4-51.2v-254c0-106.6 87.4-194 194-194h636c106.8 0 194 87.4 194 194v62l-325.8 186.2zM830 832h-636c-106.6 0-194-87.2-194-194v-318l400 60.2 112 195.8 109.8-192h402.2v254c-0.227 107.052-86.948 193.773-193.978 194h-0.022zM1024 192v64l-384 64 384-128z" />
<glyph unicode="&#xeb25;" glyph-name="icon-telemetry-spectra" d="M512 576l109.8-192h398.2c-31.4 252.6-247 448-508 448-282.8 0-512-229.2-512-512l400 60.2zM768 128h-512l102.4 179.2-354.4-50.6c31.2-252.8 246.8-448.6 508-448.6 201.6 0 376 116.6 459.6 286l-273.4 156.2zM640 320l384-128v64l-384 64z" />
<glyph unicode="&#xeb26;" glyph-name="icon-pushbutton" d="M370.2 372.6c9.326-8.53 19.666-16.261 30.729-22.914l0.871-0.486c-11.077 19.209-17.664 42.221-17.8 66.76v0.040c0 39.6 17.8 77.6 50.2 107.4 37 34 87.4 52.6 141.8 52.6 40.2 0 78.2-10.2 110.2-29.2-8.918 15.653-19.693 29.040-32.268 40.482l-0.132 0.118c-37 34-87.4 52.6-141.8 52.6s-104.8-18.6-141.8-52.6c-32.4-29.8-50.2-67.8-50.2-107.4s17.8-77.6 50.2-107.4zM885.4 562.4c-40.6 154.6-192.4 269.6-373.4 269.6s-332.8-115-373.4-269.6c-86-80-138.6-187.8-138.6-306.4 0-247.4 229.2-448 512-448s512 200.6 512 448c0 118.6-52.6 226.4-138.6 306.4zM512 704c141.2 0 256-100.4 256-224s-114.8-224-256-224-256 100.4-256 224 114.8 224 256 224zM512 0c-175.4 0-318.4 127.8-320 285.4 68.8-94.8 186.4-157.4 320-157.4s251.2 62.6 320 157.4c-1.6-157.6-144.6-285.4-320-285.4z" />
<glyph unicode="&#xeb27;" glyph-name="icon-conditional" d="M512 832c-282.76 0-512-229.24-512-512s229.24-512 512-512 512 229.24 512 512-229.24 512-512 512zM512 64l-384 256 384 256 384-256z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 51 KiB