diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/package.json b/components/device-mgt/io.entgra.device.mgt.ui/react-app/package.json index 31a539e7f60..3f4470ef197 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/package.json +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/package.json @@ -11,13 +11,18 @@ "bootstrap": "^4.3.1", "javascript-time-ago": "^2.0.1", "keymirror": "^0.1.1", + "leaflet": "^1.3.4", + "leaflet-routing-machine": "^3.2.12", "lodash.debounce": "^4.0.8", - "moment": "^2.24.0", + "moment": "latest", + "prop-types": "latest", "rc-viewer": "0.0.9", - "react-bootstrap": "^1.0.0-beta.12", + "react-advanced-datetimerange-picker": "^1.0.8", "react-highlight-words": "^0.16.0", "react-image-viewer-zoom": "^1.0.36", "react-infinite-scroller": "^1.2.4", + "react-leaflet": "^2.4.0", + "react-bootstrap": "^1.0.0-beta.12", "react-moment": "^0.9.2", "react-router": "^5.0.1", "react-router-config": "^5.0.1", diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/public/conf/config.json b/components/device-mgt/io.entgra.device.mgt.ui/react-app/public/conf/config.json index 0a78ea8abdb..aa72ba06e44 100644 --- a/components/device-mgt/io.entgra.device.mgt.ui/react-app/public/conf/config.json +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/public/conf/config.json @@ -33,5 +33,10 @@ "color": "#008cc4", "theme": "filled" } + }, + "geoMap": { + "url": "https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png", + "attribution": "© OpenStreetMap contributors", + "defaultZoomLevel": 16 } } diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/public/css/leaflet.css b/components/device-mgt/io.entgra.device.mgt.ui/react-app/public/css/leaflet.css new file mode 100644 index 00000000000..6f609e11801 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/public/css/leaflet.css @@ -0,0 +1,636 @@ +/* required styles */ + +.leaflet-pane, +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-tile-container, +.leaflet-pane > svg, +.leaflet-pane > canvas, +.leaflet-zoom-box, +.leaflet-image-layer, +.leaflet-layer { + position: absolute; + left: 0; + top: 0; +} +.leaflet-container { + overflow: hidden; +} +.leaflet-tile, +.leaflet-marker-icon, +.leaflet-marker-shadow { + -webkit-user-select: none; + -moz-user-select: none; + user-select: none; + -webkit-user-drag: none; +} +/* Safari renders non-retina tile on retina better with this, but Chrome is worse */ +.leaflet-safari .leaflet-tile { + image-rendering: -webkit-optimize-contrast; +} +/* hack that prevents hw layers "stretching" when loading new tiles */ +.leaflet-safari .leaflet-tile-container { + width: 1600px; + height: 1600px; + -webkit-transform-origin: 0 0; +} +.leaflet-marker-icon, +.leaflet-marker-shadow { + display: block; +} +/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */ +/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */ +.leaflet-container .leaflet-overlay-pane svg, +.leaflet-container .leaflet-marker-pane img, +.leaflet-container .leaflet-shadow-pane img, +.leaflet-container .leaflet-tile-pane img, +.leaflet-container img.leaflet-image-layer { + max-width: none !important; + max-height: none !important; +} + +.leaflet-container.leaflet-touch-zoom { + -ms-touch-action: pan-x pan-y; + touch-action: pan-x pan-y; +} +.leaflet-container.leaflet-touch-drag { + -ms-touch-action: pinch-zoom; + /* Fallback for FF which doesn't support pinch-zoom */ + touch-action: none; + touch-action: pinch-zoom; +} +.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom { + -ms-touch-action: none; + touch-action: none; +} +.leaflet-container { + -webkit-tap-highlight-color: transparent; +} +.leaflet-container a { + -webkit-tap-highlight-color: rgba(51, 181, 229, 0.4); +} +.leaflet-tile { + filter: inherit; + visibility: hidden; +} +.leaflet-tile-loaded { + visibility: inherit; +} +.leaflet-zoom-box { + width: 0; + height: 0; + -moz-box-sizing: border-box; + box-sizing: border-box; + z-index: 800; +} +/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */ +.leaflet-overlay-pane svg { + -moz-user-select: none; +} + +.leaflet-pane { z-index: 400; } + +.leaflet-tile-pane { z-index: 200; } +.leaflet-overlay-pane { z-index: 400; } +.leaflet-shadow-pane { z-index: 500; } +.leaflet-marker-pane { z-index: 600; } +.leaflet-tooltip-pane { z-index: 650; } +.leaflet-popup-pane { z-index: 700; } + +.leaflet-map-pane canvas { z-index: 100; } +.leaflet-map-pane svg { z-index: 200; } + +.leaflet-vml-shape { + width: 1px; + height: 1px; +} +.lvml { + behavior: url(#default#VML); + display: inline-block; + position: absolute; +} + + +/* control positioning */ + +.leaflet-control { + position: relative; + z-index: 800; + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; +} +.leaflet-top, +.leaflet-bottom { + position: absolute; + z-index: 1000; + pointer-events: none; +} +.leaflet-top { + top: 0; +} +.leaflet-right { + right: 0; +} +.leaflet-bottom { + bottom: 0; +} +.leaflet-left { + left: 0; +} +.leaflet-control { + float: left; + clear: both; +} +.leaflet-right .leaflet-control { + float: right; +} +.leaflet-top .leaflet-control { + margin-top: 10px; +} +.leaflet-bottom .leaflet-control { + margin-bottom: 10px; +} +.leaflet-left .leaflet-control { + margin-left: 10px; +} +.leaflet-right .leaflet-control { + margin-right: 10px; +} + + +/* zoom and fade animations */ + +.leaflet-fade-anim .leaflet-tile { + will-change: opacity; +} +.leaflet-fade-anim .leaflet-popup { + opacity: 0; + -webkit-transition: opacity 0.2s linear; + -moz-transition: opacity 0.2s linear; + -o-transition: opacity 0.2s linear; + transition: opacity 0.2s linear; +} +.leaflet-fade-anim .leaflet-map-pane .leaflet-popup { + opacity: 1; +} +.leaflet-zoom-animated { + -webkit-transform-origin: 0 0; + -ms-transform-origin: 0 0; + transform-origin: 0 0; +} +.leaflet-zoom-anim .leaflet-zoom-animated { + will-change: transform; +} +.leaflet-zoom-anim .leaflet-zoom-animated { + -webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1); + -moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1); + -o-transition: -o-transform 0.25s cubic-bezier(0,0,0.25,1); + transition: transform 0.25s cubic-bezier(0,0,0.25,1); +} +.leaflet-zoom-anim .leaflet-tile, +.leaflet-pan-anim .leaflet-tile { + -webkit-transition: none; + -moz-transition: none; + -o-transition: none; + transition: none; +} + +.leaflet-zoom-anim .leaflet-zoom-hide { + visibility: hidden; +} + + +/* cursors */ + +.leaflet-interactive { + cursor: pointer; +} +.leaflet-grab { + cursor: -webkit-grab; + cursor: -moz-grab; +} +.leaflet-crosshair, +.leaflet-crosshair .leaflet-interactive { + cursor: crosshair; +} +.leaflet-popup-pane, +.leaflet-control { + cursor: auto; +} +.leaflet-dragging .leaflet-grab, +.leaflet-dragging .leaflet-grab .leaflet-interactive, +.leaflet-dragging .leaflet-marker-draggable { + cursor: move; + cursor: -webkit-grabbing; + cursor: -moz-grabbing; +} + +/* marker & overlays interactivity */ +.leaflet-marker-icon, +.leaflet-marker-shadow, +.leaflet-image-layer, +.leaflet-pane > svg path, +.leaflet-tile-container { + pointer-events: none; +} + +.leaflet-marker-icon.leaflet-interactive, +.leaflet-image-layer.leaflet-interactive, +.leaflet-pane > svg path.leaflet-interactive { + pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */ + pointer-events: auto; +} + +/* visual tweaks */ + +.leaflet-container { + background: #ddd; + outline: 0; +} +.leaflet-container a { + color: #0078A8; +} +.leaflet-container a.leaflet-active { + outline: 2px solid orange; +} +.leaflet-zoom-box { + border: 2px dotted #38f; + background: rgba(255,255,255,0.5); +} + + +/* general typography */ +.leaflet-container { + font: 12px/1.5 "Helvetica Neue", Arial, Helvetica, sans-serif; +} + + +/* general toolbar styles */ + +.leaflet-bar { + box-shadow: 0 1px 5px rgba(0,0,0,0.65); + border-radius: 4px; +} +.leaflet-bar a, +.leaflet-bar a:hover { + background-color: #fff; + border-bottom: 1px solid #ccc; + width: 26px; + height: 26px; + line-height: 26px; + display: block; + text-align: center; + text-decoration: none; + color: black; +} +.leaflet-bar a, +.leaflet-control-layers-toggle { + background-position: 50% 50%; + background-repeat: no-repeat; + display: block; +} +.leaflet-bar a:hover { + background-color: #f4f4f4; +} +.leaflet-bar a:first-child { + border-top-left-radius: 4px; + border-top-right-radius: 4px; +} +.leaflet-bar a:last-child { + border-bottom-left-radius: 4px; + border-bottom-right-radius: 4px; + border-bottom: none; +} +.leaflet-bar a.leaflet-disabled { + cursor: default; + background-color: #f4f4f4; + color: #bbb; +} + +.leaflet-touch .leaflet-bar a { + width: 30px; + height: 30px; + line-height: 30px; +} +.leaflet-touch .leaflet-bar a:first-child { + border-top-left-radius: 2px; + border-top-right-radius: 2px; +} +.leaflet-touch .leaflet-bar a:last-child { + border-bottom-left-radius: 2px; + border-bottom-right-radius: 2px; +} + +/* zoom control */ + +.leaflet-control-zoom-in, +.leaflet-control-zoom-out { + font: bold 18px 'Lucida Console', Monaco, monospace; + text-indent: 1px; +} + +.leaflet-touch .leaflet-control-zoom-in, .leaflet-touch .leaflet-control-zoom-out { + font-size: 22px; +} + + +/* layers control */ + +.leaflet-control-layers { + box-shadow: 0 1px 5px rgba(0,0,0,0.4); + background: #fff; + border-radius: 5px; +} +.leaflet-control-layers-toggle { + background-image: url(images/layers.png); + width: 36px; + height: 36px; +} +.leaflet-retina .leaflet-control-layers-toggle { + background-image: url(images/layers-2x.png); + background-size: 26px 26px; +} +.leaflet-touch .leaflet-control-layers-toggle { + width: 44px; + height: 44px; +} +.leaflet-control-layers .leaflet-control-layers-list, +.leaflet-control-layers-expanded .leaflet-control-layers-toggle { + display: none; +} +.leaflet-control-layers-expanded .leaflet-control-layers-list { + display: block; + position: relative; +} +.leaflet-control-layers-expanded { + padding: 6px 10px 6px 6px; + color: #333; + background: #fff; +} +.leaflet-control-layers-scrollbar { + overflow-y: scroll; + overflow-x: hidden; + padding-right: 5px; +} +.leaflet-control-layers-selector { + margin-top: 2px; + position: relative; + top: 1px; +} +.leaflet-control-layers label { + display: block; +} +.leaflet-control-layers-separator { + height: 0; + border-top: 1px solid #ddd; + margin: 5px -10px 5px -6px; +} + +/* Default icon URLs */ +.leaflet-default-icon-path { + background-image: url(images/marker-icon.png); +} + + +/* attribution and scale controls */ + +.leaflet-container .leaflet-control-attribution { + background: #fff; + background: rgba(255, 255, 255, 0.7); + margin: 0; +} +.leaflet-control-attribution, +.leaflet-control-scale-line { + padding: 0 5px; + color: #333; +} +.leaflet-control-attribution a { + text-decoration: none; +} +.leaflet-control-attribution a:hover { + text-decoration: underline; +} +.leaflet-container .leaflet-control-attribution, +.leaflet-container .leaflet-control-scale { + font-size: 11px; +} +.leaflet-left .leaflet-control-scale { + margin-left: 5px; +} +.leaflet-bottom .leaflet-control-scale { + margin-bottom: 5px; +} +.leaflet-control-scale-line { + border: 2px solid #777; + border-top: none; + line-height: 1.1; + padding: 2px 5px 1px; + font-size: 11px; + white-space: nowrap; + overflow: hidden; + -moz-box-sizing: border-box; + box-sizing: border-box; + + background: #fff; + background: rgba(255, 255, 255, 0.5); +} +.leaflet-control-scale-line:not(:first-child) { + border-top: 2px solid #777; + border-bottom: none; + margin-top: -2px; +} +.leaflet-control-scale-line:not(:first-child):not(:last-child) { + border-bottom: 2px solid #777; +} + +.leaflet-touch .leaflet-control-attribution, +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + box-shadow: none; +} +.leaflet-touch .leaflet-control-layers, +.leaflet-touch .leaflet-bar { + border: 2px solid rgba(0,0,0,0.2); + background-clip: padding-box; +} + + +/* popup */ + +.leaflet-popup { + position: absolute; + text-align: center; + margin-bottom: 20px; +} +.leaflet-popup-content-wrapper { + padding: 1px; + text-align: left; + border-radius: 12px; +} +.leaflet-popup-content { + margin: 13px 19px; + line-height: 1.4; +} +.leaflet-popup-content p { + margin: 18px 0; +} +.leaflet-popup-tip-container { + width: 40px; + height: 20px; + position: absolute; + left: 50%; + margin-left: -20px; + overflow: hidden; + pointer-events: none; +} +.leaflet-popup-tip { + width: 17px; + height: 17px; + padding: 1px; + + margin: -10px auto 0; + + -webkit-transform: rotate(45deg); + -moz-transform: rotate(45deg); + -ms-transform: rotate(45deg); + -o-transform: rotate(45deg); + transform: rotate(45deg); +} +.leaflet-popup-content-wrapper, +.leaflet-popup-tip { + background: white; + color: #333; + box-shadow: 0 3px 14px rgba(0,0,0,0.4); +} +.leaflet-container a.leaflet-popup-close-button { + position: absolute; + top: 0; + right: 0; + padding: 4px 4px 0 0; + border: none; + text-align: center; + width: 18px; + height: 14px; + font: 16px/14px Tahoma, Verdana, sans-serif; + color: #c3c3c3; + text-decoration: none; + font-weight: bold; + background: transparent; +} +.leaflet-container a.leaflet-popup-close-button:hover { + color: #999; +} +.leaflet-popup-scrolled { + overflow: auto; + border-bottom: 1px solid #ddd; + border-top: 1px solid #ddd; +} + +.leaflet-oldie .leaflet-popup-content-wrapper { + zoom: 1; +} +.leaflet-oldie .leaflet-popup-tip { + width: 24px; + margin: 0 auto; + + -ms-filter: "progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678)"; + filter: progid:DXImageTransform.Microsoft.Matrix(M11=0.70710678, M12=0.70710678, M21=-0.70710678, M22=0.70710678); +} +.leaflet-oldie .leaflet-popup-tip-container { + margin-top: -1px; +} + +.leaflet-oldie .leaflet-control-zoom, +.leaflet-oldie .leaflet-control-layers, +.leaflet-oldie .leaflet-popup-content-wrapper, +.leaflet-oldie .leaflet-popup-tip { + border: 1px solid #999; +} + + +/* div icon */ + +.leaflet-div-icon { + background: #fff; + border: 1px solid #666; +} + + +/* Tooltip */ +/* Base styles for the element that has a tooltip */ +.leaflet-tooltip { + position: absolute; + padding: 6px; + background-color: #fff; + border: 1px solid #fff; + border-radius: 3px; + color: #222; + white-space: nowrap; + -webkit-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + pointer-events: none; + box-shadow: 0 1px 3px rgba(0,0,0,0.4); +} +.leaflet-tooltip.leaflet-clickable { + cursor: pointer; + pointer-events: auto; +} +.leaflet-tooltip-top:before, +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + position: absolute; + pointer-events: none; + border: 6px solid transparent; + background: transparent; + content: ""; +} + +/* Directions */ + +.leaflet-tooltip-bottom { + margin-top: 6px; +} +.leaflet-tooltip-top { + margin-top: -6px; +} +.leaflet-tooltip-bottom:before, +.leaflet-tooltip-top:before { + left: 50%; + margin-left: -6px; +} +.leaflet-tooltip-top:before { + bottom: 0; + margin-bottom: -12px; + border-top-color: #fff; +} +.leaflet-tooltip-bottom:before { + top: 0; + margin-top: -12px; + margin-left: -6px; + border-bottom-color: #fff; +} +.leaflet-tooltip-left { + margin-left: -6px; +} +.leaflet-tooltip-right { + margin-left: 6px; +} +.leaflet-tooltip-left:before, +.leaflet-tooltip-right:before { + top: 50%; + margin-top: -6px; +} +.leaflet-tooltip-left:before { + right: 0; + margin-right: -12px; + border-left-color: #fff; +} +.leaflet-tooltip-right:before { + left: 0; + margin-left: -12px; + border-right-color: #fff; +} \ No newline at end of file diff --git a/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Geo/geo-custom-map/GeoCustomMap.js b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Geo/geo-custom-map/GeoCustomMap.js new file mode 100644 index 00000000000..3c68ee0aaa3 --- /dev/null +++ b/components/device-mgt/io.entgra.device.mgt.ui/react-app/src/components/Geo/geo-custom-map/GeoCustomMap.js @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019, Entgra (pvt) Ltd. (http://entgra.io) All Rights Reserved. + * + * Entgra (pvt) Ltd. licenses this file to you under the Apache License, + * Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import React, {Component, Fragment} from "react"; +import { + Map, + TileLayer, + Marker, + Polyline, Popup, Tooltip +} from "react-leaflet"; +import {withConfigContext} from "../../../context/ConfigContext"; + +class GeoCustomMap extends Component { + + constructor(props) { + super(props); + } + + /** + * Polyline draw for historical locations + * @param locationData - location data object + * @returns content + */ + polylineMarker = (locationData) => { + + const polyMarkers = locationData + .map(locationPoint => { + return [locationPoint.latitude, locationPoint.longitude] + }); + + return ( +