mirror of
https://github.com/nasa/openmct.git
synced 2024-12-21 06:03:08 +00:00
Allow Data Visualization in inspector based on current selection (#7052) * visualize data in inspector per selection --------- Co-authored-by: David Tsay <3614296+davetsay@users.noreply.github.com> Co-authored-by: Khalid Adil <khalidadil29@gmail.com> Co-authored-by: John Hill <john.c.hill@nasa.gov>
This commit is contained in:
parent
b923af8705
commit
4f559fdccf
186
src/plugins/inspectorDataVisualization/DataVisualization.vue
Normal file
186
src/plugins/inspectorDataVisualization/DataVisualization.vue
Normal file
@ -0,0 +1,186 @@
|
|||||||
|
<!--
|
||||||
|
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-data-visualization-inspect-properties c-inspector__data-pivot c-data-visualization-inspector__flex-column"
|
||||||
|
>
|
||||||
|
<div class="c-inspect-properties">
|
||||||
|
<div class="c-inspect-properties__header">Data Visualization</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-if="isLoading" class="c-inspector__data-pivot-placeholder">Loading...</div>
|
||||||
|
|
||||||
|
<div v-else-if="hasDataRanges">
|
||||||
|
<div
|
||||||
|
v-if="selectedDataRange !== undefined && hasDescription"
|
||||||
|
class="c-inspector__data-pivot-coordinates-wrapper"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="c-tree__item__type-icon c-object-label__type-icon"
|
||||||
|
:class="description.icon"
|
||||||
|
></span>
|
||||||
|
<span class="c-inspector__data-pivot-coordinates">
|
||||||
|
{{ description.text }}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<select class="c-inspector__data-pivot-range-selector" v-model="selectedDataRangeIndex">
|
||||||
|
<option
|
||||||
|
v-for="(dataRange, index) in descendingDataRanges"
|
||||||
|
:key="index"
|
||||||
|
:value="index"
|
||||||
|
:selected="selectedDataRangeIndex === index"
|
||||||
|
>
|
||||||
|
{{ displayDataRange(dataRange) }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div
|
||||||
|
v-else-if="dataRanges && dataRanges.length === 0"
|
||||||
|
class="c-inspector__data-pivot-placeholder"
|
||||||
|
>
|
||||||
|
No data for the current {{ description.name }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div v-else-if="hasPlaceholderText" class="c-inspector__data-pivot-placeholder">
|
||||||
|
{{ placeholderText }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<template v-if="selectedBounds !== undefined">
|
||||||
|
<NumericData
|
||||||
|
:bounds="selectedBounds"
|
||||||
|
:telemetry-keys="plotTelemetryKeys"
|
||||||
|
:no-numeric-data-text="noNumericDataText"
|
||||||
|
/>
|
||||||
|
<Imagery v-if="hasImagery" :bounds="selectedBounds" :telemetry-keys="imageryTelemetryKeys" />
|
||||||
|
</template>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import NumericData from './NumericData.vue';
|
||||||
|
import Imagery from './Imagery.vue';
|
||||||
|
|
||||||
|
const TIMESTAMP_VIEW_BUFFER = 30 * 1000;
|
||||||
|
const timestampBufferText = `${TIMESTAMP_VIEW_BUFFER / 1000} seconds`;
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
NumericData,
|
||||||
|
Imagery
|
||||||
|
},
|
||||||
|
inject: ['timeFormatter', 'placeholderText', 'plotOptions', 'imageryOptions'],
|
||||||
|
props: {
|
||||||
|
description: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
dataRanges: {
|
||||||
|
type: Array,
|
||||||
|
default: () => undefined
|
||||||
|
},
|
||||||
|
plotTelemetryKeys: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
isLoading: {
|
||||||
|
type: Boolean,
|
||||||
|
default: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedDataRangeIndex: 0
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
hasPlaceholderText() {
|
||||||
|
return this.placeholderText.length > 0;
|
||||||
|
},
|
||||||
|
descendingDataRanges() {
|
||||||
|
return this.dataRanges?.slice().reverse();
|
||||||
|
},
|
||||||
|
hasDescription() {
|
||||||
|
return this.description?.text?.length > 0;
|
||||||
|
},
|
||||||
|
hasDataRanges() {
|
||||||
|
return this.dataRanges?.length > 0;
|
||||||
|
},
|
||||||
|
selectedDataRange() {
|
||||||
|
if (!this.hasDataRanges || this.selectedDataRangeIndex === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.descendingDataRanges[this.selectedDataRangeIndex];
|
||||||
|
},
|
||||||
|
selectedBounds() {
|
||||||
|
if (this.selectedDataRange === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { start, end } = this.selectedDataRange.bounds;
|
||||||
|
|
||||||
|
if (start === end) {
|
||||||
|
return {
|
||||||
|
start: start - TIMESTAMP_VIEW_BUFFER,
|
||||||
|
end: end + TIMESTAMP_VIEW_BUFFER
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.selectedDataRange.bounds;
|
||||||
|
},
|
||||||
|
imageryTelemetryKeys() {
|
||||||
|
return this.imageryOptions?.telemetryKeys;
|
||||||
|
},
|
||||||
|
hasImagery() {
|
||||||
|
return this.imageryTelemetryKeys?.length;
|
||||||
|
},
|
||||||
|
noNumericDataText() {
|
||||||
|
return this.plotOptions?.noNumericDataText;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
shortDate(date) {
|
||||||
|
return date.slice(0, date.indexOf('.')).replace('T', ' ');
|
||||||
|
},
|
||||||
|
displayDataRange(dataRange) {
|
||||||
|
const startTime = dataRange.bounds.start;
|
||||||
|
const endTime = dataRange.bounds.end;
|
||||||
|
if (startTime === endTime) {
|
||||||
|
return `${this.shortDate(this.timeFormatter.format(startTime))} +/- ${timestampBufferText}`;
|
||||||
|
}
|
||||||
|
return `${this.shortDate(this.timeFormatter.format(startTime))} - ${this.shortDate(
|
||||||
|
this.timeFormatter.format(endTime)
|
||||||
|
)}`;
|
||||||
|
},
|
||||||
|
isSelectedDataRange(dataRange, index) {
|
||||||
|
const selectedDataRange = this.descendingDataRanges[index];
|
||||||
|
|
||||||
|
return (
|
||||||
|
dataRange.bounds.start === selectedDataRange.bounds.start &&
|
||||||
|
dataRange.bounds.end === selectedDataRange.bounds.end
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
127
src/plugins/inspectorDataVisualization/Imagery.vue
Normal file
127
src/plugins/inspectorDataVisualization/Imagery.vue
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
<!--
|
||||||
|
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
|
||||||
|
v-if="camerasWithImagesInBounds.length > 0"
|
||||||
|
class="c-inspect-properties c-inspector__imagery-view"
|
||||||
|
>
|
||||||
|
<div class="c-inspect-properties__header">Imagery View</div>
|
||||||
|
<div
|
||||||
|
v-for="(camera, index) in camerasWithImagesInBounds"
|
||||||
|
:key="index"
|
||||||
|
class="c-imagery-view__camera-image-set"
|
||||||
|
>
|
||||||
|
<TelemetryFrame :bounds="bounds" :telemetry-object="camera">
|
||||||
|
<div class="c-imagery-view__camera-image-list">
|
||||||
|
<span
|
||||||
|
v-for="(cameraImage, imageIndex) in camera.imagesInBounds"
|
||||||
|
:key="imageIndex"
|
||||||
|
class="c-imagery-view__camera-image"
|
||||||
|
>
|
||||||
|
<img :src="cameraImage.value" />
|
||||||
|
<span class="c-imagery-view__camera-image-timestamp">
|
||||||
|
{{ cameraImage.timestamp }}
|
||||||
|
</span>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
</TelemetryFrame>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import TelemetryFrame from './TelemetryFrame.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
TelemetryFrame
|
||||||
|
},
|
||||||
|
inject: ['openmct'],
|
||||||
|
props: {
|
||||||
|
bounds: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
telemetryKeys: {
|
||||||
|
type: Array,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
camerasWithImagesInBounds: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
bounds() {
|
||||||
|
this.getCameraImagesInBounds();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.getCameraImagesInBounds();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
async getCameraImagesInBounds() {
|
||||||
|
this.camerasWithImagesInBounds = [];
|
||||||
|
this.cameraImagesList = [];
|
||||||
|
const { start, end } = this.bounds;
|
||||||
|
const cameraObjectPromises = [];
|
||||||
|
this.telemetryKeys.forEach((telemetryKey) => {
|
||||||
|
const cameraPromise = this.openmct.objects.get(telemetryKey);
|
||||||
|
cameraObjectPromises.push(cameraPromise);
|
||||||
|
});
|
||||||
|
const cameraObjects = await Promise.all(cameraObjectPromises);
|
||||||
|
|
||||||
|
const cameraTelemetryPromises = [];
|
||||||
|
cameraObjects.forEach((cameraObject) => {
|
||||||
|
const cameraTelemetryPromise = this.openmct.telemetry.request(cameraObject, {
|
||||||
|
start,
|
||||||
|
end
|
||||||
|
});
|
||||||
|
cameraTelemetryPromises.push(cameraTelemetryPromise);
|
||||||
|
});
|
||||||
|
const cameraImages = await Promise.all(cameraTelemetryPromises);
|
||||||
|
|
||||||
|
cameraObjects.forEach((cameraObject, index) => {
|
||||||
|
cameraObject.images = cameraImages[index];
|
||||||
|
});
|
||||||
|
|
||||||
|
cameraObjects.forEach((cameraObject) => {
|
||||||
|
if (cameraObject.images.length > 0) {
|
||||||
|
const imagesInBounds = cameraObject.images.filter((imageDetails) => {
|
||||||
|
if (!imageDetails.timestamp) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
const timestamp = Date.parse(imageDetails.timestamp);
|
||||||
|
return timestamp >= start && timestamp <= end;
|
||||||
|
});
|
||||||
|
if (imagesInBounds.length > 0) {
|
||||||
|
cameraObject.imagesInBounds = imagesInBounds;
|
||||||
|
this.camerasWithImagesInBounds.push(cameraObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
@ -0,0 +1,65 @@
|
|||||||
|
<!--
|
||||||
|
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-inspector__properties c-data-visualization-inspector__properties c-data-visualization-inspector__flex-column"
|
||||||
|
>
|
||||||
|
<DataVisualization
|
||||||
|
:data-ranges="dataRanges"
|
||||||
|
:plot-telemetry-keys="plotTelemetryKeys"
|
||||||
|
:description="description"
|
||||||
|
:is-loading="isLoading"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import DataVisualization from './DataVisualization.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
DataVisualization
|
||||||
|
},
|
||||||
|
inject: ['openmct', 'domainObject'],
|
||||||
|
props: {
|
||||||
|
context: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
dataRanges() {
|
||||||
|
return this.context.dataRanges;
|
||||||
|
},
|
||||||
|
plotTelemetryKeys() {
|
||||||
|
return this.context.telemetryKeys;
|
||||||
|
},
|
||||||
|
description() {
|
||||||
|
return this.context.description;
|
||||||
|
},
|
||||||
|
isLoading() {
|
||||||
|
return Boolean(this.context.loading);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
@ -0,0 +1,94 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
import mount from 'utils/mount';
|
||||||
|
|
||||||
|
import InspectorDataVisualizationComponent from './InspectorDataVisualizationComponent.vue';
|
||||||
|
|
||||||
|
export default function InspectorDataVisualizationViewProvider(openmct, configuration) {
|
||||||
|
const {
|
||||||
|
type = 'mmgis',
|
||||||
|
name = 'Data Visualization',
|
||||||
|
placeholderText = '',
|
||||||
|
plotOptions,
|
||||||
|
imageryOptions
|
||||||
|
} = configuration;
|
||||||
|
|
||||||
|
return {
|
||||||
|
key: 'inspectorDataVisualizationView',
|
||||||
|
name,
|
||||||
|
|
||||||
|
canView(selection) {
|
||||||
|
const domainObject = selection?.[0]?.[0]?.context?.item;
|
||||||
|
|
||||||
|
return domainObject?.type === type;
|
||||||
|
},
|
||||||
|
|
||||||
|
view(selection) {
|
||||||
|
let _destroy = null;
|
||||||
|
|
||||||
|
const context = selection[0][0].context;
|
||||||
|
const domainObject = context.item;
|
||||||
|
const dataVisualizationContext = context?.dataVisualization ?? {};
|
||||||
|
const timeFormatter = openmct.telemetry.getFormatter('iso');
|
||||||
|
|
||||||
|
return {
|
||||||
|
show(element) {
|
||||||
|
const { destroy } = mount(
|
||||||
|
{
|
||||||
|
components: {
|
||||||
|
InspectorDataVisualization: InspectorDataVisualizationComponent
|
||||||
|
},
|
||||||
|
provide: {
|
||||||
|
openmct,
|
||||||
|
domainObject,
|
||||||
|
timeFormatter,
|
||||||
|
placeholderText,
|
||||||
|
plotOptions,
|
||||||
|
imageryOptions
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
context: dataVisualizationContext
|
||||||
|
};
|
||||||
|
},
|
||||||
|
template: `<InspectorDataVisualization :context="context" />`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
app: openmct.app,
|
||||||
|
element
|
||||||
|
}
|
||||||
|
);
|
||||||
|
_destroy = destroy;
|
||||||
|
},
|
||||||
|
destroy() {
|
||||||
|
if (_destroy) {
|
||||||
|
_destroy();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
priority() {
|
||||||
|
return openmct.priority.HIGH;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
165
src/plugins/inspectorDataVisualization/NumericData.vue
Normal file
165
src/plugins/inspectorDataVisualization/NumericData.vue
Normal file
@ -0,0 +1,165 @@
|
|||||||
|
<!--
|
||||||
|
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-inspector__numeric-data">
|
||||||
|
<div class="c-inspect-properties">
|
||||||
|
<div class="c-inspect-properties__header">Numeric Data</div>
|
||||||
|
</div>
|
||||||
|
<div ref="numericDataView"></div>
|
||||||
|
|
||||||
|
<div v-if="!hasNumericData">
|
||||||
|
{{ noNumericDataText }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<script>
|
||||||
|
import mount from 'utils/mount';
|
||||||
|
import TelemetryFrame from './TelemetryFrame.vue';
|
||||||
|
import Plot from '../plot/Plot.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
inject: ['openmct', 'domainObject', 'timeFormatter'],
|
||||||
|
props: {
|
||||||
|
bounds: {
|
||||||
|
type: Object,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
|
telemetryKeys: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
},
|
||||||
|
noNumericDataText: {
|
||||||
|
type: String,
|
||||||
|
default: 'No Numeric Data to display.'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
plotObjects: []
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
hasNumericData() {
|
||||||
|
return this.plotObjects.length > 0;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
watch: {
|
||||||
|
telemetryKeys: {
|
||||||
|
handler() {
|
||||||
|
this.renderNumericData();
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
},
|
||||||
|
bounds: {
|
||||||
|
handler() {
|
||||||
|
this.renderNumericData();
|
||||||
|
},
|
||||||
|
deep: true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.renderNumericData();
|
||||||
|
},
|
||||||
|
beforeUnmount() {
|
||||||
|
this.clearPlots();
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
renderNumericData() {
|
||||||
|
this.clearPlots();
|
||||||
|
|
||||||
|
this.unregisterTimeContextList = [];
|
||||||
|
this.elementsList = [];
|
||||||
|
this.componentsList = [];
|
||||||
|
|
||||||
|
this.telemetryKeys.forEach(async (telemetryKey) => {
|
||||||
|
const plotObject = await this.openmct.objects.get(telemetryKey);
|
||||||
|
|
||||||
|
this.plotObjects.push(plotObject);
|
||||||
|
this.unregisterTimeContextList.push(this.setIndependentTimeContextForComponent(plotObject));
|
||||||
|
this.renderPlot(plotObject);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
setIndependentTimeContextForComponent(plotObject) {
|
||||||
|
const keyString = this.openmct.objects.makeKeyString(plotObject.identifier);
|
||||||
|
|
||||||
|
// get an independent time context for object
|
||||||
|
this.openmct.time.getContextForView([plotObject]);
|
||||||
|
// set the time context of the object to the selected time range
|
||||||
|
return this.openmct.time.addIndependentContext(keyString, this.bounds);
|
||||||
|
},
|
||||||
|
renderPlot(plotObject) {
|
||||||
|
const { vNode, destroy } = mount(
|
||||||
|
{
|
||||||
|
components: {
|
||||||
|
TelemetryFrame,
|
||||||
|
Plot
|
||||||
|
},
|
||||||
|
provide: {
|
||||||
|
openmct: this.openmct,
|
||||||
|
path: [plotObject]
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
plotObject,
|
||||||
|
bounds: this.bounds
|
||||||
|
};
|
||||||
|
},
|
||||||
|
template: `<TelemetryFrame
|
||||||
|
:bounds="bounds"
|
||||||
|
:telemetry-object="plotObject"
|
||||||
|
>
|
||||||
|
<Plot />
|
||||||
|
</TelemetryFrame>`
|
||||||
|
},
|
||||||
|
{
|
||||||
|
app: this.openmct.app
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
this.componentsList.push(destroy);
|
||||||
|
this.elementsList.push(vNode.el);
|
||||||
|
this.$refs.numericDataView.append(vNode.el);
|
||||||
|
},
|
||||||
|
clearPlots() {
|
||||||
|
if (this.componentsList?.length) {
|
||||||
|
this.componentsList.forEach((destroy) => destroy());
|
||||||
|
delete this.componentsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.elementsList?.length) {
|
||||||
|
this.elementsList.forEach((element) => element.remove());
|
||||||
|
delete this.elementsList;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.plotObjects?.length) {
|
||||||
|
this.plotObjects = [];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.unregisterTimeContextList?.length) {
|
||||||
|
this.unregisterTimeContextList.forEach((unregisterTimeContext) => unregisterTimeContext());
|
||||||
|
delete this.unregisterTimeContextList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
124
src/plugins/inspectorDataVisualization/TelemetryFrame.vue
Normal file
124
src/plugins/inspectorDataVisualization/TelemetryFrame.vue
Normal file
@ -0,0 +1,124 @@
|
|||||||
|
<!--
|
||||||
|
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-telemetry-frame">
|
||||||
|
<div class="c-telemetry-frame__title-bar">
|
||||||
|
<span class="c-telemetry-frame__title">
|
||||||
|
<span class="c-telemetry-frame__title-icon icon-telemetry"></span>
|
||||||
|
<span class="title-text">{{ telemetryObject.name }}</span>
|
||||||
|
</span>
|
||||||
|
<button
|
||||||
|
ref="menu-button"
|
||||||
|
title="More options"
|
||||||
|
class="l-browse-bar__actions c-icon-button icon-3-dots"
|
||||||
|
@click="toggleMenu"
|
||||||
|
></button>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="showMenu"
|
||||||
|
class="c-menu c-menu__inspector-telemetry-options"
|
||||||
|
aria-label="Telemetry Options"
|
||||||
|
@blur="showMenu = false"
|
||||||
|
>
|
||||||
|
<ul>
|
||||||
|
<li
|
||||||
|
v-if="telemetryObject.type === 'yamcs.telemetry'"
|
||||||
|
role="menuitem"
|
||||||
|
title="View Full Screen"
|
||||||
|
class="icon-eye-open"
|
||||||
|
@click="previewTelemetry"
|
||||||
|
>
|
||||||
|
View Full Screen
|
||||||
|
</li>
|
||||||
|
<li
|
||||||
|
role="menuitem"
|
||||||
|
title="Open in a new browser tab"
|
||||||
|
class="icon-new-window"
|
||||||
|
@click="openInNewTab"
|
||||||
|
>
|
||||||
|
Open In New Tab
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
inject: ['openmct'],
|
||||||
|
provide() {
|
||||||
|
return {
|
||||||
|
domainObject: this.telemetryObject
|
||||||
|
};
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
bounds: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
},
|
||||||
|
telemetryObject: {
|
||||||
|
type: Object,
|
||||||
|
default: () => {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
showMenu: false
|
||||||
|
};
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
toggleMenu() {
|
||||||
|
this.showMenu = !this.showMenu;
|
||||||
|
},
|
||||||
|
async getTelemetryPath() {
|
||||||
|
let sourceTelem;
|
||||||
|
if (this.telemetryObject.type === 'yamcs.telemetry') {
|
||||||
|
sourceTelem = this.openmct.objects.makeKeyString(this.telemetryObject.identifier);
|
||||||
|
} else if (this.telemetryObject.type === 'yamcs.image') {
|
||||||
|
sourceTelem = this.openmct.objects.makeKeyString(this.telemetryObject.identifier);
|
||||||
|
}
|
||||||
|
const telemetryPath = await this.openmct.objects.getOriginalPath(sourceTelem);
|
||||||
|
return telemetryPath;
|
||||||
|
},
|
||||||
|
async openInNewTab() {
|
||||||
|
const telemetryPath = await this.getTelemetryPath();
|
||||||
|
const sourceTelemObject = telemetryPath[0];
|
||||||
|
const timeBounds = this.bounds;
|
||||||
|
const urlParams = {
|
||||||
|
'tc.startBound': timeBounds?.start,
|
||||||
|
'tc.endBound': timeBounds?.end,
|
||||||
|
'tc.mode': 'fixed'
|
||||||
|
};
|
||||||
|
const newTabAction = this.openmct.actions.getAction('newTab');
|
||||||
|
newTabAction.invoke([sourceTelemObject], urlParams);
|
||||||
|
this.showMenu = false;
|
||||||
|
},
|
||||||
|
previewTelemetry() {
|
||||||
|
const previewAction = this.openmct.actions.getAction('preview');
|
||||||
|
previewAction.invoke([this.telemetryObject]);
|
||||||
|
this.showMenu = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
</script>
|
@ -0,0 +1,128 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
//InspectorDataVisualizationComponent
|
||||||
|
.c-data-visualization-inspector__flex-column {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-data-visualization-inspector__flex-row {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-data-visualization-inspect-properties + .c-data-visualization-inspect-properties {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DataVisualization
|
||||||
|
.c-inspector__data-pivot-placeholder {
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-inspector__data-pivot-coordinates-wrapper {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-inspector__data-pivot-coordinates {
|
||||||
|
margin-left: 6px;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-inspector__data-pivot-range-selector {
|
||||||
|
margin: 10px auto;
|
||||||
|
height: 25px;
|
||||||
|
max-width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-inspector__imagery-view {
|
||||||
|
margin-top: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-imagery-view__camera-image-set {
|
||||||
|
grid-column: 1/3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-imagery-view__camera-image-list {
|
||||||
|
display: grid;
|
||||||
|
grid-auto-flow: column;
|
||||||
|
grid-gap: 10px;
|
||||||
|
grid-auto-columns: min-content;
|
||||||
|
overflow: auto;
|
||||||
|
white-space: nowrap;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-imagery-view__camera-image {
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-imagery-view__camera-image img {
|
||||||
|
width: 70px;
|
||||||
|
height: 70px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-imagery-view__camera-image-timestamp {
|
||||||
|
white-space: break-spaces;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Telemetry Frame
|
||||||
|
.c-telemetry-frame {
|
||||||
|
margin: 8px 0px;
|
||||||
|
|
||||||
|
&__title-bar {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
margin: 6px 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title {
|
||||||
|
flex: 1;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
&__title-icon {
|
||||||
|
margin-right: 4px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-telemetry-frame .c-menu {
|
||||||
|
position: absolute;
|
||||||
|
right: 0px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-inspector__data-pivot .c-plot {
|
||||||
|
position: relative;
|
||||||
|
min-height: 150px;
|
||||||
|
max-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-inspector__data-pivot .c-plot .c-plot--stacked-container {
|
||||||
|
min-height: 150px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.c-inspector__numeric-data .c-inspect-properties__header {
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
31
src/plugins/inspectorDataVisualization/plugin.js
Normal file
31
src/plugins/inspectorDataVisualization/plugin.js
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
import InspectorDataVisualizationViewProvider from './InspectorDataVisualizationViewProvider';
|
||||||
|
|
||||||
|
export default function (options) {
|
||||||
|
return function (openmct) {
|
||||||
|
openmct.inspectorViews.addProvider(
|
||||||
|
new InspectorDataVisualizationViewProvider(openmct, options)
|
||||||
|
);
|
||||||
|
};
|
||||||
|
}
|
@ -83,7 +83,8 @@ define([
|
|||||||
'./timelist/plugin',
|
'./timelist/plugin',
|
||||||
'./faultManagement/FaultManagementPlugin',
|
'./faultManagement/FaultManagementPlugin',
|
||||||
'../../example/exampleTags/plugin',
|
'../../example/exampleTags/plugin',
|
||||||
'./inspectorViews/plugin'
|
'./inspectorViews/plugin',
|
||||||
|
'./inspectorDataVisualization/plugin'
|
||||||
], function (
|
], function (
|
||||||
_,
|
_,
|
||||||
UTCTimeSystem,
|
UTCTimeSystem,
|
||||||
@ -147,7 +148,8 @@ define([
|
|||||||
TimeList,
|
TimeList,
|
||||||
FaultManagementPlugin,
|
FaultManagementPlugin,
|
||||||
ExampleTags,
|
ExampleTags,
|
||||||
InspectorViews
|
InspectorViews,
|
||||||
|
InspectorDataVisualization
|
||||||
) {
|
) {
|
||||||
const plugins = {};
|
const plugins = {};
|
||||||
|
|
||||||
@ -232,6 +234,7 @@ define([
|
|||||||
plugins.Gauge = GaugePlugin.default;
|
plugins.Gauge = GaugePlugin.default;
|
||||||
plugins.Timelist = TimeList.default;
|
plugins.Timelist = TimeList.default;
|
||||||
plugins.InspectorViews = InspectorViews.default;
|
plugins.InspectorViews = InspectorViews.default;
|
||||||
|
plugins.InspectorDataVisualization = InspectorDataVisualization.default;
|
||||||
|
|
||||||
return plugins;
|
return plugins;
|
||||||
});
|
});
|
||||||
|
@ -58,6 +58,7 @@
|
|||||||
@import '../plugins/gauge/gauge.scss';
|
@import '../plugins/gauge/gauge.scss';
|
||||||
@import '../plugins/faultManagement/fault-manager.scss';
|
@import '../plugins/faultManagement/fault-manager.scss';
|
||||||
@import '../plugins/operatorStatus/operator-status';
|
@import '../plugins/operatorStatus/operator-status';
|
||||||
|
@import '../plugins/inspectorDataVisualization/inspector-data-visualization.scss';
|
||||||
|
|
||||||
#splash-screen {
|
#splash-screen {
|
||||||
display: none;
|
display: none;
|
||||||
|
Loading…
Reference in New Issue
Block a user