|
|
@ -3,12 +3,12 @@ import L from 'leaflet'; |
|
|
|
import { Button, Col, Drawer, Row, Spin, Tree } from 'antd'; |
|
|
|
import { Button, Col, Drawer, Row, Spin, Tree } from 'antd'; |
|
|
|
import ApiProject from '../../services/api/modules/project'; |
|
|
|
import ApiProject from '../../services/api/modules/project'; |
|
|
|
import { store } from '../../appredux/store'; |
|
|
|
import { store } from '../../appredux/store'; |
|
|
|
import { getUserPoints, setMapLoading, setMymap, setOpenLeft, setOpenRight, setProjectTree, setSelectedFeature, setUserPoints } from '../../appredux/modules/map/actions'; |
|
|
|
import { getUserPoints, setMapLoading, setMymap, setOpenLeft, setOpenRight, setProjectTree, setSelectedFeature, setSelectedProjectIds, setUserPoints } from '../../appredux/modules/map/actions'; |
|
|
|
import ContentLoader from 'react-content-loader'; |
|
|
|
import ContentLoader from 'react-content-loader'; |
|
|
|
import { useSelector } from 'react-redux'; |
|
|
|
import { useSelector } from 'react-redux'; |
|
|
|
import MapLeftContent from '../../components/MapLeftContent'; |
|
|
|
import MapLeftContent from '../../components/MapLeftContent'; |
|
|
|
import MapRightContent from '../../components/MapRightContent'; |
|
|
|
import MapRightContent from '../../components/MapRightContent'; |
|
|
|
import { removeLayerByName } from '../../utils/MapUtils'; |
|
|
|
import { closePopup, removeLayerByName } from '../../utils/MapUtils'; |
|
|
|
import RoutingBar from '../../components/RoutingBarV2'; |
|
|
|
import RoutingBar from '../../components/RoutingBarV2'; |
|
|
|
import Loader from "react-loader-spinner"; |
|
|
|
import Loader from "react-loader-spinner"; |
|
|
|
import "react-loader-spinner/dist/loader/css/react-spinner-loader.css"; |
|
|
|
import "react-loader-spinner/dist/loader/css/react-spinner-loader.css"; |
|
|
@ -17,7 +17,11 @@ import "react-toastify/dist/ReactToastify.css"; |
|
|
|
import './MapMonitoring.css'; |
|
|
|
import './MapMonitoring.css'; |
|
|
|
import { BASE_SIMPRO_LUMEN_IMAGE } from '../../const/ApiConst'; |
|
|
|
import { BASE_SIMPRO_LUMEN_IMAGE } from '../../const/ApiConst'; |
|
|
|
import DEFAULT_USER_ICON from '../../assets/img/avatars/user.png'; |
|
|
|
import DEFAULT_USER_ICON from '../../assets/img/avatars/user.png'; |
|
|
|
|
|
|
|
import 'leaflet.markercluster/dist/MarkerCluster.Default.css' |
|
|
|
|
|
|
|
import 'leaflet.markercluster/dist/MarkerCluster.css' |
|
|
|
|
|
|
|
import 'leaflet.markercluster/dist/leaflet.markercluster.js' |
|
|
|
|
|
|
|
import 'leaflet-control-geocoder/dist/Control.Geocoder.css' |
|
|
|
|
|
|
|
import 'leaflet-control-geocoder/dist/Control.Geocoder.js' |
|
|
|
|
|
|
|
|
|
|
|
const MapMonitoring = () => { |
|
|
|
const MapMonitoring = () => { |
|
|
|
|
|
|
|
|
|
|
@ -33,11 +37,18 @@ const MapMonitoring = () => { |
|
|
|
lng: 120.13025155062624 |
|
|
|
lng: 120.13025155062624 |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
const {userPoints, mymap, openLeft, openRight, routingBarVisible, userHistory, isSearchingRoute} = useSelector(state => state.mapReducer); |
|
|
|
const {userPoints, mymap, openLeft, openRight, routingBarVisible, userHistory, isSearchingRoute, selectedFeature} = useSelector(state => state.mapReducer); |
|
|
|
const [gridMiddle, setGridMiddle] = useState(GRID_MIDDLE); |
|
|
|
const [gridMiddle, setGridMiddle] = useState(GRID_MIDDLE); |
|
|
|
const [gridLeft, setGridLeft] = useState(0); |
|
|
|
const [gridLeft, setGridLeft] = useState(0); |
|
|
|
const [gridRight, setGridRight] = useState(0); |
|
|
|
const [gridRight, setGridRight] = useState(0); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
let markerCluster = L.markerClusterGroup({ |
|
|
|
|
|
|
|
name: "userPointLayer", |
|
|
|
|
|
|
|
// disableClusteringAtZoom: 17,
|
|
|
|
|
|
|
|
showCoverageOnHover: false, |
|
|
|
|
|
|
|
// spiderfyOnMaxZoom: false
|
|
|
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
useEffect(() => { |
|
|
|
useEffect(() => { |
|
|
|
initMap(); |
|
|
|
initMap(); |
|
|
|
getMapLeftContent(); |
|
|
|
getMapLeftContent(); |
|
|
@ -58,7 +69,8 @@ const MapMonitoring = () => { |
|
|
|
onEachFeature: onEachFeatureUserPoints, |
|
|
|
onEachFeature: onEachFeatureUserPoints, |
|
|
|
pointToLayer: pointToLayerUserPoints |
|
|
|
pointToLayer: pointToLayerUserPoints |
|
|
|
}); |
|
|
|
}); |
|
|
|
userPointLayer.addTo(mymap); |
|
|
|
// userPointLayer.addTo(mymap);
|
|
|
|
|
|
|
|
mymap.addLayer(markerCluster); |
|
|
|
mymap.fitBounds(userPointLayer.getBounds()); |
|
|
|
mymap.fitBounds(userPointLayer.getBounds()); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
@ -87,14 +99,10 @@ const MapMonitoring = () => { |
|
|
|
store.dispatch(setMymap(mymap)); |
|
|
|
store.dispatch(setMymap(mymap)); |
|
|
|
// setMymap(mymap);
|
|
|
|
// setMymap(mymap);
|
|
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' }).addTo(mymap); |
|
|
|
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: '© <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors' }).addTo(mymap); |
|
|
|
|
|
|
|
// add searching location (nominatim) on map
|
|
|
|
|
|
|
|
L.Control.geocoder().addTo(mymap); |
|
|
|
mymap.on('click', (e) => { |
|
|
|
mymap.on('click', (e) => { |
|
|
|
if (!store.getState().mapReducer.routingBarVisible) { |
|
|
|
closePopup(); |
|
|
|
// only can close popup when routing mode is not visible
|
|
|
|
|
|
|
|
removeLayerByName('popupTemp'); |
|
|
|
|
|
|
|
store.dispatch(setOpenRight(false)); |
|
|
|
|
|
|
|
store.dispatch(setSelectedFeature(null)); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
}) |
|
|
|
}) |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -102,7 +110,7 @@ const MapMonitoring = () => { |
|
|
|
const getMapLeftContent = async () => { |
|
|
|
const getMapLeftContent = async () => { |
|
|
|
store.dispatch(setMapLoading(true)); |
|
|
|
store.dispatch(setMapLoading(true)); |
|
|
|
let project = await ApiProject.list(); |
|
|
|
let project = await ApiProject.list(); |
|
|
|
console.log('project', project); |
|
|
|
// console.log('project', project);
|
|
|
|
if (project && project.status && project.data && project.data.length > 0) { |
|
|
|
if (project && project.status && project.data && project.data.length > 0) { |
|
|
|
let projectData = [ |
|
|
|
let projectData = [ |
|
|
|
{ |
|
|
|
{ |
|
|
@ -118,6 +126,9 @@ const MapMonitoring = () => { |
|
|
|
}) |
|
|
|
}) |
|
|
|
store.dispatch(setProjectTree(projectData)); |
|
|
|
store.dispatch(setProjectTree(projectData)); |
|
|
|
// console.log('projectData', projectData);
|
|
|
|
// console.log('projectData', projectData);
|
|
|
|
|
|
|
|
let selectedProject = project.data.map(n => n.id); |
|
|
|
|
|
|
|
// console.log('selectedProject', selectedProject);
|
|
|
|
|
|
|
|
store.dispatch(setSelectedProjectIds(selectedProject)) |
|
|
|
getUserPoints(); |
|
|
|
getUserPoints(); |
|
|
|
store.dispatch(setMapLoading(false)); |
|
|
|
store.dispatch(setMapLoading(false)); |
|
|
|
} |
|
|
|
} |
|
|
@ -134,18 +145,22 @@ const MapMonitoring = () => { |
|
|
|
}); |
|
|
|
}); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
const pointToLayerUserPoints = (feature, latlng) => { |
|
|
|
const renderClassMarker = (feature) => { |
|
|
|
// console.log('feature', feature);
|
|
|
|
let output = 'image-marker-red'; |
|
|
|
// create a marker style
|
|
|
|
if (selectedFeature?.properties?.user_id === feature?.properties?.user_id) { |
|
|
|
// let logoMarkerStyle = L.Icon.extend({
|
|
|
|
output = 'image-marker-active'; |
|
|
|
// options: {
|
|
|
|
} |
|
|
|
// iconSize: [85, 90],
|
|
|
|
else { |
|
|
|
// iconAnchor: [38, 86],
|
|
|
|
if (feature?.properties.presence_status === true) { |
|
|
|
// popupAnchor: [0, -80]
|
|
|
|
output = 'image-marker-green' |
|
|
|
// }
|
|
|
|
} |
|
|
|
// });
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return output; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// let logoMarker = new logoMarkerStyle({iconUrl: `${BASE_SIMPRO_LUMEN_IMAGE}/${feature.properties.image}`});
|
|
|
|
// styling points geojson
|
|
|
|
|
|
|
|
const pointToLayerUserPoints = (feature, latlng) => { |
|
|
|
let imgSrc = DEFAULT_USER_ICON; |
|
|
|
let imgSrc = DEFAULT_USER_ICON; |
|
|
|
if (feature && feature.properties && feature.properties.image && feature.properties.image !== '') { |
|
|
|
if (feature && feature.properties && feature.properties.image && feature.properties.image !== '') { |
|
|
|
imgSrc = `${BASE_SIMPRO_LUMEN_IMAGE}/${feature.properties.image}` |
|
|
|
imgSrc = `${BASE_SIMPRO_LUMEN_IMAGE}/${feature.properties.image}` |
|
|
@ -153,26 +168,20 @@ const MapMonitoring = () => { |
|
|
|
let img = `<img src="${imgSrc}" />` |
|
|
|
let img = `<img src="${imgSrc}" />` |
|
|
|
let logoMarker = L.divIcon({ |
|
|
|
let logoMarker = L.divIcon({ |
|
|
|
html: img, |
|
|
|
html: img, |
|
|
|
className: 'image-marker', |
|
|
|
// className: feature?.properties?.presence_status ? 'image-marker-green' : 'image-marker-red',
|
|
|
|
|
|
|
|
className: renderClassMarker(feature), |
|
|
|
iconSize: [40, 40], |
|
|
|
iconSize: [40, 40], |
|
|
|
iconAnchor: [20, 50], |
|
|
|
iconAnchor: [20, 50], |
|
|
|
popupAnchor: [0, -80] |
|
|
|
popupAnchor: [0, -80] |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
// let logoMarkerActive = L.divIcon({
|
|
|
|
|
|
|
|
// html: img,
|
|
|
|
|
|
|
|
// className: 'image-marker-active',
|
|
|
|
|
|
|
|
// iconSize: [40, 40],
|
|
|
|
|
|
|
|
// iconAnchor: [20, 50],
|
|
|
|
|
|
|
|
// popupAnchor: [0, -80]
|
|
|
|
|
|
|
|
// });
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// read the coordinates from your marker
|
|
|
|
// read the coordinates from your marker
|
|
|
|
let lat = feature.geometry.coordinates[1]; |
|
|
|
let lat = feature.geometry.coordinates[1]; |
|
|
|
let lon = feature.geometry.coordinates[0]; |
|
|
|
let lon = feature.geometry.coordinates[0]; |
|
|
|
|
|
|
|
|
|
|
|
// create a new marker using the icon style
|
|
|
|
// create a new marker using the icon style
|
|
|
|
let marker = new L.Marker([lat,lon],{icon: logoMarker}); |
|
|
|
let marker = new L.Marker([lat,lon],{icon: logoMarker}); |
|
|
|
|
|
|
|
markerCluster.addLayer(marker); |
|
|
|
return marker; |
|
|
|
return marker; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
@ -238,7 +247,7 @@ const MapMonitoring = () => { |
|
|
|
return ( |
|
|
|
return ( |
|
|
|
<Row> |
|
|
|
<Row> |
|
|
|
<Col span={gridLeft}> |
|
|
|
<Col span={gridLeft}> |
|
|
|
<MapLeftContent /> |
|
|
|
<MapLeftContent key={'map_left_content'} /> |
|
|
|
</Col> |
|
|
|
</Col> |
|
|
|
<Col span={gridMiddle}> |
|
|
|
<Col span={gridMiddle}> |
|
|
|
<div id="map-area" style={{ height: '90vh', width: '100%' }} ref={mapRef}></div> |
|
|
|
<div id="map-area" style={{ height: '90vh', width: '100%' }} ref={mapRef}></div> |
|
|
@ -261,7 +270,7 @@ const MapMonitoring = () => { |
|
|
|
)} |
|
|
|
)} |
|
|
|
</Col> |
|
|
|
</Col> |
|
|
|
<Col span={gridRight}> |
|
|
|
<Col span={gridRight}> |
|
|
|
<MapRightContent /> |
|
|
|
<MapRightContent key={'map_right_content'} /> |
|
|
|
</Col> |
|
|
|
</Col> |
|
|
|
<ToastContainer autoClose={5000} /> |
|
|
|
<ToastContainer autoClose={5000} /> |
|
|
|
</Row> |
|
|
|
</Row> |
|
|
|