Merge branch 'device-location-feature' into 'master'

Add  component to View device locations

See merge request entgra/carbon-device-mgt!500
4.x.x
Dharmakeerthi Lasantha 5 years ago
commit 0fdcc6cbd8

@ -36,6 +36,7 @@ import Certificates from './scenes/Home/scenes/Configurations/scenes/Certificate
import Devices from './scenes/Home/scenes/Devices'; import Devices from './scenes/Home/scenes/Devices';
import ViewPolicy from './scenes/Home/scenes/Policies/scenes/ViewPolicy'; import ViewPolicy from './scenes/Home/scenes/Policies/scenes/ViewPolicy';
import EditSelectedPolicy from './scenes/Home/scenes/Policies/scenes/EditSelectedPolicy'; import EditSelectedPolicy from './scenes/Home/scenes/Policies/scenes/EditSelectedPolicy';
import DeviceLocations from './scenes/Home/scenes/DeviceLocations';
const routes = [ const routes = [
{ {
@ -113,6 +114,11 @@ const routes = [
component: Notifications, component: Notifications,
exact: true, exact: true,
}, },
{
path: '/entgra/device-locations',
component: DeviceLocations,
exact: true,
},
], ],
}, },
]; ];

@ -150,6 +150,12 @@ class Home extends React.Component {
</Link> </Link>
</Menu.Item> </Menu.Item>
</SubMenu> </SubMenu>
<Menu.Item key="deviceLocations">
<Link to="/entgra/device-locations">
<Icon type="environment" />
<span>Device Location</span>
</Link>
</Menu.Item>
<Menu.Item className="profile" key="Notifications"> <Menu.Item className="profile" key="Notifications">
<Link to="/entgra/notifications"> <Link to="/entgra/notifications">
<span>Notifications</span> <span>Notifications</span>

@ -0,0 +1,254 @@
/*
* Copyright (c) 2020, 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 } from 'react';
import { Map, TileLayer, Marker, Popup, CircleMarker } from 'react-leaflet';
import L from 'leaflet';
import { withConfigContext } from '../../../../../../components/ConfigContext';
import axios from 'axios';
import { message, notification } from 'antd';
// const { Title, Text } = Typography;
// Icons for the location markers
const pinStart = new L.Icon({
iconUrl: require('./pin_start.svg'),
iconRetinaUrl: require('./pin_start.svg'),
shadowUrl: require('./pin_shadow.svg'),
shadowSize: new L.Point(51, 51),
shadowAnchor: [22, 22],
popupAnchor: [0, -22],
iconSize: new L.Point(50, 50),
tooltipAnchor: [0, -22],
});
class DeviceLocationMap extends Component {
constructor(props) {
super(props);
this.config = this.props.context;
this.customMap = React.createRef();
this.state = {
defaultZoomLevel: 3,
locations: [],
deviceData: {},
minLatitute: -37.43997405227057,
maxLatitute: 37.43997405227057,
minLongtitute: -151.171875,
maxLongtitute: 151.34765625,
zoomLevel: 3,
deviceName: null,
isPopup: false,
};
}
componentDidMount() {
this.getDeviceLocations(
-37.43997405227057,
37.43997405227057,
-151.171875,
151.34765625,
3,
);
}
getDeviceLocations = (
minLatitute,
maxLatitute,
minLongtitute,
maxLongtitute,
zoomLevel,
) => {
axios
.get(
window.location.origin +
this.config.serverConfig.invoker.uri +
this.config.serverConfig.invoker.deviceMgt +
'/geo-services/1.0.0/stats' +
'/device-locations?' +
'minLat=' +
minLatitute +
'&maxLat=' +
maxLatitute +
'&minLong=' +
minLongtitute +
'&maxLong=' +
maxLongtitute +
'&zoom=' +
zoomLevel,
)
.then(res => {
if (res.status === 200) {
// console.log(JSON.parse(res.data.data));
this.setState({
locations: JSON.parse(res.data.data),
});
}
})
.catch(error => {
if (error.hasOwnProperty('response') && error.response.status === 401) {
message.error('You are not logged in');
window.location.href = window.location.origin + '/entgra/login';
} else {
notification.error({
message: 'There was a problem',
duration: 0,
description: 'Error occurred while trying to fetch locations......',
});
}
});
};
setMarkers = positions => {
let markers = [];
positions.map(location => {
if (location.count > 1) {
markers.push(
<CircleMarker
key={location.deviceIdentification}
center={[
location.coordinates.latitude,
location.coordinates.longitude,
]}
radius={10}
fillOpacity={1}
color={'#c0392b'}
stroke={false}
>
<Popup>{location.count}</Popup>
</CircleMarker>,
);
} else {
markers.push(
<Marker
key={location.deviceIdentification}
icon={pinStart}
position={[
location.coordinates.latitude,
location.coordinates.longitude,
]}
onMouseOver={this
.mouseOver
// location.deviceType,
// location.deviceIdentification,
()}
onMouseOut={this.mouseOut}
>
<Popup
autoClose={true}
style={{ display: this.state.isPopup ? 'block' : 'none' }}
>
{/* {this.getPopupData(*/}
{/* // location.deviceType, // location.deviceIdentification, // )}*/}
{/* {this.state.deviceData.name}*/}
{this.state.deviceName}
</Popup>
</Marker>,
);
}
});
return (
<div>
{markers.map(markker => {
return markker;
})}
</div>
);
};
mouseOut = () => {
this.setState({
isPopup: false,
});
};
// todo get device details when mouse over the maker
mouseOver = (deviceType, deviceIdentification) => {
// let aaa = null;
// axios
// .get(
// window.location.origin +
// this.config.serverConfig.invoker.uri +
// this.config.serverConfig.invoker.deviceMgt +
// `/devices/1.0.0/${deviceType}/${deviceIdentification}`,
// )
// .then(res => {
// if (res.status === 200) {
// // console.log(res.data.data);
// this.setState({
// deviceData: res.data.data,
// isPopup: true,
// });
// // aaa = res.data.data;
// // return (
// // <div>
// // <Title>{aaa.name}</Title>
// // <Row>
// // <Text> Type : {aaa.type}</Text>
// // </Row>
// // <Row>
// // <Text> Status : {aaa.enrolmentInfo.status}</Text>
// // </Row>
// // <Row>
// // <Text> Owner : {aaa.enrolmentInfo.owner}</Text>
// // </Row>
// // </div>
// // );
// }
// })
// .catch(error => {
// if (error.hasOwnProperty('response') && error.response.status === 401) {
// message.error('You are not logged in');
// window.location.href = window.location.origin + '/entgra/login';
// } else {
// notification.error({
// message: 'There was a problem',
// duration: 0,
// description: 'Error occurred while trying to fetch locations......',
// });
// }
// });
};
// Todo : get bound and zoom level when doing movement and pass id to getDeviceLocations function
handleMovements = event => {
console.log(this.customMap.current.leafletElement.getZoom());
};
render() {
const position = [this.state.lat, this.state.lng];
const attribution = this.config.geoMap.attribution;
const url = this.config.geoMap.url;
return (
<div style={{ backgroundColor: '#ffffff', borderRadius: 5, padding: 5 }}>
<Map
ref={this.customMap}
center={position}
zoom={this.state.defaultZoomLevel}
resize={this.onResize}
onMoveEnd={this.handleMovements}
>
<TileLayer url={url} attribution={attribution} />
{this.setMarkers(this.state.locations)}
</Map>
</div>
);
}
}
export default withConfigContext(DeviceLocationMap);

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 69 KiB

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><defs><style>.a{fill:#414042;}.b{fill:#fff;}</style></defs><title>map</title><circle class="a" cx="50" cy="50" r="40.2134"/><circle class="b" cx="50" cy="50" r="18.64704"/></svg>

After

Width:  |  Height:  |  Size: 240 B

@ -0,0 +1,39 @@
import React from 'react';
import { Breadcrumb, PageHeader } from 'antd';
import DeviceLocationMap from './Component/DeviceLocationMap';
class DeviceLocations extends React.Component {
routes;
constructor(props) {
super(props);
this.routes = props.routes;
}
render() {
return (
<div>
<PageHeader style={{ paddingTop: 0 }}>
<Breadcrumb style={{ paddingBottom: 16 }}>
<Breadcrumb.Item>Devices Location</Breadcrumb.Item>
</Breadcrumb>
<div className="wrap">
<h3>Devices Location </h3>
</div>
</PageHeader>
<div
style={{
background: '#f0f2f5',
padding: 24,
minHeight: 720,
alignItems: 'center',
}}
>
<DeviceLocationMap />
</div>
</div>
);
}
}
export default DeviceLocations;
Loading…
Cancel
Save