diff --git a/app/actions/eon_detail_actions.js b/app/actions/eon_detail_actions.js index 7b22368..fd4d015 100644 --- a/app/actions/eon_detail_actions.js +++ b/app/actions/eon_detail_actions.js @@ -89,14 +89,33 @@ export function RESPONSE_tmuxPipe(lines, state) { regexKeys = Object.keys(regex); regexKeys.forEach((key) => { - // console.log(key); - if ((m = regex[key].exec(lines)) !== null) { - // console.log(m); - if (key === 'PROCESS') { - payload[m[1]] = m[3]; - } else if (key === 'VEHICLE_CONNECTION') { - payload.vehicleConnection = m[0]; - } + switch (key) { + case "THERMAL": + // console.warn("Parsing:",key); + while ((m = regex[key].exec(lines)) !== null) { + if (m.index === regex.lastIndex) { + regex.lastIndex++; + } + // console.warn(m[1],m[2]); + payload[m[1]] = m[2].replace(/\"/g,''); + } + break; + case "PROCESS": + // console.warn("Parsing:",key); + while ((m = regex[key].exec(lines)) !== null) { + if (m.index === regex.lastIndex) { + regex.lastIndex++; + } + // console.warn(m[1],m[3]); + payload[m[1]] = m[3].replace(/\"/g,''); + } + break; + case "VEHICLE_CONNECTION": + // console.warn("Parsing:",key); + if ((m = regex[key].exec(lines)) !== null) { + payload.vehicleConnection = m[0]; + } + break; } }); diff --git a/app/components/EonDetail/Styles.css b/app/components/EonDetail/Styles.scss similarity index 59% rename from app/components/EonDetail/Styles.css rename to app/components/EonDetail/Styles.scss index 7ac617b..19c2b57 100644 --- a/app/components/EonDetail/Styles.css +++ b/app/components/EonDetail/Styles.scss @@ -1,5 +1,7 @@ .eon_bar { position:relative; + margin-top:40px; + margin-bottom:30px; } .loading_overlay { position:absolute; @@ -12,8 +14,8 @@ position:absolute; top:50%; left:50%; - height:75px; - width:75px; + height:85px; + width:85px; transform:translate(-50%,-50%); /* width:100%; @@ -24,32 +26,59 @@ .add_field { border:0; } +.title,.subtext,.subsubtext { + text-align:center; + margin: 0; +} .title { font-weight:400; - text-align:center; } .subtext { font-weight:200; - text-align:center; } .disconnect_button { margin-top:10px; margin-bottom:10px; + position:absolute; + top:0; + left:0; + width:200px; } .subsubtext { font-weight:200; - text-align:center; font-weight:200; color:#555; } +.connection { + background-color:rgba(#FFF,0.2); + padding:10px; + border-radius:100px; + width:50%; + margin:0 auto; + + span { + display:block; + text-align:center; + } + + .connection_message { + font-size:18px; + font-weight:200; + line-height:20px; + } + .connection_label { + font-size:10px; + line-height:15px; + } +} .state_list { display:table; width:100%; } .state_spinner { - height: 20px; - width: 20px; + height: 100%; + width: 100%; } .state_spinner img { width:100%; @@ -58,6 +87,12 @@ .state_item { display:table-row; } +.state_loading_icon_wrap { + width: 16px; + height: 16px; + position: relative; + display: block; +} .state_label,.state_status { display:table-cell; @@ -74,6 +109,6 @@ .state_status { /* color:#28a745; */ } -.state_status.started { +.state_status_started { color:#28a745; } \ No newline at end of file diff --git a/app/components/EonDetail/index.js b/app/components/EonDetail/index.js index b9c17ae..29d0072 100644 --- a/app/components/EonDetail/index.js +++ b/app/components/EonDetail/index.js @@ -2,12 +2,15 @@ import React, { Component } from 'react'; import { Link } from 'react-router-dom'; const app = require('electron').remote.app import routes from '../../constants/routes.json'; -import styles from './Styles.css'; +import styles from './Styles.scss'; import PropTypes from 'prop-types'; import processInfo from '../../constants/processes.json'; +import thermalInfo from '../../constants/thermal.json'; +import vehicleConnectionStatuses from '../../constants/vehicle_connection_statuses.json'; import Layout from '../Layout'; import LoadingIndicator from '../LoadingIndicator'; import ConnectedTime from './ConnectedTime'; +import ReactResizeDetector from 'react-resize-detector'; const propTypes = { install: PropTypes.func, @@ -28,11 +31,35 @@ const propTypes = { logmessaged: PropTypes.string, controlsd: PropTypes.string, gpsd: PropTypes.string, - vehicleConnection: PropTypes.string + vehicleConnection: PropTypes.string, + logMonoTime: PropTypes.string, + thermal: PropTypes.string, + cpu0: PropTypes.string, + cpu1: PropTypes.string, + cpu2: PropTypes.string, + cpu3: PropTypes.string, + mem: PropTypes.string, + gpu: PropTypes.string, + bat: PropTypes.string, + freeSpace: PropTypes.string, + batteryPercent: PropTypes.string, + batteryStatus: PropTypes.string, + fanSpeed: PropTypes.string, + started: PropTypes.string, + usbOnline: PropTypes.string, + startedTs: PropTypes.string, + thermalStatus: PropTypes.string, + batteryCurrent: PropTypes.string, + batteryVoltage: PropTypes.string }; class EonDetail extends Component { - + constructor(props) { + super(props); + this.state = { + processesAndThermalsHeight: 0 + } + } componentDidMount() { if (this.props.eon && this.props.pipeTmux) { this.props.pipeTmux(); @@ -41,7 +68,7 @@ class EonDetail extends Component { this.tmuxTimeout = setTimeout(() => { if (!this.props.tmuxAttached) { console.warn("Could not connect to tmux..."); - this.props.history.push(routes.EON_DETAIL); + this.props.history.push(routes.EON_LIST); } }, 3000); @@ -56,12 +83,45 @@ class EonDetail extends Component { // console.warn(this); this.props.install(); } + onResize = (width,height) => { + console.log("width:",width); + console.log("height:",height); + let newHeight = height-400; + console.log("thermalsHeight:",newHeight); + this.setState({ + processesAndThermalsHeight: newHeight + }); + } render() { - const processKeys = Object.keys(processInfo); + const vehicleConnection = vehicleConnectionStatuses[this.props.vehicleConnection] || { + "label": "Checking vehicle status..." + }; + const processKeys = Object.keys(processInfo).sort(); + const thermalKeys = Object.keys(thermalInfo).sort(); if (!this.props.tmuxAttached) { return ; } + // THERMAL ITEMS + const thermals = thermalKeys.map((key) => { + let thermalDetails = thermalInfo[key]; + let thermalStatus = this.props[key]; + let thermalImg = thermalInfo['iconImg']; + let thermalIcon = thermalInfo['iconClassName']; + return ( +
+ {thermalDetails.label} + + {!thermalStatus && + + + + } + {thermalStatus} + +
+ ) + }); // PROCESS ITEMS const processes = processKeys.map((key) => { let processDetails = processInfo[key]; @@ -75,7 +135,9 @@ class EonDetail extends Component { } {(processStatus !== 'started') && - + + + } @@ -86,32 +148,44 @@ class EonDetail extends Component {
{this.props.eon && -
- -

- Connected to EON -

-
- {this.props.eon.ip} -
-
- {this.props.eon.mac} - +
+
+
+ +

+ Connected to EON +

+
+ {this.props.eon.ip} +
+
+ {this.props.eon.mac} +
+
+ {vehicleConnection.label} +
+ + Disconnect + +
- - Disconnect -
} -
-
- Vehicle Connection - {this.props.vehicleConnection} +
+
+
+ {processes} +
+
+
+
+ {thermals} +
- {processes}
+ ); } diff --git a/app/components/Layout/Styles.css b/app/components/Layout/Styles.scss similarity index 90% rename from app/components/Layout/Styles.css rename to app/components/Layout/Styles.scss index 13d133b..6d95e51 100644 --- a/app/components/Layout/Styles.css +++ b/app/components/Layout/Styles.scss @@ -1,6 +1,7 @@ .container { position: relative; width:100%; + height:100%; /* top: 0; left: 0; height:100%; */ @@ -9,8 +10,8 @@ .app_wrapper { padding-top:0; + } - .header { display:flex; position:relative; @@ -20,12 +21,13 @@ .header .brand { flex: 0 0 50%; - padding: 30px 0 19px 0; + padding: 60px 0 19px 0; margin: 0 auto; + transform:translateX(-6px); text-align: center; } .header .brand svg { - transform: scale(1.2); + transform: scale(1.4); } .header .eon_status { flex: 0 0 50%; diff --git a/app/components/Layout/index.js b/app/components/Layout/index.js index 1f8d628..6b26108 100644 --- a/app/components/Layout/index.js +++ b/app/components/Layout/index.js @@ -1,8 +1,8 @@ import React, { Component } from 'react'; import { bindActionCreators } from 'redux'; import { connect } from 'react-redux'; -import Logo from "./images/logo.svg"; -import styles from './Styles.css'; +import Logo from "../../images/logo.svg"; +import styles from './Styles.scss'; import * as eonListActions from '../../actions/eon_list_actions'; import PropTypes from 'prop-types'; import { Link } from 'react-router-dom'; @@ -18,11 +18,13 @@ class Layout extends React.PureComponent { render() { const { backBtn, hideLogo, selectedEon } = this.props; return ( -
+
+ {!hideLogo &&
- {!hideLogo && } +
+ }
{this.props.children} diff --git a/app/components/LoadingIndicator/Circle.js b/app/components/LoadingIndicator/Circle.js deleted file mode 100644 index 6f6a3d4..0000000 --- a/app/components/LoadingIndicator/Circle.js +++ /dev/null @@ -1,8 +0,0 @@ -import React from 'react'; -import spinnerImage from './images/img_spinner_track.png'; -import styles from './Styles.css'; -const Circle = () => ( - -); - -export default Circle; diff --git a/app/components/LoadingIndicator/IndicatorIcon.js b/app/components/LoadingIndicator/IndicatorIcon.js new file mode 100644 index 0000000..610796c --- /dev/null +++ b/app/components/LoadingIndicator/IndicatorIcon.js @@ -0,0 +1,14 @@ +import React, { Component } from 'react'; +import spinnerImage from '../../images/img_spinner_track@0.2x.png'; +import styles from './Styles.scss'; +class IndicatorIcon extends Component { + render() { + if (this.props.icon) { + return ; + } else { + return ; + } + } +} + +export default IndicatorIcon; diff --git a/app/components/LoadingIndicator/Styles.css b/app/components/LoadingIndicator/Styles.scss similarity index 88% rename from app/components/LoadingIndicator/Styles.css rename to app/components/LoadingIndicator/Styles.scss index 21abe72..1acd27b 100644 --- a/app/components/LoadingIndicator/Styles.css +++ b/app/components/LoadingIndicator/Styles.scss @@ -18,14 +18,16 @@ /* margin:25px auto; */ } .circle { - width: 75px; - height: 75px; - position: relative; + width: 100%; + height: 100%; + position: absolute; z-index: 10001; + top:0; + left:0; display: block; margin: 0 auto; background-size: 100% 100%; background-position: center center; background-repeat: no-repeat; animation: spinner 0.8s infinite linear; -} \ No newline at end of file +} diff --git a/app/components/LoadingIndicator/images/img_spinner_track.png b/app/components/LoadingIndicator/images/img_spinner_track.png deleted file mode 100644 index 931c17e..0000000 Binary files a/app/components/LoadingIndicator/images/img_spinner_track.png and /dev/null differ diff --git a/app/components/LoadingIndicator/index.js b/app/components/LoadingIndicator/index.js index 586ba51..b0f05fd 100644 --- a/app/components/LoadingIndicator/index.js +++ b/app/components/LoadingIndicator/index.js @@ -1,11 +1,10 @@ import React, { Component } from 'react'; -import Circle from './Circle'; -import styles from './Styles.css'; +import IndicatorIcon from './IndicatorIcon'; class LoadingIndicator extends Component { render() { return (
- +
) } } diff --git a/app/constants/thermal.json b/app/constants/thermal.json new file mode 100644 index 0000000..678551d --- /dev/null +++ b/app/constants/thermal.json @@ -0,0 +1,110 @@ +{ + "logMonoTime": { + "label": "Log Mono Time", + "description": "Stat for logMonoTime", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "cpu0": { + "label": "CPU #1", + "description": "Stat for cpu1", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "cpu1": { + "label": "CPU #2", + "description": "Stat for cpu2", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "cpu2": { + "label": "CPU #3", + "description": "Stat for cpu3", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "cpu3": { + "label": "CPU #4", + "description": "Stat for cpu4", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "mem": { + "label": "Memory", + "description": "Stat for mem", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "gpu": { + "label": "GPU", + "description": "Stat for gpu", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "bat": { + "label": "Battery", + "description": "Stat for bat", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "freeSpace": { + "label": "Free Space", + "description": "Stat for freeSpace", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "batteryPercent": { + "label": "Battery %", + "description": "Stat for batteryPercent", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "batteryStatus": { + "label": "Battery Status", + "description": "Stat for batteryStatus", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "fanSpeed": { + "label": "Fan Speed", + "description": "Stat for fanSpeed", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "started": { + "label": "Started", + "description": "Stat for started", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "usbOnline": { + "label": "USB Online", + "description": "Stat for usbOnline", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "startedTs": { + "label": "Started TS", + "description": "Stat for startedTs", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "thermalStatus": { + "label": "Thermal Status", + "description": "Stat for thermalStatus", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "batteryCurrent": { + "label": "Battery Current", + "description": "Stat for batteryCurrent", + "iconImg": "", + "iconClassName": "fa fa-info" + }, + "batteryVoltage": { + "label": "Battery Voltage", + "description": "Stat for batteryVoltage", + "iconImg": "", + "iconClassName": "fa fa-info" + } +} \ No newline at end of file diff --git a/app/constants/tmux_regex.js b/app/constants/tmux_regex.js index c9ff901..6e9bca5 100644 --- a/app/constants/tmux_regex.js +++ b/app/constants/tmux_regex.js @@ -1,2 +1,3 @@ -export const PROCESS = /running\ ([A-Za-z]+)\ \/gmi; -export const VEHICLE_CONNECTION = /(waiting for board\.\.\.|waiting for fingerprint\.\.\.)/gmi; \ No newline at end of file +export const PROCESS = /running\ ([A-Za-z]+)\ \/gi; +export const VEHICLE_CONNECTION = /(waiting for board\.\.\.|waiting for fingerprint\.\.\.)/gi; +export const THERMAL = /(logMonoTime|thermal|cpu0|batteryStatus|cpu1|cpu2|cpu3|mem|gpu|bat|freeSpace|batteryPercent|batteryStatus|fanSpeed|started|usbOnline|startedTs|thermalStatus|batteryCurrent|batteryVoltage)\s\=\s([a-z0-9A-Z\"\.]+)/gmi \ No newline at end of file diff --git a/app/constants/vehicle_connection_statuses.json b/app/constants/vehicle_connection_statuses.json index ad15471..767d1f6 100644 --- a/app/constants/vehicle_connection_statuses.json +++ b/app/constants/vehicle_connection_statuses.json @@ -1,3 +1,6 @@ -[ - "waiting for board..." -] \ No newline at end of file +{ + "waiting for board...": { + "label": "Vehicle not connected.", + "description": "Connect to panda for vehicle functions." + } +} \ No newline at end of file diff --git a/app/containers/EonDetailPage.js b/app/containers/EonDetailPage.js index be0762f..da4f638 100644 --- a/app/containers/EonDetailPage.js +++ b/app/containers/EonDetailPage.js @@ -23,7 +23,26 @@ function mapStateToProps(state) { logmessaged: state.eonDetail.logmessaged, controlsd: state.eonDetail.controlsd, gpsd: state.eonDetail.gpsd, - vehicleConnection: state.eonDetail.vehicleConnection + vehicleConnection: state.eonDetail.vehicleConnection, + logMonoTime: state.eonDetail.logMonoTime, + thermal: state.eonDetail.thermal, + cpu0: state.eonDetail.cpu0, + cpu1: state.eonDetail.cpu1, + cpu2: state.eonDetail.cpu2, + cpu3: state.eonDetail.cpu3, + mem: state.eonDetail.mem, + gpu: state.eonDetail.gpu, + bat: state.eonDetail.bat, + freeSpace: state.eonDetail.freeSpace, + batteryPercent: state.eonDetail.batteryPercent, + batteryStatus: state.eonDetail.batteryStatus, + fanSpeed: state.eonDetail.fanSpeed, + started: state.eonDetail.started, + usbOnline: state.eonDetail.usbOnline, + startedTs: state.eonDetail.startedTs, + thermalStatus: state.eonDetail.thermalStatus, + batteryCurrent: state.eonDetail.batteryCurrent, + batteryVoltage: state.eonDetail.batteryVoltage }; } diff --git a/app/images/img_spinner_track.png b/app/images/img_spinner_track.png new file mode 100644 index 0000000..84cbbe0 Binary files /dev/null and b/app/images/img_spinner_track.png differ diff --git a/app/images/img_spinner_track@0.2x.png b/app/images/img_spinner_track@0.2x.png new file mode 100644 index 0000000..962652c Binary files /dev/null and b/app/images/img_spinner_track@0.2x.png differ diff --git a/app/images/img_spinner_track@0.5x.png b/app/images/img_spinner_track@0.5x.png new file mode 100644 index 0000000..daf03ac Binary files /dev/null and b/app/images/img_spinner_track@0.5x.png differ diff --git a/app/images/img_spinner_track@0.75x.png b/app/images/img_spinner_track@0.75x.png new file mode 100644 index 0000000..ffa667e Binary files /dev/null and b/app/images/img_spinner_track@0.75x.png differ diff --git a/app/components/Layout/images/logo.svg b/app/images/logo.svg similarity index 100% rename from app/components/Layout/images/logo.svg rename to app/images/logo.svg diff --git a/app/main.dev.js b/app/main.dev.js index a8daf77..daf74c5 100644 --- a/app/main.dev.js +++ b/app/main.dev.js @@ -54,7 +54,7 @@ app.on('window-all-closed', () => { app.on('ready', async () => { if (!settings.get("windowBounds")) { - settings.set("windowBounds", { width: 800, height: 600 }) + settings.set("windowBounds", { width: 800, height: 800 }) } console.log("Settings are stored in:\n" + settings.file()); let { width, height } = settings.get('windowBounds'); @@ -71,8 +71,11 @@ app.on('ready', async () => { mainWindow = new BrowserWindow({ // show: false, titleBarStyle: 'hiddenInset', + backgroundColor: "#000000", width, - height + height, + minHeight: 800, + minWidth: 800 }); mainWindow.loadURL(`file://${__dirname}/app.html`); diff --git a/app/package.json b/app/package.json index abdb0d9..44e6438 100644 --- a/app/package.json +++ b/app/package.json @@ -1,7 +1,7 @@ { "name": "Workbench", "productName": "Workbench", - "version": "0.0.3", + "version": "0.0.4", "description": "The Openpilot Workbench is to help people fix problems with EON, Openpilot, etc.", "main": "./main.prod.js", "author": { diff --git a/app/reducers/eon_detail_reducer.js b/app/reducers/eon_detail_reducer.js index 37a3c57..f2c95fb 100644 --- a/app/reducers/eon_detail_reducer.js +++ b/app/reducers/eon_detail_reducer.js @@ -22,7 +22,26 @@ const initialState = { visiond: null, tmuxStartedAt: null, gpsd: null, - vehicleConnection: null + vehicleConnection: null, + logMonoTime: null, + thermal: null, + cpu0: null, + cpu1: null, + cpu2: null, + cpu3: null, + mem: null, + gpu: null, + bat: null, + freeSpace: null, + batteryPercent: null, + batteryStatus: null, + fanSpeed: null, + started: null, + usbOnline: null, + startedTs: null, + thermalStatus: null, + batteryCurrent: null, + batteryVoltage: null }; export default function eonDetailReducer(state = initialState, action) { @@ -68,7 +87,26 @@ export default function eonDetailReducer(state = initialState, action) { visiond: null, gpsd: null, vehicleConnection: null, - tmuxStartedAt: null + tmuxStartedAt: null, + logMonoTime: null, + thermal: null, + cpu0: null, + cpu1: null, + cpu2: null, + cpu3: null, + mem: null, + gpu: null, + bat: null, + freeSpace: null, + batteryPercent: null, + batteryStatus: null, + fanSpeed: null, + started: null, + usbOnline: null, + startedTs: null, + thermalStatus: null, + batteryCurrent: null, + batteryVoltage: null } case types.FETCH_PID: diff --git a/package.json b/package.json index bae9e4e..5e2d72f 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "openpilot-workbench", "productName": "Workbench", - "version": "0.0.3", + "version": "0.0.4", "description": "The Openpilot Workbench is to help people fix problems with EON, Openpilot, etc.", "scripts": { "build": "concurrently \"yarn build-main\" \"yarn build-renderer\"", @@ -28,7 +28,8 @@ "test": "cross-env NODE_ENV=test BABEL_DISABLE_CACHE=1 node --trace-warnings -r babel-register ./internals/scripts/RunTests.js", "test-all": "yarn lint && yarn build && yarn test && yarn test-e2e", "test-e2e": "cross-env NODE_ENV=test BABEL_DISABLE_CACHE=1 node --trace-warnings -r babel-register ./internals/scripts/RunTests.js e2e", - "test-watch": "yarn test --watch" + "test-watch": "yarn test --watch", + "release": "build" }, "browserslist": "electron 1.6", "lint-staged": { @@ -45,6 +46,7 @@ "build": { "productName": "Workbench", "appId": "ai.opc.workbench", + "artifactName": "Workbench-v${version}.${os}.${ext}", "files": [ "dist/", "node_modules/", @@ -217,6 +219,7 @@ "react-hot-loader": "^4.3.4", "react-moment": "^0.7.9", "react-redux": "^5.0.7", + "react-resize-detector": "^3.1.2", "react-router": "^4.3.1", "react-router-dom": "^4.3.1", "react-router-redux": "^5.0.0-alpha.6", diff --git a/test.js b/test.js new file mode 100644 index 0000000..dd25e97 --- /dev/null +++ b/test.js @@ -0,0 +1,33 @@ +const regex = /(logMonoTime|thermal|cpu0|batteryStatus|cpu1|cpu2|cpu3|mem|gpu|bat|freeSpace|batteryPercent|batteryStatus|fanSpeed|started|usbOnline|startedTs|thermalStatus|batteryCurrent|batteryVoltage)\s\=\s([a-z0-9A-Z\"\.]+)/gmi; +const str = `( logMonoTime = 130182741042, + thermal = ( + cpu0 = 301, + cpu1 = 297, + cpu2 = 294, + cpu3 = 301, + mem = 301, + gpu = 301, + bat = 28000, + freeSpace = 0.97125262, + batteryPercent = 87, + batteryStatus = "Discharging", + fanSpeed = 0, + started = false, + usbOnline = false, + startedTs = 0, + thermalStatus = green, + batteryCurrent = 171000, + batteryVoltage = 4180000 ) )`; +let m; + +while ((m = regex.exec(str)) !== null) { + // This is necessary to avoid infinite loops with zero-width matches + if (m.index === regex.lastIndex) { + regex.lastIndex++; + } + + // The result can be accessed through the `m`-variable. + m.forEach((match, groupIndex) => { + console.log(`Found match, group ${groupIndex}: ${match}`); + }); +} diff --git a/yarn.lock b/yarn.lock index 8374171..345c5e8 100644 --- a/yarn.lock +++ b/yarn.lock @@ -6162,10 +6162,18 @@ lodash.get@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99" +lodash.isarray@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/lodash.isarray/-/lodash.isarray-4.0.0.tgz#2aca496b28c4ca6d726715313590c02e6ea34403" + lodash.isequal@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.isequal/-/lodash.isequal-4.5.0.tgz#415c4478f2bcc30120c22ce10ed3226f7d3e18e0" +lodash.isfunction@^3.0.9: + version "3.0.9" + resolved "https://registry.yarnpkg.com/lodash.isfunction/-/lodash.isfunction-3.0.9.tgz#06de25df4db327ac931981d1bdb067e5af68d051" + lodash.isplainobject@^4.0.6: version "4.0.6" resolved "https://registry.yarnpkg.com/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz#7c526a52d89b45c45cc690b88163be0497f550cb" @@ -6186,6 +6194,10 @@ lodash.tail@^4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/lodash.tail/-/lodash.tail-4.1.1.tgz#d2333a36d9e7717c8ad2f7cacafec7c32b444664" +lodash.throttle@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/lodash.throttle/-/lodash.throttle-4.1.1.tgz#c23e91b710242ac70c37f1e1cda9274cc39bf2f4" + lodash.uniq@^4.5.0: version "4.5.0" resolved "https://registry.yarnpkg.com/lodash.uniq/-/lodash.uniq-4.5.0.tgz#d0225373aeb652adc1bc82e4945339a842754773" @@ -8113,6 +8125,17 @@ react-redux@^5.0.7: loose-envify "^1.1.0" prop-types "^15.6.0" +react-resize-detector@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/react-resize-detector/-/react-resize-detector-3.1.2.tgz#b0b30b45a168d5a81ed24ada3a6d5e8d2e49e306" + dependencies: + lodash.debounce "^4.0.8" + lodash.isarray "^4.0.0" + lodash.isfunction "^3.0.9" + lodash.throttle "^4.1.1" + prop-types "^15.6.1" + resize-observer-polyfill "^1.5.0" + react-router-dom@^4.3.1: version "4.3.1" resolved "https://registry.yarnpkg.com/react-router-dom/-/react-router-dom-4.3.1.tgz#4c2619fc24c4fa87c9fd18f4fb4a43fe63fbd5c6" @@ -8522,6 +8545,10 @@ requires-port@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/requires-port/-/requires-port-1.0.0.tgz#925d2601d39ac485e091cf0da5c6e694dc3dcaff" +resize-observer-polyfill@^1.5.0: + version "1.5.0" + resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.0.tgz#660ff1d9712a2382baa2cad450a4716209f9ca69" + resolve-cwd@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/resolve-cwd/-/resolve-cwd-2.0.0.tgz#00a9f7387556e27038eae232caa372a6a59b665a"