Add eslint with explorer configuration (#26)

* Add eslint and run --fix

* Remove precommit prettier
main
Chris Vickery 2019-10-07 16:11:53 -07:00 committed by GitHub
parent 8bcda7c579
commit 1be5544df3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
103 changed files with 2277 additions and 2214 deletions

5
.eslintignore 100644
View File

@ -0,0 +1,5 @@
node_modules/
public/
build/
.storybook
src/registerServiceWorker.js

18
.eslintrc 100644
View File

@ -0,0 +1,18 @@
{
"parser": "babel-eslint",
"extends": [
"airbnb"
],
"rules": {
"import/prefer-default-export": 0,
"import/no-named-as-default": 0,
"comma-dangle": 0,
"react/jsx-filename-extension": 0, // .jsx should be better? But git diff will be crazy
"react/forbid-prop-types": 0, // Too time consuming to map out types for now
"react/require-default-props": 0,
"no-plusplus": ["error", { "allowForLoopAfterthoughts": true }]
},
"env": {
"browser": true
}
}

View File

@ -1,12 +0,0 @@
{
"extends": "react-app",
"rules": {
"no-undef": 1
},
"env": {
"browser": true
},
"globals": {
"window": false
}
}

View File

@ -1,25 +1,25 @@
const WorkerLoaderPlugin = require("craco-worker-loader");
const SentryPlugin = require("craco-sentry-plugin");
const WorkerLoaderPlugin = require('craco-worker-loader');
const SentryPlugin = require('craco-sentry-plugin');
module.exports = function({ env }) {
var plugins = [
module.exports = function ({ env }) {
const plugins = [
{
plugin: WorkerLoaderPlugin
}
];
if (env === "production") {
if (env === 'production') {
// plugins.push({
// plugin: SentryPlugin
// });
}
return {
plugins: plugins,
plugins,
webpack: {
configure: (webpackConfig, { env, paths }) => {
webpackConfig.output.globalObject = "this";
webpackConfig.output.globalObject = 'this';
webpackConfig.optimization.minimizer = webpackConfig.optimization.minimizer.map(
function(plugin) {
if (plugin.constructor.name !== "TerserPlugin") {
(plugin) => {
if (plugin.constructor.name !== 'TerserPlugin') {
return plugin;
}
plugin.options.terserOptions.keep_fnames = true;

View File

@ -11,6 +11,7 @@
"@craco/craco": "^5.5.0",
"ap": "^0.2.0",
"aphrodite": "^1.2.1",
"babel-eslint": "^10.0.3",
"base64-inline-loader": "^1.1.0",
"classnames": "^2.2.5",
"clipboard": "^1.7.1",
@ -22,6 +23,12 @@
"emotion": "^8.0.12",
"enzyme": "^3.2.0",
"enzyme-adapter-react-16": "^1.1.0",
"eslint": "^6.5.1",
"eslint-config-airbnb": "^18.0.1",
"eslint-plugin-import": "^2.18.2",
"eslint-plugin-jsx-a11y": "^6.2.3",
"eslint-plugin-react": "^7.16.0",
"eslint-plugin-react-hooks": "^2.1.2",
"file-saver": "^1.3.3",
"font-awesome": "^4.7.0",
"github-api": "^3.0.0",
@ -86,11 +93,10 @@
"test-ci": "CI=true craco test --env=jsdom",
"netlify-sass": "node-sass src/index.scss > src/index.css",
"sass": "node-sass src/index.scss -o src && node-sass -w src/index.scss -o src",
"precommit": "lint-staged",
"deploy": "npm run build && gh-pages -d build"
},
"lint-staged": {
"*.{js,jsx}": ["prettier --parser flow --write", "git add"],
"*.{js,jsx}": ["eslint --fix", "git add"],
"*.json": ["prettier --parser json --write", "git add"],
"*.{graphql,gql}": ["prettier --parser graphql --write", "git add"],
"*.{md,markdown}": ["prettier --parser markdown --write", "git add"],

View File

@ -1,43 +1,43 @@
import React, { Component } from "react";
import Moment from "moment";
import PropTypes from "prop-types";
import cx from "classnames";
import { createWriteStream } from "streamsaver";
import Panda from "@commaai/pandajs";
import CommaAuth from "@commaai/my-comma-auth";
import { raw as RawDataApi, drives as DrivesApi } from "@commaai/comma-api";
import React, { Component } from 'react';
import Moment from 'moment';
import PropTypes from 'prop-types';
import cx from 'classnames';
import { createWriteStream } from 'streamsaver';
import Panda from '@commaai/pandajs';
import CommaAuth from '@commaai/my-comma-auth';
import { raw as RawDataApi, drives as DrivesApi } from '@commaai/comma-api';
import {
USE_UNLOGGER,
PART_SEGMENT_LENGTH,
STREAMING_WINDOW,
GITHUB_AUTH_TOKEN_KEY
} from "./config";
import * as GithubAuth from "./api/github-auth";
} from './config';
import * as GithubAuth from './api/github-auth';
import DBC from "./models/can/dbc";
import Meta from "./components/Meta";
import Explorer from "./components/Explorer";
import OnboardingModal from "./components/Modals/OnboardingModal";
import SaveDbcModal from "./components/SaveDbcModal";
import LoadDbcModal from "./components/LoadDbcModal";
import debounce from "./utils/debounce";
import EditMessageModal from "./components/EditMessageModal";
import LoadingBar from "./components/LoadingBar";
import DBC from './models/can/dbc';
import Meta from './components/Meta';
import Explorer from './components/Explorer';
import OnboardingModal from './components/Modals/OnboardingModal';
import SaveDbcModal from './components/SaveDbcModal';
import LoadDbcModal from './components/LoadDbcModal';
import debounce from './utils/debounce';
import EditMessageModal from './components/EditMessageModal';
import LoadingBar from './components/LoadingBar';
import {
persistDbc,
fetchPersistedDbc,
unpersistGithubAuthToken
} from "./api/localstorage";
import OpenDbc from "./api/OpenDbc";
import UnloggerClient from "./api/unlogger";
import * as ObjectUtils from "./utils/object";
import { hash } from "./utils/string";
import { modifyQueryParameters } from "./utils/url";
} from './api/localstorage';
import OpenDbc from './api/OpenDbc';
import UnloggerClient from './api/unlogger';
import * as ObjectUtils from './utils/object';
import { hash } from './utils/string';
import { modifyQueryParameters } from './utils/url';
const RLogDownloader = require("./workers/rlog-downloader.worker.js");
const LogCSVDownloader = require("./workers/dbc-csv-downloader.worker.js");
const MessageParser = require("./workers/message-parser.worker.js");
const CanStreamerWorker = require("./workers/CanStreamerWorker.worker.js");
const RLogDownloader = require('./workers/rlog-downloader.worker.js');
const LogCSVDownloader = require('./workers/dbc-csv-downloader.worker.js');
const MessageParser = require('./workers/message-parser.worker.js');
const CanStreamerWorker = require('./workers/CanStreamerWorker.worker.js');
export default class CanExplorer extends Component {
static propTypes = {
@ -73,7 +73,7 @@ export default class CanExplorer extends Component {
editMessageModalMessage: null,
dbc: props.dbc ? props.dbc : new DBC(),
dbcText: props.dbc ? props.dbc.text() : new DBC().text(),
dbcFilename: props.dbcFilename ? props.dbcFilename : "New_DBC",
dbcFilename: props.dbcFilename ? props.dbcFilename : 'New_DBC',
dbcLastSaved: null,
seekTime: 0,
seekIndex: 0,
@ -135,19 +135,19 @@ export default class CanExplorer extends Component {
if (CommaAuth.isAuthenticated() && !name) {
this.showOnboarding();
} else if (
this.props.max &&
this.props.url &&
!this.props.exp &&
!this.props.sig
this.props.max
&& this.props.url
&& !this.props.exp
&& !this.props.sig
) {
// probably the demo!
const { max, url } = this.props;
const startTime = Moment(name, "YYYY-MM-DD--H-m-s");
const startTime = Moment(name, 'YYYY-MM-DD--H-m-s');
const route = {
fullname: dongleId + "|" + name,
fullname: `${dongleId}|${name}`,
proclog: max,
url: url,
url,
start_time: startTime
};
this.setState(
@ -158,15 +158,14 @@ export default class CanExplorer extends Component {
this.initCanData
);
} else if (dongleId && name) {
const routeName = dongleId + "|" + name;
let urlPromise, logUrlsPromise;
const routeName = `${dongleId}|${name}`;
let urlPromise;
let logUrlsPromise;
if (this.props.url) {
urlPromise = Promise.resolve(this.props.url);
} else {
urlPromise = DrivesApi.getRouteInfo(routeName).then(function(route) {
return route.url;
});
urlPromise = DrivesApi.getRouteInfo(routeName).then((route) => route.url);
}
if (this.props.sig && this.props.exp) {
@ -178,13 +177,13 @@ export default class CanExplorer extends Component {
logUrlsPromise = RawDataApi.getLogUrls(routeName);
}
Promise.all([urlPromise, logUrlsPromise])
.then(initData => {
let [url, logUrls] = initData;
.then((initData) => {
const [url, logUrls] = initData;
const newState = {
route: {
fullname: routeName,
proclog: logUrls.length - 1,
start_time: Moment(name, "YYYY-MM-DD--H-m-s"),
start_time: Moment(name, 'YYYY-MM-DD--H-m-s'),
url
},
currentParts: [
@ -195,21 +194,19 @@ export default class CanExplorer extends Component {
};
this.setState(newState, this.initCanData);
DrivesApi.getShareSignature(routeName).then(shareSignature =>
this.setState({
shareUrl: modifyQueryParameters({
add: {
exp: shareSignature.exp,
sig: shareSignature.sig,
max: logUrls.length - 1,
url
},
remove: [GITHUB_AUTH_TOKEN_KEY]
})
DrivesApi.getShareSignature(routeName).then((shareSignature) => this.setState({
shareUrl: modifyQueryParameters({
add: {
exp: shareSignature.exp,
sig: shareSignature.sig,
max: logUrls.length - 1,
url
},
remove: [GITHUB_AUTH_TOKEN_KEY]
})
);
}));
})
.catch(err => {
.catch((err) => {
console.error(err);
this.showOnboarding();
});
@ -245,7 +242,12 @@ export default class CanExplorer extends Component {
}
);
} else {
this.setState({ dbc, dbcFilename, dbcText: dbc.text(), messages: {} });
this.setState({
dbc,
dbcFilename,
dbcText: dbc.text(),
messages: {}
});
}
}
@ -262,10 +264,10 @@ export default class CanExplorer extends Component {
// }
downloadLogAsCSV() {
console.log("downloadLogAsCSV:start");
console.log('downloadLogAsCSV:start');
const { dbcFilename } = this.state;
const fileStream = createWriteStream(
`${dbcFilename.replace(/\.dbc/g, "-")}${+new Date()}.csv`
`${dbcFilename.replace(/\.dbc/g, '-')}${+new Date()}.csv`
);
const writer = fileStream.getWriter();
const encoder = new TextEncoder();
@ -278,15 +280,16 @@ export default class CanExplorer extends Component {
function dataHandler(e) {
const { logData, shouldClose, progress } = e.data;
if (shouldClose) {
console.log("downloadLogAsCSV:close");
console.log('downloadLogAsCSV:close');
writer.close();
return;
}
console.log("CSV export progress:", progress);
const uint8array = encoder.encode(logData + "\n");
console.log('CSV export progress:', progress);
const uint8array = encoder.encode(`${logData}\n`);
writer.write(uint8array);
}
}
downloadRawLogAsCSV(handler) {
return this.downloadLiveLogAsCSV(handler);
}
@ -301,8 +304,8 @@ export default class CanExplorer extends Component {
worker.onmessage = handler;
worker.postMessage({
data: Object.keys(this.state.messages).map(sourceId => {
var source = this.state.messages[sourceId];
data: Object.keys(this.state.messages).map((sourceId) => {
const source = this.state.messages[sourceId];
return {
id: source.id,
bus: source.bus,
@ -321,16 +324,16 @@ export default class CanExplorer extends Component {
options = options || {};
const messages = { ...this.state.messages };
for (var key in newMessages) {
for (const key in newMessages) {
// add message
if (options.replace !== true && key in messages) {
// should merge here instead of concat
// assumes messages are always sequential
let msgEntries = messages[key].entries;
let newMsgEntries = newMessages[key].entries;
let msgLength = msgEntries.length;
let newMsgLength = newMsgEntries.length;
let entryLength = msgLength + newMsgLength;
const msgEntries = messages[key].entries;
const newMsgEntries = newMessages[key].entries;
const msgLength = msgEntries.length;
const newMsgLength = newMsgEntries.length;
const entryLength = msgLength + newMsgLength;
messages[key].entries = Array(entryLength);
let msgIndex = 0;
@ -351,8 +354,7 @@ export default class CanExplorer extends Component {
messages[key].entries[i] = newMsgEntries[newMsgIndex++];
}
}
messages[key].byteStateChangeCounts =
newMessages[key].byteStateChangeCounts;
messages[key].byteStateChangeCounts = newMessages[key].byteStateChangeCounts;
} else {
messages[key] = newMessages[key];
messages[key].frame = this.state.dbc.getMessageFrame(
@ -365,15 +367,15 @@ export default class CanExplorer extends Component {
}
cancelWorker(workerHash) {
let currentWorkers = { ...this.state.currentWorkers };
let { worker, part } = currentWorkers[workerHash];
let loadingParts = this.state.loadingParts.filter(p => p !== part);
let loadedParts = this.state.loadedParts.filter(p => p !== part);
const currentWorkers = { ...this.state.currentWorkers };
const { worker, part } = currentWorkers[workerHash];
const loadingParts = this.state.loadingParts.filter((p) => p !== part);
const loadedParts = this.state.loadedParts.filter((p) => p !== part);
delete currentWorkers[workerHash];
console.log("Stoping worker", workerHash, "for part", part);
console.log('Stoping worker', workerHash, 'for part', part);
worker.postMessage({
action: "terminate"
action: 'terminate'
});
this.setState({
@ -385,16 +387,16 @@ export default class CanExplorer extends Component {
spawnWorker(options) {
let { currentParts, currentWorkers } = this.state;
console.log("Checking worker for", currentParts);
console.log('Checking worker for', currentParts);
if (!this.state.isLoading) {
this.setState({ isLoading: true });
}
const [minPart, maxPart] = currentParts;
// cancel old workers that are still loading data no longer inside the window
Object.keys(currentWorkers).forEach(workerHash => {
Object.keys(currentWorkers).forEach((workerHash) => {
if (
currentWorkers[workerHash].part < minPart ||
currentWorkers[workerHash].part > maxPart
currentWorkers[workerHash].part < minPart
|| currentWorkers[workerHash].part > maxPart
) {
this.cancelWorker(workerHash);
}
@ -406,12 +408,12 @@ export default class CanExplorer extends Component {
// clean this up just in case, the cancel process above *should* have already done this
// they have at most 4 entries so it's trivial
loadingParts = loadingParts.filter(p => p >= minPart && p <= maxPart);
loadedParts = loadedParts.filter(p => p >= minPart && p <= maxPart);
loadingParts = loadingParts.filter((p) => p >= minPart && p <= maxPart);
loadedParts = loadedParts.filter((p) => p >= minPart && p <= maxPart);
let part = -1;
let allWorkerParts = Object.keys(currentWorkers).map(
i => currentWorkers[i].part
const allWorkerParts = Object.keys(currentWorkers).map(
(i) => currentWorkers[i].part
);
for (let partOffset = 0; partOffset <= maxPart - minPart; ++partOffset) {
@ -425,15 +427,15 @@ export default class CanExplorer extends Component {
}
}
if (part === -1) {
console.log("Loading complete");
console.log('Loading complete');
this.setState({ isLoading: false });
return;
}
console.log("Starting worker for part", part);
console.log('Starting worker for part', part);
// options is object of {part, prevMsgEntries, spawnWorkerHash, prepend}
options = options || {};
let prevMsgEntries = options.prevMsgEntries;
let prepend = false;
let { prevMsgEntries } = options;
const prepend = false;
const {
dbc,
@ -446,19 +448,19 @@ export default class CanExplorer extends Component {
if (!prevMsgEntries) {
// we have previous messages loaded
let { messages } = this.state;
let canStartTime = firstCanTime - canFrameOffset;
const { messages } = this.state;
const canStartTime = firstCanTime - canFrameOffset;
prevMsgEntries = {};
Object.keys(messages).forEach(function(key) {
let entries = messages[key].entries;
Object.keys(messages).forEach((key) => {
const { entries } = messages[key];
prevMsgEntries[key] = entries[entries.length - 1];
});
}
// var worker = new CanFetcher();
var worker = new RLogDownloader();
const worker = new RLogDownloader();
let spawnWorkerHash = hash(Math.random().toString(16));
const spawnWorkerHash = hash(Math.random().toString(16));
currentWorkers[spawnWorkerHash] = {
part,
worker
@ -471,9 +473,9 @@ export default class CanExplorer extends Component {
loadingParts
});
worker.onmessage = e => {
worker.onmessage = (e) => {
if (this.state.currentWorkers[spawnWorkerHash] === undefined) {
console.log("Worker was canceled");
console.log('Worker was canceled');
return;
}
@ -495,16 +497,15 @@ export default class CanExplorer extends Component {
maxByteStateChangeCount
);
const prevMsgEntries = {};
for (let key in newMessages) {
prevMsgEntries[key] =
newMessages[key].entries[newMessages[key].entries.length - 1];
for (const key in newMessages) {
prevMsgEntries[key] = newMessages[key].entries[newMessages[key].entries.length - 1];
}
if (!isFinished) {
this.setState({ messages });
} else {
let loadingParts = this.state.loadingParts.filter(p => p !== part);
let loadedParts = [part, ...this.state.loadedParts];
const loadingParts = this.state.loadingParts.filter((p) => p !== part);
const loadedParts = [part, ...this.state.loadedParts];
this.setState(
{
@ -537,7 +538,7 @@ export default class CanExplorer extends Component {
// data that is used
dbcText: dbc.text(),
route: route.fullname,
part: part,
part,
canStartTime: firstCanTime != null ? firstCanTime - canFrameOffset : null,
prevMsgEntries,
maxByteStateChangeCount
@ -553,11 +554,11 @@ export default class CanExplorer extends Component {
showEditMessageModal
} = this.state;
return (
showOnboarding ||
showLoadDbc ||
showSaveDbc ||
showAddSignal ||
showEditMessageModal
showOnboarding
|| showLoadDbc
|| showSaveDbc
|| showAddSignal
|| showEditMessageModal
);
}
@ -589,8 +590,8 @@ export default class CanExplorer extends Component {
this.setState({ isLoading: true });
const { dbc } = this.state;
var worker = new MessageParser();
worker.onmessage = e => {
const worker = new MessageParser();
worker.onmessage = (e) => {
let messages = e.data;
messages = this.addAndRehydrateMessages(messages, { replace: true });
@ -616,7 +617,7 @@ export default class CanExplorer extends Component {
if (route) {
persistDbc(route.fullname, { dbcFilename, dbc });
} else {
persistDbc("live", { dbcFilename, dbc });
persistDbc('live', { dbcFilename, dbc });
}
}
@ -635,19 +636,17 @@ export default class CanExplorer extends Component {
messages[message.id] = newMessage;
this.setState({ dbc, dbcText: dbc.text() }, () =>
this.reparseMessages(messages)
);
this.setState({ dbc, dbcText: dbc.text() }, () => this.reparseMessages(messages));
}
partChangeDebounced = debounce(() => {
let [minPart, maxPart] = this.state.currentParts;
let messages = { ...this.state.messages };
const [minPart, maxPart] = this.state.currentParts;
const messages = { ...this.state.messages };
// update messages to only preserve entries in new part range
let minTime = minPart * 60;
let maxTime = maxPart * 60 + 60;
Object.keys(messages).forEach(key => {
let entries = messages[key].entries;
const minTime = minPart * 60;
const maxTime = maxPart * 60 + 60;
Object.keys(messages).forEach((key) => {
const { entries } = messages[key];
let minIndex = 0;
let maxIndex = entries.length - 1;
while (minIndex < entries.length && entries[minIndex].relTime < minTime) {
@ -669,14 +668,16 @@ export default class CanExplorer extends Component {
}, 500);
onPartChange(part) {
let { currentParts, currentPart, canFrameOffset, route } = this.state;
let {
currentParts, currentPart, canFrameOffset, route
} = this.state;
if (canFrameOffset === -1 || part === currentPart) {
return;
}
// determine new parts to load, whether to prepend or append
let maxPart = Math.min(route.proclog, part + 1);
let minPart = Math.max(0, maxPart - PART_SEGMENT_LENGTH + 1);
const minPart = Math.max(0, maxPart - PART_SEGMENT_LENGTH + 1);
if (minPart === 0) {
maxPart = Math.min(route.proclog, 2);
}
@ -687,9 +688,9 @@ export default class CanExplorer extends Component {
currentPart = part;
if (
currentPart !== this.state.currentPart ||
currentParts[0] !== this.state.currentParts[0] ||
currentParts[1] !== this.state.currentParts[1]
currentPart !== this.state.currentPart
|| currentParts[0] !== this.state.currentParts[0]
|| currentParts[1] !== this.state.currentParts[1]
) {
// update state then load new parts
this.setState({ currentParts, currentPart }, this.partChangeDebounced);
@ -715,9 +716,11 @@ export default class CanExplorer extends Component {
}
onMessageFrameEdited(messageFrame) {
const { messages, dbcFilename, dbc, editMessageModalMessage } = this.state;
const {
messages, dbcFilename, dbc, editMessageModalMessage
} = this.state;
const message = Object.assign({}, messages[editMessageModalMessage]);
const message = { ...messages[editMessageModalMessage] };
message.frame = messageFrame;
dbc.messages.set(messageFrame.id, messageFrame);
this.persistDbc({ dbcFilename, dbc });
@ -730,8 +733,8 @@ export default class CanExplorer extends Component {
onSeek(seekIndex, seekTime) {
this.setState({ seekIndex, seekTime });
let { currentPart } = this.state;
let part = ~~(seekTime / 60);
const { currentPart } = this.state;
const part = ~~(seekTime / 60);
if (part !== currentPart) {
this.onPartChange(part);
}
@ -745,7 +748,7 @@ export default class CanExplorer extends Component {
const msg = this.state.messages[this.state.selectedMessage];
let seekIndex;
if (msg) {
seekIndex = msg.entries.findIndex(e => e.relTime >= seekTime);
seekIndex = msg.entries.findIndex((e) => e.relTime >= seekTime);
if (seekIndex === -1) {
seekIndex = 0;
}
@ -761,7 +764,7 @@ export default class CanExplorer extends Component {
const msg = messages[msgKey];
if (seekTime > 0 && msg.entries.length > 0) {
seekIndex = msg.entries.findIndex(e => e.relTime >= seekTime);
seekIndex = msg.entries.findIndex((e) => e.relTime >= seekTime);
if (seekIndex === -1) {
seekIndex = 0;
}
@ -785,7 +788,7 @@ export default class CanExplorer extends Component {
return (
<a
href={GithubAuth.authorizeUrl(
route && route.fullname ? route.fullname : ""
route && route.fullname ? route.fullname : ''
)}
className="button button--dark button--inline"
>
@ -847,7 +850,7 @@ export default class CanExplorer extends Component {
}
enforceStreamingMessageWindow(messages) {
let messageIds = Object.keys(messages);
const messageIds = Object.keys(messages);
for (let i = 0; i < messageIds.length; i++) {
const messageId = messageIds[i];
const message = messages[messageId];
@ -886,8 +889,8 @@ export default class CanExplorer extends Component {
messages = this.enforceStreamingMessageWindow(messages);
let { seekIndex, selectedMessages } = this.state;
if (
selectedMessages.length > 0 &&
messages[selectedMessages[0]] !== undefined
selectedMessages.length > 0
&& messages[selectedMessages[0]] !== undefined
) {
seekIndex = Math.max(0, messages[selectedMessages[0]].entries.length - 1);
}
@ -908,16 +911,16 @@ export default class CanExplorer extends Component {
async handlePandaConnect(e) {
this.setState({ attemptingPandaConnection: true, live: true });
const persistedDbc = fetchPersistedDbc("live");
const persistedDbc = fetchPersistedDbc('live');
if (persistedDbc) {
let { dbc, dbcText } = persistedDbc;
const { dbc, dbcText } = persistedDbc;
this.setState({ dbc, dbcText });
}
this.canStreamerWorker = new CanStreamerWorker();
this.canStreamerWorker.onmessage = this.onStreamedCanMessagesProcessed;
// if any errors go off during connection, mark as not trying to connect anymore...
let unlisten = this.pandaReader.onError(err => {
const unlisten = this.pandaReader.onError((err) => {
console.error(err.stack || err);
this.setState({ attemptingPandaConnection: false });
});
@ -943,7 +946,7 @@ export default class CanExplorer extends Component {
return (
<div
id="cabana"
className={cx({ "is-showing-modal": this.showingModal() })}
className={cx({ 'is-showing-modal': this.showingModal() })}
>
{this.state.isLoading ? (
<LoadingBar isLoading={this.state.isLoading} />

View File

@ -1,27 +1,28 @@
global.__JEST__ = 1;
import DBC from "../../models/can/dbc";
import Signal from "../../models/can/signal";
import DBC from '../../models/can/dbc';
import Signal from '../../models/can/signal';
test("setting signals should create a message", () => {
global.__JEST__ = 1;
test('setting signals should create a message', () => {
const dbc = new DBC();
dbc.setSignals(100, { "My Signal": new Signal({ name: "My Signal" }) });
dbc.setSignals(100, { 'My Signal': new Signal({ name: 'My Signal' }) });
expect(dbc.messages.has(100)).toBe(true);
});
test("setting signals should update DBC.boardUnits", () => {
test('setting signals should update DBC.boardUnits', () => {
const dbc = new DBC();
dbc.setSignals(100, {
"My Signal": new Signal({ name: "My Signal", receiver: ["NEO"] })
'My Signal': new Signal({ name: 'My Signal', receiver: ['NEO'] })
});
expect(dbc.boardUnits.map(bu => bu.name).indexOf("NEO")).toBe(0);
expect(dbc.boardUnits.map((bu) => bu.name).indexOf('NEO')).toBe(0);
});
test("adding a signal should update DBC.boardUnits", () => {
test('adding a signal should update DBC.boardUnits', () => {
const dbc = new DBC();
dbc.createFrame(100);
dbc.addSignal(100, new Signal({ name: "My Signal", receiver: ["NEO"] }));
dbc.addSignal(100, new Signal({ name: 'My Signal', receiver: ['NEO'] }));
expect(dbc.boardUnits.map(bu => bu.name).indexOf("NEO")).toBe(0);
expect(dbc.boardUnits.map((bu) => bu.name).indexOf('NEO')).toBe(0);
});

View File

@ -1,6 +1,7 @@
import DBC, { swapOrder } from '../../models/can/dbc';
import Signal from '../../models/can/signal';
global.__JEST__ = 1;
import DBC, { swapOrder } from "../../models/can/dbc";
import Signal from "../../models/can/signal";
const DBC_MESSAGE_DEF = `BO_ 228 STEERING_CONTROL: 5 ADAS
SG_ STEER_TORQUE : 7|16@0- (1,0) [-3840|3840] "" EPS
@ -145,7 +146,7 @@ BO_ 464 WHEEL_SPEEDS: 8 VSA
`;
const steerTorqueSignal = new Signal({
name: "STEER_TORQUE",
name: 'STEER_TORQUE',
startBit: 7,
size: 16,
isLittleEndian: false,
@ -154,165 +155,165 @@ const steerTorqueSignal = new Signal({
offset: 0,
min: -3840,
max: 3840,
receiver: ["EPS"],
unit: ""
receiver: ['EPS'],
unit: ''
});
function dbcInt32SignalValue(dbc, signalSpec, hex) {
// expects hex string to represent 8 bytes, left-justified with zeroes if frame size is smaller
const buffer = Buffer.from(hex, "hex");
const buffer = Buffer.from(hex, 'hex');
return dbc.valueForInt32Signal(signalSpec, buffer);
}
test("DBC parses steering control message", () => {
test('DBC parses steering control message', () => {
const dbcParsed = new DBC(DBC_MESSAGE_DEF);
const { signals } = dbcParsed.getMessageFrame(228);
expect(Object.keys(signals).length).toBe(6);
expect(signals["STEER_TORQUE"].equals(steerTorqueSignal)).toBe(true);
expect(signals.STEER_TORQUE.equals(steerTorqueSignal)).toBe(true);
});
test("DBC parses signal comment", () => {
test('DBC parses signal comment', () => {
const dbcParsed = new DBC(DBC_SIGNAL_WITH_COMMENT);
const { signals } = dbcParsed.getMessageFrame(228);
expect(signals.STEER_TORQUE.comment).toEqual(
"steer torque is the amount of torque in Nm applied"
'steer torque is the amount of torque in Nm applied'
);
});
test("DBC parses multi-line signal comment", () => {
test('DBC parses multi-line signal comment', () => {
const dbcParsed = new DBC(DBC_SIGNAL_WITH_MULTI_LINE_COMMENT);
const { signals } = dbcParsed.getMessageFrame(228);
expect(signals.STEER_TORQUE.comment).toEqual(
"steer torque is the\namount of torque in Nm applied"
'steer torque is the\namount of torque in Nm applied'
);
});
test("DBC parses message comment", () => {
test('DBC parses message comment', () => {
const dbcParsed = new DBC(DBC_MESSAGE_WITH_COMMENT);
const msg = dbcParsed.getMessageFrame(228);
expect(msg.comment).toEqual("this message contains steer torque information");
expect(msg.comment).toEqual('this message contains steer torque information');
});
test("DBC parses multi-line message comment", () => {
test('DBC parses multi-line message comment', () => {
const dbcParsed = new DBC(DBC_MESSAGE_WITH_MULTI_LINE_COMMENT);
const msg = dbcParsed.getMessageFrame(228);
expect(msg.comment).toEqual(
"this message contains\nsteer torque information"
'this message contains\nsteer torque information'
);
});
test("DBC parses board unit names", () => {
test('DBC parses board unit names', () => {
const dbcParsed = new DBC(DBC_BOARD_UNITS);
expect(dbcParsed.boardUnits[0].name).toEqual("first_board_unit");
expect(dbcParsed.boardUnits[1].name).toEqual("second_board_unit");
expect(dbcParsed.boardUnits[0].name).toEqual('first_board_unit');
expect(dbcParsed.boardUnits[1].name).toEqual('second_board_unit');
});
test("DBC parses board unit comments", () => {
test('DBC parses board unit comments', () => {
const dbcParsed = new DBC(DBC_BOARD_UNITS_WITH_COMMENT);
expect(dbcParsed.boardUnits[0].comment).toEqual("first board unit comment");
expect(dbcParsed.boardUnits[0].comment).toEqual('first board unit comment');
});
test("DBC parses multi-line board unit comments", () => {
test('DBC parses multi-line board unit comments', () => {
const dbcParsed = new DBC(DBC_BOARD_UNITS_WITH_COMMENT_LINES);
expect(dbcParsed.boardUnits[0].comment).toEqual("first board unit\ncomment");
expect(dbcParsed.boardUnits[0].comment).toEqual('first board unit\ncomment');
});
test("DBC parses signal value descriptions", () => {
test('DBC parses signal value descriptions', () => {
const dbcParsed = new DBC(DBC_SIGNALS_WITH_VAL);
const { signals } = dbcParsed.getMessageFrame(228);
const expectedTorqueRequestVals = new Map([
["1", "requesting torque"],
["0", "not requesting torque"]
['1', 'requesting torque'],
['0', 'not requesting torque']
]);
expect(signals.STEER_TORQUE_REQUEST.valueDescriptions).toEqual(
expectedTorqueRequestVals
);
});
test("DBC parses value tables", () => {
test('DBC parses value tables', () => {
const dbcParsed = new DBC(DBC_VALUE_TABLE);
const stateTableEntries = [
["4", "DI_STATE_ENABLE"],
["3", "DI_STATE_FAULT"],
["2", "DI_STATE_CLEAR_FAULT"],
["1", "DI_STATE_STANDBY"],
["0", "DI_STATE_PREAUTH"]
['4', 'DI_STATE_ENABLE'],
['3', 'DI_STATE_FAULT'],
['2', 'DI_STATE_CLEAR_FAULT'],
['1', 'DI_STATE_STANDBY'],
['0', 'DI_STATE_PREAUTH']
];
const stateTable = new Map(stateTableEntries);
const speedUnitsEntries = [["1", "DI_SPEED_KPH"], ["0", "DI_SPEED_MPH"]];
const speedUnitsEntries = [['1', 'DI_SPEED_KPH'], ['0', 'DI_SPEED_MPH']];
const speedUnitsTable = new Map(speedUnitsEntries);
const valueTableEntries = Array.from(dbcParsed.valueTables.entries());
expect(valueTableEntries[0]).toEqual(["DI_state", stateTable]);
expect(valueTableEntries[1]).toEqual(["DI_speedUnits", speedUnitsTable]);
expect(valueTableEntries[0]).toEqual(['DI_state', stateTable]);
expect(valueTableEntries[1]).toEqual(['DI_speedUnits', speedUnitsTable]);
});
test("swapOrder properly converts little endian to big endian", () => {
const littleEndianHex = "e2d62a0bd0d3b5e5";
const bigEndianHex = "e5b5d3d00b2ad6e2";
test('swapOrder properly converts little endian to big endian', () => {
const littleEndianHex = 'e2d62a0bd0d3b5e5';
const bigEndianHex = 'e5b5d3d00b2ad6e2';
const littleEndianHexSwapped = swapOrder(littleEndianHex, 16, 2);
expect(littleEndianHexSwapped == bigEndianHex).toBe(true);
});
test("int32 parser produces correct value for steer torque signal", () => {
test('int32 parser produces correct value for steer torque signal', () => {
const dbc = new DBC(DBC_MESSAGE_DEF);
const hex = "e2d62a0bd0d3b5e5";
const hex = 'e2d62a0bd0d3b5e5';
const value = dbcInt32SignalValue(
dbc,
dbc.getMessageFrame(228).signals["STEER_TORQUE"],
dbc.getMessageFrame(228).signals.STEER_TORQUE,
hex
);
expect(value).toBe(-7466);
});
test("int64 parser produces correct value for steer torque signal", () => {
test('int64 parser produces correct value for steer torque signal', () => {
const dbc = new DBC(DBC_MESSAGE_DEF);
const hex = "e2d62a0bd0d3b5e5";
const hex = 'e2d62a0bd0d3b5e5';
const value = dbc.valueForInt64Signal(steerTorqueSignal, hex);
expect(value).toBe(-7466);
});
test("int32 parser produces correct value for wheel speeds", () => {
test('int32 parser produces correct value for wheel speeds', () => {
const dbc = new DBC(DBC_WHEEL_SPEEDS);
const hex = "36806cd8d8f1b0b7";
const hex = '36806cd8d8f1b0b7';
const rearRight = dbcInt32SignalValue(
dbc,
dbc.getMessageFrame(464).signals["WHEEL_SPEED_RR"],
dbc.getMessageFrame(464).signals.WHEEL_SPEED_RR,
hex
);
expect(rearRight).toBe(69.23);
const rearLeft = dbcInt32SignalValue(
dbc,
dbc.getMessageFrame(464).signals["WHEEL_SPEED_RL"],
dbc.getMessageFrame(464).signals.WHEEL_SPEED_RL,
hex
);
expect(rearLeft).toBe(69.42);
const frontLeft = dbcInt32SignalValue(
dbc,
dbc.getMessageFrame(464).signals["WHEEL_SPEED_FL"],
dbc.getMessageFrame(464).signals.WHEEL_SPEED_FL,
hex
);
expect(frontLeft).toBe(69.76);
const frontRight = dbcInt32SignalValue(
dbc,
dbc.getMessageFrame(464).signals["WHEEL_SPEED_FR"],
dbc.getMessageFrame(464).signals.WHEEL_SPEED_FR,
hex
);
expect(frontRight).toBe(69.66);
@ -323,12 +324,12 @@ BO_ 768 NEW_MSG_1: 8 XXX
SG_ NEW_SIGNAL_1 : 37|1@1+ (1,0) [0|1] "" XXX
`;
test("int32 parsers produces correct value for binary little endian signal", () => {
test('int32 parsers produces correct value for binary little endian signal', () => {
const dbc = new DBC(DBC_BINARY_LE_SIGNAL);
const signalSpec = dbc.getMessageFrame(768).signals["NEW_SIGNAL_1"];
const signalSpec = dbc.getMessageFrame(768).signals.NEW_SIGNAL_1;
const hexDataSet = "0000000020000000";
const hexDataNotSet = "0000000000000000";
const hexDataSet = '0000000020000000';
const hexDataNotSet = '0000000000000000';
const setValue = dbcInt32SignalValue(dbc, signalSpec, hexDataSet, 8);
const notSetValue = dbcInt32SignalValue(dbc, signalSpec, hexDataNotSet, 8);
@ -341,11 +342,11 @@ const DBC_TWO_BIT_LE_SIGNAL = `
BO_ 768 NEW_MSG_1: 8 XXX
SG_ NEW_SIGNAL_1 : 35|2@1+ (1,0) [0|3] "" XXX
`;
test("int32 parser produces correct value for 2-bit little endian signal spanning words", () => {
test('int32 parser produces correct value for 2-bit little endian signal spanning words', () => {
const dbc = new DBC(DBC_TWO_BIT_LE_SIGNAL);
const signalSpec = dbc.getMessageFrame(768).signals["NEW_SIGNAL_1"];
const signalSpec = dbc.getMessageFrame(768).signals.NEW_SIGNAL_1;
const hexData = "00000001f8000000";
const hexData = '00000001f8000000';
const value = dbcInt32SignalValue(dbc, signalSpec, hexData, 8);
expect(value).toEqual(3);
@ -355,17 +356,17 @@ const DBC_FOUR_BIT_LE_SIGNAL = `
BO_ 768 NEW_MSG_1: 8 XXX
SG_ NEW_SIGNAL_1 : 6|4@1+ (1,0) [0|15] "" XXX
`;
test("int32 parser produces correct value for 4-bit little endian signal", () => {
test('int32 parser produces correct value for 4-bit little endian signal', () => {
const dbc = new DBC(DBC_FOUR_BIT_LE_SIGNAL);
const signalSpec = dbc.getMessageFrame(768).signals["NEW_SIGNAL_1"];
const signalSpec = dbc.getMessageFrame(768).signals.NEW_SIGNAL_1;
// this data is symmetric, the data bits are 1111
const hexDataSymmetric = "f00f000000000000";
const hexDataSymmetric = 'f00f000000000000';
const symValue = dbcInt32SignalValue(dbc, signalSpec, hexDataSymmetric, 8);
expect(symValue).toEqual(15);
// this data is asymmetric, the data bits are 1101
const hexDataAsymmetric = "f002000000000000";
const hexDataAsymmetric = 'f002000000000000';
const aSymValue = dbcInt32SignalValue(dbc, signalSpec, hexDataAsymmetric, 8);
expect(aSymValue).toEqual(11);
});
@ -385,12 +386,12 @@ BO_ 1265 CLU11: 4 CLU
SG_ CF_Clu_AmpInfo : 25|1@1+ (1.0,0.0) [0.0|1.0] "" BCM
SG_ CF_Clu_AliveCnt1 : 28|4@1+ (1.0,0.0) [0.0|15.0] "" AHLS,EMS,EPB,LDWS_LKAS,MDPS,SCC
`;
test("int32 parser produces correct value for 4-bit little endian signal within a 4-byte message", () => {
test('int32 parser produces correct value for 4-bit little endian signal within a 4-byte message', () => {
const dbc = new DBC(DBC_FOUR_BIT_LE_SIGNAL_FOUR_BYTE_MESSAGE);
const frame = dbc.getMessageFrame(1265);
const signalSpec = frame.signals["CF_Clu_AliveCnt1"];
const signalSpec = frame.signals.CF_Clu_AliveCnt1;
const hexData = "2000662000000000";
const hexData = '2000662000000000';
const value = dbcInt32SignalValue(dbc, signalSpec, hexData, frame.size);
expect(value).toEqual(2);
});
@ -403,16 +404,16 @@ BO_ 688 SAS11: 5 MDPS
SG_ MsgCount : 32|4@1+ (1.0,0.0) [0.0|15.0] "" ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,ECS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS
SG_ CheckSum : 36|4@1+ (1.0,0.0) [0.0|15.0] "" ECS,EMS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS,ECS,EMS,ESC,IBOX,LDWS_LKAS,PSB,SCC,SPAS
`;
test("int32 parser produces correct value for 2-byte signed little endian signal within a 5-byte message", () => {
test('int32 parser produces correct value for 2-byte signed little endian signal within a 5-byte message', () => {
const dbc = new DBC(DBC_MESSAGE_WITH_LE_SIGNED_SIGNAL);
const frame = dbc.getMessageFrame(688);
const signalSpec = frame.signals["SAS_Angle"];
const signalSpec = frame.signals.SAS_Angle;
const hexData = "000000fafe000700";
const hexData = '000000fafe000700';
const value = dbcInt32SignalValue(dbc, signalSpec, hexData, frame.size);
expect(value).toEqual(0.0);
const hexData2 = "0b000907d8b30000";
const hexData2 = '0b000907d8b30000';
const value2 = dbcInt32SignalValue(dbc, signalSpec, hexData2, frame.size);
expect(value2).toEqual(1.1);
});
@ -424,12 +425,12 @@ BO_ 37 STEERING_CONTROL: 8 XXX
CM_ "CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180";
`;
test("dbc parser parses top-level comment with chffr metric", () => {
test('dbc parser parses top-level comment with chffr metric', () => {
const dbc = new DBC(DBC_CHFFR_METRIC_COMMENT);
const { comments } = dbc;
expect(comments.length).toEqual(1);
expect(comments[0]).toEqual(
"CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180"
'CHFFR_METRIC 37 STEER_ANGLE STEER_ANGLE 0.36 180'
);
});

View File

@ -1,11 +1,11 @@
import DBC, { swapOrder } from "../../models/can/dbc";
import fs from "fs";
import path from "path";
import fs from 'fs';
import path from 'path';
import DBC, { swapOrder } from '../../models/can/dbc';
const ACURA_DBC = fs.readFileSync("src/__tests__/res/acura.dbc", "utf-8");
//import { TESLA_DBC } from "../res/tesla.dbc";
const ACURA_DBC = fs.readFileSync('src/__tests__/res/acura.dbc', 'utf-8');
// import { TESLA_DBC } from "../res/tesla.dbc";
test("DBC.text() for acura DBC should be equivalent to its original text", () => {
test('DBC.text() for acura DBC should be equivalent to its original text', () => {
const dbc = new DBC(ACURA_DBC);
expect(dbc.text()).toBe(ACURA_DBC);

View File

@ -1,6 +1,6 @@
import Entries from "../../models/can/entries";
import Entries from '../../models/can/entries';
test("segment index low is inclusive and index high is exclusive", () => {
test('segment index low is inclusive and index high is exclusive', () => {
const entries = [
{ time: 1.0 },
{ time: 3.45 },
@ -16,8 +16,8 @@ test("segment index low is inclusive and index high is exclusive", () => {
expect(segmentIdxHi).toBe(entries.length - 1);
});
test("segment index cant return negative indexes", () => {
var indices = Entries.findSegmentIndices([], [123, 321], true);
test('segment index cant return negative indexes', () => {
const indices = Entries.findSegmentIndices([], [123, 321], true);
expect(indices[0]).toBe(0);
expect(indices[1]).toBe(0);
});

View File

@ -1,13 +1,13 @@
import Frame from "../../models/can/frame";
import Frame from '../../models/can/frame';
const FRAME_HEADER = "BO_ 255 SOME_FRAME: 5 ADAS";
const FRAME_HEADER = 'BO_ 255 SOME_FRAME: 5 ADAS';
test("Frame.header() returns spec compliant representation", () => {
test('Frame.header() returns spec compliant representation', () => {
const frame = new Frame({
name: "SOME_FRAME",
name: 'SOME_FRAME',
id: 255,
size: 5,
transmitters: ["ADAS"]
transmitters: ['ADAS']
});
expect(frame.header()).toEqual(FRAME_HEADER);
});

View File

@ -1,7 +1,7 @@
import Signal from "../../models/can/signal";
import Signal from '../../models/can/signal';
const someSignalParams = {
name: "STEER_TORQUE",
name: 'STEER_TORQUE',
startBit: 7,
size: 16,
isLittleEndian: false,
@ -10,11 +10,11 @@ const someSignalParams = {
offset: 0,
min: -3840,
max: 3840,
unit: ""
unit: ''
};
const someOtherSignalParams = {
name: "DIFFERENT_NAME",
name: 'DIFFERENT_NAME',
startBit: 0,
size: 16,
isLittleEndian: false,
@ -23,24 +23,24 @@ const someOtherSignalParams = {
offset: 0,
min: -3840,
max: 3840,
unit: ""
unit: ''
};
test("Signal.equals returns true for signals with identical properties", () => {
test('Signal.equals returns true for signals with identical properties', () => {
const someSignal = new Signal(someSignalParams);
const someEquivalentSignal = new Signal(someSignalParams);
expect(someSignal.equals(someEquivalentSignal)).toBe(true);
});
test("Signal.equals returns false for signals with different properties", () => {
test('Signal.equals returns false for signals with different properties', () => {
const someSignal = new Signal(someSignalParams);
const differentSignal = new Signal(someOtherSignalParams);
expect(someSignal.equals(differentSignal)).toBe(false);
});
test("Signal.bitDescription returns proper description for a little endian signal", () => {
test('Signal.bitDescription returns proper description for a little endian signal', () => {
const littleEndianSignal = new Signal({
name: "little endian signal",
name: 'little endian signal',
startBit: 20,
size: 4,
isLittleEndian: true
@ -52,9 +52,9 @@ test("Signal.bitDescription returns proper description for a little endian signa
expect(littleEndianSignal.bitDescription(23).bitNumber).toBe(3);
});
test("Signal.bitDescription returns proper description for a big endian signal", () => {
test('Signal.bitDescription returns proper description for a big endian signal', () => {
const bigEndianSignal = new Signal({
name: "big endian signal",
name: 'big endian signal',
startBit: 7,
size: 16,
isLittleEndian: false
@ -91,9 +91,9 @@ test("Signal.bitDescription returns proper description for a big endian signal",
expect(bigEndianSignal.bitDescription(7)).toEqual(bitSevenDescription);
});
test("Signal.bitDescription returns null for bit index that is not in its range", () => {
test('Signal.bitDescription returns null for bit index that is not in its range', () => {
const someSignal = new Signal({
name: "some signal",
name: 'some signal',
startBit: 20,
size: 4,
isLittleEndian: false

View File

@ -5,10 +5,10 @@ note: 'right' and 'left' in test descriptions
refer to the sides of the bit matrix
as displayed to the user.
*/
import AddSignals from "../../components/AddSignals";
import React from "react";
import { shallow, mount, render } from "enzyme";
import { StyleSheetTestUtils } from "aphrodite";
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import { StyleSheetTestUtils } from 'aphrodite';
import AddSignals from '../../components/AddSignals';
// Prevents style injection from firing after test finishes
// and jsdom is torn down.
@ -31,7 +31,7 @@ function createAddSignals(signals) {
entries: [
{
relTime: 0,
hexData: "0000000000000000"
hexData: '0000000000000000'
}
]
};
@ -46,99 +46,99 @@ function createAddSignals(signals) {
return component;
}
test("double clicking adds a signal", () => {
test('double clicking adds a signal', () => {
const component = createAddSignals();
const firstBit = component.find(".bit").first();
const firstBit = component.find('.bit').first();
firstBit.simulate("dblclick");
const newSignal = Object.values(component.state("signals"))[0];
firstBit.simulate('dblclick');
const newSignal = Object.values(component.state('signals'))[0];
expect(newSignal).toBeDefined();
expect(newSignal.size).toBe(1);
});
test("dragging right to left across a byte creates a little endian signal", () => {
test('dragging right to left across a byte creates a little endian signal', () => {
const component = createAddSignals();
const leftBitInByte = component.find(".bit").first();
const rightBitInByte = component.find(".bit").at(7);
rightBitInByte.simulate("mousedown");
leftBitInByte.simulate("mouseup");
const leftBitInByte = component.find('.bit').first();
const rightBitInByte = component.find('.bit').at(7);
rightBitInByte.simulate('mousedown');
leftBitInByte.simulate('mouseup');
const newSignal = Object.values(component.state("signals"))[0];
const newSignal = Object.values(component.state('signals'))[0];
expect(newSignal).toBeDefined();
expect(newSignal.size).toBe(8);
expect(newSignal.isLittleEndian).toBe(true);
expect(newSignal.startBit).toBe(0);
});
test("dragging left to right across a byte creates a big endian signal", () => {
test('dragging left to right across a byte creates a big endian signal', () => {
const component = createAddSignals();
const leftBitInByte = component.find(".bit").first();
const rightBitInByte = component.find(".bit").at(7);
leftBitInByte.simulate("mousedown");
rightBitInByte.simulate("mouseup");
const leftBitInByte = component.find('.bit').first();
const rightBitInByte = component.find('.bit').at(7);
leftBitInByte.simulate('mousedown');
rightBitInByte.simulate('mouseup');
const newSignal = Object.values(component.state("signals"))[0];
const newSignal = Object.values(component.state('signals'))[0];
expect(newSignal).toBeDefined();
expect(newSignal.size).toBe(8);
expect(newSignal.isLittleEndian).toBe(false);
expect(newSignal.startBit).toBe(7);
});
test("dragging from the left of byte 0 to right of byte 1 creates a big endian signal spanning both bytes", () => {
test('dragging from the left of byte 0 to right of byte 1 creates a big endian signal spanning both bytes', () => {
const component = createAddSignals();
const leftBitInByte = component.find(".bit").first();
const rightBitInByte = component.find(".bit").at(15);
leftBitInByte.simulate("mousedown");
rightBitInByte.simulate("mouseup");
const leftBitInByte = component.find('.bit').first();
const rightBitInByte = component.find('.bit').at(15);
leftBitInByte.simulate('mousedown');
rightBitInByte.simulate('mouseup');
const newSignal = Object.values(component.state("signals"))[0];
const newSignal = Object.values(component.state('signals'))[0];
expect(newSignal).toBeDefined();
expect(newSignal.size).toBe(16);
expect(newSignal.isLittleEndian).toBe(false);
expect(newSignal.startBit).toBe(7);
});
test("dragging from the right of byte 0 to the left of byte 1 creates a little endian signal spanning both bytes", () => {
test('dragging from the right of byte 0 to the left of byte 1 creates a little endian signal spanning both bytes', () => {
const component = createAddSignals();
const leftBitInByteOne = component.find(".bit").at(8); // left of byte 1
const rightBitInByteZero = component.find(".bit").at(7); // right of byte 0
const leftBitInByteOne = component.find('.bit').at(8); // left of byte 1
const rightBitInByteZero = component.find('.bit').at(7); // right of byte 0
rightBitInByteZero.simulate("mousedown");
leftBitInByteOne.simulate("mouseup");
rightBitInByteZero.simulate('mousedown');
leftBitInByteOne.simulate('mouseup');
const newSignal = Object.values(component.state("signals"))[0];
const newSignal = Object.values(component.state('signals'))[0];
expect(newSignal).toBeDefined();
expect(newSignal.size).toBe(16);
expect(newSignal.isLittleEndian).toBe(true);
expect(newSignal.startBit).toBe(0);
});
test("dragging from the left of byte 1 to the right of byte 0 creates a little endian signal spanning both bytes", () => {
test('dragging from the left of byte 1 to the right of byte 0 creates a little endian signal spanning both bytes', () => {
const component = createAddSignals();
const leftBitInByteOne = component.find(".bit").at(8);
const rightBitInByteZero = component.find(".bit").at(7);
const leftBitInByteOne = component.find('.bit').at(8);
const rightBitInByteZero = component.find('.bit').at(7);
leftBitInByteOne.simulate("mousedown");
rightBitInByteZero.simulate("mouseup");
leftBitInByteOne.simulate('mousedown');
rightBitInByteZero.simulate('mouseup');
const signal = Object.values(component.state("signals"))[0];
const signal = Object.values(component.state('signals'))[0];
expect(signal).toBeDefined();
expect(signal.size).toBe(16);
expect(signal.isLittleEndian).toBe(true);
expect(signal.startBit).toBe(0);
});
test("dragging from the right of byte 1 to the left of byte 0 creates a big endian signal spanning both bytes", () => {
test('dragging from the right of byte 1 to the left of byte 0 creates a big endian signal spanning both bytes', () => {
const component = createAddSignals();
const leftBitInByteZero = component.find(".bit").at(0);
const rightBitInByteOne = component.find(".bit").at(15);
const leftBitInByteZero = component.find('.bit').at(0);
const rightBitInByteOne = component.find('.bit').at(15);
rightBitInByteOne.simulate("mousedown");
leftBitInByteZero.simulate("mouseup");
rightBitInByteOne.simulate('mousedown');
leftBitInByteZero.simulate('mouseup');
const signal = Object.values(component.state("signals"))[0];
const signal = Object.values(component.state('signals'))[0];
expect(signal).toBeDefined();
expect(signal.size).toBe(16);
expect(signal.isLittleEndian).toBe(false);
@ -147,205 +147,205 @@ test("dragging from the right of byte 1 to the left of byte 0 creates a big endi
// signal mutation
test.skip("dragging a one-bit big-endian signal to the right should extend it to the right of the byte", () => {
test.skip('dragging a one-bit big-endian signal to the right should extend it to the right of the byte', () => {
const component = createAddSignals();
component
.instance()
.createSignal({ startBit: 7, size: 1, isLittleEndian: false });
const signalBit = component.find(".bit").at(0);
signalBit.simulate("mousedown");
const signalBit = component.find('.bit').at(0);
signalBit.simulate('mousedown');
for (let i = 1; i < 8; i++) {
component
.find(".bit")
.find('.bit')
.at(i)
.simulate("mouseenter");
.simulate('mouseenter');
}
const bitAtRightOfFirstByte = component.find(".bit").at(7);
bitAtRightOfFirstByte.simulate("mouseup");
const bitAtRightOfFirstByte = component.find('.bit').at(7);
bitAtRightOfFirstByte.simulate('mouseup');
const signal = Object.values(component.state("signals"))[0];
const signal = Object.values(component.state('signals'))[0];
expect(signal).toBeDefined();
expect(signal.size).toBe(8);
expect(signal.isLittleEndian).toBe(false);
expect(signal.startBit).toBe(7);
});
test.skip("dragging a one-bit little-endian signal to the right should extend it to the right of the byte", () => {
test.skip('dragging a one-bit little-endian signal to the right should extend it to the right of the byte', () => {
const component = createAddSignals();
component
.instance()
.createSignal({ startBit: 7, size: 1, isLittleEndian: true });
const signalBit = component.find(".bit").at(0);
signalBit.simulate("mousedown");
const signalBit = component.find('.bit').at(0);
signalBit.simulate('mousedown');
for (let i = 1; i < 8; i++) {
component
.find(".bit")
.find('.bit')
.at(i)
.simulate("mouseenter");
.simulate('mouseenter');
}
const bitAtRightOfFirstByte = component.find(".bit").at(7);
bitAtRightOfFirstByte.simulate("mouseup");
const bitAtRightOfFirstByte = component.find('.bit').at(7);
bitAtRightOfFirstByte.simulate('mouseup');
const signal = Object.values(component.state("signals"))[0];
const signal = Object.values(component.state('signals'))[0];
expect(signal).toBeDefined();
expect(signal.size).toBe(8);
expect(signal.isLittleEndian).toBe(true);
expect(signal.startBit).toBe(0);
});
test.skip("dragging a one-bit big-endian signal to the left should extend it to the left of the byte", () => {
test.skip('dragging a one-bit big-endian signal to the left should extend it to the left of the byte', () => {
const component = createAddSignals();
component
.instance()
.createSignal({ startBit: 0, size: 1, isLittleEndian: false });
const signalBit = component.find(".bit").at(7);
signalBit.simulate("mousedown");
const signalBit = component.find('.bit').at(7);
signalBit.simulate('mousedown');
for (let i = 6; i > -1; i--) {
component
.find(".bit")
.find('.bit')
.at(i)
.simulate("mouseenter");
.simulate('mouseenter');
}
const bitAtRightOfFirstByte = component.find(".bit").at(0);
bitAtRightOfFirstByte.simulate("mouseup");
const bitAtRightOfFirstByte = component.find('.bit').at(0);
bitAtRightOfFirstByte.simulate('mouseup');
const signal = Object.values(component.state("signals"))[0];
const signal = Object.values(component.state('signals'))[0];
expect(signal).toBeDefined();
expect(signal.size).toBe(8);
expect(signal.isLittleEndian).toBe(false);
expect(signal.startBit).toBe(7);
});
test.skip("extending a two-bit big-endian signal by its LSB should extend it to the right of the byte", () => {
test.skip('extending a two-bit big-endian signal by its LSB should extend it to the right of the byte', () => {
const component = createAddSignals();
component
.instance()
.createSignal({ startBit: 7, size: 2, isLittleEndian: false });
const lsb = component.find(".bit").at(1);
lsb.simulate("mousedown");
const lsb = component.find('.bit').at(1);
lsb.simulate('mousedown');
for (let i = 0; i < 8; i++) {
component
.find(".bit")
.find('.bit')
.at(i)
.simulate("mouseenter");
.simulate('mouseenter');
}
const bitAtRightOfFirstByte = component.find(".bit").at(7);
bitAtRightOfFirstByte.simulate("mouseup");
const bitAtRightOfFirstByte = component.find('.bit').at(7);
bitAtRightOfFirstByte.simulate('mouseup');
const signal = Object.values(component.state("signals"))[0];
const signal = Object.values(component.state('signals'))[0];
expect(signal).toBeDefined();
expect(signal.size).toBe(8);
expect(signal.isLittleEndian).toBe(false);
expect(signal.startBit).toBe(7);
});
test.skip("a two-bit little-endian signal should extend by its LSB to the end of the byte", () => {
test.skip('a two-bit little-endian signal should extend by its LSB to the end of the byte', () => {
const component = createAddSignals();
component
.instance()
.createSignal({ startBit: 6, size: 2, isLittleEndian: true });
const lsb = component.find(".bit").at(1);
lsb.simulate("mousedown");
const lsb = component.find('.bit').at(1);
lsb.simulate('mousedown');
for (let i = 0; i < 8; i++) {
component
.find(".bit")
.find('.bit')
.at(i)
.simulate("mouseenter");
.simulate('mouseenter');
}
const bitAtRightOfFirstByte = component.find(".bit").at(7);
bitAtRightOfFirstByte.simulate("mouseup");
const bitAtRightOfFirstByte = component.find('.bit').at(7);
bitAtRightOfFirstByte.simulate('mouseup');
const signal = Object.values(component.state("signals"))[0];
const signal = Object.values(component.state('signals'))[0];
expect(signal).toBeDefined();
expect(signal.size).toBe(8);
expect(signal.isLittleEndian).toBe(true);
expect(signal.startBit).toBe(0);
});
test("dragging the lsb of a little-endian signal spanning an entire byte should not be allowed to pass the MSB", () => {
test('dragging the lsb of a little-endian signal spanning an entire byte should not be allowed to pass the MSB', () => {
const component = createAddSignals();
component
.instance()
.createSignal({ startBit: 0, size: 8, isLittleEndian: true });
const lsb = component.find(".bit").at(7);
lsb.simulate("mousedown");
const lsb = component.find('.bit').at(7);
lsb.simulate('mousedown');
const bitPastMsb = component.find(".bit").at(15);
bitPastMsb.simulate("mouseenter");
bitPastMsb.simulate("mouseup");
const bitPastMsb = component.find('.bit').at(15);
bitPastMsb.simulate('mouseenter');
bitPastMsb.simulate('mouseup');
const signal = Object.values(component.state("signals"))[0];
const signal = Object.values(component.state('signals'))[0];
expect(signal).toBeDefined();
expect(signal.size).toBe(8);
expect(signal.isLittleEndian).toBe(true);
expect(signal.startBit).toBe(0);
});
test.skip("dragging the lsb of a big-endian signal towards the msb in the same byte should contract the signal", () => {
test.skip('dragging the lsb of a big-endian signal towards the msb in the same byte should contract the signal', () => {
const component = createAddSignals();
component
.instance()
.createSignal({ startBit: 7, size: 8, isLittleEndian: false });
const lsb = component.find(".bit").at(7);
lsb.simulate("mousedown");
const lsb = component.find('.bit').at(7);
lsb.simulate('mousedown');
for (let i = 6; i > 0; i--) {
component
.find(".bit")
.find('.bit')
.at(i)
.simulate("mouseenter");
.simulate('mouseenter');
}
component
.find(".bit")
.find('.bit')
.at(1)
.simulate("mouseup");
.simulate('mouseup');
const signal = Object.values(component.state("signals"))[0];
const signal = Object.values(component.state('signals'))[0];
expect(signal).toBeDefined();
expect(signal.size).toBe(2);
expect(signal.isLittleEndian).toBe(false);
expect(signal.startBit).toBe(7);
});
test("a big endian signal spanning one byte should switch to little endian preserving its bit coverage", () => {
test('a big endian signal spanning one byte should switch to little endian preserving its bit coverage', () => {
const component = createAddSignals();
component
.instance()
.createSignal({ startBit: 0, size: 8, isLittleEndian: true });
const lsb = component.find(".bit").at(7);
lsb.simulate("mousedown");
const lsb = component.find('.bit').at(7);
lsb.simulate('mousedown');
const bitPastMsb = component.find(".bit").at(15);
bitPastMsb.simulate("mouseenter");
bitPastMsb.simulate("mouseup");
const bitPastMsb = component.find('.bit').at(15);
bitPastMsb.simulate('mouseenter');
bitPastMsb.simulate('mouseup');
const signal = Object.values(component.state("signals"))[0];
const signal = Object.values(component.state('signals'))[0];
expect(signal).toBeDefined();
expect(signal.size).toBe(8);
expect(signal.isLittleEndian).toBe(true);
expect(signal.startBit).toBe(0);
});
test("dragging the msb of a 2-bit little endian signal to a lower byte should not change the signal", () => {
test('dragging the msb of a 2-bit little endian signal to a lower byte should not change the signal', () => {
const component = createAddSignals();
component
.instance()
.createSignal({ startBit: 14, size: 2, isLittleEndian: true });
const msb = component.find(".bit").at(8);
msb.simulate("mousedown");
const bitOutOfBounds = component.find(".bit").at(0);
bitOutOfBounds.simulate("mouseenter");
bitOutOfBounds.simulate("mouseup");
const msb = component.find('.bit').at(8);
msb.simulate('mousedown');
const bitOutOfBounds = component.find('.bit').at(0);
bitOutOfBounds.simulate('mouseenter');
bitOutOfBounds.simulate('mouseup');
const signal = Object.values(component.state("signals"))[0];
const signal = Object.values(component.state('signals'))[0];
expect(signal).toBeDefined();
expect(signal.size).toBe(2);
expect(signal.isLittleEndian).toBe(true);

View File

@ -1,9 +1,10 @@
global.__JEST__ = 1;
import CanExplorer from "../../CanExplorer";
import React from "react";
import { shallow, mount, render } from "enzyme";
import { StyleSheetTestUtils } from "aphrodite";
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import { StyleSheetTestUtils } from 'aphrodite';
import CanExplorer from '../../CanExplorer';
test("CanExplorer renders", () => {
global.__JEST__ = 1;
test('CanExplorer renders', () => {
const canExplorer = shallow(<CanExplorer />);
});

View File

@ -1,10 +1,10 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import CanGraph from '../../components/CanGraph';
global.__JEST__ = 1;
import CanGraph from "../../components/CanGraph";
import React from "react";
import { shallow, mount, render } from "enzyme";
test("CanGraph successfully mounts with minimal default props", () => {
test('CanGraph successfully mounts with minimal default props', () => {
const component = shallow(
<CanGraph
onGraphRefAvailable={() => {}}
@ -24,7 +24,7 @@ test("CanGraph successfully mounts with minimal default props", () => {
dragPos={null}
canReceiveGraphDrop={false}
plottedSignals={[]}
live={true}
live
/>
);
expect(component.exists()).toBe(true);

View File

@ -1,10 +1,10 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import CanGraphList from '../../components/CanGraphList';
global.__JEST__ = 1;
import CanGraphList from "../../components/CanGraphList";
import React from "react";
import { shallow, mount, render } from "enzyme";
test("CanGraphList successfully mounts with minimal default props", () => {
test('CanGraphList successfully mounts with minimal default props', () => {
const component = shallow(
<CanGraphList
plottedSignals={[]}
@ -16,7 +16,7 @@ test("CanGraphList successfully mounts with minimal default props", () => {
onSignalUnplotPressed={() => {}}
segment={[]}
mergePlots={() => {}}
live={true}
live
/>
);
expect(component.exists()).toBe(true);

View File

@ -1,10 +1,10 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import CanLog from '../../components/CanLog';
global.__JEST__ = 1;
import CanLog from "../../components/CanLog";
import React from "react";
import { shallow, mount, render } from "enzyme";
test("CanLog successfully mounts with minimal default props", () => {
test('CanLog successfully mounts with minimal default props', () => {
const component = shallow(
<CanLog
message={null}

View File

@ -1,10 +1,10 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import DbcUpload from '../../components/DbcUpload';
global.__JEST__ = 1;
import DbcUpload from "../../components/DbcUpload";
import React from "react";
import { shallow, mount, render } from "enzyme";
test("DbcUpload successfully mounts with minimal default props", () => {
test('DbcUpload successfully mounts with minimal default props', () => {
const component = shallow(<DbcUpload />);
expect(component.exists()).toBe(true);
});

View File

@ -1,15 +1,15 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import EditMessageModal from '../../components/EditMessageModal';
import DbcUtils from '../../utils/dbc';
import DBC from '../../models/can/dbc';
global.__JEST__ = 1;
import EditMessageModal from "../../components/EditMessageModal";
import React from "react";
import { shallow, mount, render } from "enzyme";
import DbcUtils from "../../utils/dbc";
import DBC from "../../models/can/dbc";
test("EditMessageModal successfully mounts with minimal default props", () => {
test('EditMessageModal successfully mounts with minimal default props', () => {
const dbc = new DBC();
const frame = dbc.createFrame(0);
const message = DbcUtils.createMessageSpec(dbc, 0, "0", 1);
const message = DbcUtils.createMessageSpec(dbc, 0, '0', 1);
const component = shallow(
<EditMessageModal

View File

@ -1,15 +1,15 @@
import React from 'react';
import Moment from 'moment';
import { shallow, mount, render } from 'enzyme';
import Explorer from '../../components/Explorer';
global.__JEST__ = 1;
import Explorer from "../../components/Explorer";
import React from "react";
import Moment from "moment";
import { shallow, mount, render } from "enzyme";
test("Explorer successfully mounts with minimal default props", () => {
test('Explorer successfully mounts with minimal default props', () => {
const component = shallow(
<Explorer
url={null}
live={true}
live
messages={{}}
selectedMessage={null}
onConfirmedSignalChange={() => {}}
@ -21,7 +21,7 @@ test("Explorer successfully mounts with minimal default props", () => {
seekIndex={0}
currentParts={[0, 0]}
partsLoaded={0}
autoplay={true}
autoplay
showEditMessageModal={() => {}}
onPartChange={() => {}}
routeStartTime={Moment()}

View File

@ -1,12 +1,12 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import GithubDbcList from '../../components/GithubDbcList';
import OpenDbc from '../../api/OpenDbc';
global.__JEST__ = 1;
import GithubDbcList from "../../components/GithubDbcList";
import React from "react";
import { shallow, mount, render } from "enzyme";
import OpenDbc from "../../api/OpenDbc";
test("GithubDbcList successfully mounts with minimal default props", () => {
test('GithubDbcList successfully mounts with minimal default props', () => {
const openDbcClient = new OpenDbc(null);
const component = shallow(

View File

@ -1,11 +1,11 @@
import HLS from "../../components/HLS";
import React from "react";
import { shallow, mount, render } from "enzyme";
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import HLS from '../../components/HLS';
test("HLS successfully mounts with minimal default props", () => {
test('HLS successfully mounts with minimal default props', () => {
const component = shallow(
<HLS
source={"http://comma.ai"}
source="http://comma.ai"
startTime={0}
playbackSpeed={1}
onVideoElementAvailable={() => {}}

View File

@ -1,12 +1,12 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import LoadDbcModal from '../../components/LoadDbcModal';
import OpenDbc from '../../api/OpenDbc';
global.__JEST__ = 1;
import React from "react";
import { shallow, mount, render } from "enzyme";
import LoadDbcModal from "../../components/LoadDbcModal";
import OpenDbc from "../../api/OpenDbc";
test("LoadDbcModal successfully mounts with minimal default props", () => {
test('LoadDbcModal successfully mounts with minimal default props', () => {
const openDbcClient = new OpenDbc(null);
const component = shallow(
<LoadDbcModal

View File

@ -1,8 +1,8 @@
import LoadingBar from "../../components/LoadingBar";
import React from "react";
import { shallow, mount, render } from "enzyme";
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import LoadingBar from '../../components/LoadingBar';
test("LoadingBar successfully mounts with minimal default props", () => {
test('LoadingBar successfully mounts with minimal default props', () => {
const component = shallow(<LoadingBar />);
expect(component.exists()).toBe(true);
});

View File

@ -1,16 +1,16 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import MessageBytes from '../../components/MessageBytes';
import DbcUtils from '../../utils/dbc';
import DBC from '../../models/can/dbc';
global.__JEST__ = 1;
import React from "react";
import { shallow, mount, render } from "enzyme";
import MessageBytes from "../../components/MessageBytes";
import DbcUtils from "../../utils/dbc";
import DBC from "../../models/can/dbc";
test("MessageBytes successfully mounts with minimal default props", () => {
const message = DbcUtils.createMessageSpec(new DBC(), 0, "0", 1);
test('MessageBytes successfully mounts with minimal default props', () => {
const message = DbcUtils.createMessageSpec(new DBC(), 0, '0', 1);
const component = shallow(
<MessageBytes seekTime={0} message={message} live={true} />
<MessageBytes seekTime={0} message={message} live />
);
expect(component.exists()).toBe(true);
});

View File

@ -1,10 +1,10 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import Meta from '../../components/Meta';
global.__JEST__ = 1;
import Meta from "../../components/Meta";
import React from "react";
import { shallow, mount, render } from "enzyme";
test("Meta successfully mounts with minimal default props", () => {
test('Meta successfully mounts with minimal default props', () => {
const component = shallow(
<Meta
url={null}
@ -26,7 +26,7 @@ test("Meta successfully mounts with minimal default props", () => {
seekIndex={0}
maxByteStateChangeCount={0}
isDemo={false}
live={true}
live
/>
);
expect(component.exists()).toBe(true);

View File

@ -1,10 +1,10 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import PartSelector from '../../components/PartSelector';
global.__JEST__ = 1;
import PartSelector from "../../components/PartSelector";
import React from "react";
import { shallow, mount, render } from "enzyme";
test("PartSelector successfully mounts with minimal default props", () => {
test('PartSelector successfully mounts with minimal default props', () => {
const component = shallow(
<PartSelector onPartChange={() => {}} partsCount={0} selectedPart={0} />
);

View File

@ -1,10 +1,10 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import PlayButton from '../../components/PlayButton';
global.__JEST__ = 1;
import PlayButton from "../../components/PlayButton";
import React from "react";
import { shallow, mount, render } from "enzyme";
test("PlayButton successfully mounts with minimal default props", () => {
test('PlayButton successfully mounts with minimal default props', () => {
const component = shallow(<PlayButton />);
expect(component.exists()).toBe(true);
});

View File

@ -1,10 +1,10 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import RouteSeeker from '../../components/RouteSeeker';
global.__JEST__ = 1;
import RouteSeeker from "../../components/RouteSeeker";
import React from "react";
import { shallow, mount, render } from "enzyme";
test("RouteSeeker successfully mounts with minimal default props", () => {
test('RouteSeeker successfully mounts with minimal default props', () => {
const component = shallow(
<RouteSeeker
nearestFrameTime={0}

View File

@ -1,10 +1,10 @@
global.__JEST__ = 1;
import API from '@commaai/comma-api';
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import { StyleSheetTestUtils } from 'aphrodite';
import RouteVideoSync from '../../components/RouteVideoSync';
import API from "@commaai/comma-api";
import RouteVideoSync from "../../components/RouteVideoSync";
import React from "react";
import { shallow, mount, render } from "enzyme";
import { StyleSheetTestUtils } from "aphrodite";
global.__JEST__ = 1;
// Prevents style injection from firing after test finishes
// and jsdom is torn down.
@ -15,7 +15,7 @@ afterEach(() => {
StyleSheetTestUtils.clearBufferAndResumeStyleInjection();
});
test("RouteVideoSync successfully mounts with minimal default props", () => {
test('RouteVideoSync successfully mounts with minimal default props', () => {
const component = shallow(
<RouteVideoSync
message={null}
@ -26,7 +26,7 @@ test("RouteVideoSync successfully mounts with minimal default props", () => {
userSeekIndex={0}
playing={false}
playSpeed={1}
url={"http://comma.ai"}
url="http://comma.ai"
canFrameOffset={0}
firstCanTime={0}
onVideoClick={() => {}}

View File

@ -1,19 +1,19 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import SaveDbcModal from '../../components/SaveDbcModal';
import OpenDbc from '../../api/OpenDbc';
import DBC from '../../models/can/dbc';
global.__JEST__ = 1;
import React from "react";
import { shallow, mount, render } from "enzyme";
import SaveDbcModal from "../../components/SaveDbcModal";
import OpenDbc from "../../api/OpenDbc";
import DBC from "../../models/can/dbc";
test("SaveDbcModal successfully mounts with minimal default props", () => {
test('SaveDbcModal successfully mounts with minimal default props', () => {
const openDbcClient = new OpenDbc(null);
const dbc = new DBC();
const component = shallow(
<SaveDbcModal
dbc={dbc}
sourceDbcFilename={""}
sourceDbcFilename=""
onDbcSaved={() => {}}
handleClose={() => {}}
openDbcClient={openDbcClient}

View File

@ -1,10 +1,10 @@
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import SignalLegend from '../../components/SignalLegend';
global.__JEST__ = 1;
import SignalLegend from "../../components/SignalLegend";
import React from "react";
import { shallow, mount, render } from "enzyme";
test("SignalLegend successfully mounts with minimal default props", () => {
test('SignalLegend successfully mounts with minimal default props', () => {
const component = shallow(
<SignalLegend
signals={{}}

View File

@ -1,6 +1,6 @@
import { shade } from "../../utils/color";
import { shade } from '../../utils/color';
test("Shade darkens rgb white (255,255,255)", () => {
test('Shade darkens rgb white (255,255,255)', () => {
const rgb = [255, 255, 255];
const darkenRgb = shade(rgb, -0.5);

View File

@ -1,21 +1,23 @@
global.__JEST__ = 1;
import extend from 'xtend';
import DbcUtils from '../../utils/dbc';
import DBC from '../../models/can/dbc';
import Signal from '../../models/can/signal';
import DbcUtils from "../../utils/dbc";
import DBC from "../../models/can/dbc";
import Signal from "../../models/can/signal";
import extend from "xtend";
global.__JEST__ = 1;
// want to mock pandareader and test processStreamedCanMessages
const SAMPLE_MESSAGE = {
address: 0x10,
busTime: 0,
data: Buffer.from("abababababababab", "hex"),
data: Buffer.from('abababababababab', 'hex'),
bus: 1
};
const SAMPLE_MESSAGE_ID = "1:10";
const SAMPLE_MESSAGE_ID = '1:10';
function expectSampleMessageFieldsPreserved(messages, frame) {
const { address, busTime, data, bus } = SAMPLE_MESSAGE;
const {
address, busTime, data, bus
} = SAMPLE_MESSAGE;
expect(messages[SAMPLE_MESSAGE_ID].address).toEqual(address);
expect(messages[SAMPLE_MESSAGE_ID].id).toEqual(SAMPLE_MESSAGE_ID);
expect(messages[SAMPLE_MESSAGE_ID].bus).toEqual(bus);
@ -28,7 +30,7 @@ function expectSampleMessageFieldsPreserved(messages, frame) {
// function addCanMessage([address, busTime, data, bus], dbc, canStartTime, messages, prevMsgEntries, byteStateChangeCountsByMessage) {
function addMessages(messages, message, dbc, n) {
const firstCanTime = 0;
let nextMessage = () => {
const nextMessage = () => {
message = extend(message);
message.busTime += 1;
return message;
@ -38,7 +40,7 @@ function addMessages(messages, message, dbc, n) {
DbcUtils.addCanMessage(nextMessage(), dbc, firstCanTime, messages, {}, {});
}
}
test("addCanMessage should add raw can message with empty dbc", () => {
test('addCanMessage should add raw can message with empty dbc', () => {
const messages = {};
addMessages(messages, SAMPLE_MESSAGE, new DBC(), 1);
@ -46,7 +48,7 @@ test("addCanMessage should add raw can message with empty dbc", () => {
expectSampleMessageFieldsPreserved(messages);
});
test("addCanMessage should add multiple raw can messages with empty dbc", () => {
test('addCanMessage should add multiple raw can messages with empty dbc', () => {
const messages = {};
addMessages(messages, SAMPLE_MESSAGE, new DBC(), 3);
@ -54,12 +56,12 @@ test("addCanMessage should add multiple raw can messages with empty dbc", () =>
expectSampleMessageFieldsPreserved(messages);
});
test("addCanMessage should add parsed can message with dbc containing message spec", () => {
test('addCanMessage should add parsed can message with dbc containing message spec', () => {
const messages = {};
// create dbc with message spec and signal for sample_message
const dbc = new DBC();
dbc.createFrame(SAMPLE_MESSAGE.address);
const signal = new Signal({ name: "NEW_SIGNAL", startBit: 0, size: 8 });
const signal = new Signal({ name: 'NEW_SIGNAL', startBit: 0, size: 8 });
dbc.addSignal(SAMPLE_MESSAGE.address, signal);
// add 1 sample_message

View File

@ -1,4 +1,4 @@
import DBC from "./models/can/dbc";
import DBC from './models/can/dbc';
const AcuraDbc = new DBC(`
VERSION ""

View File

@ -1,12 +1,12 @@
import GitHub from "github-api";
import GitHub from 'github-api';
import { OPENDBC_SOURCE_REPO } from "../config";
import { OPENDBC_SOURCE_REPO } from '../config';
export default class OpenDBC {
constructor(token) {
this.token = token;
this.github = new GitHub({ token });
this.sourceRepo = this.github.getRepo("commaai", "opendbc");
this.sourceRepo = this.github.getRepo('commaai', 'opendbc');
this.githubUsername = null;
}
@ -17,11 +17,10 @@ export default class OpenDBC {
async getGithubUsername() {
if (this.githubUsername) {
return this.githubUsername;
} else {
const githubUsername = await this.fetchGithubUsername();
if (githubUsername) {
return githubUsername;
}
}
const githubUsername = await this.fetchGithubUsername();
if (githubUsername) {
return githubUsername;
}
}
@ -50,13 +49,13 @@ export default class OpenDBC {
if (repoFullName === undefined) {
repo = this.sourceRepo;
} else {
const [username, repoName] = repoFullName.split("/");
const [username, repoName] = repoFullName.split('/');
repo = this.github.getRepo(username, repoName);
}
try {
const response = await repo.getContents("master", "");
const response = await repo.getContents('master', '');
return response.data.map(content => content.path);
return response.data.map((content) => content.path);
} catch (e) {
return [];
}
@ -67,15 +66,15 @@ export default class OpenDBC {
if (repoFullName === undefined) {
repo = this.sourceRepo;
} else {
const [username, repoName] = repoFullName.split("/");
const [username, repoName] = repoFullName.split('/');
repo = this.github.getRepo(username, repoName);
}
const fileContents = await repo.getContents("master", dbcPath);
const fileContents = await repo.getContents('master', dbcPath);
const rawContentsUrl = fileContents.data.download_url;
const resp = await fetch(rawContentsUrl, { cache: "no-cache" });
const resp = await fetch(rawContentsUrl, { cache: 'no-cache' });
return resp.text();
}
@ -90,24 +89,22 @@ export default class OpenDBC {
const githubUsername = await this.getGithubUsername();
if (!githubUsername) return null;
const openDbcFork = this.github.getRepo(githubUsername, "opendbc");
const openDbcFork = this.github.getRepo(githubUsername, 'opendbc');
const repoDetailResp = await openDbcFork.getDetails();
const repoDetails = repoDetailResp.data;
if (this.repoSourceIsOpenDbc(repoDetails)) {
return repoDetails.full_name;
} else {
return null;
}
return null;
}
async fork() {
const forkResponse = await this.sourceRepo.fork();
if (forkResponse.status === 202) {
return true;
} else {
return false;
}
return false;
}
async commitFile(repoFullName, path, contents, commitMessage) {
@ -115,11 +112,11 @@ export default class OpenDBC {
repo is of format username/reponame
authenciated user must have write access to repo
*/
const [user, repoName] = repoFullName.split("/");
const [user, repoName] = repoFullName.split('/');
const repo = this.github.getRepo(user, repoName);
// get HEAD reference
const refResp = await repo.getRef("heads/master");
const refResp = await repo.getRef('heads/master');
const ref = refResp.data;
// get HEAD commit sha
@ -133,9 +130,9 @@ export default class OpenDBC {
// create new tree
const tree = [
{
mode: "100644",
path: path,
type: "blob",
mode: '100644',
path,
type: 'blob',
content: contents
}
];
@ -147,13 +144,13 @@ export default class OpenDBC {
const commitResp = await repo.commit(
headCommit.sha,
createdTree.sha,
commitMessage || "OpenDBC updates"
commitMessage || 'OpenDBC updates'
);
const commit = commitResp.data;
// update HEAD
const updateHeadResp = await repo.updateHead(
"heads/master",
'heads/master',
commit.sha,
false
);

View File

@ -1,11 +1,11 @@
import { GITHUB_CLIENT_ID, GITHUB_REDIRECT_URL } from "../config";
import { objToQuery } from "../utils/url";
import { GITHUB_CLIENT_ID, GITHUB_REDIRECT_URL } from '../config';
import { objToQuery } from '../utils/url';
export function authorizeUrl(route) {
const params = {
client_id: GITHUB_CLIENT_ID,
redirect_uri: GITHUB_REDIRECT_URL,
scope: "user:email public_repo",
scope: 'user:email public_repo',
state: JSON.stringify({ route })
};

View File

@ -1,4 +1,4 @@
import DBC from "../models/can/dbc";
import DBC from '../models/can/dbc';
export function fetchPersistedDbc(routeName) {
const maybeDbc = window.localStorage.getItem(routeName);
@ -7,7 +7,8 @@ export function fetchPersistedDbc(routeName) {
const dbc = new DBC(dbcText);
return { dbc, dbcText, dbcFilename };
} else return null;
}
return null;
}
export function persistDbc(routeName, { dbcFilename, dbc }) {
@ -18,7 +19,7 @@ export function persistDbc(routeName, { dbcFilename, dbc }) {
window.localStorage.setItem(routeName, dbcJson);
}
const GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY = "gh_auth_token";
const GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY = 'gh_auth_token';
export function fetchPersistedGithubAuthToken() {
return window.localStorage.getItem(GITHUB_AUTH_TOKEN_LOCALSTORAGE_KEY);
}

View File

@ -1,13 +1,13 @@
import { raw as RawDataApi, request as Request } from "@commaai/comma-api";
import CommaAuth from "@commaai/my-comma-auth";
import request from "simple-get";
import { raw as RawDataApi, request as Request } from '@commaai/comma-api';
import CommaAuth from '@commaai/my-comma-auth';
import request from 'simple-get';
const urlStore = {};
var initPromise;
let initPromise;
function ensureInit() {
if (!initPromise) {
initPromise = CommaAuth.init().then(function(token) {
initPromise = CommaAuth.init().then((token) => {
Request.configure(token);
return Promise.resolve();
});
@ -16,8 +16,8 @@ function ensureInit() {
}
export async function getLogPart(logUrl) {
return new Promise(async function(resolve, reject) {
request(logUrl, function(err, res) {
return new Promise(async (resolve, reject) => {
request(logUrl, (err, res) => {
if (err) {
return reject(err);
}

View File

@ -1,5 +1,5 @@
import SocketIO from "socket.io-client";
import { UNLOGGER_HOST } from "../config";
import SocketIO from 'socket.io-client';
import { UNLOGGER_HOST } from '../config';
export default class UnloggerClient {
constructor() {
@ -7,6 +7,6 @@ export default class UnloggerClient {
}
seek(dongleId, baseTime, seekSeconds) {
this.socket.emit("seek", dongleId, baseTime, seekSeconds);
this.socket.emit('seek', dongleId, baseTime, seekSeconds);
}
}

View File

@ -1,4 +1,4 @@
import DBC from "./models/can/dbc";
import DBC from './models/can/dbc';
const CivicDbc = new DBC(`
VERSION ""

View File

@ -1,12 +1,12 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { StyleSheet } from "aphrodite/no-important";
import css from "../utils/css";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { StyleSheet } from 'aphrodite/no-important';
import css from '../utils/css';
import SignalLegend from "./SignalLegend";
import Signal from "../models/can/signal";
import { shade } from "../utils/color";
import DbcUtils from "../utils/dbc";
import SignalLegend from './SignalLegend';
import Signal from '../models/can/signal';
import { shade } from '../utils/color';
import DbcUtils from '../utils/dbc';
/*
AddSignals component draws an 8x8 matrix
@ -20,25 +20,25 @@ const Styles = StyleSheet.create({
bit: {
margin: 0,
padding: 12,
userSelect: "none",
cursor: "pointer",
textAlign: "center",
position: "relative"
userSelect: 'none',
cursor: 'pointer',
textAlign: 'center',
position: 'relative'
},
bitSelectedStyle: {
backgroundColor: "rgba(0,119,158,0.5)"
backgroundColor: 'rgba(0,119,158,0.5)'
},
bitSignificance: {
fontSize: 12,
display: "block",
position: "absolute",
display: 'block',
position: 'absolute',
bottom: 0,
left: 0,
right: 0,
margin: "0 auto"
margin: '0 auto'
},
highlightedSignalTitle: {
backgroundColor: "rgba(0,0,0,0.2)"
backgroundColor: 'rgba(0,0,0,0.2)'
}
});
@ -61,7 +61,7 @@ export default class AddSignals extends Component {
this.state = {
bits: [],
signals: signals,
signals,
signalStyles: this.calcSignalStyles(signals),
highlightedSignal: null,
dragStartBit: null,
@ -82,28 +82,29 @@ export default class AddSignals extends Component {
shouldComponentUpdate(nextProps, nextState) {
return (
nextProps.message.hexData !== this.props.message.hexData ||
nextProps.messageIndex !== this.props.messageIndex ||
JSON.stringify(nextProps.plottedSignalUids) !==
JSON.stringify(this.props.plottedSignalUids) ||
JSON.stringify(this.state) !== JSON.stringify(nextState)
nextProps.message.hexData !== this.props.message.hexData
|| nextProps.messageIndex !== this.props.messageIndex
|| JSON.stringify(nextProps.plottedSignalUids)
!== JSON.stringify(this.props.plottedSignalUids)
|| JSON.stringify(this.state) !== JSON.stringify(nextState)
);
}
signalColorStyle(signal) {
const { colors } = signal;
let colorRgbStr, backgroundColor;
let colorRgbStr;
let backgroundColor;
if (this.state && this.state.highlightedSignal === signal.name) {
// when signal highlighted,
// darkened background and lightened text.
const darkenedColors = shade(colors, -0.5);
const lightenedColors = shade(colors, 0.9);
colorRgbStr = `rgb(${lightenedColors.join(",")})`;
backgroundColor = `rgba(${darkenedColors.join(",")},0.5)`;
colorRgbStr = `rgb(${lightenedColors.join(',')})`;
backgroundColor = `rgba(${darkenedColors.join(',')},0.5)`;
} else {
const colorsCommaSep = colors.join(",");
const colorsCommaSep = colors.join(',');
colorRgbStr = `rgb(${colorsCommaSep})`;
backgroundColor = `rgba(${colorsCommaSep},0.2)`;
}
@ -122,7 +123,7 @@ export default class AddSignals extends Component {
calcSignalStyles(signals) {
const signalStyles = {};
Object.values(signals).forEach(signal => {
Object.values(signals).forEach((signal) => {
signalStyles[signal.name] = this.signalColorStyle(signal);
});
@ -145,12 +146,12 @@ export default class AddSignals extends Component {
// bitIdx in [0,64)
// returns instance of Signal
return Object.values(this.state.signals).filter(signal => {
return signal.bitDescription(bitIdx) !== null;
})[0];
return Object.values(this.state.signals).filter(
(signal) => signal.bitDescription(bitIdx) !== null
)[0];
}
onSignalHover = signal => {
onSignalHover = (signal) => {
if (!signal) return;
this.setState({ highlightedSignal: signal.name }, this.updateSignalStyles);
@ -214,22 +215,20 @@ export default class AddSignals extends Component {
dragSignal.size = bitIdx - dragStartBit + 1;
dragStartBit = bitIdx;
}
} else if (dragSignal.isLittleEndian) {
dragSignal.startBit = bitIdx;
dragSignal.size = dragStartBit - bitIdx + 1;
dragStartBit = bitIdx;
} else {
if (dragSignal.isLittleEndian) {
dragSignal.startBit = bitIdx;
dragSignal.size = dragStartBit - bitIdx + 1;
dragStartBit = bitIdx;
} else {
dragSignal.size = dragStartBit - bitIdx + 1;
dragStartBit = bitIdx;
}
dragSignal.size = dragStartBit - bitIdx + 1;
dragStartBit = bitIdx;
}
}
signals[dragSignal.name] = dragSignal;
} else if (
dragSignal.isLittleEndian &&
dragStartBit === dragSignal.msbBitIndex()
dragSignal.isLittleEndian
&& dragStartBit === dragSignal.msbBitIndex()
) {
if (bitIdx < dragSignal.startBit) {
// should not be able to drag the MSB past the LSB
@ -244,8 +243,8 @@ export default class AddSignals extends Component {
signals[dragSignal.name] = dragSignal;
dragStartBit = dragSignal.msbBitIndex();
} else if (
!dragSignal.isLittleEndian &&
dragStartBit === dragSignal.lsbBitIndex()
!dragSignal.isLittleEndian
&& dragStartBit === dragSignal.lsbBitIndex()
) {
const diff = bitIdx - dragStartBit;
if (dragSignal.bitDescription(bitIdx) === null) {
@ -271,7 +270,7 @@ export default class AddSignals extends Component {
}
};
onSignalHoverEnd = signal => {
onSignalHoverEnd = (signal) => {
if (!signal) return;
this.setState({ highlightedSignal: null }, this.updateSignalStyles);
@ -279,10 +278,10 @@ export default class AddSignals extends Component {
nextNewSignalName() {
const existingNames = Object.keys(this.state.signals);
let signalNum = 1,
signalName;
let signalNum = 1;
let signalName;
do {
signalName = "NEW_SIGNAL_" + signalNum;
signalName = `NEW_SIGNAL_${signalNum}`;
signalNum++;
} while (existingNames.indexOf(signalName) !== -1);
@ -300,7 +299,7 @@ export default class AddSignals extends Component {
const signal = new Signal({
name: this.nextNewSignalName(),
startBit,
size: size,
size,
isLittleEndian
});
let { signals } = this.state;
@ -319,10 +318,8 @@ export default class AddSignals extends Component {
return;
}
}
const isDragAcrossSingleByte =
Math.floor(dragEndBit / 8) === Math.floor(dragStartBit / 8);
const isDragDirectionUp =
!isDragAcrossSingleByte && dragEndBit < dragStartBit;
const isDragAcrossSingleByte = Math.floor(dragEndBit / 8) === Math.floor(dragStartBit / 8);
const isDragDirectionUp = !isDragAcrossSingleByte && dragEndBit < dragStartBit;
let isLittleEndian;
if (isDragAcrossSingleByte || !isDragDirectionUp) {
@ -330,30 +327,27 @@ export default class AddSignals extends Component {
} else {
isLittleEndian = dragStartBit % 8 >= 4;
}
let size,
startBit = dragStartBit;
let size;
let startBit = dragStartBit;
if (isDragAcrossSingleByte) {
size = Math.abs(dragEndBit - dragStartBit) + 1;
} else {
if (isLittleEndian) {
if (dragEndBit > dragStartBit) {
startBit = dragStartBit;
size = dragEndBit - dragStartBit + 1;
} else {
startBit = dragEndBit;
size = dragStartBit - dragEndBit + 1;
}
} else if (isLittleEndian) {
if (dragEndBit > dragStartBit) {
startBit = dragStartBit;
size = dragEndBit - dragStartBit + 1;
} else {
if (dragEndBit < dragStartBit) {
startBit = dragEndBit;
}
size =
Math.abs(
DbcUtils.bigEndianBitIndex(dragEndBit) -
DbcUtils.bigEndianBitIndex(dragStartBit)
) + 1;
startBit = dragEndBit;
size = dragStartBit - dragEndBit + 1;
}
} else {
if (dragEndBit < dragStartBit) {
startBit = dragEndBit;
}
size = Math.abs(
DbcUtils.bigEndianBitIndex(dragEndBit)
- DbcUtils.bigEndianBitIndex(dragStartBit)
) + 1;
}
this.createSignal({ startBit, size, isLittleEndian });
@ -362,7 +356,7 @@ export default class AddSignals extends Component {
onBitMouseUp(dragEndBit, signal) {
if (this.state.dragStartBit !== null) {
let { dragStartBit } = this.state;
const { dragStartBit } = this.state;
if (dragEndBit !== dragStartBit) {
// one-bit signal requires double click
@ -380,24 +374,22 @@ export default class AddSignals extends Component {
const entry = entries[this.props.messageIndex];
return entry.hexData.substr(byteIdx * 2, 2);
} else {
return "--";
}
return '--';
}
bitValue(byteIdx, byteBitIdx) {
const { entries } = this.props.message;
if (this.props.messageIndex < entries.length) {
const entry = entries[this.props.messageIndex];
const data = Buffer.from(entry.hexData, "hex");
const data = Buffer.from(entry.hexData, 'hex');
if (byteIdx >= data.length) {
return "-";
return '-';
}
const byte = data.readInt8(byteIdx);
return (byte >> byteBitIdx) & 1;
} else {
return "-";
}
return '-';
}
bitIsContainedInSelection(bitIdx, isLittleEndian = false) {
@ -405,22 +397,21 @@ export default class AddSignals extends Component {
if (isLittleEndian || dragStartBit % 8 < 4) {
return (
dragStartBit !== null &&
dragCurrentBit !== null &&
bitIdx >= dragStartBit &&
bitIdx <= dragCurrentBit
);
} else {
const bigEndianStartBit = DbcUtils.bigEndianBitIndex(dragStartBit);
const bigEndianCurrentBit = DbcUtils.bigEndianBitIndex(dragCurrentBit);
const bigEndianBitIdx = DbcUtils.bigEndianBitIndex(bitIdx);
return (
dragStartBit !== null &&
dragCurrentBit !== null &&
bigEndianBitIdx >= bigEndianStartBit &&
bigEndianBitIdx <= bigEndianCurrentBit
dragStartBit !== null
&& dragCurrentBit !== null
&& bitIdx >= dragStartBit
&& bitIdx <= dragCurrentBit
);
}
const bigEndianStartBit = DbcUtils.bigEndianBitIndex(dragStartBit);
const bigEndianCurrentBit = DbcUtils.bigEndianBitIndex(dragCurrentBit);
const bigEndianBitIdx = DbcUtils.bigEndianBitIndex(bitIdx);
return (
dragStartBit !== null
&& dragCurrentBit !== null
&& bigEndianBitIdx >= bigEndianStartBit
&& bigEndianBitIdx <= bigEndianCurrentBit
);
}
onBitDoubleClick(startBit, signal) {
@ -434,26 +425,26 @@ export default class AddSignals extends Component {
const rows = [];
let rowCount;
if (message.frame && message.frame.size) {
rowCount = Math.floor(message.frame.size * 8 / 8);
rowCount = Math.floor((message.frame.size * 8) / 8);
} else {
rowCount = 8;
}
for (var i = 0; i < rowCount; i++) {
for (let i = 0; i < rowCount; i++) {
const rowBits = [];
for (var j = 7; j >= 0; j--) {
for (let j = 7; j >= 0; j--) {
const bitIdx = i * 8 + j;
const signal = this.signalForBit(bitIdx);
let bitStyle = null,
bitSignificance = "";
let bitStyle = null;
let bitSignificance = '';
if (signal) {
bitStyle = this.state.signalStyles[signal.name] || null;
const bitDesc = signal.bitDescription(bitIdx);
bitSignificance = bitDesc.isMsb ? "msb" : bitDesc.isLsb ? "lsb" : "";
bitSignificance = bitDesc.isMsb ? 'msb' : bitDesc.isLsb ? 'lsb' : '';
} else if (this.bitIsContainedInSelection(bitIdx)) {
bitStyle = Styles.bitSelectedStyle;
}
const className = css("bit", Styles.bit, bitStyle);
const className = css('bit', Styles.bit, bitStyle);
const bitValue = this.bitValue(i, j);
rowBits.push(
@ -474,7 +465,7 @@ export default class AddSignals extends Component {
);
}
rowBits.push(<td key={"hex-repr"}>{this.byteValueHex(i)}</td>);
rowBits.push(<td key="hex-repr">{this.byteValueHex(i)}</td>);
rows.push(<tr key={i.toString()}>{rowBits}</tr>);
}
@ -495,7 +486,7 @@ export default class AddSignals extends Component {
});
};
onTentativeSignalChange = signal => {
onTentativeSignalChange = (signal) => {
// Tentative signal changes are not propagated up
// but their effects are displayed in the bitmatrix
const { signals } = this.state;
@ -506,7 +497,7 @@ export default class AddSignals extends Component {
onSignalChange = (signal, oldSignal) => {
const { signals } = this.state;
for (let signalName in signals) {
for (const signalName in signals) {
if (signals[signalName].uid === signal.uid) {
delete signals[signalName];
}
@ -516,7 +507,7 @@ export default class AddSignals extends Component {
this.setState({ signals }, this.propagateUpSignalChange);
};
onSignalRemove = signal => {
onSignalRemove = (signal) => {
const { signals } = this.state;
delete signals[signal.name];
this.setState({ signals }, this.propagateUpSignalChange);
@ -546,7 +537,8 @@ export default class AddSignals extends Component {
{this.props.message.entries[this.props.messageIndex] ? (
<div className="cabana-explorer-signals-time">
<p>
time:{" "}
time:
{' '}
{this.props.message.entries[
this.props.messageIndex
].relTime.toFixed(3)}

View File

@ -1,16 +1,16 @@
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 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 CanPlotSpec from "../vega/CanPlot";
import debounce from "../utils/debounce";
import Signal from '../models/can/signal';
import GraphData from '../models/graph-data';
import CanPlotSpec from '../vega/CanPlot';
import debounce from '../utils/debounce';
const DefaultPlotInnerStyle = {
position: "absolute",
position: 'absolute',
top: 0,
left: 0
};
@ -63,10 +63,10 @@ export default class CanGraph extends Component {
getGraphData(props) {
let firstRelTime = -1;
let lastRelTime = -1;
let series = props.plottedSignals
.map(signals => {
const series = props.plottedSignals
.map((signals) => {
const { messageId, signalUid } = signals;
let entries = props.messages[messageId].entries;
const { entries } = props.messages[messageId];
if (entries.length) {
let messageRelTime = entries[0].relTime;
if (firstRelTime === -1) {
@ -109,15 +109,15 @@ export default class CanGraph extends Component {
segmentIsNew(newSegment) {
return (
newSegment.length !== this.props.segment.length ||
!newSegment.every((val, idx) => this.props.segment[idx] === val)
newSegment.length !== this.props.segment.length
|| !newSegment.every((val, idx) => this.props.segment[idx] === val)
);
}
visualChanged(prevProps, nextProps) {
return (
prevProps.canReceiveGraphDrop !== nextProps.canReceiveGraphDrop ||
JSON.stringify(prevProps.dragPos) !== JSON.stringify(nextProps.dragPos)
prevProps.canReceiveGraphDrop !== nextProps.canReceiveGraphDrop
|| JSON.stringify(prevProps.dragPos) !== JSON.stringify(nextProps.dragPos)
);
}
@ -138,46 +138,46 @@ export default class CanGraph extends Component {
}
updateBounds = debounce(() => {
this.view.signal("width", this.state.bounds.width - 70);
this.view.signal("height", 0.4 * (this.state.bounds.width - 70)); // 5:2 aspect ratio
this.view.signal('width', this.state.bounds.width - 70);
this.view.signal('height', 0.4 * (this.state.bounds.width - 70)); // 5:2 aspect ratio
this.view.run();
}, 100);
insertData = debounce(() => {
if (!this.view) {
console.log("Cannot insertData");
console.log('Cannot insertData');
return;
}
// adding plot points by diff isn't faster since it basically has to be n^2
// out-of-order events make it so that you can't just check the bounds
let { series } = this.state.data;
let changeset = this.view
const { series } = this.state.data;
const changeset = this.view
.changeset()
.remove(v => true)
.remove((v) => true)
.insert(series);
this.view.change("table", changeset);
this.view.change('table', changeset);
this.view.run();
}, 250);
componentWillReceiveProps(nextProps) {
if (
nextProps.dragPos &&
JSON.stringify(nextProps.dragPos) !== JSON.stringify(this.props.dragPos)
nextProps.dragPos
&& JSON.stringify(nextProps.dragPos) !== JSON.stringify(this.props.dragPos)
) {
this.updateStyleFromDragPos(nextProps.dragPos);
} else if (!nextProps.dragPos && this.state.plotInnerStyle !== null) {
this.setState({ plotInnerStyle: null });
}
if (
this.props.messages !== nextProps.messages ||
this.props.plottedSignal !== nextProps.plottedSignal
this.props.messages !== nextProps.messages
|| this.props.plottedSignal !== nextProps.plottedSignal
) {
let data = this.getGraphData(nextProps);
const data = this.getGraphData(nextProps);
if (
data.series.length === this.state.data.series.length &&
data.firstRelTime === this.state.data.firstRelTime &&
data.lastRelTime === this.state.data.lastRelTime
data.series.length === this.state.data.series.length
&& data.firstRelTime === this.state.data.firstRelTime
&& data.lastRelTime === this.state.data.lastRelTime
) {
// do nothing, the data didn't *actually* change
} else {
@ -188,6 +188,7 @@ export default class CanGraph extends Component {
this.setState({ spec: this.getGraphSpec(nextProps) });
}
}
shouldComponentUpdate(nextProps, nextState) {
if (!this.view) {
return true;
@ -199,30 +200,31 @@ export default class CanGraph extends Component {
this.insertData();
}
if (this.props.currentTime !== nextProps.currentTime) {
this.view.signal("videoTime", nextProps.currentTime);
this.view.signal('videoTime', nextProps.currentTime);
}
if (this.segmentIsNew(nextProps.segment)) {
if (nextProps.segment.length > 0) {
// Set segmented domain
this.view.signal("segment", nextProps.segment);
this.view.signal('segment', nextProps.segment);
} else {
// Reset segment to full domain
this.view.signal("segment", 0);
this.view.signal('segment', 0);
}
}
this.view.runAsync();
return false;
}
componentDidUpdate(oldProps, oldState) {
if (this.view) {
if (this.props.segment.length > 0) {
// Set segmented domain
this.view.signal("segment", this.props.segment);
this.view.signal('segment', this.props.segment);
} else {
// Reset segment to full domain
this.view.signal("segment", 0);
this.view.signal('segment', 0);
}
this.view.signal("videoTime", this.props.currentTime);
this.view.signal('videoTime', this.props.currentTime);
this.view.runAsync();
}
}
@ -241,9 +243,9 @@ export default class CanGraph extends Component {
this.onPlotResize();
}
if (this.props.segment.length > 0) {
view.signal("segment", this.props.segment);
view.signal('segment', this.props.segment);
}
view.signal("videoTime", this.props.currentTime);
view.signal('videoTime', this.props.currentTime);
this.insertData();
}
@ -319,7 +321,7 @@ export default class CanGraph extends Component {
render() {
const { plotInnerStyle } = this.state;
const canReceiveDropClass = this.props.canReceiveGraphDrop
? "is-droppable"
? 'is-droppable'
: null;
return (
@ -329,7 +331,7 @@ export default class CanGraph extends Component {
>
<div
className={cx(
"cabana-explorer-visuals-plot-inner",
'cabana-explorer-visuals-plot-inner',
canReceiveDropClass
)}
style={plotInnerStyle || null}
@ -344,13 +346,13 @@ export default class CanGraph extends Component {
({ messageId, signalUid, messageName }) => {
const signal = Object.values(
this.props.messages[messageId].frame.signals
).find(s => s.uid === signalUid);
).find((s) => s.uid === signalUid);
const { colors } = signal;
return (
<div
className="cabana-explorer-visuals-plot-header"
key={messageId + "_" + signal.uid}
key={`${messageId}_${signal.uid}`}
>
<div className="cabana-explorer-visuals-plot-header-toggle">
<button
@ -377,29 +379,27 @@ export default class CanGraph extends Component {
}
)}
<Measure bounds onResize={this.onPlotResize}>
{({ measureRef }) => {
return (
<div
ref={measureRef}
className="cabana-explorer-visuals-plot-container"
>
<Vega
onNewView={this.onNewView}
logLevel={1}
signalListeners={{
clickTime: this.onSignalClickTime,
segment: this.onSignalSegment
}}
renderer={"canvas"}
spec={this.state.spec}
actions={false}
data={{
table: this.state.data.series
}}
/>
</div>
);
}}
{({ measureRef }) => (
<div
ref={measureRef}
className="cabana-explorer-visuals-plot-container"
>
<Vega
onNewView={this.onNewView}
logLevel={1}
signalListeners={{
clickTime: this.onSignalClickTime,
segment: this.onSignalSegment
}}
renderer="canvas"
spec={this.state.spec}
actions={false}
data={{
table: this.state.data.series
}}
/>
</div>
)}
</Measure>
</div>
</div>

View File

@ -1,9 +1,9 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import CanGraph from "./CanGraph";
import CanGraph from './CanGraph';
require("element-closest");
require('element-closest');
export default class CanGraphList extends Component {
static propTypes = {
@ -46,9 +46,8 @@ export default class CanGraphList extends Component {
determineDraggingGraph() {
const { draggingSignal } = this.state;
return this.plotRefs.find(
({ messageId, signalUid }) =>
draggingSignal.messageId === messageId &&
draggingSignal.signalUid === signalUid
({ messageId, signalUid }) => draggingSignal.messageId === messageId
&& draggingSignal.signalUid === signalUid
);
}
@ -66,13 +65,12 @@ export default class CanGraphList extends Component {
draggingGraph.ref.hidden = true;
const ele = document.elementFromPoint(e.clientX, e.clientY);
draggingGraph.ref.hidden = false;
const closestPlot = ele.closest(".cabana-explorer-visuals-plot");
const closestPlot = ele.closest('.cabana-explorer-visuals-plot');
const closestPlotRef = this.plotRefs.find(
({ ref, messageId, signalUid }) =>
!(
messageId === draggingGraph.messageId &&
signalUid === draggingGraph.signalUid
) && ref.isEqualNode(closestPlot)
({ ref, messageId, signalUid }) => !(
messageId === draggingGraph.messageId
&& signalUid === draggingGraph.signalUid
) && ref.isEqualNode(closestPlot)
);
if (closestPlotRef) {
this.setState({ graphToReceiveDrop: closestPlotRef });
@ -107,7 +105,7 @@ export default class CanGraphList extends Component {
let { plotRefs } = this;
plotRefs = plotRefs
.filter(
ref => !(ref.messageId === messageId && ref.signalUid === signalUid)
(ref) => !(ref.messageId === messageId && ref.signalUid === signalUid)
)
.concat([{ messageId, signalUid, ref }]);
this.plotRefs = plotRefs;
@ -119,33 +117,29 @@ export default class CanGraphList extends Component {
const { messageId, signalUid } = plottedSignals[0];
const msg = this.props.messages[messageId];
const signal = Object.values(msg.frame.signals).find(
s => s.uid === signalUid
(s) => s.uid === signalUid
);
if (!this.plotListRef) {
return [];
}
const isDragging =
draggingSignal.signalUid === signalUid &&
draggingSignal.messageId === messageId;
const canReceiveGraphDrop =
graphToReceiveDrop &&
graphToReceiveDrop.signalUid === signalUid &&
graphToReceiveDrop.messageId === messageId;
plottedSignals = plottedSignals.map(plottedSignal => {
return {
messageName: this.props.messages[plottedSignal.messageId].frame.name,
...plottedSignal
};
});
const isDragging = draggingSignal.signalUid === signalUid
&& draggingSignal.messageId === messageId;
const canReceiveGraphDrop = graphToReceiveDrop
&& graphToReceiveDrop.signalUid === signalUid
&& graphToReceiveDrop.messageId === messageId;
plottedSignals = plottedSignals.map((plottedSignal) => ({
messageName: this.props.messages[plottedSignal.messageId].frame.name,
...plottedSignal
}));
const key = plottedSignals.reduce(
(key, { messageId, signalUid }) => key + messageId + "_" + signalUid,
""
(key, { messageId, signalUid }) => `${key + messageId}_${signalUid}`,
''
);
return (
<CanGraph
onGraphRefAvailable={ref => {
onGraphRefAvailable={(ref) => {
this.addCanGraphRef(ref, messageId, signalUid);
}}
key={key}

View File

@ -1,8 +1,8 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import ReactList from "react-list";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import ReactList from 'react-list';
import cx from "classnames";
import cx from 'classnames';
export default class CanLog extends Component {
static ITEMS_PER_PAGE = 50;
@ -52,21 +52,20 @@ export default class CanLog extends Component {
? nextProps.message.entries.length
: 0;
const shouldUpdate =
this.props.message !== nextProps.message ||
nextMessageLength !== curMessageLength ||
nextProps.messageIndex !== this.props.messageIndex ||
nextProps.plottedSignals.length !== this.props.plottedSignals.length ||
JSON.stringify(nextProps.segmentIndices) !==
JSON.stringify(this.props.segmentIndices) ||
JSON.stringify(nextState) !== JSON.stringify(this.state) ||
this.props.message !== nextProps.message ||
(this.props.message !== undefined &&
nextProps.message !== undefined &&
this.props.message.frame !== undefined &&
nextProps.message.frame !== undefined &&
JSON.stringify(this.props.message.frame) !==
JSON.stringify(nextProps.message.frame));
const shouldUpdate = this.props.message !== nextProps.message
|| nextMessageLength !== curMessageLength
|| nextProps.messageIndex !== this.props.messageIndex
|| nextProps.plottedSignals.length !== this.props.plottedSignals.length
|| JSON.stringify(nextProps.segmentIndices)
!== JSON.stringify(this.props.segmentIndices)
|| JSON.stringify(nextState) !== JSON.stringify(this.state)
|| this.props.message !== nextProps.message
|| (this.props.message !== undefined
&& nextProps.message !== undefined
&& this.props.message.frame !== undefined
&& nextProps.message.frame !== undefined
&& JSON.stringify(this.props.message.frame)
!== JSON.stringify(nextProps.message.frame));
return shouldUpdate;
}
@ -88,24 +87,23 @@ export default class CanLog extends Component {
collapseMessage(msg, msgIdx) {
this.setState({
expandedMessages: this.state.expandedMessages.filter(
expMsgTime => expMsgTime !== msg.time
(expMsgTime) => expMsgTime !== msg.time
)
});
}
isSignalPlotted(msgId, signalUid) {
const plottedSignal = this.props.plottedSignals.find(plot =>
plot.some(
signal => signal.messageId === msgId && signal.signalUid === signalUid
)
);
const plottedSignal = this.props.plottedSignals.find((plot) => plot.some(
(signal) => signal.messageId === msgId && signal.signalUid === signalUid
));
return plottedSignal !== undefined;
}
signalValuePretty(signal, value) {
if (signal.isFloat) {
return value.toFixed(3);
} else return value;
}
return value;
}
isMessageExpanded(msg) {
@ -124,15 +122,13 @@ export default class CanLog extends Component {
if (!this.props.message.frame) {
return;
}
const msgIsExpanded =
this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry);
const msgIsExpanded = this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry);
const msgHasSignals =
Object.keys(this.props.message.frame.signals).length > 0;
const msgHasSignals = Object.keys(this.props.message.frame.signals).length > 0;
if (msgIsExpanded && msgHasSignals) {
this.setState({
expandedMessages: this.state.expandedMessages.filter(
expMsgTime => expMsgTime !== msgEntry.time
(expMsgTime) => expMsgTime !== msgEntry.time
)
});
} else if (msgHasSignals) {
@ -141,7 +137,6 @@ export default class CanLog extends Component {
});
this.props.onMessageExpanded();
} else {
return;
}
}
@ -155,10 +150,10 @@ export default class CanLog extends Component {
// Signal removed?
return null;
}
const unit = signal.unit.length > 0 ? signal.unit : "units";
const unit = signal.unit.length > 0 ? signal.unit : 'units';
const isPlotted = this.isSignalPlotted(message.id, signal.uid);
const plottedButtonClass = isPlotted ? null : "button--alpha";
const plottedButtonText = isPlotted ? "Hide Plot" : "Show Plot";
const plottedButtonClass = isPlotted ? null : 'button--alpha';
const plottedButtonText = isPlotted ? 'Hide Plot' : 'Show Plot';
return (
<div key={name} className="signals-log-list-signal">
<div className="signals-log-list-signal-message">
@ -166,8 +161,11 @@ export default class CanLog extends Component {
</div>
<div className="signals-log-list-signal-value">
<span>
(<strong>{this.signalValuePretty(signal, value)}</strong>{" "}
{unit})
(
<strong>{this.signalValuePretty(signal, value)}</strong>
{' '}
{unit}
)
</span>
</div>
<div
@ -176,7 +174,7 @@ export default class CanLog extends Component {
this.toggleSignalPlot(message.id, signal.uid, isPlotted);
}}
>
<button className={cx("button--tiny", plottedButtonClass)}>
<button className={cx('button--tiny', plottedButtonClass)}>
<span>{plottedButtonText}</span>
</button>
</div>
@ -189,15 +187,14 @@ export default class CanLog extends Component {
renderLogListItemMessage(msgEntry, key) {
const { message } = this.props;
const msgIsExpanded =
this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry);
const msgIsExpanded = this.state.allPacketsExpanded || this.isMessageExpanded(msgEntry);
const msgHasSignals = Object.keys(msgEntry.signals).length > 0;
const hasSignalsClass = msgHasSignals ? "has-signals" : null;
const expandedClass = msgIsExpanded ? "is-expanded" : null;
const hasSignalsClass = msgHasSignals ? 'has-signals' : null;
const expandedClass = msgIsExpanded ? 'is-expanded' : null;
const row = (
<div
key={key}
className={cx("signals-log-list-item", hasSignalsClass, expandedClass)}
className={cx('signals-log-list-item', hasSignalsClass, expandedClass)}
>
<div
className="signals-log-list-item-header"
@ -211,7 +208,11 @@ export default class CanLog extends Component {
</strong>
</div>
<div className="signals-log-list-time">
<span>[{msgEntry.relTime.toFixed(3)}]</span>
<span>
[
{msgEntry.relTime.toFixed(3)}
]
</span>
</div>
<div className="signals-log-list-bytes">
<span className="t-mono">{msgEntry.hexData}</span>
@ -239,9 +240,8 @@ export default class CanLog extends Component {
this.props.message.entries[offset + index],
key
);
} else {
return null;
}
return null;
}
renderLogList(items, ref) {
@ -263,14 +263,15 @@ export default class CanLog extends Component {
const { segmentIndices, messageIndex } = this.props;
if (messageIndex > 0) {
return this.props.message.entries.length - messageIndex;
} else if (segmentIndices.length === 2) {
return segmentIndices[1] - segmentIndices[0];
} else if (this.props.message) {
return this.props.message.entries.length;
} else {
// no message yet
return 0;
}
if (segmentIndices.length === 2) {
return segmentIndices[1] - segmentIndices[0];
}
if (this.props.message) {
return this.props.message.entries.length;
}
// no message yet
return 0;
}
onExpandAllChanged(e) {
@ -282,16 +283,18 @@ export default class CanLog extends Component {
}
render() {
let expandAllText = this.state.allPacketsExpanded
? "Collapse All"
: "Expand All";
let expandAllClass = this.state.allPacketsExpanded ? null : "button--alpha";
const expandAllText = this.state.allPacketsExpanded
? 'Collapse All'
: 'Expand All';
const expandAllClass = this.state.allPacketsExpanded
? null
: 'button--alpha';
return (
<div className="cabana-explorer-signals-log">
<div className="cabana-explorer-signals-log-header">
<strong>Message Packets</strong>
<button
className={cx("button--tiny", expandAllClass)}
className={cx('button--tiny', expandAllClass)}
onClick={this.toggleExpandAllPackets}
>
{expandAllText}

View File

@ -1,14 +1,15 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class DbcUpload extends Component {
static propTypes = {
onDbcLoaded: PropTypes.func
};
constructor(props) {
super(props);
this.state = {
dbcText: ""
dbcText: ''
};
this.onTextChanged = this.onTextChanged.bind(this);
@ -17,7 +18,7 @@ export default class DbcUpload extends Component {
onTextChanged(e) {
const dbcText = e.target.value;
this.setState({ dbcText });
this.props.onDbcLoaded("from paste", dbcText);
this.props.onDbcLoaded('from paste', dbcText);
}
render() {

View File

@ -1,7 +1,7 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Modal from "./Modals/baseModal";
import Modal from './Modals/baseModal';
export default class EditMessageModal extends Component {
static propTypes = {
@ -32,9 +32,7 @@ export default class EditMessageModal extends Component {
this.setState({ messageFrame });
}
editTransmitter(transmitter) {
return;
}
editTransmitter(transmitter) {}
renderActions() {
return (
@ -67,7 +65,7 @@ export default class EditMessageModal extends Component {
type="text"
id="message_name"
value={this.state.messageFrame.name}
onChange={e => {
onChange={(e) => {
const { messageFrame } = this.state;
messageFrame.name = e.target.value;
this.setState({ messageFrame });
@ -83,7 +81,7 @@ export default class EditMessageModal extends Component {
type="number"
id="message_size"
value={this.state.messageFrame.size}
onChange={e => {
onChange={(e) => {
const { messageFrame } = this.state;
if (e.target.value > 8) {
return;
@ -102,23 +100,21 @@ export default class EditMessageModal extends Component {
</label>
<div className="form-field-inset">
<ul className="form-field-inset-list">
{this.state.messageFrame.transmitters.map(transmitter => {
return (
<li className="form-field-inset-list-item" key={transmitter}>
<div className="form-field-inset-list-item-title">
<span>{transmitter}</span>
</div>
<div className="form-field-inset-list-item-action">
<button className="button--tiny button--alpha">
Edit
</button>
</div>
</li>
);
})}
{this.state.messageFrame.transmitters.map((transmitter) => (
<li className="form-field-inset-list-item" key={transmitter}>
<div className="form-field-inset-list-item-title">
<span>{transmitter}</span>
</div>
<div className="form-field-inset-list-item-action">
<button className="button--tiny button--alpha">Edit</button>
</div>
</li>
))}
<button className="button--tiny button--alpha">
<span>
<i className="fa fa-plus" /> Add Transmitter
<i className="fa fa-plus" />
{' '}
Add Transmitter
</span>
</button>
</ul>

View File

@ -1,16 +1,16 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import cx from "classnames";
import cx from 'classnames';
import AddSignals from "./AddSignals";
import CanGraphList from "./CanGraphList";
import RouteVideoSync from "./RouteVideoSync";
import CanLog from "./CanLog";
import Entries from "../models/can/entries";
import debounce from "../utils/debounce";
import PartSelector from "./PartSelector";
import PlaySpeedSelector from "./PlaySpeedSelector";
import AddSignals from './AddSignals';
import CanGraphList from './CanGraphList';
import RouteVideoSync from './RouteVideoSync';
import CanLog from './CanLog';
import Entries from '../models/can/entries';
import debounce from '../utils/debounce';
import PartSelector from './PartSelector';
import PlaySpeedSelector from './PlaySpeedSelector';
export default class Explorer extends Component {
static propTypes = {
@ -66,20 +66,20 @@ export default class Explorer extends Component {
}
componentWillMount() {
document.addEventListener("keydown", this._onKeyDown);
document.addEventListener('keydown', this._onKeyDown);
}
componentWillUnmount() {
document.removeEventListener("keydown", this._onKeyDown);
document.removeEventListener('keydown', this._onKeyDown);
}
clipSegment(segment, segmentIndices, nextMessage) {
if (segment.length === 2) {
const segmentStartIdx = nextMessage.entries.findIndex(
e => e.relTime >= segment[0]
(e) => e.relTime >= segment[0]
);
let segmentEndIdx = nextMessage.entries.findIndex(
e => e.relTime >= segment[1]
(e) => e.relTime >= segment[1]
);
if (segmentStartIdx !== -1) {
if (segmentEndIdx === -1) {
@ -119,32 +119,30 @@ export default class Explorer extends Component {
// remove plottedSignals that no longer exist
plottedSignals = plottedSignals
.map(plot =>
plot.filter(({ messageId, signalUid }, index) => {
const messageExists = !!nextProps.messages[messageId];
let signalExists = true;
if (messageExists) {
signalExists = Object.values(
nextProps.messages[messageId].frame.signals
).some(signal => signal.uid === signalUid);
}
.map((plot) => plot.filter(({ messageId, signalUid }, index) => {
const messageExists = !!nextProps.messages[messageId];
let signalExists = true;
if (messageExists) {
signalExists = Object.values(
nextProps.messages[messageId].frame.signals
).some((signal) => signal.uid === signalUid);
}
return messageExists && signalExists;
})
)
.filter(plot => plot.length > 0);
return messageExists && signalExists;
}))
.filter((plot) => plot.length > 0);
this.setState({ plottedSignals });
if (
nextProps.selectedMessage &&
nextProps.selectedMessage !== this.props.selectedMessage
nextProps.selectedMessage
&& nextProps.selectedMessage !== this.props.selectedMessage
) {
// Update segment and seek state
// by finding a entry indices
// corresponding to old message segment/seek times.
let { segment, segmentIndices } = this.clipSegment(
const { segment, segmentIndices } = this.clipSegment(
this.state.segment,
this.state.segmentIndices,
nextMessage
@ -169,11 +167,11 @@ export default class Explorer extends Component {
}
if (
nextMessage &&
curMessage &&
nextMessage.entries.length !== curMessage.entries.length
nextMessage
&& curMessage
&& nextMessage.entries.length !== curMessage.entries.length
) {
let { segment, segmentIndices } = this.clipSegment(
const { segment, segmentIndices } = this.clipSegment(
this.state.segment,
this.state.segmentIndices,
nextMessage
@ -193,20 +191,21 @@ export default class Explorer extends Component {
const { routeStartTime, currentParts } = this.props;
if (routeStartTime) {
const partStartOffset = currentParts[0] * 60,
partEndOffset = (currentParts[1] + 1) * 60;
const partStartOffset = currentParts[0] * 60;
const partEndOffset = (currentParts[1] + 1) * 60;
const windowStartTime = routeStartTime
.clone()
.add(partStartOffset, "s")
.format("HH:mm:ss");
.add(partStartOffset, 's')
.format('HH:mm:ss');
const windowEndTime = routeStartTime
.clone()
.add(partEndOffset, "s")
.format("HH:mm:ss");
.add(partEndOffset, 's')
.format('HH:mm:ss');
return `${windowStartTime} - ${windowEndTime}`;
} else return "";
}
return '';
}
onSignalPlotPressed(messageId, signalUid) {
@ -220,13 +219,10 @@ export default class Explorer extends Component {
onSignalUnplotPressed(messageId, signalUid) {
const { plottedSignals } = this.state;
const newPlottedSignals = plottedSignals
.map(plot =>
plot.filter(
signal =>
!(signal.messageId === messageId && signal.signalUid === signalUid)
)
)
.filter(plot => plot.length > 0);
.map((plot) => plot.filter(
(signal) => !(signal.messageId === messageId && signal.signalUid === signalUid)
))
.filter((plot) => plot.length > 0);
this.setState({ plottedSignals: newPlottedSignals });
}
@ -237,8 +233,8 @@ export default class Explorer extends Component {
// console.log(this.state.segment, '->', segment, segmentIndices);
if (
segment[0] === this.props.currentParts[0] * 60 &&
segment[1] === (this.props.currentParts[1] + 1) * 60
segment[0] === this.props.currentParts[0] * 60
&& segment[1] === (this.props.currentParts[1] + 1) * 60
) {
segment = [];
segmentIndices = [];
@ -297,14 +293,13 @@ export default class Explorer extends Component {
}
}
return segmentIndices[1];
} else {
for (let i = 0; i < entries.length; i++) {
if (entries[i].relTime >= time) {
return i;
}
}
return entries.length - 1;
}
for (let i = 0; i < entries.length; i++) {
if (entries[i].relTime >= time) {
return i;
}
}
return entries.length - 1;
}
onUserSeek(time) {
@ -377,24 +372,20 @@ export default class Explorer extends Component {
selectedMessagePlottedSignalUids() {
const { plottedSignals } = this.state;
return plottedSignals
.map(plot =>
plot
.filter(
({ messageId, signalUid }) =>
messageId === this.props.selectedMessage
)
.map(({ signalUid }) => signalUid)
)
.map((plot) => plot
.filter(
({ messageId, signalUid }) => messageId === this.props.selectedMessage
)
.map(({ signalUid }) => signalUid))
.reduce((arr, signalUid) => arr.concat(signalUid), []);
}
renderExplorerSignals() {
const selectedMessageKey = this.props.selectedMessage;
const selectedMessage = this.props.messages[selectedMessageKey];
const selectedMessageName =
selectedMessage.frame !== undefined
? selectedMessage.frame.name
: "undefined";
const selectedMessageName = selectedMessage.frame !== undefined
? selectedMessage.frame.name
: 'undefined';
return (
<div className="cabana-explorer-signals-wrapper">
<div className="cabana-explorer-signals-header">
@ -405,9 +396,7 @@ export default class Explorer extends Component {
<div className="cabana-explorer-signals-header-action">
<button
className="button--small"
onClick={() =>
this.props.showEditMessageModal(selectedMessageKey)
}
onClick={() => this.props.showEditMessageModal(selectedMessageKey)}
>
Edit
</button>
@ -448,25 +437,19 @@ export default class Explorer extends Component {
}
mergePlots({ fromPlot, toPlot }) {
let { plottedSignals } = this.state;
const { plottedSignals } = this.state;
// remove fromPlot from plottedSignals
const fromPlotIdx = plottedSignals.findIndex(plot =>
plot.some(
signal =>
signal.signalUid === fromPlot.signalUid &&
signal.messageId === fromPlot.messageId
)
);
const fromPlotIdx = plottedSignals.findIndex((plot) => plot.some(
(signal) => signal.signalUid === fromPlot.signalUid
&& signal.messageId === fromPlot.messageId
));
plottedSignals.splice(fromPlotIdx, 1);
const toPlotIdx = plottedSignals.findIndex(plot =>
plot.some(
signal =>
signal.signalUid === toPlot.signalUid &&
signal.messageId === toPlot.messageId
)
);
const toPlotIdx = plottedSignals.findIndex((plot) => plot.some(
(signal) => signal.signalUid === toPlot.signalUid
&& signal.messageId === toPlot.messageId
));
plottedSignals[toPlotIdx] = [fromPlot, toPlot];
this.setState({ plottedSignals });
@ -474,7 +457,7 @@ export default class Explorer extends Component {
render() {
const signalsExpandedClass = this.state.shouldShowAddSignal
? "is-expanded"
? 'is-expanded'
: null;
let graphSegment = this.state.segment;
@ -487,7 +470,7 @@ export default class Explorer extends Component {
return (
<div className="cabana-explorer">
<div className={cx("cabana-explorer-signals", signalsExpandedClass)}>
<div className={cx('cabana-explorer-signals', signalsExpandedClass)}>
{this.props.messages[this.props.selectedMessage]
? this.renderExplorerSignals()
: this.renderSelectMessagePrompt()}
@ -522,7 +505,7 @@ export default class Explorer extends Component {
) : null}
{this.state.segment.length > 0 ? (
<div
className={"cabana-explorer-visuals-segmentreset"}
className="cabana-explorer-visuals-segmentreset"
onClick={() => {
this.resetSegment();
}}

View File

@ -1,8 +1,8 @@
import React, { Component } from "react";
import cx from "classnames";
import PropTypes from "prop-types";
import React, { Component } from 'react';
import cx from 'classnames';
import PropTypes from 'prop-types';
import OpenDbc from "../api/OpenDbc";
import OpenDbc from '../api/OpenDbc';
export default class GithubDbcList extends Component {
static propTypes = {
@ -17,7 +17,7 @@ export default class GithubDbcList extends Component {
this.state = {
paths: [],
selectedPath: null,
pathQuery: ""
pathQuery: ''
};
this.updatePathQuery = this.updatePathQuery.bind(this);
@ -25,15 +25,15 @@ export default class GithubDbcList extends Component {
componentWillReceiveProps(nextProps) {
if (nextProps.repo !== this.props.repo) {
this.props.openDbcClient.list(nextProps.repo).then(paths => {
this.props.openDbcClient.list(nextProps.repo).then((paths) => {
this.setState({ paths, selectedPath: null });
});
}
}
componentWillMount() {
this.props.openDbcClient.list(this.props.repo).then(paths => {
paths = paths.filter(path => path.indexOf(".dbc") !== -1);
this.props.openDbcClient.list(this.props.repo).then((paths) => {
paths = paths.filter((path) => path.indexOf('.dbc') !== -1);
this.setState({ paths });
});
}
@ -48,7 +48,7 @@ export default class GithubDbcList extends Component {
this.setState({ selectedPath: path });
this.props.openDbcClient
.getDbcContents(path, this.props.repo)
.then(dbcContents => {
.then((dbcContents) => {
this.props.onDbcLoaded(path, dbcContents);
});
}
@ -72,24 +72,21 @@ export default class GithubDbcList extends Component {
<div className="cabana-dbc-list-files">
{this.state.paths
.filter(
p =>
(this.state.pathQuery === "") | p.includes(this.state.pathQuery)
(p) => (this.state.pathQuery === '') | p.includes(this.state.pathQuery)
)
.map(path => {
return (
<div
className={cx("cabana-dbc-list-file", {
"is-selected": this.state.selectedPath === path
})}
onClick={() => {
this.selectPath(path);
}}
key={path}
>
<span>{path}</span>
</div>
);
})}
.map((path) => (
<div
className={cx('cabana-dbc-list-file', {
'is-selected': this.state.selectedPath === path
})}
onClick={() => {
this.selectPath(path);
}}
key={path}
>
<span>{path}</span>
</div>
))}
</div>
</div>
);

View File

@ -1,6 +1,6 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import Hls from "hls.js";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Hls from 'hls.js';
export default class HLS extends Component {
static propTypes = {
@ -26,8 +26,8 @@ export default class HLS extends Component {
}
if (nextProps.playing) {
if (
this.videoElement &&
(this.videoElement.paused || this.videoElement.currentTime < 0.01)
this.videoElement
&& (this.videoElement.paused || this.videoElement.currentTime < 0.01)
) {
this.videoElement.play();
}
@ -46,6 +46,7 @@ export default class HLS extends Component {
// legacy outer scope variable. Revisit this to see if putting in state
// makes more sense
shouldInitVideoTime = true;
onSeeked = () => {
if (!this.props.playing) {
if (this.shouldInitVideoTime) {
@ -84,7 +85,7 @@ export default class HLS extends Component {
onClick={this.props.onClick}
>
<video
ref={video => {
ref={(video) => {
this.videoElement = video;
}}
autoPlay={this.props.playing}

View File

@ -1,12 +1,12 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import DBC from "../models/can/dbc";
import OpenDbc from "../api/OpenDbc";
import Modal from "./Modals/baseModal";
import GithubDbcList from "./GithubDbcList";
import DbcUpload from "./DbcUpload";
import DBC from '../models/can/dbc';
import OpenDbc from '../api/OpenDbc';
import Modal from './Modals/baseModal';
import GithubDbcList from './GithubDbcList';
import DbcUpload from './DbcUpload';
export default class LoadDbcModal extends Component {
static propTypes = {
@ -19,8 +19,8 @@ export default class LoadDbcModal extends Component {
constructor(props) {
super(props);
this.state = {
tab: "OpenDBC",
tabs: ["OpenDBC", "GitHub", "Upload"],
tab: 'OpenDBC',
tabs: ['OpenDBC', 'GitHub', 'Upload'],
dbc: null,
dbcSource: null,
userOpenDbcRepo: null
@ -34,7 +34,7 @@ export default class LoadDbcModal extends Component {
}
componentWillMount() {
this.props.openDbcClient.getUserOpenDbcFork().then(userOpenDbcRepo => {
this.props.openDbcClient.getUserOpenDbcFork().then((userOpenDbcRepo) => {
this.setState({ userOpenDbcRepo });
});
}
@ -54,26 +54,24 @@ export default class LoadDbcModal extends Component {
renderTabNavigation() {
return (
<div className="cabana-tabs-navigation">
{this.state.tabs.map(tab => {
return (
<a
className={cx({ "is-active": this.state.tab === tab })}
onClick={() => {
this.setState({ tab });
}}
key={tab}
>
<span>{tab}</span>
</a>
);
})}
{this.state.tabs.map((tab) => (
<a
className={cx({ 'is-active': this.state.tab === tab })}
onClick={() => {
this.setState({ tab });
}}
key={tab}
>
<span>{tab}</span>
</a>
))}
</div>
);
}
renderTabContent() {
const { tab } = this.state;
if (tab === "OpenDBC") {
if (tab === 'OpenDBC') {
return (
<GithubDbcList
onDbcLoaded={this.onDbcLoaded}
@ -81,21 +79,23 @@ export default class LoadDbcModal extends Component {
openDbcClient={this.props.openDbcClient}
/>
);
} else if (tab === "GitHub") {
}
if (tab === 'GitHub') {
if (!this.props.openDbcClient.hasAuth()) {
return this.props.loginWithGithub;
} else if (this.state.userOpenDbcRepo === null) {
return <div>Fork it</div>;
} else {
return (
<GithubDbcList
onDbcLoaded={this.onDbcLoaded}
repo={this.state.userOpenDbcRepo}
openDbcClient={this.props.openDbcClient}
/>
);
}
} else if (tab === "Upload") {
if (this.state.userOpenDbcRepo === null) {
return <div>Fork it</div>;
}
return (
<GithubDbcList
onDbcLoaded={this.onDbcLoaded}
repo={this.state.userOpenDbcRepo}
openDbcClient={this.props.openDbcClient}
/>
);
}
if (tab === 'Upload') {
return <DbcUpload onDbcLoaded={this.onDbcLoaded} />;
}
}

View File

@ -1,4 +1,4 @@
import styled, { keyframes } from "react-emotion";
import styled, { keyframes } from 'react-emotion';
const frames = keyframes`
0% {
@ -8,10 +8,10 @@ const frames = keyframes`
transform: translateX(-400px)
}
`;
const animationColor1 = "rgba(74, 242, 161, 1.00)";
const animationColor2 = "rgba(140, 169, 197, 1.00)";
const animationColor1 = 'rgba(74, 242, 161, 1.00)';
const animationColor2 = 'rgba(140, 169, 197, 1.00)';
export default styled("div")`
export default styled('div')`
display: block;
animation-name: ${frames};
animation-duration: 2s;

View File

@ -1,5 +1,5 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class MessageBytes extends Component {
static propTypes = {
@ -23,22 +23,20 @@ export default class MessageBytes extends Component {
shouldComponentUpdate(nextProps, nextState) {
if (nextProps.live) {
const nextLastEntry =
nextProps.message.entries[nextProps.message.entries.length - 1];
const nextLastEntry = nextProps.message.entries[nextProps.message.entries.length - 1];
const curLastEntry = this.props.message.entries[
this.props.message.entries.length - 1
];
return nextLastEntry.hexData !== curLastEntry.hexData;
} else {
return nextProps.seekTime !== this.props.seekTime;
}
return nextProps.seekTime !== this.props.seekTime;
}
componentWillReceiveProps(nextProps) {
if (
this.props.seekIndex !== nextProps.seekIndex ||
frameForTime(this.props.seekTime) !== frameForTime(nextProps.seekTime)
this.props.seekIndex !== nextProps.seekIndex
|| frameForTime(this.props.seekTime) !== frameForTime(nextProps.seekTime)
) {
this.updateCanvas(nextProps);
}
@ -66,7 +64,7 @@ export default class MessageBytes extends Component {
// TODO this can be faster with binary search, not currently a bottleneck though.
mostRecentMessageIndex = message.entries.findIndex(
e => e.relTime >= seekTime
(e) => e.relTime >= seekTime
);
}
@ -92,7 +90,7 @@ export default class MessageBytes extends Component {
}
}
const ctx = this.canvas.getContext("2d");
const ctx = this.canvas.getContext('2d');
// ctx.clearRect(0, 0, 180, 15);
for (let i = 0; i < message.byteStateChangeCounts.length; ++i) {
@ -101,12 +99,12 @@ export default class MessageBytes extends Component {
ctx.fillRect(i * 20, 0, 20, 15);
ctx.font = "12px Courier";
ctx.fillStyle = "white";
ctx.font = '12px Courier';
ctx.fillStyle = 'white';
if (hexData) {
ctx.fillText(hexData, i * 20 + 2, 12);
} else {
ctx.fillText("-", i * 20 + 7, 12);
ctx.fillText('-', i * 20 + 7, 12);
}
}
}
@ -123,7 +121,7 @@ export default class MessageBytes extends Component {
this.canvas = ref;
this.canvas.width = 160 * window.devicePixelRatio;
this.canvas.height = 15 * window.devicePixelRatio;
const ctx = this.canvas.getContext("2d");
const ctx = this.canvas.getContext('2d');
ctx.scale(window.devicePixelRatio, window.devicePixelRatio);
}

View File

@ -1,10 +1,11 @@
import React, { Component } from "react";
import cx from "classnames";
import PropTypes from "prop-types";
import Clipboard from "clipboard";
import React, { Component } from 'react';
import cx from 'classnames';
import PropTypes from 'prop-types';
import Clipboard from 'clipboard';
import MessageBytes from "./MessageBytes";
const { ckmeans } = require("simple-statistics");
import MessageBytes from './MessageBytes';
const { ckmeans } = require('simple-statistics');
export default class Meta extends Component {
static propTypes = {
@ -44,7 +45,7 @@ export default class Meta extends Component {
const { dbcLastSaved } = props;
this.state = {
filterText: "Filter",
filterText: 'Filter',
lastSaved:
dbcLastSaved !== null ? this.props.dbcLastSaved.fromNow() : null,
hoveredMessages: [],
@ -67,25 +68,25 @@ export default class Meta extends Component {
componentWillReceiveProps(nextProps) {
if (
nextProps.lastSaved !== this.props.lastSaved &&
typeof nextProps === "object"
nextProps.lastSaved !== this.props.lastSaved
&& typeof nextProps === 'object'
) {
this.setState({ lastSaved: nextProps.dbcLastSaved.fromNow() });
}
const nextMsgKeys = Object.keys(nextProps.messages);
if (
JSON.stringify(nextMsgKeys) !==
JSON.stringify(Object.keys(this.props.messages))
JSON.stringify(nextMsgKeys)
!== JSON.stringify(Object.keys(this.props.messages))
) {
const orderedMessageKeys = this.sortMessages(nextProps.messages);
this.setState({ hoveredMessages: [], orderedMessageKeys });
} else if (
this.state.orderedMessageKeys.length === 0 ||
(!this.props.live &&
this.props.messages &&
nextProps.messages &&
this.byteCountsDidUpdate(this.props.messages, nextProps.messages))
this.state.orderedMessageKeys.length === 0
|| (!this.props.live
&& this.props.messages
&& nextProps.messages
&& this.byteCountsDidUpdate(this.props.messages, nextProps.messages))
) {
const orderedMessageKeys = this.sortMessages(nextProps.messages);
this.setState({ orderedMessageKeys });
@ -94,9 +95,8 @@ export default class Meta extends Component {
byteCountsDidUpdate(prevMessages, nextMessages) {
return Object.entries(nextMessages).some(
([msgId, msg]) =>
JSON.stringify(msg.byteStateChangeCounts) !==
JSON.stringify(prevMessages[msgId].byteStateChangeCounts)
([msgId, msg]) => JSON.stringify(msg.byteStateChangeCounts)
!== JSON.stringify(prevMessages[msgId].byteStateChangeCounts)
);
}
@ -121,27 +121,22 @@ export default class Meta extends Component {
{}
);
const entryCounts = Object.keys(messagesByEntryCount).map(count =>
parseInt(count, 10)
);
const entryCounts = Object.keys(messagesByEntryCount).map((count) => parseInt(count, 10));
const binnedEntryCounts = ckmeans(
entryCounts,
Math.min(entryCounts.length, 10)
);
const sortedKeys = binnedEntryCounts
.map(bin =>
bin
.map(entryCount => messagesByEntryCount[entryCount.toString()])
.reduce((messages, partial) => messages.concat(partial), [])
.sort((msg1, msg2) => {
if (msg1.address < msg2.address) {
return 1;
} else {
return -1;
}
})
.map(msg => msg.id)
)
.map((bin) => bin
.map((entryCount) => messagesByEntryCount[entryCount.toString()])
.reduce((messages, partial) => messages.concat(partial), [])
.sort((msg1, msg2) => {
if (msg1.address < msg2.address) {
return 1;
}
return -1;
})
.map((msg) => msg.id))
.reduce((keys, bin) => keys.concat(bin), [])
.reverse();
@ -156,20 +151,20 @@ export default class Meta extends Component {
onFilterChanged(e) {
let val = e.target.value;
if (val.trim() === "Filter") val = "";
if (val.trim() === 'Filter') val = '';
this.setState({ filterText: val });
}
onFilterFocus(e) {
if (this.state.filterText.trim() === "Filter") {
this.setState({ filterText: "" });
if (this.state.filterText.trim() === 'Filter') {
this.setState({ filterText: '' });
}
}
onFilterUnfocus(e) {
if (this.state.filterText.trim() === "") {
this.setState({ filterText: "Filter" });
if (this.state.filterText.trim() === '') {
this.setState({ filterText: 'Filter' });
}
}
@ -178,13 +173,13 @@ export default class Meta extends Component {
return;
}
const { filterText } = this.state;
const msgName = msg.frame ? msg.frame.name : "";
const msgName = msg.frame ? msg.frame.name : '';
return (
filterText === "Filter" ||
filterText === "" ||
msg.id.toLowerCase().indexOf(filterText.toLowerCase()) !== -1 ||
msgName.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
filterText === 'Filter'
|| filterText === ''
|| msg.id.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
|| msgName.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
);
}
@ -193,13 +188,13 @@ export default class Meta extends Component {
return;
}
const { filterText } = this.state;
const msgName = msg.frame ? msg.frame.name : "";
const msgName = msg.frame ? msg.frame.name : '';
return (
filterText === "Filter" ||
filterText === "" ||
msg.id.toLowerCase().indexOf(filterText.toLowerCase()) !== -1 ||
msgName.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
filterText === 'Filter'
|| filterText === ''
|| msg.id.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
|| msgName.toLowerCase().indexOf(filterText.toLowerCase()) !== -1
);
}
@ -209,7 +204,7 @@ export default class Meta extends Component {
}
onMessageHover(key) {
let { hoveredMessages } = this.state;
const { hoveredMessages } = this.state;
if (hoveredMessages.indexOf(key) !== -1) return;
hoveredMessages.push(key);
@ -218,13 +213,13 @@ export default class Meta extends Component {
onMessageHoverEnd(key) {
let { hoveredMessages } = this.state;
hoveredMessages = hoveredMessages.filter(m => m !== key);
hoveredMessages = hoveredMessages.filter((m) => m !== key);
this.setState({ hoveredMessages });
}
onMsgRemoveClick(key) {
let { selectedMessages } = this.state;
selectedMessages = selectedMessages.filter(m => m !== key);
selectedMessages = selectedMessages.filter((m) => m !== key);
this.props.onMessageUnselected(key);
this.setState({ selectedMessages });
}
@ -241,12 +236,12 @@ export default class Meta extends Component {
orderedMessages() {
const { orderedMessageKeys } = this.state;
const { messages } = this.props;
return orderedMessageKeys.map(key => messages[key]);
return orderedMessageKeys.map((key) => messages[key]);
}
selectedMessageClass(messageId) {
return this.props.selectedMessages.includes(messageId)
? "is-selected"
? 'is-selected'
: null;
}
@ -258,17 +253,17 @@ export default class Meta extends Component {
}}
key={msg.id}
className={cx(
"cabana-meta-messages-list-item",
'cabana-meta-messages-list-item',
this.selectedMessageClass(msg.id)
)}
>
{msg.isLogEvent ? (
<td colSpan="2">{msg.id}</td>
) : (
<React.Fragment>
<td>{msg.frame ? msg.frame.name : "untitled"}</td>
<>
<td>{msg.frame ? msg.frame.name : 'untitled'}</td>
<td>{msg.id}</td>
</React.Fragment>
</>
)}
<td>{msg.entries.length}</td>
<td>
@ -303,10 +298,10 @@ export default class Meta extends Component {
return <p>Loading messages...</p>;
}
return (
<React.Fragment>
<>
<table cellPadding="5">
{this.state.showLogEvents && (
<React.Fragment>
<>
<thead>
<tr>
<td colSpan="2">Name</td>
@ -322,7 +317,7 @@ export default class Meta extends Component {
</td>
</tr>
</tbody>
</React.Fragment>
</>
)}
<thead>
<tr>
@ -334,7 +329,7 @@ export default class Meta extends Component {
</thead>
<tbody>{this.renderCanMessages()}</tbody>
</table>
</React.Fragment>
</>
);
}
@ -342,13 +337,14 @@ export default class Meta extends Component {
try {
// eslint-disable-next-line
"serviceWorker" in navigator &&
!!new ReadableStream() &&
!!new WritableStream(); // eslint-disable-line no-undef
return "saveable";
!!new ReadableStream()
&& !!new WritableStream(); // eslint-disable-line no-undef
return 'saveable';
} catch (e) {
return false;
}
}
render() {
return (
<div className="cabana-meta">
@ -361,7 +357,10 @@ export default class Meta extends Component {
</strong>
{this.props.dbcLastSaved !== null ? (
<div className="cabana-meta-header-last-saved">
<p>Last saved: {this.lastSavedPretty()}</p>
<p>
Last saved:
{this.lastSavedPretty()}
</p>
</div>
) : null}
<div className={`cabana-meta-header-actions ${this.saveable()}`}>
@ -378,12 +377,12 @@ export default class Meta extends Component {
className="cabana-meta-header-action special-wide"
data-clipboard-text={this.props.shareUrl}
data-clipboard-action="copy"
ref={ref => (ref ? new Clipboard(ref) : null)}
ref={(ref) => (ref ? new Clipboard(ref) : null)}
>
<a
className="button"
href={this.props.shareUrl}
onClick={e => e.preventDefault()}
onClick={(e) => e.preventDefault()}
>
Copy Share Link
</a>
@ -398,8 +397,8 @@ export default class Meta extends Component {
<div className="cabana-meta-messages-header">
<div
style={{
display: "inline-block",
float: "right"
display: 'inline-block',
float: 'right'
}}
>
<h5 className="t-capline">

View File

@ -1,12 +1,12 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import Moment from "moment";
import _ from "lodash";
import cx from "classnames";
import CommaAuth from "@commaai/my-comma-auth";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import Moment from 'moment';
import _ from 'lodash';
import cx from 'classnames';
import CommaAuth from '@commaai/my-comma-auth';
import { EXPLORER_URL } from "../../config";
import Modal from "../Modals/baseModal";
import { EXPLORER_URL } from '../../config';
import Modal from './baseModal';
export default class OnboardingModal extends Component {
static propTypes = {
@ -15,8 +15,8 @@ export default class OnboardingModal extends Component {
};
static instructionalImages = {
step2: require("../../images/webusb-enable-experimental-features.png"),
step3: require("../../images/webusb-enable-webusb.png")
step2: require('../../images/webusb-enable-experimental-features.png'),
step3: require('../../images/webusb-enable-webusb.png')
};
constructor(props) {
@ -66,7 +66,8 @@ export default class OnboardingModal extends Component {
</a>
</p>
);
} else if (!pandaConnected && attemptingPandaConnection) {
}
if (!pandaConnected && attemptingPandaConnection) {
return (
<p>
<i className="fa fa-spinner animate-spin" />
@ -87,8 +88,8 @@ export default class OnboardingModal extends Component {
<i className="fa fa-video-camera" />
<strong>
{CommaAuth.isAuthenticated()
? "Find a drive in Explorer"
: "Log in with Explorer"}
? 'Find a drive in Explorer'
: 'Log in with Explorer'}
</strong>
<sup>Click "View CAN Data" while replaying a drive</sup>
</button>
@ -101,17 +102,19 @@ export default class OnboardingModal extends Component {
<div className="cabana-onboarding-mode">{this.renderLogin()}</div>
<div className="cabana-onboarding-mode">
<button
className={cx("button--secondary button--kiosk", {
"is-disabled":
!this.state.webUsbEnabled ||
this.props.attemptingPandaConnection
className={cx('button--secondary button--kiosk', {
'is-disabled':
!this.state.webUsbEnabled
|| this.props.attemptingPandaConnection
})}
onClick={this.attemptPandaConnection}
>
<i className="fa fa-bolt" />
<strong>Launch Realtime Streaming</strong>
<sup>
Interactively stream car data over USB with <em>panda</em>
Interactively stream car data over USB with
{' '}
<em>panda</em>
</sup>
{this.renderPandaEligibility()}
</button>
@ -147,7 +150,7 @@ export default class OnboardingModal extends Component {
<strong>Enable Experimental Platform features:</strong>
</p>
<img
alt={"Screenshot of Google Chrome Experimental Platform features"}
alt="Screenshot of Google Chrome Experimental Platform features"
src={OnboardingModal.instructionalImages.step2}
/>
</li>
@ -156,7 +159,7 @@ export default class OnboardingModal extends Component {
<strong>Enable WebUSB:</strong>
</p>
<img
alt={"Screenshot of Google Chrome enable WebUSB"}
alt="Screenshot of Google Chrome enable WebUSB"
src={OnboardingModal.instructionalImages.step3}
/>
</li>
@ -175,23 +178,25 @@ export default class OnboardingModal extends Component {
renderModalContent() {
if (this.state.viewingUsbInstructions) {
return this.renderUsbInstructions();
} else {
return this.renderOnboardingOptions();
}
return this.renderOnboardingOptions();
}
renderModalFooter() {
return (
<p>
<span>
Don't have a{" "}
Don't have a
{' '}
<a
href="https://panda.comma.ai"
target="_blank"
rel="noopener noreferrer"
>
panda
</a>?{" "}
</a>
?
{' '}
</span>
<span>
<a
@ -200,10 +205,14 @@ export default class OnboardingModal extends Component {
rel="noopener noreferrer"
>
Get one here
</a>{" "}
</a>
{' '}
</span>
<span>
or <a href={`${window.location.href}?demo=1`}>try the demo</a>.
or
{' '}
<a href={`${window.location.href}?demo=1`}>try the demo</a>
.
</span>
</p>
);
@ -215,8 +224,8 @@ export default class OnboardingModal extends Component {
title="Welcome to Cabana"
subtitle="Get started by selecting a drive from Explorer or enabling live mode"
footer={this.renderModalFooter()}
disableClose={true}
variations={["wide", "dark"]}
disableClose
variations={['wide', 'dark']}
>
{this.renderModalContent()}
</Modal>

View File

@ -1,7 +1,7 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import Measure from "react-measure";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import Measure from 'react-measure';
export default class Modal extends Component {
static propTypes = {
@ -36,8 +36,8 @@ export default class Modal extends Component {
if (this.props.variations) {
const { variations } = this.props;
const classes = variations.reduce(
(classes, variation) => classes + `cabana-modal--${variation} `,
""
(classes, variation) => `${classes}cabana-modal--${variation} `,
''
);
return classes;
}
@ -54,14 +54,14 @@ export default class Modal extends Component {
render() {
return (
<div
className={cx("cabana-modal", this.readVariationClasses(), {
"cabana-modal--not-closable": this.checkClosability(),
"cabana-modal--scrollable-y": this.checkYScrollability()
className={cx('cabana-modal', this.readVariationClasses(), {
'cabana-modal--not-closable': this.checkClosability(),
'cabana-modal--scrollable-y': this.checkYScrollability()
})}
>
<Measure
bounds
onResize={contentRect => {
onResize={(contentRect) => {
this.updateHeights(contentRect);
}}
>

View File

@ -1,10 +1,11 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { PART_SEGMENT_LENGTH } from "../config";
import { PART_SEGMENT_LENGTH } from '../config';
export default class PartSelector extends Component {
static selectorWidth = 150;
static propTypes = {
onPartChange: PropTypes.func.isRequired,
partsCount: PropTypes.number.isRequired,
@ -29,14 +30,14 @@ export default class PartSelector extends Component {
makePartStyle(partsCount, selectedPart) {
return {
left: selectedPart / partsCount * PartSelector.selectorWidth,
width: PART_SEGMENT_LENGTH / partsCount * PartSelector.selectorWidth
left: (selectedPart / partsCount) * PartSelector.selectorWidth,
width: (PART_SEGMENT_LENGTH / partsCount) * PartSelector.selectorWidth
};
}
componentWillUpdate(nextProps, nextState) {
if (nextProps.selectedPart !== this.props.selectedPart) {
console.log("updating styles for part picker");
console.log('updating styles for part picker');
const selectedPartStyle = this.makePartStyle(
nextProps.partsCount,
nextProps.selectedPart
@ -80,12 +81,12 @@ export default class PartSelector extends Component {
partAtClientX(clientX) {
const rect = this.selectorRect.getBoundingClientRect();
const x = clientX - rect.left;
return Math.floor(x * this.props.partsCount / PartSelector.selectorWidth);
return Math.floor((x * this.props.partsCount) / PartSelector.selectorWidth);
}
onSelectedPartDragStart(e) {
this.setState({ isDragging: true });
document.addEventListener("mouseup", this.onSelectedPartDragEnd);
document.addEventListener('mouseup', this.onSelectedPartDragEnd);
}
onSelectedPartMouseMove(e) {
@ -97,7 +98,7 @@ export default class PartSelector extends Component {
onSelectedPartDragEnd(e) {
this.setState({ isDragging: false });
document.removeEventListener("mouseup", this.onSelectedPartDragEnd);
document.removeEventListener('mouseup', this.onSelectedPartDragEnd);
}
onClick(e) {
@ -116,7 +117,7 @@ export default class PartSelector extends Component {
<div className="cabana-explorer-part-selector">
<div
className="cabana-explorer-part-selector-track"
ref={selector => (this.selectorRect = selector)}
ref={(selector) => (this.selectorRect = selector)}
style={{ width: PartSelector.selectorWidth }}
onMouseMove={this.onSelectedPartMouseMove}
onClick={this.onClick}

View File

@ -1,5 +1,5 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
export default class PlayButton extends Component {
static propTypes = {
@ -21,29 +21,18 @@ export default class PlayButton extends Component {
const { isPlaying } = this.props;
if (isPlaying) {
if (hover) {
return (
process.env.PUBLIC_URL + "/img/ic_pause_circle_filled_white_24px.svg"
);
} else {
return (
process.env.PUBLIC_URL + "/img/ic_pause_circle_outline_white_24px.svg"
);
}
} else {
if (hover) {
return (
process.env.PUBLIC_URL + "/img/ic_play_circle_filled_white_24px.svg"
);
} else {
return (
process.env.PUBLIC_URL + "/img/ic_play_circle_outline_white_24px.svg"
);
return `${process.env.PUBLIC_URL}/img/ic_pause_circle_filled_white_24px.svg`;
}
return `${process.env.PUBLIC_URL}/img/ic_pause_circle_outline_white_24px.svg`;
}
if (hover) {
return `${process.env.PUBLIC_URL}/img/ic_play_circle_filled_white_24px.svg`;
}
return `${process.env.PUBLIC_URL}/img/ic_play_circle_outline_white_24px.svg`;
}
onClick(e) {
let { isPlaying } = this.props;
const { isPlaying } = this.props;
if (!isPlaying) {
this.props.onPlay();
@ -56,7 +45,7 @@ export default class PlayButton extends Component {
return (
<img
src={this.imageSource()}
alt={this.props.isPlaying ? "Pause" : "Play"}
alt={this.props.isPlaying ? 'Pause' : 'Play'}
className={this.props.className}
onClick={this.onClick}
onMouseOver={() => this.setState({ hover: true })}

View File

@ -1,4 +1,4 @@
import React, { Component } from "react";
import React, { Component } from 'react';
export default class PlaySpeedSelector extends Component {
constructor(props) {
@ -16,8 +16,8 @@ export default class PlaySpeedSelector extends Component {
return (
<div
style={{
display: "inline-block",
float: "right",
display: 'inline-block',
float: 'right',
margin: 10
}}
>

View File

@ -1,7 +1,7 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import PlayButton from "../PlayButton";
import debounce from "../../utils/debounce";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import PlayButton from '../PlayButton';
import debounce from '../../utils/debounce';
export default class RouteSeeker extends Component {
static propTypes = {
@ -18,10 +18,14 @@ export default class RouteSeeker extends Component {
nearestFrameTime: PropTypes.number
};
static hiddenMarkerStyle = { display: "none", left: 0 };
static hiddenMarkerStyle = { display: 'none', left: 0 };
static zeroSeekedBarStyle = { width: 0 };
static hiddenTooltipStyle = { display: "none", left: 0 };
static hiddenTooltipStyle = { display: 'none', left: 0 };
static markerWidth = 20;
static tooltipWidth = 50;
constructor(props) {
@ -31,7 +35,7 @@ export default class RouteSeeker extends Component {
markerStyle: RouteSeeker.hiddenMarkerStyle,
tooltipStyle: RouteSeeker.hiddenTooltipStyle,
ratio: 0,
tooltipTime: "0:00",
tooltipTime: '0:00',
isPlaying: false,
isDragging: false
};
@ -50,8 +54,8 @@ export default class RouteSeeker extends Component {
const { ratio } = this.state;
if (
JSON.stringify(this.props.segmentIndices) !==
JSON.stringify(nextProps.segmentIndices)
JSON.stringify(this.props.segmentIndices)
!== JSON.stringify(nextProps.segmentIndices)
) {
this.setState({
seekedBarStyle: RouteSeeker.zeroSeekedBarStyle,
@ -88,7 +92,7 @@ export default class RouteSeeker extends Component {
return 100 * (x / this.progressBar.offsetWidth);
}
updateDraggingSeek = debounce(ratio => this.props.onUserSeek(ratio), 250);
updateDraggingSeek = debounce((ratio) => this.props.onUserSeek(ratio), 250);
onMouseMove(e) {
const markerOffsetPct = this.mouseEventXOffsetPercent(e);
@ -96,18 +100,18 @@ export default class RouteSeeker extends Component {
this.onMouseLeave();
return;
}
const markerWidth = RouteSeeker.markerWidth;
const { markerWidth } = RouteSeeker;
const markerLeft = `calc(${markerOffsetPct + "%"} - ${markerWidth / 2}px)`;
const markerLeft = `calc(${`${markerOffsetPct}%`} - ${markerWidth / 2}px)`;
const markerStyle = {
display: "",
display: '',
left: markerLeft
};
const tooltipWidth = RouteSeeker.tooltipWidth;
const tooltipLeft = `calc(${markerOffsetPct + "%"} - ${tooltipWidth /
2}px)`;
const { tooltipWidth } = RouteSeeker;
const tooltipLeft = `calc(${`${markerOffsetPct}%`} - ${tooltipWidth
/ 2}px)`;
const tooltipStyle = { display: "flex", left: tooltipLeft };
const tooltipStyle = { display: 'flex', left: tooltipLeft };
const ratio = Math.max(0, markerOffsetPct / 100);
if (this.state.isDragging) {
this.updateSeekedBar(ratio);
@ -130,7 +134,7 @@ export default class RouteSeeker extends Component {
}
updateSeekedBar(ratio) {
const seekedBarStyle = { width: 100 * ratio + "%" };
const seekedBarStyle = { width: `${100 * ratio}%` };
this.setState({ seekedBarStyle, ratio });
}
@ -210,32 +214,32 @@ export default class RouteSeeker extends Component {
return (
<div className="cabana-explorer-visuals-camera-seeker">
<PlayButton
className={"cabana-explorer-visuals-camera-seeker-playbutton"}
className="cabana-explorer-visuals-camera-seeker-playbutton"
onPlay={this.onPlay}
onPause={this.onPause}
isPlaying={this.state.isPlaying}
/>
<div
className={"cabana-explorer-visuals-camera-seeker-progress"}
className="cabana-explorer-visuals-camera-seeker-progress"
onMouseMove={this.onMouseMove}
onMouseLeave={this.onMouseLeave}
onMouseDown={this.onMouseDown}
onMouseUp={this.onMouseUp}
onClick={this.onClick}
ref={ref => (this.progressBar = ref)}
ref={(ref) => (this.progressBar = ref)}
>
<div
className={"cabana-explorer-visuals-camera-seeker-progress-tooltip"}
className="cabana-explorer-visuals-camera-seeker-progress-tooltip"
style={tooltipStyle}
>
{this.state.tooltipTime}
</div>
<div
className={"cabana-explorer-visuals-camera-seeker-progress-marker"}
className="cabana-explorer-visuals-camera-seeker-progress-marker"
style={markerStyle}
/>
<div
className={"cabana-explorer-visuals-camera-seeker-progress-inner"}
className="cabana-explorer-visuals-camera-seeker-progress-inner"
style={seekedBarStyle}
/>
</div>

View File

@ -1,2 +1,3 @@
import RouteSeeker from "./RouteSeeker";
import RouteSeeker from './RouteSeeker';
export default RouteSeeker;

View File

@ -1,44 +1,44 @@
import React, { Component } from "react";
import PropTypes from "prop-types";
import { StyleSheet, css } from "aphrodite/no-important";
import { derived as RouteApi, video as VideoApi } from "@commaai/comma-api";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { StyleSheet, css } from 'aphrodite/no-important';
import { derived as RouteApi, video as VideoApi } from '@commaai/comma-api';
import HLS from "./HLS";
import RouteSeeker from "./RouteSeeker/RouteSeeker";
import HLS from './HLS';
import RouteSeeker from './RouteSeeker/RouteSeeker';
const Styles = StyleSheet.create({
loadingOverlay: {
position: "absolute",
position: 'absolute',
top: 0,
left: 0,
width: "100%",
height: "100%",
display: "flex",
justifyContent: "center",
alignItems: "center",
width: '100%',
height: '100%',
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
zIndex: 3
},
loadingSpinner: {
width: "25%",
height: "25%",
display: "block"
width: '25%',
height: '25%',
display: 'block'
},
img: {
height: 480,
display: "block",
position: "absolute",
display: 'block',
position: 'absolute',
zIndex: 2
},
hls: {
zIndex: 1,
height: 480,
backgroundColor: "rgba(0,0,0,0.9)"
backgroundColor: 'rgba(0,0,0,0.9)'
},
seekBar: {
position: "absolute",
position: 'absolute',
bottom: 0,
left: 0,
width: "100%",
width: '100%',
zIndex: 4
}
});
@ -79,17 +79,17 @@ export default class RouteVideoSync extends Component {
componentWillReceiveProps(nextProps) {
if (
this.props.userSeekIndex !== nextProps.userSeekIndex ||
this.props.canFrameOffset !== nextProps.canFrameOffset ||
(this.props.message &&
nextProps.message &&
this.props.message.entries.length !== nextProps.message.entries.length)
this.props.userSeekIndex !== nextProps.userSeekIndex
|| this.props.canFrameOffset !== nextProps.canFrameOffset
|| (this.props.message
&& nextProps.message
&& this.props.message.entries.length !== nextProps.message.entries.length)
) {
this.setState({ shouldRestartHls: true });
}
if (
nextProps.userSeekTime &&
this.props.userSeekTime !== nextProps.userSeekTime
nextProps.userSeekTime
&& this.props.userSeekTime !== nextProps.userSeekTime
) {
if (this.state.videoElement) {
this.state.videoElement.currentTime = nextProps.userSeekTime;
@ -111,8 +111,8 @@ export default class RouteVideoSync extends Component {
<div className={css(Styles.loadingOverlay)}>
<img
className={css(Styles.loadingSpinner)}
src={process.env.PUBLIC_URL + "/img/loading.svg"}
alt={"Loading video"}
src={`${process.env.PUBLIC_URL}/img/loading.svg`}
alt="Loading video"
/>
</div>
);
@ -154,7 +154,7 @@ export default class RouteVideoSync extends Component {
segmentProgress(currentTime) {
// returns progress as number in [0,1]
let startTime = this.startTime();
const startTime = this.startTime();
if (currentTime < startTime) {
currentTime = startTime;
@ -175,12 +175,12 @@ export default class RouteVideoSync extends Component {
onUserSeek(ratio) {
/* ratio in [0,1] */
let { videoElement } = this.state;
const { videoElement } = this.state;
if (isNaN(videoElement.duration)) {
this.setState({ shouldRestartHls: true }, funcSeekToRatio);
return;
}
let seekTime = this.ratioTime(ratio);
const seekTime = this.ratioTime(ratio);
videoElement.currentTime = seekTime;
const funcSeekToRatio = () => this.props.onUserSeek(seekTime);
@ -203,7 +203,7 @@ export default class RouteVideoSync extends Component {
<img
src={this.nearestFrameUrl()}
className={css(Styles.img)}
alt={"Camera preview at t = " + Math.round(this.props.userSeekTime)}
alt={`Camera preview at t = ${Math.round(this.props.userSeekTime)}`}
/>
) : null}
<HLS

View File

@ -1,11 +1,11 @@
import React, { Component } from "react";
import cx from "classnames";
import PropTypes from "prop-types";
import FileSaver from "file-saver";
import React, { Component } from 'react';
import cx from 'classnames';
import PropTypes from 'prop-types';
import FileSaver from 'file-saver';
import OpenDbc from "../api/OpenDbc";
import DBC from "../models/can/dbc";
import Modal from "./Modals/baseModal";
import OpenDbc from '../api/OpenDbc';
import DBC from '../models/can/dbc';
import Modal from './Modals/baseModal';
// import TabStyles from '../styles/modal-tabs';
export default class SaveDbcModal extends Component {
@ -22,11 +22,11 @@ export default class SaveDbcModal extends Component {
constructor(props) {
super(props);
this.state = {
tab: "GitHub",
tab: 'GitHub',
openDbcFork: null,
dbcFilename: this.props.sourceDbcFilename,
tabs: ["GitHub", "Download"],
commitMessage: "OpenDBC updates"
tabs: ['GitHub', 'Download'],
commitMessage: 'OpenDBC updates'
};
this.commitToGitHub = this.commitToGitHub.bind(this);
@ -44,7 +44,7 @@ export default class SaveDbcModal extends Component {
async commitToGitHub() {
const { openDbcFork, dbcFilename } = this.state;
const filename = dbcFilename.replace(/\.dbc/g, "") + ".dbc";
const filename = `${dbcFilename.replace(/\.dbc/g, '')}.dbc`;
const success = await this.props.openDbcClient.commitFile(
openDbcFork,
filename,
@ -58,9 +58,9 @@ export default class SaveDbcModal extends Component {
async downloadDbcFile() {
const blob = new Blob([this.props.dbc.text()], {
type: "text/plain;charset=utf-8"
type: 'text/plain;charset=utf-8'
});
const filename = this.state.dbcFilename.replace(/\.dbc/g, "") + ".dbc";
const filename = `${this.state.dbcFilename.replace(/\.dbc/g, '')}.dbc`;
FileSaver.saveAs(blob, filename, true);
}
@ -74,7 +74,7 @@ export default class SaveDbcModal extends Component {
const interval = window.setInterval(() => {
if (!isTimedOut) {
this.props.openDbcClient.getUserOpenDbcFork().then(openDbcFork => {
this.props.openDbcClient.getUserOpenDbcFork().then((openDbcFork) => {
if (openDbcFork !== null) {
this.setState({ openDbcFork });
window.clearInterval(interval);
@ -92,11 +92,12 @@ export default class SaveDbcModal extends Component {
primaryActionDisabled() {
const { tab } = this.state;
if (tab === "GitHub") {
if (tab === 'GitHub') {
return (
this.state.openDbcFork != null && this.state.dbcFilename.length > 0
);
} else if (tab === "Download") {
}
if (tab === 'Download') {
return true;
}
}
@ -117,7 +118,11 @@ export default class SaveDbcModal extends Component {
content = (
<button disabled>
<i className="fa fa-code-fork" />
<span> Forked: {openDbcFork}</span>
<span>
{' '}
Forked:
{openDbcFork}
</span>
</button>
);
} else if (this.props.hasGithubAuth) {
@ -144,9 +149,9 @@ export default class SaveDbcModal extends Component {
<input
type="text"
id="filename"
value={this.state.dbcFilename.replace(/\.dbc/g, "")}
value={this.state.dbcFilename.replace(/\.dbc/g, '')}
size={this.state.dbcFilename.length + 2}
onChange={e => this.setState({ dbcFilename: e.target.value })}
onChange={(e) => this.setState({ dbcFilename: e.target.value })}
/>
</div>
);
@ -155,19 +160,17 @@ export default class SaveDbcModal extends Component {
renderTabNavigation() {
return (
<div className="cabana-tabs-navigation">
{this.state.tabs.map(tab => {
return (
<a
className={cx({ "is-active": this.state.tab === tab })}
onClick={() => {
this.setState({ tab });
}}
key={tab}
>
<span>{tab}</span>
</a>
);
})}
{this.state.tabs.map((tab) => (
<a
className={cx({ 'is-active': this.state.tab === tab })}
onClick={() => {
this.setState({ tab });
}}
key={tab}
>
<span>{tab}</span>
</a>
))}
</div>
);
}
@ -183,7 +186,7 @@ export default class SaveDbcModal extends Component {
type="text"
id="commit-message"
value={this.state.commitMessage}
onChange={e => this.setState({ commitMessage: e.target.value })}
onChange={(e) => this.setState({ commitMessage: e.target.value })}
/>
</div>
);
@ -191,7 +194,7 @@ export default class SaveDbcModal extends Component {
renderTabContent() {
const { tab } = this.state;
if (tab === "GitHub") {
if (tab === 'GitHub') {
return (
<div>
{this.renderForkStep()}
@ -199,14 +202,15 @@ export default class SaveDbcModal extends Component {
{this.renderCommitMessage()}
</div>
);
} else if (tab === "Download") {
}
if (tab === 'Download') {
return <div>{this.renderFilenameField()}</div>;
}
}
renderActions() {
const { tab } = this.state;
if (tab === "GitHub") {
if (tab === 'GitHub') {
return (
<div>
<button className="button--inverted" onClick={this.props.handleClose}>
@ -217,7 +221,8 @@ export default class SaveDbcModal extends Component {
</button>
</div>
);
} else if (tab === "Download") {
}
if (tab === 'Download') {
return (
<div>
<button className="button--inverted" onClick={this.props.handleClose}>

View File

@ -1,8 +1,8 @@
// SignalLegend.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import SignalLegendEntry from "./SignalLegendEntry";
import SignalLegendEntry from './SignalLegendEntry';
export default class SignalLegend extends Component {
static propTypes = {
@ -23,13 +23,13 @@ export default class SignalLegend extends Component {
expandedSignals: []
};
toggleExpandSignal = s => {
toggleExpandSignal = (s) => {
const { expandedSignals } = this.state;
if (!expandedSignals.includes(s.uid)) {
const updatedExpandedSignals = [...expandedSignals, s.uid];
this.setState({ expandedSignals: updatedExpandedSignals });
} else {
const updatedExpandedSignals = expandedSignals.filter(i => i !== s.uid);
const updatedExpandedSignals = expandedSignals.filter((i) => i !== s.uid);
this.setState({ expandedSignals: updatedExpandedSignals });
}
};
@ -44,9 +44,8 @@ export default class SignalLegend extends Component {
.sort(([_, signal1], [__, signal2]) => {
if (signal1.startBit < signal2.startBit) {
return -1;
} else {
return 1;
}
return 1;
})
.map(([signalName, signal]) => {
const { colors } = signals[signalName];
@ -73,10 +72,8 @@ export default class SignalLegend extends Component {
});
const signalRows = signalRowsNested
.filter(row => row != null)
.reduce((a, b) => {
return a.concat(b);
}, []);
.filter((row) => row != null)
.reduce((a, b) => a.concat(b), []);
return <div className="cabana-explorer-signals-legend">{signalRows}</div>;
}

View File

@ -1,12 +1,12 @@
import styled from "react-emotion";
import styled from 'react-emotion';
// color bar on the left side of the signals legend
export default styled("div")`
export default styled('div')`
display: block;
height: 100%;
left: 0;
position: absolute;
width: 1.5%;
opacity: ${({ isHighlighted }) => (isHighlighted ? 0.5 : 0.3)};
background-color: rgb(${({ rgb }) => rgb.join(",")});
background-color: rgb(${({ rgb }) => rgb.join(',')});
`;

View File

@ -1,44 +1,41 @@
import DbcUtils from "../../utils/dbc";
import DbcUtils from '../../utils/dbc';
const unsignedTransformation = field => {
return (value, signal) => {
if (value !== "") {
value = Number(value) || 0;
const unsignedTransformation = (field) => (value, signal) => {
if (value !== '') {
value = Number(value) || 0;
if (value < 0) {
value = 0;
}
if (value < 0) {
value = 0;
}
signal[field] = value;
return signal;
};
}
signal[field] = value;
return signal;
};
export default [
{
field: "name",
title: "Name",
type: "string"
field: 'name',
title: 'Name',
type: 'string'
},
{
field: "size",
title: "Size",
type: "number",
transform: unsignedTransformation("size")
field: 'size',
title: 'Size',
type: 'number',
transform: unsignedTransformation('size')
},
{
field: "startBit",
title: signal =>
signal.isLittleEndian ? "Least significant bit" : "Most significant bit",
type: "number",
transform: unsignedTransformation("startBit")
field: 'startBit',
title: (signal) => (signal.isLittleEndian ? 'Least significant bit' : 'Most significant bit'),
type: 'number',
transform: unsignedTransformation('startBit')
},
{
field: "isLittleEndian",
title: "Endianness",
type: "option",
field: 'isLittleEndian',
title: 'Endianness',
type: 'option',
options: {
options: ["Little", "Big"],
options: ['Little', 'Big'],
optionValues: { Little: true, Big: false }
},
transform: (isLittleEndian, signal) => {
@ -47,8 +44,8 @@ export default [
if (isLittleEndian) {
// big endian -> little endian
const startByte = Math.floor(signal.startBit / 8),
endByte = Math.floor((signal.startBit - signal.size + 1) / 8);
const startByte = Math.floor(signal.startBit / 8);
const endByte = Math.floor((signal.startBit - signal.size + 1) / 8);
if (startByte === endByte) {
signal.startBit = signal.startBit - signal.size + 1;
@ -57,8 +54,8 @@ export default [
}
} else {
// little endian -> big endian
const startByte = Math.floor(signal.startBit / 8),
endByte = Math.floor((signal.startBit + signal.size - 1) / 8);
const startByte = Math.floor(signal.startBit / 8);
const endByte = Math.floor((signal.startBit + signal.size - 1) / 8);
if (startByte === endByte) {
signal.startBit = signal.startBit + signal.size - 1;
@ -72,42 +69,42 @@ export default [
}
},
{
field: "isSigned",
title: "Sign",
type: "option",
field: 'isSigned',
title: 'Sign',
type: 'option',
options: {
options: ["Signed", "Unsigned"],
options: ['Signed', 'Unsigned'],
optionValues: { Signed: true, Unsigned: false }
}
},
{
field: "factor",
title: "Factor",
type: "number"
field: 'factor',
title: 'Factor',
type: 'number'
},
{
field: "offset",
title: "Offset",
type: "number"
field: 'offset',
title: 'Offset',
type: 'number'
},
{
field: "unit",
title: "Unit",
type: "string"
field: 'unit',
title: 'Unit',
type: 'string'
},
{
field: "comment",
title: "Comment",
type: "string"
field: 'comment',
title: 'Comment',
type: 'string'
},
{
field: "min",
title: "Minimum value",
type: "number"
field: 'min',
title: 'Minimum value',
type: 'number'
},
{
field: "max",
title: "Maximum value",
type: "number"
field: 'max',
title: 'Maximum value',
type: 'number'
}
];

View File

@ -1,4 +1,4 @@
import React, { Component } from "react";
import React, { Component } from 'react';
export default class Field extends Component {
render() {

View File

@ -1,5 +1,5 @@
import React from "react";
import Field from "./Field";
import React from 'react';
import Field from './Field';
export default ({
fieldSpec,
@ -14,27 +14,27 @@ export default ({
if (isExpanded) {
let value = signalEdited;
if (value !== "") {
let num = Number(value);
value = isNaN(num) ? "" : num;
if (value !== '') {
const num = Number(value);
value = isNaN(num) ? '' : num;
}
valueCol = (
<input
id={htmlFor}
type="number"
value={value}
onChange={e => {
onChange={(e) => {
updateField(fieldSpec, e.target.value);
}}
/>
);
} else {
let value = signal[field];
const value = signal[field];
valueCol = <span>{value}</span>;
}
return (
<Field
title={typeof title === "function" ? title(signal) : title}
title={typeof title === 'function' ? title(signal) : title}
htmlFor={htmlFor}
>
{valueCol}

View File

@ -1,7 +1,7 @@
import React from "react";
import Field from "./Field";
import React from 'react';
import Field from './Field';
import { swapKeysAndValues } from "../../utils/object";
import { swapKeysAndValues } from '../../utils/object';
export default ({
fieldSpec,
@ -14,10 +14,10 @@ export default ({
const { field, title } = fieldSpec;
const htmlFor = `${signal.name}_${field}`;
const { options, optionValues } = fieldSpec.options;
let valueOptions = swapKeysAndValues(optionValues);
const valueOptions = swapKeysAndValues(optionValues);
if (isExpanded) {
const optionEles = options.map(opt => (
const optionEles = options.map((opt) => (
<option key={opt} value={optionValues[opt]}>
{opt}
</option>
@ -26,8 +26,8 @@ export default ({
<select
id={htmlFor}
defaultValue={signalEdited}
onChange={e => {
updateField(fieldSpec, e.target.value === "true");
onChange={(e) => {
updateField(fieldSpec, e.target.value === 'true');
}}
>
{optionEles}
@ -39,7 +39,7 @@ export default ({
return (
<Field
title={typeof title === "function" ? title(signal) : title}
title={typeof title === 'function' ? title(signal) : title}
htmlFor={htmlFor}
>
{valueCol}

View File

@ -1,9 +1,9 @@
import React from "react";
import React from 'react';
import FIELDS from "./FIELDS";
import NumberField from "./NumberField";
import StringField from "./StringField";
import OptionField from "./OptionField";
import FIELDS from './FIELDS';
import NumberField from './NumberField';
import StringField from './StringField';
import OptionField from './OptionField';
const FieldMap = {
number: NumberField,
@ -17,31 +17,29 @@ export default ({
isExpanded,
getSignalEdited,
update
}) => {
return (
<div className="signals-legend-entry-form">
{FIELDS.map(field => {
const Node = FieldMap[field.type];
return (
<div className="signals-legend-entry-form-field" key={field.field}>
<Node
fieldSpec={field}
signal={signal}
isExpanded={isExpanded}
signalEdited={getSignalEdited(field.field)}
updateField={update}
/>
</div>
);
})}
<div className="signals-legend-entry-form-remove">
<button
className="button--tiny button--alpha"
onClick={() => onSignalRemove(signal)}
>
Remove Signal
</button>
</div>
}) => (
<div className="signals-legend-entry-form">
{FIELDS.map((field) => {
const Node = FieldMap[field.type];
return (
<div className="signals-legend-entry-form-field" key={field.field}>
<Node
fieldSpec={field}
signal={signal}
isExpanded={isExpanded}
signalEdited={getSignalEdited(field.field)}
updateField={update}
/>
</div>
);
})}
<div className="signals-legend-entry-form-remove">
<button
className="button--tiny button--alpha"
onClick={() => onSignalRemove(signal)}
>
Remove Signal
</button>
</div>
);
};
</div>
);

View File

@ -1,5 +1,5 @@
import React from "react";
import Field from "./Field";
import React from 'react';
import Field from './Field';
export default ({
fieldSpec,
@ -16,8 +16,8 @@ export default ({
<input
id={htmlFor}
type="text"
value={signalEdited || ""}
onChange={e => {
value={signalEdited || ''}
onChange={(e) => {
updateField(fieldSpec, e.target.value);
}}
/>
@ -28,7 +28,7 @@ export default ({
return (
<Field
title={typeof title === "function" ? title(signal) : title}
title={typeof title === 'function' ? title(signal) : title}
htmlFor={htmlFor}
>
{valueCol}

View File

@ -1,13 +1,13 @@
// SignalLegendEntry.js
import React, { Component } from "react";
import PropTypes from "prop-types";
import cx from "classnames";
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import cx from 'classnames';
import Signal from "../../models/can/signal";
import SignalForm from "./SignalForm";
import ColorBar from "./ColorBar";
import FIELDS from "./FIELDS";
import Signal from '../../models/can/signal';
import SignalForm from './SignalForm';
import ColorBar from './ColorBar';
import FIELDS from './FIELDS';
export default class SignalLegendEntry extends Component {
static propTypes = {
@ -25,9 +25,7 @@ export default class SignalLegendEntry extends Component {
isExpanded: PropTypes.bool
};
static fieldSpecForName = name => {
return FIELDS.find(field => field.field === name);
};
static fieldSpecForName = (name) => FIELDS.find((field) => field.field === name);
constructor(props) {
super(props);
@ -66,7 +64,7 @@ export default class SignalLegendEntry extends Component {
this.props.onSignalChange(signalCopy, signal);
};
toggleEditing = e => {
toggleEditing = (e) => {
if (this.props.isLogEvent) {
return;
}
@ -81,9 +79,9 @@ export default class SignalLegendEntry extends Component {
const fieldSpec = SignalLegendEntry.fieldSpecForName(field);
if (
fieldSpec &&
fieldSpec.type === "number" &&
isNaN(parseInt(value, 10))
fieldSpec
&& fieldSpec.type === 'number'
&& isNaN(parseInt(value, 10))
) {
value = 0;
}
@ -103,22 +101,23 @@ export default class SignalLegendEntry extends Component {
e.stopPropagation();
};
toggleSignalPlot = e => {
toggleSignalPlot = (e) => {
const { signal, isPlotted } = this.props;
e.preventDefault();
this.props.onSignalPlotChange(!isPlotted, signal.uid);
};
getSignalEdited = field => {
return this.state.signalEdited[field];
};
getSignalEdited = (field) => this.state.signalEdited[field];
render() {
const { signal, isHighlighted, color, isPlotted, isExpanded } = this.props;
const expandedEntryClass = isExpanded ? "is-expanded" : null;
const plottedButtonClass = isPlotted ? "button" : "button--alpha";
const {
signal, isHighlighted, color, isPlotted, isExpanded
} = this.props;
const expandedEntryClass = isExpanded ? 'is-expanded' : null;
const plottedButtonClass = isPlotted ? 'button' : 'button--alpha';
return (
<div
className={cx("signals-legend-entry", expandedEntryClass)}
className={cx('signals-legend-entry', expandedEntryClass)}
onMouseEnter={() => this.props.onSignalHover(signal)}
onMouseLeave={() => this.props.onSignalHoverEnd(signal)}
>
@ -134,8 +133,8 @@ export default class SignalLegendEntry extends Component {
className="signals-legend-entry-header-action"
onClick={this.toggleSignalPlot}
>
<button className={cx("button--tiny", plottedButtonClass)}>
{isPlotted ? "Hide Plot" : "Show Plot"}
<button className={cx('button--tiny', plottedButtonClass)}>
{isPlotted ? 'Hide Plot' : 'Show Plot'}
</button>
</div>
</div>

View File

@ -1,8 +1,8 @@
import SignalLegendEntry from ".";
import Signal from "../../models/can/signal";
import React from "react";
import { shallow, mount, render } from "enzyme";
import { StyleSheetTestUtils } from "aphrodite";
import React from 'react';
import { shallow, mount, render } from 'enzyme';
import { StyleSheetTestUtils } from 'aphrodite';
import Signal from '../../models/can/signal';
import SignalLegendEntry from '.';
// Prevents style injection from firing after test finishes
// and jsdom is torn down.
@ -14,11 +14,11 @@ afterEach(() => {
});
function createSignalLegendEntry(props) {
let signal = props.signal,
onSignalChange = props.onSignalChange,
onTentativeSignalChange = props.onTentativeSignalChange;
let { signal } = props;
let { onSignalChange } = props;
let { onTentativeSignalChange } = props;
if (signal === undefined) {
signal = new Signal({ name: "NEW_SIGNAL" });
signal = new Signal({ name: 'NEW_SIGNAL' });
}
if (onSignalChange === undefined) {
onSignalChange = () => {};
@ -37,9 +37,9 @@ function createSignalLegendEntry(props) {
);
}
test("a little endian signal spanning one byte should adjust its startBit switching to big endian, preserving its bit coverage", () => {
test('a little endian signal spanning one byte should adjust its startBit switching to big endian, preserving its bit coverage', () => {
const signal = new Signal({
name: "signal",
name: 'signal',
startBit: 0,
size: 8,
isLittleEndian: true
@ -47,30 +47,30 @@ test("a little endian signal spanning one byte should adjust its startBit switch
const component = createSignalLegendEntry({ signal });
const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName(
"isLittleEndian"
'isLittleEndian'
);
component.instance().updateField(endiannessFieldSpec, false);
const signalEdited = component.state("signalEdited");
const signalEdited = component.state('signalEdited');
expect(signalEdited.isLittleEndian).toBe(false);
expect(signalEdited.startBit).toBe(7);
expect(signalEdited.size).toBe(8);
});
test("a big endian signal spanning two bytes should should adjust its startBit switching to little endian, preserving its bit coverage", () => {
test('a big endian signal spanning two bytes should should adjust its startBit switching to little endian, preserving its bit coverage', () => {
const signal = new Signal({
name: "signal",
name: 'signal',
startBit: 7,
size: 8,
isLittleEndian: false
});
const component = createSignalLegendEntry({ signal });
const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName(
"isLittleEndian"
'isLittleEndian'
);
component.instance().updateField(endiannessFieldSpec, true);
const signalEdited = component.state("signalEdited");
const signalEdited = component.state('signalEdited');
expect(signalEdited.isLittleEndian).toBe(true);
expect(signalEdited.startBit).toBe(0);
expect(signalEdited.size).toBe(8);
@ -78,7 +78,7 @@ test("a big endian signal spanning two bytes should should adjust its startBit s
test("a big endian signal spanning one and a half bytes should adjust its startBit switching to little endian, preserving the first byte's coverage", () => {
const signal = new Signal({
name: "signal",
name: 'signal',
startBit: 7,
size: 12,
isLittleEndian: false
@ -86,49 +86,49 @@ test("a big endian signal spanning one and a half bytes should adjust its startB
const component = createSignalLegendEntry({ signal });
const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName(
"isLittleEndian"
'isLittleEndian'
);
component.instance().updateField(endiannessFieldSpec, true);
const signalEdited = component.state("signalEdited");
const signalEdited = component.state('signalEdited');
expect(signalEdited.isLittleEndian).toBe(true);
expect(signalEdited.startBit).toBe(0);
expect(signalEdited.size).toBe(12);
});
test("a little endian signal spanning 3 bits on one byte should adjust its startBit switching to big endian, preserving its bit coverage", () => {
test('a little endian signal spanning 3 bits on one byte should adjust its startBit switching to big endian, preserving its bit coverage', () => {
const signal = new Signal({
name: "signal",
name: 'signal',
startBit: 13,
size: 3,
isLittleEndian: true
});
const component = createSignalLegendEntry({ signal });
const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName(
"isLittleEndian"
'isLittleEndian'
);
component.instance().updateField(endiannessFieldSpec, false);
const signalEdited = component.state("signalEdited");
const signalEdited = component.state('signalEdited');
expect(signalEdited.isLittleEndian).toBe(false);
expect(signalEdited.startBit).toBe(15);
expect(signalEdited.size).toBe(3);
});
test("a big endian signal spanning 3 bytes on one byte should adjust its startBit switching to little endian, preserving its bit coverage", () => {
test('a big endian signal spanning 3 bytes on one byte should adjust its startBit switching to little endian, preserving its bit coverage', () => {
const signal = new Signal({
name: "signal",
name: 'signal',
startBit: 15,
size: 3,
isLittleEndian: false
});
const component = createSignalLegendEntry({ signal });
const endiannessFieldSpec = SignalLegendEntry.fieldSpecForName(
"isLittleEndian"
'isLittleEndian'
);
component.instance().updateField(endiannessFieldSpec, true);
const signalEdited = component.state("signalEdited");
const signalEdited = component.state('signalEdited');
expect(signalEdited.isLittleEndian).toBe(true);
expect(signalEdited.startBit).toBe(13);
expect(signalEdited.size).toBe(3);

View File

@ -1,26 +1,25 @@
import { getUrlParameter } from "./utils/url";
import { getUrlParameter } from './utils/url';
const ENV = process.env.NODE_ENV === "production" ? "prod" : "debug";
const ENV = process.env.NODE_ENV === 'production' ? 'prod' : 'debug';
const ENV_GITHUB_CLIENT_ID = {
debug: "f1e42d14f45491f9ca34",
prod: "4b43250e7499a97d62a5"
debug: 'f1e42d14f45491f9ca34',
prod: '4b43250e7499a97d62a5'
};
export const GITHUB_CLIENT_ID = ENV_GITHUB_CLIENT_ID[ENV];
const ENV_GITHUB_REDIRECT_URL = {
debug: "http://127.0.0.1:1235/callback",
prod: "https://api.comma.ai/cabana/ghcallback"
debug: 'http://127.0.0.1:1235/callback',
prod: 'https://api.comma.ai/cabana/ghcallback'
};
export const GITHUB_REDIRECT_URL = ENV_GITHUB_REDIRECT_URL[ENV];
export const GITHUB_AUTH_TOKEN_KEY = "gh_access_token";
export const OPENDBC_SOURCE_REPO = "commaai/opendbc";
export const GITHUB_AUTH_TOKEN_KEY = 'gh_access_token';
export const OPENDBC_SOURCE_REPO = 'commaai/opendbc';
export const USE_UNLOGGER =
typeof window !== "undefined" && getUrlParameter("unlogger") !== null;
export const UNLOGGER_HOST = "http://localhost:8080/unlogger";
export const USE_UNLOGGER = typeof window !== 'undefined' && getUrlParameter('unlogger') !== null;
export const UNLOGGER_HOST = 'http://localhost:8080/unlogger';
export const LOGENTRIES_TOKEN = "4bc98019-8277-4fe0-867c-ed21ea843cc5";
export const LOGENTRIES_TOKEN = '4bc98019-8277-4fe0-867c-ed21ea843cc5';
export const PART_SEGMENT_LENGTH = 3;
@ -29,7 +28,7 @@ export const CAN_GRAPH_MAX_POINTS = 5000;
export const STREAMING_WINDOW = 60;
const ENV_EXPLORER_URL = {
debug: "http://127.0.0.1:3000/",
prod: "https://my.comma.ai/"
debug: 'http://127.0.0.1:3000/',
prod: 'https://my.comma.ai/'
};
export const EXPLORER_URL = ENV_EXPLORER_URL[ENV];

View File

@ -1,37 +1,37 @@
import Sentry from "./logging/Sentry";
import React from "react";
import ReactDOM from "react-dom";
import CommaAuth from "@commaai/my-comma-auth";
import { request as Request } from "@commaai/comma-api";
import CanExplorer from "./CanExplorer";
import AcuraDbc from "./acura-dbc";
import { getUrlParameter, modifyQueryParameters } from "./utils/url";
import { GITHUB_AUTH_TOKEN_KEY } from "./config";
import React from 'react';
import ReactDOM from 'react-dom';
import CommaAuth from '@commaai/my-comma-auth';
import { request as Request } from '@commaai/comma-api';
import Sentry from './logging/Sentry';
import CanExplorer from './CanExplorer';
import AcuraDbc from './acura-dbc';
import { getUrlParameter, modifyQueryParameters } from './utils/url';
import { GITHUB_AUTH_TOKEN_KEY } from './config';
import {
fetchPersistedDbc,
fetchPersistedGithubAuthToken,
persistGithubAuthToken
} from "./api/localstorage";
import "./index.css";
} from './api/localstorage';
import './index.css';
Sentry.init();
const routeFullName = getUrlParameter("route");
let isDemo = !routeFullName;
let props = { autoplay: true, isDemo };
const routeFullName = getUrlParameter('route');
const isDemo = !routeFullName;
const props = { autoplay: true, isDemo };
let persistedDbc = null;
if (routeFullName) {
const [dongleId, route] = routeFullName.split("|");
const [dongleId, route] = routeFullName.split('|');
props.dongleId = dongleId;
props.name = route;
persistedDbc = fetchPersistedDbc(routeFullName);
let max = getUrlParameter("max"),
url = getUrlParameter("url"),
exp = getUrlParameter("exp"),
sig = getUrlParameter("sig");
const max = getUrlParameter('max');
const url = getUrlParameter('url');
const exp = getUrlParameter('exp');
const sig = getUrlParameter('sig');
if (max) {
props.max = max;
@ -47,15 +47,14 @@ if (routeFullName) {
}
props.isLegacyShare = max && url && !exp && !sig;
props.isShare = max && url && exp && sig;
} else if (getUrlParameter("demo")) {
} else if (getUrlParameter('demo')) {
props.max = 12;
props.url =
"https://chffrprivate.blob.core.windows.net/chffrprivate3-permanent/v2/cb38263377b873ee/78392b99580c5920227cc5b43dff8a70_2017-06-12--18-51-47";
props.name = "2017-06-12--18-51-47";
props.dongleId = "cb38263377b873ee";
props.url = 'https://chffrprivate.blob.core.windows.net/chffrprivate3-permanent/v2/cb38263377b873ee/78392b99580c5920227cc5b43dff8a70_2017-06-12--18-51-47';
props.name = '2017-06-12--18-51-47';
props.dongleId = 'cb38263377b873ee';
props.dbc = AcuraDbc;
props.isDemo = true;
props.dbcFilename = "acura_ilx_2016_can.dbc";
props.dbcFilename = 'acura_ilx_2016_can.dbc';
// lots of 404s on this one
// props.max = 752;
@ -97,17 +96,17 @@ async function init() {
if (token) {
Request.configure(token);
}
ReactDOM.render(<CanExplorer {...props} />, document.getElementById("root"));
ReactDOM.render(<CanExplorer {...props} />, document.getElementById('root'));
}
if (routeFullName || isDemo) {
init();
} else {
const img = document.createElement("img");
img.src = process.env.PUBLIC_URL + "/img/cabana.jpg";
img.style.width = "100%";
const comment = document.createComment("7/6/17");
const img = document.createElement('img');
img.src = `${process.env.PUBLIC_URL}/img/cabana.jpg`;
img.style.width = '100%';
const comment = document.createComment('7/6/17');
document.getElementById("root").appendChild(img);
document.getElementById("root").appendChild(comment);
document.getElementById('root').appendChild(img);
document.getElementById('root').appendChild(comment);
}

View File

@ -1,5 +1,5 @@
import LogEntries from "./LogEntries";
import { LOGENTRIES_TOKEN } from "../config";
import LogEntries from './LogEntries';
import { LOGENTRIES_TOKEN } from '../config';
class CloudLog {
constructor() {
@ -15,8 +15,8 @@ class CloudLog {
this.context.update(obj);
}
emit(message, level = "log") {
if (typeof global.__JEST__ !== "undefined") {
emit(message, level = 'log') {
if (typeof global.__JEST__ !== 'undefined') {
// Don't log in testing environment
return;
}
@ -25,14 +25,14 @@ class CloudLog {
ctx: this.context,
created: new Date().getTime() / 1000,
msg: message,
src: "JSCloudLog"
src: 'JSCloudLog'
};
if (level === "log") {
if (level === 'log') {
LogEntries.log(entry);
} else if (level === "warn") {
} else if (level === 'warn') {
LogEntries.warn(entry);
} else if (level === "error") {
} else if (level === 'error') {
LogEntries.error(entry);
}
}
@ -42,11 +42,11 @@ class CloudLog {
}
warn(message) {
this.emit(message, "warn");
this.emit(message, 'warn');
}
error(message) {
this.emit(message, "error");
this.emit(message, 'error');
}
}

View File

@ -1,15 +1,15 @@
import Raven from "raven-js";
import Raven from 'raven-js';
function init() {
if (process.env.NODE_ENV === "production") {
if (process.env.NODE_ENV === 'production') {
const opts = {};
if (typeof __webpack_hash__ !== "undefined") {
opts["release"] = __webpack_hash__; // eslint-disable-line no-undef
if (typeof __webpack_hash__ !== 'undefined') {
opts.release = __webpack_hash__; // eslint-disable-line no-undef
}
Raven.config(
"https://50006e5d91894f508dd288bbbf4585a6@sentry.io/185303",
'https://50006e5d91894f508dd288bbbf4585a6@sentry.io/185303',
opts
).install();
}

View File

@ -1,4 +1,4 @@
const Uint64BE = require("int64-buffer").Uint64BE;
const { Uint64BE } = require('int64-buffer');
export function formatForMsg(msg) {
return { bstart: 0, bend: 15 };
@ -7,7 +7,7 @@ export function formatForMsg(msg) {
export function formatMsgDec(msg) {
const { bstart, bend } = formatForMsg(msg);
const uint = Uint64BE(msg[1]);
var tt = "0" + uint.toString(2);
let tt = `0${uint.toString(2)}`;
tt = tt.substring(0, tt.length - (63 - bend));
tt = tt.substring(tt.length - (bend - bstart) - 1);
return [msg[0], parseInt(tt, 2)];
@ -20,17 +20,17 @@ export function uint64BEToHex(int64) {
export function int64BufferToPrettyHexStr(buffer) {
const uint = Uint64BE(buffer);
let hex = uint.toString(16);
if (hex.length === 1) hex = "0" + hex;
let hexParts = hex.match(/.{1,2}/g);
if (hex.length === 1) hex = `0${hex}`;
const hexParts = hex.match(/.{1,2}/g);
return hexParts.join(" ");
return hexParts.join(' ');
}
export function formatMsgHex(msg) {
const uint = Uint64BE(msg[1]);
let hex = uint.toString(16);
if (hex.length === 1) hex = "0" + hex;
let hexParts = hex.match(/.{1,2}/g);
if (hex.length === 1) hex = `0${hex}`;
const hexParts = hex.match(/.{1,2}/g);
return [msg[0], hexParts.join(" ")];
return [msg[0], hexParts.join(' ')];
}

View File

@ -1,12 +1,12 @@
import rightPad from "right-pad";
import CloudLog from "../../logging/CloudLog";
import Signal from "./signal";
import Frame from "./frame";
import BoardUnit from "./BoardUnit";
import DbcUtils from "../../utils/dbc";
import * as LogSignals from "./logSignals";
import rightPad from 'right-pad';
import CloudLog from '../../logging/CloudLog';
import Signal from './signal';
import Frame from './frame';
import BoardUnit from './BoardUnit';
import DbcUtils from '../../utils/dbc';
import * as LogSignals from './logSignals';
const UINT64 = require("cuint").UINT64;
const { UINT64 } = require('cuint');
const DBC_COMMENT_RE = /^CM_ *"(.*)";/;
const DBC_COMMENT_MULTI_LINE_RE = /^CM_ *"(.*)/;
@ -34,17 +34,16 @@ const BOARD_UNIT_COMMENT_RE = /^CM_ BU_ *(\w+) *"(.*)";/;
const BOARD_UNIT_COMMENT_MULTI_LINE_RE = /^CM_ BU_ *(\w+) *"(.*)/;
// Follow ups are used to parse multi-line comment definitions
const FOLLOW_UP_DBC_COMMENT = "FollowUpDbcComment";
const FOLLOW_UP_SIGNAL_COMMENT = "FollowUpSignalComment";
const FOLLOW_UP_MSG_COMMENT = "FollowUpMsgComment";
const FOLLOW_UP_BOARD_UNIT_COMMENT = "FollowUpBoardUnitComment";
const FOLLOW_UP_DBC_COMMENT = 'FollowUpDbcComment';
const FOLLOW_UP_SIGNAL_COMMENT = 'FollowUpSignalComment';
const FOLLOW_UP_MSG_COMMENT = 'FollowUpMsgComment';
const FOLLOW_UP_BOARD_UNIT_COMMENT = 'FollowUpBoardUnitComment';
function floatOrInt(numericStr) {
if (Number.isInteger(numericStr)) {
return parseInt(numericStr, 10);
} else {
return parseFloat(numericStr);
}
return parseFloat(numericStr);
}
export function swapOrder(arr, wordSize, gSize) {
@ -57,7 +56,7 @@ export function swapOrder(arr, wordSize, gSize) {
}
}
return swappedWords.join("");
return swappedWords.join('');
}
export default class DBC {
@ -82,14 +81,14 @@ export default class DBC {
nextNewFrameName() {
const messageNames = [];
for (let msg of this.messages.values()) {
for (const msg of this.messages.values()) {
messageNames.push(msg.name);
}
let msgNum = 1,
msgName;
let msgNum = 1;
let msgName;
do {
msgName = "NEW_MSG_" + msgNum;
msgName = `NEW_MSG_${msgNum}`;
msgNum++;
} while (messageNames.indexOf(msgName) !== -1);
@ -97,15 +96,15 @@ export default class DBC {
}
updateBoardUnits() {
const boardUnitNames = this.boardUnits.map(bu => bu.name);
const boardUnitNames = this.boardUnits.map((bu) => bu.name);
const missingBoardUnits = Array.from(this.messages.entries())
.map(([msgId, frame]) => Object.values(frame.signals))
.reduce((arr, signals) => arr.concat(signals), [])
.map(signal => signal.receiver)
.map((signal) => signal.receiver)
.reduce((arr, receivers) => arr.concat(receivers), [])
.filter((recv, idx, array) => array.indexOf(recv) === idx)
.filter(recv => boardUnitNames.indexOf(recv) === -1)
.map(recv => new BoardUnit(recv));
.filter((recv) => boardUnitNames.indexOf(recv) === -1)
.map((recv) => new BoardUnit(recv));
this.boardUnits = this.boardUnits.concat(missingBoardUnits);
}
@ -114,57 +113,54 @@ export default class DBC {
this.updateBoardUnits();
let txt = 'VERSION ""\n\n\n';
txt += "NS_ :" + this._newSymbols();
txt += "\n\nBS_:\n";
txt += `NS_ :${this._newSymbols()}`;
txt += '\n\nBS_:\n';
const boardUnitsText = this.boardUnits.map(bu => bu.text()).join(" ");
txt += "\nBU_: " + boardUnitsText + "\n\n\n";
const boardUnitsText = this.boardUnits.map((bu) => bu.text()).join(' ');
txt += `\nBU_: ${boardUnitsText}\n\n\n`;
const frames = [];
for (let frame of this.messages.values()) {
for (const frame of this.messages.values()) {
frames.push(frame);
}
txt += frames.map(f => f.text()).join("\n\n") + "\n\n";
txt += `${frames.map((f) => f.text()).join('\n\n')}\n\n`;
const messageTxs = frames
.map(f => [f.id, f.transmitters.slice(1)])
.map((f) => [f.id, f.transmitters.slice(1)])
.filter(([addr, txs]) => txs.length > 0);
txt +=
messageTxs
.map(([addr, txs]) => `BO_TX_BU_ ${addr} : ${txs.join(",")};`)
.join("\n") + "\n\n\n";
txt += `${messageTxs
.map(([addr, txs]) => `BO_TX_BU_ ${addr} : ${txs.join(',')};`)
.join('\n')}\n\n\n`;
txt += this.boardUnits
.filter(bu => bu.comment !== null)
.map(bu => `CM_ BU_ ${bu.name} "${bu.comment}";`)
.join("\n");
.filter((bu) => bu.comment !== null)
.map((bu) => `CM_ BU_ ${bu.name} "${bu.comment}";`)
.join('\n');
txt += frames
.filter(f => f.comment !== null)
.map(msg => `CM_ BO_ ${msg.address} "${msg.comment}";`)
.join("\n");
.filter((f) => f.comment !== null)
.map((msg) => `CM_ BO_ ${msg.address} "${msg.comment}";`)
.join('\n');
const signalsByMsgId = frames
.map(f => Object.values(f.signals).map(sig => [f.id, sig]))
.map((f) => Object.values(f.signals).map((sig) => [f.id, sig]))
.reduce((s1, s2) => s1.concat(s2), []);
txt +=
signalsByMsgId
.filter(([msgAddr, sig]) => sig.comment !== null)
.map(
([msgAddr, sig]) => `CM_ SG_ ${msgAddr} ${sig.name} "${sig.comment}";`
)
.join("\n") + "\n";
txt += `${signalsByMsgId
.filter(([msgAddr, sig]) => sig.comment !== null)
.map(
([msgAddr, sig]) => `CM_ SG_ ${msgAddr} ${sig.name} "${sig.comment}";`
)
.join('\n')}\n`;
txt +=
signalsByMsgId
.filter(([msgAddr, sig]) => sig.valueDescriptions.size > 0)
.map(([msgAddr, sig]) => sig.valueDescriptionText(msgAddr))
.join("\n") + "\n";
txt += `${signalsByMsgId
.filter(([msgAddr, sig]) => sig.valueDescriptions.size > 0)
.map(([msgAddr, sig]) => sig.valueDescriptionText(msgAddr))
.join('\n')}\n`;
txt += this.comments.map(comment => `CM_ "${comment}";`).join("\n");
txt += this.comments.map((comment) => `CM_ "${comment}";`).join('\n');
return txt.trim() + "\n";
return `${txt.trim()}\n`;
}
getMessageName(msgId) {
@ -218,11 +214,11 @@ export default class DBC {
const warnings = [];
const messages = new Map();
let boardUnits = [];
let valueTables = new Map();
const valueTables = new Map();
let id = 0;
let followUp = null;
const lines = dbcString.split("\n");
const lines = dbcString.split('\n');
for (let i = 0; i < lines.length; i++) {
let line = lines[i].trim();
@ -230,7 +226,7 @@ export default class DBC {
if (followUp != null) {
const { type, data } = followUp;
line = line.replace(/" *;/, "");
line = line.replace(/" *;/, '');
let followUpLine = `\n${line.substr(0, line.length)}`;
if (line.indexOf('"') !== -1) {
followUp = null;
@ -248,13 +244,12 @@ export default class DBC {
} else if (type === FOLLOW_UP_DBC_COMMENT) {
// const comment = data;
const partialComment = this.comments[this.comments.length - 1];
this.comments[this.comments.length - 1] =
partialComment + followUpLine;
this.comments[this.comments.length - 1] = partialComment + followUpLine;
}
}
if (line.indexOf("BO_ ") === 0) {
let matches = line.match(MSG_RE);
if (line.indexOf('BO_ ') === 0) {
const matches = line.match(MSG_RE);
if (matches === null) {
warnings.push(
`failed to parse message definition on line ${i + 1} -- ${line}`
@ -271,7 +266,7 @@ export default class DBC {
transmitters: [transmitter]
});
messages.set(id, frame);
} else if (line.indexOf("SG_") === 0) {
} else if (line.indexOf('SG_') === 0) {
let matches = line.match(SIGNAL_RE);
if (matches === null) {
@ -304,12 +299,12 @@ export default class DBC {
startBit = parseInt(startBit, 10);
size = parseInt(size, 10);
isLittleEndian = parseInt(isLittleEndian, 10) === 1;
isSigned = isSigned === "-";
isSigned = isSigned === '-';
factor = floatOrInt(factor);
offset = floatOrInt(offset);
min = floatOrInt(min);
max = floatOrInt(max);
const receiver = receiverStr.split(",").map(s => s.trim());
const receiver = receiverStr.split(',').map((s) => s.trim());
const signalProperties = {
name,
@ -330,35 +325,32 @@ export default class DBC {
messages.get(id).signals[name] = signal;
} else {
CloudLog.warn(
"importDbcString: could not add signal: " +
name +
" due to missing message: " +
id
`importDbcString: could not add signal: ${name} due to missing message: ${id}`
);
}
} else if (line.indexOf("VAL_ ") === 0) {
let matches = line.match(VAL_RE);
} else if (line.indexOf('VAL_ ') === 0) {
const matches = line.match(VAL_RE);
if (matches !== null) {
let [messageId, signalName, vals] = matches.slice(1);
vals = vals
.split('"')
.map(s => s.trim())
.filter(s => s.length > 0);
.map((s) => s.trim())
.filter((s) => s.length > 0);
messageId = parseInt(messageId, 10);
const msg = messages.get(messageId);
const signal = msg.signals[signalName];
if (signal === undefined) {
warnings.push(
`could not find signal for value description on line ${i +
1} -- ${line}`
`could not find signal for value description on line ${i
+ 1} -- ${line}`
);
continue;
}
for (let i = 0; i < vals.length; i += 2) {
const value = vals[i].trim(),
description = vals[i + 1].trim();
const value = vals[i].trim();
const description = vals[i + 1].trim();
signal.valueDescriptions.set(value, description);
}
} else {
@ -366,20 +358,20 @@ export default class DBC {
`failed to parse value description on line ${i + 1} -- ${line}`
);
}
} else if (line.indexOf("VAL_TABLE_ ") === 0) {
let matches = line.match(VAL_TABLE_RE);
} else if (line.indexOf('VAL_TABLE_ ') === 0) {
const matches = line.match(VAL_TABLE_RE);
if (matches !== null) {
const table = new Map();
let [tableName, items] = matches.slice(1);
items = items
.split('"')
.map(s => s.trim())
.filter(s => s.length > 0);
.map((s) => s.trim())
.filter((s) => s.length > 0);
for (let i = 0; i < items.length; i += 2) {
const key = items[i],
value = items[i + 1];
const key = items[i];
const value = items[i + 1];
table.set(key, value);
}
valueTables.set(tableName, table);
@ -388,8 +380,8 @@ export default class DBC {
`failed to parse value table on line ${i + 1} -- ${line}`
);
}
} else if (line.indexOf("BO_TX_BU_ ") === 0) {
let matches = line.match(MSG_TRANSMITTER_RE);
} else if (line.indexOf('BO_TX_BU_ ') === 0) {
const matches = line.match(MSG_TRANSMITTER_RE);
if (matches !== null) {
let [messageId, transmitter] = matches.slice(1);
@ -400,11 +392,11 @@ export default class DBC {
messages.set(messageId, msg);
} else {
warnings.push(
`failed to parse message transmitter definition on line ${i +
1} -- ${line}`
`failed to parse message transmitter definition on line ${i
+ 1} -- ${line}`
);
}
} else if (line.indexOf("CM_ SG_ ") === 0) {
} else if (line.indexOf('CM_ SG_ ') === 0) {
let matches = line.match(SIGNAL_COMMENT_RE);
let hasFollowUp = false;
if (matches === null) {
@ -423,8 +415,8 @@ export default class DBC {
messageId = parseInt(messageId, 10);
const msg = messages.get(messageId);
if (msg === undefined) {
warnings.push(`failed to parse signal comment on line ${i +
1} -- ${line}:
warnings.push(`failed to parse signal comment on line ${i
+ 1} -- ${line}:
message id ${messageId} does not exist prior to this line`);
continue;
}
@ -442,7 +434,7 @@ export default class DBC {
if (hasFollowUp) {
followUp = { type: FOLLOW_UP_SIGNAL_COMMENT, data: signal };
}
} else if (line.indexOf("CM_ BO_ ") === 0) {
} else if (line.indexOf('CM_ BO_ ') === 0) {
let matches = line.match(MESSAGE_COMMENT_RE);
let hasFollowUp = false;
if (matches === null) {
@ -464,16 +456,16 @@ export default class DBC {
if (hasFollowUp) {
followUp = { type: FOLLOW_UP_MSG_COMMENT, data: msg };
}
} else if (line.indexOf("BU_: ") === 0) {
let matches = line.match(BOARD_UNIT_RE);
} else if (line.indexOf('BU_: ') === 0) {
const matches = line.match(BOARD_UNIT_RE);
if (matches !== null) {
const [boardUnitNameStr] = matches.slice(1);
const newBoardUnits = boardUnitNameStr
.split(" ")
.map(s => s.trim())
.filter(s => s.length > 0)
.map(name => new BoardUnit(name));
.split(' ')
.map((s) => s.trim())
.filter((s) => s.length > 0)
.map((name) => new BoardUnit(name));
boardUnits = boardUnits.concat(newBoardUnits);
} else {
@ -482,7 +474,7 @@ export default class DBC {
);
continue;
}
} else if (line.indexOf("CM_ BU_ ") === 0) {
} else if (line.indexOf('CM_ BU_ ') === 0) {
let matches = line.match(BOARD_UNIT_COMMENT_RE);
let hasFollowUp = false;
if (matches === null) {
@ -496,8 +488,8 @@ export default class DBC {
}
}
let [boardUnitName, comment] = matches.slice(1);
let boardUnit = boardUnits.find(bu => bu.name === boardUnitName);
const [boardUnitName, comment] = matches.slice(1);
const boardUnit = boardUnits.find((bu) => bu.name === boardUnitName);
if (boardUnit) {
boardUnit.comment = comment;
}
@ -505,7 +497,7 @@ export default class DBC {
if (hasFollowUp) {
followUp = { type: FOLLOW_UP_BOARD_UNIT_COMMENT, data: boardUnit };
}
} else if (line.indexOf("CM_ ") === 0) {
} else if (line.indexOf('CM_ ') === 0) {
let matches = line.match(DBC_COMMENT_RE);
let hasFollowUp = false;
if (matches === null) {
@ -520,7 +512,7 @@ export default class DBC {
}
}
let [comment] = matches.slice(1);
const [comment] = matches.slice(1);
this.comments.push(comment);
if (hasFollowUp) {
followUp = { type: FOLLOW_UP_DBC_COMMENT, data: comment };
@ -542,7 +534,9 @@ export default class DBC {
valueForInt64Signal(signalSpec, hexData) {
const blen = hexData.length * 4;
let value, startBit, dataBitPos;
let value;
let startBit;
let dataBitPos;
if (signalSpec.isLittleEndian) {
value = UINT64(swapOrder(hexData, 16, 2), 16);
@ -559,7 +553,7 @@ export default class DBC {
return null;
}
let rightHandAnd = UINT64(Math.pow(2, signalSpec.size) - 1);
const rightHandAnd = UINT64(Math.pow(2, signalSpec.size) - 1);
let ival = value
.shiftr(dataBitPos)
.and(rightHandAnd)
@ -573,11 +567,11 @@ export default class DBC {
}
valueForInt32Signal(signalSpec, buf) {
var startBit;
let startBit;
if (signalSpec.isLittleEndian) {
startBit = 64 - signalSpec.startBit - signalSpec.size;
} else {
var bitPos = (-signalSpec.startBit - 1) % 8;
let bitPos = (-signalSpec.startBit - 1) % 8;
if (bitPos < 0) {
bitPos += 8; // mimic python modulo behavior
}
@ -585,8 +579,9 @@ export default class DBC {
startBit = Math.floor(signalSpec.startBit / 8) * 8 + bitPos;
}
var shiftAmount, signalValue;
let byteOffset = Math.min(4, Math.floor(signalSpec.startBit / 8));
let shiftAmount;
let signalValue;
const byteOffset = Math.min(4, Math.floor(signalSpec.startBit / 8));
if (signalSpec.isLittleEndian) {
signalValue = buf.readUInt32LE(byteOffset);
shiftAmount = signalSpec.startBit - 8 * byteOffset;
@ -609,17 +604,17 @@ export default class DBC {
}
const frame = this.getMessageFrame(messageId);
let buffer = Buffer.from(data);
const buffer = Buffer.from(data);
let paddedBuffer = buffer;
if (buffer.length !== 8) {
// pad data it's 64 bits long
const paddedDataHex = rightPad(buffer.toString("hex"), 16, "0");
paddedBuffer = Buffer.from(paddedDataHex, "hex");
const paddedDataHex = rightPad(buffer.toString('hex'), 16, '0');
paddedBuffer = Buffer.from(paddedDataHex, 'hex');
}
const hexData = paddedBuffer.toString("hex");
const hexData = paddedBuffer.toString('hex');
const signalValuesByName = {};
Object.values(frame.signals).forEach(signalSpec => {
Object.values(frame.signals).forEach((signalSpec) => {
let value;
if (signalSpec.size > 32) {
value = this.valueForInt64Signal(signalSpec, hexData);
@ -634,15 +629,15 @@ export default class DBC {
getChffrMetricMappings() {
const metricComment = this.comments.find(
comment => comment.indexOf("CHFFR_METRIC") === 0
(comment) => comment.indexOf('CHFFR_METRIC') === 0
);
if (!metricComment) {
return null;
}
return metricComment
.split(";")
.map(metric => metric.trim().split(" "))
.split(';')
.map((metric) => metric.trim().split(' '))
.reduce(
(metrics, [_, messageId, signalName, metricName, factor, offset]) => {
metrics[metricName] = {

View File

@ -1,9 +1,9 @@
function findTimeIndex(entries, time) {
return entries.findIndex(e => e.time >= time);
return entries.findIndex((e) => e.time >= time);
}
function findRelativeTimeIndex(entries, relTime) {
return entries.findIndex(e => e.relTime >= relTime);
return entries.findIndex((e) => e.relTime >= relTime);
}
function findSegmentIndices(
@ -20,17 +20,15 @@ function findSegmentIndices(
Returns `[segmentIdxLow, segmentIdxHigh]`
(inclusive, exclusive)
*/
let timeIndexFunc =
isRelative === true ? findRelativeTimeIndex : findTimeIndex;
const timeIndexFunc = isRelative === true ? findRelativeTimeIndex : findTimeIndex;
const segmentIdxLow = Math.max(0, timeIndexFunc(entries, segmentTimeLow));
const upperSegments = entries.slice(segmentIdxLow);
let upperSegmentIdxHi = timeIndexFunc(upperSegments, segmentTimeHi);
const segmentIdxHi =
upperSegmentIdxHi >= 0
? upperSegmentIdxHi + segmentIdxLow + 1
: entries.length - 1;
const upperSegmentIdxHi = timeIndexFunc(upperSegments, segmentTimeHi);
const segmentIdxHi = upperSegmentIdxHi >= 0
? upperSegmentIdxHi + segmentIdxLow + 1
: entries.length - 1;
return [
segmentIdxLow,

View File

@ -20,10 +20,10 @@ export default class Frame {
}
nextNewTransmitterName() {
let txNum = 1,
txName;
let txNum = 1;
let txName;
do {
txName = "NEW_TRANSMITTER_" + txNum;
txName = `NEW_TRANSMITTER_${txNum}`;
txNum++;
} while (this.transmitters.indexOf(txName) !== -1);
@ -38,21 +38,20 @@ export default class Frame {
header() {
return (
`BO_ ${this.id} ${this.name}: ${this.size} ` +
`${this.transmitters[0] || "XXX"}`
`BO_ ${this.id} ${this.name}: ${this.size} `
+ `${this.transmitters[0] || 'XXX'}`
);
}
text() {
const signals = Object.values(this.signals)
.map(signal => " " + signal.text()) // indent
.join("\n");
.map((signal) => ` ${signal.text()}`) // indent
.join('\n');
if (signals.length > 0) {
return this.header() + "\n" + signals;
} else {
return this.header();
return `${this.header()}\n${signals}`;
}
return this.header();
}
copy() {

View File

@ -1,5 +1,5 @@
import Frame from "./frame";
import Signal from "./signal";
import Frame from './frame';
import Signal from './signal';
export const wheelSpeeds = {
FrontLeftWheel: shortSignal({
@ -82,13 +82,13 @@ export const flags = {
Standstill: boolSignal({
index: 8
}),
"CruiseState.Enabled": boolSignal({
'CruiseState.Enabled': boolSignal({
index: 9
}),
"CruiseState.Available": boolSignal({
'CruiseState.Available': boolSignal({
index: 10
}),
"CruiseState.Standstill": boolSignal({
'CruiseState.Standstill': boolSignal({
index: 11
}),
GearShifter: {
@ -96,7 +96,7 @@ export const flags = {
size: 4,
unsigned: true
},
"CruiseState.Speed": charSignal({
'CruiseState.Speed': charSignal({
index: 2
})
};
@ -192,21 +192,21 @@ export const thermalFreeSpace = {
};
export const signalMap = {
"CarState:WheelSpeeds": wheelSpeeds,
"CarState:Ego": ego,
"CarState:Controls": controls,
"CarState:Flags": flags,
"UbloxGnss:MeasurementReport": ubloxGnss,
"Health:Data": health,
"Thermal:CPU": thermalCPU,
"Thermal:Data": thermalData,
"Thermal:FreeSpace": thermalFreeSpace
'CarState:WheelSpeeds': wheelSpeeds,
'CarState:Ego': ego,
'CarState:Controls': controls,
'CarState:Flags': flags,
'UbloxGnss:MeasurementReport': ubloxGnss,
'Health:Data': health,
'Thermal:CPU': thermalCPU,
'Thermal:Data': thermalData,
'Thermal:FreeSpace': thermalFreeSpace
};
const ADDRESS_LIST = [];
Object.keys(signalMap).forEach(function(name) {
Object.keys(signalMap[name]).forEach(function(signal) {
Object.keys(signalMap).forEach((name) => {
Object.keys(signalMap[name]).forEach((signal) => {
signalMap[name][signal] = createSignalEntry({
name: signal,
...signalMap[name][signal]
@ -224,7 +224,7 @@ function createSignalEntry(options) {
isSigned: !options.unsigned,
factor: options.factor || 1,
offset: options.offset || 0,
unit: options.unit || ""
unit: options.unit || ''
});
}
@ -262,7 +262,7 @@ function boolSignal(options) {
}
export function addressForName(name) {
var i = ADDRESS_LIST.indexOf(name);
const i = ADDRESS_LIST.indexOf(name);
if (i === -1) {
ADDRESS_LIST.push(name);
return ADDRESS_LIST.indexOf(name) + 0x1000;
@ -282,10 +282,10 @@ export function isLogAddress(address) {
}
export function frameForAddress(address) {
let name = nameForAddress(address);
const name = nameForAddress(address);
return new Frame({
id: name,
name: name,
name,
size: 8,
signals: signalMap[name]
});

View File

@ -1,4 +1,4 @@
import DbcUtils from "../../utils/dbc";
import DbcUtils from '../../utils/dbc';
export default class Signal {
constructor({
@ -10,8 +10,8 @@ export default class Signal {
isFloat = false,
factor = 1,
offset = 0,
unit = "",
receiver = ["XXX"],
unit = '',
receiver = ['XXX'],
comment = null,
multiplex = null,
min = null,
@ -45,28 +45,33 @@ export default class Signal {
const colors = this.generateColors();
Object.assign(this, { min, max, uid, colors });
Object.assign(this, {
min,
max,
uid,
colors
});
}
text() {
const multiplex = this.multiplex ? " " + this.multiplex : "";
const multiplex = this.multiplex ? ` ${this.multiplex}` : '';
const byteOrder = this.isLittleEndian ? 1 : 0;
const signedChar = this.isSigned ? "-" : "+";
const signedChar = this.isSigned ? '-' : '+';
return (
`SG_ ${this.name}${multiplex} : ` +
`${this.startBit}|${this.size}@${byteOrder}${signedChar}` +
` (${this.factor},${this.offset})` +
` [${this.min}|${this.max}]` +
` "${this.unit}" ${this.receiver}`
`SG_ ${this.name}${multiplex} : `
+ `${this.startBit}|${this.size}@${byteOrder}${signedChar}`
+ ` (${this.factor},${this.offset})`
+ ` [${this.min}|${this.max}]`
+ ` "${this.unit}" ${this.receiver}`
);
}
valueDescriptionText(msgId) {
const entryPairs = Array.from(this.valueDescriptions.entries());
const values = entryPairs.reduce(
(str, [value, desc]) => str + value + ` "${desc}" `,
""
(str, [value, desc]) => `${str + value} "${desc}" `,
''
);
return `VAL_ ${msgId} ${this.name} ${values};`;
}
@ -76,11 +81,10 @@ export default class Signal {
if (this.isLittleEndian) {
return this.startBit;
} else {
const lsbBitNumber = this.lsbBitNumber();
return DbcUtils.matrixBitNumber(lsbBitNumber);
}
const lsbBitNumber = this.lsbBitNumber();
return DbcUtils.matrixBitNumber(lsbBitNumber);
}
lsbBitNumber() {
@ -92,21 +96,19 @@ export default class Signal {
msbBitIndex() {
if (this.isLittleEndian) {
return this.startBit + this.size - 1;
} else {
return this.startBit;
}
return this.startBit;
}
littleEndianBitDescription(bitIndex) {
const bitRange = [this.startBit, this.startBit + this.size - 1];
if (bitIndex < bitRange[0] || bitIndex > bitRange[1]) {
return null;
} else {
const bitNumber = bitIndex - bitRange[0];
const isLsb = bitIndex === bitRange[0];
const isMsb = bitIndex === bitRange[1];
return { bitNumber, isLsb, isMsb };
}
const bitNumber = bitIndex - bitRange[0];
const isLsb = bitIndex === bitRange[0];
const isMsb = bitIndex === bitRange[1];
return { bitNumber, isLsb, isMsb };
}
bigEndianBitDescription(bitIndex) {
@ -120,15 +122,19 @@ export default class Signal {
const isLsb = bitNumber === range[1];
const isMsb = bitIndex === this.startBit;
return { bitNumber, isLsb, isMsb, range };
return {
bitNumber,
isLsb,
isMsb,
range
};
}
bitDescription(bitIndex) {
if (this.isLittleEndian) {
return this.littleEndianBitDescription(bitIndex);
} else {
return this.bigEndianBitDescription(bitIndex);
}
return this.bigEndianBitDescription(bitIndex);
}
calculateRawRange() {
@ -150,7 +156,7 @@ export default class Signal {
}
generateColors() {
let colors = Array(3);
const colors = Array(3);
for (let i = 0; i < 3; i++) {
colors[i] = Math.floor(Math.random() * 211);
}
@ -160,19 +166,19 @@ export default class Signal {
equals(otherSignal) {
return (
otherSignal.name === this.name &&
otherSignal.startBit === this.startBit &&
otherSignal.size === this.size &&
otherSignal.isLittleEndian === this.isLittleEndian &&
otherSignal.isSigned === this.isSigned &&
otherSignal.isFloat === this.isFloat &&
otherSignal.factor === this.factor &&
otherSignal.offset === this.offset &&
otherSignal.unit === this.unit &&
otherSignal.receiver.length === this.receiver.length &&
otherSignal.receiver.every((v, i) => v === this.receiver[i]) &&
otherSignal.comment === this.comment &&
otherSignal.multiplex === this.multiplex
otherSignal.name === this.name
&& otherSignal.startBit === this.startBit
&& otherSignal.size === this.size
&& otherSignal.isLittleEndian === this.isLittleEndian
&& otherSignal.isSigned === this.isSigned
&& otherSignal.isFloat === this.isFloat
&& otherSignal.factor === this.factor
&& otherSignal.offset === this.offset
&& otherSignal.unit === this.unit
&& otherSignal.receiver.length === this.receiver.length
&& otherSignal.receiver.every((v, i) => v === this.receiver[i])
&& otherSignal.comment === this.comment
&& otherSignal.multiplex === this.multiplex
);
}
}

View File

@ -1,18 +1,18 @@
import ArrayUtils from "../utils/array";
import { CAN_GRAPH_MAX_POINTS } from "../config";
import ArrayUtils from '../utils/array';
import { CAN_GRAPH_MAX_POINTS } from '../config';
function _calcGraphData(msg, signalUid, firstCanTime) {
if (!msg) return null;
const signal = Object.values(msg.frame.signals).find(
s => s.uid === signalUid
(s) => s.uid === signalUid
);
if (!signal) {
console.warn("_calcGraphData: no signal", signalUid, msg);
console.warn('_calcGraphData: no signal', signalUid, msg);
return null;
}
let samples = [];
let skip = Math.floor(msg.entries.length / CAN_GRAPH_MAX_POINTS);
const skip = Math.floor(msg.entries.length / CAN_GRAPH_MAX_POINTS);
if (skip === 0) {
samples = msg.entries;
@ -29,8 +29,8 @@ function _calcGraphData(msg, signalUid, firstCanTime) {
// sorting these doesn't fix the phantom lines
let lastEntry = samples[0].relTime;
return samples
.filter(e => e.signals[signal.name] !== undefined)
.map(entry => {
.filter((e) => e.signals[signal.name] !== undefined)
.map((entry) => {
if (entry.relTime - lastEntry > 2) {
signalUid = Math.random().toString(36);
}
@ -41,7 +41,7 @@ function _calcGraphData(msg, signalUid, firstCanTime) {
relTime: entry.relTime,
y: entry.signals[signal.name],
unit: signal.unit,
color: `rgba(${signal.colors.join(",")}, 0.5)`,
color: `rgba(${signal.colors.join(',')}, 0.5)`,
signalName: signal.name,
signalUid
};
@ -49,17 +49,13 @@ function _calcGraphData(msg, signalUid, firstCanTime) {
}
function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
const messagesPerPlot = plottedSignals.map(plottedMessages =>
plottedMessages.reduce((messages, { messageId, signalUid }) => {
messages.push(messageId);
return messages;
}, [])
);
const messagesPerPlot = plottedSignals.map((plottedMessages) => plottedMessages.reduce((messages, { messageId, signalUid }) => {
messages.push(messageId);
return messages;
}, []));
const extendedPlots = messagesPerPlot
.map((plottedMessageIds, index) => {
return { plottedMessageIds, index };
}) // preserve index so we can look up graphData
.map((plottedMessageIds, index) => ({ plottedMessageIds, index })) // preserve index so we can look up graphData
.filter(({ plottedMessageIds, index }) => {
if (index < graphData.length) {
let maxGraphTime = 0;
@ -69,13 +65,11 @@ function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
}
return plottedMessageIds.some(
messageId =>
(messages[messageId].entries.length > 0 && series.length === 0) ||
messages[messageId].entries.some(e => e.relTime > maxGraphTime)
(messageId) => (messages[messageId].entries.length > 0 && series.length === 0)
|| messages[messageId].entries.some((e) => e.relTime > maxGraphTime)
);
} else {
return false;
}
return false;
})
.map(({ plottedMessageIds, index }) => {
plottedMessageIds = plottedMessageIds.reduce((arr, messageId) => {
@ -102,9 +96,10 @@ function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
const graphDataMaxMessageTimes = plottedMessageIds.reduce(
(obj, messageId) => {
const signalUids = signalUidsByMessageId[messageId];
const maxIndex = ArrayUtils.findIndexRight(series, entry => {
return signalUids.indexOf(entry.signalUid) !== -1;
});
const maxIndex = ArrayUtils.findIndexRight(
series,
(entry) => signalUids.indexOf(entry.signalUid) !== -1
);
if (maxIndex) {
obj[messageId] = series[maxIndex].relTime;
} else if (series.length > 0) {
@ -121,24 +116,21 @@ function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
let newGraphData = [];
plottedMessageIds
.map(messageId => {
return { messageId, entries: messages[messageId].entries };
})
.map((messageId) => ({ messageId, entries: messages[messageId].entries }))
.filter(
(
{ messageId, entries } // Filter to only messages with stale graphData
) =>
entries[entries.length - 1].relTime >
graphDataMaxMessageTimes[messageId]
) => entries[entries.length - 1].relTime
> graphDataMaxMessageTimes[messageId]
)
.forEach(({ messageId, entries }) => {
// Compute and append new graphData
let firstNewEntryIdx = entries.findIndex(
entry => entry.relTime > graphDataMaxMessageTimes[messageId]
const firstNewEntryIdx = entries.findIndex(
(entry) => entry.relTime > graphDataMaxMessageTimes[messageId]
);
const newEntries = entries.slice(firstNewEntryIdx);
signalUidsByMessageId[messageId].forEach(signalUid => {
signalUidsByMessageId[messageId].forEach((signalUid) => {
const signalGraphData = _calcGraphData(
{
...messages[messageId],
@ -152,12 +144,10 @@ function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
});
});
const messageIdOutOfBounds =
series.length > 0 &&
plottedMessageIds.find(
messageId =>
messages[messageId].entries.length > 0 &&
series[0].relTime < messages[messageId].entries[0].relTime
const messageIdOutOfBounds = series.length > 0
&& plottedMessageIds.find(
(messageId) => messages[messageId].entries.length > 0
&& series[0].relTime < messages[messageId].entries[0].relTime
);
graphData[index] = {
series: graphData[index].series.concat(newGraphData),
@ -166,7 +156,7 @@ function appendNewGraphData(plottedSignals, graphData, messages, firstCanTime) {
if (messageIdOutOfBounds) {
const graphDataLowerBound = graphData[index].series.findIndex(
e => e.relTime > messages[messageIdOutOfBounds].entries[0].relTime
(e) => e.relTime > messages[messageIdOutOfBounds].entries[0].relTime
);
if (graphDataLowerBound) {

View File

@ -1,4 +1,4 @@
import { configure } from "enzyme";
import Adapter from "enzyme-adapter-react-16";
import { configure } from 'enzyme';
import Adapter from 'enzyme-adapter-react-16';
configure({ adapter: new Adapter() });

View File

@ -1,7 +1,7 @@
import React from "react";
import { StyleSheet, css } from "aphrodite/no-important";
import React from 'react';
import { StyleSheet, css } from 'aphrodite/no-important';
import * as ObjectUtils from "../utils/object";
import * as ObjectUtils from '../utils/object';
function createImageComponent(source, alt, styles) {
if (styles === undefined) {
@ -10,13 +10,13 @@ function createImageComponent(source, alt, styles) {
styles = [styles];
}
return props => {
return (props) => {
let localStyles = styles.slice();
if (Array.isArray(props.styles)) {
localStyles = localStyles.concat(props.styles);
// filter 'styles' from props, which is passed via spread to <img> tag.
props = ObjectUtils.fromArray(
Object.entries(props).filter(([k, v]) => k !== "styles")
Object.entries(props).filter(([k, v]) => k !== 'styles')
);
}
@ -32,36 +32,42 @@ const Styles = StyleSheet.create({
height: 24
},
pointer: {
cursor: "pointer"
cursor: 'pointer'
}
});
const leftArrow = createImageComponent(
process.env.PUBLIC_URL + "/img/ic_arrow_left_black_24dp.png",
"Left arrow",
`${process.env.PUBLIC_URL}/img/ic_arrow_left_black_24dp.png`,
'Left arrow',
Styles.materialIcon
);
const rightArrow = createImageComponent(
process.env.PUBLIC_URL + "/img/ic_arrow_right_black_24dp.png",
"Right arrow",
`${process.env.PUBLIC_URL}/img/ic_arrow_right_black_24dp.png`,
'Right arrow',
Styles.materialIcon
);
const downArrow = createImageComponent(
process.env.PUBLIC_URL + "/img/ic_arrow_drop_down_black_24dp.png",
"Down arrow",
`${process.env.PUBLIC_URL}/img/ic_arrow_drop_down_black_24dp.png`,
'Down arrow',
Styles.materialIcon
);
const clear = createImageComponent(
process.env.PUBLIC_URL + "/img/ic_clear_black_24dp.png",
"Clear",
`${process.env.PUBLIC_URL}/img/ic_clear_black_24dp.png`,
'Clear',
[Styles.materialIcon, Styles.pointer]
);
const panda = createImageComponent(
process.env.PUBLIC_URL + "/img/panda.png",
"Panda",
`${process.env.PUBLIC_URL}/img/panda.png`,
'Panda',
[]
);
export default { rightArrow, leftArrow, downArrow, clear, panda };
export default {
rightArrow,
leftArrow,
downArrow,
clear,
panda
};

View File

@ -1,14 +1,14 @@
import { StyleSheet } from "aphrodite/no-important";
import { StyleSheet } from 'aphrodite/no-important';
export default StyleSheet.create({
tab: {
display: "inline",
display: 'inline',
marginRight: 20,
cursor: "pointer"
cursor: 'pointer'
},
selectedTab: {
borderBottom: "2px solid #000",
fontWeight: "bold"
borderBottom: '2px solid #000',
fontWeight: 'bold'
},
tabContent: {
paddingTop: 20

View File

@ -1,22 +1,22 @@
import { StyleSheet } from "aphrodite/no-important";
import { StyleSheet } from 'aphrodite/no-important';
export default StyleSheet.create({
root: {
flexDirection: "row"
flexDirection: 'row'
},
button: {
cursor: "pointer",
backgroundColor: "RGB(63, 135, 255)",
cursor: 'pointer',
backgroundColor: 'RGB(63, 135, 255)',
borderRadius: 5,
minWidth: 80,
paddingLeft: 20,
paddingRight: 20,
display: "flex",
alignItems: "center",
justifyContent: "center",
color: "white",
":hover": {
backgroundColor: "RGBA(63, 135, 255, 0.5)"
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
color: 'white',
':hover': {
backgroundColor: 'RGBA(63, 135, 255, 0.5)'
}
}
});

View File

@ -4,14 +4,14 @@
// Useful for component testing
import { css } from "aphrodite";
import classNames from "classnames";
import { css } from 'aphrodite';
import classNames from 'classnames';
export default function() {
export default function () {
const styles = [];
const classes = [];
[].forEach.call(arguments, it => {
[].forEach.call(arguments, (it) => {
if (it && it._definition && it._name) styles.push(it);
else classes.push(it);
});

View File

@ -1,6 +1,6 @@
function findMaxByteStateChangeCount(messages) {
return Object.values(messages)
.map(m => m.byteStateChangeCounts)
.map((m) => m.byteStateChangeCounts)
.reduce((counts, countArr) => counts.concat(countArr), []) // flatten arrays
.reduce((count1, count2) => (count1 > count2 ? count1 : count2), 0); // find max
}
@ -13,20 +13,20 @@ function addCanMessage(
prevMsgEntries,
byteStateChangeCountsByMessage
) {
var { address, busTime, data, bus } = canMessage;
var id = bus + ":" + address.toString(16);
const {
address, busTime, data, bus
} = canMessage;
const id = `${bus}:${address.toString(16)}`;
if (messages[id] === undefined)
messages[id] = createMessageSpec(dbc, address, id, bus);
if (messages[id] === undefined) messages[id] = createMessageSpec(dbc, address, id, bus);
const prevMsgEntry =
messages[id].entries.length > 0
? messages[id].entries[messages[id].entries.length - 1]
: prevMsgEntries[id] || null;
const prevMsgEntry = messages[id].entries.length > 0
? messages[id].entries[messages[id].entries.length - 1]
: prevMsgEntries[id] || null;
if (
byteStateChangeCountsByMessage[id] &&
messages[id].byteStateChangeCounts.every(c => c === 0)
byteStateChangeCountsByMessage[id]
&& messages[id].byteStateChangeCounts.every((c) => c === 0)
) {
messages[id].byteStateChangeCounts = byteStateChangeCountsByMessage[id];
}
@ -54,11 +54,11 @@ function createMessageSpec(dbc, address, id, bus) {
const size = frame ? frame.size : 8;
return {
address: address,
id: id,
bus: bus,
address,
id,
bus,
entries: [],
frame: frame,
frame,
byteColors: Array(size).fill(0),
byteStateChangeCounts: Array(size).fill(0)
};
@ -79,8 +79,8 @@ function determineByteStateChangeTimes(
byteStateChangeTimes = Array.from(lastParsedMessage.byteStateChangeTimes);
for (let i = 0; i < byteStateChangeTimes.length; i++) {
const currentData = hexData.substr(i * 2, 2),
prevData = lastParsedMessage.hexData.substr(i * 2, 2);
const currentData = hexData.substr(i * 2, 2);
const prevData = lastParsedMessage.hexData.substr(i * 2, 2);
if (currentData !== prevData) {
byteStateChangeTimes[i] = time;
@ -104,7 +104,7 @@ function createMessageEntry(
signals: dbc.getSignalValues(address, data),
time,
relTime,
hexData: Buffer.from(data).toString("hex"),
hexData: Buffer.from(data).toString('hex'),
byteStateChangeTimes,
updated: Date.now()
};
@ -112,11 +112,11 @@ function createMessageEntry(
function parseMessage(dbc, time, address, data, timeStart, lastParsedMessage) {
let hexData;
if (typeof data === "string") {
if (typeof data === 'string') {
hexData = data;
data = Buffer.from(data, "hex");
data = Buffer.from(data, 'hex');
} else {
hexData = Buffer.from(data).toString("hex");
hexData = Buffer.from(data).toString('hex');
}
const msgSpec = dbc.getMessageFrame(address);
const msgSize = msgSpec ? msgSpec.size : 8;
@ -160,13 +160,10 @@ function matrixBitNumber(bigEndianIndex) {
function setMessageByteColors(message, maxByteStateChangeCount) {
message.byteColors = message.byteStateChangeCounts
.map(
count =>
isNaN(count)
? 0
: Math.min(255, 75 + 180 * (count / maxByteStateChangeCount))
)
.map(red => "rgb(" + Math.round(red) + ",0,0)");
.map((count) => (isNaN(count)
? 0
: Math.min(255, 75 + 180 * (count / maxByteStateChangeCount))))
.map((red) => `rgb(${Math.round(red)},0,0)`);
return message;
}

View File

@ -1,13 +1,13 @@
export default function debounce(func, wait, immediate) {
var timeout;
return function() {
var context = this,
args = arguments;
var later = function() {
let timeout;
return function () {
const context = this;
const args = arguments;
const later = function () {
timeout = null;
if (!immediate) func.apply(context, args);
};
var callNow = immediate && !timeout;
const callNow = immediate && !timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) func.apply(context, args);

View File

@ -1,19 +1,19 @@
const binTimeIntervals = [
{
seconds: 1,
title: "second"
title: 'second'
},
{
seconds: 60,
title: "minute"
title: 'minute'
},
{
seconds: 300,
title: "5 minutes"
title: '5 minutes'
},
{
seconds: 3600,
title: "hour"
title: 'hour'
}
];
@ -33,13 +33,13 @@ function prettyBinDuration(samplesDurationSeconds, maxBinCount = 100) {
}
export function binMessages(messageEntries, segmentIndices) {
let startIdx = 0,
endIdx = messageEntries.length - 1;
let startIdx = 0;
let endIdx = messageEntries.length - 1;
if (segmentIndices && segmentIndices.length === 2) {
[startIdx, endIdx] = segmentIndices;
}
const first = messageEntries[startIdx],
last = messageEntries[endIdx];
const first = messageEntries[startIdx];
const last = messageEntries[endIdx];
const binDuration = prettyBinDuration(last.time - first.time);
const bins = [];
@ -63,5 +63,5 @@ export function binMessages(messageEntries, segmentIndices) {
});
}
return { bins: bins, binDuration };
return { bins, binDuration };
}

View File

@ -7,103 +7,103 @@ const NumpyLoader = (function NumpyLoader() {
}
function readUint16LE(buffer) {
var view = new DataView(buffer);
var val = view.getUint8(0);
const view = new DataView(buffer);
let val = view.getUint8(0);
val |= view.getUint8(1) << 8;
return val;
}
function fromArrayBuffer(buf) {
// Check the magic number
var magic = asciiDecode(buf.slice(0, 6));
if (magic !== "\x93NUMPY") {
throw new Error("Bad magic number");
const magic = asciiDecode(buf.slice(0, 6));
if (magic !== '\x93NUMPY') {
throw new Error('Bad magic number');
}
var version = new Uint8Array(buf.slice(6, 8)),
headerLength = readUint16LE(buf.slice(8, 10)),
headerStr = asciiDecode(buf.slice(10, 10 + headerLength));
const version = new Uint8Array(buf.slice(6, 8));
const headerLength = readUint16LE(buf.slice(8, 10));
const headerStr = asciiDecode(buf.slice(10, 10 + headerLength));
const offsetBytes = 10 + headerLength;
//rest = buf.slice(10+headerLength); XXX -- This makes a copy!!! https://www.khronos.org/registry/typedarray/specs/latest/#5
// rest = buf.slice(10+headerLength); XXX -- This makes a copy!!! https://www.khronos.org/registry/typedarray/specs/latest/#5
// Hacky conversion of dict literal string to JS Object
const info = JSON.parse(
headerStr
.toLowerCase()
.replace("(", "[")
.replace("),", "]")
.replace('(', '[')
.replace('),', ']')
.replace(/'/g, '"')
.replace(",]", "]")
.replace(',]', ']')
);
// Intepret the bytes according to the specified dtype
var data;
if (info.descr === "|u1") {
let data;
if (info.descr === '|u1') {
data = new Uint8Array(buf, offsetBytes);
} else if (info.descr === "|i1") {
} else if (info.descr === '|i1') {
data = new Int8Array(buf, offsetBytes);
} else if (info.descr === "<u2") {
} else if (info.descr === '<u2') {
data = new Uint16Array(buf, offsetBytes);
} else if (info.descr === "<i2") {
} else if (info.descr === '<i2') {
data = new Int16Array(buf, offsetBytes);
} else if (info.descr === "<u4") {
} else if (info.descr === '<u4') {
data = new Uint32Array(buf, offsetBytes);
} else if (info.descr === "<i4") {
} else if (info.descr === '<i4') {
data = new Int32Array(buf, offsetBytes);
} else if (info.descr === "<f4") {
} else if (info.descr === '<f4') {
data = new Float32Array(buf, offsetBytes);
} else if (info.descr === "<f8") {
} else if (info.descr === '<f8') {
data = new Float64Array(buf, offsetBytes);
} else if (info.descr === "<u8") {
} else if (info.descr === '<u8') {
// 8 byte uint64s
data = new Uint8Array(buf, offsetBytes);
} else if (info.descr === "<i8") {
} else if (info.descr === '<i8') {
// 8 byte int64s
data = new Uint8Array(buf, offsetBytes);
} else if (info.descr === "|s5") {
} else if (info.descr === '|s5') {
// 5 byte string
data = new Uint8Array(buf, offsetBytes);
} else if (info.descr === "|s8") {
} else if (info.descr === '|s8') {
// 8 byte strings
data = new Uint8Array(buf, offsetBytes);
} else if (info.descr === "|s15") {
} else if (info.descr === '|s15') {
// 15 byte strings?
data = new Uint8Array(buf, offsetBytes);
} else {
throw new Error("unknown numeric dtype " + info.descr);
throw new Error(`unknown numeric dtype ${info.descr}`);
}
return {
shape: info.shape,
fortran_order: info.fortran_order,
data: data
data
};
}
function open(file, callback) {
var reader = new FileReader();
reader.onload = function() {
const reader = new FileReader();
reader.onload = function () {
// the file contents have been read as an array buffer
var buf = reader.result;
var ndarray = fromArrayBuffer(buf);
const buf = reader.result;
const ndarray = fromArrayBuffer(buf);
callback(ndarray);
};
reader.readAsArrayBuffer(file);
}
function promise(url) {
return new Promise(function(resolve, reject) {
return new Promise((resolve, reject) => {
// Do the usual XHR stuff
var req = new XMLHttpRequest();
req.onload = function() {
const req = new XMLHttpRequest();
req.onload = function () {
// This is called even on 404 etc
// so check the status
if (req.status == 200) {
var buf = req.response; // not responseText
var ndarray = fromArrayBuffer(buf);
const buf = req.response; // not responseText
const ndarray = fromArrayBuffer(buf);
resolve(ndarray);
} else if (req.status == 404) {
console.log("yup");
console.log('yup');
reject({ is404: true });
} else {
// Otherwise reject with the status text
@ -113,22 +113,22 @@ const NumpyLoader = (function NumpyLoader() {
};
// Handle network errors
req.onerror = function() {
reject(Error("Network Error"));
req.onerror = function () {
reject(Error('Network Error'));
};
// Make the request
req.open("GET", url, true);
req.responseType = "arraybuffer";
req.open('GET', url, true);
req.responseType = 'arraybuffer';
req.send(null);
});
}
return {
open: open,
promise: promise,
fromArrayBuffer: fromArrayBuffer
open,
promise,
fromArrayBuffer
};
})();
}());
module.exports = NumpyLoader;

View File

@ -1,5 +1,5 @@
export function swapKeysAndValues(obj, f) {
return Object.keys(obj).reduce(function(acc, k) {
return Object.keys(obj).reduce((acc, k) => {
acc[obj[k]] = k;
return acc;
}, {});
@ -12,7 +12,6 @@ export function fromArray(arr) {
const pairs = arr.map(([k, v]) => ({ [k]: v }));
if (pairs.length > 0) {
return Object.assign(...pairs);
} else {
return {};
}
return {};
}

View File

@ -1,6 +1,6 @@
export function hash(str) {
var hash = 5381,
i = str.length;
let hash = 5381;
let i = str.length;
while (i) {
hash = (hash * 33) ^ str.charCodeAt(--i);

View File

@ -1,33 +1,33 @@
/* eslint-disable no-restricted-globals*/
/* eslint-disable no-restricted-globals */
export function objToQuery(obj) {
return Object.keys(obj)
.map(k => k + "=" + encodeURIComponent(decodeURIComponent(obj[k])))
.join("&");
.map((k) => `${k}=${encodeURIComponent(decodeURIComponent(obj[k]))}`)
.join('&');
}
export function getUrlParameter(name) {
var location = window.location;
name = name.replace(/[[]/, "\\[").replace(/[\]]/, "\\]");
var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
var results = regex.exec(location.search);
const { location } = window;
name = name.replace(/[[]/, '\\[').replace(/[\]]/, '\\]');
const regex = new RegExp(`[\\?&]${name}=([^&#]*)`);
const results = regex.exec(location.search);
return results === null
? null
: decodeURIComponent(results[1].replace(/\+/g, " "));
: decodeURIComponent(results[1].replace(/\+/g, ' '));
}
export function modifyQueryParameters({ add, remove = [] }) {
var regex = new RegExp("[\\?&]([^&#]+)=([^&#]*)");
var results = regex.exec(location.search);
const regex = new RegExp('[\\?&]([^&#]+)=([^&#]*)');
const results = regex.exec(location.search);
let params = {};
if (results != null) {
for (let i = 1; i < results.length - 1; i += 2) {
let key = results[i],
value = results[i + 1];
const key = results[i];
const value = results[i + 1];
params[key] = value;
}
for (let key in params) {
for (const key in params) {
if (remove.indexOf(key) !== -1) {
delete params[key];
}
@ -37,5 +37,5 @@ export function modifyQueryParameters({ add, remove = [] }) {
params = add;
}
return location.origin + location.pathname + "?" + objToQuery(params);
return `${location.origin + location.pathname}?${objToQuery(params)}`;
}

View File

@ -1,111 +1,121 @@
import { createClassFromSpec } from "react-vega";
import { createClassFromSpec } from 'react-vega';
const canHistogramSpec = {
$schema: "https://vega.github.io/schema/vega/v3.0.json",
$schema: 'https://vega.github.io/schema/vega/v3.0.json',
width: 1000,
height: 100,
padding: 5,
signals: [
{
name: "segment"
name: 'segment'
}
],
data: [
{
name: "binned"
name: 'binned'
}
],
scales: [
{
name: "xscale",
type: "linear",
name: 'xscale',
type: 'linear',
zero: false,
range: "width",
domain: { data: "binned", field: "startTime" }
range: 'width',
domain: { data: 'binned', field: 'startTime' }
},
{
name: "xrelscale",
type: "linear",
name: 'xrelscale',
type: 'linear',
zero: false,
range: "width",
domain: { data: "binned", field: "relStartTime" }
range: 'width',
domain: { data: 'binned', field: 'relStartTime' }
},
{
name: "yscale",
type: "linear",
range: "height",
name: 'yscale',
type: 'linear',
range: 'height',
round: true,
domain: { data: "binned", field: "count" },
domain: { data: 'binned', field: 'count' },
zero: true,
nice: true
}
],
axes: [
{ orient: "bottom", scale: "xrelscale", zindex: 1, tickCount: 10 },
{ orient: "left", scale: "yscale", tickCount: 5, zindex: 1 }
{
orient: 'bottom',
scale: 'xrelscale',
zindex: 1,
tickCount: 10
},
{
orient: 'left',
scale: 'yscale',
tickCount: 5,
zindex: 1
}
],
marks: [
{
type: "group",
name: "histogram",
type: 'group',
name: 'histogram',
interactive: true,
encode: {
enter: {
height: { value: 75 },
width: { value: 1000 },
fill: { value: "transparent" }
fill: { value: 'transparent' }
}
},
signals: [
{
name: "brush",
name: 'brush',
value: 0,
on: [
{
events: "@bins:mousedown",
update: "[x(), x()]"
events: '@bins:mousedown',
update: '[x(), x()]'
},
{
events: "[@bins:mousedown, window:mouseup] > window:mousemove!",
update: "[brush[0], clamp(x(), 0, width)]"
events: '[@bins:mousedown, window:mouseup] > window:mousemove!',
update: '[brush[0], clamp(x(), 0, width)]'
},
{
events: { signal: "delta" },
events: { signal: 'delta' },
update:
"clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)"
'clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)'
}
]
},
{
name: "anchor",
name: 'anchor',
value: null,
on: [{ events: "@brush:mousedown", update: "slice(brush)" }]
on: [{ events: '@brush:mousedown', update: 'slice(brush)' }]
},
{
name: "xdown",
name: 'xdown',
value: 0,
on: [{ events: "@brush:mousedown", update: "x()" }]
on: [{ events: '@brush:mousedown', update: 'x()' }]
},
{
name: "delta",
name: 'delta',
value: 0,
on: [
{
events: "[@brush:mousedown, window:mouseup] > window:mousemove!",
update: "x() - xdown"
events: '[@brush:mousedown, window:mouseup] > window:mousemove!',
update: 'x() - xdown'
}
]
},
{
name: "segment",
push: "outer",
name: 'segment',
push: 'outer',
on: [
{
events: { signal: "brush" },
events: { signal: 'brush' },
update: "span(brush) ? invert('xscale', brush) : null"
}
]
@ -113,72 +123,72 @@ const canHistogramSpec = {
],
marks: [
{
type: "rect",
type: 'rect',
interactive: true,
from: { data: "binned" },
name: "bins",
from: { data: 'binned' },
name: 'bins',
encode: {
update: {
x: { scale: "xscale", field: "startTime" },
x: { scale: 'xscale', field: 'startTime' },
x2: {
scale: "xscale",
field: "endTime",
scale: 'xscale',
field: 'endTime',
offset: 0
},
y: { scale: "yscale", field: "count" },
y2: { scale: "yscale", value: 0 },
fill: { value: "steelblue" }
y: { scale: 'yscale', field: 'count' },
y2: { scale: 'yscale', value: 0 },
fill: { value: 'steelblue' }
},
hover: {
fill: { value: "goldenrod" },
cursor: { value: "ew-resize" }
fill: { value: 'goldenrod' },
cursor: { value: 'ew-resize' }
}
}
},
{
type: "rect",
type: 'rect',
interactive: true,
name: "brush",
name: 'brush',
encode: {
enter: {
y: { value: 0 },
height: { value: 100 },
fill: { value: "#333" },
fill: { value: '#333' },
fillOpacity: { value: 0.2 }
},
update: {
x: { signal: "brush[0]" },
x2: { signal: "brush[1]" }
x: { signal: 'brush[0]' },
x2: { signal: 'brush[1]' }
}
}
},
{
type: "rect",
type: 'rect',
interactive: false,
encode: {
enter: {
y: { value: 0 },
height: { value: 100 },
width: { value: 2 },
fill: { value: "firebrick" }
fill: { value: 'firebrick' }
},
update: {
x: { signal: "brush[0]" }
x: { signal: 'brush[0]' }
}
}
},
{
type: "rect",
type: 'rect',
interactive: false,
encode: {
enter: {
y: { value: 0 },
height: { value: 100 },
width: { value: 2 },
fill: { value: "firebrick" }
fill: { value: 'firebrick' }
},
update: {
x: { signal: "brush[1]" }
x: { signal: 'brush[1]' }
}
}
}

View File

@ -1,5 +1,5 @@
export default {
$schema: "https://vega.github.io/schema/vega/v5.6.json",
$schema: 'https://vega.github.io/schema/vega/v5.6.json',
width: 400,
height: 200,
padding: {
@ -10,166 +10,166 @@ export default {
},
signals: [
{
name: "tipTime",
name: 'tipTime',
on: [
{
events: "mousemove",
events: 'mousemove',
update: "invert('xrelscale', x())"
}
]
},
{
name: "clickTime",
name: 'clickTime',
on: [
{
events: "click",
events: 'click',
update: "invert('xrelscale', x())"
}
]
},
{ name: "videoTime" },
{ name: 'videoTime' },
{
name: "segment",
value: { data: "table", field: "relTime" }
name: 'segment',
value: { data: 'table', field: 'relTime' }
}
],
data: [
{
name: "table"
name: 'table'
},
{
name: "segment"
name: 'segment'
},
{
name: "tooltip",
source: "table",
name: 'tooltip',
source: 'table',
transform: [
{
type: "filter",
expr: "abs(datum.relTime - tipTime) <= 0.01"
type: 'filter',
expr: 'abs(datum.relTime - tipTime) <= 0.01'
},
{
type: "aggregate",
fields: ["relTime", "y", "unit"],
ops: ["min", "argmin", "argmin"],
as: ["min", "argmin", "argmin"]
type: 'aggregate',
fields: ['relTime', 'y', 'unit'],
ops: ['min', 'argmin', 'argmin'],
as: ['min', 'argmin', 'argmin']
}
]
},
{
name: "ySegmentScale",
source: "table",
name: 'ySegmentScale',
source: 'table',
transform: [
{
type: "filter",
type: 'filter',
expr:
"length(segment) != 2 || (datum.relTime >= segment[0] && datum.relTime <= segment[1])"
'length(segment) != 2 || (datum.relTime >= segment[0] && datum.relTime <= segment[1])'
},
{ type: "extent", field: "y", signal: "ySegment" }
{ type: 'extent', field: 'y', signal: 'ySegment' }
]
}
],
scales: [
{
name: "xscale",
type: "linear",
range: "width",
domain: { data: "table", field: "x" },
name: 'xscale',
type: 'linear',
range: 'width',
domain: { data: 'table', field: 'x' },
zero: false
},
{
name: "xrelscale",
type: "linear",
range: "width",
domain: { data: "table", field: "relTime" },
name: 'xrelscale',
type: 'linear',
range: 'width',
domain: { data: 'table', field: 'relTime' },
zero: false,
clamp: true,
domainRaw: { signal: "segment" }
domainRaw: { signal: 'segment' }
},
{
name: "yscale",
type: "linear",
range: "height",
name: 'yscale',
type: 'linear',
range: 'height',
clamp: true,
zero: false,
domain: { signal: "ySegment" }
domain: { signal: 'ySegment' }
},
{
name: "color",
type: "ordinal",
domain: { data: "table", field: "color" },
range: { data: "table", field: "color" }
name: 'color',
type: 'ordinal',
domain: { data: 'table', field: 'color' },
range: { data: 'table', field: 'color' }
}
],
axes: [
{ orient: "bottom", scale: "xrelscale", labelOverlap: true },
{ orient: "left", scale: "yscale" }
{ orient: 'bottom', scale: 'xrelscale', labelOverlap: true },
{ orient: 'left', scale: 'yscale' }
],
marks: [
{
type: "group",
name: "plot",
type: 'group',
name: 'plot',
interactive: true,
encode: {
enter: {
width: { signal: "width" },
height: { signal: "height" },
fill: { value: "transparent" }
width: { signal: 'width' },
height: { signal: 'height' },
fill: { value: 'transparent' }
}
},
signals: [
{
name: "brush",
name: 'brush',
value: 0,
on: [
{
events: "@boundingRect:mousedown",
update: "[x(), x()]"
events: '@boundingRect:mousedown',
update: '[x(), x()]'
},
{
events:
"[@boundingRect:mousedown, window:mouseup] > window:mousemove!",
update: "[brush[0], clamp(x(), 0, width)]"
'[@boundingRect:mousedown, window:mouseup] > window:mousemove!',
update: '[brush[0], clamp(x(), 0, width)]'
},
{
events: { signal: "delta" },
events: { signal: 'delta' },
update:
"clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)"
'clampRange([anchor[0] + delta, anchor[1] + delta], 0, width)'
}
]
},
{
name: "anchor",
name: 'anchor',
value: null,
on: [{ events: "@brush:mousedown", update: "slice(brush)" }]
on: [{ events: '@brush:mousedown', update: 'slice(brush)' }]
},
{
name: "xdown",
name: 'xdown',
value: 0,
on: [{ events: "@brush:mousedown", update: "x()" }]
on: [{ events: '@brush:mousedown', update: 'x()' }]
},
{
name: "xup",
name: 'xup',
value: 0,
on: [{ events: "@brush:mouseup", update: "x()" }]
on: [{ events: '@brush:mouseup', update: 'x()' }]
},
{
name: "delta",
name: 'delta',
value: 0,
on: [
{
events: "[@brush:mousedown, window:mouseup] > window:mousemove!",
update: "x() - xdown"
events: '[@brush:mousedown, window:mouseup] > window:mousemove!',
update: 'x() - xdown'
}
]
},
{
name: "segment",
push: "outer",
name: 'segment',
push: 'outer',
on: [
{
events: "window:mouseup",
events: 'window:mouseup',
update:
"span(brush) && span(brush) > 15 ? invert('xrelscale', brush) : segment"
}
@ -178,50 +178,50 @@ export default {
],
marks: [
{
type: "group",
type: 'group',
from: {
facet: {
name: "series",
data: "table",
groupby: "signalUid"
name: 'series',
data: 'table',
groupby: 'signalUid'
}
},
marks: {
type: "line",
name: "lineMark",
from: { data: "series" },
type: 'line',
name: 'lineMark',
from: { data: 'series' },
interactive: true,
encode: {
update: {
interpolate: { value: "step" },
x: { scale: "xrelscale", field: "relTime" },
y: { scale: "yscale", field: "y" }
interpolate: { value: 'step' },
x: { scale: 'xrelscale', field: 'relTime' },
y: { scale: 'yscale', field: 'y' }
},
hover: {
fillOpacity: { value: 0.5 }
},
enter: {
clip: { value: true },
stroke: { scale: "color", field: "color" },
stroke: { scale: 'color', field: 'color' },
strokeWidth: { value: 2 }
}
}
}
},
{
type: "rect",
type: 'rect',
interactive: true,
name: "brush",
name: 'brush',
encode: {
enter: {
y: { value: 0 },
height: { signal: "height" },
fill: { value: "#333" },
height: { signal: 'height' },
fill: { value: '#333' },
fillOpacity: { value: 0.2 }
},
update: {
x: { signal: "brush[0]" },
x2: { signal: "brush[1]" }
x: { signal: 'brush[0]' },
x2: { signal: 'brush[1]' }
}
}
},
@ -256,61 +256,61 @@ export default {
// }
// },
{
type: "rule",
type: 'rule',
encode: {
update: {
y: { value: 0 },
y2: { field: { group: "height" } },
stroke: { value: "#000" },
y2: { field: { group: 'height' } },
stroke: { value: '#000' },
strokeWidth: { value: 2 },
x: {
scale: "xrelscale",
signal: "videoTime",
scale: 'xrelscale',
signal: 'videoTime',
offset: 0.5
}
}
}
},
{
type: "symbol",
from: { data: "tooltip" },
type: 'symbol',
from: { data: 'tooltip' },
encode: {
update: {
x: { scale: "xrelscale", field: "argmin.relTime" },
y: { scale: "yscale", field: "argmin.y" },
x: { scale: 'xrelscale', field: 'argmin.relTime' },
y: { scale: 'yscale', field: 'argmin.y' },
size: { value: 50 },
fill: { value: "black" }
fill: { value: 'black' }
}
}
},
{
type: "group",
from: { data: "tooltip" },
type: 'group',
from: { data: 'tooltip' },
interactive: false,
name: "tooltipGroup",
name: 'tooltipGroup',
encode: {
update: {
x: [
{
test:
"inrange(datum.argmin.relTime + 80, domain('xrelscale'))",
scale: "xrelscale",
field: "argmin.relTime"
scale: 'xrelscale',
field: 'argmin.relTime'
},
{ scale: "xrelscale", field: "argmin.relTime", offset: -80 }
{ scale: 'xrelscale', field: 'argmin.relTime', offset: -80 }
],
y: { scale: "yscale", field: "argmin.y" },
y: { scale: 'yscale', field: 'argmin.y' },
height: { value: 20 },
width: { value: 80 },
fill: { value: "#fff" },
fill: { value: '#fff' },
fillOpacity: { value: 0.85 },
stroke: { value: "#aaa" },
stroke: { value: '#aaa' },
strokeWidth: { value: 0.5 }
}
},
marks: [
{
type: "text",
type: 'text',
interactive: false,
encode: {
update: {
@ -318,8 +318,8 @@ export default {
signal:
"format(parent.argmin.relTime, ',.2f') + ': ' + format(parent.argmin.y, ',.2f') + ' ' + parent.argmin.unit"
},
fill: { value: "black" },
fontWeight: { value: "bold" },
fill: { value: 'black' },
fontWeight: { value: 'bold' },
y: { value: 20 }
}
}
@ -327,14 +327,14 @@ export default {
]
},
{
type: "rect",
name: "boundingRect",
type: 'rect',
name: 'boundingRect',
interactive: true,
encode: {
enter: {
width: { signal: "width" },
height: { signal: "height" },
fill: { value: "transparent" }
width: { signal: 'width' },
height: { signal: 'height' },
fill: { value: 'transparent' }
}
}
}

View File

@ -1,8 +1,8 @@
/* eslint-env worker */
/* eslint-disable no-restricted-globals */
import DBC from "../models/can/dbc";
import DbcUtils from "../utils/dbc";
import extend from "xtend";
import extend from 'xtend';
import DBC from '../models/can/dbc';
import DbcUtils from '../utils/dbc';
function processStreamedCanMessages(
newCanMessages,
@ -21,17 +21,19 @@ function processStreamedCanMessages(
canMessages = canMessages.sort((msg1, msg2) => {
if (msg1[1] < msg2[1]) {
return -1;
} else if (msg1[1] > msg2[1]) {
return 1;
} else {
return 0;
}
if (msg1[1] > msg2[1]) {
return 1;
}
return 0;
});
let busTimeSum = 0;
for (let i = 0; i < canMessages.length; i++) {
let { address, busTime, data, bus } = canMessages[i];
const {
address, busTime, data, bus
} = canMessages[i];
let prevBusTime;
if (i === 0) {
@ -78,7 +80,7 @@ function processStreamedCanMessages(
maxByteStateChangeCount = newMaxByteStateChangeCount;
}
Object.keys(messages).forEach(key => {
Object.keys(messages).forEach((key) => {
messages[key] = DbcUtils.setMessageByteColors(
messages[key],
maxByteStateChangeCount
@ -95,7 +97,7 @@ function processStreamedCanMessages(
});
}
self.onmessage = function(e) {
self.onmessage = function (e) {
const {
newCanMessages,
prevMsgEntries,

View File

@ -2,19 +2,19 @@
/* eslint-disable no-restricted-globals */
// import Sentry from '../logging/Sentry';
import NumpyLoader from "../utils/loadnpy";
import NumpyLoader from '../utils/loadnpy';
const MAX_CONNECTIONS = 8;
var window = self;
const window = self;
const Int64LE = require("int64-buffer").Int64LE;
const { Int64LE } = require('int64-buffer');
function transformAndSend(rawData) {
var totalSize = 0;
var maxTime = rawData.reduce(function(memo, sourceData) {
let totalSize = 0;
const maxTime = rawData.reduce((memo, sourceData) => {
totalSize += sourceData.entries.length;
sourceData.entries = sourceData.entries.sort(function(a, b) {
sourceData.entries = sourceData.entries.sort((a, b) => {
if (a.relTime > b.relTime) {
return 1;
}
@ -26,14 +26,14 @@ function transformAndSend(rawData) {
return Math.max(memo, getLastTimeFromEntries(sourceData.entries));
}, 0);
var minTime = Math.max(0, maxTime - 30);
console.log("Time span from", minTime, maxTime);
var curIndexes = {};
rawData.forEach(function(sourceData) {
const minTime = Math.max(0, maxTime - 30);
console.log('Time span from', minTime, maxTime);
const curIndexes = {};
rawData.forEach((sourceData) => {
if (!sourceData.entries.length) {
return;
}
var sourceId = sourceData.id;
const sourceId = sourceData.id;
if (minTime === 0 || sourceData.entries[0].relTime > minTime) {
curIndexes[sourceId] = 0;
return;
@ -41,12 +41,12 @@ function transformAndSend(rawData) {
curIndexes[sourceId] = findFirstEntryIndex(sourceData.entries, minTime);
});
var entryBuffer = [];
var totalEntries = 0;
let entryBuffer = [];
let totalEntries = 0;
while (!isAtEnd()) {
let nextSource = rawData.reduce(function(memo, sourceData) {
let curEntry = sourceData.entries[curIndexes[sourceData.id]];
const nextSource = rawData.reduce((memo, sourceData) => {
const curEntry = sourceData.entries[curIndexes[sourceData.id]];
if (!curEntry) {
return memo;
}
@ -79,7 +79,7 @@ function transformAndSend(rawData) {
if (entryBuffer.length > 5000) {
self.postMessage({
progress: 100 * (totalEntries / totalSize),
logData: entryBuffer.join("\n"),
logData: entryBuffer.join('\n'),
shouldClose: false
});
entryBuffer = [];
@ -88,13 +88,13 @@ function transformAndSend(rawData) {
if (entryBuffer.length > 0) {
self.postMessage({
progress: 99,
logData: entryBuffer.join("\n"),
logData: entryBuffer.join('\n'),
shouldClose: false
});
entryBuffer = [];
}
console.log("Wrote", totalEntries, "lines of CSV");
console.log('Wrote', totalEntries, 'lines of CSV');
self.postMessage({
progress: 100,
shouldClose: true
@ -102,8 +102,7 @@ function transformAndSend(rawData) {
function isAtEnd() {
return rawData.reduce(
(memo, sourceData) =>
memo && curIndexes[sourceData.id] >= sourceData.entries.length
(memo, sourceData) => memo && curIndexes[sourceData.id] >= sourceData.entries.length
);
}
}
@ -114,7 +113,7 @@ function makeEntry(nextSource) {
nextSource.address,
nextSource.bus,
nextSource.entry.hexData
].join(",");
].join(',');
}
function findFirstEntryIndex(entries, minTime, start, length) {
@ -160,11 +159,11 @@ function getLastTimeFromEntries(entries) {
return entries[entries.length - 1].relTime;
}
self.onmessage = function(e) {
console.log("onmessage worker");
self.onmessage = function (e) {
console.log('onmessage worker');
self.postMessage({
progress: 0,
logData: "time,addr,bus,data",
logData: 'time,addr,bus,data',
shouldClose: false
});
const {
@ -180,7 +179,7 @@ self.onmessage = function(e) {
// saveDBC(dbc, base, num, canStartTime);
if (data) {
// has raw data from live mode, process this instead
console.log("Using raw data from memory", canStartTime);
console.log('Using raw data from memory', canStartTime);
transformAndSend(data, canStartTime);
} else {
self.postMessage({

Some files were not shown because too many files have changed in this diff Show More