aboutsummaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx')
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx677
1 files changed, 677 insertions, 0 deletions
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx
new file mode 100644
index 000000000..9637d745e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx
@@ -0,0 +1,677 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2020 highstreet technologies GmbH Intellectual Property. All rights reserved.
+ * =================================================================================================
+ * Licensed 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.
+ * ============LICENSE_END==========================================================================
+ */
+
+import * as React from 'react'
+import * as mapboxgl from 'mapbox-gl';
+import { RouteComponentProps, withRouter } from 'react-router-dom';
+
+
+import { Site } from '../../model/site';
+import { SelectSiteAction, ClearHistoryAction, SelectLinkAction } from '../../actions/detailsAction';
+import { OSM_STYLE, URL_API, URL_BASEPATH, URL_TILE_API } from '../../config';
+import { link } from '../../model/link';
+import MapPopup from './mapPopup';
+import { SetPopupPositionAction, SelectMultipleLinksAction, SelectMultipleSitesAction } from '../../actions/popupActions';
+import { Feature } from '../../model/Feature';
+import { HighlightLinkAction, HighlightSiteAction, SetCoordinatesAction, SetStatistics } from '../../actions/mapActions';
+import { addDistance, getUniqueFeatures, increaseBoundingBox } from '../../utils/mapUtils';
+import { IApplicationStoreState } from '../../../../../framework/src/store/applicationStore';
+import connect, { IDispatcher, Connect } from '../../../../../framework/src/flux/connect';
+import SearchBar from './searchBar';
+import { verifyResponse, IsTileServerReachableAction, handleConnectionError, setTileServerReachableAction, IsBusycheckingConnectivityAction } from '../../actions/connectivityAction';
+import ConnectionInfo from './connectionInfo'
+import mapLayerService from '../../utils/mapLayers';
+import Statistics from './statistics';
+import IconSwitch from './iconSwitch';
+import { addImages } from '../../services/mapImagesService';
+import { PopupElement } from '../../model/popupElements';
+import { Button } from '@material-ui/core';
+import { NavigateToApplication } from '../../../../../framework/src/actions/navigationActions';
+import customize from '../../../icons/customize.png';
+
+type coordinates = { lat: number, lon: number, zoom: number }
+
+let alarmElements: Feature[] = [];
+let map: mapboxgl.Map;
+let isLoadingInProgress = false;
+let notLoadedBoundingBoxes: mapboxgl.LngLatBounds[] = [];
+
+let lastBoundingBox: mapboxgl.LngLatBounds | null = null;
+let myRef = React.createRef<HTMLDivElement>();
+
+
+class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
+
+ constructor(props: mapProps) {
+ super(props);
+ //any state stuff
+ this.state = { isPopupOpen: false }
+
+ }
+
+ updateTheme(){
+ mapLayerService.settings=this.props.settings.themes;
+ if(this.props.settings.mapSettings?.networkMap.styling.theme){
+ mapLayerService.selectedTheme = this.props.settings.mapSettings?.networkMap.styling.theme;
+ }
+ }
+
+ updateOpacity(){
+ if(this.props.settings.mapSettings && this.props.settings.mapSettings.networkMap.tileOpacity){
+ mapLayerService.changeMapOpacity(map, Number(this.props.settings.mapSettings.networkMap.tileOpacity));
+ }
+ }
+
+ async componentDidMount() {
+
+ // resize the map, if menu gets collapsed
+ window.addEventListener("menu-resized", this.handleResize);
+
+ //pass themes to mapLayerService
+ this.updateTheme();
+
+ // try if connection to tile + topologyserver are available
+
+ try {
+ const tiles = await fetch(URL_TILE_API + '/10/0/0.png');
+ if (tiles.ok) {
+ this.props.setTileServerLoaded(true);
+ }else{
+ this.props.setTileServerLoaded(false);
+ }
+
+ } catch (error) {
+ this.props.setTileServerLoaded(false);
+ console.error("tileserver " + URL_TILE_API + " can't be reached.");
+ }
+
+ try {
+ const topology = await fetch(URL_API + "/info/count/all");
+ verifyResponse(topology);
+ } catch (error) {
+ this.props.handleConnectionError(error)
+ }
+
+ //both done
+ this.props.setConnectivityCheck(false);
+ //map loaded in componentDidUpdate
+ }
+
+ setupMap = () => {
+
+ let lat = this.props.lat;
+ let lon = this.props.lon;
+ let zoom = this.props.zoom;
+
+ if(this.props.settings.mapSettings){
+ if(this.props.settings.mapSettings.networkMap.startupPosition.latitude){
+ lat = Number(this.props.settings.mapSettings.networkMap.startupPosition.latitude)
+ }
+
+ if(this.props.settings.mapSettings.networkMap.startupPosition.longitude){
+ lon = Number(this.props.settings.mapSettings.networkMap.startupPosition.longitude)
+ }
+
+ if(this.props.settings.mapSettings.networkMap.startupPosition.zoom){
+ zoom = Number(this.props.settings.mapSettings.networkMap.startupPosition.zoom)
+ }
+
+ }
+
+ const coordinates = this.extractCoordinatesFromUrl();
+ // override lat/lon/zoom with coordinates from url, if available
+ if (this.areCoordinatesValid(coordinates)) {
+ lat = coordinates.lat;
+ lon = coordinates.lon;
+ zoom = !Number.isNaN(coordinates.zoom) ? coordinates.zoom : zoom;
+ }
+
+ map = new mapboxgl.Map({
+ container: myRef.current!,
+ style: OSM_STYLE as any,
+ center: [lon, lat],
+ zoom: zoom,
+ accessToken: ''
+ });
+
+ map.on('load', (ev) => {
+
+ map.setMaxZoom(18);
+ const bbox = map.getBounds();
+ this.props.updateMapPosition(bbox.getCenter().lat, bbox.getCenter().lng, map.getZoom())
+
+ mapLayerService.addBaseSources(map, this.props.selectedSite, this.props.selectedLink);
+
+ addImages(map, (result: boolean)=>{
+ if(map.getZoom()>11)
+ {
+ mapLayerService.addIconLayers(map, this.props.selectedSite?.properties.id)
+ }else{
+ mapLayerService.addBaseLayers(map);
+ }
+ this.updateOpacity();
+
+ });
+
+ const boundingBox = increaseBoundingBox(map);
+
+ fetch(`${URL_API}/links/geojson/${boundingBox.west},${boundingBox.south},${boundingBox.east},${boundingBox.north}`)
+ .then(result => verifyResponse(result))
+ .then(result => result.json())
+ .then(features => {
+ if (map.getSource('lines')) {
+ (map.getSource('lines') as mapboxgl.GeoJSONSource).setData(features);
+ }
+ })
+ .catch(error => this.props.handleConnectionError(error));
+
+
+ fetch(`${URL_API}/sites/geojson/${boundingBox.west},${boundingBox.south},${boundingBox.east},${boundingBox.north}`)
+ .then(result => verifyResponse(result))
+ .then(result => result.json())
+ .then(features => {
+ if (map.getSource('points')) {
+ (map.getSource('points') as mapboxgl.GeoJSONSource).setData(features);
+ }
+ })
+ .catch(error => this.props.handleConnectionError(error));
+ });
+
+ map.on('click', (e: any) => {
+
+ if (map.getLayer('points')) { // data is shown as points
+
+ var clickedLines = getUniqueFeatures(map.queryRenderedFeatures([[e.point.x - 5, e.point.y - 5],
+ [e.point.x + 5, e.point.y + 5]], {
+ layers: ['microwave-lines', 'fibre-lines']
+ }), "id");
+
+ const clickedPoints = getUniqueFeatures(map.queryRenderedFeatures(e.point, { layers: ['points'] }), "id");
+ const alarmedSites = getUniqueFeatures(map.queryRenderedFeatures(e.point, { layers: ['alarmedPoints'] }), "id");
+
+ if (clickedPoints.length != 0) {
+
+
+ if (alarmedSites.length > 0) {
+ alarmedSites.forEach(alarm => {
+ const index = clickedPoints.findIndex(item => item.properties!.id === alarm.properties!.id);
+
+ if (index !== -1) {
+ clickedPoints[index].properties!.alarmed = true;
+ clickedPoints[index].properties!.type = "alarmed";
+ }
+ });
+ }
+
+ this.showSitePopup(clickedPoints, e.point.x, e.point.y);
+ } else if (clickedLines.length != 0) {
+ this.showLinkPopup(clickedLines, e.point.x, e.point.y);
+ }
+
+
+ } else { // data is shown as icons
+
+ const clickedSites = getUniqueFeatures(map.queryRenderedFeatures(e.point, { layers: ['point-lamps', 'point-building', 'point-data-center', 'point-factory', 'point-remaining'] }), "id");
+ const clickedLines = getUniqueFeatures(map.queryRenderedFeatures([[e.point.x - 5, e.point.y - 5],
+ [e.point.x + 5, e.point.y + 5]], {
+ layers: ['microwave-lines', 'fibre-lines']
+ }), "id");
+
+ if (clickedSites.length > 0)
+ this.showSitePopup(clickedSites, e.point.x, e.point.y);
+ else if (clickedLines.length != 0) {
+ this.showLinkPopup(clickedLines, e.point.x, e.point.y);
+ }
+ }
+
+ });
+
+ map.on('moveend', () => {
+
+ const mapZoom = Number(map.getZoom().toFixed(2));
+ const lat = Number(map.getCenter().lat.toFixed(4));
+ const lon = Number(map.getCenter().lng.toFixed(4));
+
+
+ if (this.props.lat !== lat || this.props.lon !== lon || this.props.zoom !== mapZoom) {
+ this.props.updateMapPosition(lat, lon, mapZoom)
+ }
+
+ // update the url to current lat,lon,zoom values
+
+ const currentUrl = window.location.href;
+ const parts = currentUrl.split(URL_BASEPATH);
+ if(parts.length>0){
+
+ const detailsPath = parts[1].split("/details/");
+
+ if (detailsPath[1] !== undefined && detailsPath[1].length > 0) {
+ this.props.history.replace(`/${URL_BASEPATH}/${map.getCenter().lat.toFixed(4)},${map.getCenter().lng.toFixed(4)},${mapZoom.toFixed(2)}/details/${detailsPath[1]}`)
+ }
+ else {
+ this.props.history.replace(`/${URL_BASEPATH}/${map.getCenter().lat.toFixed(4)},${map.getCenter().lng.toFixed(4)},${mapZoom.toFixed(2)}`)
+ }
+ }
+
+
+ //switch icon layers if applicable
+ mapLayerService.showIconLayers(map, this.props.showIcons, this.props.selectedSite?.properties.id);
+
+ //update statistics
+ const boundingBox = map.getBounds();
+
+ fetch(`${URL_API}/info/count/${boundingBox.getWest()},${boundingBox.getSouth()},${boundingBox.getEast()},${boundingBox.getNorth()}`)
+ .then(result => verifyResponse(result))
+ .then(res => res.json())
+ .then(result => {
+ if (result.links !== this.props.linkCount || result.sites !== this.props.siteCount) {
+ this.props.setStatistics(result.links, result.sites);
+ }
+ })
+ .catch(error => this.props.handleConnectionError(error));;
+ })
+
+ map.on('move', () => {
+ const mapZoom = map.getZoom();
+
+ const boundingBox = map.getBounds();
+
+ this.loadNetworkData(boundingBox);
+ if (mapZoom > 9) {
+
+ if (map.getLayer('points')) {
+ map.setLayoutProperty('selectedPoints', 'visibility', 'visible');
+ map.setPaintProperty('points', 'circle-radius', 7);
+ }
+ } else {
+
+ // reduce size of points / lines if zoomed out
+ map.setPaintProperty('points', 'circle-radius', 2);
+ map.setLayoutProperty('selectedPoints', 'visibility', 'none');
+
+ if (mapZoom <= 4) {
+ map.setPaintProperty('fibre-lines', 'line-width', 1);
+ map.setPaintProperty('microwave-lines', 'line-width', 1);
+
+ } else {
+ map.setPaintProperty('fibre-lines', 'line-width', 2);
+ map.setPaintProperty('microwave-lines', 'line-width', 2);
+ }
+ }
+ });
+ }
+
+ componentDidUpdate(prevProps: mapProps, prevState: {}) {
+
+ //(load map)
+ //triggered if either settings were done loading or tile/topology server connectivity checked
+ if(prevProps.settings !== this.props.settings || this.props.isConnectivityCheckBusy !== prevProps.isConnectivityCheckBusy){
+
+ //update theme if settings changed
+ if(prevProps.settings !== this.props.settings){
+ this.updateTheme();
+ }
+
+ //if everything done loading/reachable, load map
+ if(!this.props.isConnectivityCheckBusy && this.props.isTileServerReachable && !this.props.settings.isLoadingData && (prevProps.settings.isLoadingData !==this.props.settings.isLoadingData || prevProps.isConnectivityCheckBusy !== this.props.isConnectivityCheckBusy)){
+ if(map == undefined){
+ this.setupMap();
+ }
+ else
+ if(map.getContainer() !== myRef.current){
+ // reload map, because the current container (fresh div) doesn't hold the map and changing containers isn't supported
+ map.remove();
+ this.setupMap();
+ }
+ }
+ }
+
+ if (map !== undefined) {
+ if (prevProps.selectedSite?.properties.id !== this.props.selectedSite?.properties.id) {
+
+ if (this.props.selectedSite != null) {
+ if (map.getSource("selectedLine") !== undefined) {
+ (map.getSource("selectedLine") as mapboxgl.GeoJSONSource).setData({ type: "FeatureCollection", features: [] });
+ (map.getSource("selectedPoints") as mapboxgl.GeoJSONSource).setData({ type: "FeatureCollection", features: [this.props.selectedSite] });
+ }
+
+
+ if (map.getLayer('point-lamps') !== undefined) {
+
+ map.setFilter('point-lamps', ['==', 'type', 'street lamp']);
+ map.setFilter('point-data-center', ['==', 'type', 'data center']);
+ map.setFilter('point-building', ['==', 'type', 'high rise building']);
+ map.setFilter('point-factory', ['==', 'type', 'factory']);
+
+ if (this.props.selectedSite?.properties.type !== undefined) {
+ switch (this.props.selectedSite?.properties.type) {
+ case 'street lamp':
+ map.setFilter('point-lamps', ["all", ['==', 'type', 'street lamp'], ['!=', 'id', this.props.selectedSite.properties.id]]);
+ break;
+ case 'data center':
+ map.setFilter('point-data-center', ["all", ['==', 'type', 'data center'], ['!=', 'id', this.props.selectedSite.properties.id]]);
+ break;
+ case 'high rise building':
+ map.setFilter('point-building', ["all", ['==', 'type', 'high rise building'], ['!=', 'id', this.props.selectedSite.properties.id]])
+ break;
+ case 'factory':
+ map.setFilter('point-factory', ["all", ['==', 'type', 'factory'], ['!=', 'id', this.props.selectedSite.properties.id]]);
+ break;
+ }
+ }
+ }
+
+
+ }
+ else
+ {
+ if (map.getSource("selectedPoints") !== undefined)
+ (map.getSource("selectedPoints") as mapboxgl.GeoJSONSource).setData({ type: "FeatureCollection", features: [] });
+
+ }
+ }
+
+ if (prevProps.selectedLink !== this.props.selectedLink) {
+ if (this.props.selectedLink != null) {
+
+ if (map.getLayer('point-lamps') !== undefined) {
+ map.setFilter('point-lamps', ['==', 'type', 'street lamp']);
+ map.setFilter('point-data-center', ['==', 'type', 'data center']);
+ map.setFilter('point-building', ['==', 'type', 'high rise building']);
+ map.setFilter('point-factory', ['==', 'type', 'factory']);
+ }
+
+ if (map.getSource("selectedLine") !== undefined) {
+ (map.getSource("selectedPoints") as mapboxgl.GeoJSONSource).setData({ type: "FeatureCollection", features: [] });
+ (map.getSource("selectedLine") as mapboxgl.GeoJSONSource).setData({ type: "FeatureCollection", features: [this.props.selectedLink] });
+ }
+ }
+ else
+ {
+ if (map.getSource("selectedLine") !== undefined)
+ (map.getSource("selectedLine") as mapboxgl.GeoJSONSource).setData({ type: "FeatureCollection", features: [] });
+ }
+ }
+
+ if (prevProps.location.pathname !== this.props.location.pathname) {
+ if (map) {
+ const coordinates = this.extractCoordinatesFromUrl();
+ this.moveMapToCoordinates(coordinates);
+ }
+ }
+
+ if (prevProps.alarmlement !== this.props.alarmlement) {
+ if (this.props.alarmlement !== null && !alarmElements.includes(this.props.alarmlement)) {
+ if (map.getSource("alarmedPoints"))
+ (map.getSource("alarmedPoints") as mapboxgl.GeoJSONSource).setData({ type: "FeatureCollection", features: alarmElements });
+ alarmElements.push(this.props.alarmlement)
+ }
+ }
+
+ if (prevProps.showIcons !== this.props.showIcons) {
+ if (map && map.getZoom() > 11) {
+ mapLayerService.showIconLayers(map, this.props.showIcons, this.props.selectedSite?.properties.id);
+ }
+ }
+
+ if (prevProps.zoomToElement !== this.props.zoomToElement) {
+ if (this.props.zoomToElement !== null) {
+ const currentZoom = map?.getZoom();
+
+ map.flyTo({
+ center: [
+ this.props.zoomToElement.lon,
+ this.props.zoomToElement.lat
+ ], zoom: currentZoom < 10 ? 10 : currentZoom,
+ essential: true
+ });
+ }
+ }
+ }
+ }
+
+ componentWillUnmount(){
+ window.removeEventListener("menu-resized", this.handleResize);
+ lastBoundingBox=null;
+
+ // will be checked again on next load
+ this.props.setConnectivityCheck(true);
+ }
+
+ handleResize = () => {
+ if (map) {
+ // wait a moment until resizing actually happened
+ window.setTimeout(() => map.resize(), 500);
+ }
+ }
+
+ extractCoordinatesFromUrl = (): coordinates => {
+ const currentUrl = window.location.href;
+ const mainPathParts = currentUrl.split(URL_BASEPATH);
+ const coordinatePathPart = mainPathParts[1].split("/details/"); // split by details if present
+ const allCoordinates = coordinatePathPart[0].replace("/", "");
+ const coordinates = allCoordinates.split(",");
+ return { lat: Number(coordinates[0]), lon: Number(coordinates[1]), zoom: Number(coordinates[2]) }
+ }
+
+ areCoordinatesValid = (coordinates: coordinates) => {
+
+ if ((!Number.isNaN(coordinates.lat)) && (!Number.isNaN(coordinates.lon))) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ moveMapToCoordinates = (coordinates: coordinates) => {
+
+ if (this.areCoordinatesValid(coordinates)) {
+ let zoom = -1;
+
+ if (!Number.isNaN(coordinates.zoom)) {
+ zoom = coordinates.zoom;
+ }
+
+ map.flyTo({
+ center: [
+ coordinates.lon,
+ coordinates.lat
+ ], zoom: zoom !== -1 ? zoom : this.props.zoom,
+ essential: true
+ })
+ }
+ }
+
+ loadNetworkData = async (bbox: mapboxgl.LngLatBounds) => {
+ if (!isLoadingInProgress) { // only load data if loading not in progress
+ isLoadingInProgress = true;
+
+ if (lastBoundingBox == null) {
+ lastBoundingBox = bbox;
+ await this.draw('lines', `${URL_API}/links/geojson/${lastBoundingBox.getWest()},${lastBoundingBox.getSouth()},${lastBoundingBox.getEast()},${lastBoundingBox.getNorth()}`);
+ await this.draw('points', `${URL_API}/sites/geojson/${lastBoundingBox.getWest()},${lastBoundingBox.getSouth()},${lastBoundingBox.getEast()},${lastBoundingBox.getNorth()}`);
+ } else {
+
+ // new bbox is bigger than old one
+ if (bbox.contains(lastBoundingBox.getNorthEast()) && bbox.contains(lastBoundingBox.getSouthWest()) && lastBoundingBox !== bbox) { //if new bb is bigger than old one
+
+ lastBoundingBox = bbox;
+
+ //calculate new boundingBox
+ const increasedBoundingBox = increaseBoundingBox(map);
+
+ await this.draw('lines', `${URL_API}/links/geojson/${increasedBoundingBox.west},${increasedBoundingBox.south},${increasedBoundingBox.east},${increasedBoundingBox.north}`);
+ await this.draw('points', `${URL_API}/sites/geojson/${increasedBoundingBox.west},${increasedBoundingBox.south},${increasedBoundingBox.east},${increasedBoundingBox.north}`);
+
+ } else if (lastBoundingBox.contains(bbox.getNorthEast()) && lastBoundingBox.contains(bbox.getSouthWest())) { // last one contains new one
+ // bbox is contained in last one, do nothing
+ isLoadingInProgress = false;
+
+ } else { // bbox is not fully contained in old one, extend
+
+ lastBoundingBox.extend(bbox);
+
+ await this.draw('lines', `${URL_API}/links/geojson/${lastBoundingBox.getWest()},${lastBoundingBox.getSouth()},${lastBoundingBox.getEast()},${lastBoundingBox.getNorth()}`);
+ await this.draw('points', `${URL_API}/sites/geojson/${lastBoundingBox.getWest()},${lastBoundingBox.getSouth()},${lastBoundingBox.getEast()},${lastBoundingBox.getNorth()}`);
+ }
+
+ }
+
+
+ if (notLoadedBoundingBoxes.length > 0) { // load last not loaded boundingbox
+ this.loadNetworkData(notLoadedBoundingBoxes.pop()!)
+ notLoadedBoundingBoxes = [];
+ }
+
+ } else {
+ notLoadedBoundingBoxes.push(bbox);
+ }
+ }
+
+ showSitePopup = (sites: mapboxgl.MapboxGeoJSONFeature[], top: number, left: number) => {
+ if (sites.length > 1) {
+ const elements: PopupElement[] = sites.map(feature => {return {name: feature.properties!.name, id: feature.properties!.id}});
+
+ this.props.setPopupPosition(top, left);
+ this.props.selectMultipleSites(elements); //name, id object container
+ this.setState({ isPopupOpen: true });
+
+ } else {
+ const id = sites[0].properties!.id;
+
+ fetch(`${URL_API}/sites/${id}`)
+ .then(result => verifyResponse(result))
+ .then(res => res.json() as Promise<Site>)
+ .then(result => {
+ this.props.selectSite(result);
+ this.props.highlightSite(result);
+ this.props.clearDetailsHistory();
+ })
+ .catch(error => this.props.handleConnectionError(error));;
+ }
+ }
+
+ showLinkPopup = (links: mapboxgl.MapboxGeoJSONFeature[], top: number, left: number) => {
+
+ if (links.length > 1) {
+
+ const elements: PopupElement[] = links.map(feature => {return {name: feature.properties!.name, id: feature.properties!.id}});
+
+ this.props.setPopupPosition(top, left);
+ this.props.selectMultipleLinks(elements);
+ this.setState({ isPopupOpen: true });
+
+ } else {
+ var id = links[0].properties!.id;
+
+ fetch(`${URL_API}/links/${id}`)
+ .then(result => verifyResponse(result))
+ .then(res => res.json() as Promise<link>)
+ .then(result => {
+ this.props.selectLink(result);
+ this.props.highlightLink(result);
+
+ this.props.clearDetailsHistory();
+ })
+ .catch(error => this.props.handleConnectionError(error));;
+ }
+ }
+
+ draw = async (layer: string, url: string) => {
+
+ fetch(url)
+ .then(result => verifyResponse(result))
+ .then(res => res.json())
+ .then(result => {
+ isLoadingInProgress = false;
+ if (map.getSource(layer)) {
+ (map.getSource(layer) as mapboxgl.GeoJSONSource).setData(result);
+ }
+ })
+ .catch(error => this.props.handleConnectionError(error));;
+ }
+
+ render() {
+
+ return <>
+
+{
+ !this.props.settings.isLoadingData ?
+
+ <div id="map" style={{ width: "70%", position: 'relative' }} ref={myRef} >
+ {
+ this.state.isPopupOpen &&
+ <MapPopup onClose={() => { this.setState({ isPopupOpen: false }); }} />
+ }
+ <SearchBar />
+ <Statistics />
+ <IconSwitch visible={this.props.zoom>11} />
+ <ConnectionInfo />
+ <Button
+ disabled={!this.props.isTopoServerReachable}
+ style={{'position': 'absolute', 'right':5, top:5, backgroundColor:'white'}}
+ onClick={e => this.props.navigateToApplication("network", "customize")} >
+ <img src={customize} />
+ </Button>
+ </div>
+ :<div style={{ width: "70%", position: 'relative' }} />
+
+ }
+ </>
+ }
+
+}
+
+type mapProps = RouteComponentProps & Connect<typeof mapStateToProps, typeof mapDispatchToProps>;
+
+const mapStateToProps = (state: IApplicationStoreState) => ({
+ selectedLink: state.network.map.selectedLink,
+ selectedSite: state.network.map.selectedSite,
+ zoomToElement: state.network.map.zoomToElement,
+ alarmlement: state.network.map.alarmlement,
+ lat: state.network.map.lat,
+ lon: state.network.map.lon,
+ zoom: state.network.map.zoom,
+ linkCount: state.network.map.statistics.links,
+ siteCount: state.network.map.statistics.sites,
+ isTopoServerReachable: state.network.connectivity.isToplogyServerAvailable,
+ isTileServerReachable: state.network.connectivity.isTileServerAvailable,
+ isConnectivityCheckBusy: state.network.connectivity.isBusy,
+ showIcons: state.network.map.allowIconSwitch,
+ settings: state.network.settings,
+});
+
+const mapDispatchToProps = (dispatcher: IDispatcher) => ({
+ selectSite: (site: Site) => dispatcher.dispatch(new SelectSiteAction(site)),
+ selectLink: (link: link) => dispatcher.dispatch(new SelectLinkAction(link)),
+ clearDetailsHistory: () => dispatcher.dispatch(new ClearHistoryAction()),
+ selectMultipleLinks: (ids: PopupElement[]) => dispatcher.dispatch(new SelectMultipleLinksAction(ids)),
+ selectMultipleSites: (ids: PopupElement[]) => dispatcher.dispatch(new SelectMultipleSitesAction(ids)),
+ setPopupPosition: (x: number, y: number) => dispatcher.dispatch(new SetPopupPositionAction(x, y)),
+ highlightLink: (link: link) => dispatcher.dispatch(new HighlightLinkAction(link)),
+ highlightSite: (site: Site) => dispatcher.dispatch(new HighlightSiteAction(site)),
+ updateMapPosition: (lat: number, lon: number, zoom: number) => dispatcher.dispatch(new SetCoordinatesAction(lat, lon, zoom)),
+ setStatistics: (linkCount: string, siteCount: string) => dispatcher.dispatch(new SetStatistics(siteCount, linkCount)),
+ setTileServerLoaded: (reachable: boolean) => dispatcher.dispatch(setTileServerReachableAction(reachable)),
+ handleConnectionError: (error: Error) => dispatcher.dispatch(handleConnectionError(error)),
+ navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path, "test3")),
+ setConnectivityCheck: (done: boolean) => dispatcher.dispatch(new IsBusycheckingConnectivityAction(done)),
+
+})
+
+export default withRouter(connect(mapStateToProps, mapDispatchToProps)(Map)); \ No newline at end of file