From f03bfdebb4bcff8d09d0451f5d2a3fb45518e0e0 Mon Sep 17 00:00:00 2001 From: Jamie V Date: Fri, 31 Jul 2020 13:13:58 -0700 Subject: [PATCH] [Telemetry Tables][Plots] Display units where applicable (#3198) * added unit columns in telemetry tables * added unit column hiding in telemetry tables, added units to lad tables and sets * added units to plots and plot legends --- .../generator/GeneratorMetadataProvider.js | 2 + src/plugins/LADTable/components/LADRow.vue | 20 ++++++- src/plugins/LADTable/components/LADTable.vue | 19 ++++++ .../LADTable/components/LadTableSet.vue | 22 ++++++- .../displayLayout/DisplayLayoutToolbar.js | 60 +++++++++++++++++++ .../components/TelemetryView.vue | 16 ++++- src/plugins/plot/res/templates/mct-plot.html | 10 +++- .../res/templates/plot-options-browse.html | 1 + .../plot/res/templates/plot-options-edit.html | 3 + .../plot/src/configuration/LegendModel.js | 3 +- .../plot/src/configuration/PlotSeries.js | 6 ++ .../src/inspector/PlotLegendFormController.js | 5 ++ src/plugins/telemetryTable/TelemetryTable.js | 12 +++- .../telemetryTable/TelemetryTableRow.js | 6 +- .../TelemetryTableUnitColumn.js | 60 +++++++++++++++++++ .../components/table-configuration.vue | 7 ++- src/ui/toolbar/Toolbar.vue | 2 - 17 files changed, 242 insertions(+), 12 deletions(-) create mode 100644 src/plugins/telemetryTable/TelemetryTableUnitColumn.js diff --git a/example/generator/GeneratorMetadataProvider.js b/example/generator/GeneratorMetadataProvider.js index fd85e7a5dc..5aba6e7c0d 100644 --- a/example/generator/GeneratorMetadataProvider.js +++ b/example/generator/GeneratorMetadataProvider.js @@ -41,6 +41,7 @@ define([ { key: "sin", name: "Sine", + unit: "Hz", formatString: '%0.2f', hints: { range: 1 @@ -49,6 +50,7 @@ define([ { key: "cos", name: "Cosine", + unit: "deg", formatString: '%0.2f', hints: { range: 2 diff --git a/src/plugins/LADTable/components/LADRow.vue b/src/plugins/LADTable/components/LADRow.vue index 9963b483f7..e64891d414 100644 --- a/src/plugins/LADTable/components/LADRow.vue +++ b/src/plugins/LADTable/components/LADRow.vue @@ -32,6 +32,12 @@ class="js-third-data" :class="valueClass" >{{ value }} + + {{ unit }} + @@ -48,6 +54,10 @@ export default { domainObject: { type: Object, required: true + }, + hasUnits: { + type: Boolean, + requred: true } }, data() { @@ -59,7 +69,8 @@ export default { timestamp: undefined, value: '---', valueClass: '', - currentObjectPath + currentObjectPath, + unit: '' }; }, computed: { @@ -101,6 +112,10 @@ export default { .subscribe(this.domainObject, this.updateValues); this.requestHistory(); + + if (this.hasUnits) { + this.setUnit(); + } }, destroyed() { this.stopWatchingMutation(); @@ -186,6 +201,9 @@ export default { return false; } + }, + setUnit() { + this.unit = this.valueMetadata.unit || ''; } } }; diff --git a/src/plugins/LADTable/components/LADTable.vue b/src/plugins/LADTable/components/LADTable.vue index 16896d6499..cf2625aa3e 100644 --- a/src/plugins/LADTable/components/LADTable.vue +++ b/src/plugins/LADTable/components/LADTable.vue @@ -28,6 +28,7 @@ Name Timestamp Value + Unit @@ -35,6 +36,7 @@ v-for="item in items" :key="item.key" :domain-object="item.domainObject" + :has-units="hasUnits" /> @@ -54,6 +56,18 @@ export default { items: [] }; }, + computed: { + hasUnits() { + let itemsWithUnits = this.items.filter((item) => { + let metadata = this.openmct.telemetry.getMetadata(item.domainObject); + + return this.metadataHasUnits(metadata.valueMetadatas); + + }); + + return itemsWithUnits.length !== 0; + } + }, mounted() { this.composition = this.openmct.composition.get(this.domainObject); this.composition.on('add', this.addItem); @@ -84,6 +98,11 @@ export default { reorderPlan.forEach((reorderEvent) => { this.$set(this.items, reorderEvent.newIndex, oldItems[reorderEvent.oldIndex]); }); + }, + metadataHasUnits(valueMetadatas) { + let metadataWithUnits = valueMetadatas.filter(metadatum => metadatum.unit); + + return metadataWithUnits.length > 0; } } }; diff --git a/src/plugins/LADTable/components/LadTableSet.vue b/src/plugins/LADTable/components/LadTableSet.vue index c8fb4787b7..03cd6966ed 100644 --- a/src/plugins/LADTable/components/LadTableSet.vue +++ b/src/plugins/LADTable/components/LadTableSet.vue @@ -27,6 +27,7 @@ Name Timestamp Value + Unit @@ -45,6 +46,7 @@ v-for="secondary in secondaryTelemetryObjects[primary.key]" :key="secondary.key" :domain-object="secondary.domainObject" + :has-units="hasUnits" /> @@ -66,6 +68,23 @@ export default { compositions: [] }; }, + computed: { + hasUnits() { + let ladTables = Object.values(this.secondaryTelemetryObjects); + for (let ladTable of ladTables) { + for (let telemetryObject of ladTable) { + let metadata = this.openmct.telemetry.getMetadata(telemetryObject.domainObject); + for (let metadatum of metadata.valueMetadatas) { + if (metadatum.unit) { + return true; + } + } + } + } + + return false; + } + }, mounted() { this.composition = this.openmct.composition.get(this.domainObject); this.composition.on('add', this.addPrimary); @@ -109,9 +128,8 @@ export default { let index = this.primaryTelemetryObjects.findIndex(primary => this.openmct.objects.makeKeyString(identifier) === primary.key), primary = this.primaryTelemetryObjects[index]; - this.$set(this.secondaryTelemetryObjects, primary.key, undefined); + this.$delete(this.secondaryTelemetryObjects, primary.key); this.primaryTelemetryObjects.splice(index, 1); - primary = undefined; }, reorderPrimary(reorderPlan) { let oldComposition = this.primaryTelemetryObjects.slice(); diff --git a/src/plugins/displayLayout/DisplayLayoutToolbar.js b/src/plugins/displayLayout/DisplayLayoutToolbar.js index 2bb8135c51..35fe9956ec 100644 --- a/src/plugins/displayLayout/DisplayLayoutToolbar.js +++ b/src/plugins/displayLayout/DisplayLayoutToolbar.js @@ -134,6 +134,14 @@ define(['lodash'], function (_) { return `configuration.items[${selectionPath[0].context.index}]`; } + function getAllOfType(selection, specificType) { + return selection.filter(selectionPath => { + let type = selectionPath[0].context.layoutItem.type; + + return type === specificType; + }); + } + function getAllTypes(selection) { return selection.filter(selectionPath => { let type = selectionPath[0].context.layoutItem.type; @@ -510,6 +518,50 @@ define(['lodash'], function (_) { return allTelemetry; } + function getToggleUnitsButton(selectedParent, selection) { + let applicableItems = getAllOfType(selection, 'telemetry-view'); + applicableItems = unitsOnly(applicableItems); + if (!applicableItems.length) { + return; + } + + return { + control: "toggle-button", + domainObject: selectedParent, + applicableSelectedItems: applicableItems, + property: function (selectionPath) { + return getPath(selectionPath) + '.showUnits'; + }, + options: [ + { + value: true, + icon: 'icon-eye-open', + title: "Show units" + }, + { + value: false, + icon: 'icon-eye-disabled', + title: "Hide units" + } + ] + }; + } + + function unitsOnly(items) { + let results = items.filter((item) => { + let currentItem = item[0]; + let metadata = this.openmct.telemetry.getMetadata(currentItem.context.item); + let hasUnits = metadata + .valueMetadatas + .filter((metadatum) => metadatum.unit) + .length; + + return hasUnits > 0; + }); + + return results; + } + function getViewSwitcherMenu(selectedParent, selectionPath, selection) { if (selection.length === 1) { let displayLayoutContext = selectionPath[1].context, @@ -594,6 +646,7 @@ define(['lodash'], function (_) { 'text-style': [], 'position': [], 'duplicate': [], + 'unit-toggle': [], 'remove': [] }; @@ -663,6 +716,13 @@ define(['lodash'], function (_) { if (toolbar.viewSwitcher.length === 0) { toolbar.viewSwitcher = [getViewSwitcherMenu(selectedParent, selectionPath, selectedObjects)]; } + + if (toolbar['unit-toggle'].length === 0) { + let toggleUnitsButton = getToggleUnitsButton(selectedParent, selectedObjects); + if (toggleUnitsButton) { + toolbar['unit-toggle'] = [toggleUnitsButton]; + } + } } else if (layoutItem.type === 'text-view') { if (toolbar['text-style'].length === 0) { toolbar['text-style'] = [ diff --git a/src/plugins/displayLayout/components/TelemetryView.vue b/src/plugins/displayLayout/components/TelemetryView.vue index 46744dd33c..9d1253badb 100644 --- a/src/plugins/displayLayout/components/TelemetryView.vue +++ b/src/plugins/displayLayout/components/TelemetryView.vue @@ -58,6 +58,12 @@ >
{{ telemetryValue }} + + {{ unit }} +
@@ -137,6 +143,12 @@ export default { return displayMode === 'all' || displayMode === 'value'; }, + unit() { + let value = this.item.value, + unit = this.metadata.value(value).unit; + + return unit; + }, styleObject() { return Object.assign({}, { fontSize: this.item.size @@ -257,7 +269,9 @@ export default { item: domainObject, layoutItem: this.item, index: this.index, - updateTelemetryFormat: this.updateTelemetryFormat + updateTelemetryFormat: this.updateTelemetryFormat, + toggleUnits: this.toggleUnits, + showUnits: this.showUnits }; this.removeSelectable = this.openmct.selection.selectable( this.$el, this.context, this.immediatelySelect || this.initSelect); diff --git a/src/plugins/plot/res/templates/mct-plot.html b/src/plugins/plot/res/templates/mct-plot.html index 788ecda916..2f275a9cb8 100644 --- a/src/plugins/plot/res/templates/mct-plot.html +++ b/src/plugins/plot/res/templates/mct-plot.html @@ -49,7 +49,7 @@ ng-style="{ 'background-color': series.get('color').asHexString() }"> - {{ series.get('name') }} + {{ series.nameWithUnit() }}
Value + + Unit + Min @@ -114,6 +117,11 @@ {{ series.formatY(series.closest) }} + + + {{ series.get('unit') }} + + diff --git a/src/plugins/plot/res/templates/plot-options-browse.html b/src/plugins/plot/res/templates/plot-options-browse.html index 3a07047d36..163165b90a 100644 --- a/src/plugins/plot/res/templates/plot-options-browse.html +++ b/src/plugins/plot/res/templates/plot-options-browse.html @@ -140,6 +140,7 @@ Value Min Max + Units
diff --git a/src/plugins/plot/res/templates/plot-options-edit.html b/src/plugins/plot/res/templates/plot-options-edit.html index bdfd39ef0c..00b91c23de 100644 --- a/src/plugins/plot/res/templates/plot-options-edit.html +++ b/src/plugins/plot/res/templates/plot-options-edit.html @@ -201,6 +201,7 @@ + @@ -217,6 +218,8 @@ ng-model="form.showMinimumWhenExpanded"/> Minimum value
  • Maximum value
  • +
  • Units
  • diff --git a/src/plugins/plot/src/configuration/LegendModel.js b/src/plugins/plot/src/configuration/LegendModel.js index bbf8d45db1..82dd22cc26 100644 --- a/src/plugins/plot/src/configuration/LegendModel.js +++ b/src/plugins/plot/src/configuration/LegendModel.js @@ -53,7 +53,8 @@ define([ showTimestampWhenExpanded: true, showValueWhenExpanded: true, showMaximumWhenExpanded: true, - showMinimumWhenExpanded: true + showMinimumWhenExpanded: true, + showUnitsWhenExpanded: true }; } }); diff --git a/src/plugins/plot/src/configuration/PlotSeries.js b/src/plugins/plot/src/configuration/PlotSeries.js index aa20d07f97..08775ab6b5 100644 --- a/src/plugins/plot/src/configuration/PlotSeries.js +++ b/src/plugins/plot/src/configuration/PlotSeries.js @@ -102,6 +102,7 @@ define([ return { name: options.domainObject.name, + unit: range.unit, xKey: options.collection.plot.xAxis.get('key'), yKey: range.key, markers: true, @@ -439,6 +440,11 @@ define([ const markerSize = this.get('markerSize'); return `${markerShape}: ${markerSize}px`; + }, + nameWithUnit: function () { + let unit = this.get('unit'); + + return this.get('name') + (unit ? ' ' + unit : ''); } }); diff --git a/src/plugins/plot/src/inspector/PlotLegendFormController.js b/src/plugins/plot/src/inspector/PlotLegendFormController.js index 06e9eda0a8..601e5437ea 100644 --- a/src/plugins/plot/src/inspector/PlotLegendFormController.js +++ b/src/plugins/plot/src/inspector/PlotLegendFormController.js @@ -65,6 +65,11 @@ define([ modelProp: 'showMinimumWhenExpanded', coerce: Boolean, objectPath: 'configuration.legend.showMinimumWhenExpanded' + }, + { + modelProp: 'showUnitsWhenExpanded', + coerce: Boolean, + objectPath: 'configuration.legend.showUnitsWhenExpanded' } ] }); diff --git a/src/plugins/telemetryTable/TelemetryTable.js b/src/plugins/telemetryTable/TelemetryTable.js index 26d1e4969d..fcae5b6071 100644 --- a/src/plugins/telemetryTable/TelemetryTable.js +++ b/src/plugins/telemetryTable/TelemetryTable.js @@ -27,6 +27,7 @@ define([ './collections/FilteredTableRowCollection', './TelemetryTableRow', './TelemetryTableColumn', + './TelemetryTableUnitColumn', './TelemetryTableConfiguration' ], function ( EventEmitter, @@ -35,6 +36,7 @@ define([ FilteredTableRowCollection, TelemetryTableRow, TelemetryTableColumn, + TelemetryTableUnitColumn, TelemetryTableConfiguration ) { class TelemetryTable extends EventEmitter { @@ -210,10 +212,14 @@ define([ addColumnsForObject(telemetryObject) { let metadataValues = this.openmct.telemetry.getMetadata(telemetryObject).values(); - metadataValues.forEach(metadatum => { let column = this.createColumn(metadatum); this.configuration.addSingleColumnForObject(telemetryObject, column); + // add units column if available + if (metadatum.unit !== undefined) { + let unitColumn = this.createUnitColumn(metadatum); + this.configuration.addSingleColumnForObject(telemetryObject, unitColumn); + } }); } @@ -221,6 +227,10 @@ define([ return new TelemetryTableColumn(this.openmct, metadatum); } + createUnitColumn(metadatum) { + return new TelemetryTableUnitColumn(this.openmct, metadatum); + } + subscribeTo(telemetryObject) { let subscribeOptions = this.buildOptionsFromConfiguration(telemetryObject); let keyString = this.openmct.objects.makeKeyString(telemetryObject.identifier); diff --git a/src/plugins/telemetryTable/TelemetryTableRow.js b/src/plugins/telemetryTable/TelemetryTableRow.js index 443ff3dab6..06ca66088c 100644 --- a/src/plugins/telemetryTable/TelemetryTableRow.js +++ b/src/plugins/telemetryTable/TelemetryTableRow.js @@ -70,8 +70,10 @@ define([], function () { getCellLimitClasses() { if (!this.cellLimitClasses) { this.cellLimitClasses = Object.values(this.columns).reduce((alarmStateMap, column) => { - let limitEvaluation = this.limitEvaluator.evaluate(this.datum, column.getMetadatum()); - alarmStateMap[column.getKey()] = limitEvaluation && limitEvaluation.cssClass; + if (!column.isUnit) { + let limitEvaluation = this.limitEvaluator.evaluate(this.datum, column.getMetadatum()); + alarmStateMap[column.getKey()] = limitEvaluation && limitEvaluation.cssClass; + } return alarmStateMap; }, {}); diff --git a/src/plugins/telemetryTable/TelemetryTableUnitColumn.js b/src/plugins/telemetryTable/TelemetryTableUnitColumn.js new file mode 100644 index 0000000000..ffd269e04e --- /dev/null +++ b/src/plugins/telemetryTable/TelemetryTableUnitColumn.js @@ -0,0 +1,60 @@ +/***************************************************************************** + * Open MCT, Copyright (c) 2014-2018, 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. + *****************************************************************************/ +define([ + './TelemetryTableColumn.js' +], function ( + TelemetryTableColumn +) { + class TelemetryTableUnitColumn extends TelemetryTableColumn { + constructor(openmct, metadatum) { + super(openmct, metadatum); + this.isUnit = true; + this.titleValue += ' Unit'; + this.formatter = { + format: (datum) => { + return this.metadatum.unit; + }, + parse: (datum) => { + return this.metadatum.unit; + } + }; + } + + getKey() { + return this.metadatum.key + '-unit'; + } + + getTitle() { + return this.metadatum.name + ' Unit'; + } + + getRawValue(telemetryDatum) { + return this.metadatum.unit; + } + + getFormattedValue(telemetryDatum) { + return this.formatter.format(telemetryDatum); + } + } + + return TelemetryTableUnitColumn; +}); diff --git a/src/plugins/telemetryTable/components/table-configuration.vue b/src/plugins/telemetryTable/components/table-configuration.vue index 2a9a00b6fd..2d43573969 100644 --- a/src/plugins/telemetryTable/components/table-configuration.vue +++ b/src/plugins/telemetryTable/components/table-configuration.vue @@ -69,6 +69,7 @@