提交 61452b2a 编写于 作者: V vlin17 提交者: Liu Jiaming

Dreamview: upgrade lint spec and related packages

上级 bab98f32
{
"parser": "babel-eslint",
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module",
"ecmaFeatures": {
"jsx": true,
"modules": true,
"legacyDecorators": true
}
},
"env": {
"browser": true
},
"extends": "airbnb",
"rules": {
"indent": [2, 4, {"SwitchCase": 1}],
// Allow using console
"no-console": 0,
// Alow using continue,
"no-continue": 0,
// Allow function without return
"consistent-return": 0,
// Allow write functions not-js-style, such as try-catch,class,for loop,etc
"no-restricted-syntax": 0,
// Allow creating variables from array or object use same name with the props
"prefer-destructuring": 0,
// Allow underscore at the beginning or end of variable name, because we have '_id'
"no-underscore-dangle": 0,
// Allow reassign props value of function parameters
"no-param-reassign": [2, {"props": false}],
// Allow function without name
"func-names": 0,
// Allow use global variables such as location/event
"no-restricted-globals": 0,
// Allow use await inside loop, because we have codes that output of one iteration is used as input to another
"no-await-in-loop": 0,
"react/jsx-indent": [2, 4, {checkAttributes: true}],
"react/jsx-indent-props": [2, 4],
// Same as before
"react/destructuring-assignment": 0,
// Allow not checking if props params exist
// TODO: add propTypes
"react/prop-types": 0,
// Allow .js as JSX component
"react/jsx-filename-extension": [2, { "extensions": [".js", ".jsx"] }],
// Allow static components has 'onClick' method
// TODO: use 'onClick' method on non-static components such as button
"jsx-a11y/no-static-element-interactions": 0,
// Allow only use 'onClick' method without keyboard listener
// TODO: add keyboard listener
"jsx-a11y/click-events-have-key-events": 0,
// Allow use onClick in <a>
"jsx-a11y/anchor-is-valid": 0,
// Allow noninteractive elements use onClick without keyboard listener
// TODO: Add keyboard listener
"jsx-a11y/no-noninteractive-element-interactions": 0,
// Allow module.exports for unnamed exports
"import/named": 0
},
"settings": {
"import/resolver": {
"webpack": "webpack.config.js"
}
}
}
......@@ -6,8 +6,12 @@
"ecmaFeatures": {
"jsx": true,
"modules": true,
"legacyDecorators": true
}
},
"env": {
"browser": true
},
"rules": {
// Require a semi colon at the end of a statement.
"semi": ["error", "always"],
......@@ -15,6 +19,8 @@
"max-len": ["error", 100, { "ignoreStrings": true }],
// Always require curly brackets.
"curly": "error",
// specify whether double or single quotes should be used
"quotes": ["error", "single", { "avoidEscape": true }],
// Require the use of `===` and `!==`.
"eqeqeq": "error",
......@@ -40,8 +46,24 @@
// Require parentheses when invoking a constructor with no
// arguments.
"new-parens": "error",
// disallow mixed spaces and tabs for indentation
"no-mixed-spaces-and-tabs": "error",
// Disallow trailing white space at the end of lines.
"no-trailing-spaces": "error",
// require or disallow space before blocks
"space-before-blocks": "error",
// require or disallow space before function opening parenthesis
// https://eslint.org/docs/rules/space-before-function-paren
"space-before-function-paren": ["error", {
"anonymous": "always",
"named": "never",
"asyncArrow": "always"
}],
// require or disallow spaces inside parentheses
"space-in-parens": ["error", "never"],
// require spaces around operators
"space-infix-ops": "error",
// React specific rule. Enable this so that no-unused-vars respect
// the use of a react component.
"react/jsx-uses-vars": "error",
......@@ -57,6 +79,33 @@
// Require `const` declaration for variables that are never
// reassigned after declared.
"prefer-const": "error",
// this option sets a specific tab width for your code
// https://eslint.org/docs/rules/indent
"indent": ["error", 2, {
"SwitchCase": 1,
"VariableDeclarator": 1,
"outerIIFEBody": 1,
// MemberExpression: null,
"FunctionDeclaration": {
"parameters": 1,
"body": 1
},
"FunctionExpression": {
"parameters": 1,
"body": 1
},
"CallExpression": {
"arguments": 1
},
"ArrayExpression": 1,
"ObjectExpression": 1,
"ImportDeclaration": 1,
"flatTernaryExpressions": false,
// list derived from https://github.com/benjamn/ast-types/blob/HEAD/def/jsx.js
"ignoredNodes": ["JSXElement", "JSXElement > *", "JSXAttribute", "JSXIdentifier", "JSXNamespacedName", "JSXMemberExpression", "JSXSpreadAttribute", "JSXExpressionContainer", "JSXOpeningElement", "JSXClosingElement", "JSXFragment", "JSXOpeningFragment", "JSXClosingFragment", "JSXText", "JSXEmptyExpression", "JSXSpreadChild"],
"ignoreComments": false
}],
},
"plugins": [
"react"
......
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{468:function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=m(a(3)),l=m(a(1)),i=m(a(2)),o=m(a(4)),r=m(a(5)),d=m(a(0)),u=m(a(109)),c=m(a(20)),f=a(177),s=m(a(469)),p=m(a(470));function m(e){return e&&e.__esModule?e:{default:e}}var v=function(e){function t(e){(0,l.default)(this,t);var a=(0,o.default)(this,(t.__proto__||(0,n.default)(t)).call(this,e));if(a.scriptOnLoadHandler=a.scriptOnLoadHandler.bind(a),!u.default.mapAPILoaded){var i=function(){console.log("Map API script loaded.")};"BaiduMap"===PARAMETERS.navigation.map?window.initMap=a.scriptOnLoadHandler:"GoogleMap"===PARAMETERS.navigation.map&&(i=a.scriptOnLoadHandler),(0,s.default)({url:PARAMETERS.navigation.mapAPiUrl,onLoad:i,onError:function(){console.log("Failed to load map api")}})}return a}return(0,r.default)(t,e),(0,i.default)(t,[{key:"componentDidMount",value:function(){u.default.mapAPILoaded&&this.scriptOnLoadHandler()}},{key:"componentDidUpdate",value:function(){var e=this.props,t=e.hasRoutingControls,a=e.size;t&&a===f.MAP_SIZE.FULL?u.default.enableControls():u.default.disableControls()}},{key:"scriptOnLoadHandler",value:function(){a(471)("./"+PARAMETERS.navigation.map+"Adapter").then((function(e){var t=new(0,e.default);u.default.mapAPILoaded=!0,u.default.initialize(c.default,t),u.default.disableControls()}))}},{key:"componentWillUnmount",value:function(){u.default.reset()}},{key:"render",value:function(){var e=this.props,t=e.width,a=e.height,n=e.size,l=e.onResize;return["GoogleMap","BaiduMap"].includes(PARAMETERS.navigation.map)?d.default.createElement("div",{displayname:"navigation",className:"navigation-view",style:{width:t,height:a}},d.default.createElement("div",{id:"map_canvas"}),d.default.createElement(p.default,{type:n,onClick:l})):(console.error("Map API "+PARAMETERS.navigation.map+" is not supported."),null)}}]),t}(d.default.Component);t.default=v},469:function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=e.url,a=e.onLoad,n=e.onError,l=document.createElement("script");l.src=t,l.type="text/javascript",l.async=!0,l.onload=a,l.onerror=n,document.body.appendChild(l)}},470:function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=c(a(3)),l=c(a(1)),i=c(a(2)),o=c(a(4)),r=c(a(5)),d=c(a(0)),u=a(177);function c(e){return e&&e.__esModule?e:{default:e}}var f=function(e){function t(){return(0,l.default)(this,t),(0,o.default)(this,(t.__proto__||(0,n.default)(t)).apply(this,arguments))}return(0,r.default)(t,e),(0,i.default)(t,[{key:"getMinimizingIcon",value:function(){return d.default.createElement("svg",{viewBox:"0 0 20 20"},d.default.createElement("defs",null,d.default.createElement("path",{d:"M20 0L0 20h20V0z",id:"a"}),d.default.createElement("path",{d:"M11.53 18.5l-.03-7h7",id:"b"}),d.default.createElement("path",{d:"M12 12l7 7",id:"c"})),d.default.createElement("use",{xlinkHref:"#a",opacity:".8",fill:"#84b7FF"}),d.default.createElement("use",{xlinkHref:"#b",fillOpacity:"0",stroke:"#006AFF",strokeWidth:"2"}),d.default.createElement("use",{xlinkHref:"#c",fillOpacity:"0",stroke:"#006AFF",strokeWidth:"2"}))}},{key:"getMaximizingIcon",value:function(){return d.default.createElement("svg",{viewBox:"0 0 20 20"},d.default.createElement("defs",null,d.default.createElement("path",{d:"M20 0L0 20h20V0z",id:"a"}),d.default.createElement("path",{d:"M18.47 11.5l.03 7h-7",id:"b"}),d.default.createElement("path",{d:"M11 11l7 7",id:"c"})),d.default.createElement("use",{xlinkHref:"#a",opacity:".8",fill:"#84b7FF"}),d.default.createElement("use",{xlinkHref:"#b",fillOpacity:"0",stroke:"#006AFF",strokeWidth:"2"}),d.default.createElement("use",{xlinkHref:"#c",fillOpacity:"0",stroke:"#006AFF",strokeWidth:"2"}))}},{key:"render",value:function(){var e=this.props,t=e.type,a=e.onClick,n=null;switch(t){case u.MAP_SIZE.FULL:n=this.getMinimizingIcon();break;case u.MAP_SIZE.DEFAULT:n=this.getMaximizingIcon();break;default:console.error("Unknown window size found:",t)}return d.default.createElement("div",{className:"window-resize-control",onClick:a},n)}}]),t}(d.default.PureComponent);t.default=f},471:function(e,t,a){var n={"./BaiduMapAdapter":[472,3],"./GoogleMapAdapter":[473,4]};function l(e){var t=n[e];return t?a.e(t[1]).then((function(){var e=t[0];return a.t(e,7)})):Promise.resolve().then((function(){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}))}l.keys=function(){return Object.keys(n)},l.id=471,e.exports=l}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{468:function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=m(a(4)),l=m(a(1)),i=m(a(2)),o=m(a(5)),r=m(a(6)),d=m(a(0)),u=m(a(109)),c=m(a(20)),f=a(177),s=m(a(470)),p=m(a(471));function m(e){return e&&e.__esModule?e:{default:e}}var v=function(e){function t(e){(0,l.default)(this,t);var a=(0,o.default)(this,(t.__proto__||(0,n.default)(t)).call(this,e));if(a.scriptOnLoadHandler=a.scriptOnLoadHandler.bind(a),!u.default.mapAPILoaded){var i=function(){console.log("Map API script loaded.")};"BaiduMap"===PARAMETERS.navigation.map?window.initMap=a.scriptOnLoadHandler:"GoogleMap"===PARAMETERS.navigation.map&&(i=a.scriptOnLoadHandler),(0,s.default)({url:PARAMETERS.navigation.mapAPiUrl,onLoad:i,onError:function(){console.log("Failed to load map api")}})}return a}return(0,r.default)(t,e),(0,i.default)(t,[{key:"componentDidMount",value:function(){u.default.mapAPILoaded&&this.scriptOnLoadHandler()}},{key:"componentDidUpdate",value:function(){var e=this.props,t=e.hasRoutingControls,a=e.size;t&&a===f.MAP_SIZE.FULL?u.default.enableControls():u.default.disableControls()}},{key:"scriptOnLoadHandler",value:function(){a(472)("./"+PARAMETERS.navigation.map+"Adapter").then((function(e){var t=new(0,e.default);u.default.mapAPILoaded=!0,u.default.initialize(c.default,t),u.default.disableControls()}))}},{key:"componentWillUnmount",value:function(){u.default.reset()}},{key:"render",value:function(){var e=this.props,t=e.width,a=e.height,n=e.size,l=e.onResize;return["GoogleMap","BaiduMap"].includes(PARAMETERS.navigation.map)?d.default.createElement("div",{displayname:"navigation",className:"navigation-view",style:{width:t,height:a}},d.default.createElement("div",{id:"map_canvas"}),d.default.createElement(p.default,{type:n,onClick:l})):(console.error("Map API "+PARAMETERS.navigation.map+" is not supported."),null)}}]),t}(d.default.Component);t.default=v},470:function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e){var t=e.url,a=e.onLoad,n=e.onError,l=document.createElement("script");l.src=t,l.type="text/javascript",l.async=!0,l.onload=a,l.onerror=n,document.body.appendChild(l)}},471:function(e,t,a){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n=c(a(4)),l=c(a(1)),i=c(a(2)),o=c(a(5)),r=c(a(6)),d=c(a(0)),u=a(177);function c(e){return e&&e.__esModule?e:{default:e}}var f=function(e){function t(){return(0,l.default)(this,t),(0,o.default)(this,(t.__proto__||(0,n.default)(t)).apply(this,arguments))}return(0,r.default)(t,e),(0,i.default)(t,[{key:"getMinimizingIcon",value:function(){return d.default.createElement("svg",{viewBox:"0 0 20 20"},d.default.createElement("defs",null,d.default.createElement("path",{d:"M20 0L0 20h20V0z",id:"a"}),d.default.createElement("path",{d:"M11.53 18.5l-.03-7h7",id:"b"}),d.default.createElement("path",{d:"M12 12l7 7",id:"c"})),d.default.createElement("use",{xlinkHref:"#a",opacity:".8",fill:"#84b7FF"}),d.default.createElement("use",{xlinkHref:"#b",fillOpacity:"0",stroke:"#006AFF",strokeWidth:"2"}),d.default.createElement("use",{xlinkHref:"#c",fillOpacity:"0",stroke:"#006AFF",strokeWidth:"2"}))}},{key:"getMaximizingIcon",value:function(){return d.default.createElement("svg",{viewBox:"0 0 20 20"},d.default.createElement("defs",null,d.default.createElement("path",{d:"M20 0L0 20h20V0z",id:"a"}),d.default.createElement("path",{d:"M18.47 11.5l.03 7h-7",id:"b"}),d.default.createElement("path",{d:"M11 11l7 7",id:"c"})),d.default.createElement("use",{xlinkHref:"#a",opacity:".8",fill:"#84b7FF"}),d.default.createElement("use",{xlinkHref:"#b",fillOpacity:"0",stroke:"#006AFF",strokeWidth:"2"}),d.default.createElement("use",{xlinkHref:"#c",fillOpacity:"0",stroke:"#006AFF",strokeWidth:"2"}))}},{key:"render",value:function(){var e=this.props,t=e.type,a=e.onClick,n=null;switch(t){case u.MAP_SIZE.FULL:n=this.getMinimizingIcon();break;case u.MAP_SIZE.DEFAULT:n=this.getMaximizingIcon();break;default:console.error("Unknown window size found:",t)}return d.default.createElement("div",{className:"window-resize-control",onClick:a},n)}}]),t}(d.default.PureComponent);t.default=f},472:function(e,t,a){var n={"./BaiduMapAdapter":[473,3],"./GoogleMapAdapter":[474,4]};function l(e){var t=n[e];return t?a.e(t[1]).then((function(){var e=t[0];return a.t(e,7)})):Promise.resolve().then((function(){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}))}l.keys=function(){return Object.keys(n)},l.id=472,e.exports=l}}]);
//# sourceMappingURL=2.bundle.js.map
\ No newline at end of file
{"version":3,"file":"2.bundle.js","sources":["webpack:///2.bundle.js"],"sourcesContent":["(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{468:function(e,t,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.default=void 0;var n=m(a(3)),l=m(a(1)),i=m(a(2)),o=m(a(4)),r=m(a(5)),d=m(a(0)),u=m(a(109)),c=m(a(20)),f=a(177),s=m(a(469)),p=m(a(470));function m(e){return e&&e.__esModule?e:{default:e}}var v=function(e){function t(e){(0,l.default)(this,t);var a=(0,o.default)(this,(t.__proto__||(0,n.default)(t)).call(this,e));if(a.scriptOnLoadHandler=a.scriptOnLoadHandler.bind(a),!u.default.mapAPILoaded){var i=function(){console.log(\"Map API script loaded.\")};\"BaiduMap\"===PARAMETERS.navigation.map?window.initMap=a.scriptOnLoadHandler:\"GoogleMap\"===PARAMETERS.navigation.map&&(i=a.scriptOnLoadHandler),(0,s.default)({url:PARAMETERS.navigation.mapAPiUrl,onLoad:i,onError:function(){console.log(\"Failed to load map api\")}})}return a}return(0,r.default)(t,e),(0,i.default)(t,[{key:\"componentDidMount\",value:function(){u.default.mapAPILoaded&&this.scriptOnLoadHandler()}},{key:\"componentDidUpdate\",value:function(){var e=this.props,t=e.hasRoutingControls,a=e.size;t&&a===f.MAP_SIZE.FULL?u.default.enableControls():u.default.disableControls()}},{key:\"scriptOnLoadHandler\",value:function(){a(471)(\"./\"+PARAMETERS.navigation.map+\"Adapter\").then((function(e){var t=new(0,e.default);u.default.mapAPILoaded=!0,u.default.initialize(c.default,t),u.default.disableControls()}))}},{key:\"componentWillUnmount\",value:function(){u.default.reset()}},{key:\"render\",value:function(){var e=this.props,t=e.width,a=e.height,n=e.size,l=e.onResize;return[\"GoogleMap\",\"BaiduMap\"].includes(PARAMETERS.navigation.map)?d.default.createElement(\"div\",{displayname:\"navigation\",className:\"navigation-view\",style:{width:t,height:a}},d.default.createElement(\"div\",{id:\"map_canvas\"}),d.default.createElement(p.default,{type:n,onClick:l})):(console.error(\"Map API \"+PARAMETERS.navigation.map+\" is not supported.\"),null)}}]),t}(d.default.Component);t.default=v},469:function(e,t,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.default=function(e){var t=e.url,a=e.onLoad,n=e.onError,l=document.createElement(\"script\");l.src=t,l.type=\"text/javascript\",l.async=!0,l.onload=a,l.onerror=n,document.body.appendChild(l)}},470:function(e,t,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.default=void 0;var n=c(a(3)),l=c(a(1)),i=c(a(2)),o=c(a(4)),r=c(a(5)),d=c(a(0)),u=a(177);function c(e){return e&&e.__esModule?e:{default:e}}var f=function(e){function t(){return(0,l.default)(this,t),(0,o.default)(this,(t.__proto__||(0,n.default)(t)).apply(this,arguments))}return(0,r.default)(t,e),(0,i.default)(t,[{key:\"getMinimizingIcon\",value:function(){return d.default.createElement(\"svg\",{viewBox:\"0 0 20 20\"},d.default.createElement(\"defs\",null,d.default.createElement(\"path\",{d:\"M20 0L0 20h20V0z\",id:\"a\"}),d.default.createElement(\"path\",{d:\"M11.53 18.5l-.03-7h7\",id:\"b\"}),d.default.createElement(\"path\",{d:\"M12 12l7 7\",id:\"c\"})),d.default.createElement(\"use\",{xlinkHref:\"#a\",opacity:\".8\",fill:\"#84b7FF\"}),d.default.createElement(\"use\",{xlinkHref:\"#b\",fillOpacity:\"0\",stroke:\"#006AFF\",strokeWidth:\"2\"}),d.default.createElement(\"use\",{xlinkHref:\"#c\",fillOpacity:\"0\",stroke:\"#006AFF\",strokeWidth:\"2\"}))}},{key:\"getMaximizingIcon\",value:function(){return d.default.createElement(\"svg\",{viewBox:\"0 0 20 20\"},d.default.createElement(\"defs\",null,d.default.createElement(\"path\",{d:\"M20 0L0 20h20V0z\",id:\"a\"}),d.default.createElement(\"path\",{d:\"M18.47 11.5l.03 7h-7\",id:\"b\"}),d.default.createElement(\"path\",{d:\"M11 11l7 7\",id:\"c\"})),d.default.createElement(\"use\",{xlinkHref:\"#a\",opacity:\".8\",fill:\"#84b7FF\"}),d.default.createElement(\"use\",{xlinkHref:\"#b\",fillOpacity:\"0\",stroke:\"#006AFF\",strokeWidth:\"2\"}),d.default.createElement(\"use\",{xlinkHref:\"#c\",fillOpacity:\"0\",stroke:\"#006AFF\",strokeWidth:\"2\"}))}},{key:\"render\",value:function(){var e=this.props,t=e.type,a=e.onClick,n=null;switch(t){case u.MAP_SIZE.FULL:n=this.getMinimizingIcon();break;case u.MAP_SIZE.DEFAULT:n=this.getMaximizingIcon();break;default:console.error(\"Unknown window size found:\",t)}return d.default.createElement(\"div\",{className:\"window-resize-control\",onClick:a},n)}}]),t}(d.default.PureComponent);t.default=f},471:function(e,t,a){var n={\"./BaiduMapAdapter\":[472,3],\"./GoogleMapAdapter\":[473,4]};function l(e){var t=n[e];return t?a.e(t[1]).then((function(){var e=t[0];return a.t(e,7)})):Promise.resolve().then((function(){var t=new Error(\"Cannot find module '\"+e+\"'\");throw t.code=\"MODULE_NOT_FOUND\",t}))}l.keys=function(){return Object.keys(n)},l.id=471,e.exports=l}}]);"],"mappings":"AAAA","sourceRoot":""}
\ No newline at end of file
{"version":3,"file":"2.bundle.js","sources":["webpack:///2.bundle.js"],"sourcesContent":["(window.webpackJsonp=window.webpackJsonp||[]).push([[2],{468:function(e,t,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.default=void 0;var n=m(a(4)),l=m(a(1)),i=m(a(2)),o=m(a(5)),r=m(a(6)),d=m(a(0)),u=m(a(109)),c=m(a(20)),f=a(177),s=m(a(470)),p=m(a(471));function m(e){return e&&e.__esModule?e:{default:e}}var v=function(e){function t(e){(0,l.default)(this,t);var a=(0,o.default)(this,(t.__proto__||(0,n.default)(t)).call(this,e));if(a.scriptOnLoadHandler=a.scriptOnLoadHandler.bind(a),!u.default.mapAPILoaded){var i=function(){console.log(\"Map API script loaded.\")};\"BaiduMap\"===PARAMETERS.navigation.map?window.initMap=a.scriptOnLoadHandler:\"GoogleMap\"===PARAMETERS.navigation.map&&(i=a.scriptOnLoadHandler),(0,s.default)({url:PARAMETERS.navigation.mapAPiUrl,onLoad:i,onError:function(){console.log(\"Failed to load map api\")}})}return a}return(0,r.default)(t,e),(0,i.default)(t,[{key:\"componentDidMount\",value:function(){u.default.mapAPILoaded&&this.scriptOnLoadHandler()}},{key:\"componentDidUpdate\",value:function(){var e=this.props,t=e.hasRoutingControls,a=e.size;t&&a===f.MAP_SIZE.FULL?u.default.enableControls():u.default.disableControls()}},{key:\"scriptOnLoadHandler\",value:function(){a(472)(\"./\"+PARAMETERS.navigation.map+\"Adapter\").then((function(e){var t=new(0,e.default);u.default.mapAPILoaded=!0,u.default.initialize(c.default,t),u.default.disableControls()}))}},{key:\"componentWillUnmount\",value:function(){u.default.reset()}},{key:\"render\",value:function(){var e=this.props,t=e.width,a=e.height,n=e.size,l=e.onResize;return[\"GoogleMap\",\"BaiduMap\"].includes(PARAMETERS.navigation.map)?d.default.createElement(\"div\",{displayname:\"navigation\",className:\"navigation-view\",style:{width:t,height:a}},d.default.createElement(\"div\",{id:\"map_canvas\"}),d.default.createElement(p.default,{type:n,onClick:l})):(console.error(\"Map API \"+PARAMETERS.navigation.map+\" is not supported.\"),null)}}]),t}(d.default.Component);t.default=v},470:function(e,t,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.default=function(e){var t=e.url,a=e.onLoad,n=e.onError,l=document.createElement(\"script\");l.src=t,l.type=\"text/javascript\",l.async=!0,l.onload=a,l.onerror=n,document.body.appendChild(l)}},471:function(e,t,a){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.default=void 0;var n=c(a(4)),l=c(a(1)),i=c(a(2)),o=c(a(5)),r=c(a(6)),d=c(a(0)),u=a(177);function c(e){return e&&e.__esModule?e:{default:e}}var f=function(e){function t(){return(0,l.default)(this,t),(0,o.default)(this,(t.__proto__||(0,n.default)(t)).apply(this,arguments))}return(0,r.default)(t,e),(0,i.default)(t,[{key:\"getMinimizingIcon\",value:function(){return d.default.createElement(\"svg\",{viewBox:\"0 0 20 20\"},d.default.createElement(\"defs\",null,d.default.createElement(\"path\",{d:\"M20 0L0 20h20V0z\",id:\"a\"}),d.default.createElement(\"path\",{d:\"M11.53 18.5l-.03-7h7\",id:\"b\"}),d.default.createElement(\"path\",{d:\"M12 12l7 7\",id:\"c\"})),d.default.createElement(\"use\",{xlinkHref:\"#a\",opacity:\".8\",fill:\"#84b7FF\"}),d.default.createElement(\"use\",{xlinkHref:\"#b\",fillOpacity:\"0\",stroke:\"#006AFF\",strokeWidth:\"2\"}),d.default.createElement(\"use\",{xlinkHref:\"#c\",fillOpacity:\"0\",stroke:\"#006AFF\",strokeWidth:\"2\"}))}},{key:\"getMaximizingIcon\",value:function(){return d.default.createElement(\"svg\",{viewBox:\"0 0 20 20\"},d.default.createElement(\"defs\",null,d.default.createElement(\"path\",{d:\"M20 0L0 20h20V0z\",id:\"a\"}),d.default.createElement(\"path\",{d:\"M18.47 11.5l.03 7h-7\",id:\"b\"}),d.default.createElement(\"path\",{d:\"M11 11l7 7\",id:\"c\"})),d.default.createElement(\"use\",{xlinkHref:\"#a\",opacity:\".8\",fill:\"#84b7FF\"}),d.default.createElement(\"use\",{xlinkHref:\"#b\",fillOpacity:\"0\",stroke:\"#006AFF\",strokeWidth:\"2\"}),d.default.createElement(\"use\",{xlinkHref:\"#c\",fillOpacity:\"0\",stroke:\"#006AFF\",strokeWidth:\"2\"}))}},{key:\"render\",value:function(){var e=this.props,t=e.type,a=e.onClick,n=null;switch(t){case u.MAP_SIZE.FULL:n=this.getMinimizingIcon();break;case u.MAP_SIZE.DEFAULT:n=this.getMaximizingIcon();break;default:console.error(\"Unknown window size found:\",t)}return d.default.createElement(\"div\",{className:\"window-resize-control\",onClick:a},n)}}]),t}(d.default.PureComponent);t.default=f},472:function(e,t,a){var n={\"./BaiduMapAdapter\":[473,3],\"./GoogleMapAdapter\":[474,4]};function l(e){var t=n[e];return t?a.e(t[1]).then((function(){var e=t[0];return a.t(e,7)})):Promise.resolve().then((function(){var t=new Error(\"Cannot find module '\"+e+\"'\");throw t.code=\"MODULE_NOT_FOUND\",t}))}l.keys=function(){return Object.keys(n)},l.id=472,e.exports=l}}]);"],"mappings":"AAAA","sourceRoot":""}
\ No newline at end of file
(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{472:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=c(n(3)),o=c(n(4)),i=c(n(5)),l=c(n(36)),r=c(n(23)),s=c(n(1)),u=c(n(2)),d=n(176);function c(e){return e&&e.__esModule?e:{default:e}}var p=function(){function e(){(0,s.default)(this,e),this.map=null,this.controls=[],this.initializedCenter=!1}return(0,u.default)(e,[{key:"isInitialized",value:function(){return null!==this.map&&(0,r.default)(this.map).length>0}},{key:"loadMap",value:function(e,t){this.map=new BMap.Map(t,{enableMapClick:!1}),this.map.enableScrollWheelZoom(),this.map.addControl(new BMap.MapTypeControl({anchor:BMAP_ANCHOR_TOP_LEFT,type:BMAP_NAVIGATION_CONTROL_SMALL})),this.map.addControl(new BMap.NavigationControl({anchor:BMAP_ANCHOR_BOTTOM_RIGHT,type:BMAP_NAVIGATION_CONTROL_SMALL,enableGeolocation:!1}))}},{key:"setCenter",value:function(e){this.initializedCenter?this.map.setCenter(e):(this.map.centerAndZoom(e,19),this.initializedCenter=!0)}},{key:"setZoom",value:function(e){this.map.setZoom(e)}},{key:"addEventHandler",value:function(e,t){this.map.addEventListener(e,(function(e){var n=e.point;t(n)}))}},{key:"createPoint",value:function(e){var t=e.lat,n=e.lng;return new BMap.Point(n,t)}},{key:"createMarker",value:function(e,t){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=null;t&&(a=new BMap.Label(t,{point:e,offset:new BMap.Size(15,-15)}));var o=new BMap.Marker(e,{label:a,enableDragging:n,rotation:5});return o.setLabel(a),this.map.addOverlay(o),o}},{key:"createPolyline",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:2,o={geodesic:!0,strokeColor:t,strokeOpacity:n,strokeWeight:a},i=new BMap.Polyline(e,o);return this.map.addOverlay(i),i}},{key:"createControl",value:function(e){var t=e.text,n=e.tip,a=e.color,o=e.offsetX,i=e.offsetY,l=e.onClickHandler,r=new f(t,n,a,new BMap.Size(o,i),l);this.map.addControl(r),this.controls.push(r)}},{key:"disableControls",value:function(){var e=this;this.controls.forEach((function(t){e.map.removeControl(t)}))}},{key:"enableControls",value:function(){var e=this;this.controls.forEach((function(t){e.map.addControl(t)}))}},{key:"getMarkerPosition",value:function(e){return e.getPosition()}},{key:"updatePolyline",value:function(e,t){e.setPath(t)}},{key:"removePolyline",value:function(e){this.map.removeOverlay(e)}},{key:"applyCoordinateOffset",value:function(e){var t=(0,l.default)(e,2),n=t[0],a=t[1];return(0,d.WGS84ToBD09LL)(n,a)}}]),e}();t.default=p;var f=function(e){function t(e,n,i,l,r){var u;(0,s.default)(this,t);for(var d=arguments.length,c=Array(d>5?d-5:0),p=5;p<d;p++)c[p-5]=arguments[p];var f=(0,o.default)(this,(u=t.__proto__||(0,a.default)(t)).call.apply(u,[this].concat(c)));return f.defaultAnchor=BMAP_ANCHOR_TOP_LEFT,f.defaultOffset=l,f.onClickHandler=r,f.title=n,f.text=e,f.backgroundColor=i,f}return(0,i.default)(t,e),(0,u.default)(t,[{key:"initialize",value:function(e){var t=this,n=document.createElement("div"),a=document.createElement("div");a.style.backgroundColor=this.backgroundColor,a.style.border="2px solid #fff",a.style.borderRadius="3px",a.style.boxShadow="0 2px 6px rgba(0,0,0,.3)",a.style.cursor="pointer",a.style.marginBottom="22px",a.style.textAlign="center",a.title=this.title,n.appendChild(a);var o=document.createElement("div");return o.style.color="rgb(25,25,25)",o.style.fontFamily="Roboto,Arial,sans-serif",o.style.fontSize="16px",o.style.lineHeight="38px",o.style.paddingLeft="5px",o.style.paddingRight="5px",o.innerHTML=this.text,a.appendChild(o),e.getContainer().appendChild(n),a.addEventListener("click",(function(){t.onClickHandler(o)})),n}}]),t}(BMap.Control)}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{473:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var a=c(n(4)),o=c(n(5)),i=c(n(6)),l=c(n(36)),r=c(n(23)),s=c(n(1)),u=c(n(2)),d=n(176);function c(e){return e&&e.__esModule?e:{default:e}}var p=function(){function e(){(0,s.default)(this,e),this.map=null,this.controls=[],this.initializedCenter=!1}return(0,u.default)(e,[{key:"isInitialized",value:function(){return null!==this.map&&(0,r.default)(this.map).length>0}},{key:"loadMap",value:function(e,t){this.map=new BMap.Map(t,{enableMapClick:!1}),this.map.enableScrollWheelZoom(),this.map.addControl(new BMap.MapTypeControl({anchor:BMAP_ANCHOR_TOP_LEFT,type:BMAP_NAVIGATION_CONTROL_SMALL})),this.map.addControl(new BMap.NavigationControl({anchor:BMAP_ANCHOR_BOTTOM_RIGHT,type:BMAP_NAVIGATION_CONTROL_SMALL,enableGeolocation:!1}))}},{key:"setCenter",value:function(e){this.initializedCenter?this.map.setCenter(e):(this.map.centerAndZoom(e,19),this.initializedCenter=!0)}},{key:"setZoom",value:function(e){this.map.setZoom(e)}},{key:"addEventHandler",value:function(e,t){this.map.addEventListener(e,(function(e){var n=e.point;t(n)}))}},{key:"createPoint",value:function(e){var t=e.lat,n=e.lng;return new BMap.Point(n,t)}},{key:"createMarker",value:function(e,t){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=null;t&&(a=new BMap.Label(t,{point:e,offset:new BMap.Size(15,-15)}));var o=new BMap.Marker(e,{label:a,enableDragging:n,rotation:5});return o.setLabel(a),this.map.addOverlay(o),o}},{key:"createPolyline",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:2,o={geodesic:!0,strokeColor:t,strokeOpacity:n,strokeWeight:a},i=new BMap.Polyline(e,o);return this.map.addOverlay(i),i}},{key:"createControl",value:function(e){var t=e.text,n=e.tip,a=e.color,o=e.offsetX,i=e.offsetY,l=e.onClickHandler,r=new f(t,n,a,new BMap.Size(o,i),l);this.map.addControl(r),this.controls.push(r)}},{key:"disableControls",value:function(){var e=this;this.controls.forEach((function(t){e.map.removeControl(t)}))}},{key:"enableControls",value:function(){var e=this;this.controls.forEach((function(t){e.map.addControl(t)}))}},{key:"getMarkerPosition",value:function(e){return e.getPosition()}},{key:"updatePolyline",value:function(e,t){e.setPath(t)}},{key:"removePolyline",value:function(e){this.map.removeOverlay(e)}},{key:"applyCoordinateOffset",value:function(e){var t=(0,l.default)(e,2),n=t[0],a=t[1];return(0,d.WGS84ToBD09LL)(n,a)}}]),e}();t.default=p;var f=function(e){function t(e,n,i,l,r){var u;(0,s.default)(this,t);for(var d=arguments.length,c=Array(d>5?d-5:0),p=5;p<d;p++)c[p-5]=arguments[p];var f=(0,o.default)(this,(u=t.__proto__||(0,a.default)(t)).call.apply(u,[this].concat(c)));return f.defaultAnchor=BMAP_ANCHOR_TOP_LEFT,f.defaultOffset=l,f.onClickHandler=r,f.title=n,f.text=e,f.backgroundColor=i,f}return(0,i.default)(t,e),(0,u.default)(t,[{key:"initialize",value:function(e){var t=this,n=document.createElement("div"),a=document.createElement("div");a.style.backgroundColor=this.backgroundColor,a.style.border="2px solid #fff",a.style.borderRadius="3px",a.style.boxShadow="0 2px 6px rgba(0,0,0,.3)",a.style.cursor="pointer",a.style.marginBottom="22px",a.style.textAlign="center",a.title=this.title,n.appendChild(a);var o=document.createElement("div");return o.style.color="rgb(25,25,25)",o.style.fontFamily="Roboto,Arial,sans-serif",o.style.fontSize="16px",o.style.lineHeight="38px",o.style.paddingLeft="5px",o.style.paddingRight="5px",o.innerHTML=this.text,a.appendChild(o),e.getContainer().appendChild(n),a.addEventListener("click",(function(){t.onClickHandler(o)})),n}}]),t}(BMap.Control)}}]);
//# sourceMappingURL=3.bundle.js.map
\ No newline at end of file
{"version":3,"file":"3.bundle.js","sources":["webpack:///3.bundle.js"],"sourcesContent":["(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{472:function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.default=void 0;var a=c(n(3)),o=c(n(4)),i=c(n(5)),l=c(n(36)),r=c(n(23)),s=c(n(1)),u=c(n(2)),d=n(176);function c(e){return e&&e.__esModule?e:{default:e}}var p=function(){function e(){(0,s.default)(this,e),this.map=null,this.controls=[],this.initializedCenter=!1}return(0,u.default)(e,[{key:\"isInitialized\",value:function(){return null!==this.map&&(0,r.default)(this.map).length>0}},{key:\"loadMap\",value:function(e,t){this.map=new BMap.Map(t,{enableMapClick:!1}),this.map.enableScrollWheelZoom(),this.map.addControl(new BMap.MapTypeControl({anchor:BMAP_ANCHOR_TOP_LEFT,type:BMAP_NAVIGATION_CONTROL_SMALL})),this.map.addControl(new BMap.NavigationControl({anchor:BMAP_ANCHOR_BOTTOM_RIGHT,type:BMAP_NAVIGATION_CONTROL_SMALL,enableGeolocation:!1}))}},{key:\"setCenter\",value:function(e){this.initializedCenter?this.map.setCenter(e):(this.map.centerAndZoom(e,19),this.initializedCenter=!0)}},{key:\"setZoom\",value:function(e){this.map.setZoom(e)}},{key:\"addEventHandler\",value:function(e,t){this.map.addEventListener(e,(function(e){var n=e.point;t(n)}))}},{key:\"createPoint\",value:function(e){var t=e.lat,n=e.lng;return new BMap.Point(n,t)}},{key:\"createMarker\",value:function(e,t){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=null;t&&(a=new BMap.Label(t,{point:e,offset:new BMap.Size(15,-15)}));var o=new BMap.Marker(e,{label:a,enableDragging:n,rotation:5});return o.setLabel(a),this.map.addOverlay(o),o}},{key:\"createPolyline\",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:2,o={geodesic:!0,strokeColor:t,strokeOpacity:n,strokeWeight:a},i=new BMap.Polyline(e,o);return this.map.addOverlay(i),i}},{key:\"createControl\",value:function(e){var t=e.text,n=e.tip,a=e.color,o=e.offsetX,i=e.offsetY,l=e.onClickHandler,r=new f(t,n,a,new BMap.Size(o,i),l);this.map.addControl(r),this.controls.push(r)}},{key:\"disableControls\",value:function(){var e=this;this.controls.forEach((function(t){e.map.removeControl(t)}))}},{key:\"enableControls\",value:function(){var e=this;this.controls.forEach((function(t){e.map.addControl(t)}))}},{key:\"getMarkerPosition\",value:function(e){return e.getPosition()}},{key:\"updatePolyline\",value:function(e,t){e.setPath(t)}},{key:\"removePolyline\",value:function(e){this.map.removeOverlay(e)}},{key:\"applyCoordinateOffset\",value:function(e){var t=(0,l.default)(e,2),n=t[0],a=t[1];return(0,d.WGS84ToBD09LL)(n,a)}}]),e}();t.default=p;var f=function(e){function t(e,n,i,l,r){var u;(0,s.default)(this,t);for(var d=arguments.length,c=Array(d>5?d-5:0),p=5;p<d;p++)c[p-5]=arguments[p];var f=(0,o.default)(this,(u=t.__proto__||(0,a.default)(t)).call.apply(u,[this].concat(c)));return f.defaultAnchor=BMAP_ANCHOR_TOP_LEFT,f.defaultOffset=l,f.onClickHandler=r,f.title=n,f.text=e,f.backgroundColor=i,f}return(0,i.default)(t,e),(0,u.default)(t,[{key:\"initialize\",value:function(e){var t=this,n=document.createElement(\"div\"),a=document.createElement(\"div\");a.style.backgroundColor=this.backgroundColor,a.style.border=\"2px solid #fff\",a.style.borderRadius=\"3px\",a.style.boxShadow=\"0 2px 6px rgba(0,0,0,.3)\",a.style.cursor=\"pointer\",a.style.marginBottom=\"22px\",a.style.textAlign=\"center\",a.title=this.title,n.appendChild(a);var o=document.createElement(\"div\");return o.style.color=\"rgb(25,25,25)\",o.style.fontFamily=\"Roboto,Arial,sans-serif\",o.style.fontSize=\"16px\",o.style.lineHeight=\"38px\",o.style.paddingLeft=\"5px\",o.style.paddingRight=\"5px\",o.innerHTML=this.text,a.appendChild(o),e.getContainer().appendChild(n),a.addEventListener(\"click\",(function(){t.onClickHandler(o)})),n}}]),t}(BMap.Control)}}]);"],"mappings":"AAAA","sourceRoot":""}
\ No newline at end of file
{"version":3,"file":"3.bundle.js","sources":["webpack:///3.bundle.js"],"sourcesContent":["(window.webpackJsonp=window.webpackJsonp||[]).push([[3],{473:function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.default=void 0;var a=c(n(4)),o=c(n(5)),i=c(n(6)),l=c(n(36)),r=c(n(23)),s=c(n(1)),u=c(n(2)),d=n(176);function c(e){return e&&e.__esModule?e:{default:e}}var p=function(){function e(){(0,s.default)(this,e),this.map=null,this.controls=[],this.initializedCenter=!1}return(0,u.default)(e,[{key:\"isInitialized\",value:function(){return null!==this.map&&(0,r.default)(this.map).length>0}},{key:\"loadMap\",value:function(e,t){this.map=new BMap.Map(t,{enableMapClick:!1}),this.map.enableScrollWheelZoom(),this.map.addControl(new BMap.MapTypeControl({anchor:BMAP_ANCHOR_TOP_LEFT,type:BMAP_NAVIGATION_CONTROL_SMALL})),this.map.addControl(new BMap.NavigationControl({anchor:BMAP_ANCHOR_BOTTOM_RIGHT,type:BMAP_NAVIGATION_CONTROL_SMALL,enableGeolocation:!1}))}},{key:\"setCenter\",value:function(e){this.initializedCenter?this.map.setCenter(e):(this.map.centerAndZoom(e,19),this.initializedCenter=!0)}},{key:\"setZoom\",value:function(e){this.map.setZoom(e)}},{key:\"addEventHandler\",value:function(e,t){this.map.addEventListener(e,(function(e){var n=e.point;t(n)}))}},{key:\"createPoint\",value:function(e){var t=e.lat,n=e.lng;return new BMap.Point(n,t)}},{key:\"createMarker\",value:function(e,t){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],a=null;t&&(a=new BMap.Label(t,{point:e,offset:new BMap.Size(15,-15)}));var o=new BMap.Marker(e,{label:a,enableDragging:n,rotation:5});return o.setLabel(a),this.map.addOverlay(o),o}},{key:\"createPolyline\",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,a=arguments.length>3&&void 0!==arguments[3]?arguments[3]:2,o={geodesic:!0,strokeColor:t,strokeOpacity:n,strokeWeight:a},i=new BMap.Polyline(e,o);return this.map.addOverlay(i),i}},{key:\"createControl\",value:function(e){var t=e.text,n=e.tip,a=e.color,o=e.offsetX,i=e.offsetY,l=e.onClickHandler,r=new f(t,n,a,new BMap.Size(o,i),l);this.map.addControl(r),this.controls.push(r)}},{key:\"disableControls\",value:function(){var e=this;this.controls.forEach((function(t){e.map.removeControl(t)}))}},{key:\"enableControls\",value:function(){var e=this;this.controls.forEach((function(t){e.map.addControl(t)}))}},{key:\"getMarkerPosition\",value:function(e){return e.getPosition()}},{key:\"updatePolyline\",value:function(e,t){e.setPath(t)}},{key:\"removePolyline\",value:function(e){this.map.removeOverlay(e)}},{key:\"applyCoordinateOffset\",value:function(e){var t=(0,l.default)(e,2),n=t[0],a=t[1];return(0,d.WGS84ToBD09LL)(n,a)}}]),e}();t.default=p;var f=function(e){function t(e,n,i,l,r){var u;(0,s.default)(this,t);for(var d=arguments.length,c=Array(d>5?d-5:0),p=5;p<d;p++)c[p-5]=arguments[p];var f=(0,o.default)(this,(u=t.__proto__||(0,a.default)(t)).call.apply(u,[this].concat(c)));return f.defaultAnchor=BMAP_ANCHOR_TOP_LEFT,f.defaultOffset=l,f.onClickHandler=r,f.title=n,f.text=e,f.backgroundColor=i,f}return(0,i.default)(t,e),(0,u.default)(t,[{key:\"initialize\",value:function(e){var t=this,n=document.createElement(\"div\"),a=document.createElement(\"div\");a.style.backgroundColor=this.backgroundColor,a.style.border=\"2px solid #fff\",a.style.borderRadius=\"3px\",a.style.boxShadow=\"0 2px 6px rgba(0,0,0,.3)\",a.style.cursor=\"pointer\",a.style.marginBottom=\"22px\",a.style.textAlign=\"center\",a.title=this.title,n.appendChild(a);var o=document.createElement(\"div\");return o.style.color=\"rgb(25,25,25)\",o.style.fontFamily=\"Roboto,Arial,sans-serif\",o.style.fontSize=\"16px\",o.style.lineHeight=\"38px\",o.style.paddingLeft=\"5px\",o.style.paddingRight=\"5px\",o.innerHTML=this.text,a.appendChild(o),e.getContainer().appendChild(n),a.addEventListener(\"click\",(function(){t.onClickHandler(o)})),n}}]),t}(BMap.Control)}}]);"],"mappings":"AAAA","sourceRoot":""}
\ No newline at end of file
(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{473:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=r(n(36)),l=r(n(1)),a=r(n(2)),i=n(176);function r(e){return e&&e.__esModule?e:{default:e}}var s=function(){function e(){(0,l.default)(this,e),this.map=null,this.controls=[]}return(0,a.default)(e,[{key:"isInitialized",value:function(){return null!==this.map}},{key:"loadMap",value:function(e,t){var n={center:e,zoom:20,mapTypeId:google.maps.MapTypeId.ROADMAP,fullscreenControl:!1};this.map=new google.maps.Map(document.getElementById(t),n)}},{key:"setCenter",value:function(e){this.map.setCenter(e)}},{key:"setZoom",value:function(e){this.map.setZoom(e)}},{key:"addEventHandler",value:function(e,t){google.maps.event.addListener(this.map,e,(function(e){var n=e.latLng;t(n)}))}},{key:"createPoint",value:function(e){var t=e.lat,n=e.lng;return new google.maps.LatLng(t,n)}},{key:"createMarker",value:function(e,t){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],o=new google.maps.Marker({position:e,label:t,draggable:n,map:this.map});return o}},{key:"createPolyline",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:2,l=new google.maps.Polyline({path:e,geodesic:!0,strokeColor:t,strokeOpacity:n,strokeWeight:o,map:this.map});return l}},{key:"createControl",value:function(e){var t=e.text,n=e.tip,o=e.color,l=(e.offsetX,e.offsetY,e.onClickHandler),a=document.createElement("div"),i=document.createElement("div");i.style.backgroundColor=o,i.style.border="2px solid #fff",i.style.borderRadius="3px",i.style.boxShadow="0 2px 6px rgba(0,0,0,.3)",i.style.cursor="pointer",i.style.marginBottom="22px",i.style.textAlign="center",i.title=n,a.appendChild(i);var r=document.createElement("div");r.style.color="rgb(25,25,25)",r.style.fontFamily="Roboto,Arial,sans-serif",r.style.fontSize="16px",r.style.lineHeight="38px",r.style.paddingLeft="5px",r.style.paddingRight="5px",r.innerHTML=t,i.appendChild(r),i.addEventListener("click",(function(){l(r)})),this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(a),this.controls.push(a)}},{key:"disableControls",value:function(){this.controls.forEach((function(e){e.style.display="none"}))}},{key:"enableControls",value:function(){this.controls.forEach((function(e){e.style.display="block"}))}},{key:"getMarkerPosition",value:function(e){var t=e.getPosition();return{lat:t.lat(),lng:t.lng()}}},{key:"updatePolyline",value:function(e,t){e.setPath(t)}},{key:"removePolyline",value:function(e){e.setMap(null)}},{key:"applyCoordinateOffset",value:function(e){var t=(0,o.default)(e,2),n=t[0],l=t[1];return(0,i.WGS84ToGCJ02)(n,l)}}]),e}();t.default=s}}]);
(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{474:function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var o=r(n(36)),l=r(n(1)),a=r(n(2)),i=n(176);function r(e){return e&&e.__esModule?e:{default:e}}var s=function(){function e(){(0,l.default)(this,e),this.map=null,this.controls=[]}return(0,a.default)(e,[{key:"isInitialized",value:function(){return null!==this.map}},{key:"loadMap",value:function(e,t){var n={center:e,zoom:20,mapTypeId:google.maps.MapTypeId.ROADMAP,fullscreenControl:!1};this.map=new google.maps.Map(document.getElementById(t),n)}},{key:"setCenter",value:function(e){this.map.setCenter(e)}},{key:"setZoom",value:function(e){this.map.setZoom(e)}},{key:"addEventHandler",value:function(e,t){google.maps.event.addListener(this.map,e,(function(e){var n=e.latLng;t(n)}))}},{key:"createPoint",value:function(e){var t=e.lat,n=e.lng;return new google.maps.LatLng(t,n)}},{key:"createMarker",value:function(e,t){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],o=new google.maps.Marker({position:e,label:t,draggable:n,map:this.map});return o}},{key:"createPolyline",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:2,l=new google.maps.Polyline({path:e,geodesic:!0,strokeColor:t,strokeOpacity:n,strokeWeight:o,map:this.map});return l}},{key:"createControl",value:function(e){var t=e.text,n=e.tip,o=e.color,l=(e.offsetX,e.offsetY,e.onClickHandler),a=document.createElement("div"),i=document.createElement("div");i.style.backgroundColor=o,i.style.border="2px solid #fff",i.style.borderRadius="3px",i.style.boxShadow="0 2px 6px rgba(0,0,0,.3)",i.style.cursor="pointer",i.style.marginBottom="22px",i.style.textAlign="center",i.title=n,a.appendChild(i);var r=document.createElement("div");r.style.color="rgb(25,25,25)",r.style.fontFamily="Roboto,Arial,sans-serif",r.style.fontSize="16px",r.style.lineHeight="38px",r.style.paddingLeft="5px",r.style.paddingRight="5px",r.innerHTML=t,i.appendChild(r),i.addEventListener("click",(function(){l(r)})),this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(a),this.controls.push(a)}},{key:"disableControls",value:function(){this.controls.forEach((function(e){e.style.display="none"}))}},{key:"enableControls",value:function(){this.controls.forEach((function(e){e.style.display="block"}))}},{key:"getMarkerPosition",value:function(e){var t=e.getPosition();return{lat:t.lat(),lng:t.lng()}}},{key:"updatePolyline",value:function(e,t){e.setPath(t)}},{key:"removePolyline",value:function(e){e.setMap(null)}},{key:"applyCoordinateOffset",value:function(e){var t=(0,o.default)(e,2),n=t[0],l=t[1];return(0,i.WGS84ToGCJ02)(n,l)}}]),e}();t.default=s}}]);
//# sourceMappingURL=4.bundle.js.map
\ No newline at end of file
{"version":3,"file":"4.bundle.js","sources":["webpack:///4.bundle.js"],"sourcesContent":["(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{473:function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.default=void 0;var o=r(n(36)),l=r(n(1)),a=r(n(2)),i=n(176);function r(e){return e&&e.__esModule?e:{default:e}}var s=function(){function e(){(0,l.default)(this,e),this.map=null,this.controls=[]}return(0,a.default)(e,[{key:\"isInitialized\",value:function(){return null!==this.map}},{key:\"loadMap\",value:function(e,t){var n={center:e,zoom:20,mapTypeId:google.maps.MapTypeId.ROADMAP,fullscreenControl:!1};this.map=new google.maps.Map(document.getElementById(t),n)}},{key:\"setCenter\",value:function(e){this.map.setCenter(e)}},{key:\"setZoom\",value:function(e){this.map.setZoom(e)}},{key:\"addEventHandler\",value:function(e,t){google.maps.event.addListener(this.map,e,(function(e){var n=e.latLng;t(n)}))}},{key:\"createPoint\",value:function(e){var t=e.lat,n=e.lng;return new google.maps.LatLng(t,n)}},{key:\"createMarker\",value:function(e,t){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],o=new google.maps.Marker({position:e,label:t,draggable:n,map:this.map});return o}},{key:\"createPolyline\",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:2,l=new google.maps.Polyline({path:e,geodesic:!0,strokeColor:t,strokeOpacity:n,strokeWeight:o,map:this.map});return l}},{key:\"createControl\",value:function(e){var t=e.text,n=e.tip,o=e.color,l=(e.offsetX,e.offsetY,e.onClickHandler),a=document.createElement(\"div\"),i=document.createElement(\"div\");i.style.backgroundColor=o,i.style.border=\"2px solid #fff\",i.style.borderRadius=\"3px\",i.style.boxShadow=\"0 2px 6px rgba(0,0,0,.3)\",i.style.cursor=\"pointer\",i.style.marginBottom=\"22px\",i.style.textAlign=\"center\",i.title=n,a.appendChild(i);var r=document.createElement(\"div\");r.style.color=\"rgb(25,25,25)\",r.style.fontFamily=\"Roboto,Arial,sans-serif\",r.style.fontSize=\"16px\",r.style.lineHeight=\"38px\",r.style.paddingLeft=\"5px\",r.style.paddingRight=\"5px\",r.innerHTML=t,i.appendChild(r),i.addEventListener(\"click\",(function(){l(r)})),this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(a),this.controls.push(a)}},{key:\"disableControls\",value:function(){this.controls.forEach((function(e){e.style.display=\"none\"}))}},{key:\"enableControls\",value:function(){this.controls.forEach((function(e){e.style.display=\"block\"}))}},{key:\"getMarkerPosition\",value:function(e){var t=e.getPosition();return{lat:t.lat(),lng:t.lng()}}},{key:\"updatePolyline\",value:function(e,t){e.setPath(t)}},{key:\"removePolyline\",value:function(e){e.setMap(null)}},{key:\"applyCoordinateOffset\",value:function(e){var t=(0,o.default)(e,2),n=t[0],l=t[1];return(0,i.WGS84ToGCJ02)(n,l)}}]),e}();t.default=s}}]);"],"mappings":"AAAA","sourceRoot":""}
\ No newline at end of file
{"version":3,"file":"4.bundle.js","sources":["webpack:///4.bundle.js"],"sourcesContent":["(window.webpackJsonp=window.webpackJsonp||[]).push([[4],{474:function(e,t,n){\"use strict\";Object.defineProperty(t,\"__esModule\",{value:!0}),t.default=void 0;var o=r(n(36)),l=r(n(1)),a=r(n(2)),i=n(176);function r(e){return e&&e.__esModule?e:{default:e}}var s=function(){function e(){(0,l.default)(this,e),this.map=null,this.controls=[]}return(0,a.default)(e,[{key:\"isInitialized\",value:function(){return null!==this.map}},{key:\"loadMap\",value:function(e,t){var n={center:e,zoom:20,mapTypeId:google.maps.MapTypeId.ROADMAP,fullscreenControl:!1};this.map=new google.maps.Map(document.getElementById(t),n)}},{key:\"setCenter\",value:function(e){this.map.setCenter(e)}},{key:\"setZoom\",value:function(e){this.map.setZoom(e)}},{key:\"addEventHandler\",value:function(e,t){google.maps.event.addListener(this.map,e,(function(e){var n=e.latLng;t(n)}))}},{key:\"createPoint\",value:function(e){var t=e.lat,n=e.lng;return new google.maps.LatLng(t,n)}},{key:\"createMarker\",value:function(e,t){var n=!(arguments.length>2&&void 0!==arguments[2])||arguments[2],o=new google.maps.Marker({position:e,label:t,draggable:n,map:this.map});return o}},{key:\"createPolyline\",value:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:1,o=arguments.length>3&&void 0!==arguments[3]?arguments[3]:2,l=new google.maps.Polyline({path:e,geodesic:!0,strokeColor:t,strokeOpacity:n,strokeWeight:o,map:this.map});return l}},{key:\"createControl\",value:function(e){var t=e.text,n=e.tip,o=e.color,l=(e.offsetX,e.offsetY,e.onClickHandler),a=document.createElement(\"div\"),i=document.createElement(\"div\");i.style.backgroundColor=o,i.style.border=\"2px solid #fff\",i.style.borderRadius=\"3px\",i.style.boxShadow=\"0 2px 6px rgba(0,0,0,.3)\",i.style.cursor=\"pointer\",i.style.marginBottom=\"22px\",i.style.textAlign=\"center\",i.title=n,a.appendChild(i);var r=document.createElement(\"div\");r.style.color=\"rgb(25,25,25)\",r.style.fontFamily=\"Roboto,Arial,sans-serif\",r.style.fontSize=\"16px\",r.style.lineHeight=\"38px\",r.style.paddingLeft=\"5px\",r.style.paddingRight=\"5px\",r.innerHTML=t,i.appendChild(r),i.addEventListener(\"click\",(function(){l(r)})),this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(a),this.controls.push(a)}},{key:\"disableControls\",value:function(){this.controls.forEach((function(e){e.style.display=\"none\"}))}},{key:\"enableControls\",value:function(){this.controls.forEach((function(e){e.style.display=\"block\"}))}},{key:\"getMarkerPosition\",value:function(e){var t=e.getPosition();return{lat:t.lat(),lng:t.lng()}}},{key:\"updatePolyline\",value:function(e,t){e.setPath(t)}},{key:\"removePolyline\",value:function(e){e.setMap(null)}},{key:\"applyCoordinateOffset\",value:function(e){var t=(0,o.default)(e,2),n=t[0],l=t[1];return(0,i.WGS84ToGCJ02)(n,l)}}]),e}();t.default=s}}]);"],"mappings":"AAAA","sourceRoot":""}
\ No newline at end of file
{
"version": "5.0.0",
"version": "5.5.0",
"name": "dreamview",
"description": "Visualization of the Apollo simulator.",
"icons": {
......
{
"version": "5.0.0",
"version": "5.5.0",
"api_version": 1,
"layout": {
"logo": "/icons/yandex-browser-50x50.png",
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
因为 它太大了无法显示 source diff 。你可以改为 查看blob
{
"name": "dreamview",
"version": "5.0.0",
"version": "5.5.0",
"description": "Visualization of the Apollo simulator.",
"main": "app.js",
"author": "adu-sim",
"license": "Apache-2.0",
"engines": {
"npm": ">=5.6.0",
"node": ">=8.11.1"
"npm": ">6.14.5",
"node": ">=12.18.1"
},
"scripts": {
"build": "./setup.sh; node_modules/.bin/webpack --progress --mode=production",
"start": "./setup.sh; node_modules/.bin/webpack-dev-server --progress --mode=development --watch-poll",
"build_offline": "./setup.sh; node_modules/.bin/webpack -p --progress --config webpack.offline.config.js",
"start_offline": "./setup.sh; node_modules/.bin/webpack-dev-server --watch-poll --config webpack.offline.config.js"
"start_offline": "./setup.sh; node_modules/.bin/webpack-dev-server --watch-poll --config webpack.offline.config.js",
"lint": "./node_modules/eslint/bin/eslint.js src",
"lint-fix": "./node_modules/eslint/bin/eslint.js --fix src"
},
"dependencies": {
"chart.js": "^2.7.0",
......@@ -33,7 +35,7 @@
"react-rangeslider": "^2.2.0",
"react-split-pane": "^0.1.66",
"react-tabs": "^2.2.1",
"react-tooltip": "^3.8.1",
"react-tooltip": "4.2.5",
"recorder-js": "^1.0.7",
"stats.js": "^0.17.0",
"styled-components": "^4.1.3",
......@@ -42,7 +44,7 @@
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-eslint": "^7.2.3",
"babel-eslint": "10.0.1",
"babel-loader": "^7.1.5",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-runtime": "^6.23.0",
......@@ -51,9 +53,14 @@
"babel-preset-stage-0": "^6.24.1",
"copy-webpack-plugin": "^5.1.0",
"css-loader": "^0.28.2",
"eslint": "^4.18.2",
"eslint-loader": "^2.0.0",
"eslint-plugin-react": "^7.0.1",
"eslint": "7.2.0",
"eslint-config-airbnb": "18.2.0",
"eslint-import-resolver-webpack": "^0.12.2",
"eslint-loader": "4.0.2",
"eslint-plugin-import": "^2.21.2",
"eslint-plugin-jsx-a11y": "^6.3.0",
"eslint-plugin-react": "^7.20.0",
"eslint-plugin-react-hooks": "4.0.0",
"favicons-webpack-plugin": "^3.0.1",
"file-loader": "^1.1.11",
"html-webpack-plugin": "4.0.0",
......@@ -73,6 +80,7 @@
},
"resolutions": {
"js-yaml": "^3.13.1",
"**/kind-of": "^6.0.3"
"**/kind-of": "^6.0.3",
"@babel/parser": "7.7.5"
}
}
/* import "whatwg-fetch";
* import "font-awesome-webpack";*/
import * as ReactDOM from 'react-dom';
import React from 'react';
import { Provider } from 'mobx-react';
import * as ReactDOM from "react-dom";
import React from "react";
import { Provider } from "mobx-react";
import "styles/main.scss";
import STORE from "store";
import Dreamview from "components/Dreamview";
import 'styles/main.scss';
import STORE from 'store';
import Dreamview from 'components/Dreamview';
ReactDOM.render(
<Provider store={STORE}>
<Dreamview />
</Provider>,
document.getElementById("root")
document.getElementById('root'),
);
......@@ -2,121 +2,127 @@ import React, { Component } from 'react';
import ReactTooltip from 'react-tooltip';
import { inject, observer } from 'mobx-react';
import positionIcon from "assets/images/icons/position.png";
import rotationIcon from "assets/images/icons/rotation.png";
import positionIcon from 'assets/images/icons/position.png';
import rotationIcon from 'assets/images/icons/rotation.png';
const ResetSvg = () => (
<svg viewBox="0 0 1024 1024" width="20" height="20" fill="#999999">
<path d="M978.637 890.58H178.116V1024L0 846.551l176.115-174.78v133.42H933.94c29.353 0 44.696-12.008 44.696-41.36V496.99l88.725-141.426V800.52a88.724 88.724 0 0 1-88.725 88.058z m-88.724-667.101H133.42c-29.352 0-44.696 12.008-44.696 42.027v268.175L0 673.105v-450.96a88.724 88.724 0 0 1 88.724-88.725h800.522V0l178.116 178.116-176.115 176.115V220.81z"></path>
<path d="M978.637 890.58H178.116V1024L0 846.551l176.115-174.78v133.42H933.94c29.353 0 44.696-12.008 44.696-41.36V496.99l88.725-141.426V800.52a88.724 88.724 0 0 1-88.725 88.058z m-88.724-667.101H133.42c-29.352 0-44.696 12.008-44.696 42.027v268.175L0 673.105v-450.96a88.724 88.724 0 0 1 88.724-88.725h800.522V0l178.116 178.116-176.115 176.115V220.81z" />
</svg>
);
const UpArrowSvg = ({onClick}) => (
const UpArrowSvg = ({ onClick }) => (
<svg viewBox="0 0 1024 1024" width="15" height="15" onClick={onClick} fill="#999999">
<path d="M820.00415442 790.08350547l-617.53286931-1e-8c-34.17530758 0-61.8167847-27.4267503-61.81678473-61.59899038 0-15.89285244 6.0951742-30.25807684 15.89285244-41.14165922l305.39062223-407.4809563c20.4634662-26.98809409 58.98852574-32.65074716 86.20054921-12.19034849 4.79147569 3.48470957 8.92343326 7.61973466 12.19034848 12.19034849L869.19806953 691.69567529c20.24260435 26.99116162 14.79774561 65.73401549-12.40814284 85.97968733C845.68548239 786.16627474 832.84481844 790.08350547 820.00415442 790.08350547L820.00415442 790.08350547z"></path>
<path d="M820.00415442 790.08350547l-617.53286931-1e-8c-34.17530758 0-61.8167847-27.4267503-61.81678473-61.59899038 0-15.89285244 6.0951742-30.25807684 15.89285244-41.14165922l305.39062223-407.4809563c20.4634662-26.98809409 58.98852574-32.65074716 86.20054921-12.19034849 4.79147569 3.48470957 8.92343326 7.61973466 12.19034848 12.19034849L869.19806953 691.69567529c20.24260435 26.99116162 14.79774561 65.73401549-12.40814284 85.97968733C845.68548239 786.16627474 832.84481844 790.08350547 820.00415442 790.08350547L820.00415442 790.08350547z" />
</svg>
);
const DownArrowSvg = ({onClick}) => (
const DownArrowSvg = ({ onClick }) => (
<svg viewBox="0 0 1024 1024" width="15" height="15" onClick={onClick} fill="#999999">
<path d="M151.477 199.554l718.53099999 0c39.763 0 71.922 31.91 71.92200002 71.674 0 18.485-7.096 35.206-18.48600001 47.872l-355.33 474.125c-23.81 31.4-68.641 37.994-100.297 14.183-5.571-4.052-10.385-8.873-14.183-14.19l-359.398-479.178c-23.547-31.407-17.217-76.48 14.43699999-100.041 12.922-9.881 27.865-14.438 42.80500001-14.439v0l0-0.007zM151.477 199.554z"></path>
<path d="M151.477 199.554l718.53099999 0c39.763 0 71.922 31.91 71.92200002 71.674 0 18.485-7.096 35.206-18.48600001 47.872l-355.33 474.125c-23.81 31.4-68.641 37.994-100.297 14.183-5.571-4.052-10.385-8.873-14.183-14.19l-359.398-479.178c-23.547-31.407-17.217-76.48 14.43699999-100.041 12.922-9.881 27.865-14.438 42.80500001-14.439v0l0-0.007zM151.477 199.554z" />
</svg>
);
const FIELDS = {
Position: {
X: 'x',
Y: 'y',
Z: 'z'
},
StaticRotation: {
Pitch: 'x',
Yaw: 'y',
Roll: 'z'
},
DynamicRotation: {
Pitch: 'y',
Yaw: 'z',
Roll: 'x'
}
Position: {
X: 'x',
Y: 'y',
Z: 'z',
},
StaticRotation: {
Pitch: 'x',
Yaw: 'y',
Roll: 'z',
},
DynamicRotation: {
Pitch: 'y',
Yaw: 'z',
Roll: 'x',
},
};
@inject("store") @observer
@inject('store') @observer
export default class CameraParam extends Component {
constructor(props) {
super(props);
this.resetParam = this.resetParam.bind(this);
constructor(props) {
super(props);
this.resetParam = this.resetParam.bind(this);
}
resetParam() {
this.props.store.cameraData.reset();
}
renderParamRow(type) {
function getDeltaColorAndText(delta) {
let color = '#FFFFFF';
let text = '-';
if (delta > 0) {
color = '#1C9063';
text = `+${delta}`;
} else if (delta < 0) {
color = '#B43131';
text = delta;
}
return { color, text };
}
resetParam() {
this.props.store.cameraData.reset();
const { cameraData } = this.props.store;
let step = undefined;
switch (type) {
case 'Position': {
step = 2;
break;
}
case 'StaticRotation':
case 'DynamicRotation': {
step = 3;
break;
}
default:
console.warn('Unknown parameter type:', type);
return null;
}
renderParamRow(type) {
function getDeltaColorAndText(delta) {
let color = '#FFFFFF';
let text = '-';
if (delta > 0) {
color = '#1C9063';
text = `+${delta}`;
} else if (delta < 0) {
color = '#B43131';
text = delta;
}
return {color, text};
};
const { cameraData } = this.props.store;
let step = undefined;
switch (type) {
case 'Position': {
step = 2;
break;
};
case 'StaticRotation':
case 'DynamicRotation': {
step = 3;
break;
}
default:
console.warn('Unknown parameter type:', type);
return null;
}
const rows = Object.keys(FIELDS[type]).map((field) => {
const axis = FIELDS[type][field];
const adjustStep = Math.pow(0.1, step);
const value = cameraData[`init${type}`].get(axis).toFixed(step);
const delta = cameraData[`delta${type}`].get(axis).toFixed(step);
const { color, text } = getDeltaColorAndText(delta);
return (
const rows = Object.keys(FIELDS[type]).map((field) => {
const axis = FIELDS[type][field];
const adjustStep = Math.pow(0.1, step);
const value = cameraData[`init${type}`].get(axis).toFixed(step);
const delta = cameraData[`delta${type}`].get(axis).toFixed(step);
const { color, text } = getDeltaColorAndText(delta);
return (
<div className="camera-param-row" key={`${type}_${field}`}>
<div className="field">{field}</div>
<div className="value">{value}</div>
<div className="delta" style={{color}}>{text}</div>
<div className="delta" style={{ color }}>{text}</div>
<div className="action">
<UpArrowSvg onClick={() => cameraData.update(
type, axis, adjustStep)} />
type, axis, adjustStep,
)}
/>
<DownArrowSvg onClick={() => cameraData.update(
type, axis, (-1) * adjustStep)} />
type, axis, (-1) * adjustStep,
)}
/>
</div>
</div>
);
});
);
});
return rows;
}
return rows;
}
renderCameraParam() {
return (
renderCameraParam() {
return (
<div className="monitor-content">
<div className="section">
<div className="section-title"
data-tip="Camera position in world coordinate system"
data-for="param">
<div
className="section-title"
data-tip="Camera position in world coordinate system"
data-for="param"
>
<img height="20px" width="20px" src={positionIcon} />
<span>Position</span>
</div>
......@@ -129,17 +135,21 @@ export default class CameraParam extends Component {
<img height="18px" width="20px" src={rotationIcon} />
<span>Rotation</span>
</div>
<div className="section-subtitle"
data-tip="Camera rotation in IMU coordinate system, default facing to Z negative direction"
data-for="param">
<div
className="section-subtitle"
data-tip="Camera rotation in IMU coordinate system, default facing to Z negative direction"
data-for="param"
>
Static
</div>
<div className="section-content">
{this.renderParamRow('StaticRotation')}
</div>
<div className="section-subtitle"
data-tip="IMU rotation in world coordinate system"
data-for="param">
<div
className="section-subtitle"
data-tip="IMU rotation in world coordinate system"
data-for="param"
>
Dynamic
</div>
<div className="section-content">
......@@ -148,17 +158,21 @@ export default class CameraParam extends Component {
</div>
<ReactTooltip id="param" place="right" delayShow={300} multiline />
</div>
);
}
);
}
render() {
return (
render() {
return (
<div className="monitor camera-param">
<div className="monitor-header">
<div className="title">Camera Parameter</div>
<div className="actions">
<div className="action" onClick={this.resetParam} data-tip="Reset"
data-for="action">
<div
className="action"
onClick={this.resetParam}
data-tip="Reset"
data-for="action"
>
<ResetSvg />
</div>
<ReactTooltip id="action" place="left" delayShow={100} />
......@@ -166,6 +180,6 @@ export default class CameraParam extends Component {
</div>
{this.renderCameraParam()}
</div>
);
}
);
}
}
import React from "react";
import { observer } from "mobx-react";
import classNames from "classnames";
import React from 'react';
import { observer } from 'mobx-react';
import classNames from 'classnames';
@observer
export default class ScenarioCollectionMonitor extends React.Component {
renderCategoryProgress(description, progressInPercentage, isUpdated, isCompleted) {
return (
renderCategoryProgress(description, progressInPercentage, isUpdated, isCompleted) {
return (
<div key={description} className="category">
<div className={classNames({
"category-description": true,
"category-updated": isUpdated,
})}>{description}</div>
'category-description': true,
'category-updated': isUpdated,
})}
>
{description}
</div>
<div className="category-progress-background">
<span className={isCompleted
? "category-completed" : "category-in-progress"}
style={{ width: progressInPercentage + "%" }} />
<span
className={isCompleted
? 'category-completed' : 'category-in-progress'}
style={{ width: `${progressInPercentage}%` }}
/>
</div>
</div>
);
}
);
}
render() {
const { statusMap, progressMap } = this.props;
render() {
const { statusMap, progressMap } = this.props;
const inProgressCategories = [];
const completedCategories = [];
statusMap.forEach((isUpdated, description) => {
const progressInPercentage = progressMap.get(description);
const isCompleted = progressInPercentage >= 100.0;
const element = this.renderCategoryProgress(
description, progressInPercentage, isUpdated, isCompleted);
const inProgressCategories = [];
const completedCategories = [];
statusMap.forEach((isUpdated, description) => {
const progressInPercentage = progressMap.get(description);
const isCompleted = progressInPercentage >= 100.0;
const element = this.renderCategoryProgress(
description, progressInPercentage, isUpdated, isCompleted,
);
if (isCompleted) {
completedCategories.push(element);
} else {
inProgressCategories.push(element);
}
});
if (isCompleted) {
completedCategories.push(element);
} else {
inProgressCategories.push(element);
}
});
// To make sure the category in the last row has the width that
// matches the rest, adding a dummy category that shows nothing
// but helps flex-box adjusts the width correctly.
if (inProgressCategories.length % 2 === 1) {
inProgressCategories.push(<div className="dummy-category" key="in-progress-dummy" />);
}
if (completedCategories.length % 2 === 1) {
completedCategories.push(<div className="dummy-category" key="completed-dummy" />);
}
// To make sure the category in the last row has the width that
// matches the rest, adding a dummy category that shows nothing
// but helps flex-box adjusts the width correctly.
if (inProgressCategories.length % 2 === 1) {
inProgressCategories.push(<div className="dummy-category" key="in-progress-dummy" />);
}
if (completedCategories.length % 2 === 1) {
completedCategories.push(<div className="dummy-category" key="completed-dummy" />);
}
return (
return (
<div className="scenario-container">
<div className="category-container">
{inProgressCategories}
</div>
{completedCategories.length > 0 &&
<div className="category-container section-divider-on-top">
{completedCategories}
</div>
}
{completedCategories.length > 0
&& (
<div className="category-container section-divider-on-top">
{completedCategories}
</div>
)}
</div>
);
}
);
}
}
import React from "react";
import { Tab, Tabs, TabList, TabPanel } from "react-tabs";
import { observer } from "mobx-react";
import React from 'react';
import {
Tab, Tabs, TabList, TabPanel,
} from 'react-tabs';
import { observer } from 'mobx-react';
import ScenarioCollectionMonitor from "components/DataCollectionMonitor/ScenarioCollectionMonitor";
import ScenarioCollectionMonitor from 'components/DataCollectionMonitor/ScenarioCollectionMonitor';
@observer
export default class DataCollectionMonitor extends React.Component {
render() {
const { dataCollectionUpdateStatus, dataCollectionProgress } = this.props;
render() {
const { dataCollectionUpdateStatus, dataCollectionProgress } = this.props;
if (!dataCollectionProgress || dataCollectionUpdateStatus.size === 0) {
return <div className="no-data">No Data Found</div>;
}
if (!dataCollectionProgress || dataCollectionUpdateStatus.size === 0) {
return <div className="no-data">No Data Found</div>;
}
const tabs = [];
const tabPanels = [];
dataCollectionProgress.entries().forEach(([scenarioName, categories]) => {
tabs.push(<Tab key={scenarioName}>{scenarioName}</Tab>);
const tabs = [];
const tabPanels = [];
dataCollectionProgress.entries().forEach(([scenarioName, categories]) => {
tabs.push(<Tab key={scenarioName}>{scenarioName}</Tab>);
tabPanels.push(
tabPanels.push(
<TabPanel key={scenarioName}>
<ScenarioCollectionMonitor
statusMap={dataCollectionUpdateStatus.get(scenarioName)}
progressMap={categories} />
</TabPanel>
);
});
progressMap={categories}
/>
</TabPanel>,
);
});
return (
return (
<div className="monitor data-collection-monitor">
<Tabs>
<TabList>{tabs}</TabList>
{tabPanels}
</Tabs>
</div>
);
}
);
}
}
import React from "react";
import protobuf from "protobufjs/light";
import classNames from "classnames";
import _ from "lodash";
import React from 'react';
import protobuf from 'protobufjs/light';
import classNames from 'classnames';
import _ from 'lodash';
import STORE from "store";
import WS from "store/websocket";
import PortalModal from "components/common/PortalModal";
import CheckboxItem from "components/common/CheckboxItem";
import STORE from 'store';
import WS from 'store/websocket';
import PortalModal from 'components/common/PortalModal';
import CheckboxItem from 'components/common/CheckboxItem';
const simWorldRoot = protobuf.Root.fromJSON(require("proto_bundle/sim_world_proto_bundle.json"));
const DriveEventType = simWorldRoot.lookup("apollo.common.DriveEvent.Type").values;
const simWorldRoot = protobuf.Root.fromJSON(require('proto_bundle/sim_world_proto_bundle.json'));
const DriveEventType = simWorldRoot.lookup('apollo.common.DriveEvent.Type').values;
export default class DriveEventEditor extends React.Component {
constructor(props) {
super(props);
this.state = {
eventTime: new Date(STORE.timestamp),
eventMessage: "",
eventTypes: new Set(),
popupReminder: this.props.newDisengagementReminder,
isReportable: false,
};
this.handleMessageChange = this.handleMessageChange.bind(this);
this.handleTimestampUpdate = this.handleTimestampUpdate.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.toggleTicket = this.toggleTicket.bind(this);
this.setTextareaRef = (element) => {
this.textareaElement = element;
};
constructor(props) {
super(props);
this.state = {
eventTime: new Date(STORE.timestamp),
eventMessage: '',
eventTypes: new Set(),
popupReminder: this.props.newDisengagementReminder,
isReportable: false,
};
this.handleMessageChange = this.handleMessageChange.bind(this);
this.handleTimestampUpdate = this.handleTimestampUpdate.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleCancel = this.handleCancel.bind(this);
this.toggleTicket = this.toggleTicket.bind(this);
this.setTextareaRef = (element) => {
this.textareaElement = element;
};
}
componentWillReceiveProps(nextProps) {
if (nextProps.newDisengagementReminder) {
this.handleTimestampUpdate();
this.setState({ popupReminder: true });
}
}
componentWillReceiveProps(nextProps) {
if (nextProps.newDisengagementReminder) {
this.handleTimestampUpdate();
this.setState({ popupReminder: true });
}
}
handleMessageChange(event) {
this.setState({ eventMessage: event.target.value });
}
handleMessageChange(event) {
this.setState({ eventMessage: event.target.value });
}
handleTimestampUpdate() {
this.setState({ eventTime: new Date(STORE.timestamp) });
}
handleTimestampUpdate() {
this.setState({ eventTime: new Date(STORE.timestamp) });
handleSubmit(event) {
event.preventDefault();
if (!this.state.eventMessage) {
return alert('Please provide a drive event message.');
}
handleSubmit(event) {
event.preventDefault();
if (!this.state.eventMessage) {
return alert("Please provide a drive event message.");
}
if (!this.state.eventTypes.size) {
return alert("Please select at least one event type.");
}
WS.submitDriveEvent(
this.state.eventTime.getTime(),
this.state.eventMessage,
this.state.eventTypes,
this.state.isReportable,
);
STORE.handleOptionToggle('showDataRecorder');
if (!this.state.eventTypes.size) {
return alert('Please select at least one event type.');
}
handleCancel() {
STORE.handleOptionToggle('showDataRecorder');
WS.submitDriveEvent(
this.state.eventTime.getTime(),
this.state.eventMessage,
this.state.eventTypes,
this.state.isReportable,
);
STORE.handleOptionToggle('showDataRecorder');
}
handleCancel() {
STORE.handleOptionToggle('showDataRecorder');
}
handleEventTypeSelection(type) {
const eventTypes = this.state.eventTypes;
if (eventTypes.has(type)) {
eventTypes.delete(type);
} else {
eventTypes.add(type);
}
handleEventTypeSelection(type) {
const eventTypes = this.state.eventTypes;
if (eventTypes.has(type)) {
eventTypes.delete(type);
} else {
eventTypes.add(type);
}
this.setState({ eventTypes: new Set(eventTypes) });
}
toggleTicket() {
this.setState((prevState) => {
return { isReportable: !prevState.isReportable };
});
}
renderTypeCheckBox() {
const typeCheckbox = Object.keys(DriveEventType).map(type => {
return (
<button
key={type}
onClick={this.handleEventTypeSelection.bind(this, type)}
className={classNames({
"drive-event-type-button": true,
"drive-event-type-button-active": this.state.eventTypes.has(type),
})}
>
{_.startCase(_.lowerCase(type))}
</button>
);
});
return typeCheckbox;
}
render() {
return (
this.setState({ eventTypes: new Set(eventTypes) });
}
toggleTicket() {
this.setState((prevState) => ({ isReportable: !prevState.isReportable }));
}
renderTypeCheckBox() {
const typeCheckbox = Object.keys(DriveEventType).map((type) => (
<button
key={type}
onClick={this.handleEventTypeSelection.bind(this, type)}
className={classNames({
'drive-event-type-button': true,
'drive-event-type-button-active': this.state.eventTypes.has(type),
})}
>
{_.startCase(_.lowerCase(type))}
</button>
));
return typeCheckbox;
}
render() {
return (
<div className="card data-recorder">
<div className="card-header">
<span>Add Drive Event</span>
......@@ -121,7 +117,8 @@ export default class DriveEventEditor extends React.Component {
{this.state.eventTime.toString()}
<button
className="timestamp-button"
onClick={this.handleTimestampUpdate} >
onClick={this.handleTimestampUpdate}
>
Update Time
</button>
</span>
......@@ -139,7 +136,8 @@ export default class DriveEventEditor extends React.Component {
ref={this.setTextareaRef}
placeholder="please enter a message..."
value={this.state.eventMessage}
onChange={this.handleMessageChange} />
onChange={this.handleMessageChange}
/>
</td>
</tr>
<tr className="drive-event-row">
......@@ -154,12 +152,16 @@ export default class DriveEventEditor extends React.Component {
/>
</span>
<span>
<button className="cancel-button"
onClick={this.handleCancel}>
<button
className="cancel-button"
onClick={this.handleCancel}
>
Cancel
</button>
<button className="submit-button"
onClick={this.handleSubmit}>
<button
className="submit-button"
onClick={this.handleSubmit}
>
Submit
</button>
</span>
......@@ -171,15 +173,16 @@ export default class DriveEventEditor extends React.Component {
<PortalModal
open={this.state.popupReminder}
onClose={() => {
this.setState({ popupReminder: false });
this.textareaElement.focus();
}} >
this.setState({ popupReminder: false });
this.textareaElement.focus();
}}
>
<div className="codriver-msg">
<p>Disengagement found. </p>
<p>Please record a drive event.</p>
</div>
</PortalModal>
</div>
);
}
);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import React from 'react';
import { inject, observer } from 'mobx-react';
import SplitPane from 'react-split-pane';
import Header from "components/Header";
import MainView from "components/Layouts/MainView";
import ToolView from "components/Layouts/ToolView";
import MonitorPanel from "components/Layouts/MonitorPanel";
import SideBar from "components/SideBar";
import Header from 'components/Header';
import MainView from 'components/Layouts/MainView';
import ToolView from 'components/Layouts/ToolView';
import MonitorPanel from 'components/Layouts/MonitorPanel';
import SideBar from 'components/SideBar';
import HOTKEYS_CONFIG from "store/config/hotkeys.yml";
import WS, { MAP_WS, POINT_CLOUD_WS, CAMERA_WS } from "store/websocket";
import HOTKEYS_CONFIG from 'store/config/hotkeys.yml';
import WS, { MAP_WS, POINT_CLOUD_WS, CAMERA_WS } from 'store/websocket';
@inject("store") @observer
@inject('store') @observer
export default class Dreamview extends React.Component {
constructor(props) {
super(props);
this.handleDrag = this.handleDrag.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
this.updateDimension = this.props.store.dimension.update.bind(this.props.store.dimension);
}
constructor(props) {
super(props);
this.handleDrag = this.handleDrag.bind(this);
this.handleKeyPress = this.handleKeyPress.bind(this);
this.updateDimension = this.props.store.dimension.update.bind(this.props.store.dimension);
}
handleDrag(masterViewWidth) {
const { options, dimension } = this.props.store;
if (options.showMonitor) {
dimension.updateMonitorWidth(
Math.min(
Math.max(window.innerWidth - masterViewWidth, 0),
window.innerWidth
)
);
}
handleDrag(masterViewWidth) {
const { options, dimension } = this.props.store;
if (options.showMonitor) {
dimension.updateMonitorWidth(
Math.min(
Math.max(window.innerWidth - masterViewWidth, 0),
window.innerWidth,
),
);
}
}
handleKeyPress(event) {
const { options, enableHMIButtonsOnly, hmi } = this.props.store;
handleKeyPress(event) {
const { options, enableHMIButtonsOnly, hmi } = this.props.store;
const optionName = HOTKEYS_CONFIG[event.key];
if (!optionName || options.showDataRecorder) {
return;
}
event.preventDefault();
if (optionName === "cameraAngle") {
options.rotateCameraAngle();
} else if (
!options.isSideBarButtonDisabled(optionName, enableHMIButtonsOnly, hmi.inNavigationMode)
) {
this.props.store.handleOptionToggle(optionName);
}
const optionName = HOTKEYS_CONFIG[event.key];
if (!optionName || options.showDataRecorder) {
return;
}
componentWillMount() {
this.props.store.dimension.initialize();
event.preventDefault();
if (optionName === 'cameraAngle') {
options.rotateCameraAngle();
} else if (
!options.isSideBarButtonDisabled(optionName, enableHMIButtonsOnly, hmi.inNavigationMode)
) {
this.props.store.handleOptionToggle(optionName);
}
}
componentDidMount() {
WS.initialize();
MAP_WS.initialize();
POINT_CLOUD_WS.initialize();
CAMERA_WS.initialize();
window.addEventListener("resize", this.updateDimension, false);
window.addEventListener("keypress", this.handleKeyPress, false);
}
componentWillMount() {
this.props.store.dimension.initialize();
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateDimension, false);
window.removeEventListener("keypress", this.handleKeyPress, false);
}
componentDidMount() {
WS.initialize();
MAP_WS.initialize();
POINT_CLOUD_WS.initialize();
CAMERA_WS.initialize();
window.addEventListener('resize', this.updateDimension, false);
window.addEventListener('keypress', this.handleKeyPress, false);
}
componentWillUnmount() {
window.removeEventListener('resize', this.updateDimension, false);
window.removeEventListener('keypress', this.handleKeyPress, false);
}
render() {
const { dimension, options, hmi } = this.props.store;
render() {
const { dimension, options, hmi } = this.props.store;
return (
return (
<div>
<Header />
<div className="pane-container">
<SplitPane split="vertical"
<SplitPane
split="vertical"
size={dimension.pane.width}
onChange={this.handleDrag}
allowResize={options.showMonitor}>
allowResize={options.showMonitor}
>
<div className="left-pane">
<SideBar />
<div className="dreamview-body">
......@@ -90,10 +91,11 @@ export default class Dreamview extends React.Component {
<MonitorPanel
hmi={hmi}
viewName={options.monitorName}
showVideo={options.showVideo} />
showVideo={options.showVideo}
/>
</SplitPane>
</div>
</div>
);
}
}
\ No newline at end of file
);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import classNames from "classnames";
import React from 'react';
import { inject, observer } from 'mobx-react';
import classNames from 'classnames';
import HMISelectors from "components/Header/HMISelectors";
import HMISelectors from 'components/Header/HMISelectors';
@inject("store") @observer
@inject('store') @observer
export default class HMIControls extends React.Component {
render() {
const {
dockerImage,
modes, currentMode,
maps, currentMap,
vehicles, currentVehicle,
isCoDriver,
isMute
} = this.props.store.hmi;
render() {
const {
dockerImage,
modes, currentMode,
maps, currentMap,
vehicles, currentVehicle,
isCoDriver,
isMute,
} = this.props.store.hmi;
return (
return (
<React.Fragment>
<button className="header-item header-button" onClick={() => alert(dockerImage)}>
Docker Version
</button>
<button
className={classNames({
"header-item": true,
"header-button": true,
"header-button-active": isCoDriver,
'header-item': true,
'header-button': true,
'header-button-active': isCoDriver,
})}
onClick={() => this.props.store.hmi.toggleCoDriverFlag()}>
onClick={() => this.props.store.hmi.toggleCoDriverFlag()}
>
Co-Driver
</button>
<button
className={classNames({
"header-item": true,
"header-button": true,
"header-button-active": isMute,
'header-item': true,
'header-button': true,
'header-button-active': isMute,
})}
onClick={() => this.props.store.hmi.toggleMuteFlag()}>
onClick={() => this.props.store.hmi.toggleMuteFlag()}
>
Mute
</button>
<HMISelectors
......@@ -45,8 +47,9 @@ export default class HMIControls extends React.Component {
maps={maps}
currentMap={currentMap}
vehicles={vehicles}
currentVehicle={currentVehicle} />
currentVehicle={currentVehicle}
/>
</React.Fragment>
);
}
);
}
}
import React from "react";
import React from 'react';
import Selector from "components/Header/Selector";
import WS from "store/websocket";
import Selector from 'components/Header/Selector';
import WS from 'store/websocket';
export default class HMISelectors extends React.Component {
render() {
const { modes, currentMode,
maps, currentMap,
vehicles, currentVehicle } = this.props;
render() {
const {
modes, currentMode,
maps, currentMap,
vehicles, currentVehicle,
} = this.props;
return (
return (
<React.Fragment>
<Selector name="setup mode"
options={modes}
currentOption={currentMode}
onChange={(event) => {
WS.changeSetupMode(event.target.value);
}} />
<Selector name="vehicle"
options={vehicles}
currentOption={currentVehicle}
onChange={(event) => {
WS.changeVehicle(event.target.value);
}} />
<Selector name="map"
options={maps}
currentOption={currentMap}
onChange={(event) => {
WS.changeMap(event.target.value);
}} />
<Selector
name="setup mode"
options={modes}
currentOption={currentMode}
onChange={(event) => {
WS.changeSetupMode(event.target.value);
}}
/>
<Selector
name="vehicle"
options={vehicles}
currentOption={currentVehicle}
onChange={(event) => {
WS.changeVehicle(event.target.value);
}}
/>
<Selector
name="map"
options={maps}
currentOption={currentMap}
onChange={(event) => {
WS.changeMap(event.target.value);
}}
/>
</React.Fragment>
);
}
);
}
}
import React from "react";
import React from 'react';
export default class Selector extends React.Component {
constructor(props) {
super(props);
constructor(props) {
super(props);
this.state = {
name: props.name,
value: props.currentOption,
};
this.state = {
name: props.name,
value: props.currentOption,
};
this.onChangeHandler = this.onChangeHandler.bind(this);
}
this.onChangeHandler = this.onChangeHandler.bind(this);
}
onChangeHandler(event) {
this.setState({value: event.target.value});
this.props.onChange(event);
}
onChangeHandler(event) {
this.setState({ value: event.target.value });
this.props.onChange(event);
}
componentWillReceiveProps(nextProps) {
if (nextProps.currentOption !== this.props.currentOption) {
this.setState({value: nextProps.currentOption});
}
componentWillReceiveProps(nextProps) {
if (nextProps.currentOption !== this.props.currentOption) {
this.setState({ value: nextProps.currentOption });
}
}
render() {
const { name, options, currentOption, onChange } = this.props;
render() {
const {
name, options, currentOption, onChange,
} = this.props;
this.entries = this.props.options.map(key => {
return (
<option value={key} key={key}>{key}</option>
);
});
this.entries.unshift(
this.entries = this.props.options.map((key) => (
<option value={key} key={key}>{key}</option>
));
this.entries.unshift(
<option key="none" value="none" disabled>
{`-- ${this.state.name} --`}
</option>
);
</option>,
);
return (
return (
<div className="header-item selector">
<span className="arrow"></span>
<span className="arrow" />
<select onChange={this.onChangeHandler} value={this.state.value}>
{this.entries}
</select>
</div>
);
}
}
\ No newline at end of file
);
}
}
import React from "react";
import React from 'react';
import Image from "components/common/Image";
import logoApollo from "assets/images/logo_apollo.png";
import HMIControls from "components/Header/HMIControls";
import Image from 'components/common/Image';
import logoApollo from 'assets/images/logo_apollo.png';
import HMIControls from 'components/Header/HMIControls';
export default class Header extends React.Component {
render() {
return (
render() {
return (
<header className="header">
<Image image={logoApollo} className="apollo-logo" />
{!OFFLINE_PLAYBACK && <HMIControls />}
</header>
);
}
);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import React from 'react';
import { inject, observer } from 'mobx-react';
import Loadable from 'react-loadable';
import RouteEditingBar from "components/RouteEditingBar";
import StatusBar from "components/StatusBar";
import Scene from "components/Scene";
import Loader from "components/common/Loader";
import PlaybackControls from "components/PlaybackControls";
import RouteEditingBar from 'components/RouteEditingBar';
import StatusBar from 'components/StatusBar';
import Scene from 'components/Scene';
import Loader from 'components/common/Loader';
import PlaybackControls from 'components/PlaybackControls';
const Navigation = Loadable({
loader: () => import("components/Navigation"),
loading() {
return <div className="navigation-view">Loading...</div>;
}
loader: () => import('components/Navigation'),
loading() {
return <div className="navigation-view">Loading...</div>;
},
});
@inject("store") @observer
@inject('store') @observer
class SceneView extends React.Component {
render() {
const { dimension, meters, monitor,
hmi, options, trafficSignal } = this.props.store;
render() {
const {
dimension, meters, monitor,
hmi, options, trafficSignal,
} = this.props.store;
return (
return (
<React.Fragment>
<Scene
width={dimension.scene.width}
height={dimension.scene.height}
options={options}
shouldDisplayOnRight={dimension.shouldDivideSceneAndMapSpace} />
shouldDisplayOnRight={dimension.shouldDivideSceneAndMapSpace}
/>
{options.showRouteEditingBar
? <RouteEditingBar />
: <StatusBar meters={meters}
trafficSignal={trafficSignal}
showNotification={!options.showTasks}
showPlanningRSSInfo={options.showPlanningRSSInfo}
monitor={monitor} />}
? <RouteEditingBar />
: (
<StatusBar
meters={meters}
trafficSignal={trafficSignal}
showNotification={!options.showTasks}
showPlanningRSSInfo={options.showPlanningRSSInfo}
monitor={monitor}
/>
)}
{OFFLINE_PLAYBACK && <PlaybackControls />}
{hmi.shouldDisplayNavigationMap &&
<Navigation onResize={() => dimension.toggleNavigationSize()}
hasRoutingControls={hmi.inNavigationMode}
{...dimension.navigation} />}
{hmi.shouldDisplayNavigationMap
&& (
<Navigation
onResize={() => dimension.toggleNavigationSize()}
hasRoutingControls={hmi.inNavigationMode}
{...dimension.navigation}
/>
)}
</React.Fragment>
);
}
);
}
}
@inject("store") @observer
@inject('store') @observer
export default class MainView extends React.Component {
render() {
const { isInitialized, dimension } = this.props.store;
render() {
const { isInitialized, dimension } = this.props.store;
const height = dimension.main.height;
return (
const height = dimension.main.height;
return (
<div className="main-view" style={{ height }}>
{(!isInitialized && !OFFLINE_PLAYBACK) ? <Loader /> : <SceneView />}
</div >
);
}
</div>
);
}
}
import 'styles/monitor.scss';
import "styles/monitor.scss";
import React from 'react';
import {
Tabs, TabList, Tab, TabPanel,
} from 'react-tabs';
import React from "react";
import { Tabs, TabList, Tab, TabPanel } from "react-tabs";
import { MONITOR_MENU } from 'store/options';
import { MONITOR_MENU } from "store/options";
import CameraParam from "components/CameraParam";
import { CameraVideo } from "components/Tasks/SensorCamera";
import DataCollectionMonitor from "components/DataCollectionMonitor";
import PNCMonitor from "components/PNCMonitor";
import ConsoleTeleOp from "components/TeleopMonitor/ConsoleTeleop";
import CarTeleOp from "components/TeleopMonitor/CarTeleop";
import CameraParam from 'components/CameraParam';
import { CameraVideo } from 'components/Tasks/SensorCamera';
import DataCollectionMonitor from 'components/DataCollectionMonitor';
import PNCMonitor from 'components/PNCMonitor';
import ConsoleTeleOp from 'components/TeleopMonitor/ConsoleTeleop';
import CarTeleOp from 'components/TeleopMonitor/CarTeleop';
export default class MonitorPanel extends React.Component {
renderMonitor() {
const { viewName, hmi } = this.props;
switch (viewName) {
case MONITOR_MENU.CONSOLE_TELEOP_MONITOR:
return <ConsoleTeleOp />;
case MONITOR_MENU.CAR_TELEOP_MONITOR:
return <CarTeleOp />;
case MONITOR_MENU.CAMERA_PARAM:
return <CameraParam />;
case MONITOR_MENU.DATA_COLLECTION_MONITOR:
return <DataCollectionMonitor
dataCollectionUpdateStatus={hmi.dataCollectionUpdateStatus}
dataCollectionProgress={hmi.dataCollectionProgress}
/>;
case MONITOR_MENU.PNC_MONITOR:
return <PNCMonitor />;
default:
return null;
}
renderMonitor() {
const { viewName, hmi } = this.props;
switch (viewName) {
case MONITOR_MENU.CONSOLE_TELEOP_MONITOR:
return <ConsoleTeleOp />;
case MONITOR_MENU.CAR_TELEOP_MONITOR:
return <CarTeleOp />;
case MONITOR_MENU.CAMERA_PARAM:
return <CameraParam />;
case MONITOR_MENU.DATA_COLLECTION_MONITOR:
return (
<DataCollectionMonitor
dataCollectionUpdateStatus={hmi.dataCollectionUpdateStatus}
dataCollectionProgress={hmi.dataCollectionProgress}
/>
);
case MONITOR_MENU.PNC_MONITOR:
return <PNCMonitor />;
default:
return null;
}
}
render() {
const { showCameraVideo } = this.props;
render() {
const { showCameraVideo } = this.props;
return (
return (
<div className="right-pane">
{showCameraVideo &&
<Tabs>
<TabList>
<Tab>Camera View</Tab>
</TabList>
<TabPanel>
<CameraVideo />
</TabPanel>
</Tabs>
}
{showCameraVideo
&& (
<Tabs>
<TabList>
<Tab>Camera View</Tab>
</TabList>
<TabPanel>
<CameraVideo />
</TabPanel>
</Tabs>
)}
{this.renderMonitor()}
</div>
);
}
);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import React from 'react';
import { inject, observer } from 'mobx-react';
import DataRecorder from "components/DataRecorder";
import ModuleController from "components/ModuleController";
import Menu from "components/SideBar/Menu";
import POI from "components/SideBar/POI";
import Tasks from "components/Tasks";
import DataRecorder from 'components/DataRecorder';
import ModuleController from 'components/ModuleController';
import Menu from 'components/SideBar/Menu';
import POI from 'components/SideBar/POI';
import Tasks from 'components/Tasks';
@inject("store") @observer
@inject('store') @observer
export default class ToolView extends React.Component {
render() {
const { options, routeEditingManager, hmi, newDisengagementReminder } = this.props.store;
render() {
const {
options, routeEditingManager, hmi, newDisengagementReminder,
} = this.props.store;
return (
return (
<div className="tools">
{options.showTasks && <Tasks options={options}/>}
{options.showTasks && <Tasks options={options} />}
{options.showModuleController && <ModuleController />}
{options.showMenu && <Menu options={options} />}
{options.showPOI && (
......@@ -30,6 +32,6 @@ export default class ToolView extends React.Component {
/>
)}
</div>
);
}
);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import React from 'react';
import { inject, observer } from 'mobx-react';
const StatusColorMapping = {
OK: "#1C9063",
NOT_READY: "#B43131",
NOT_PRESENT: "#B43131",
ERR: "#B43131",
UNDEF: "#B43131",
OK: '#1C9063',
NOT_READY: '#B43131',
NOT_PRESENT: '#B43131',
ERR: '#B43131',
UNDEF: '#B43131',
};
@observer
export default class StatusDisplay extends React.Component {
constructor(props) {
super(props);
constructor(props) {
super(props);
this.showStatusMessage = this.showStatusMessage.bind(this);
}
this.showStatusMessage = this.showStatusMessage.bind(this);
}
showStatusMessage() {
if (this.props.status['message']) {
alert(this.props.title + ': ' + this.props.status['message']);
} else {
alert('No message from ' + this.props.title );
}
showStatusMessage() {
if (this.props.status.message) {
alert(`${this.props.title}: ${this.props.status.message}`);
} else {
alert(`No message from ${this.props.title}`);
}
}
render() {
const { title, status } = this.props;
const status_code = status["status"];
render() {
const { title, status } = this.props;
const status_code = status.status;
return (
return (
<div className="status-display">
<div className="name">{title}</div>
<div className="status" onClick={this.showStatusMessage}>
<span>{status_code}</span>
<span className="status-icon"
style={{
backgroundColor: StatusColorMapping[status_code],
}}/>
<span
className="status-icon"
style={{
backgroundColor: StatusColorMapping[status_code],
}}
/>
</div>
</div>
);
}
}
\ No newline at end of file
);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import React from 'react';
import { inject, observer } from 'mobx-react';
import CheckboxItem from "components/common/CheckboxItem";
import StatusDisplay from "components/ModuleController/StatusDisplay";
import WS from "store/websocket";
import CheckboxItem from 'components/common/CheckboxItem';
import StatusDisplay from 'components/ModuleController/StatusDisplay';
import WS from 'store/websocket';
@inject("store") @observer
@inject('store') @observer
export default class ModuleController extends React.Component {
render() {
const { modes, currentMode, moduleStatus, componentStatus } = this.props.store.hmi;
render() {
const {
modes, currentMode, moduleStatus, componentStatus,
} = this.props.store.hmi;
const moduleEntries = Array.from(moduleStatus.keys()).sort().map(key => {
return <CheckboxItem key={key} id={key} title={key}
disabled={false} isChecked={moduleStatus.get(key)}
onClick={() => {
this.props.store.hmi.toggleModule(key);
}}
extraClasses="controller" />;
});
const moduleEntries = Array.from(moduleStatus.keys()).sort().map((key) => (
<CheckboxItem
key={key}
id={key}
title={key}
disabled={false}
isChecked={moduleStatus.get(key)}
onClick={() => {
this.props.store.hmi.toggleModule(key);
}}
extraClasses="controller"
/>
));
const componentEntries = Array.from(componentStatus.keys()).sort().map(key => {
return <StatusDisplay key={key} title={key}
status={componentStatus.get(key)} />;
});
const componentEntries = Array.from(componentStatus.keys()).sort().map((key) => (
<StatusDisplay
key={key}
title={key}
status={componentStatus.get(key)}
/>
));
return (
return (
<div className="module-controller">
<div className="card">
<div className="card-header"><span>Components</span></div>
......@@ -39,6 +49,6 @@ export default class ModuleController extends React.Component {
</div>
</div>
</div>
);
}
);
}
}
import { WGS84ToBD09LL } from "utils/coordinate_converter";
import { WGS84ToBD09LL } from 'utils/coordinate_converter';
export default class BaiduMapAdapter {
constructor() {
this.map = null;
this.controls = [];
this.initializedCenter = false;
}
isInitialized() {
return this.map !== null && Object.keys(this.map).length > 0;
}
loadMap(initPoint, divElementName) {
this.map = new BMap.Map(divElementName, { enableMapClick: false });
this.map.enableScrollWheelZoom();
this.map.addControl(
new BMap.MapTypeControl({
anchor: BMAP_ANCHOR_TOP_LEFT,
type: BMAP_NAVIGATION_CONTROL_SMALL,
})
);
this.map.addControl(
new BMap.NavigationControl({
anchor: BMAP_ANCHOR_BOTTOM_RIGHT,
type: BMAP_NAVIGATION_CONTROL_SMALL,
enableGeolocation: false,
})
);
}
setCenter(point) {
if (this.initializedCenter) {
this.map.setCenter(point);
} else {
this.map.centerAndZoom(point, 19);
this.initializedCenter = true;
}
}
setZoom(zoom) {
this.map.setZoom(zoom);
}
addEventHandler(eventName, handlerFunction) {
this.map.addEventListener(eventName, event => {
const clickedLatLng = event.point;
handlerFunction(clickedLatLng);
});
}
createPoint({ lat, lng }) {
return new BMap.Point(lng, lat);
}
createMarker(point, title, draggable = true) {
let label = null;
if (title) {
label = new BMap.Label(title, {
point: point,
offset: new BMap.Size(15, -15),
});
}
const marker = new BMap.Marker(point, {
label: label,
enableDragging: draggable,
rotation: 5,
});
marker.setLabel(label);
this.map.addOverlay(marker);
return marker;
}
createPolyline(path, color, opacity = 1.0, weight = 2.0) {
const options = {
geodesic: true,
strokeColor: color,
strokeOpacity: opacity,
strokeWeight: weight,
};
const polyline = new BMap.Polyline(path, options);
this.map.addOverlay(polyline);
return polyline;
}
createControl({ text, tip, color, offsetX, offsetY, onClickHandler }) {
const myControl = new NavigationControl(
text,
tip,
color,
new BMap.Size(offsetX, offsetY),
onClickHandler
);
this.map.addControl(myControl);
this.controls.push(myControl);
}
disableControls() {
this.controls.forEach(control => {
this.map.removeControl(control);
});
}
enableControls() {
this.controls.forEach(control => {
this.map.addControl(control);
});
}
getMarkerPosition(marker) {
return marker.getPosition();
}
updatePolyline(polyline, newPath) {
polyline.setPath(newPath);
}
removePolyline(polyline) {
this.map.removeOverlay(polyline);
}
applyCoordinateOffset([lng, lat]) {
return WGS84ToBD09LL(lng, lat);
}
constructor() {
this.map = null;
this.controls = [];
this.initializedCenter = false;
}
isInitialized() {
return this.map !== null && Object.keys(this.map).length > 0;
}
loadMap(initPoint, divElementName) {
this.map = new BMap.Map(divElementName, { enableMapClick: false });
this.map.enableScrollWheelZoom();
this.map.addControl(
new BMap.MapTypeControl({
anchor: BMAP_ANCHOR_TOP_LEFT,
type: BMAP_NAVIGATION_CONTROL_SMALL,
}),
);
this.map.addControl(
new BMap.NavigationControl({
anchor: BMAP_ANCHOR_BOTTOM_RIGHT,
type: BMAP_NAVIGATION_CONTROL_SMALL,
enableGeolocation: false,
}),
);
}
setCenter(point) {
if (this.initializedCenter) {
this.map.setCenter(point);
} else {
this.map.centerAndZoom(point, 19);
this.initializedCenter = true;
}
}
setZoom(zoom) {
this.map.setZoom(zoom);
}
addEventHandler(eventName, handlerFunction) {
this.map.addEventListener(eventName, (event) => {
const clickedLatLng = event.point;
handlerFunction(clickedLatLng);
});
}
createPoint({ lat, lng }) {
return new BMap.Point(lng, lat);
}
createMarker(point, title, draggable = true) {
let label = null;
if (title) {
label = new BMap.Label(title, {
point,
offset: new BMap.Size(15, -15),
});
}
const marker = new BMap.Marker(point, {
label,
enableDragging: draggable,
rotation: 5,
});
marker.setLabel(label);
this.map.addOverlay(marker);
return marker;
}
createPolyline(path, color, opacity = 1.0, weight = 2.0) {
const options = {
geodesic: true,
strokeColor: color,
strokeOpacity: opacity,
strokeWeight: weight,
};
const polyline = new BMap.Polyline(path, options);
this.map.addOverlay(polyline);
return polyline;
}
createControl({
text, tip, color, offsetX, offsetY, onClickHandler,
}) {
const myControl = new NavigationControl(
text,
tip,
color,
new BMap.Size(offsetX, offsetY),
onClickHandler,
);
this.map.addControl(myControl);
this.controls.push(myControl);
}
disableControls() {
this.controls.forEach((control) => {
this.map.removeControl(control);
});
}
enableControls() {
this.controls.forEach((control) => {
this.map.addControl(control);
});
}
getMarkerPosition(marker) {
return marker.getPosition();
}
updatePolyline(polyline, newPath) {
polyline.setPath(newPath);
}
removePolyline(polyline) {
this.map.removeOverlay(polyline);
}
applyCoordinateOffset([lng, lat]) {
return WGS84ToBD09LL(lng, lat);
}
}
class NavigationControl extends BMap.Control {
constructor(text, tip, color, offset, onClickHandler, ...args) {
super(...args);
this.defaultAnchor = BMAP_ANCHOR_TOP_LEFT;
this.defaultOffset = offset;
this.onClickHandler = onClickHandler;
this.title = tip;
this.text = text;
this.backgroundColor = color;
}
initialize(map) {
const controlDiv = document.createElement("div");
// Set CSS for the control border.
const controlUI = document.createElement("div");
controlUI.style.backgroundColor = this.backgroundColor;
controlUI.style.border = "2px solid #fff";
controlUI.style.borderRadius = "3px";
controlUI.style.boxShadow = "0 2px 6px rgba(0,0,0,.3)";
controlUI.style.cursor = "pointer";
controlUI.style.marginBottom = "22px";
controlUI.style.textAlign = "center";
controlUI.title = this.title;
controlDiv.appendChild(controlUI);
// // Set CSS for the control interior.
const controlText = document.createElement("div");
controlText.style.color = "rgb(25,25,25)";
controlText.style.fontFamily = "Roboto,Arial,sans-serif";
controlText.style.fontSize = "16px";
controlText.style.lineHeight = "38px";
controlText.style.paddingLeft = "5px";
controlText.style.paddingRight = "5px";
controlText.innerHTML = this.text;
controlUI.appendChild(controlText);
map.getContainer().appendChild(controlDiv);
controlUI.addEventListener("click", () => {
this.onClickHandler(controlText);
});
return controlDiv;
}
constructor(text, tip, color, offset, onClickHandler, ...args) {
super(...args);
this.defaultAnchor = BMAP_ANCHOR_TOP_LEFT;
this.defaultOffset = offset;
this.onClickHandler = onClickHandler;
this.title = tip;
this.text = text;
this.backgroundColor = color;
}
initialize(map) {
const controlDiv = document.createElement('div');
// Set CSS for the control border.
const controlUI = document.createElement('div');
controlUI.style.backgroundColor = this.backgroundColor;
controlUI.style.border = '2px solid #fff';
controlUI.style.borderRadius = '3px';
controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
controlUI.style.cursor = 'pointer';
controlUI.style.marginBottom = '22px';
controlUI.style.textAlign = 'center';
controlUI.title = this.title;
controlDiv.appendChild(controlUI);
// // Set CSS for the control interior.
const controlText = document.createElement('div');
controlText.style.color = 'rgb(25,25,25)';
controlText.style.fontFamily = 'Roboto,Arial,sans-serif';
controlText.style.fontSize = '16px';
controlText.style.lineHeight = '38px';
controlText.style.paddingLeft = '5px';
controlText.style.paddingRight = '5px';
controlText.innerHTML = this.text;
controlUI.appendChild(controlText);
map.getContainer().appendChild(controlDiv);
controlUI.addEventListener('click', () => {
this.onClickHandler(controlText);
});
return controlDiv;
}
}
import { WGS84ToGCJ02 } from "utils/coordinate_converter";
import { WGS84ToGCJ02 } from 'utils/coordinate_converter';
export default class GoogleMapAdapter {
constructor() {
this.map = null;
this.controls = [];
}
isInitialized() {
return this.map !== null;
}
loadMap(initPoint, divElementName) {
const mapOptions = {
center: initPoint,
zoom: 20,
mapTypeId: google.maps.MapTypeId.ROADMAP,
fullscreenControl: false
};
this.map = new google.maps.Map(document.getElementById(divElementName), mapOptions);
}
setCenter(point) {
this.map.setCenter(point);
}
setZoom(zoom) {
this.map.setZoom(zoom);
}
addEventHandler(eventName, handler) {
google.maps.event.addListener(this.map, eventName, event => {
const clickedLatLng = event.latLng;
handler(clickedLatLng);
});
}
createPoint({ lat, lng }) {
return new google.maps.LatLng(lat, lng);
}
createMarker(point, title, draggable = true) {
const marker = new google.maps.Marker({
position: point,
label: title,
draggable: draggable,
map: this.map,
});
return marker;
}
createPolyline(path, color, opacity = 1.0, weight = 2.0) {
const polyline = new google.maps.Polyline({
path: path,
geodesic: true,
strokeColor: color,
strokeOpacity: opacity,
strokeWeight: weight,
map: this.map,
});
return polyline;
}
createControl({ text, tip, color, offsetX, offsetY, onClickHandler }) {
const controlDiv = document.createElement("div");
// Set CSS for the control border.
const controlUI = document.createElement("div");
controlUI.style.backgroundColor = color;
controlUI.style.border = "2px solid #fff";
controlUI.style.borderRadius = "3px";
controlUI.style.boxShadow = "0 2px 6px rgba(0,0,0,.3)";
controlUI.style.cursor = "pointer";
controlUI.style.marginBottom = "22px";
controlUI.style.textAlign = "center";
controlUI.title = tip;
controlDiv.appendChild(controlUI);
// Set CSS for the control interior.
const controlText = document.createElement("div");
controlText.style.color = "rgb(25,25,25)";
controlText.style.fontFamily = "Roboto,Arial,sans-serif";
controlText.style.fontSize = "16px";
controlText.style.lineHeight = "38px";
controlText.style.paddingLeft = "5px";
controlText.style.paddingRight = "5px";
controlText.innerHTML = text;
controlUI.appendChild(controlText);
// Setup the click event listeners: simply set the map to Chicago.
controlUI.addEventListener("click", () => {
onClickHandler(controlText);
});
this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(controlDiv);
this.controls.push(controlDiv);
}
disableControls() {
this.controls.forEach(control => {
control.style.display = "none";
});
}
enableControls() {
this.controls.forEach(control => {
control.style.display = "block";
});
}
getMarkerPosition(marker) {
const position = marker.getPosition();
return { lat: position.lat(), lng: position.lng() };
}
updatePolyline(polyline, newPath) {
polyline.setPath(newPath);
}
removePolyline(polyline) {
polyline.setMap(null);
}
applyCoordinateOffset([lng, lat]) {
return WGS84ToGCJ02(lng, lat);
}
constructor() {
this.map = null;
this.controls = [];
}
isInitialized() {
return this.map !== null;
}
loadMap(initPoint, divElementName) {
const mapOptions = {
center: initPoint,
zoom: 20,
mapTypeId: google.maps.MapTypeId.ROADMAP,
fullscreenControl: false,
};
this.map = new google.maps.Map(document.getElementById(divElementName), mapOptions);
}
setCenter(point) {
this.map.setCenter(point);
}
setZoom(zoom) {
this.map.setZoom(zoom);
}
addEventHandler(eventName, handler) {
google.maps.event.addListener(this.map, eventName, (event) => {
const clickedLatLng = event.latLng;
handler(clickedLatLng);
});
}
createPoint({ lat, lng }) {
return new google.maps.LatLng(lat, lng);
}
createMarker(point, title, draggable = true) {
const marker = new google.maps.Marker({
position: point,
label: title,
draggable,
map: this.map,
});
return marker;
}
createPolyline(path, color, opacity = 1.0, weight = 2.0) {
const polyline = new google.maps.Polyline({
path,
geodesic: true,
strokeColor: color,
strokeOpacity: opacity,
strokeWeight: weight,
map: this.map,
});
return polyline;
}
createControl({
text, tip, color, offsetX, offsetY, onClickHandler,
}) {
const controlDiv = document.createElement('div');
// Set CSS for the control border.
const controlUI = document.createElement('div');
controlUI.style.backgroundColor = color;
controlUI.style.border = '2px solid #fff';
controlUI.style.borderRadius = '3px';
controlUI.style.boxShadow = '0 2px 6px rgba(0,0,0,.3)';
controlUI.style.cursor = 'pointer';
controlUI.style.marginBottom = '22px';
controlUI.style.textAlign = 'center';
controlUI.title = tip;
controlDiv.appendChild(controlUI);
// Set CSS for the control interior.
const controlText = document.createElement('div');
controlText.style.color = 'rgb(25,25,25)';
controlText.style.fontFamily = 'Roboto,Arial,sans-serif';
controlText.style.fontSize = '16px';
controlText.style.lineHeight = '38px';
controlText.style.paddingLeft = '5px';
controlText.style.paddingRight = '5px';
controlText.innerHTML = text;
controlUI.appendChild(controlText);
// Setup the click event listeners: simply set the map to Chicago.
controlUI.addEventListener('click', () => {
onClickHandler(controlText);
});
this.map.controls[google.maps.ControlPosition.TOP_LEFT].push(controlDiv);
this.controls.push(controlDiv);
}
disableControls() {
this.controls.forEach((control) => {
control.style.display = 'none';
});
}
enableControls() {
this.controls.forEach((control) => {
control.style.display = 'block';
});
}
getMarkerPosition(marker) {
const position = marker.getPosition();
return { lat: position.lat(), lng: position.lng() };
}
updatePolyline(polyline, newPath) {
polyline.setPath(newPath);
}
removePolyline(polyline) {
polyline.setMap(null);
}
applyCoordinateOffset([lng, lat]) {
return WGS84ToGCJ02(lng, lat);
}
}
import { UTMToWGS84 } from "utils/coordinate_converter";
import { calculateLaneMarkerPoints } from "utils/misc";
import { UTMToWGS84 } from 'utils/coordinate_converter';
import { calculateLaneMarkerPoints } from 'utils/misc';
class MapNavigator {
constructor() {
this.mapAPILoaded = false;
this.WS = null;
this.mapAdapter = null;
this.routingPaths = [];
this.plannedPath = null;
this.vehicleMarker = null;
this.rightLaneMarker = null;
this.leftLaneMarker = null;
this.destinationMarker = null;
this.centerVehicle = true;
this.routingRequestPoints = [];
constructor() {
this.mapAPILoaded = false;
this.WS = null;
this.mapAdapter = null;
this.routingPaths = [];
this.plannedPath = null;
this.vehicleMarker = null;
this.rightLaneMarker = null;
this.leftLaneMarker = null;
this.destinationMarker = null;
this.centerVehicle = true;
this.routingRequestPoints = [];
}
initialize(WS, mapAdapter) {
this.WS = WS;
this.mapAdapter = mapAdapter;
const initLatlng = { lng: -122.014487, lat: 37.415885 };
const point = this.mapAdapter.createPoint(initLatlng);
const divElementName = 'map_canvas';
this.mapAdapter.loadMap(point, divElementName);
this.vehicleMarker = this.mapAdapter.createMarker(point, null, false);
this.createControls();
this.mapAdapter.addEventHandler('click', (clickedLatLng) => {
if (!this.destinationMarker) {
this.destinationMarker = this.mapAdapter.createMarker(clickedLatLng, 'D');
} else {
this.destinationMarker.setPosition(clickedLatLng);
}
});
}
isInitialized() {
return this.WS && this.mapAdapter && this.mapAdapter.isInitialized();
}
reset() {
this.routingPaths.forEach((path) => {
this.mapAdapter.removePolyline(path);
});
this.routingPaths = [];
if (this.plannedPath) {
this.mapAdapter.removePolyline(this.plannedPath);
this.plannedPath = null;
}
initialize(WS, mapAdapter) {
this.WS = WS;
this.mapAdapter = mapAdapter;
const initLatlng = { lng: -122.014487, lat: 37.415885 };
const point = this.mapAdapter.createPoint(initLatlng);
const divElementName = "map_canvas";
this.mapAdapter.loadMap(point, divElementName);
this.vehicleMarker = this.mapAdapter.createMarker(point, null, false);
this.createControls();
this.mapAdapter.addEventHandler("click", clickedLatLng => {
if (!this.destinationMarker) {
this.destinationMarker = this.mapAdapter.createMarker(clickedLatLng, "D");
} else {
this.destinationMarker.setPosition(clickedLatLng);
}
});
if (this.rightLaneMarker) {
this.mapAdapter.removePolyline(this.rightLaneMarker);
this.rightLaneMarker = null;
}
isInitialized() {
return this.WS && this.mapAdapter && this.mapAdapter.isInitialized();
if (this.leftLaneMarker) {
this.mapAdapter.removePolyline(this.leftLaneMarker);
this.leftLaneMarker = null;
}
reset() {
this.routingPaths.forEach(path => {
this.mapAdapter.removePolyline(path);
});
this.routingPaths = [];
if (this.plannedPath) {
this.mapAdapter.removePolyline(this.plannedPath);
this.plannedPath = null;
this.WS = null;
this.mapAdapter = null;
this.vehicleMarker = null;
this.destinationMarker = null;
this.centerVehicle = true;
}
createControls() {
this.mapAdapter.createControl({
text: 'CarView ON',
tip: 'Click to recenter the vehicle',
color: '#FFFFFF',
offsetX: 130,
offsetY: 0,
onClickHandler: (textElementDiv) => {
if (this.centerVehicle) {
this.centerVehicle = false;
textElementDiv.innerHTML = 'CarView OFF';
this.mapAdapter.setZoom(18);
} else {
this.centerVehicle = true;
textElementDiv.innerHTML = 'CarView ON';
this.mapAdapter.setZoom(20);
}
if (this.rightLaneMarker) {
this.mapAdapter.removePolyline(this.rightLaneMarker);
this.rightLaneMarker = null;
},
});
this.mapAdapter.createControl({
text: 'Route',
tip: 'Click to send routing request',
color: '#CD5C5C',
offsetX: 235,
offsetY: 0,
onClickHandler: (textElementDiv) => {
if (!this.destinationMarker) {
alert('please select a destination point.');
return;
}
if (this.leftLaneMarker) {
this.mapAdapter.removePolyline(this.leftLaneMarker);
this.leftLaneMarker = null;
}
const start = this.mapAdapter.getMarkerPosition(this.vehicleMarker);
const end = this.mapAdapter.getMarkerPosition(this.destinationMarker);
this.requestRoute(start.lat, start.lng, end.lat, end.lng);
},
});
}
this.WS = null;
this.mapAdapter = null;
this.vehicleMarker = null;
this.destinationMarker = null;
this.centerVehicle = true;
}
createControls() {
this.mapAdapter.createControl({
text: "CarView ON",
tip: "Click to recenter the vehicle",
color: "#FFFFFF",
offsetX: 130,
offsetY: 0,
onClickHandler: textElementDiv => {
if (this.centerVehicle) {
this.centerVehicle = false;
textElementDiv.innerHTML = "CarView OFF";
this.mapAdapter.setZoom(18);
} else {
this.centerVehicle = true;
textElementDiv.innerHTML = "CarView ON";
this.mapAdapter.setZoom(20);
}
},
});
this.mapAdapter.createControl({
text: "Route",
tip: "Click to send routing request",
color: "#CD5C5C",
offsetX: 235,
offsetY: 0,
onClickHandler: textElementDiv => {
if (!this.destinationMarker) {
alert("please select a destination point.");
return;
}
const start = this.mapAdapter.getMarkerPosition(this.vehicleMarker);
const end = this.mapAdapter.getMarkerPosition(this.destinationMarker);
this.requestRoute(start.lat, start.lng, end.lat, end.lng);
},
});
}
disableControls() {
this.mapAdapter.disableControls();
}
disableControls() {
this.mapAdapter.disableControls();
}
enableControls() {
this.mapAdapter.enableControls();
}
enableControls() {
this.mapAdapter.enableControls();
update(data) {
if (!this.isInitialized()) {
return;
}
update(data) {
if (!this.isInitialized()) {
return;
}
const adc = data.autoDrivingCar;
this.updateCenterVehicle(adc);
this.updateNavigationPath(data.navigationPath);
this.updateLaneMarkers(adc, data.laneMarker);
this.updatePlanningPath(adc, data.planningTrajectory);
}
const adc = data.autoDrivingCar;
this.updateCenterVehicle(adc);
this.updateNavigationPath(data.navigationPath);
this.updateLaneMarkers(adc, data.laneMarker);
this.updatePlanningPath(adc, data.planningTrajectory);
updateCenterVehicle(autoDrivingCar) {
if (!autoDrivingCar) {
return;
}
updateCenterVehicle(autoDrivingCar) {
if (!autoDrivingCar) {
return;
}
const x = autoDrivingCar.positionX;
const y = autoDrivingCar.positionY;
const x = autoDrivingCar.positionX;
const y = autoDrivingCar.positionY;
const [longitude, latitude] = this.mapAdapter.applyCoordinateOffset(UTMToWGS84(x, y));
const latLng = this.mapAdapter.createPoint({
lat: latitude,
lng: longitude,
});
if (this.centerVehicle) {
this.mapAdapter.setCenter(latLng);
}
this.vehicleMarker.setPosition(latLng);
const [longitude, latitude] = this.mapAdapter.applyCoordinateOffset(UTMToWGS84(x, y));
const latLng = this.mapAdapter.createPoint({
lat: latitude,
lng: longitude,
});
if (this.centerVehicle) {
this.mapAdapter.setCenter(latLng);
}
calculateLaneMarkerPath(autoDrivingCar, laneMarkerData) {
const path = calculateLaneMarkerPoints(autoDrivingCar, laneMarkerData);
return path.map(point => {
const [plon, plat] = this.mapAdapter.applyCoordinateOffset(
UTMToWGS84(point.x, point.y)
);
return this.mapAdapter.createPoint({ lat: plat, lng: plon });
});
this.vehicleMarker.setPosition(latLng);
}
calculateLaneMarkerPath(autoDrivingCar, laneMarkerData) {
const path = calculateLaneMarkerPoints(autoDrivingCar, laneMarkerData);
return path.map((point) => {
const [plon, plat] = this.mapAdapter.applyCoordinateOffset(
UTMToWGS84(point.x, point.y),
);
return this.mapAdapter.createPoint({ lat: plat, lng: plon });
});
}
updateLaneMarkers(autoDrivingCar, laneMarker) {
if (!autoDrivingCar || !laneMarker) {
return;
}
updateLaneMarkers(autoDrivingCar, laneMarker) {
if (!autoDrivingCar || !laneMarker) {
return;
}
const rightLane = this.calculateLaneMarkerPath(autoDrivingCar, laneMarker.rightLaneMarker);
if (!this.rightLaneMarker) {
this.rightLaneMarker = this.mapAdapter.createPolyline(rightLane, "#0000FF");
} else {
this.mapAdapter.updatePolyline(this.rightLaneMarker, rightLane);
}
const leftLane = this.calculateLaneMarkerPath(autoDrivingCar, laneMarker.leftLaneMarker);
if (!this.leftLaneMarker) {
this.leftLaneMarker = this.mapAdapter.createPolyline(leftLane, "#0000FF");
} else {
this.mapAdapter.updatePolyline(this.leftLaneMarker, leftLane);
}
const rightLane = this.calculateLaneMarkerPath(autoDrivingCar, laneMarker.rightLaneMarker);
if (!this.rightLaneMarker) {
this.rightLaneMarker = this.mapAdapter.createPolyline(rightLane, '#0000FF');
} else {
this.mapAdapter.updatePolyline(this.rightLaneMarker, rightLane);
}
updatePlanningPath(autoDrivingCar, trajectory) {
if (!autoDrivingCar || !trajectory) {
return;
}
const adcX = autoDrivingCar.positionX;
const adcY = autoDrivingCar.positionY;
const heading = autoDrivingCar.heading;
const path = trajectory.map(point => {
const x = point.positionX;
const y = point.positionY;
const newX = x * Math.cos(heading) - y * Math.sin(heading);
const newY = y * Math.cos(heading) + x * Math.sin(heading);
const [plon, plat] = this.mapAdapter.applyCoordinateOffset(
UTMToWGS84(adcX + newX, adcY + newY)
);
return this.mapAdapter.createPoint({ lat: plat, lng: plon });
});
if (!this.plannedPath) {
this.plannedPath = this.mapAdapter.createPolyline(path, "#00FF00");
} else {
this.mapAdapter.updatePolyline(this.plannedPath, path);
}
const leftLane = this.calculateLaneMarkerPath(autoDrivingCar, laneMarker.leftLaneMarker);
if (!this.leftLaneMarker) {
this.leftLaneMarker = this.mapAdapter.createPolyline(leftLane, '#0000FF');
} else {
this.mapAdapter.updatePolyline(this.leftLaneMarker, leftLane);
}
}
updateNavigationPath(navigationPaths) {
if (!navigationPaths) {
return;
}
const paths = navigationPaths.map(navigationPath => {
return navigationPath.pathPoint.map(point => {
const [lng, lat] = this.mapAdapter.applyCoordinateOffset(
UTMToWGS84(point.x, point.y)
);
return this.mapAdapter.createPoint({ lat: lat, lng: lng });
});
});
if (this.routingPaths.length < paths.length) {
// adding more polyline(s)
while (this.routingPaths.length < paths.length) {
this.routingPaths.push(this.mapAdapter.createPolyline(null, "#CD5C5C", 0.7, 6));
}
} else if (this.routingPaths.length > paths.length) {
// removing extra polyline(s)
while (this.routingPaths.length > paths.length) {
this.mapAdapter.removePolyline(this.routingPaths[this.routingPaths.length - 1]);
this.routingPaths.pop();
}
}
updatePlanningPath(autoDrivingCar, trajectory) {
if (!autoDrivingCar || !trajectory) {
return;
}
this.routingPaths.forEach((polyline, index) => {
this.mapAdapter.updatePolyline(polyline, paths[index]);
});
const adcX = autoDrivingCar.positionX;
const adcY = autoDrivingCar.positionY;
const heading = autoDrivingCar.heading;
const path = trajectory.map((point) => {
const x = point.positionX;
const y = point.positionY;
const newX = x * Math.cos(heading) - y * Math.sin(heading);
const newY = y * Math.cos(heading) + x * Math.sin(heading);
const [plon, plat] = this.mapAdapter.applyCoordinateOffset(
UTMToWGS84(adcX + newX, adcY + newY),
);
return this.mapAdapter.createPoint({ lat: plat, lng: plon });
});
if (!this.plannedPath) {
this.plannedPath = this.mapAdapter.createPolyline(path, '#00FF00');
} else {
this.mapAdapter.updatePolyline(this.plannedPath, path);
}
}
requestRoute(startLat, startLng, endLat, endLng) {
if (!startLat || !startLng || !endLat || !endLng) {
return;
}
updateNavigationPath(navigationPaths) {
if (!navigationPaths) {
return;
}
const url =
"http://navi-env.axty8vi3ic.us-west-2.elasticbeanstalk.com" +
"/dreamview/navigation" +
`?origin=${startLat},${startLng}` +
`&destination=${endLat},${endLng}` +
"&heading=0";
fetch(encodeURI(url), {
method: "GET",
mode: "cors",
}).then(response => {
return response.arrayBuffer();
}).then(response => {
if (!response.byteLength) {
alert("No navigation info received.");
return;
}
this.WS.publishNavigationInfo(response);
}).catch(error => {
console.error("Failed to retrieve navigation data:", error);
});
const paths = navigationPaths.map((navigationPath) =>
navigationPath.pathPoint.map((point) => {
const [lng, lat] = this.mapAdapter.applyCoordinateOffset(
UTMToWGS84(point.x, point.y),
);
return this.mapAdapter.createPoint({ lat, lng });
}));
if (this.routingPaths.length < paths.length) {
// adding more polyline(s)
while (this.routingPaths.length < paths.length) {
this.routingPaths.push(this.mapAdapter.createPolyline(null, '#CD5C5C', 0.7, 6));
}
} else if (this.routingPaths.length > paths.length) {
// removing extra polyline(s)
while (this.routingPaths.length > paths.length) {
this.mapAdapter.removePolyline(this.routingPaths[this.routingPaths.length - 1]);
this.routingPaths.pop();
}
}
sendRoutingRequest() {
if (this.routingRequestPoints) {
const start =
this.routingRequestPoints.length > 1
? this.routingRequestPoints[0]
: this.mapAdapter.getMarkerPosition(this.vehicleMarker);
const end = this.routingRequestPoints[this.routingRequestPoints.length - 1];
this.routingRequestPoints = [];
this.requestRoute(start.lat, start.lng, end.lat, end.lng);
return true;
} else {
alert("Please select a route");
return false;
}
this.routingPaths.forEach((polyline, index) => {
this.mapAdapter.updatePolyline(polyline, paths[index]);
});
}
requestRoute(startLat, startLng, endLat, endLng) {
if (!startLat || !startLng || !endLat || !endLng) {
return;
}
addDefaultEndPoint(points) {
points.forEach(point => {
const [lng, lat] = this.mapAdapter.applyCoordinateOffset(UTMToWGS84(point.x, point.y));
this.routingRequestPoints.push({ lat: lat, lng: lng });
});
const url = 'http://navi-env.axty8vi3ic.us-west-2.elasticbeanstalk.com'
+ '/dreamview/navigation'
+ `?origin=${startLat},${startLng}`
+ `&destination=${endLat},${endLng}`
+ '&heading=0';
fetch(encodeURI(url), {
method: 'GET',
mode: 'cors',
}).then((response) => response.arrayBuffer()).then((response) => {
if (!response.byteLength) {
alert('No navigation info received.');
return;
}
this.WS.publishNavigationInfo(response);
}).catch((error) => {
console.error('Failed to retrieve navigation data:', error);
});
}
sendRoutingRequest() {
if (this.routingRequestPoints) {
const start = this.routingRequestPoints.length > 1
? this.routingRequestPoints[0]
: this.mapAdapter.getMarkerPosition(this.vehicleMarker);
const end = this.routingRequestPoints[this.routingRequestPoints.length - 1];
this.routingRequestPoints = [];
this.requestRoute(start.lat, start.lng, end.lat, end.lng);
return true;
}
alert('Please select a route');
return false;
}
addDefaultEndPoint(points) {
points.forEach((point) => {
const [lng, lat] = this.mapAdapter.applyCoordinateOffset(UTMToWGS84(point.x, point.y));
this.routingRequestPoints.push({ lat, lng });
});
}
}
const MAP_NAVIGATOR = new MapNavigator();
......
import React from "react";
import React from 'react';
import { MAP_SIZE } from "store/dimension";
import { MAP_SIZE } from 'store/dimension';
export default class WindowResizeControl extends React.PureComponent {
getMinimizingIcon() {
return (
getMinimizingIcon() {
return (
<svg viewBox="0 0 20 20">
<defs>
<path d="M20 0L0 20h20V0z" id="a" />
......@@ -15,11 +15,11 @@ export default class WindowResizeControl extends React.PureComponent {
<use xlinkHref="#b" fillOpacity="0" stroke="#006AFF" strokeWidth="2" />
<use xlinkHref="#c" fillOpacity="0" stroke="#006AFF" strokeWidth="2" />
</svg>
);
}
);
}
getMaximizingIcon() {
return (
getMaximizingIcon() {
return (
<svg viewBox="0 0 20 20">
<defs>
<path d="M20 0L0 20h20V0z" id="a" />
......@@ -30,29 +30,29 @@ export default class WindowResizeControl extends React.PureComponent {
<use xlinkHref="#b" fillOpacity="0" stroke="#006AFF" strokeWidth="2" />
<use xlinkHref="#c" fillOpacity="0" stroke="#006AFF" strokeWidth="2" />
</svg>
);
}
);
}
render() {
const { type, onClick } = this.props;
render() {
const { type, onClick } = this.props;
let icon = null;
switch (type) {
case MAP_SIZE.FULL:
icon = this.getMinimizingIcon();
break;
case MAP_SIZE.DEFAULT:
icon = this.getMaximizingIcon();
break;
default:
console.error('Unknown window size found:', type);
break;
}
let icon = null;
switch (type) {
case MAP_SIZE.FULL:
icon = this.getMinimizingIcon();
break;
case MAP_SIZE.DEFAULT:
icon = this.getMaximizingIcon();
break;
default:
console.error('Unknown window size found:', type);
break;
}
return (
return (
<div className="window-resize-control" onClick={onClick}>
{icon}
</div>
);
}
);
}
}
import React from "react";
import React from 'react';
import MAP_NAVIGATOR from "components/Navigation/MapNavigator";
import WS from "store/websocket";
import { MAP_SIZE } from "store/dimension";
import loadScriptAsync from "utils/script_loader";
import MAP_NAVIGATOR from 'components/Navigation/MapNavigator';
import WS from 'store/websocket';
import { MAP_SIZE } from 'store/dimension';
import loadScriptAsync from 'utils/script_loader';
import WindowResizeControl from "components/Navigation/WindowResizeControl";
import WindowResizeControl from 'components/Navigation/WindowResizeControl';
export default class Navigation extends React.Component {
constructor(props) {
super(props);
constructor(props) {
super(props);
this.scriptOnLoadHandler = this.scriptOnLoadHandler.bind(this);
this.scriptOnLoadHandler = this.scriptOnLoadHandler.bind(this);
if (!MAP_NAVIGATOR.mapAPILoaded) {
let onLoad = () => {
console.log("Map API script loaded.");
};
if (PARAMETERS.navigation.map === "BaiduMap") {
// For Baidu Map, the callback function is set in the window Object level
window.initMap = this.scriptOnLoadHandler;
} else if (PARAMETERS.navigation.map === "GoogleMap") {
// For Google Map, the callback function is set from the <Script>
onLoad = this.scriptOnLoadHandler;
}
if (!MAP_NAVIGATOR.mapAPILoaded) {
let onLoad = () => {
console.log('Map API script loaded.');
};
if (PARAMETERS.navigation.map === 'BaiduMap') {
// For Baidu Map, the callback function is set in the window Object level
window.initMap = this.scriptOnLoadHandler;
} else if (PARAMETERS.navigation.map === 'GoogleMap') {
// For Google Map, the callback function is set from the <Script>
onLoad = this.scriptOnLoadHandler;
}
loadScriptAsync({
url: PARAMETERS.navigation.mapAPiUrl,
onLoad: onLoad,
onError: () => {
console.log("Failed to load map api");
},
});
}
loadScriptAsync({
url: PARAMETERS.navigation.mapAPiUrl,
onLoad,
onError: () => {
console.log('Failed to load map api');
},
});
}
}
componentDidMount() {
if (MAP_NAVIGATOR.mapAPILoaded) {
this.scriptOnLoadHandler();
}
componentDidMount() {
if (MAP_NAVIGATOR.mapAPILoaded) {
this.scriptOnLoadHandler();
}
}
componentDidUpdate() {
const { hasRoutingControls, size } = this.props;
componentDidUpdate() {
const { hasRoutingControls, size } = this.props;
if (hasRoutingControls && size === MAP_SIZE.FULL) {
MAP_NAVIGATOR.enableControls();
} else {
MAP_NAVIGATOR.disableControls();
}
if (hasRoutingControls && size === MAP_SIZE.FULL) {
MAP_NAVIGATOR.enableControls();
} else {
MAP_NAVIGATOR.disableControls();
}
}
scriptOnLoadHandler() {
scriptOnLoadHandler() {
import(`components/Navigation/${PARAMETERS.navigation.map}Adapter`).then(
mapAdapterModule => {
const MapAdapterClass = mapAdapterModule.default;
const mapAdapter = new MapAdapterClass();
MAP_NAVIGATOR.mapAPILoaded = true;
MAP_NAVIGATOR.initialize(WS, mapAdapter);
MAP_NAVIGATOR.disableControls();
}
(mapAdapterModule) => {
const MapAdapterClass = mapAdapterModule.default;
const mapAdapter = new MapAdapterClass();
MAP_NAVIGATOR.mapAPILoaded = true;
MAP_NAVIGATOR.initialize(WS, mapAdapter);
MAP_NAVIGATOR.disableControls();
},
);
}
}
componentWillUnmount() {
MAP_NAVIGATOR.reset();
}
componentWillUnmount() {
MAP_NAVIGATOR.reset();
}
render() {
const { width, height, size, onResize } = this.props;
render() {
const {
width, height, size, onResize,
} = this.props;
if (!["GoogleMap", "BaiduMap"].includes(PARAMETERS.navigation.map)) {
console.error(`Map API ${PARAMETERS.navigation.map} is not supported.`);
return null;
}
if (!['GoogleMap', 'BaiduMap'].includes(PARAMETERS.navigation.map)) {
console.error(`Map API ${PARAMETERS.navigation.map} is not supported.`);
return null;
}
return (
<div displayname="navigation" className="navigation-view" style={{ width, height }} >
return (
<div displayname="navigation" className="navigation-view" style={{ width, height }}>
<div id="map_canvas" />
<WindowResizeControl type={size} onClick={onResize} />
</div>
);
}
);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import React from 'react';
import { inject, observer } from 'mobx-react';
import MainView from "components/Layouts/MainView";
import ToolView from "components/Layouts/ToolView";
import Loader from "components/common/Loader";
import MainView from 'components/Layouts/MainView';
import ToolView from 'components/Layouts/ToolView';
import Loader from 'components/common/Loader';
import HOTKEYS_CONFIG from "store/config/hotkeys.yml";
import WS from "store/websocket";
import HOTKEYS_CONFIG from 'store/config/hotkeys.yml';
import WS from 'store/websocket';
@inject("store") @observer
@inject('store') @observer
export default class Offlineview extends React.Component {
constructor(props) {
super(props);
constructor(props) {
super(props);
this.handleKeyPress = this.handleKeyPress.bind(this);
this.updateDimension = this.props.store.dimension.update.bind(this.props.store.dimension);
}
this.handleKeyPress = this.handleKeyPress.bind(this);
this.updateDimension = this.props.store.dimension.update.bind(this.props.store.dimension);
}
parseQueryString(queryString) {
const params = {};
parseQueryString(queryString) {
const params = {};
queryString.replace('?','').split("&").forEach((query) => {
const segments = query.split('=');
params[segments[0]] = segments[1];
});
return params;
}
queryString.replace('?', '').split('&').forEach((query) => {
const segments = query.split('=');
params[segments[0]] = segments[1];
});
return params;
}
componentWillMount() {
this.updateDimension();
}
componentWillMount() {
this.updateDimension();
}
componentDidMount() {
const params = this.parseQueryString(window.location.search);
WS.initialize(params);
window.addEventListener("resize", this.updateDimension, false);
window.addEventListener("keypress", this.handleKeyPress, false);
}
componentDidMount() {
const params = this.parseQueryString(window.location.search);
WS.initialize(params);
window.addEventListener('resize', this.updateDimension, false);
window.addEventListener('keypress', this.handleKeyPress, false);
}
componentWillUnmount() {
window.removeEventListener("resize", this.updateDimension, false);
window.removeEventListener("keypress", this.handleKeyPress, false);
}
componentWillUnmount() {
window.removeEventListener('resize', this.updateDimension, false);
window.removeEventListener('keypress', this.handleKeyPress, false);
}
handleKeyPress(event) {
const optionName = HOTKEYS_CONFIG[event.key];
if (!optionName) {
return;
}
handleKeyPress(event) {
const optionName = HOTKEYS_CONFIG[event.key];
if (!optionName) {
return;
}
const { options } = this.props.store;
event.preventDefault();
if (optionName === "cameraAngle") {
options.rotateCameraAngle();
}
const { options } = this.props.store;
event.preventDefault();
if (optionName === 'cameraAngle') {
options.rotateCameraAngle();
}
}
render() {
const { isInitialized, offlineViewErrorMsg } = this.props.store;
render() {
const { isInitialized, offlineViewErrorMsg } = this.props.store;
if (!isInitialized) {
return (
if (!isInitialized) {
return (
<div className="offlineview">
<Loader extraClasses="offline-loader" offlineViewErr={offlineViewErrorMsg} />
</div>
);
}
);
}
return (
return (
<div className="offlineview">
<MainView />
<ToolView />
</div>
);
}
}
\ No newline at end of file
);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import React from 'react';
import { inject, observer } from 'mobx-react';
import SETTING from "store/config/ControlGraph.yml";
import ScatterGraph, { generateScatterGraph } from "components/PNCMonitor/ScatterGraph";
import SETTING from 'store/config/ControlGraph.yml';
import ScatterGraph, { generateScatterGraph } from 'components/PNCMonitor/ScatterGraph';
@inject("store") @observer
@inject('store') @observer
export default class ControlMonitor extends React.Component {
render() {
const { lastUpdatedTime, data } = this.props.store.controlData;
render() {
const { lastUpdatedTime, data } = this.props.store.controlData;
if (!lastUpdatedTime) {
return null;
}
if (!lastUpdatedTime) {
return null;
}
return (
return (
<div>
{generateScatterGraph(SETTING.trajectoryGraph, data.trajectoryGraph, {
pose: data.pose,
pose: data.pose,
})}
{generateScatterGraph(SETTING.speedGraph, data.speedGraph)}
{generateScatterGraph(SETTING.accelerationGraph, data.accelerationGraph)}
......@@ -25,6 +25,6 @@ export default class ControlMonitor extends React.Component {
{generateScatterGraph(SETTING.lateralErrorGraph, data.lateralErrorGraph)}
{generateScatterGraph(SETTING.headingErrorGraph, data.headingErrorGraph)}
</div>
);
}
);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import React from 'react';
import { inject, observer } from 'mobx-react';
import setting from "store/config/LatencyGraph.yml";
import ScatterGraph, { generateScatterGraph } from "components/PNCMonitor/ScatterGraph";
import setting from 'store/config/LatencyGraph.yml';
import ScatterGraph, { generateScatterGraph } from 'components/PNCMonitor/ScatterGraph';
@inject("store") @observer
@inject('store') @observer
export default class LatencyMonitor extends React.Component {
render() {
const { lastUpdatedTime, data } = this.props.store.latency;
render() {
const { lastUpdatedTime, data } = this.props.store.latency;
if (!data) {
return null;
}
const graphs = {};
Object.keys(data).forEach(moduleName => {
graphs[moduleName] = data[moduleName];
});
return generateScatterGraph(setting, graphs);
if (!data) {
return null;
}
const graphs = {};
Object.keys(data).forEach((moduleName) => {
graphs[moduleName] = data[moduleName];
});
return generateScatterGraph(setting, graphs);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import React from 'react';
import { inject, observer } from 'mobx-react';
import _ from 'lodash';
import SETTING from "store/config/PlanningGraph.yml";
import ScatterGraph, { generateScatterGraph } from "components/PNCMonitor/ScatterGraph";
import PlanningScenarioTable from "components/PNCMonitor/PlanningScenarioTable";
import SETTING from 'store/config/PlanningGraph.yml';
import ScatterGraph, { generateScatterGraph } from 'components/PNCMonitor/ScatterGraph';
import PlanningScenarioTable from 'components/PNCMonitor/PlanningScenarioTable';
@inject("store") @observer
@inject('store') @observer
export default class PlanningMonitor extends React.Component {
generateGraphsFromDatasets(settingName, datasets) {
const setting = SETTING[settingName];
if (!setting) {
console.error("No such setting name found in PlanningGraph.yml:", settingName);
return null;
}
generateGraphsFromDatasets(settingName, datasets) {
const setting = SETTING[settingName];
if (!setting) {
console.error('No such setting name found in PlanningGraph.yml:', settingName);
return null;
}
return _.get(setting, 'datasets', []).map(({name, graphTitle}) => {
const graph = datasets[name];
const polygons = graph ? graph.obstaclesBoundary : [];
return (
return _.get(setting, 'datasets', []).map(({ name, graphTitle }) => {
const graph = datasets[name];
const polygons = graph ? graph.obstaclesBoundary : [];
return (
<ScatterGraph
key={`${settingName}_${name}`}
title={graphTitle}
options={setting.options}
properties={setting.properties}
data={{ lines: graph, polygons: polygons }}
data={{ lines: graph, polygons }}
/>
);
});
}
);
});
}
render() {
const { planningTimeSec, data, chartData, scenarioHistory } = this.props.store.planningData;
render() {
const {
planningTimeSec, data, chartData, scenarioHistory,
} = this.props.store.planningData;
if (!planningTimeSec) {
return null;
}
if (!planningTimeSec) {
return null;
}
const chartCount = {};
const chartCount = {};
return (
return (
<div>
<PlanningScenarioTable scenarios={scenarioHistory} />
{chartData.map(chart => {
// Adding count to chart key to prevent duplicate chart title
if (!chartCount[chart.title]) {
chartCount[chart.title] = 1;
} else {
chartCount[chart.title] += 1;
}
{chartData.map((chart) => {
// Adding count to chart key to prevent duplicate chart title
if (!chartCount[chart.title]) {
chartCount[chart.title] = 1;
} else {
chartCount[chart.title] += 1;
}
return <ScatterGraph key={`custom_${chart.title}_${chartCount[chart.title]}`}
title={chart.title}
options={chart.options}
properties={chart.properties}
data={chart.data} />;
return (
<ScatterGraph
key={`custom_${chart.title}_${chartCount[chart.title]}`}
title={chart.title}
options={chart.options}
properties={chart.properties}
data={chart.data}
/>
);
})}
{generateScatterGraph(SETTING.speedGraph, data.speedGraph)}
{generateScatterGraph(SETTING.accelerationGraph, data.accelerationGraph)}
......@@ -67,6 +73,6 @@ export default class PlanningMonitor extends React.Component {
{generateScatterGraph(SETTING.referenceLineKappaGraph, data.kappaGraph)}
{generateScatterGraph(SETTING.referenceLineDkappaGraph, data.dkappaGraph)}
</div>
);
}
);
}
}
......@@ -3,38 +3,40 @@ import React from 'react';
import { timestampMsToTimeString } from 'utils/misc';
class PlanningScenarioItem extends React.Component {
render() {
const { scenario } = this.props;
render() {
const { scenario } = this.props;
const type = scenario.scenarioType;
const stage = scenario.stageType ? scenario.stageType.replace(type + '_', '') : '-';
const type = scenario.scenarioType;
const stage = scenario.stageType ? scenario.stageType.replace(`${type}_`, '') : '-';
return (
return (
<tr className="monitor-table-item">
<td className="text time">{timestampMsToTimeString(scenario.timeSec * 1000, true)}</td>
<td className="text">{type}</td>
<td className="text">{stage}</td>
</tr>
);
}
);
}
}
export default class PlanningScenarioTable extends React.Component {
render() {
const { scenarios } = this.props;
render() {
const { scenarios } = this.props;
return (
return (
<div className="monitor-table-container">
<div className="monitor-table-title">Scenario History</div>
<table className="monitor-table">
<tbody>
{scenarios.map(scenario => (
<PlanningScenarioItem key={`scenario_${scenario.timeSec}`}
scenario={scenario} />
{scenarios.map((scenario) => (
<PlanningScenarioItem
key={`scenario_${scenario.timeSec}`}
scenario={scenario}
/>
))}
</tbody>
</table>
</div>
);
}
);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import classNames from "classnames";
import { Tabs, TabList, Tab, TabPanel } from "react-tabs";
import React from 'react';
import { inject, observer } from 'mobx-react';
import classNames from 'classnames';
import {
Tabs, TabList, Tab, TabPanel,
} from 'react-tabs';
class StoryItem extends React.PureComponent {
render() {
const { name, value } = this.props;
render() {
const { name, value } = this.props;
const textClassNames = classNames({
"text": true,
"active": value,
});
const textClassNames = classNames({
text: true,
active: value,
});
return (
return (
<tr className="monitor-table-item">
<td className={textClassNames}>{name.toUpperCase()}</td>
<td className={textClassNames}>{value ? 'YES' : 'No'}</td>
</tr>
);
}
);
}
}
@inject("store") @observer
@inject('store') @observer
export default class StoryTellingMonitor extends React.Component {
render() {
const { stories } = this.props.store.storyTellers;
render() {
const { stories } = this.props.store.storyTellers;
let storyTable = null;
if (stories.size > 0) {
storyTable = stories.entries().map(([story, isOn]) =>
let storyTable = null;
if (stories.size > 0) {
storyTable = stories.entries().map(([story, isOn]) =>
<StoryItem key={`story_${story}`} name={story} value={isOn} />
);
} else {
storyTable = (
);
} else {
storyTable = (
<tr className="monitor-table-item">
<td className="text">No Data</td>
</tr>
);
}
);
}
return (
return (
<Tabs>
<TabList>
<Tab>Story Tellers</Tab>
......@@ -51,6 +52,6 @@ export default class StoryTellingMonitor extends React.Component {
</table>
</TabPanel>
</Tabs>
);
}
);
}
}
import React from "react";
import { Tab, Tabs, TabList, TabPanel } from "react-tabs";
import React from 'react';
import {
Tab, Tabs, TabList, TabPanel,
} from 'react-tabs';
import ControlMonitor from "components/PNCMonitor/ControlMonitor";
import LatencyMonitor from "components/PNCMonitor/LatencyMonitor";
import PlanningMonitor from "components/PNCMonitor/PlanningMonitor";
import StoryTellingMonitor from "components/PNCMonitor/StoryTellingMonitor";
import ControlMonitor from 'components/PNCMonitor/ControlMonitor';
import LatencyMonitor from 'components/PNCMonitor/LatencyMonitor';
import PlanningMonitor from 'components/PNCMonitor/PlanningMonitor';
import StoryTellingMonitor from 'components/PNCMonitor/StoryTellingMonitor';
export default class PNCMonitor extends React.Component {
render() {
return (
render() {
return (
<div className="monitor pnc-monitor">
<StoryTellingMonitor />
<Tabs>
......@@ -28,6 +30,6 @@ export default class PNCMonitor extends React.Component {
</TabPanel>
</Tabs>
</div>
);
}
);
}
}
import React from "react";
import React from 'react';
import classNames from "classnames";
import classNames from 'classnames';
class PlayIcons extends React.Component {
render() {
const { onClick } = this.props;
render() {
const { onClick } = this.props;
return (
return (
<svg className="icon" viewBox="0 0 10 10" onClick={onClick}>
<polygon className="play" points="0 0, 10 5, 0 10" />
</svg>
);
}
);
}
}
class ReplayIcons extends React.Component {
render() {
const { onClick } = this.props;
render() {
const { onClick } = this.props;
return (
return (
<svg className="icon" viewBox="0 0 100 100" onClick={onClick}>
<path className="replay"
d="M0.166,49.438C0.166,75.152,20.744,96,46.125,96
<path
className="replay"
d="M0.166,49.438C0.166,75.152,20.744,96,46.125,96
c12.096,0,23.1-4.731,31.306-12.469
c2.144-2.021-8.776-12.227-10.269-10.84
c-5.54,5.146-12.926,8.286-21.037,8.286
......@@ -39,87 +39,91 @@ class ReplayIcons extends React.Component {
M78.743,44.933
l0.115,0.023l-0.089,0.086
C78.754,44.977,78.743,44.933,78.743,44.933
z">
</path>
z"
/>
</svg>
);
}
);
}
}
class PauseIcons extends React.Component {
render() {
const { onClick } = this.props;
render() {
const { onClick } = this.props;
return (
return (
<svg className="icon" viewBox="0 0 20 20" onClick={onClick}>
<polygon className="pause" points="4 0, 6 0, 6 20, 4 20"/>
<polygon className="pause" points="13 0, 15 0, 15 20, 13 20"/>
<polygon className="pause" points="4 0, 6 0, 6 20, 4 20" />
<polygon className="pause" points="13 0, 15 0, 15 20, 13 20" />
</svg>
);
}
);
}
}
class FullScreenIcons extends React.Component {
render() {
const { onClick } = this.props;
render() {
const { onClick } = this.props;
return (
return (
<svg className="icon" viewBox="0 0 70 70">
<path className="fullscreen"
d="M0 25 V0 H25
<path
className="fullscreen"
d="M0 25 V0 H25
M0 45 V70 H25
M45 0 H70 V25
M45 70 H70 V45"/>
M45 70 H70 V45"
/>
</svg>
);
}
);
}
}
class NormalScreenIcons extends React.Component {
render() {
const { onClick } = this.props;
render() {
const { onClick } = this.props;
return (
return (
<svg className="icon" viewBox="0 0 70 70">
<path className="exit-fullscreen"
d="M0 25 H25 V0
<path
className="exit-fullscreen"
d="M0 25 H25 V0
M0 45 H25 V70
M45 0 V25 H70
M45 70 V45 H70"/>
M45 70 V45 H70"
/>
</svg>
);
}
);
}
}
export default class ControlIcons extends React.Component {
render() {
const { type, onClick, extraClasses } = this.props;
render() {
const { type, onClick, extraClasses } = this.props;
let icon = null;
switch(type) {
case 'replay':
icon = <ReplayIcons />;
break;
case 'pause':
icon = <PauseIcons />;
break;
case 'play':
icon = <PlayIcons />;
break;
case 'fullscreen':
icon = <FullScreenIcons />;
break;
case 'normalscreen':
icon = <NormalScreenIcons />;
break;
default:
break;
}
let icon = null;
switch (type) {
case 'replay':
icon = <ReplayIcons />;
break;
case 'pause':
icon = <PauseIcons />;
break;
case 'play':
icon = <PlayIcons />;
break;
case 'fullscreen':
icon = <FullScreenIcons />;
break;
case 'normalscreen':
icon = <NormalScreenIcons />;
break;
default:
break;
}
return (
return (
<div className={classNames(extraClasses)} onClick={onClick}>
{icon}
</div>
);
}
);
}
}
import React from "react";
import React from 'react';
import Slider from 'react-rangeslider';
import styled from 'styled-components';
export default class TimeControls extends React.Component {
constructor(props) {
super(props);
constructor(props) {
super(props);
this.state = {
frame: -1,
loadingProcess: '#2D3B50'
};
this.state = {
frame: -1,
loadingProcess: '#2D3B50',
};
this.updatingSeekingTime = false;
this.updatingSeekingTime = false;
this.handleSliderChange = this.handleSliderChange.bind(this);
this.handleSliderChangeComplete = this.handleSliderChangeComplete.bind(this);
}
this.handleSliderChange = this.handleSliderChange.bind(this);
this.handleSliderChangeComplete = this.handleSliderChangeComplete.bind(this);
}
getTimeFromFrame(fps, frame) {
const numIntervals = Math.max(0, frame - 1);
return (numIntervals / fps).toFixed(1);
}
getTimeFromFrame(fps, frame) {
const numIntervals = Math.max(0, frame - 1);
return (numIntervals / fps).toFixed(1);
}
handleSliderChange(frame) {
this.setState({frame: frame});
this.updatingSeekingTime = true;
}
handleSliderChange(frame) {
this.setState({ frame });
this.updatingSeekingTime = true;
}
handleSliderChangeComplete() {
this.props.handleFrameSeek(this.state.frame);
this.updatingSeekingTime = false;
}
handleSliderChangeComplete() {
this.props.handleFrameSeek(this.state.frame);
this.updatingSeekingTime = false;
}
componentWillReceiveProps(nextProps) {
if (!this.updatingSeekingTime && !nextProps.isSeeking) {
this.setState({frame: nextProps.currentFrame});
}
if (nextProps.loadingMarker <= nextProps.numFrames) {
const loadingPercent = (nextProps.loadingMarker / nextProps.numFrames) * 100;
const unloadingPercent = 100 - loadingPercent;
const backgroundColor = `linear-gradient(90deg, #212c3d ${loadingPercent.toFixed()}%,` +
` #2d3b50 ${loadingPercent.toFixed()}%, #2d3b50 ${unloadingPercent.toFixed()}%)`;
this.setState({
loadingProcess: backgroundColor
});
}
componentWillReceiveProps(nextProps) {
if (!this.updatingSeekingTime && !nextProps.isSeeking) {
this.setState({ frame: nextProps.currentFrame });
}
if (nextProps.loadingMarker <= nextProps.numFrames) {
const loadingPercent = (nextProps.loadingMarker / nextProps.numFrames) * 100;
const unloadingPercent = 100 - loadingPercent;
const backgroundColor = `linear-gradient(90deg, #212c3d ${loadingPercent.toFixed()}%,`
+ ` #2d3b50 ${loadingPercent.toFixed()}%, #2d3b50 ${unloadingPercent.toFixed()}%)`;
this.setState({
loadingProcess: backgroundColor,
});
}
}
render() {
const { numFrames, currentFrame, fps } = this.props;
render() {
const { numFrames, currentFrame, fps } = this.props;
const totalTime = this.getTimeFromFrame(fps, numFrames);
const currentTime = this.getTimeFromFrame(fps, currentFrame);
const totalTime = this.getTimeFromFrame(fps, numFrames);
const currentTime = this.getTimeFromFrame(fps, currentFrame);
const StyledSlider = styled(Slider)`
const StyledSlider = styled(Slider)`
background: ${this.state.loadingProcess}
`;
return (
return (
<div className="time-controls">
<StyledSlider
tooltip={false}
......@@ -70,6 +70,6 @@ export default class TimeControls extends React.Component {
{`${currentTime} / ${totalTime} s`}
</div>
</div>
);
}
}
\ No newline at end of file
);
}
}
import React from "react";
import { inject, observer } from "mobx-react";
import React from 'react';
import { inject, observer } from 'mobx-react';
import ControlIcons from "components/PlaybackControls/ControlIcons";
import TimeControls from "components/PlaybackControls/TimeControls";
import WS from "store/websocket";
import ControlIcons from 'components/PlaybackControls/ControlIcons';
import TimeControls from 'components/PlaybackControls/TimeControls';
import WS from 'store/websocket';
const PLAY_BACK_SPEED = [0.5, 1.0, 1.5, 2.0, 3.0];
@inject("store") @observer
@inject('store') @observer
export default class PlaybackControls extends React.Component {
constructor(props) {
super(props);
this.state = {
rate: 1.0,
isPlaying: false,
nextScreenMode: 'normalscreen',
};
this.nextAction = 'play';
this.handleRateChange = this.handleRateChange.bind(this);
this.handleFrameSeek = this.handleFrameSeek.bind(this);
this.handleActionChange = this.handleActionChange.bind(this);
this.handleScreenModeChange = this.handleScreenModeChange.bind(this);
constructor(props) {
super(props);
this.state = {
rate: 1.0,
isPlaying: false,
nextScreenMode: 'normalscreen',
};
this.nextAction = 'play';
this.handleRateChange = this.handleRateChange.bind(this);
this.handleFrameSeek = this.handleFrameSeek.bind(this);
this.handleActionChange = this.handleActionChange.bind(this);
this.handleScreenModeChange = this.handleScreenModeChange.bind(this);
}
handleRateChange(event) {
const { playback } = this.props.store;
const newRate = parseFloat(event.target.value);
this.setState({ rate: newRate });
playback.setPlayRate(newRate);
if (this.state.isPlaying) {
WS.startPlayback(playback.msPerFrame);
}
handleRateChange(event) {
const { playback } = this.props.store;
const newRate = parseFloat(event.target.value);
this.setState({ rate: newRate });
playback.setPlayRate(newRate);
if (this.state.isPlaying) {
WS.startPlayback(playback.msPerFrame);
}
}
handleActionChange() {
const { playback } = this.props.store;
const isPlaying = !this.state.isPlaying;
playback.setPlayAction(isPlaying);
this.setState({ isPlaying });
switch (this.nextAction) {
case 'play':
WS.startPlayback(playback.msPerFrame);
break;
case 'pause':
WS.pausePlayback();
break;
case 'replay':
playback.resetFrame();
WS.startPlayback(playback.msPerFrame);
break;
}
handleActionChange() {
const { playback } = this.props.store;
const isPlaying = !this.state.isPlaying;
playback.setPlayAction(isPlaying);
this.setState({ isPlaying: isPlaying });
switch (this.nextAction) {
case 'play':
WS.startPlayback(playback.msPerFrame);
break;
case 'pause':
WS.pausePlayback();
break;
case 'replay':
playback.resetFrame();
WS.startPlayback(playback.msPerFrame);
break;
}
}
handleScreenModeChange() {
switch (this.state.nextScreenMode) {
case 'fullscreen':
this.props.store.setOptionStatus('showMenu', false);
this.setState({ nextScreenMode: 'normalscreen' });
break;
case 'normalscreen':
this.props.store.setOptionStatus('showMenu', true);
this.setState({ nextScreenMode: 'fullscreen' });
break;
}
}
handleScreenModeChange() {
switch (this.state.nextScreenMode) {
case 'fullscreen':
this.props.store.setOptionStatus('showMenu', false);
this.setState({ nextScreenMode: 'normalscreen' });
break;
case 'normalscreen':
this.props.store.setOptionStatus('showMenu', true);
this.setState({ nextScreenMode: 'fullscreen' });
break;
}
handleFrameSeek(frame) {
const { playback } = this.props.store;
playback.seekFrame(frame);
if (!this.state.isPlaying) {
WS.requestSimulationWorld(playback.recordId, frame);
} else if (!WS.requestTimer) {
WS.startPlayback(playback.msPerFrame);
}
}
handleFrameSeek(frame) {
const { playback } = this.props.store;
componentWillUpdate(nextProps, nextState) {
const { playback } = this.props.store;
playback.seekFrame(frame);
if (!this.state.isPlaying) {
WS.requestSimulationWorld(playback.recordId, frame);
} else if (!WS.requestTimer) {
WS.startPlayback(playback.msPerFrame);
}
if (playback.replayComplete && this.state.isPlaying) {
playback.setPlayAction(false);
this.setState({ isPlaying: false });
}
componentWillUpdate(nextProps, nextState) {
const { playback } = this.props.store;
if (playback.replayComplete && this.state.isPlaying) {
playback.setPlayAction(false);
this.setState({ isPlaying: false });
}
if (playback.replayComplete && !playback.isSeeking) {
this.nextAction = 'replay';
} else if (nextState.isPlaying) {
this.nextAction = 'pause';
} else {
this.nextAction = 'play';
}
if (playback.replayComplete && !playback.isSeeking) {
this.nextAction = 'replay';
} else if (nextState.isPlaying) {
this.nextAction = 'pause';
} else {
this.nextAction = 'play';
}
}
render() {
const { playback } = this.props.store;
render() {
const { playback } = this.props.store;
return (
return (
<div className="playback-controls">
<ControlIcons extraClasses="left-controls"
onClick={this.handleActionChange}
type={this.nextAction} />
<ControlIcons
extraClasses="left-controls"
onClick={this.handleActionChange}
type={this.nextAction}
/>
<div className="rate-selector">
<select onChange={this.handleRateChange} value={this.state.rate}>
{PLAY_BACK_SPEED.map(
(speed) => (
(speed) => (
<option key={speed} value={speed}>
{`x ${speed.toFixed(1)}`}
</option>
))
}
),
)}
</select>
<span className="arrow"></span>
<span className="arrow" />
</div>
<TimeControls numFrames={playback.numFrames}
loadingMarker={playback.loadingMarker}
currentFrame={playback.currentFrame}
fps={playback.FPS}
isSeeking={playback.isSeeking}
handleFrameSeek={this.handleFrameSeek} />
<ControlIcons extraClasses="right-controls"
onClick={this.handleScreenModeChange}
type={this.state.nextScreenMode} />
<TimeControls
numFrames={playback.numFrames}
loadingMarker={playback.loadingMarker}
currentFrame={playback.currentFrame}
fps={playback.FPS}
isSeeking={playback.isSeeking}
handleFrameSeek={this.handleFrameSeek}
/>
<ControlIcons
extraClasses="right-controls"
onClick={this.handleScreenModeChange}
type={this.state.nextScreenMode}
/>
</div>
);
}
}
\ No newline at end of file
);
}
}
import React from "react";
import React from 'react';
export class CameraVideo extends React.Component {
render() {
return (
render() {
return (
<div className="camera-video">
<img src='/image'/>
<img src="/image" />
</div>
);
}
);
}
}
export default class SensorCamera extends React.Component {
render() {
return (
render() {
return (
<div className="card camera">
<div className="card-header"><span>Camera View</span></div>
<div className="card-content-column">
<CameraVideo />
</div>
</div>
);
}
);
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册