Fix cabana graphs and upgrade react-vega (#22)

* Fix cabana graphs by upgrading react-vega

* Fix test cases

* Ensure tests on prs

* Remove actions menu from graphs
main
Chris Vickery 2019-09-25 15:31:59 -07:00 committed by GitHub
parent ef3ba96f18
commit 3eed6ea06c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 1093 additions and 359 deletions

View File

@ -2,6 +2,9 @@
trigger:
- master
pr:
- master
pool:
vmImage: 'ubuntu-latest'

View File

@ -46,19 +46,21 @@
"react-infinite": "^0.11.0",
"react-list": "^0.8.6",
"react-measure": "^2.0.2",
"react-scripts": "1.0.17",
"react-scripts": "^1.1.2",
"react-test-renderer": "^16.2.0",
"react-vega": "^3.0.0",
"react-vega": "^7.0.0",
"react-visibility-sensor": "^3.10.1",
"right-pad": "^1.0.1",
"simple-statistics": "^4.1.0",
"socket.io-client": "^2.0.3",
"stream-selector": "^0.1.1",
"streamsaver": "^1.0.1",
"vega": "3.0.10",
"vega": "^5.3.4",
"vega-lite": "^3.0.0",
"vega-tooltip": "^0.4.0"
},
"devDependencies": {
"@babel/plugin-transform-regenerator": "^7.4.5",
"connect-history-api-fallback": "1.3.0",
"cross-spawn": "4.0.2",
"detect-port": "1.1.0",

View File

@ -2,10 +2,11 @@ import React, { Component } from "react";
import Measure from "react-measure";
import PropTypes from "prop-types";
import cx from "classnames";
import { Vega } from "react-vega";
import Signal from "../models/can/signal";
import GraphData from "../models/graph-data";
import CanPlot from "../vega/CanPlot";
import CanPlotSpec from "../vega/CanPlot";
import debounce from "../utils/debounce";
const DefaultPlotInnerStyle = {
@ -106,19 +107,27 @@ export default class CanGraph extends Component {
}
onPlotResize({ bounds }) {
this.setState({ bounds });
if (bounds) {
this.setState({ bounds });
} else {
bounds = this.state.bounds;
}
if (!this.view) {
console.log("Cannot bounds");
return;
}
this.view.signal("width", bounds.width - 70);
this.view.signal("height", 0.4 * (bounds.width - 70)); // 5:2 aspect ratio
this.view.run();
}
shouldComponentUpdate(nextProps, nextState) {
componentWillUpdate(nextProps, nextState) {
if (this.view) {
let segmentChanged = this.segmentIsNew(nextProps.segment);
this.view.runAfter(() => {
// only update if segment is new
let segmentChanged = false;
if (this.segmentIsNew(nextProps.segment)) {
if (segmentChanged) {
if (nextProps.segment.length > 0) {
// Set segmented domain
this.view.signal("segment", nextProps.segment);
@ -141,14 +150,17 @@ export default class CanGraph extends Component {
this.view.runAsync();
}
});
return false;
}
return true;
}
insertData = debounce(() => {
if (!this.view) {
console.log("Cannot insertData");
return;
}
let { series } = this.state.data;
// adding plot points by diff isn't faster since it basically has to be n^2
@ -198,7 +210,7 @@ export default class CanGraph extends Component {
this.view = view;
if (this.state.bounds) {
this.onPlotResize({ bounds: this.state.bounds });
this.onPlotResize();
}
if (this.props.segment.length > 0) {
view.signal("segment", this.props.segment);
@ -220,6 +232,11 @@ export default class CanGraph extends Component {
this.props.onSegmentChanged(this.props.messageId, segment);
if (!this.view) {
console.log("Cannot insertData");
return;
}
this.view.runAfter(() => {
const state = this.view.getState();
state.subcontext[0].signals.brush = 0;
@ -336,12 +353,19 @@ export default class CanGraph extends Component {
ref={measureRef}
className="cabana-explorer-visuals-plot-container"
>
<CanPlot
logLevel={1}
<Vega
onNewView={this.onNewView}
onSignalClickTime={this.onSignalClickTime}
onSignalSegment={this.onSignalSegment}
logLevel={1}
signalListeners={{
clickTime: this.onSignalClickTime,
segment: this.onSignalSegment
}}
renderer={"canvas"}
spec={CanPlotSpec}
actions={false}
data={{
values: this.state.data.series
}}
/>
</div>
);

View File

@ -11,7 +11,6 @@ import Entries from "../models/can/entries";
import debounce from "../utils/debounce";
import PartSelector from "./PartSelector";
import PlaySpeedSelector from "./PlaySpeedSelector";
import GraphData from "../models/graph-data";
export default class Explorer extends Component {
static propTypes = {
@ -33,7 +32,6 @@ export default class Explorer extends Component {
this.state = {
plottedSignals: [],
graphData: [],
segment: [],
segmentIndices: [],
shouldShowAddSignal: true,
@ -56,7 +54,6 @@ export default class Explorer extends Component {
this.onSignalPlotChange = this.onSignalPlotChange.bind(this);
this._onKeyDown = this._onKeyDown.bind(this);
this.mergePlots = this.mergePlots.bind(this);
this.refreshGraphData = this.refreshGraphData.bind(this);
this.toggleShouldShowAddSignal = this.toggleShouldShowAddSignal.bind(this);
this.changePlaySpeed = this.changePlaySpeed.bind(this);
}
@ -107,7 +104,7 @@ export default class Explorer extends Component {
componentWillReceiveProps(nextProps) {
const nextMessage = nextProps.messages[nextProps.selectedMessage];
const curMessage = this.props.messages[this.props.selectedMessage];
let { plottedSignals, graphData } = this.state;
let { plottedSignals } = this.state;
if (Object.keys(nextProps.messages).length === 0) {
this.resetSegment();
@ -183,43 +180,6 @@ export default class Explorer extends Component {
);
this.setState({ segment, segmentIndices });
}
const partsDidChange =
JSON.stringify(nextProps.currentParts) !==
JSON.stringify(this.props.currentParts);
if (plottedSignals.length > 0) {
if (graphData.length !== plottedSignals.length || partsDidChange) {
this.refreshGraphData(nextProps.messages, plottedSignals);
} else if (graphData.length === plottedSignals.length) {
if (
plottedSignals.some(plot =>
plot.some(({ messageId, signalUid }) => {
/* const signalName = Object.values(
* this.props.messages[messageId].frame.signals
* ).find(s => s.uid === signalUid);
*/
return (
nextProps.messages[messageId].entries.length > 0 &&
this.props.messages[messageId].entries.length > 0 &&
nextProps.messages[messageId].entries[0].updated !==
this.props.messages[messageId].entries[0].updated
);
})
)
) {
this.refreshGraphData(nextProps.messages, plottedSignals);
} else {
graphData = GraphData.appendNewGraphData(
plottedSignals,
graphData,
nextProps.messages,
nextProps.firstCanTime
);
this.setState({ graphData });
}
}
}
}
changePlaySpeed(value) {
@ -248,56 +208,12 @@ export default class Explorer extends Component {
} else return "";
}
sortGraphData(graphData) {
return graphData.sort((entry1, entry2) => {
if (entry1.relTime < entry2.relTime) {
return -1;
} else if (entry1.relTime > entry2.relTime) {
return 1;
} else {
return 0;
}
});
}
calcGraphData(plottedSignals, messages) {
const { firstCanTime } = this.props;
if (typeof messages === "undefined") {
messages = this.props.messages;
}
const series = this.sortGraphData(
plottedSignals
.map(({ messageId, signalUid }) =>
GraphData._calcGraphData(messages[messageId], signalUid, firstCanTime)
)
.reduce((combined, signalData) => combined.concat(signalData), [])
);
return { series, updated: Date.now() };
}
onSignalPlotPressed(messageId, signalUid) {
let { plottedSignals, graphData } = this.state;
let { plottedSignals } = this.state;
graphData = [this.calcGraphData([{ messageId, signalUid }]), ...graphData];
plottedSignals = [[{ messageId, signalUid }], ...plottedSignals];
this.setState({ plottedSignals, graphData });
}
refreshGraphData(messages, plottedSignals) {
if (typeof messages === "undefined") {
messages = this.props.messages;
}
if (typeof plottedSignals === "undefined") {
plottedSignals = this.state.plottedSignals;
}
let graphData = plottedSignals.map((plotSignals, index) =>
this.calcGraphData(plotSignals, messages)
);
this.setState({ graphData });
this.setState({ plottedSignals });
}
onSignalUnplotPressed(messageId, signalUid) {
@ -311,10 +227,7 @@ export default class Explorer extends Component {
)
.filter(plot => plot.length > 0);
this.setState(
{ plottedSignals: newPlottedSignals },
this.refreshGraphData(this.props.messages, newPlottedSignals)
);
this.setState({ plottedSignals: newPlottedSignals });
}
updateSegment = debounce((messageId, segment) => {
@ -526,9 +439,9 @@ export default class Explorer extends Component {
}
mergePlots({ fromPlot, toPlot }) {
let { plottedSignals, graphData } = this.state;
let { plottedSignals } = this.state;
// remove fromPlot from plottedSignals, graphData
// remove fromPlot from plottedSignals
const fromPlotIdx = plottedSignals.findIndex(plot =>
plot.some(
signal =>
@ -537,10 +450,6 @@ export default class Explorer extends Component {
)
);
plottedSignals.splice(fromPlotIdx, 1);
graphData.splice(fromPlotIdx, 1);
// calc new graph data
const newGraphData = this.calcGraphData([fromPlot, toPlot]);
const toPlotIdx = plottedSignals.findIndex(plot =>
plot.some(
@ -549,10 +458,9 @@ export default class Explorer extends Component {
signal.messageId === toPlot.messageId
)
);
graphData[toPlotIdx] = newGraphData;
plottedSignals[toPlotIdx] = [fromPlot, toPlot];
this.setState({ graphData, plottedSignals });
this.setState({ plottedSignals });
}
render() {

View File

@ -1,6 +1,4 @@
import { createClassFromSpec } from "react-vega";
export default createClassFromSpec("CanPlot", {
export default {
$schema: "https://vega.github.io/schema/vega/v3.0.json",
width: 400,
height: 200,
@ -335,4 +333,4 @@ export default createClassFromSpec("CanPlot", {
]
}
]
});
};

1281
yarn.lock

File diff suppressed because it is too large Load Diff