mirror of
https://github.com/nasa/openmct.git
synced 2025-05-05 10:13:07 +00:00
* feat(eslint): sort import rule * chore(deps): pin dep * refactor: sort imports --------- Co-authored-by: Jesse Mazzella <jesse.d.mazzella@nasa.gov>
393 lines
12 KiB
Vue
393 lines
12 KiB
Vue
<!--
|
|
Open MCT, Copyright (c) 2014-2023, 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>
|
|
<div
|
|
class="c-condition-h"
|
|
:class="{ 'is-drag-target': draggingOver }"
|
|
@dragover.prevent
|
|
@drop.prevent="dropCondition($event, conditionIndex)"
|
|
@dragenter="dragEnter($event, conditionIndex)"
|
|
@dragleave="dragLeave($event, conditionIndex)"
|
|
>
|
|
<div class="c-condition-h__drop-target"></div>
|
|
<div
|
|
v-if="isEditing"
|
|
:class="{ 'is-current': condition.id === currentConditionId }"
|
|
class="c-condition c-condition--edit"
|
|
>
|
|
<!-- Edit view -->
|
|
<div class="c-condition__header">
|
|
<span
|
|
class="c-condition__drag-grippy c-grippy c-grippy--vertical-drag"
|
|
title="Drag to reorder conditions"
|
|
:class="[{ 'is-enabled': !condition.isDefault }, { 'hide-nice': condition.isDefault }]"
|
|
:draggable="!condition.isDefault"
|
|
@dragstart="dragStart"
|
|
@dragend="dragEnd"
|
|
></span>
|
|
|
|
<span
|
|
class="c-condition__disclosure c-disclosure-triangle c-tree__item__view-control is-enabled"
|
|
:class="{ 'c-disclosure-triangle--expanded': expanded }"
|
|
@click="expanded = !expanded"
|
|
></span>
|
|
|
|
<span class="c-condition__name">{{ condition.configuration.name }}</span>
|
|
<span class="c-condition__summary">
|
|
<template v-if="!condition.isDefault && !canEvaluateCriteria"> Define criteria </template>
|
|
<span v-else>
|
|
<condition-description :show-label="false" :condition="condition" />
|
|
</span>
|
|
</span>
|
|
|
|
<div class="c-condition__buttons">
|
|
<button
|
|
v-if="!condition.isDefault"
|
|
class="c-click-icon c-condition__duplicate-button icon-duplicate"
|
|
title="Duplicate this condition"
|
|
@click="cloneCondition"
|
|
></button>
|
|
|
|
<button
|
|
v-if="!condition.isDefault"
|
|
class="c-click-icon c-condition__delete-button icon-trash"
|
|
title="Delete this condition"
|
|
@click="removeCondition"
|
|
></button>
|
|
</div>
|
|
</div>
|
|
<div v-if="expanded" class="c-condition__definition c-cdef">
|
|
<span class="c-cdef__separator c-row-separator"></span>
|
|
<span class="c-cdef__label">Condition Name</span>
|
|
<span class="c-cdef__controls">
|
|
<input
|
|
v-model="condition.configuration.name"
|
|
class="t-condition-input__name"
|
|
type="text"
|
|
@change="persist"
|
|
/>
|
|
</span>
|
|
|
|
<span class="c-cdef__label">Output</span>
|
|
<span class="c-cdef__controls">
|
|
<span class="c-cdef__control">
|
|
<select v-model="selectedOutputSelection" @change="setOutputValue">
|
|
<option v-for="option in outputOptions" :key="option" :value="option">
|
|
{{ initCap(option) }}
|
|
</option>
|
|
</select>
|
|
</span>
|
|
<span class="c-cdef__control">
|
|
<input
|
|
v-if="selectedOutputSelection === outputOptions[2]"
|
|
v-model="condition.configuration.output"
|
|
class="t-condition-name-input"
|
|
type="text"
|
|
@change="persist"
|
|
/>
|
|
</span>
|
|
</span>
|
|
|
|
<div v-if="!condition.isDefault" class="c-cdef__match-and-criteria">
|
|
<span class="c-cdef__separator c-row-separator"></span>
|
|
<span class="c-cdef__label">Match</span>
|
|
<span class="c-cdef__controls">
|
|
<select
|
|
v-model="condition.configuration.trigger"
|
|
aria-label="Condition Trigger"
|
|
@change="persist"
|
|
>
|
|
<option v-for="option in triggers" :key="option.value" :value="option.value">
|
|
{{ option.label }}
|
|
</option>
|
|
</select>
|
|
</span>
|
|
|
|
<template v-if="telemetry.length || condition.configuration.criteria.length">
|
|
<div
|
|
v-for="(criterion, index) in condition.configuration.criteria"
|
|
:key="criterion.id"
|
|
class="c-cdef__criteria"
|
|
>
|
|
<Criterion
|
|
:telemetry="telemetry"
|
|
:criterion="criterion"
|
|
:index="index"
|
|
:trigger="condition.configuration.trigger"
|
|
:is-default="condition.configuration.criteria.length === 1"
|
|
@persist="persist"
|
|
/>
|
|
<div class="c-cdef__criteria__buttons">
|
|
<button
|
|
class="c-click-icon c-cdef__criteria-duplicate-button icon-duplicate"
|
|
title="Duplicate this criteria"
|
|
@click="cloneCriterion(index)"
|
|
></button>
|
|
<button
|
|
v-if="!(condition.configuration.criteria.length === 1)"
|
|
class="c-click-icon c-cdef__criteria-duplicate-button icon-trash"
|
|
title="Delete this criteria"
|
|
@click="removeCriterion(index)"
|
|
></button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
<div class="c-cdef__separator c-row-separator"></div>
|
|
<div class="c-cdef__controls" :disabled="!telemetry.length">
|
|
<button
|
|
class="c-cdef__add-criteria-button c-button c-button--labeled icon-plus"
|
|
@click="addCriteria"
|
|
>
|
|
<span class="c-button__label">Add Criteria</span>
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div
|
|
v-else
|
|
class="c-condition c-condition--browse"
|
|
:class="{ 'is-current': condition.id === currentConditionId }"
|
|
>
|
|
<!-- Browse view -->
|
|
<div class="c-condition__header">
|
|
<span class="c-condition__name">
|
|
{{ condition.configuration.name }}
|
|
</span>
|
|
<span class="c-condition__output"> Output: {{ condition.configuration.output }} </span>
|
|
</div>
|
|
<div class="c-condition__summary">
|
|
<condition-description :show-label="false" :condition="condition" />
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { v4 as uuid } from 'uuid';
|
|
|
|
import { TRIGGER, TRIGGER_LABEL } from '@/plugins/condition/utils/constants';
|
|
|
|
import ConditionDescription from './ConditionDescription.vue';
|
|
import Criterion from './Criterion.vue';
|
|
|
|
export default {
|
|
components: {
|
|
Criterion,
|
|
ConditionDescription
|
|
},
|
|
inject: ['openmct'],
|
|
props: {
|
|
currentConditionId: {
|
|
type: String,
|
|
default: ''
|
|
},
|
|
condition: {
|
|
type: Object,
|
|
required: true
|
|
},
|
|
conditionIndex: {
|
|
type: Number,
|
|
required: true
|
|
},
|
|
isEditing: {
|
|
type: Boolean,
|
|
required: true,
|
|
default: false
|
|
},
|
|
telemetry: {
|
|
type: Array,
|
|
required: true,
|
|
default: () => []
|
|
},
|
|
isDragging: {
|
|
type: Boolean,
|
|
default: false
|
|
},
|
|
moveIndex: {
|
|
type: Number,
|
|
default: 0
|
|
}
|
|
},
|
|
data() {
|
|
return {
|
|
currentCriteria: this.currentCriteria,
|
|
expanded: true,
|
|
trigger: 'all',
|
|
selectedOutputSelection: '',
|
|
outputOptions: ['false', 'true', 'string'],
|
|
criterionIndex: 0,
|
|
draggingOver: false,
|
|
isDefault: this.condition.isDefault
|
|
};
|
|
},
|
|
computed: {
|
|
triggers() {
|
|
const keys = Object.keys(TRIGGER);
|
|
const triggerOptions = [];
|
|
keys.forEach((trigger) => {
|
|
triggerOptions.push({
|
|
value: TRIGGER[trigger],
|
|
label: `when ${TRIGGER_LABEL[TRIGGER[trigger]]}`
|
|
});
|
|
});
|
|
|
|
return triggerOptions;
|
|
},
|
|
canEvaluateCriteria: function () {
|
|
let criteria = this.condition.configuration.criteria;
|
|
if (criteria.length) {
|
|
let lastCriterion = criteria[criteria.length - 1];
|
|
if (
|
|
lastCriterion.telemetry &&
|
|
lastCriterion.operation &&
|
|
(lastCriterion.input.length ||
|
|
lastCriterion.operation === 'isDefined' ||
|
|
lastCriterion.operation === 'isUndefined')
|
|
) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
},
|
|
unmounted() {
|
|
this.destroy();
|
|
},
|
|
mounted() {
|
|
this.setOutputSelection();
|
|
},
|
|
methods: {
|
|
setOutputSelection() {
|
|
let conditionOutput = this.condition.configuration.output;
|
|
if (conditionOutput) {
|
|
if (conditionOutput !== 'false' && conditionOutput !== 'true') {
|
|
this.selectedOutputSelection = 'string';
|
|
} else {
|
|
this.selectedOutputSelection = conditionOutput;
|
|
}
|
|
}
|
|
},
|
|
setOutputValue() {
|
|
if (this.selectedOutputSelection === 'string') {
|
|
this.condition.configuration.output = '';
|
|
} else {
|
|
this.condition.configuration.output = this.selectedOutputSelection;
|
|
}
|
|
|
|
this.persist();
|
|
},
|
|
addCriteria() {
|
|
const criteriaObject = {
|
|
id: uuid(),
|
|
telemetry: '',
|
|
operation: '',
|
|
input: '',
|
|
metadata: ''
|
|
};
|
|
this.condition.configuration.criteria.push(criteriaObject);
|
|
},
|
|
dragStart(event) {
|
|
event.dataTransfer.clearData();
|
|
event.dataTransfer.setData('dragging', event.target); // required for FF to initiate drag
|
|
event.dataTransfer.effectAllowed = 'copyMove';
|
|
event.dataTransfer.setDragImage(event.target.closest('.c-condition-h'), 0, 0);
|
|
this.$emit('setMoveIndex', this.conditionIndex);
|
|
},
|
|
dragEnd() {
|
|
this.dragStarted = false;
|
|
this.$emit('dragComplete');
|
|
},
|
|
dropCondition(event, targetIndex) {
|
|
if (!this.isDragging) {
|
|
return;
|
|
}
|
|
|
|
if (targetIndex > this.moveIndex) {
|
|
targetIndex--;
|
|
} // for 'downward' move
|
|
|
|
if (this.isValidTarget(targetIndex)) {
|
|
this.dragElement = undefined;
|
|
this.draggingOver = false;
|
|
this.$emit('dropCondition', targetIndex);
|
|
}
|
|
},
|
|
dragEnter(event, targetIndex) {
|
|
if (!this.isDragging) {
|
|
return;
|
|
}
|
|
|
|
if (targetIndex > this.moveIndex) {
|
|
targetIndex--;
|
|
} // for 'downward' move
|
|
|
|
if (this.isValidTarget(targetIndex)) {
|
|
this.dragElement = event.target.parentElement;
|
|
this.draggingOver = true;
|
|
}
|
|
},
|
|
dragLeave(event) {
|
|
if (event.target.parentElement === this.dragElement) {
|
|
this.draggingOver = false;
|
|
this.dragElement = undefined;
|
|
}
|
|
},
|
|
isValidTarget(targetIndex) {
|
|
return this.moveIndex !== targetIndex;
|
|
},
|
|
destroy() {},
|
|
removeCondition() {
|
|
this.$emit('removeCondition', this.condition.id);
|
|
},
|
|
cloneCondition() {
|
|
this.$emit('cloneCondition', {
|
|
condition: this.condition,
|
|
index: this.conditionIndex
|
|
});
|
|
},
|
|
removeCriterion(index) {
|
|
this.condition.configuration.criteria.splice(index, 1);
|
|
this.persist();
|
|
},
|
|
cloneCriterion(index) {
|
|
const clonedCriterion = JSON.parse(
|
|
JSON.stringify(this.condition.configuration.criteria[index])
|
|
);
|
|
clonedCriterion.id = uuid();
|
|
this.condition.configuration.criteria.splice(index + 1, 0, clonedCriterion);
|
|
this.persist();
|
|
},
|
|
persist() {
|
|
this.$emit('updateCondition', {
|
|
condition: this.condition
|
|
});
|
|
},
|
|
initCap(str) {
|
|
return str.charAt(0).toUpperCase() + str.slice(1);
|
|
}
|
|
}
|
|
};
|
|
</script>
|