mirror of
https://github.com/nasa/openmct.git
synced 2025-01-31 08:25:31 +00:00
Refactor plot actions to save space (#5201)
* Move image export actions to 3-dot menu * Move cursor guide and toggle grid lines to local controls for plots (on hover) * toggle cursor and gridlines affect all plots in a stacked plot * Fix tests * Better message when exporting plots, fixed typo Co-authored-by: Joe Pea <trusktr@gmail.com> Co-authored-by: Charles Hacskaylo <charlesh88@gmail.com>
This commit is contained in:
parent
1ca5271c3e
commit
48916564e4
@ -51,7 +51,7 @@ class ImageExporter {
|
||||
const overlays = this.openmct.overlays;
|
||||
const dialog = overlays.dialog({
|
||||
iconClass: 'info',
|
||||
message: 'Caputuring an image',
|
||||
message: 'Capturing image, please wait...',
|
||||
buttons: [
|
||||
{
|
||||
label: 'Cancel',
|
||||
|
@ -154,6 +154,22 @@
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
<div class="c-button-set c-button-set--strip-h">
|
||||
<button
|
||||
class="c-button icon-crosshair"
|
||||
:class="{ 'is-active': cursorGuide }"
|
||||
title="Toggle cursor guides"
|
||||
@click="toggleCursorGuide"
|
||||
>
|
||||
</button>
|
||||
<button
|
||||
class="c-button"
|
||||
:class="{ 'icon-grid-on': gridLines, 'icon-grid-off': !gridLines }"
|
||||
title="Toggle grid lines"
|
||||
@click="toggleGridLines"
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--Cursor guides-->
|
||||
@ -213,16 +229,16 @@ export default {
|
||||
};
|
||||
}
|
||||
},
|
||||
gridLines: {
|
||||
initGridLines: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
}
|
||||
},
|
||||
cursorGuide: {
|
||||
initCursorGuide: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
},
|
||||
plotTickWidth: {
|
||||
@ -252,7 +268,9 @@ export default {
|
||||
isTimeOutOfSync: false,
|
||||
showLimitLineLabels: undefined,
|
||||
isFrozenOnMouseDown: false,
|
||||
hasSameRangeValue: true
|
||||
hasSameRangeValue: true,
|
||||
cursorGuide: this.initCursorGuide,
|
||||
gridLines: this.initGridLines
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
@ -273,6 +291,14 @@ export default {
|
||||
return this.plotTickWidth || this.tickWidth;
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
initGridLines(newGridLines) {
|
||||
this.gridLines = newGridLines;
|
||||
},
|
||||
initCursorGuide(newCursorGuide) {
|
||||
this.cursorGuide = newCursorGuide;
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
document.addEventListener('keydown', this.handleKeyDown);
|
||||
document.addEventListener('keyup', this.handleKeyUp);
|
||||
@ -1130,6 +1156,14 @@ export default {
|
||||
},
|
||||
legendHoverChanged(data) {
|
||||
this.showLimitLineLabels = data;
|
||||
},
|
||||
toggleCursorGuide() {
|
||||
this.cursorGuide = !this.cursorGuide;
|
||||
this.$emit('cursorGuide', this.cursorGuide);
|
||||
},
|
||||
toggleGridLines() {
|
||||
this.gridLines = !this.gridLines;
|
||||
this.$emit('gridLines', this.gridLines);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -24,41 +24,6 @@
|
||||
ref="plotWrapper"
|
||||
class="c-plot holder holder-plot has-control-bar"
|
||||
>
|
||||
<div
|
||||
v-if="!options.compact"
|
||||
class="c-control-bar"
|
||||
>
|
||||
<span class="c-button-set c-button-set--strip-h">
|
||||
<button
|
||||
class="c-button icon-download"
|
||||
title="Export This View's Data as PNG"
|
||||
@click="exportPNG()"
|
||||
>
|
||||
<span class="c-button__label">PNG</span>
|
||||
</button>
|
||||
<button
|
||||
class="c-button"
|
||||
title="Export This View's Data as JPG"
|
||||
@click="exportJPG()"
|
||||
>
|
||||
<span class="c-button__label">JPG</span>
|
||||
</button>
|
||||
</span>
|
||||
<button
|
||||
class="c-button icon-crosshair"
|
||||
:class="{ 'is-active': cursorGuide }"
|
||||
title="Toggle cursor guides"
|
||||
@click="toggleCursorGuide"
|
||||
>
|
||||
</button>
|
||||
<button
|
||||
class="c-button"
|
||||
:class="{ 'icon-grid-on': gridLines, 'icon-grid-off': !gridLines }"
|
||||
title="Toggle grid lines"
|
||||
@click="toggleGridLines"
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div
|
||||
ref="plotContainer"
|
||||
@ -70,8 +35,8 @@
|
||||
class="c-loading--overlay loading"
|
||||
></div>
|
||||
<mct-plot
|
||||
:grid-lines="gridLines"
|
||||
:cursor-guide="cursorGuide"
|
||||
:init-grid-lines="gridLines"
|
||||
:init-cursor-guide="cursorGuide"
|
||||
:options="options"
|
||||
@loadingUpdated="loadingUpdated"
|
||||
@statusUpdated="setStatus"
|
||||
@ -135,15 +100,14 @@ export default {
|
||||
this.imageExporter.exportPNG(plotElement, 'plot.png', 'export-plot');
|
||||
},
|
||||
|
||||
toggleCursorGuide() {
|
||||
this.cursorGuide = !this.cursorGuide;
|
||||
},
|
||||
|
||||
toggleGridLines() {
|
||||
this.gridLines = !this.gridLines;
|
||||
},
|
||||
setStatus(status) {
|
||||
this.status = status;
|
||||
},
|
||||
getViewContext() {
|
||||
return {
|
||||
exportPNG: this.exportPNG,
|
||||
exportJPG: this.exportJPG
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -80,9 +80,16 @@ export default function PlotViewProvider(openmct) {
|
||||
}
|
||||
};
|
||||
},
|
||||
template: '<plot :options="options"></plot>'
|
||||
template: '<plot ref="plotComponent" :options="options"></plot>'
|
||||
});
|
||||
},
|
||||
getViewContext() {
|
||||
if (!component) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return component.$refs.plotComponent.getViewContext();
|
||||
},
|
||||
destroy: function () {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
|
57
src/plugins/plot/actions/ViewActions.js
Normal file
57
src/plugins/plot/actions/ViewActions.js
Normal file
@ -0,0 +1,57 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT, Copyright (c) 2014-2022, 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 {isPlotView} from "@/plugins/plot/actions/utils";
|
||||
|
||||
const exportPNG = {
|
||||
name: 'Export as PNG',
|
||||
key: 'export-as-png',
|
||||
description: 'Export This View\'s Data as PNG',
|
||||
cssClass: 'c-icon-button icon-download',
|
||||
group: 'view',
|
||||
invoke(objectPath, view) {
|
||||
view.getViewContext().exportPNG();
|
||||
}
|
||||
};
|
||||
|
||||
const exportJPG = {
|
||||
name: 'Export as JPG',
|
||||
key: 'export-as-jpg',
|
||||
description: 'Export This View\'s Data as JPG',
|
||||
cssClass: 'c-icon-button icon-download',
|
||||
group: 'view',
|
||||
invoke(objectPath, view) {
|
||||
view.getViewContext().exportJPG();
|
||||
}
|
||||
};
|
||||
|
||||
const viewActions = [
|
||||
exportPNG,
|
||||
exportJPG
|
||||
];
|
||||
|
||||
viewActions.forEach(action => {
|
||||
action.appliesTo = (objectPath, view = {}) => {
|
||||
return isPlotView(view);
|
||||
};
|
||||
});
|
||||
|
||||
export default viewActions;
|
3
src/plugins/plot/actions/utils.js
Normal file
3
src/plugins/plot/actions/utils.js
Normal file
@ -0,0 +1,3 @@
|
||||
export function isPlotView(view) {
|
||||
return view.key === 'plot-single' || view.key === 'plot-overlay' || view.key === 'plot-stacked';
|
||||
}
|
@ -65,9 +65,16 @@ export default function OverlayPlotViewProvider(openmct) {
|
||||
}
|
||||
};
|
||||
},
|
||||
template: '<plot :options="options"></plot>'
|
||||
template: '<plot ref="plotComponent" :options="options"></plot>'
|
||||
});
|
||||
},
|
||||
getViewContext() {
|
||||
if (!component) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return component.$refs.plotComponent.getViewContext();
|
||||
},
|
||||
destroy: function () {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
|
@ -25,6 +25,7 @@ import StackedPlotViewProvider from './stackedPlot/StackedPlotViewProvider';
|
||||
import PlotsInspectorViewProvider from './inspector/PlotsInspectorViewProvider';
|
||||
import OverlayPlotCompositionPolicy from './overlayPlot/OverlayPlotCompositionPolicy';
|
||||
import StackedPlotCompositionPolicy from './stackedPlot/StackedPlotCompositionPolicy';
|
||||
import PlotViewActions from "./actions/ViewActions";
|
||||
|
||||
export default function () {
|
||||
return function install(openmct) {
|
||||
@ -67,6 +68,9 @@ export default function () {
|
||||
|
||||
openmct.composition.addPolicy(new OverlayPlotCompositionPolicy(openmct).allow);
|
||||
openmct.composition.addPolicy(new StackedPlotCompositionPolicy(openmct).allow);
|
||||
|
||||
PlotViewActions.forEach(action => {
|
||||
openmct.actions.register(action);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -724,16 +724,16 @@ describe("the plugin", function () {
|
||||
});
|
||||
|
||||
it("turns on cursor Guides all telemetry objects", (done) => {
|
||||
expect(plotViewComponentObject.cursorGuide).toBeFalse();
|
||||
plotViewComponentObject.toggleCursorGuide();
|
||||
expect(plotViewComponentObject.$children[0].cursorGuide).toBeFalse();
|
||||
plotViewComponentObject.$children[0].cursorGuide = true;
|
||||
Vue.nextTick(() => {
|
||||
expect(plotViewComponentObject.$children[0].component.$children[0].cursorGuide).toBeTrue();
|
||||
expect(plotViewComponentObject.$children[0].cursorGuide).toBeTrue();
|
||||
done();
|
||||
});
|
||||
});
|
||||
|
||||
it("shows grid lines for all telemetry objects", () => {
|
||||
expect(plotViewComponentObject.gridLines).toBeTrue();
|
||||
expect(plotViewComponentObject.$children[0].gridLines).toBeTrue();
|
||||
let gridLinesContainer = element.querySelectorAll(".gl-plot-display-area .js-ticks");
|
||||
let visible = 0;
|
||||
gridLinesContainer.forEach(el => {
|
||||
@ -745,10 +745,10 @@ describe("the plugin", function () {
|
||||
});
|
||||
|
||||
it("hides grid lines for all telemetry objects", (done) => {
|
||||
expect(plotViewComponentObject.gridLines).toBeTrue();
|
||||
plotViewComponentObject.toggleGridLines();
|
||||
expect(plotViewComponentObject.$children[0].gridLines).toBeTrue();
|
||||
plotViewComponentObject.$children[0].gridLines = false;
|
||||
Vue.nextTick(() => {
|
||||
expect(plotViewComponentObject.gridLines).toBeFalse();
|
||||
expect(plotViewComponentObject.$children[0].gridLines).toBeFalse();
|
||||
let gridLinesContainer = element.querySelectorAll(".gl-plot-display-area .js-ticks");
|
||||
let visible = 0;
|
||||
gridLinesContainer.forEach(el => {
|
||||
|
@ -22,41 +22,6 @@
|
||||
|
||||
<template>
|
||||
<div class="c-plot c-plot--stacked holder holder-plot has-control-bar">
|
||||
<div
|
||||
v-show="!hideExportButtons && !options.compact"
|
||||
class="c-control-bar"
|
||||
>
|
||||
<span class="c-button-set c-button-set--strip-h">
|
||||
<button
|
||||
class="c-button icon-download"
|
||||
title="Export This View's Data as PNG"
|
||||
@click="exportPNG()"
|
||||
>
|
||||
<span class="c-button__label">PNG</span>
|
||||
</button>
|
||||
<button
|
||||
class="c-button"
|
||||
title="Export This View's Data as JPG"
|
||||
@click="exportJPG()"
|
||||
>
|
||||
<span class="c-button__label">JPG</span>
|
||||
</button>
|
||||
</span>
|
||||
<button
|
||||
class="c-button icon-crosshair"
|
||||
:class="{ 'is-active': cursorGuide }"
|
||||
title="Toggle cursor guides"
|
||||
@click="toggleCursorGuide"
|
||||
>
|
||||
</button>
|
||||
<button
|
||||
class="c-button"
|
||||
:class="{ 'icon-grid-on': gridLines, 'icon-grid-off': !gridLines }"
|
||||
title="Toggle grid lines"
|
||||
@click="toggleGridLines"
|
||||
>
|
||||
</button>
|
||||
</div>
|
||||
<div class="l-view-section">
|
||||
<stacked-plot-item
|
||||
v-for="object in compositionObjects"
|
||||
@ -69,6 +34,8 @@
|
||||
:plot-tick-width="maxTickWidth"
|
||||
@plotTickWidth="onTickWidthChange"
|
||||
@loadingUpdated="loadingUpdated"
|
||||
@cursorGuide="onCursorGuideChange"
|
||||
@gridLines="onGridLinesChange"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
@ -184,20 +151,24 @@ export default {
|
||||
this.hideExportButtons = false;
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
toggleCursorGuide() {
|
||||
this.cursorGuide = !this.cursorGuide;
|
||||
},
|
||||
|
||||
toggleGridLines() {
|
||||
this.gridLines = !this.gridLines;
|
||||
},
|
||||
onTickWidthChange(width, plotId) {
|
||||
if (!Object.prototype.hasOwnProperty.call(this.tickWidthMap, plotId)) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.$set(this.tickWidthMap, plotId, width);
|
||||
},
|
||||
onCursorGuideChange(cursorGuide) {
|
||||
this.cursorGuide = cursorGuide === true;
|
||||
},
|
||||
onGridLinesChange(gridLines) {
|
||||
this.gridLines = gridLines === true;
|
||||
},
|
||||
getViewContext() {
|
||||
return {
|
||||
exportPNG: this.exportPNG,
|
||||
exportJPG: this.exportJPG
|
||||
};
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -96,6 +96,8 @@ export default {
|
||||
}
|
||||
|
||||
const onTickWidthChange = this.onTickWidthChange;
|
||||
const onCursorGuideChange = this.onCursorGuideChange;
|
||||
const onGridLinesChange = this.onGridLinesChange;
|
||||
const loadingUpdated = this.loadingUpdated;
|
||||
const setStatus = this.setStatus;
|
||||
|
||||
@ -121,16 +123,24 @@ export default {
|
||||
return {
|
||||
...getProps(),
|
||||
onTickWidthChange,
|
||||
onCursorGuideChange,
|
||||
onGridLinesChange,
|
||||
loadingUpdated,
|
||||
setStatus
|
||||
};
|
||||
},
|
||||
template: '<div ref="plotWrapper" class="l-view-section u-style-receiver js-style-receiver" :class="{\'s-status-timeconductor-unsynced\': status && status === \'timeconductor-unsynced\'}"><div v-show="!!loading" class="c-loading--overlay loading"></div><mct-plot :grid-lines="gridLines" :cursor-guide="cursorGuide" :plot-tick-width="plotTickWidth" :options="options" @plotTickWidth="onTickWidthChange" @statusUpdated="setStatus" @loadingUpdated="loadingUpdated"/></div>'
|
||||
template: '<div ref="plotWrapper" class="l-view-section u-style-receiver js-style-receiver" :class="{\'s-status-timeconductor-unsynced\': status && status === \'timeconductor-unsynced\'}"><div v-show="!!loading" class="c-loading--overlay loading"></div><mct-plot :init-grid-lines="gridLines" :init-cursor-guide="cursorGuide" :plot-tick-width="plotTickWidth" :options="options" @plotTickWidth="onTickWidthChange" @cursorGuide="onCursorGuideChange" @gridLines="onGridLinesChange" @statusUpdated="setStatus" @loadingUpdated="loadingUpdated"/></div>'
|
||||
});
|
||||
},
|
||||
onTickWidthChange() {
|
||||
this.$emit('plotTickWidth', ...arguments);
|
||||
},
|
||||
onCursorGuideChange() {
|
||||
this.$emit('cursorGuide', ...arguments);
|
||||
},
|
||||
onGridLinesChange() {
|
||||
this.$emit('gridLines', ...arguments);
|
||||
},
|
||||
setStatus(status) {
|
||||
this.status = status;
|
||||
this.updateComponentProp('status', status);
|
||||
|
@ -67,9 +67,16 @@ export default function StackedPlotViewProvider(openmct) {
|
||||
}
|
||||
};
|
||||
},
|
||||
template: '<stacked-plot :options="options"></stacked-plot>'
|
||||
template: '<stacked-plot ref="plotComponent" :options="options"></stacked-plot>'
|
||||
});
|
||||
},
|
||||
getViewContext() {
|
||||
if (!component) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return component.$refs.plotComponent.getViewContext();
|
||||
},
|
||||
destroy: function () {
|
||||
component.$destroy();
|
||||
component = undefined;
|
||||
|
Loading…
x
Reference in New Issue
Block a user