mirror of
https://github.com/nasa/openmct.git
synced 2025-05-08 11:38:35 +00:00
Update telemetry table for multisession (#2686)
* update telemetry table to ingest marked row data, add a new alterntate bar with includes row name, selected rows and show selected rows toggle * Enhancements for alternate toolbar in telem tables - .c-control-bar adds style enhancements and `__label` element; - Added `label` prop, markup and styling to ToggleSwitch; - ToggleSwitch layout enhanced; - Unit tested in main view and placed in Display Layout; * made improvements to row marking * bug fixes for marking * fix linting issues * -Make reviewer requested changes -Clarify prop for marking -Include alternateControlBar in the marking prop - - since it only makes sense for making Co-authored-by: Charles Hacskaylo <charlesh88@gmail.com>
This commit is contained in:
parent
a0b7999ea2
commit
85902b878e
@ -47,6 +47,7 @@ define([
|
|||||||
this.subscriptions = {};
|
this.subscriptions = {};
|
||||||
this.tableComposition = undefined;
|
this.tableComposition = undefined;
|
||||||
this.telemetryObjects = [];
|
this.telemetryObjects = [];
|
||||||
|
this.datumCache = [];
|
||||||
this.outstandingRequests = 0;
|
this.outstandingRequests = 0;
|
||||||
this.configuration = new TelemetryTableConfiguration(domainObject, openmct);
|
this.configuration = new TelemetryTableConfiguration(domainObject, openmct);
|
||||||
this.paused = false;
|
this.paused = false;
|
||||||
@ -155,6 +156,7 @@ define([
|
|||||||
processHistoricalData(telemetryData, columnMap, keyString, limitEvaluator) {
|
processHistoricalData(telemetryData, columnMap, keyString, limitEvaluator) {
|
||||||
let telemetryRows = telemetryData.map(datum => new TelemetryTableRow(datum, columnMap, keyString, limitEvaluator));
|
let telemetryRows = telemetryData.map(datum => new TelemetryTableRow(datum, columnMap, keyString, limitEvaluator));
|
||||||
this.boundedRows.add(telemetryRows);
|
this.boundedRows.add(telemetryRows);
|
||||||
|
this.emit('historical-rows-processed');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -227,12 +229,28 @@ define([
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!this.paused) {
|
if (this.paused) {
|
||||||
|
let realtimeDatum = {
|
||||||
|
datum,
|
||||||
|
columnMap,
|
||||||
|
keyString,
|
||||||
|
limitEvaluator
|
||||||
|
};
|
||||||
|
|
||||||
|
this.datumCache.push(realtimeDatum);
|
||||||
|
} else {
|
||||||
this.processRealtimeDatum(datum, columnMap, keyString, limitEvaluator);
|
this.processRealtimeDatum(datum, columnMap, keyString, limitEvaluator);
|
||||||
}
|
}
|
||||||
}, subscribeOptions);
|
}, subscribeOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
processDatumCache() {
|
||||||
|
this.datumCache.forEach(cachedDatum => {
|
||||||
|
this.processRealtimeDatum(cachedDatum.datum, cachedDatum.columnMap, cachedDatum.keyString, cachedDatum.limitEvaluator);
|
||||||
|
});
|
||||||
|
this.datumCache = [];
|
||||||
|
}
|
||||||
|
|
||||||
processRealtimeDatum(datum, columnMap, keyString, limitEvaluator) {
|
processRealtimeDatum(datum, columnMap, keyString, limitEvaluator) {
|
||||||
this.boundedRows.add(new TelemetryTableRow(datum, columnMap, keyString, limitEvaluator));
|
this.boundedRows.add(new TelemetryTableRow(datum, columnMap, keyString, limitEvaluator));
|
||||||
}
|
}
|
||||||
@ -272,8 +290,8 @@ define([
|
|||||||
|
|
||||||
unpause() {
|
unpause() {
|
||||||
this.paused = false;
|
this.paused = false;
|
||||||
|
this.processDatumCache();
|
||||||
this.boundedRows.subscribeToBounds();
|
this.boundedRows.subscribeToBounds();
|
||||||
this.refreshData();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
destroy() {
|
destroy() {
|
||||||
|
@ -68,7 +68,7 @@ define([
|
|||||||
table,
|
table,
|
||||||
objectPath
|
objectPath
|
||||||
},
|
},
|
||||||
template: '<table-component :isEditing="isEditing" :enableMarking="true"></table-component>'
|
template: '<table-component :isEditing="isEditing" :marking="{enable: true}"/>'
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
onEditModeChange(editMode) {
|
onEditModeChange(editMode) {
|
||||||
@ -86,7 +86,7 @@ define([
|
|||||||
priority() {
|
priority() {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
return TelemetryTableViewProvider;
|
return TelemetryTableViewProvider;
|
||||||
});
|
});
|
||||||
|
@ -21,7 +21,10 @@
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
<template>
|
<template>
|
||||||
<div class="c-table-wrapper">
|
<div class="c-table-wrapper">
|
||||||
<div class="c-table-control-bar c-control-bar">
|
<!-- main contolbar start-->
|
||||||
|
<div v-if="!marking.useAlternateControlBar"
|
||||||
|
class="c-table-control-bar c-control-bar"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
v-if="allowExport"
|
v-if="allowExport"
|
||||||
class="c-button icon-download labeled"
|
class="c-button icon-download labeled"
|
||||||
@ -48,11 +51,11 @@
|
|||||||
<span class="c-button__label">Unmark All Rows</span>
|
<span class="c-button__label">Unmark All Rows</span>
|
||||||
</button>
|
</button>
|
||||||
<div
|
<div
|
||||||
v-if="enableMarking"
|
v-if="marking.enable"
|
||||||
class="c-separator"
|
class="c-separator"
|
||||||
></div>
|
></div>
|
||||||
<button
|
<button
|
||||||
v-if="enableMarking"
|
v-if="marking.enable"
|
||||||
class="c-button icon-pause pause-play labeled"
|
class="c-button icon-pause pause-play labeled"
|
||||||
:class=" paused ? 'icon-play is-paused' : 'icon-pause'"
|
:class=" paused ? 'icon-play is-paused' : 'icon-pause'"
|
||||||
:title="paused ? 'Continue Data Flow' : 'Pause Data Flow'"
|
:title="paused ? 'Continue Data Flow' : 'Pause Data Flow'"
|
||||||
@ -62,8 +65,37 @@
|
|||||||
{{ paused ? 'Play' : 'Pause' }}
|
{{ paused ? 'Play' : 'Pause' }}
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
||||||
<slot name="buttons"></slot>
|
<slot name="buttons"></slot>
|
||||||
</div>
|
</div>
|
||||||
|
<!-- main controlbar end -->
|
||||||
|
|
||||||
|
<!-- alternate controlbar start -->
|
||||||
|
<div v-if="marking.useAlternateControlBar && markedRows.length"
|
||||||
|
class="c-table-control-bar c-control-bar"
|
||||||
|
>
|
||||||
|
<div class="c-control-bar__label">
|
||||||
|
{{ markedRows.length > 1 ? `${markedRows.length} ${marking.rowNamePlural} selected`: `${markedRows.length} ${marking.rowName} selected` }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<toggle-switch
|
||||||
|
id="show-filtered-rows-toggle"
|
||||||
|
label="Show selected items only"
|
||||||
|
:checked="isShowingMarkedRowsOnly"
|
||||||
|
@change="toggleMarkedRows"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<button
|
||||||
|
class="c-button icon-x labeled"
|
||||||
|
title="Deselect All"
|
||||||
|
@click="unmarkAllRows()"
|
||||||
|
>
|
||||||
|
<span class="c-button__label">Deselect All</span>
|
||||||
|
</button>
|
||||||
|
|
||||||
|
<slot name="buttons"></slot>
|
||||||
|
</div>
|
||||||
|
<!-- alternate controlbar end -->
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="c-table c-telemetry-table c-table--filterable c-table--sortable has-control-bar"
|
class="c-table c-telemetry-table c-table--filterable c-table--sortable has-control-bar"
|
||||||
@ -205,6 +237,7 @@ import TableColumnHeader from './table-column-header.vue';
|
|||||||
import TelemetryFilterIndicator from './TelemetryFilterIndicator.vue';
|
import TelemetryFilterIndicator from './TelemetryFilterIndicator.vue';
|
||||||
import CSVExporter from '../../../exporters/CSVExporter.js';
|
import CSVExporter from '../../../exporters/CSVExporter.js';
|
||||||
import _ from 'lodash';
|
import _ from 'lodash';
|
||||||
|
import ToggleSwitch from '../../../ui/components/ToggleSwitch.vue';
|
||||||
|
|
||||||
const VISIBLE_ROW_COUNT = 100;
|
const VISIBLE_ROW_COUNT = 100;
|
||||||
const ROW_HEIGHT = 17;
|
const ROW_HEIGHT = 17;
|
||||||
@ -216,7 +249,8 @@ export default {
|
|||||||
TelemetryTableRow,
|
TelemetryTableRow,
|
||||||
TableColumnHeader,
|
TableColumnHeader,
|
||||||
search,
|
search,
|
||||||
TelemetryFilterIndicator
|
TelemetryFilterIndicator,
|
||||||
|
ToggleSwitch
|
||||||
},
|
},
|
||||||
inject: ['table', 'openmct', 'objectPath'],
|
inject: ['table', 'openmct', 'objectPath'],
|
||||||
props: {
|
props: {
|
||||||
@ -236,9 +270,16 @@ export default {
|
|||||||
'type': Boolean,
|
'type': Boolean,
|
||||||
'default': true
|
'default': true
|
||||||
},
|
},
|
||||||
enableMarking: {
|
marking: {
|
||||||
type: Boolean,
|
type: Object,
|
||||||
default: false
|
default() {
|
||||||
|
return {
|
||||||
|
enable: false,
|
||||||
|
useAlternateControlBar: false,
|
||||||
|
rowName: '',
|
||||||
|
rowNamePlural: ""
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
@ -270,7 +311,8 @@ export default {
|
|||||||
scrollW: 0,
|
scrollW: 0,
|
||||||
markCounter: 0,
|
markCounter: 0,
|
||||||
paused: false,
|
paused: false,
|
||||||
markedRows: []
|
markedRows: [],
|
||||||
|
isShowingMarkedRowsOnly: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -317,6 +359,7 @@ export default {
|
|||||||
this.table.on('object-removed', this.removeObject);
|
this.table.on('object-removed', this.removeObject);
|
||||||
this.table.on('outstanding-requests', this.outstandingRequests);
|
this.table.on('outstanding-requests', this.outstandingRequests);
|
||||||
this.table.on('refresh', this.clearRowsAndRerender);
|
this.table.on('refresh', this.clearRowsAndRerender);
|
||||||
|
this.table.on('historical-rows-processed', this.checkForMarkedRows);
|
||||||
|
|
||||||
this.table.filteredRows.on('add', this.rowsAdded);
|
this.table.filteredRows.on('add', this.rowsAdded);
|
||||||
this.table.filteredRows.on('remove', this.rowsRemoved);
|
this.table.filteredRows.on('remove', this.rowsRemoved);
|
||||||
@ -631,18 +674,19 @@ export default {
|
|||||||
},
|
},
|
||||||
unpause(unpausedByButton) {
|
unpause(unpausedByButton) {
|
||||||
if (unpausedByButton) {
|
if (unpausedByButton) {
|
||||||
this.paused = false;
|
this.undoMarkedRows();
|
||||||
this.table.unpause();
|
this.table.unpause();
|
||||||
this.markedRows = [];
|
this.paused = false;
|
||||||
this.pausedByButton = false;
|
this.pausedByButton = false;
|
||||||
} else {
|
} else {
|
||||||
if (!this.pausedByButton) {
|
if (!this.pausedByButton) {
|
||||||
this.paused = false;
|
this.undoMarkedRows();
|
||||||
this.table.unpause();
|
this.table.unpause();
|
||||||
this.markedRows = [];
|
this.paused = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.isShowingMarkedRowsOnly = false;
|
||||||
},
|
},
|
||||||
togglePauseByButton() {
|
togglePauseByButton() {
|
||||||
if (this.paused) {
|
if (this.paused) {
|
||||||
@ -655,24 +699,23 @@ export default {
|
|||||||
this.markedRows.forEach(r => r.marked = false);
|
this.markedRows.forEach(r => r.marked = false);
|
||||||
this.markedRows = [];
|
this.markedRows = [];
|
||||||
},
|
},
|
||||||
unmarkRow(rowIndex, ctrlKeyModifier) {
|
unmarkRow(rowIndex) {
|
||||||
if (ctrlKeyModifier) {
|
if (this.markedRows.length > 1) {
|
||||||
let row = this.visibleRows[rowIndex],
|
let row = this.visibleRows[rowIndex],
|
||||||
positionInMarkedArray = this.markedRows.indexOf(row);
|
positionInMarkedArray = this.markedRows.indexOf(row);
|
||||||
|
|
||||||
row.marked = false;
|
row.marked = false;
|
||||||
this.markedRows.splice(positionInMarkedArray, 1);
|
this.markedRows.splice(positionInMarkedArray, 1);
|
||||||
|
} else if (this.markedRows.length === 1) {
|
||||||
|
this.unmarkAllRows();
|
||||||
|
}
|
||||||
|
|
||||||
if (this.markedRows.length === 0) {
|
if (this.markedRows.length === 0) {
|
||||||
this.unpause();
|
this.unpause();
|
||||||
}
|
}
|
||||||
} else if (this.markedRows.length) {
|
|
||||||
this.undoMarkedRows();
|
|
||||||
this.markRow(rowIndex);
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
markRow(rowIndex, keyModifier) {
|
markRow(rowIndex, keyModifier) {
|
||||||
if (!this.enableMarking) {
|
if (!this.marking.enable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -691,12 +734,13 @@ export default {
|
|||||||
this.markedRows[insertMethod](markedRow);
|
this.markedRows[insertMethod](markedRow);
|
||||||
},
|
},
|
||||||
unmarkAllRows(skipUnpause) {
|
unmarkAllRows(skipUnpause) {
|
||||||
this.markedRows.forEach(row => row.marked = false);
|
this.undoMarkedRows();
|
||||||
this.markedRows = [];
|
this.isShowingMarkedRowsOnly = false;
|
||||||
this.unpause();
|
this.unpause();
|
||||||
|
this.restorePreviousRows();
|
||||||
},
|
},
|
||||||
markMultipleConcurrentRows(rowIndex) {
|
markMultipleConcurrentRows(rowIndex) {
|
||||||
if (!this.enableMarking) {
|
if (!this.marking.enable) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -733,6 +777,34 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
checkForMarkedRows() {
|
||||||
|
this.markedRows = this.table.filteredRows.getRows().filter(row => row.marked);
|
||||||
|
},
|
||||||
|
showRows(rows) {
|
||||||
|
this.table.filteredRows.rows = rows;
|
||||||
|
this.table.filteredRows.emit('filter');
|
||||||
|
},
|
||||||
|
toggleMarkedRows(flag) {
|
||||||
|
if (flag) {
|
||||||
|
this.isShowingMarkedRowsOnly = true;
|
||||||
|
this.userScroll = this.scrollable.scrollTop;
|
||||||
|
this.allRows = this.table.filteredRows.getRows();
|
||||||
|
|
||||||
|
this.showRows(this.markedRows);
|
||||||
|
this.setHeight();
|
||||||
|
} else {
|
||||||
|
this.isShowingMarkedRowsOnly = false;
|
||||||
|
this.restorePreviousRows();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
restorePreviousRows() {
|
||||||
|
if (this.allRows && this.allRows.length) {
|
||||||
|
this.showRows(this.allRows);
|
||||||
|
this.allRows = [];
|
||||||
|
this.setHeight();
|
||||||
|
this.scrollable.scrollTop = this.userScroll;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,6 +28,16 @@
|
|||||||
height: $controlBarH;
|
height: $controlBarH;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.c-control-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
|
||||||
|
&__label {
|
||||||
|
display: inline-block;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.l-view-section {
|
.l-view-section {
|
||||||
@include abs();
|
@include abs();
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
<template>
|
<template>
|
||||||
<label class="c-toggle-switch">
|
<div class="c-toggle-switch">
|
||||||
|
<label class="c-toggle-switch__control">
|
||||||
<input
|
<input
|
||||||
:id="id"
|
:id="id"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
@ -7,10 +8,18 @@
|
|||||||
@change="onUserSelect($event)"
|
@change="onUserSelect($event)"
|
||||||
>
|
>
|
||||||
<span class="c-toggle-switch__slider"></span>
|
<span class="c-toggle-switch__slider"></span>
|
||||||
</label>
|
</label>
|
||||||
|
<div
|
||||||
|
v-if="label && label.length"
|
||||||
|
class="c-toggle-switch__label"
|
||||||
|
>
|
||||||
|
{{ label }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
inject: ['openmct'],
|
inject: ['openmct'],
|
||||||
props: {
|
props: {
|
||||||
@ -18,6 +27,11 @@ export default {
|
|||||||
type: String,
|
type: String,
|
||||||
required: true
|
required: true
|
||||||
},
|
},
|
||||||
|
label: {
|
||||||
|
type: String,
|
||||||
|
required: false,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
checked: Boolean
|
checked: Boolean
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@ -26,4 +40,5 @@ export default {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
|
@ -2,15 +2,40 @@
|
|||||||
$d: 12px;
|
$d: 12px;
|
||||||
$m: 2px;
|
$m: 2px;
|
||||||
$br: $d/1.5;
|
$br: $d/1.5;
|
||||||
cursor: pointer;
|
display: inline-flex;
|
||||||
overflow: hidden;
|
align-items: center;
|
||||||
display: inline;
|
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
|
|
||||||
|
&__control,
|
||||||
|
&__label {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__control {
|
||||||
|
cursor: pointer;
|
||||||
|
overflow: hidden;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
opacity: 0;
|
||||||
|
width: 0;
|
||||||
|
height: 0;
|
||||||
|
|
||||||
|
&:checked {
|
||||||
|
+ .c-toggle-switch__slider {
|
||||||
|
background: $colorKey; // TODO: make discrete theme constants for these colors
|
||||||
|
&:before {
|
||||||
|
transform: translateX(100%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&__slider {
|
&__slider {
|
||||||
|
// Sits within __switch
|
||||||
background: $colorBtnBg; // TODO: make discrete theme constants for these colors
|
background: $colorBtnBg; // TODO: make discrete theme constants for these colors
|
||||||
border-radius: $br;
|
border-radius: $br;
|
||||||
//box-shadow: inset rgba($colorBtnFg, 0.4) 0 0 0 1px;
|
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
height: $d + ($m*2);
|
height: $d + ($m*2);
|
||||||
position: relative;
|
position: relative;
|
||||||
@ -31,18 +56,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
&__label {
|
||||||
opacity: 0;
|
margin-left: $interiorMarginSm;
|
||||||
width: 0;
|
margin-right: $interiorMargin;
|
||||||
height: 0;
|
white-space: nowrap;
|
||||||
|
|
||||||
&:checked {
|
|
||||||
+ .c-toggle-switch__slider {
|
|
||||||
background: $colorKey; // TODO: make discrete theme constants for these colors
|
|
||||||
&:before {
|
|
||||||
transform: translateX(100%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user