Skip to content

Commit

Permalink
Merge pull request #542 from OpenC3/graph_limits
Browse files Browse the repository at this point in the history
Allow user to graph limits
  • Loading branch information
ryanmelt authored Mar 16, 2023
2 parents 5fde3c4 + aa4f4c0 commit 9c73d9c
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 75 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ export default {
},
success: function () {
// Only process the success call if a file is selected and no error
if ((this.selectedFile !== null) && (this.error === null)) {
if (this.selectedFile !== null && this.error === null) {
if (this.type === 'open') {
this.openSuccess()
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -328,50 +328,15 @@
</v-list>
</v-menu>

<!-- Edit Item dialog -->
<v-dialog
max-width="600"
<graph-edit-item-dialog
v-if="editItem"
v-model="editItem"
@keydown.esc="editItem = false"
>
<v-card class="pa-3">
<v-card-title class="headline">Edit Item</v-card-title>
<v-select
outlined
hide-details
label="Value Type"
:items="valueTypes"
v-model="currentValueType"
/>
<v-select
outlined
hide-details
label="Reduction"
:items="reduction"
v-model="currentReduced"
/>
<v-select
outlined
hide-details
label="Reduced Type"
:items="reducedTypes"
:disabled="currentReduced === 'DECOM'"
v-model="currentReducedType"
/>
<v-select
outlined
hide-details
label="Color"
:items="colors"
v-model="selectedItem.color"
@change="changeColor($event)"
/>
<v-card-actions>
<v-btn color="primary" @click="closeEditItem()">Ok</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
:colors="colors"
:item="selectedItem"
@changeColor="changeColor"
@changeLimits="changeLimits"
@close="closeEditItem"
/>

<!-- Edit Item right click context menu -->
<v-menu
Expand All @@ -388,7 +353,7 @@
{{ selectedItem.packetName }}
{{ selectedItem.itemName }}
</v-subheader>
<v-list-item @click="openEditItem()">
<v-list-item @click="editItem = true">
<v-list-item-icon>
<v-icon>mdi-pencil</v-icon>
</v-list-item-icon>
Expand Down Expand Up @@ -444,6 +409,7 @@

<script>
import DateTimeChooser from './DateTimeChooser'
import GraphEditItemDialog from './GraphEditItemDialog'
import uPlot from 'uplot'
import bs from 'binary-search'
import { toDate, format } from 'date-fns'
Expand All @@ -454,6 +420,7 @@ require('uplot/dist/uPlot.min.css')
export default {
components: {
DateTimeChooser,
GraphEditItemDialog,
},
props: {
id: {
Expand Down Expand Up @@ -520,15 +487,6 @@ export default {
{ text: 'Item Name', value: 'itemName' },
{ text: 'Actions', value: 'actions', sortable: false },
],
valueTypes: ['CONVERTED', 'RAW'],
reduction: [
// Map NONE to DECOM for clarity
{ text: 'NONE', value: 'DECOM' },
{ text: 'REDUCED_MINUTE', value: 'REDUCED_MINUTE' },
{ text: 'REDUCED_HOUR', value: 'REDUCED_HOUR' },
{ text: 'REDUCED_DAY', value: 'REDUCED_DAY' },
],
reducedTypes: ['MIN', 'MAX', 'AVG', 'STDDEV'],
active: true,
expand: true,
fullWidth: true,
Expand All @@ -549,9 +507,6 @@ export default {
legendPositions: ['top', 'bottom', 'left', 'right'],
selectedItem: null,
showOverview: !this.hideOverview,
currentValueType: null,
currentReduced: null,
currentReducedType: null,
title: '',
overview: null,
data: [[]],
Expand All @@ -563,6 +518,7 @@ export default {
graphEndDateTime: null,
indexes: {},
items: this.initialItems || [],
limitsValues: [],
drawInterval: null,
zoomChart: false,
zoomOverview: false,
Expand Down Expand Up @@ -745,6 +701,7 @@ export default {
...this.getScales(),
...this.getAxes('chart'),
// series: series, // TODO: Uncomment with the performance code
plugins: [this.linesPlugin()],
series: [
{
label: 'Time',
Expand Down Expand Up @@ -1251,39 +1208,68 @@ export default {
],
}
},
openEditItem: function () {
this.currentValueType = this.selectedItem.valueType
this.currentReduced = this.selectedItem.reduced
this.currentReducedType = this.selectedItem.reducedType
this.editItem = true
},
closeEditItem: function () {
closeEditItem: function (event) {
this.editItem = false
// If the type, mode, or reducedType was changed we need to change the item
if (
this.selectedItem.valueType !== this.currentValueType ||
this.selectedItem.reduced !== this.currentReduced ||
this.selectedItem.reducedType !== this.currentReducedType
this.selectedItem.valueType !== event.valueType ||
this.selectedItem.reduced !== event.reduced ||
this.selectedItem.reducedType !== event.reducedType
) {
this.changeItem()
this.changeItem(event)
}
},
changeColor: function (event) {
let key = this.subscriptionKey(this.selectedItem)
let index = this.indexes[key]
this.items[index - 1].color = event
this.selectedItem.color = event
this.graph.root.querySelectorAll('.u-marker')[index].style.borderColor =
event
},
changeItem: function () {
changeLimits: function (limits) {
let key = this.subscriptionKey(this.selectedItem)
let index = this.indexes[key]
this.items[index - 1].limits = limits
this.selectedItem.limits = limits
this.limitsValues = limits
},
linesPlugin: function () {
return {
hooks: {
draw: (u) => {
const { ctx, bbox } = u
for (var i = 0; i < this.limitsValues.length; i++) {
let yPos = u.valToPos(this.limitsValues[i], 'y', true)
ctx.save()
ctx.beginPath()
if (i === 0 || i === 3) {
ctx.strokeStyle = 'red'
} else if (i === 1 || i === 2) {
ctx.strokeStyle = 'yellow'
} else {
ctx.strokeStyle = 'green'
}
ctx.lineWidth = 1
ctx.setLineDash([5, 5])
ctx.moveTo(bbox.left, yPos)
ctx.lineTo(bbox.left + bbox.width, yPos)
ctx.stroke()
ctx.restore()
}
},
},
}
},
changeItem: function (event) {
// NOTE: removing and adding items back to back broke the streaming_api
// because the messages got out of order (add before remove)
// Code in openc3-cosmos-cmd-tlm-api/app/channels/application_cable/channel.rb
// fixed the issue to enforce ordering.
this.removeItems([this.selectedItem])
this.selectedItem.valueType = this.currentValueType
this.selectedItem.reduced = this.currentReduced
this.selectedItem.reducedType = this.currentReducedType
this.selectedItem.valueType = event.valueType
this.selectedItem.reduced = event.reduced
this.selectedItem.reducedType = event.reducedType
setTimeout(() => {
this.addItems([this.selectedItem]), 0
})
Expand All @@ -1294,6 +1280,16 @@ export default {
if (item.color === undefined) {
item.color = this.colors[this.colorIndex]
}
if (item.limits === undefined) {
// [] matches 'NONE' in GraphEditItemDialog
item.limits = []
} else {
if (item.limits.length > 0) {
// If somehow we have more than one limits
// the last one wins which is fine
this.limitsValues = item.limits
}
}
this.colorIndex++
if (this.colorIndex === this.colors.length) {
this.colorIndex = 0
Expand Down Expand Up @@ -1459,10 +1455,11 @@ export default {
break
}
}
this.currentValueType = 'RAW'
this.currentReduced = this.selectedItem.reduced
this.currentReducedType = this.selectedItem.reducedType
this.changeItem()
this.changeItem({
valueType: 'RAW',
reduced: this.selectedItem.reduced,
reducedType: this.selectedItem.reducedType,
})
}
} else {
array[index] = value
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
<!--
# Copyright 2022 Ball Aerospace & Technologies Corp.
# All Rights Reserved.
#
# This program is free software; you can modify and/or redistribute it
# under the terms of the GNU Affero General Public License
# as published by the Free Software Foundation; version 3 with
# attribution addendums as found in the LICENSE.txt
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.

# Modified by OpenC3, Inc.
# All changes Copyright 2023, OpenC3, Inc.
# All Rights Reserved
#
# This file may also be used under the terms of a commercial license
# if purchased from OpenC3, Inc.
-->

<template>
<!-- Edit Item dialog -->
<v-dialog v-model="show" width="600" @keydown.enter="success()">
<v-card class="pa-3">
<v-card-title class="headline">Edit Item</v-card-title>
<v-select
outlined
hide-details
label="Value Type"
:items="valueTypes"
v-model="editItem.valueType"
/>
<v-select
outlined
hide-details
label="Reduction"
:items="reduction"
v-model="editItem.reduced"
/>
<v-select
outlined
hide-details
label="Reduced Type"
:items="reducedTypes"
:disabled="currentReduced === 'DECOM'"
v-model="editItem.reducedType"
/>
<v-select
outlined
hide-details
label="Color"
:items="colors"
v-model="editItem.color"
@change="$emit('changeColor', $event)"
/>
<div v-if="limitsNames.length > 1">
<v-select
outlined
hide-details
label="Display Limits"
:items="limitsNames"
v-model="limitsName"
@change="$emit('changeLimits', limits[limitsName])"
/>
<div class="pa-3">{{ limitsName }}: {{ limits[limitsName] }}</div>
</div>
<v-card-actions>
<v-btn color="primary" @click="$emit('close', editItem)">Ok</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</template>

<script>
import { OpenC3Api } from '../services/openc3-api.js'
export default {
props: {
value: Boolean, // value is the default prop when using v-model
item: {
type: Object,
required: true,
},
colors: {
type: Array,
required: true,
},
},
data: function () {
return {
editItem: null,
limitsName: 'NONE',
// NONE: [] matches the default limits assigned in Graph addItems
limits: { NONE: [] },
valueTypes: ['CONVERTED', 'RAW'],
reduction: [
// Map NONE to DECOM for clarity
{ text: 'NONE', value: 'DECOM' },
{ text: 'REDUCED_MINUTE', value: 'REDUCED_MINUTE' },
{ text: 'REDUCED_HOUR', value: 'REDUCED_HOUR' },
{ text: 'REDUCED_DAY', value: 'REDUCED_DAY' },
],
reducedTypes: ['MIN', 'MAX', 'AVG', 'STDDEV'],
}
},
computed: {
show: {
get() {
return this.value
},
set(value) {
this.$emit('input', value) // input is the default event when using v-model
},
},
limitsNames() {
return Object.keys(this.limits)
},
},
async created() {
this.editItem = { ...this.item }
await this.api
this.api = new OpenC3Api()
.get_item(this.item.targetName, this.item.packetName, this.item.itemName)
.then((details) => {
for (const [key, value] of Object.entries(details.limits)) {
if (Object.keys(value).includes('red_low')) {
// Must call this.$set to allow Vue to make the limits object reactive
this.$set(this.limits, key, Object.values(value))
}
}
// Locate the key for the value array that we pass in
this.limitsName = Object.keys(this.limits).find(
// Little hack to compare arrays you convert them to strings
(key) => this.limits[key] + '' === this.editItem.limits + ''
)
})
},
}
</script>

0 comments on commit 9c73d9c

Please sign in to comment.