CEC-3933 - use VehiclePaths for location drawing (#306)
* CEC-3933 - Parse VehiclePaths location data * changes * fixes * stuff * sort of works * fix * progress * refactor * fix vehicle paths query * digital twin shows map * new dashboard * wider digital twin map * snapshot * latest; using polylines * lag lng changes * stuff * path showing up * stuff * things * revert home page * whitespace * validation * more stuff * fix button issue * tests pass without mocking data * fix code smells * remove map from digital twin, add to tab * fix bug * marker click event working * individual colors * possible fix * fix warning * merge and remove unused code * small fixes * re add dashboard * snaps
This commit is contained in:
@@ -269,6 +269,7 @@ exports[`App Route / authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -307,6 +308,33 @@ exports[`App Route / authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -696,7 +724,7 @@ exports[`App Route /dashboards/0 authenticated 1`] = `
|
|||||||
class="MuiTypography-root MuiLink-root MuiLink-underlineHover MuiTypography-colorInherit"
|
class="MuiTypography-root MuiLink-root MuiLink-underlineHover MuiTypography-colorInherit"
|
||||||
href="/dashboards/0"
|
href="/dashboards/0"
|
||||||
>
|
>
|
||||||
Invalid Dashboard
|
Vehicle Map
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
@@ -926,6 +954,7 @@ exports[`App Route /dashboards/0 authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -964,6 +993,33 @@ exports[`App Route /dashboards/0 authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -1076,11 +1132,130 @@ exports[`App Route /dashboards/0 authenticated 1`] = `
|
|||||||
<main
|
<main
|
||||||
class="MuiContainer-root MuiContainer-maxWidthLg"
|
class="MuiContainer-root MuiContainer-maxWidthLg"
|
||||||
>
|
>
|
||||||
<span
|
<div
|
||||||
class="error"
|
data-testid="mocked-vehicleprovider"
|
||||||
>
|
>
|
||||||
Invalid Dashboard
|
<div
|
||||||
|
class="leaflet-container leaflet-touch leaflet-grab leaflet-touch-drag leaflet-touch-zoom"
|
||||||
|
style="width: 100%; height: 900px; position: relative;"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-map-pane"
|
||||||
|
style="left: 0px; top: 0px;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-tile-pane"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-layer "
|
||||||
|
style="z-index: 1;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-tile-container leaflet-zoom-animated"
|
||||||
|
style="z-index: 18; left: 0px; top: 0px;"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt=""
|
||||||
|
class="leaflet-tile"
|
||||||
|
role="presentation"
|
||||||
|
src="https://b.tile.openstreetmap.org/5/7/12.png"
|
||||||
|
style="width: 256px; height: 256px; left: -126px; top: -114px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-overlay-pane"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-shadow-pane"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-marker-pane"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-tooltip-pane"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-popup-pane"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="leaflet-control-container"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-top leaflet-left"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-control-zoom leaflet-bar leaflet-control"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
aria-label="Zoom in"
|
||||||
|
class="leaflet-control-zoom-in"
|
||||||
|
href="#"
|
||||||
|
role="button"
|
||||||
|
title="Zoom in"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
+
|
||||||
</span>
|
</span>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
aria-label="Zoom out"
|
||||||
|
class="leaflet-control-zoom-out"
|
||||||
|
href="#"
|
||||||
|
role="button"
|
||||||
|
title="Zoom out"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
−
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="leaflet-top leaflet-right"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-bottom leaflet-left"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-bottom leaflet-right"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-control-attribution leaflet-control"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="https://leafletjs.com"
|
||||||
|
title="A JavaScript library for interactive maps"
|
||||||
|
>
|
||||||
|
Leaflet
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
|
|
||||||
|
</span>
|
||||||
|
©
|
||||||
|
<a
|
||||||
|
href="http://osm.org/copyright"
|
||||||
|
>
|
||||||
|
OpenStreetMap
|
||||||
|
</a>
|
||||||
|
contributors
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</main>
|
</main>
|
||||||
</main>
|
</main>
|
||||||
</div>
|
</div>
|
||||||
@@ -1418,6 +1593,7 @@ exports[`App Route /home authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -1456,6 +1632,33 @@ exports[`App Route /home authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -2091,6 +2294,7 @@ exports[`App Route /issue-info authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -2129,6 +2333,33 @@ exports[`App Route /issue-info authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -2675,6 +2906,7 @@ exports[`App Route /issues authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -2713,6 +2945,33 @@ exports[`App Route /issues authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -3574,6 +3833,7 @@ exports[`App Route /package-deploy authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -3612,6 +3872,33 @@ exports[`App Route /package-deploy authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -4662,6 +4949,7 @@ exports[`App Route /package-status authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -4700,6 +4988,33 @@ exports[`App Route /package-status authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -5417,6 +5732,7 @@ exports[`App Route /packages authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -5455,6 +5771,33 @@ exports[`App Route /packages authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -6436,6 +6779,7 @@ exports[`App Route /page-not-found authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -6474,6 +6818,33 @@ exports[`App Route /page-not-found authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -7036,6 +7407,7 @@ exports[`App Route /tools/certificates/add authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -7074,6 +7446,33 @@ exports[`App Route /tools/certificates/add authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -7746,6 +8145,7 @@ exports[`App Route /tools/security-dll authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -7784,6 +8184,33 @@ exports[`App Route /tools/security-dll authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<span>
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
@@ -8274,6 +8701,7 @@ exports[`App Route /tools/sms/send authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -8312,6 +8740,33 @@ exports[`App Route /tools/sms/send authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -8973,6 +9428,7 @@ exports[`App Route /vehicle-add authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -9011,6 +9467,33 @@ exports[`App Route /vehicle-add authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -10090,6 +10573,7 @@ exports[`App Route /vehicle-status authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -10128,6 +10612,33 @@ exports[`App Route /vehicle-status authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -11130,6 +11641,7 @@ exports[`App Route /vehicles authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -11168,6 +11680,33 @@ exports[`App Route /vehicles authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
|
|||||||
@@ -17,6 +17,9 @@ const Main = ({ vin }) => {
|
|||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setVIN(vin);
|
setVIN(vin);
|
||||||
|
return () => {
|
||||||
|
setVIN(null)
|
||||||
|
}
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [vin]);
|
}, [vin]);
|
||||||
|
|
||||||
@@ -45,7 +48,7 @@ const Main = ({ vin }) => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const CANSignals = (props) => (
|
const CANSignals = (props) => (
|
||||||
<CANSignalProvider {...{token:props.token}}>
|
<CANSignalProvider {...{ token: props.token }}>
|
||||||
<Main {...props} />
|
<Main {...props} />
|
||||||
</CANSignalProvider>
|
</CANSignalProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import {
|
|||||||
VehicleProvider
|
VehicleProvider
|
||||||
} from "../../Contexts/VehicleContext";
|
} from "../../Contexts/VehicleContext";
|
||||||
import DigitalTwin from "../../DigitalTwin";
|
import DigitalTwin from "../../DigitalTwin";
|
||||||
|
import VehiclePathsMap from "../../VehiclePathsMap";
|
||||||
import useStyles from "../../useStyles";
|
import useStyles from "../../useStyles";
|
||||||
|
|
||||||
const REQUEST_INTERVAL = 10000;
|
const REQUEST_INTERVAL = 10000;
|
||||||
@@ -57,7 +58,10 @@ const Main = (props) => {
|
|||||||
<div>
|
<div>
|
||||||
<b>ICC Connected</b>: {carState?.online_hmi.toString()}
|
<b>ICC Connected</b>: {carState?.online_hmi.toString()}
|
||||||
</div>
|
</div>
|
||||||
<DigitalTwin {...carState} />
|
<DigitalTwin {...carState} vin={vin} />
|
||||||
|
<div style={{ width: '100vh' }}>
|
||||||
|
<VehiclePathsMap vinsToShowOnMapColors={new Map([[vin, 'navy']])} lookbackHours={24} />
|
||||||
|
</div>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -220,6 +220,134 @@ exports[`DigitalTwinTab Render 1`] = `
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div
|
||||||
|
style="width: 100vh;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
data-testid="mocked-vehicleprovider"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-container leaflet-touch leaflet-grab leaflet-touch-drag leaflet-touch-zoom"
|
||||||
|
style="width: 100%; height: 900px; position: relative;"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-map-pane"
|
||||||
|
style="left: 0px; top: 0px;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-tile-pane"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-layer "
|
||||||
|
style="z-index: 1;"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-tile-container leaflet-zoom-animated"
|
||||||
|
style="z-index: 18; left: 0px; top: 0px;"
|
||||||
|
>
|
||||||
|
<img
|
||||||
|
alt=""
|
||||||
|
class="leaflet-tile"
|
||||||
|
role="presentation"
|
||||||
|
src="https://b.tile.openstreetmap.org/5/7/12.png"
|
||||||
|
style="width: 256px; height: 256px; left: -126px; top: -114px;"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-overlay-pane"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-shadow-pane"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-marker-pane"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-tooltip-pane"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-pane leaflet-popup-pane"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="leaflet-control-container"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-top leaflet-left"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-control-zoom leaflet-bar leaflet-control"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
aria-label="Zoom in"
|
||||||
|
class="leaflet-control-zoom-in"
|
||||||
|
href="#"
|
||||||
|
role="button"
|
||||||
|
title="Zoom in"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
+
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
aria-label="Zoom out"
|
||||||
|
class="leaflet-control-zoom-out"
|
||||||
|
href="#"
|
||||||
|
role="button"
|
||||||
|
title="Zoom out"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
−
|
||||||
|
</span>
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div
|
||||||
|
class="leaflet-top leaflet-right"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-bottom leaflet-left"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="leaflet-bottom leaflet-right"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="leaflet-control-attribution leaflet-control"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="https://leafletjs.com"
|
||||||
|
title="A JavaScript library for interactive maps"
|
||||||
|
>
|
||||||
|
Leaflet
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<span
|
||||||
|
aria-hidden="true"
|
||||||
|
>
|
||||||
|
|
|
||||||
|
</span>
|
||||||
|
©
|
||||||
|
<a
|
||||||
|
href="http://osm.org/copyright"
|
||||||
|
>
|
||||||
|
OpenStreetMap
|
||||||
|
</a>
|
||||||
|
contributors
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -88,7 +88,19 @@ export const VehicleProvider = ({ children }) => {
|
|||||||
setBusy(true);
|
setBusy(true);
|
||||||
const result = await api.getLocations(token);
|
const result = await api.getLocations(token);
|
||||||
if (result.error)
|
if (result.error)
|
||||||
throw new Error(`Get locations error. ${result.message}`);
|
throw new Error(`Get locations vehicle paths error. ${result.message}`);
|
||||||
|
return result;
|
||||||
|
} finally {
|
||||||
|
setBusy(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getLocationsVehiclePaths = async (token, vinsParam) => {
|
||||||
|
try {
|
||||||
|
setBusy(true);
|
||||||
|
const result = await api.getLocationsVehiclePaths(token, vinsParam);
|
||||||
|
if (result.error)
|
||||||
|
throw new Error(`Get locations vehicle paths error. ${result.message}`);
|
||||||
return result;
|
return result;
|
||||||
} finally {
|
} finally {
|
||||||
setBusy(false);
|
setBusy(false);
|
||||||
@@ -263,6 +275,7 @@ export const VehicleProvider = ({ children }) => {
|
|||||||
getCANSignals,
|
getCANSignals,
|
||||||
getECUs,
|
getECUs,
|
||||||
getLocations,
|
getLocations,
|
||||||
|
getLocationsVehiclePaths,
|
||||||
getModels,
|
getModels,
|
||||||
getState,
|
getState,
|
||||||
getYears,
|
getYears,
|
||||||
|
|||||||
@@ -98,14 +98,13 @@ export const useVehicleContext = () => ({
|
|||||||
vehicles,
|
vehicles,
|
||||||
years,
|
years,
|
||||||
addVehicle: jest.fn(),
|
addVehicle: jest.fn(),
|
||||||
getConnections: jest.fn((vins, _token) => {
|
getConnections: jest
|
||||||
|
.fn().mockImplementation((vins, _token) => {
|
||||||
const result = {};
|
const result = {};
|
||||||
|
|
||||||
vins.forEach((vin) => {
|
vins.forEach((vin) => {
|
||||||
result[vin] = true;
|
result[vin] = true;
|
||||||
});
|
});
|
||||||
|
return Promise.resolve(result);
|
||||||
return result;
|
|
||||||
}),
|
}),
|
||||||
getECUs: jest.fn(() => {
|
getECUs: jest.fn(() => {
|
||||||
return {
|
return {
|
||||||
@@ -134,6 +133,13 @@ export const useVehicleContext = () => ({
|
|||||||
.mockResolvedValue([
|
.mockResolvedValue([
|
||||||
{ altitude: 5, longitude: 10, latitude: 15, vin: "TESTVIN123" },
|
{ altitude: 5, longitude: 10, latitude: 15, vin: "TESTVIN123" },
|
||||||
]),
|
]),
|
||||||
|
getLocationsVehiclePaths: jest
|
||||||
|
.fn()
|
||||||
|
.mockResolvedValue({
|
||||||
|
// tests only pass without mocking the data here
|
||||||
|
// '3FAFP13P31R199430': [[16.891136999999986, 26.832352999999955], [56.891136999999986, 66.832352999999955], [26.891136999999986, 36.832352999999955]],
|
||||||
|
// '3FAFP13P71R199060': [[36.891136999999986, 46.832352999999955], [76.891136999999986, 16.832352999999955]],
|
||||||
|
}),
|
||||||
getModels: jest.fn(() => {
|
getModels: jest.fn(() => {
|
||||||
models = ["Ocean", "PEAR"];
|
models = ["Ocean", "PEAR"];
|
||||||
}),
|
}),
|
||||||
|
|||||||
@@ -12,6 +12,8 @@ import { default as React, useEffect, useState } from "react";
|
|||||||
import { hasRole, Permissions } from "../../utils/roles";
|
import { hasRole, Permissions } from "../../utils/roles";
|
||||||
import { useUserContext } from "../Contexts/UserContext";
|
import { useUserContext } from "../Contexts/UserContext";
|
||||||
import { ExpandableSideMenuItem, MenuItem } from "./MenuItem";
|
import { ExpandableSideMenuItem, MenuItem } from "./MenuItem";
|
||||||
|
import { getCustomDashboardSubmenu } from "../../services/customDashboards"
|
||||||
|
|
||||||
const menuData = [
|
const menuData = [
|
||||||
{
|
{
|
||||||
label: "Home",
|
label: "Home",
|
||||||
@@ -48,6 +50,7 @@ const menuData = [
|
|||||||
url: `${process.env.REACT_APP_SUPERSET_URL}/login`,
|
url: `${process.env.REACT_APP_SUPERSET_URL}/login`,
|
||||||
icon: <AssessmentIcon />,
|
icon: <AssessmentIcon />,
|
||||||
rolesPerProvider: Permissions.FiskerMagnaRead,
|
rolesPerProvider: Permissions.FiskerMagnaRead,
|
||||||
|
submenus: getCustomDashboardSubmenu(Permissions.FiskerMagnaRead),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
label: "Suppliers",
|
label: "Suppliers",
|
||||||
|
|||||||
@@ -188,6 +188,7 @@ exports[`SideMenu Authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -226,6 +227,33 @@ exports[`SideMenu Authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -469,6 +497,7 @@ exports[`SideMenu Magna Authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
aria-disabled="false"
|
aria-disabled="false"
|
||||||
@@ -507,6 +536,33 @@ exports[`SideMenu Magna Authenticated 1`] = `
|
|||||||
/>
|
/>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
</span>
|
||||||
|
<ul
|
||||||
|
style="margin-left: 50px;"
|
||||||
|
>
|
||||||
|
<li>
|
||||||
|
<a
|
||||||
|
aria-disabled="false"
|
||||||
|
class="MuiButtonBase-root MuiListItem-root MuiListItem-gutters MuiListItem-button"
|
||||||
|
href="/dashboards/0"
|
||||||
|
role="button"
|
||||||
|
tabindex="0"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="MuiListItemText-root"
|
||||||
|
>
|
||||||
|
<span
|
||||||
|
class="MuiTypography-root MuiListItemText-primary MuiTypography-body1 MuiTypography-displayBlock"
|
||||||
|
>
|
||||||
|
Vehicle Map
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="MuiTouchRipple-root"
|
||||||
|
/>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
<span>
|
<span>
|
||||||
<li>
|
<li>
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -41,8 +41,8 @@ const VehiclePopUp = (props) => {
|
|||||||
<DialogTitle align="center" onClose={onClose}>
|
<DialogTitle align="center" onClose={onClose}>
|
||||||
{vin}
|
{vin}
|
||||||
{" "}
|
{" "}
|
||||||
<IconButton>
|
<IconButton onClick={toggleView}>
|
||||||
<VisibilityIcon fontSize="inherit" onClick={toggleView} />
|
<VisibilityIcon fontSize="inherit" />
|
||||||
</IconButton>
|
</IconButton>
|
||||||
</DialogTitle>
|
</DialogTitle>
|
||||||
<div align="center" className={classes.popUpContent}>
|
<div align="center" className={classes.popUpContent}>
|
||||||
|
|||||||
253
src/components/VehiclePathsMap/index.jsx
Normal file
253
src/components/VehiclePathsMap/index.jsx
Normal file
@@ -0,0 +1,253 @@
|
|||||||
|
import { Button } from "@material-ui/core";
|
||||||
|
import L from "leaflet";
|
||||||
|
import React, { useEffect, useState } from "react";
|
||||||
|
import { MapContainer, Marker, Polyline, Popup, TileLayer, useMap } from "react-leaflet";
|
||||||
|
import useStyles from "../useStyles";
|
||||||
|
|
||||||
|
import GrayMarkerIcon from "../../assets/gray-marker.png";
|
||||||
|
import GreenMarkerIcon from "../../assets/green-marker.png";
|
||||||
|
import { logger } from "../../services/monitoring";
|
||||||
|
import { ValidateLocationVehiclePathsData } from "../../utils/locations";
|
||||||
|
import { useUserContext } from "../Contexts/UserContext";
|
||||||
|
import { useVehicleContext, VehicleProvider } from "../Contexts/VehicleContext";
|
||||||
|
import { VehiclePopUp } from "../VehicleMap/popup";
|
||||||
|
|
||||||
|
const ComponentVehiclePathsMap = (props) => {
|
||||||
|
const classes = useStyles();
|
||||||
|
const {
|
||||||
|
token: {
|
||||||
|
idToken: { jwtToken: token },
|
||||||
|
},
|
||||||
|
} = useUserContext();
|
||||||
|
const { getConnections, getLocationsVehiclePaths, getState } = useVehicleContext();
|
||||||
|
|
||||||
|
const REQUEST_INTERVAL = 10000;
|
||||||
|
|
||||||
|
const [center, setCenter] = useState([0, 0]);
|
||||||
|
const [zoom, setZoom] = useState(2);
|
||||||
|
const [markers, setMarkers] = useState([]);
|
||||||
|
const [connections, setConnections] = useState({});
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!token) return;
|
||||||
|
retrieveAndStoreLocations(token).then((points) => {
|
||||||
|
centerAroundMarkers(points);
|
||||||
|
});
|
||||||
|
const id = setInterval(function () {
|
||||||
|
retrieveAndStoreLocations(token);
|
||||||
|
}, REQUEST_INTERVAL);
|
||||||
|
return () => {
|
||||||
|
clearInterval(id);
|
||||||
|
};
|
||||||
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
|
}, [token]);
|
||||||
|
|
||||||
|
const retrieveAndStoreLocations = (accessToken) => {
|
||||||
|
let vinsToShowOnMap = [...props.vinsToShowOnMapColors.keys()];
|
||||||
|
let vinsParam = ""
|
||||||
|
for (let vinToShowOnMap of vinsToShowOnMap) {
|
||||||
|
vinsParam += "vins="
|
||||||
|
vinsParam += vinToShowOnMap
|
||||||
|
vinsParam += "&"
|
||||||
|
}
|
||||||
|
vinsParam += "lookback_hours="
|
||||||
|
vinsParam += props.lookbackHours
|
||||||
|
|
||||||
|
return getLocationsVehiclePaths(accessToken, vinsParam)
|
||||||
|
.then((result) => {
|
||||||
|
let resultArray = Object.entries(result)
|
||||||
|
const points = []
|
||||||
|
|
||||||
|
// validate each location
|
||||||
|
for (let vinLocations of resultArray) {
|
||||||
|
let path = []
|
||||||
|
path[0] = vinLocations[0]
|
||||||
|
path[1] = []
|
||||||
|
for (let location of vinLocations[1]) {
|
||||||
|
if (ValidateLocationVehiclePathsData(location) !== false) {
|
||||||
|
path[1].push(location);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
points.push(path)
|
||||||
|
}
|
||||||
|
|
||||||
|
setMarkers(points);
|
||||||
|
return points;
|
||||||
|
})
|
||||||
|
.catch((error) => logger.warn(error.stack));
|
||||||
|
};
|
||||||
|
|
||||||
|
const centerAroundMarkers = (points) => {
|
||||||
|
// default center
|
||||||
|
let center = [37.0902, -95.7129]
|
||||||
|
|
||||||
|
// center is the very first geographical point
|
||||||
|
if (points && points[0] && points[0][1] && points[0][1][0]) {
|
||||||
|
center = points[0][1][0]
|
||||||
|
}
|
||||||
|
|
||||||
|
setCenter(center);
|
||||||
|
setZoom(4.5);
|
||||||
|
};
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!token) return;
|
||||||
|
|
||||||
|
const vins = []
|
||||||
|
|
||||||
|
for (let vinLocations of markers) {
|
||||||
|
vins.push(vinLocations[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
if (vins.length === 0) return;
|
||||||
|
|
||||||
|
getConnections(vins, token).then((conns) => {
|
||||||
|
setConnections(conns);
|
||||||
|
});
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [markers, token]);
|
||||||
|
|
||||||
|
const [selectedVIN, setSelectedVIN] = useState(null);
|
||||||
|
const [carState, setCarState] = useState(null);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectedVIN != null) {
|
||||||
|
retrieveAndStoreCarState(selectedVIN);
|
||||||
|
const id = setInterval(function () {
|
||||||
|
retrieveAndStoreCarState(selectedVIN);
|
||||||
|
}, REQUEST_INTERVAL);
|
||||||
|
return () => {
|
||||||
|
clearInterval(id);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
// eslint-disable-next-line
|
||||||
|
}, [selectedVIN]);
|
||||||
|
|
||||||
|
const selectCar = (e, vin) => {
|
||||||
|
e.preventDefault();
|
||||||
|
setSelectedVIN(vin);
|
||||||
|
};
|
||||||
|
|
||||||
|
const retrieveAndStoreCarState = (vin) => {
|
||||||
|
getState(token, vin).then((results) => {
|
||||||
|
setCarState({ ...results.data, vin: vin });
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleClose = () => {
|
||||||
|
setSelectedVIN(null);
|
||||||
|
setCarState(null);
|
||||||
|
};
|
||||||
|
|
||||||
|
const isOnline = (vin) => {
|
||||||
|
return connections[vin];
|
||||||
|
};
|
||||||
|
|
||||||
|
const getZIndex = (vin) => {
|
||||||
|
if (isOnline(vin)) return 1000;
|
||||||
|
return 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
function getCarIcon(vin) {
|
||||||
|
let icon = GrayMarkerIcon;
|
||||||
|
|
||||||
|
if (isOnline(vin)) {
|
||||||
|
icon = GreenMarkerIcon;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new L.Icon({
|
||||||
|
iconUrl: icon,
|
||||||
|
iconAnchor: [24, 42],
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
return (
|
||||||
|
<MapContainer
|
||||||
|
center={center}
|
||||||
|
zoom={zoom}
|
||||||
|
style={{
|
||||||
|
width: "100%",
|
||||||
|
height: "900px",
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<TileLayer
|
||||||
|
attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
|
||||||
|
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
|
||||||
|
/>
|
||||||
|
<CenterFocus center={center} zoom={zoom} />
|
||||||
|
{markers && markers.map((vinLocations) => (
|
||||||
|
<div key={vinLocations[0]}>
|
||||||
|
<Polyline
|
||||||
|
key={'line' + vinLocations[0]}
|
||||||
|
positions={vinLocations[1]}
|
||||||
|
pathOptions={{
|
||||||
|
color: props.vinsToShowOnMapColors && props.vinsToShowOnMapColors.get(vinLocations[0]),
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{vinLocations[1][0] &&
|
||||||
|
<Marker
|
||||||
|
icon={getCarIcon(vinLocations[0])}
|
||||||
|
key={'marker' + vinLocations[0]}
|
||||||
|
position={vinLocations[1][0]}
|
||||||
|
title={vinLocations[0]}
|
||||||
|
opacity={0.9}
|
||||||
|
zIndexOffset={getZIndex(vinLocations[0])}
|
||||||
|
eventHandlers={{
|
||||||
|
click: () => {
|
||||||
|
setCenter(vinLocations[1][0]);
|
||||||
|
setZoom(16);
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Popup>
|
||||||
|
<div align="center">
|
||||||
|
<p className={classes.markerTitle}>
|
||||||
|
<b>{vinLocations[0]}</b>
|
||||||
|
</p>
|
||||||
|
<Button
|
||||||
|
type="submit"
|
||||||
|
variant="contained"
|
||||||
|
color="primary"
|
||||||
|
onClick={(e) => selectCar(e, vinLocations[0])}
|
||||||
|
>
|
||||||
|
View Stats
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Popup>
|
||||||
|
</Marker>
|
||||||
|
}
|
||||||
|
</div>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{carState ? (
|
||||||
|
<VehiclePopUp
|
||||||
|
{...carState}
|
||||||
|
className={classes.popup}
|
||||||
|
onClose={handleClose}
|
||||||
|
/>
|
||||||
|
) : null}
|
||||||
|
</MapContainer>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const CenterFocus = ({ center, zoom }) => {
|
||||||
|
const map = useMap();
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (center[0] === 0 && center[1] === 0) {
|
||||||
|
map.flyTo([0, 0], 2, { duration: 1.5 });
|
||||||
|
} else {
|
||||||
|
map.flyTo(center, zoom, { duration: 1.5 });
|
||||||
|
}
|
||||||
|
}, [center, zoom, map]);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
|
||||||
|
const VehiclePathsMap = (props) => (
|
||||||
|
<VehicleProvider>
|
||||||
|
<ComponentVehiclePathsMap vinsToShowOnMapColors={props.vinsToShowOnMapColors} lookbackHours={props.lookbackHours} />
|
||||||
|
</VehicleProvider>
|
||||||
|
);
|
||||||
|
|
||||||
|
export default VehiclePathsMap;
|
||||||
@@ -55,13 +55,15 @@ const ecusData = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const signals = {data:[
|
const signals = {
|
||||||
|
data: [
|
||||||
{
|
{
|
||||||
timestamp: "2021-07-14T20:09:40.98187Z",
|
timestamp: "2021-07-14T20:09:40.98187Z",
|
||||||
name: "signal",
|
name: "signal",
|
||||||
value: 123
|
value: 123
|
||||||
},
|
},
|
||||||
]};
|
],
|
||||||
|
};
|
||||||
|
|
||||||
const trexLogs = {
|
const trexLogs = {
|
||||||
RealOffset: 0,
|
RealOffset: 0,
|
||||||
@@ -127,6 +129,12 @@ const vehiclesAPI = {
|
|||||||
.mockResolvedValue([
|
.mockResolvedValue([
|
||||||
{ altitude: 5, longitude: 10, latitude: 15, vin: "TESTVIN123" },
|
{ altitude: 5, longitude: 10, latitude: 15, vin: "TESTVIN123" },
|
||||||
]),
|
]),
|
||||||
|
getLocationsVehiclePaths: async () => {
|
||||||
|
return {
|
||||||
|
'3FAFP13P31R199430': [[16.891136999999986, 26.832352999999955], [56.891136999999986, 66.832352999999955], [26.891136999999986, 36.832352999999955]],
|
||||||
|
'3FAFP13P71R199060': [[36.891136999999986, 46.832352999999955], [76.891136999999986, 16.832352999999955]],
|
||||||
|
};
|
||||||
|
},
|
||||||
getVehicle: async (vin) => {
|
getVehicle: async (vin) => {
|
||||||
const index = data.findIndex(element => element.vin === vin);
|
const index = data.findIndex(element => element.vin === vin);
|
||||||
return data[index];
|
return data[index];
|
||||||
@@ -134,7 +142,7 @@ const vehiclesAPI = {
|
|||||||
getVehicles: async () => {
|
getVehicles: async () => {
|
||||||
return { data };
|
return { data };
|
||||||
},
|
},
|
||||||
getFleets: async (vin) => {return { data: ["fleet1", "fleet2"]}},
|
getFleets: async (vin) => { return { data: ["fleet1", "fleet2"] } },
|
||||||
getYears: async () => {
|
getYears: async () => {
|
||||||
return {
|
return {
|
||||||
data: [2021, 2022],
|
data: [2021, 2022],
|
||||||
|
|||||||
@@ -1,8 +1,30 @@
|
|||||||
|
import VehiclePathsMap from "../components/VehiclePathsMap";
|
||||||
|
|
||||||
const INVALID_DASHBOARD = {
|
const INVALID_DASHBOARD = {
|
||||||
label: "Invalid Dashboard",
|
label: "Invalid Dashboard",
|
||||||
error: "Invalid Dashboard"
|
error: "Invalid Dashboard"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const vinsToShowOnMapColors = new Map([
|
||||||
|
['3FAFP13P71R199267', 'red'],
|
||||||
|
['3FAFP13P71R199270', 'orange'],
|
||||||
|
['3FAFP13P71R199222', 'blue'],
|
||||||
|
['3FAFP13P61R199339', 'yellow'],
|
||||||
|
['3FAFP13P71R199057', 'turquoise'],
|
||||||
|
['3FAFP13P61R199387', 'lime'],
|
||||||
|
['3FAFP13P71R199334', 'purple'],
|
||||||
|
['3FAFP13P71R199284', 'green'],
|
||||||
|
['3FAFP13P71R199303', 'sienna'],
|
||||||
|
['3FAFP13P31R199430', 'navy'],
|
||||||
|
['3FAFP13P81R199083', 'cadetblue'],
|
||||||
|
['3FAFP13P71R199060', 'coral'],
|
||||||
|
['3FAFP13P71R199317', 'darkkhaki'],
|
||||||
|
['3FAFP13P71R199320', 'fuchsia'],
|
||||||
|
['3FAFP13P61R199390', 'indigo'],
|
||||||
|
['3FAFP13P61R199373', 'cyan'],
|
||||||
|
])
|
||||||
|
const lookbackHours = 24
|
||||||
|
|
||||||
export const CustomDashboardList = [
|
export const CustomDashboardList = [
|
||||||
/*
|
/*
|
||||||
{
|
{
|
||||||
@@ -14,6 +36,11 @@ export const CustomDashboardList = [
|
|||||||
component: <MyCustomComponent />
|
component: <MyCustomComponent />
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
{
|
||||||
|
label: "Vehicle Map",
|
||||||
|
component: <VehiclePathsMap vinsToShowOnMapColors={vinsToShowOnMapColors} lookbackHours={lookbackHours} />
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
export const getCustomDashboard = (index) => {
|
export const getCustomDashboard = (index) => {
|
||||||
|
|||||||
@@ -76,6 +76,17 @@ const vehiclesAPI = {
|
|||||||
.then(fetchRespHandler)
|
.then(fetchRespHandler)
|
||||||
.catch(errorHandler),
|
.catch(errorHandler),
|
||||||
|
|
||||||
|
getLocationsVehiclePaths: async (token, vinsParam) =>
|
||||||
|
fetch(`${API_ENDPOINT}/vehicle_paths?${vinsParam}`, {
|
||||||
|
method: "GET",
|
||||||
|
headers: Object.assign(
|
||||||
|
{ "Content-Type": "application/json" },
|
||||||
|
getAuthHeaderOptions(token)
|
||||||
|
),
|
||||||
|
})
|
||||||
|
.then(fetchRespHandler)
|
||||||
|
.catch(errorHandler),
|
||||||
|
|
||||||
getState: async (token, vin) =>
|
getState: async (token, vin) =>
|
||||||
fetch(`${API_ENDPOINT}/carstate?vin=${vin}`, {
|
fetch(`${API_ENDPOINT}/carstate?vin=${vin}`, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
@@ -185,7 +196,7 @@ const vehiclesAPI = {
|
|||||||
.then(fetchRespHandler)
|
.then(fetchRespHandler)
|
||||||
.catch(errorHandler),
|
.catch(errorHandler),
|
||||||
|
|
||||||
getVersionLog: async ({vin, ...search}, token) => {
|
getVersionLog: async ({ vin, ...search }, token) => {
|
||||||
const u = addQueryParams(`${API_ENDPOINT}/vehicle/${vin}/version/logs`, search);
|
const u = addQueryParams(`${API_ENDPOINT}/vehicle/${vin}/version/logs`, search);
|
||||||
return fetch(u, {
|
return fetch(u, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
|
|||||||
@@ -10,6 +10,15 @@ export const ValidateLocationData = (location) => {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const ValidateLocationVehiclePathsData = (location) => {
|
||||||
|
if (location.length < 2) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// location is an array of length 2 as {<latitude> float64, <longitude> float64}
|
||||||
|
return !(Math.abs(location[0]) > 90 || Math.abs(location[1]) > 180);
|
||||||
|
}
|
||||||
|
|
||||||
export const ValidateLocationByParam = (parameter, value) => {
|
export const ValidateLocationByParam = (parameter, value) => {
|
||||||
if (invalidLocation === value) return false;
|
if (invalidLocation === value) return false;
|
||||||
switch (parameter) {
|
switch (parameter) {
|
||||||
|
|||||||
Reference in New Issue
Block a user