summaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/apps/networkMapApp/src
diff options
context:
space:
mode:
authorAijana Schumann <aijana.schumann@highstreet-technologies.com>2021-05-07 13:56:52 +0200
committerAijana Schumann <aijana.schumann@highstreet-technologies.com>2021-05-07 13:56:52 +0200
commit2c1f3727a703634cf62c63cfc4a3d4bb30fe2d9c (patch)
treec8f9f47f11f7ff239ee9d71bcccc9236316f1729 /sdnr/wt/odlux/apps/networkMapApp/src
parent3cb21ac46f62e5c03afef0584af8472a3bb6b13b (diff)
Add customization of networkmap
Add customization capabilities to the networkmap Issue-ID: CCSDK-2938 Signed-off-by: Aijana Schumann <aijana.schumann@highstreet-technologies.com> Change-Id: Ibd3fe258d02939ea69b21de25569f20d9087f693
Diffstat (limited to 'sdnr/wt/odlux/apps/networkMapApp/src')
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/App.tsx2
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/actions/connectivityAction.ts6
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/actions/settingsAction.ts85
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/customize/customizationView.tsx291
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/customize/themeElement.tsx47
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/connectionInfo.tsx (renamed from sdnr/wt/odlux/apps/networkMapApp/src/components/connectionInfo.tsx)4
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/iconSwitch.tsx (renamed from sdnr/wt/odlux/apps/networkMapApp/src/components/iconSwitch.tsx)6
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx (renamed from sdnr/wt/odlux/apps/networkMapApp/src/components/map.tsx)164
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/mapPopup.tsx (renamed from sdnr/wt/odlux/apps/networkMapApp/src/components/mapPopup.tsx)16
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/searchBar.tsx (renamed from sdnr/wt/odlux/apps/networkMapApp/src/components/searchBar.tsx)20
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map/statistics.tsx (renamed from sdnr/wt/odlux/apps/networkMapApp/src/components/statistics.tsx)4
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/handlers/connectivityReducer.ts9
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/handlers/rootReducer.ts7
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/handlers/settingsReducer.ts61
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/model/settings.ts34
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/pluginTransport.tsx44
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/services/settingsService.ts43
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts712
18 files changed, 1001 insertions, 554 deletions
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/App.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/App.tsx
index 6caab5147..5840d1842 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/App.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/App.tsx
@@ -17,7 +17,7 @@
*/
import * as React from 'react';
-import Map from './components/map'
+import Map from './components/map/map'
import Details from './components/details/details'
function MainView() {
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/actions/connectivityAction.ts b/sdnr/wt/odlux/apps/networkMapApp/src/actions/connectivityAction.ts
index 8fcdc4c3b..63f52c8f9 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/actions/connectivityAction.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/actions/connectivityAction.ts
@@ -33,6 +33,12 @@ export class IsTileServerReachableAction extends Action{
}
}
+export class IsBusycheckingConnectivityAction extends Action{
+ constructor(public isBusy: boolean){
+ super();
+ }
+}
+
export const verifyResponse = (response: Response) =>{
if(response.ok){
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/actions/settingsAction.ts b/sdnr/wt/odlux/apps/networkMapApp/src/actions/settingsAction.ts
new file mode 100644
index 000000000..5b8982368
--- /dev/null
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/actions/settingsAction.ts
@@ -0,0 +1,85 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 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 { NetworkMapSettings, NetworkMapThemes, NetworkSettings } from '../model/settings';
+import { Action } from '../../../../framework/src/flux/action';
+import { Dispatch } from '../../../../framework/src/flux/store';
+import { settingsService } from '../services/settingsService';
+
+export class SetMapSettingsAction extends Action{
+
+ constructor(public settings:NetworkMapSettings) {
+ super();
+ }
+}
+
+export class SetThemeSettingsAction extends Action{
+
+ constructor(public settings:NetworkMapThemes) {
+ super();
+ }
+}
+
+export class SetSettingsAction extends Action{
+
+ constructor(public settings:NetworkSettings) {
+ super();
+ }
+}
+
+export class SetBusyLoadingAction extends Action{
+
+ constructor(public busy: boolean) {
+ super();
+
+ }
+}
+
+
+export const getSettings = () => async (dispatcher: Dispatch) => {
+ dispatcher(new SetBusyLoadingAction(true));
+ console.log("getting settings in action..")
+ settingsService.getMapSettings().then(result =>{
+ if(result){
+ if(result.networkMap && result.networkMapThemes){
+ const mapSettings : NetworkSettings = { networkMap: result.networkMap, networkMapThemes: result.networkMapThemes}
+ dispatcher(new SetSettingsAction(mapSettings));
+ }else if(result.networkMap){
+ dispatcher(new SetMapSettingsAction(result));
+ }else if(result.networkMapThemes){
+ dispatcher(new SetThemeSettingsAction(result));
+ }
+ }
+ else{
+ console.warn("settings couldn't be loaded.");
+ }
+ dispatcher(new SetBusyLoadingAction(false));
+ });
+}
+
+export const updateSettings = (mapSettings: NetworkMapSettings) => async (dispatcher: Dispatch) =>{
+
+ const result = await settingsService.updateMapSettings(mapSettings);
+ console.log("update settings");
+ dispatcher(new SetMapSettingsAction(mapSettings));
+
+ console.log(result);
+ if(result){
+ }
+
+}
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/customize/customizationView.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/customize/customizationView.tsx
new file mode 100644
index 000000000..82e7b795b
--- /dev/null
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/customize/customizationView.tsx
@@ -0,0 +1,291 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 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 { Button, Grid, InputLabel, makeStyles, MenuItem, Select, Slider, TextField, Typography } from '@material-ui/core';
+import { NetworkMapSettings, ThemeElement } from '../../model/settings';
+import * as React from 'react'
+import connect, { Connect, IDispatcher } from '../../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../../framework/src/store/applicationStore';
+import { updateSettings } from '../../actions/settingsAction';
+import ThemeEntry from './themeElement'
+import * as mapboxgl from 'mapbox-gl';
+import { OSM_STYLE } from '../../config';
+import mapLayerService from '../../utils/mapLayers';
+import { requestRest } from '../../../../../framework/src/services/restService';
+import { NavigateToApplication } from '../../../../../framework/src/actions/navigationActions';
+
+type props = Connect<typeof mapProps, typeof mapDispatch>;
+let map: mapboxgl.Map;
+let myMapRef = React.createRef<HTMLDivElement>();
+const default_boundingbox = "12.882544785787754,52.21421979821472,13.775455214211949,52.80406241672602";
+
+
+const mapProps = (state: IApplicationStoreState) => ({
+ settings: state.network.settings,
+});
+
+const mapDispatch = (dispatcher: IDispatcher) => ({
+ updateSettings: (mapSettings: NetworkMapSettings) => dispatcher.dispatch(updateSettings(mapSettings)),
+ navigateToApplication: (applicationName: string) => dispatcher.dispatch(new NavigateToApplication(applicationName)),
+
+
+});
+
+const styles = makeStyles({
+ sectionMargin: {
+ marginTop: "30px",
+ marginBottom: "15px"
+ },
+ elementMargin: {
+
+ marginLeft: "10px"
+ }
+});
+
+const CustomizationView: React.FunctionComponent<props> = (props) => {
+
+ const [opacity, setOpacity] = React.useState(Number(props.settings.mapSettings?.networkMap.tileOpacity) || 100);
+ const [theme, setTheme] = React.useState(props.settings.mapSettings?.networkMap.styling.theme || '');
+ const [latitude, setLatitude] = React.useState<number>(Number(props.settings.mapSettings?.networkMap.startupPosition.latitude)|| 52.5);
+ const [longitude, setLongitude] = React.useState<number>(Number(props.settings.mapSettings?.networkMap.startupPosition.longitude)|| 13.35);
+ const [zoom, setZoom] = React.useState<number>(Number(props.settings.mapSettings?.networkMap.startupPosition.zoom) || 10);
+
+
+ //used to make opacity available within the map event-listeners
+ //(hook state values are snapshotted at initalization and not updated afterwards, thus use a ref here)
+ const myOpacityRef = React.useRef(opacity);
+ const setOpacityState = (data:any) => {
+ myOpacityRef.current = data;
+ setOpacity(data);
+ };
+
+ const classes = styles();
+ const currentTheme = props.settings.themes.networkMapThemes.themes.find(el => el.key === theme);
+
+
+ React.useEffect(() => {
+ mapLayerService.settings = props.settings.themes;
+
+ map = new mapboxgl.Map({
+ container: myMapRef.current!,
+ style: OSM_STYLE as any,
+ center: [longitude, latitude],
+ zoom: zoom,
+ accessToken: ''
+ });
+
+ map.on('load', (ev) => {
+
+ mapLayerService.addBaseSources(map, null, null);
+ if(props.settings.mapSettings?.networkMap.styling.theme !== theme){
+ mapLayerService.addBaseLayers(map, currentTheme);
+
+ }else{
+ mapLayerService.addBaseLayers(map);
+ }
+
+ mapLayerService.changeMapOpacity(map, myOpacityRef.current);
+
+ getData();
+ });
+
+ map.on('moveend', () => {
+ const center = map.getCenter();
+ setZoom(Number(map.getZoom().toFixed(4)));
+ setLatitude(Number(center.lat.toFixed(4)));
+ setLongitude(Number(center.lng.toFixed(4)));
+ });
+
+ }, []);
+
+ React.useEffect(() => {
+ recenterMap();
+ }, [latitude, longitude, zoom]);
+
+ const setState = () => {
+ if (props.settings.mapSettings?.networkMap.styling) {
+ setTheme(props.settings.mapSettings.networkMap.styling.theme);
+ mapLayerService.changeTheme(map, props.settings.mapSettings.networkMap.styling.theme);
+ }
+
+ const propOpacity = props.settings.mapSettings?.networkMap.tileOpacity;
+ if (propOpacity) {
+ setOpacityState(propOpacity);
+ }
+ }
+
+ React.useEffect(() => {
+ setState();
+ }, [props.settings.mapSettings]);
+
+ const onOpacityChange = (event: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>, newValue: number) => {
+ setOpacity(newValue);
+ mapLayerService.changeMapOpacity(map, newValue);
+
+ };
+
+ const onChangeTheme = (e: any) => {
+
+ const newTheme = e.target.value;
+ setTheme(newTheme);
+ mapLayerService.changeTheme(map, newTheme);
+ }
+
+ const onCancel = (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
+ e.preventDefault();
+ props.navigateToApplication("network");
+ }
+
+ const onSaveSettings = async (e: React.MouseEvent<HTMLButtonElement, MouseEvent>) => {
+ e.preventDefault();
+
+ const updatedSettings: NetworkMapSettings = {
+ networkMap: {
+ tileOpacity: opacity.toString(),
+ styling: { theme: theme },
+ startupPosition: {
+ latitude: latitude.toString(),
+ longitude: longitude.toString(),
+ zoom: zoom.toString()
+ }
+ }
+ };
+
+ console.log(updatedSettings);
+
+ await props.updateSettings(updatedSettings)
+ props.navigateToApplication("network");
+
+ }
+
+ const recenterMap = () => {
+
+ if (!isNaN(latitude) && !isNaN(longitude) && !isNaN(zoom))
+
+ map.flyTo({
+ center: [
+ longitude,
+ latitude
+ ], zoom: zoom,
+ essential: false
+ });
+ }
+
+
+
+ const getData = () => {
+
+ //get data of boundingbox from networkmap
+
+ const links = requestRest<any>("/topology/network/links/geojson/" + default_boundingbox);
+ const sites = requestRest<any>("/topology/network/sites/geojson/" + default_boundingbox);
+
+ Promise.all([links, sites]).then(results => {
+ if (map.getSource('lines')) {
+ (map.getSource('lines') as mapboxgl.GeoJSONSource).setData(results[0]);
+ }
+
+ if (map.getSource('points')) {
+ (map.getSource('points') as mapboxgl.GeoJSONSource).setData(results[1]);
+ }
+
+ if (map.getSource('selectedPoints')) {
+ (map.getSource('selectedPoints') as mapboxgl.GeoJSONSource).setData(results[1].features[0]);
+ }
+ });
+ }
+
+ /**
+ * Style property names to readable text
+ * @param text propretyName
+ * @returns readable text
+ */
+ const styleText = (text: string) => {
+ const textParts = text.split(/(?=[A-Z])/); //split on uppercase character
+ const newText = textParts.join(" ");
+ return newText.charAt(0).toUpperCase() + newText.slice(1);
+ }
+
+
+ return (<>
+ <h3>Settings</h3>
+ <div style={{ display: 'flex', flexDirection: 'row', flexGrow: 1, height: "100%", position: 'relative' }}>
+ <div style={{ width: "60%", flexDirection: 'column', position:'relative' }}>
+ <Typography variant="body1" style={{ fontWeight: "bold" }} gutterBottom>Startup Position</Typography>
+ <div style={{ display: 'flex', flexDirection: 'row' }}>
+ <TextField type="number" value={latitude} onChange={(e) => setLatitude(e.target.value as any)} style={{ marginLeft: 10 }} label="Latitude" />
+ <TextField type="number" value={longitude} onChange={(e) => setLongitude(e.target.value as any)} style={{ marginLeft: 5 }} label="Longitude" />
+ <TextField type="number" value={zoom} onChange={(e) => setZoom(e.target.value as any)} style={{ marginLeft: 5 }} label="Zoom" />
+ </div>
+
+ <Typography className={classes.sectionMargin} variant="body1" style={{ fontWeight: "bold" }} gutterBottom>
+ Tile Opacity
+ </Typography>
+ <Grid className={classes.elementMargin} container spacing={2} style={{ width: '50%' }}>
+ <Grid item>0</Grid>
+ <Grid item xs>
+ <Slider color="secondary" min={0} max={100} value={opacity} onChange={onOpacityChange} aria-labelledby="continuous-slider" />
+ </Grid>
+ <Grid item>100</Grid>
+ </Grid>
+
+ <Typography className={classes.sectionMargin} variant="body1" style={{ fontWeight: "bold" }} gutterBottom>
+ Style of properties
+ </Typography>
+ <InputLabel id="theme-select-label">Theme</InputLabel>
+ <Select
+ className={classes.elementMargin}
+ value={theme}
+ onChange={onChangeTheme}
+ labelId="theme-select-label"
+ style={{ marginLeft: 10 }}>
+ {
+ props.settings.themes.networkMapThemes.themes.map(el => <MenuItem value={el.key}>{el.key}</MenuItem>)
+ }
+
+ </Select>
+
+ {
+ currentTheme && <div style={{ marginLeft: 60 }}>
+ { //skip the 'key' (theme name) entry
+ Object.keys(currentTheme).slice(1).map(el => <ThemeEntry text={styleText(el)} color={(currentTheme as any)[el]} />)
+ }
+ </div>
+ }
+
+
+ <div className={classes.sectionMargin} style={{ position: 'absolute', right: 0, top: '60%' }}>
+ <Button className={classes.elementMargin} variant="contained"
+ color="primary" onClick={onCancel}>Cancel</Button>
+
+ <Button className={classes.elementMargin} variant="contained"
+ color="secondary" onClick={onSaveSettings}>Save</Button>
+ </div>
+ </div>
+ <div id="map" ref={myMapRef} style={{ width: "35%", height: "50%" }}>
+
+ </div>
+ </div>
+
+ </>)
+
+}
+
+export default connect(mapProps, mapDispatch)(CustomizationView);
+
+
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/customize/themeElement.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/customize/themeElement.tsx
new file mode 100644
index 000000000..c991aaf63
--- /dev/null
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/customize/themeElement.tsx
@@ -0,0 +1,47 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 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 { Typography } from '@material-ui/core';
+import * as React from 'react'
+
+
+type props={
+ color: string,
+ text: string
+};
+
+const ThemeEntry = (props: props) =>{
+
+ var circleStyle = {
+ padding:10,
+ margin:20,
+ backgroundColor: props.color,
+ borderRadius: "50%",
+ width:10,
+ height:10,
+ left:0,
+ top:0};
+
+ return <div style={{display: 'flex', flexDirection:'row'}}>
+ <div style={circleStyle} />
+ <Typography variant="body1" style={{marginTop:24}}>{props.text}</Typography>
+ </div>
+
+}
+
+export default ThemeEntry; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/connectionInfo.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/connectionInfo.tsx
index d1e2d978f..c1fdccfb8 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/connectionInfo.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/connectionInfo.tsx
@@ -18,8 +18,8 @@
import * as React from 'react'
-import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore";
-import connect, { IDispatcher, Connect } from "../../../../framework/src/flux/connect";
+import { IApplicationStoreState } from "../../../../../framework/src/store/applicationStore";
+import connect, { IDispatcher, Connect } from "../../../../../framework/src/flux/connect";
import { Paper, Typography } from "@material-ui/core";
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { faExclamationTriangle } from '@fortawesome/free-solid-svg-icons';
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/iconSwitch.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/iconSwitch.tsx
index 8df1385d0..bb98cb467 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/iconSwitch.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/iconSwitch.tsx
@@ -18,9 +18,9 @@
import * as React from 'react';
import { FormControlLabel, Switch, Paper } from "@material-ui/core";
-import connect, { Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import { SetIconSwitchAction } from '../actions/mapActions';
+import connect, { Connect, IDispatcher } from '../../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../../framework/src/store/applicationStore';
+import { SetIconSwitchAction } from '../../actions/mapActions';
type props = Connect<typeof mapStateToProps, typeof mapDispatchToProps> & {visible: boolean}
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/map.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx
index 855e5cedf..9637d745e 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/map.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/map.tsx
@@ -21,25 +21,28 @@ 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 { 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 { 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 } from '../actions/connectivityAction';
+import { verifyResponse, IsTileServerReachableAction, handleConnectionError, setTileServerReachableAction, IsBusycheckingConnectivityAction } from '../../actions/connectivityAction';
import ConnectionInfo from './connectionInfo'
-import { showIconLayers, addBaseLayers, addBaseSources, addIconLayers } from '../utils/mapLayers';
+import mapLayerService from '../../utils/mapLayers';
import Statistics from './statistics';
import IconSwitch from './iconSwitch';
-import { addImages } from '../services/mapImagesService';
-import { PopupElement } from '../model/popupElements';
+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 }
@@ -61,31 +64,52 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
}
- componentDidMount() {
+ 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);
- // try if connection to tile + topologyserver is available
+ //pass themes to mapLayerService
+ this.updateTheme();
- fetch(URL_TILE_API + '/10/0/0.png')
- .then(res => {
- if (res.ok) {
- this.setupMap();
- this.props.setTileServerLoaded(true);
- } else {
- this.props.setTileServerLoaded(false);
- console.error("tileserver " + URL_TILE_API + " can't be reached.");
- }
- })
- .catch(err => {
+ // 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);
- console.error("tileserver " + URL_TILE_API + " can't be reached.");
- });
+ }
- fetch(URL_API + "/info/count/all")
- .then(result => verifyResponse(result))
- .catch(error => this.props.handleConnectionError(error));
+ } 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 = () => {
@@ -94,6 +118,21 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
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)) {
@@ -116,15 +155,17 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
const bbox = map.getBounds();
this.props.updateMapPosition(bbox.getCenter().lat, bbox.getCenter().lng, map.getZoom())
- addBaseSources(map, this.props.selectedSite, this.props.selectedLink);
-
+ mapLayerService.addBaseSources(map, this.props.selectedSite, this.props.selectedLink);
+
addImages(map, (result: boolean)=>{
if(map.getZoom()>11)
{
- addIconLayers(map, this.props.selectedSite?.properties.id)
+ mapLayerService.addIconLayers(map, this.props.selectedSite?.properties.id)
}else{
- addBaseLayers(map, this.props.selectedSite, this.props.selectedLink);
+ mapLayerService.addBaseLayers(map);
}
+ this.updateOpacity();
+
});
const boundingBox = increaseBoundingBox(map);
@@ -229,7 +270,7 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
//switch icon layers if applicable
- showIconLayers(map, this.props.showIcons, this.props.selectedSite?.properties.id);
+ mapLayerService.showIconLayers(map, this.props.showIcons, this.props.selectedSite?.properties.id);
//update statistics
const boundingBox = map.getBounds();
@@ -277,6 +318,29 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
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) {
@@ -361,7 +425,7 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
if (prevProps.showIcons !== this.props.showIcons) {
if (map && map.getZoom() > 11) {
- showIconLayers(map, this.props.showIcons, this.props.selectedSite?.properties.id);
+ mapLayerService.showIconLayers(map, this.props.showIcons, this.props.selectedSite?.properties.id);
}
}
@@ -384,6 +448,9 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
componentWillUnmount(){
window.removeEventListener("menu-resized", this.handleResize);
lastBoundingBox=null;
+
+ // will be checked again on next load
+ this.props.setConnectivityCheck(true);
}
handleResize = () => {
@@ -543,6 +610,9 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
return <>
+{
+ !this.props.settings.isLoadingData ?
+
<div id="map" style={{ width: "70%", position: 'relative' }} ref={myRef} >
{
this.state.isPopupOpen &&
@@ -552,7 +622,16 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
<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' }} />
+
+ }
</>
}
@@ -572,7 +651,9 @@ const mapStateToProps = (state: IApplicationStoreState) => ({
siteCount: state.network.map.statistics.sites,
isTopoServerReachable: state.network.connectivity.isToplogyServerAvailable,
isTileServerReachable: state.network.connectivity.isTileServerAvailable,
- showIcons: state.network.map.allowIconSwitch
+ isConnectivityCheckBusy: state.network.connectivity.isBusy,
+ showIcons: state.network.map.allowIconSwitch,
+ settings: state.network.settings,
});
const mapDispatchToProps = (dispatcher: IDispatcher) => ({
@@ -587,7 +668,10 @@ const mapDispatchToProps = (dispatcher: IDispatcher) => ({
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))
+ 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
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/mapPopup.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/mapPopup.tsx
index 7435a0a3f..7a64f5a58 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/mapPopup.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/mapPopup.tsx
@@ -18,14 +18,14 @@
import * as React from 'react';
import { Typography, Select, MenuItem, ClickAwayListener, Popper, Paper, FormGroup, Portal, Popover } from '@material-ui/core';
-import { SelectSiteAction, ClearHistoryAction, ClearDetailsAction } from '../actions/detailsAction';
-import { Site } from '../model/site';
-import { link } from '../model/link';
-import { URL_API } from '../config';
-import { HighlightLinkAction, HighlightSiteAction } from '../actions/mapActions';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
-import { verifyResponse, handleConnectionError } from '../actions/connectivityAction';
+import { SelectSiteAction, ClearHistoryAction, ClearDetailsAction } from '../../actions/detailsAction';
+import { Site } from '../../model/site';
+import { link } from '../../model/link';
+import { URL_API } from '../../config';
+import { HighlightLinkAction, HighlightSiteAction } from '../../actions/mapActions';
+import { IApplicationStoreState } from '../../../../../framework/src/store/applicationStore';
+import connect, { IDispatcher, Connect } from '../../../../../framework/src/flux/connect';
+import { verifyResponse, handleConnectionError } from '../../actions/connectivityAction';
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/searchBar.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/searchBar.tsx
index 2e698158d..45bc6092d 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/searchBar.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/searchBar.tsx
@@ -20,16 +20,16 @@ import * as React from 'react';
import { makeStyles, Paper, InputBase, IconButton, Divider, Popover, Typography } from '@material-ui/core';
import SearchIcon from '@material-ui/icons/Search';
-import { URL_API } from '../config';
-import { isSite } from '../utils/utils';
-import { Site } from '../model/site';
-import { link } from '../model/link';
-import { SelectSiteAction, SelectLinkAction } from '../actions/detailsAction';
-import { HighlightLinkAction, HighlightSiteAction, ZoomToSearchResultAction } from '../actions/mapActions';
-import { calculateMidPoint } from '../utils/mapUtils';
-import { SetSearchValueAction } from '../actions/searchAction';
-import connect,{ Connect, IDispatcher } from '../../../../framework/src/flux/connect';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
+import { URL_API } from '../../config';
+import { isSite } from '../../utils/utils';
+import { Site } from '../../model/site';
+import { link } from '../../model/link';
+import { SelectSiteAction, SelectLinkAction } from '../../actions/detailsAction';
+import { HighlightLinkAction, HighlightSiteAction, ZoomToSearchResultAction } from '../../actions/mapActions';
+import { calculateMidPoint } from '../../utils/mapUtils';
+import { SetSearchValueAction } from '../../actions/searchAction';
+import connect,{ Connect, IDispatcher } from '../../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../../framework/src/store/applicationStore';
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/statistics.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/statistics.tsx
index 4103d64f1..116b789d7 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/statistics.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map/statistics.tsx
@@ -20,8 +20,8 @@ import * as React from 'react';
import { Paper, Typography, Tooltip } from '@material-ui/core';
import InfoIcon from '@material-ui/icons/Info';
-import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
-import connect, { IDispatcher, Connect } from '../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../../framework/src/store/applicationStore';
+import connect, { IDispatcher, Connect } from '../../../../../framework/src/flux/connect';
type props = Connect<typeof mapStateToProps, typeof mapDispatchToProps>;
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/connectivityReducer.ts b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/connectivityReducer.ts
index 7214705e1..8ab82f2e9 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/connectivityReducer.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/connectivityReducer.ts
@@ -17,12 +17,12 @@
*/
import { IActionHandler } from "../../../../framework/src/flux/action";
-import { IsTopologyServerReachableAction, IsTileServerReachableAction } from "../actions/connectivityAction";
+import { IsTopologyServerReachableAction, IsTileServerReachableAction, IsBusycheckingConnectivityAction } from "../actions/connectivityAction";
-export type connectivityState = {isToplogyServerAvailable: boolean, isTileServerAvailable: boolean };
+export type connectivityState = {isToplogyServerAvailable: boolean, isTileServerAvailable: boolean, isBusy: boolean };
-const initialState: connectivityState = {isToplogyServerAvailable: true, isTileServerAvailable: true};
+const initialState: connectivityState = {isToplogyServerAvailable: true, isTileServerAvailable: true, isBusy: true};
export const ConnectivityReducer: IActionHandler<connectivityState> =(state=initialState, action)=> {
@@ -32,6 +32,9 @@ export const ConnectivityReducer: IActionHandler<connectivityState> =(state=init
else if (action instanceof IsTileServerReachableAction){
state = Object.assign({}, state, { isTileServerAvailable: action.reachable });
+ }else if(action instanceof IsBusycheckingConnectivityAction){
+ state = {...state, isBusy: action.isBusy}
+
}
return state;
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/rootReducer.ts b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/rootReducer.ts
index c9c475411..697dbd7a0 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/rootReducer.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/rootReducer.ts
@@ -23,13 +23,15 @@ import { PopupsReducer, popupStoreState } from "./popupReducer";
import { MapReducer, mapState } from "./mapReducer";
import { SearchReducer, searchState } from "./searchReducer";
import { connectivityState, ConnectivityReducer } from './connectivityReducer';
+import { SettingsReducer, SettingsState } from './settingsReducer';
export interface INetworkAppStoreState{
details: DetailsStoreState,
popup: popupStoreState,
map: mapState,
search: searchState,
- connectivity: connectivityState
+ connectivity: connectivityState,
+ settings: SettingsState
}
declare module '../../../../framework/src/store/applicationStore' {
@@ -43,7 +45,8 @@ const appHandler = {
popup: PopupsReducer,
map: MapReducer,
search: SearchReducer,
- connectivity: ConnectivityReducer};
+ connectivity: ConnectivityReducer,
+ settings: SettingsReducer};
export const networkmapRootHandler = combineActionHandler<INetworkAppStoreState>(appHandler)
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/settingsReducer.ts b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/settingsReducer.ts
new file mode 100644
index 000000000..977a379a0
--- /dev/null
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/settingsReducer.ts
@@ -0,0 +1,61 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 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 { NetworkMapSettings, NetworkMapThemes } from "../model/settings";
+import { IActionHandler } from "../../../../framework/src/flux/action";
+import { SetBusyLoadingAction, SetMapSettingsAction, SetSettingsAction, SetThemeSettingsAction } from "../actions/settingsAction";
+
+export type SettingsState = {
+ mapSettings: NetworkMapSettings|null,
+ themes: NetworkMapThemes,
+ isLoadingData: boolean
+};
+
+
+const defaultThemes:NetworkMapThemes = {networkMapThemes:{themes: [
+
+ {key: "light", site: "#11b4da", selectedSite: "#116bda", fiberLink: "#1154d9", microwaveLink: "#039903"},
+ {key: "dark", site: "#000000", selectedSite: "#6e6e6e", fiberLink: "#0a2a6b", microwaveLink: "#005200"},
+]}}
+
+const initialState: SettingsState = {
+ mapSettings: null,
+ themes: defaultThemes,
+ isLoadingData: true
+
+};
+
+export const SettingsReducer: IActionHandler<SettingsState> = (state = initialState, action) => {
+
+ if(action instanceof SetSettingsAction){
+ state = {
+ isLoadingData: false,
+ mapSettings: {networkMap: action.settings.networkMap},
+ themes:{networkMapThemes: {themes: action.settings.networkMapThemes.themes}}
+ };
+ }else if(action instanceof SetMapSettingsAction){
+ state={...state, mapSettings: action.settings};
+ }else if(action instanceof SetThemeSettingsAction){
+ state={...state, themes:{networkMapThemes: {themes: action.settings.networkMapThemes.themes}}};
+ }else if(action instanceof SetBusyLoadingAction){
+ state={...state, isLoadingData: action.busy};
+ }
+
+ return state;
+
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/model/settings.ts b/sdnr/wt/odlux/apps/networkMapApp/src/model/settings.ts
new file mode 100644
index 000000000..521f47ccc
--- /dev/null
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/model/settings.ts
@@ -0,0 +1,34 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 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==========================================================================
+ */
+
+export type NetworkMapSettings = {
+ networkMap: {
+ startupPosition: { latitude?: string, longitude?: string, zoom?: string },
+ tileOpacity: string,
+ styling: { theme: string } } };
+
+export type ThemeElement = {
+ key: string,
+ site: string,
+ selectedSite: string,
+ microwaveLink: string,
+ fiberLink: string};
+
+export type NetworkMapThemes = {networkMapThemes: {themes: ThemeElement[]} };
+
+export type NetworkSettings = NetworkMapSettings & NetworkMapThemes; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/pluginTransport.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/pluginTransport.tsx
index 3ce435f9b..e93368524 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/pluginTransport.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/pluginTransport.tsx
@@ -30,17 +30,46 @@ import applicationApi from "../../../framework/src/services/applicationApi";
import { UpdateDetailsView } from "./actions/detailsAction";
import { findSiteToAlarm } from "./actions/mapActions";
import { URL_BASEPATH } from "./config";
+import { Redirect, Route, RouteComponentProps, Switch, withRouter } from "react-router-dom";
+import CustomizationView from "./components/customize/customizationView";
+import { getSettings } from "./actions/settingsAction";
+import connect, { Connect, IDispatcher } from "../../../framework/src/flux/connect";
+import { IApplicationStoreState } from "../../../framework/src/store/applicationStore";
-const App : React.SFC = (props) => {
- return <MainView />
-};
+const mapProps = (state: IApplicationStoreState) => ({
+});
+
+const mapDisp = (dispatcher: IDispatcher) => ({
+ getSettings: () => dispatcher.dispatch(getSettings())
+
+});
+
+
+const NetworkRouterApp = withRouter(connect(mapProps, mapDisp)((props: RouteComponentProps & Connect<typeof mapProps, typeof mapDisp>) => {
+
+ React.useLayoutEffect(() => {
+ (async function waitFor() {
+ await props.getSettings();
+ })();
+
+ }, []);
+
+ //props.history.action = "POP";
+ return (
+ <Switch>
+ <Route path={`${props.match.path}/customize`} component={CustomizationView} />
+ <Route path={`${props.match.path}`} component={MainView} />
+ <Redirect to={`${props.match.path}`} />
+ </Switch>
+ )
+}));
export function register() {
applicationManager.registerApplication({
name: URL_BASEPATH, // used as name of state as well
icon: faMapMarked,
rootActionHandler: networkmapRootHandler,
- rootComponent: App,
+ rootComponent: NetworkRouterApp,
menuEntry: "Network Map"
});
}
@@ -73,12 +102,13 @@ subscribe<ObjectNotification & IFormatedMessage>(["ObjectCreationNotification",
}));
*/
+/*
subscribe<FaultAlarmNotification & IFormatedMessage>("ProblemNotification", (fault => {
const store = applicationApi && applicationApi.applicationStore;
if (fault && store) {
- store.dispatch(findSiteToAlarm(fault.nodeName));
+ store.dispatch(findSiteToAlarm(fault.nodeName));
+
-
}
-}));
+}));*/
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/services/settingsService.ts b/sdnr/wt/odlux/apps/networkMapApp/src/services/settingsService.ts
new file mode 100644
index 000000000..2a2f09466
--- /dev/null
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/services/settingsService.ts
@@ -0,0 +1,43 @@
+/**
+ * ============LICENSE_START========================================================================
+ * ONAP : ccsdk feature sdnr wt odlux
+ * =================================================================================================
+ * Copyright (C) 2021 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 { NetworkMapSettings, NetworkMapThemes, NetworkSettings } from "../model/settings";
+import { requestRest } from "../../../../framework/src/services/restService";
+
+ class SettingsService{
+
+ public getMapSettings = async () =>{
+ const result = await requestRest<any>("/userdata", {method: "GET"});
+ return result;
+ }
+
+ public getMapThemes = async () =>{
+ const result = await requestRest<NetworkMapThemes>("/userdata/networkMapThemes", {method: "GET"});
+ return result;
+ }
+
+ public updateMapSettings = async (newElement: NetworkMapSettings) =>{
+
+ const result = await requestRest<NetworkMapSettings>("/userdata/networkMap", {method: "PUT", body: JSON.stringify(newElement.networkMap)});
+ return result;
+ }
+
+
+ }
+
+ export const settingsService = new SettingsService(); \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts b/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts
index 1d4aa89ad..6dfd7983a 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/utils/mapLayers.ts
@@ -18,553 +18,313 @@
import * as mapboxgl from 'mapbox-gl';
import { Feature } from 'model/Feature';
+import { NetworkMapThemes, ThemeElement } from 'model/settings';
const fibreLinkColor = "#1154d9";
-const microwaveLinkColor="#039903";
+const microwaveLinkColor = "#039903";
-export const addBaseSources = (map: mapboxgl.Map, selectedPoint: Feature|null, selectedLine: Feature|null) =>{
-
+class MapLayerService {
- // make sure the sources don't already exist
- // (if the networkmap app gets opened quickly within short time periods, the prior sources might not be fully removed)
+ checkedLayers = false;
+ settings: NetworkMapThemes;
+ selectedTheme: string | null = null;
- if(!map.getSource("lines")){
-
- map.addSource('lines', {
- type: 'geojson',
- data: { type: "FeatureCollection", features: [] }
- });
- }
-
- if(!map.getSource("selectedLine"))
- {
- const features = selectedLine !== null ? [selectedLine] : [];
- map.addSource('selectedLine', {
- type: 'geojson',
- data: { type: "FeatureCollection", features: features }
- });
- }
+ public addBaseSources = (map: mapboxgl.Map, selectedPoint: Feature | null, selectedLine: Feature | null) => {
- if(!map.getSource("points"))
- {
- map.addSource('points', {
- type: 'geojson',
- data: { type: "FeatureCollection", features: [] }
- });
- }
- if(!map.getSource("selectedPoints"))
- {
- const selectedPointFeature = selectedPoint !== null ? [selectedPoint] : [];
- map.addSource('selectedPoints', {
- type: 'geojson',
- data: { type: "FeatureCollection", features: selectedPointFeature }
-
- });
- }
+ // make sure the sources don't already exist
+ // (if the networkmap app gets opened quickly within short time periods, the prior sources might not be fully removed)
- if(!map.getSource("alarmedPoints"))
- {
- map.addSource("alarmedPoints", {
- type: 'geojson',
- data: {type:"FeatureCollection", features:[]}
- });
- }
-}
-
-export const addBaseLayers = (map: mapboxgl.Map, selectedPoint: Feature|null, selectedLine: Feature|null) => {
-
- addCommonLayers(map);
+ if (!map.getSource("lines")) {
- map.addLayer({
- id: 'points',
- source: 'points',
- type: 'circle',
- paint: {
- 'circle-color': '#11b4da',
- 'circle-radius': 7,
- 'circle-stroke-width': 1,
- 'circle-stroke-color': '#fff'
+ map.addSource('lines', {
+ type: 'geojson',
+ data: { type: "FeatureCollection", features: [] }
+ });
}
- });
-
- map.addLayer({
- id: 'selectedPoints',
- source: 'selectedPoints',
- type: 'circle',
- paint: {
- 'circle-color': '#116bda',
- 'circle-radius': 9,
- 'circle-stroke-width': 1,
- 'circle-stroke-color': '#fff'
+
+ if (!map.getSource("selectedLine")) {
+ const features = selectedLine !== null ? [selectedLine] : [];
+ map.addSource('selectedLine', {
+ type: 'geojson',
+ data: { type: "FeatureCollection", features: features }
+ });
}
- });
-
- map.addLayer({
- id: 'alarmedPoints',
- source: 'alarmedPoints',
- type: 'circle',
- paint: {
- 'circle-color': '#CC0000',
- 'circle-radius': 9,
- 'circle-stroke-width': 1,
- 'circle-stroke-color': '#fff'
+
+ if (!map.getSource("points")) {
+ map.addSource('points', {
+ type: 'geojson',
+ data: { type: "FeatureCollection", features: [] }
+ });
}
- });
-}
-export const addIconLayers = (map: mapboxgl.Map, selectedSiteId?: string) =>{
+ if (!map.getSource("selectedPoints")) {
+ const selectedPointFeature = selectedPoint !== null ? [selectedPoint] : [];
+ map.addSource('selectedPoints', {
+ type: 'geojson',
+ data: { type: "FeatureCollection", features: selectedPointFeature }
- addCommonLayers(map);
- createIconLayers(map, selectedSiteId);
-}
+ });
+ }
-const createIconLayers =(map: mapboxgl.Map, selectedSiteId?: string) =>{
- map.addLayer({
- 'id': 'point-lamps',
- 'type': 'symbol',
- 'source': 'points',
- 'layout': {
- 'icon-allow-overlap': true,
- 'icon-image': 'lamp',
- 'icon-size': 0.1
-
- },
- 'filter': createFilter("street lamp", selectedSiteId),
- });
-
- map.addLayer({
- 'id': 'point-building',
- 'type': 'symbol',
- 'source': 'points',
- 'filter': createFilter("high rise building", selectedSiteId),
- 'layout': {
- 'icon-allow-overlap': true,
- 'icon-image': 'house',
- 'icon-size': 0.1
+ if (!map.getSource("alarmedPoints")) {
+ map.addSource("alarmedPoints", {
+ type: 'geojson',
+ data: { type: "FeatureCollection", features: [] }
+ });
}
- });
-
- map.addLayer({
- 'id': 'point-data-center',
- 'type': 'symbol',
- 'source': 'points',
- 'filter': createFilter("data center", selectedSiteId),
- 'layout': {
- 'icon-allow-overlap': true,
- 'icon-image': 'data-center',
- 'icon-size': 0.1
- } });
+ }
+
+ private addCircleLayer = (map: mapboxgl.Map, id: string, source: string, circleColor: string, radius: number, strokeWidth: number, outerColor: string) => {
map.addLayer({
- 'id': 'point-factory',
- 'type': 'symbol',
- 'source': 'points',
- 'filter': createFilter("factory", selectedSiteId),
- 'layout': {
- 'icon-allow-overlap': true,
- 'icon-image': 'factory',
- 'icon-size': 0.2
+ id: id,
+ source: source,
+ type: 'circle',
+ paint: {
+ 'circle-color': circleColor,
+ 'circle-radius': radius,
+ 'circle-stroke-width': strokeWidth,
+ 'circle-stroke-color': outerColor
}
});
+ }
- //select layers
+ private addLineLayer = (map: mapboxgl.Map, id: string, source: string, color: string, width: number, filter: string[]) => {
map.addLayer({
- 'id': 'select-point-lamps',
- 'type': 'symbol',
- 'source': 'selectedPoints',
+ 'id': id,
+ 'type': 'line',
+ 'source': source,
'layout': {
- 'icon-allow-overlap': true,
- 'icon-image': 'lamp',
- 'icon-size': 0.15
-
+ 'line-join': 'round',
+ 'line-cap': 'round'
},
- 'filter': ['==', 'type', 'street lamp'],
- });
-
- map.addLayer({
- 'id': 'select-point-buildings',
- 'type': 'symbol',
- 'source': 'selectedPoints',
- 'filter': ['==', 'type', 'high rise building'],
- 'layout': {
- 'icon-allow-overlap': true,
- 'icon-image': 'house',
- 'icon-size': 0.15
- }
- });
-
- map.addLayer({
- 'id': 'select-point-data-center',
- 'type': 'symbol',
- 'source': 'selectedPoints',
- 'filter': ['==', 'type', 'data center'],
- 'layout': {
- 'icon-allow-overlap': true,
- 'icon-image': 'data-center',
- 'icon-size': 0.15
- }
- });
-
- map.addLayer({
- 'id': 'select-point-factory',
- 'type': 'symbol',
- 'source': 'selectedPoints',
- 'filter': ['==', 'type', 'factory'],
- 'layout': {
- 'icon-allow-overlap': true,
- 'icon-image': 'factory',
- 'icon-size': 0.3
- }
+ 'paint': {
+ 'line-color': color,
+ 'line-width': width
+ },
+ 'filter': filter
});
+ }
- //alarm layers
-
+ private addIconLayer = (map: mapboxgl.Map, id: string, source: string, iconName: string, iconSize: number, filter: (string | string[])[]) => {
map.addLayer({
- 'id': 'point-lamps-alarm',
+ 'id': id,
'type': 'symbol',
- 'source': 'alarmedPoints',
+ 'source': source,
'layout': {
'icon-allow-overlap': true,
- 'icon-image': 'lamp-red',
- 'icon-size': 0.15
+ 'icon-image': iconName,
+ 'icon-size': iconSize
},
- 'filter': createFilter("street lamp"),
- });
-
- map.addLayer({
- 'id': 'point-building-alarm',
- 'type': 'symbol',
- 'source': 'alarmedPoints',
- 'filter': createFilter("high rise building"),
- 'layout': {
- 'icon-allow-overlap': true,
- 'icon-image': 'house-red',
- 'icon-size': 0.15
- }
+ 'filter': filter,
});
+ }
- map.addLayer({
- 'id': 'point-data-center-alarm',
- 'type': 'symbol',
- 'source': 'alarmedPoints',
- 'filter': createFilter("data center"),
- 'layout': {
- 'icon-allow-overlap': true,
- 'icon-image': 'data-center-red',
- 'icon-size': 0.15
- } });
-
- map.addLayer({
- 'id': 'point-factory-alarm',
- 'type': 'symbol',
- 'source': 'alarmedPoints',
- 'filter': createFilter("factory"),
- 'layout': {
- 'icon-allow-overlap': true,
- 'icon-image': 'factory-red',
- 'icon-size': 0.3
- }
- });
+ /**
+ * Pick the correct theme based on user selection
+ */
+ private pickTheme = () => {
+ if (this.selectedTheme !== null) {
+ const result = this.settings.networkMapThemes.themes.find(el => el.key === this.selectedTheme);
+ if (result)
+ return result;
- map.addLayer({
- id: 'point-remaining',
- source: 'points',
- type: 'circle',
- 'filter': ['none', ['==', 'type', "high rise building"], ['==', 'type', "data center"], ['==', 'type', "factory"], ['==', 'type', "street lamp"] ],
- paint: {
- 'circle-color': '#11b4da',
- 'circle-radius': 7,
- 'circle-stroke-width': 1,
- 'circle-stroke-color': '#fff'
}
- });
-}
- const addCommonLayers = (map: mapboxgl.Map) =>{
-
- map.addLayer({
- 'id': 'microwave-lines',
- 'type': 'line',
- 'source': 'lines',
- 'layout': {
- 'line-join': 'round',
- 'line-cap': 'round'
- },
- 'paint': {
- 'line-color': microwaveLinkColor,
- 'line-width': 2
- },
- 'filter': ['==', 'type', 'microwave']
- });
-
- map.addLayer({
- 'id': 'fibre-lines',
- 'type': 'line',
- 'source': 'lines',
- 'layout': {
- 'line-join': 'round',
- 'line-cap': 'round'
- },
- 'paint': {
- 'line-color': fibreLinkColor,
- 'line-width': 2
- },
- 'filter': ['==', 'type', 'fibre']
- });
-
- map.addLayer({
- 'id': 'selectedLineMicrowave',
- 'type': 'line',
- 'source': 'selectedLine',
- 'layout': {
- 'line-join': 'round',
- 'line-cap': 'round'
- },
- 'paint': {
- 'line-color': microwaveLinkColor,
- 'line-width': 4
- },
- 'filter': ['==', 'type', 'microwave']
- });
-
- map.addLayer({
- 'id': 'selectedLineFibre',
- 'type': 'line',
- 'source': 'selectedLine',
- 'layout': {
- 'line-join': 'round',
- 'line-cap': 'round'
- },
- 'paint': {
- 'line-color': fibreLinkColor,
- 'line-width': 4
- },
- 'filter': ['==', 'type', 'fibre']
- });
-}
+ return this.settings.networkMapThemes.themes[0];
-export const removeBaseLayers = (map: mapboxgl.Map) => {
-
- map.removeLayer("points");
- map.removeLayer("lines");
- map.removeLayer('selectedPoints');
- map.removeLayer('selectedLine');
-}
-
-const removeIconLayers = (map: mapboxgl.Map) =>{
-
- map.removeLayer('point-building');
- map.removeLayer('point-lamps');
- map.removeLayer('point-data-center');
- map.removeLayer('point-factory');
- map.removeLayer('point-remaining');
- map.removeLayer('select-point-data-center');
- map.removeLayer('select-point-buildings');
- map.removeLayer('select-point-lamps');
- map.removeLayer('select-point-factory');
- map.removeLayer('point-building-alarm');
- map.removeLayer('point-lamps-alarm');
- map.removeLayer('point-data-center-alarm');
- map.removeLayer('point-factory-alarm');
-}
-
-let checkedLayers = false;
+ }
-const createFilter = (type:'street lamp'|'high rise building'|'data center'|'factory', selectedSiteId?:string) =>{
+ public addBaseLayers = (map: mapboxgl.Map, themesettings?: ThemeElement) => {
- return selectedSiteId === undefined ? ['==', 'type', type] : ["all", ['==', 'type', type], ['!=', 'id', selectedSiteId]]
-}
+ const theme = !themesettings ? this.pickTheme() : themesettings;
-export const showIconLayers = (map: mapboxgl.Map, show: boolean, selectedSiteId?: string) => {
+ this.addCommonLayers(map);
- const zoom = map.getZoom();
-
- if(show){
-
- if (zoom > 11) {
+ this.addCircleLayer(map, 'points', 'points', theme.site, 7, 1, '#fff');
+ this.addCircleLayer(map, 'selectedPoints', 'selectedPoints', theme.selectedSite, 9, 1, '#fff');
+ this.addCircleLayer(map, 'alarmedPoints', 'alarmedPoints', '#CC0000', 9, 1, '#fff');
+ }
- const bounds = map.getBounds();
+ public addIconLayers = (map: mapboxgl.Map, selectedSiteId?: string) => {
- if(map.getLayer('points')!== undefined && map.getLayer('point-lamps')===undefined && !checkedLayers){
+ this.addCommonLayers(map);
+ this.createIconLayers(map, selectedSiteId);
+ }
- // if sites don't have a type don't change layers to icons
- const elements = map.queryRenderedFeatures( undefined,{
- layers: ['points'], filter:['has', 'type']
- });
- checkedLayers=true;
+ private createIconLayers = (map: mapboxgl.Map, selectedSiteId?: string) => {
- if(elements.length>0 && elements.length<1000){
+ this.addIconLayer(map, 'point-lamps', 'points', 'lamp', 0.1, this.createFilter("street lamp", selectedSiteId));
+ this.addIconLayer(map, 'point-building', 'points', 'house', 0.1, this.createFilter("high rise building", selectedSiteId));
+ this.addIconLayer(map, 'point-data-center', 'points', 'data-center', 0.1, this.createFilter("data center", selectedSiteId));
+ this.addIconLayer(map, 'point-factory', 'points', 'factory', 0.2, this.createFilter("factory", selectedSiteId));
- if (map.getLayer('point-lamps') === undefined) {
- map.removeLayer('points');
- map.setLayoutProperty('alarmedPoints', 'visibility', 'none');
- map.setLayoutProperty('selectedPoints', 'visibility', 'none');
- createIconLayers(map,selectedSiteId);
- //map.moveLayer('point-remaining','selectedPoints');
- }
- }
- }
-
- } else {
- swapLayersBack(map);
- }
-}else{
- swapLayersBack(map);
-}
-}
+ //select layers
+ this.addIconLayer(map, 'select-point-lamps', 'selectedPoints', 'lamp', 0.15, ['==', 'type', 'street lamp']);
+ this.addIconLayer(map, 'select-point-buildings', 'selectedPoints', 'house', 0.15, ['==', 'type', 'high rise building']);
+ this.addIconLayer(map, 'select-point-data-center', 'selectedPoints', 'data-center', 0.15, ['==', 'type', 'data center']);
+ this.addIconLayer(map, 'select-point-factory', 'selectedPoints', 'factory', 0.3, ['==', 'type', 'factory']);
-export const swapLayersBack = (map: mapboxgl.Map) =>{
- checkedLayers=false;
+ //alarm layers
+ this.addIconLayer(map, 'point-lamps-alarm', 'alarmedPoints', 'lamp-red', 0.3, this.createFilter("street lamp"));
+ this.addIconLayer(map, 'point-building-alarm', 'alarmedPoints', 'house-red', 0.3, this.createFilter("high rise building"));
+ this.addIconLayer(map, 'point-data-center-alarm', 'alarmedPoints', 'data-center-red', 0.3, this.createFilter("data center"));
+ this.addIconLayer(map, 'point-factory-alarm', 'alarmedPoints', 'factory-red', 0.45, this.createFilter("factory"));
- if(map.getLayer('selectedPoints') === undefined){
map.addLayer({
- id: 'selectedPoints',
- source: 'selectedPoints',
+ id: 'point-remaining',
+ source: 'points',
type: 'circle',
+ 'filter': ['none', ['==', 'type', "high rise building"], ['==', 'type', "data center"], ['==', 'type', "factory"], ['==', 'type', "street lamp"]],
paint: {
- 'circle-color': '#116bda',
- 'circle-radius': 9,
+ 'circle-color': '#11b4da',
+ 'circle-radius': 7,
'circle-stroke-width': 1,
'circle-stroke-color': '#fff'
}
});
}
- if(map.getLayer('alarmedPoints') === undefined){
- map.addLayer({
- id: 'alarmedPoints',
- source: 'alarmedPoints',
- type: 'circle',
- paint: {
- 'circle-color': '#CC0000',
- 'circle-radius': 9,
- 'circle-stroke-width': 1,
- 'circle-stroke-color': '#fff'
- }
- });
+ private addCommonLayers = (map: mapboxgl.Map, themesettings?: ThemeElement) => {
+
+ const theme = !themesettings ? this.pickTheme() : themesettings;
+
+ this.addLineLayer(map, 'microwave-lines', 'lines', theme.microwaveLink, 2, ['==', 'type', 'microwave']);
+ this.addLineLayer(map, 'fibre-lines', 'lines', theme.fiberLink, 2, ['==', 'type', 'fibre']);
+ this.addLineLayer(map, 'selectedLineMicrowave', 'selectedLine', theme.microwaveLink, 4, ['==', 'type', 'microwave']);
+ this.addLineLayer(map, 'selectedLineFibre', 'selectedLine', theme.fiberLink, 4, ['==', 'type', 'fibre']);
}
+ public removeBaseLayers = (map: mapboxgl.Map) => {
- if (map.getLayer('points') === undefined) {
+ map.removeLayer("points");
+ map.removeLayer("lines");
+ map.removeLayer('selectedPoints');
+ map.removeLayer('selectedLine');
+ }
- map.setLayoutProperty('selectedPoints', 'visibility', 'visible');
- map.setLayoutProperty('alarmedPoints', 'visibility', 'visible');
- removeIconLayers(map);
+ private removeIconLayers = (map: mapboxgl.Map) => {
+
+ map.removeLayer('point-building');
+ map.removeLayer('point-lamps');
+ map.removeLayer('point-data-center');
+ map.removeLayer('point-factory');
+ map.removeLayer('point-remaining');
+ map.removeLayer('select-point-data-center');
+ map.removeLayer('select-point-buildings');
+ map.removeLayer('select-point-lamps');
+ map.removeLayer('select-point-factory');
+ map.removeLayer('point-building-alarm');
+ map.removeLayer('point-lamps-alarm');
+ map.removeLayer('point-data-center-alarm');
+ map.removeLayer('point-factory-alarm');
+ }
- map.addLayer({
- id: 'points',
- source: 'points',
- type: 'circle',
- paint: {
- 'circle-color': '#11b4da',
- 'circle-radius': 7,
- 'circle-stroke-width': 1,
- 'circle-stroke-color': '#fff'
- }
- });
- map.moveLayer('points', map.getLayer('selectedPoints').id);
+ private createFilter = (type: 'street lamp' | 'high rise building' | 'data center' | 'factory', selectedSiteId?: string) => {
+
+ return selectedSiteId === undefined ? ['==', 'type', type] : ["all", ['==', 'type', type], ['!=', 'id', selectedSiteId]]
}
-}
-const addClusterLayers = (map: mapboxgl.Map, data: any) => {
- map.addSource('clusters', {
- type: 'geojson',
- data: data
- });
-
- map.addSource('selectedLine', {
- type: 'geojson',
- data: { type: "FeatureCollection", features: [] }
- });
-
- map.addSource('selectedPoints', {
- type: 'geojson',
- data: { type: "FeatureCollection", features: [] }
-
- });
-
- map.addLayer({
- id: 'clusters',
- type: 'circle',
- source: 'clusters',
- filter: ['has', 'count'],
- paint: {
- 'circle-color': [
- 'step',
- ['get', 'count'],
- '#51bbd6',
- 100,
- '#f1f075',
- 750,
- '#f28cb1'
- ],
- 'circle-radius': [
- 'step',
- ['get', 'count'],
- 20,
- 100,
- 30,
- 750,
- 40
- ]
+ public showIconLayers = (map: mapboxgl.Map, show: boolean, selectedSiteId?: string) => {
+
+ const zoom = map.getZoom();
+
+ if (show) {
+
+ if (zoom > 11) {
+
+ const bounds = map.getBounds();
+
+ if (map.getLayer('points') !== undefined && map.getLayer('point-lamps') === undefined && !this.checkedLayers) {
+
+ // if sites don't have a type don't change layers to icons
+ const elements = map.queryRenderedFeatures(undefined, {
+ layers: ['points'], filter: ['has', 'type']
+ });
+ this.checkedLayers = true;
+
+ if (elements.length > 0 && elements.length < 1000) {
+
+ if (map.getLayer('point-lamps') === undefined) {
+ map.removeLayer('points');
+ map.setLayoutProperty('alarmedPoints', 'visibility', 'none');
+ map.setLayoutProperty('selectedPoints', 'visibility', 'none');
+ this.createIconLayers(map, selectedSiteId);
+ //map.moveLayer('point-remaining','selectedPoints');
+
+ }
+ }
+ }
+
+ } else {
+ this.swapLayersBack(map);
+ }
+ } else {
+ this.swapLayersBack(map);
}
- });
-
-
- map.addLayer({
- id: 'cluster-count',
- type: 'symbol',
- source: 'clusters',
- filter: ['has', 'count'],
- layout: {
- 'text-field': '{count}',
- 'text-font': ['Roboto Bold'],
- 'text-size': 12
+ }
+
+ public swapLayersBack = (map: mapboxgl.Map) => {
+ this.checkedLayers = false;
+ const theme = this.pickTheme();
+
+ if (map.getLayer('selectedPoints') === undefined) {
+ this.addCircleLayer(map, 'selectedPoints', 'selectedPoints', theme.selectedSite, 9, 1, '#fff');
+
}
- });
-
- map.addLayer({
- 'id': 'selectedLine',
- 'type': 'line',
- 'source': 'selectedLine',
- 'layout': {
- 'line-join': 'round',
- 'line-cap': 'round'
- },
- 'paint': {
- 'line-color': '#888',
- 'line-width': 4
+
+ if (map.getLayer('alarmedPoints') === undefined) {
+ this.addCircleLayer(map, 'alarmedPoints', 'alarmedPoints', '#CC0000', 9, 1, '#fff');
+
+ }
+
+
+ if (map.getLayer('points') === undefined) {
+
+ map.setLayoutProperty('selectedPoints', 'visibility', 'visible');
+ map.setLayoutProperty('alarmedPoints', 'visibility', 'visible');
+ this.removeIconLayers(map);
+
+ this.addCircleLayer(map, 'points', 'points', theme.site, 7, 1, '#fff');
+
+
+ map.moveLayer('points', map.getLayer('selectedPoints').id);
}
- });
-
- map.addLayer({
- id: 'unclustered-points',
- source: 'clusters',
- filter: ['!', ['has', 'count'],],
- type: 'circle',
- paint: {
- 'circle-color': '#11b4da',
- 'circle-radius': 7,
- 'circle-stroke-width': 1,
- 'circle-stroke-color': '#fff'
+ }
+
+ public changeMapOpacity = (map: mapboxgl.Map, newValue: number) => {
+ const newOpacity = newValue / 100;
+ if (map) {
+ const tiles = map.getStyle().layers?.filter(el => el.id.includes("tiles"))
+ tiles?.forEach(layer => {
+ if (layer.type === 'symbol') {
+ map.setPaintProperty(layer.id, `icon-opacity`, newOpacity);
+ map.setPaintProperty(layer.id, `text-opacity`, newOpacity);
+ } else {
+ map.setPaintProperty(layer.id, `${layer.type}-opacity`, newOpacity);
+ }
+ })
}
- });
-
- map.addLayer({
- id: 'selectedPoints',
- source: 'selectedPoints',
- type: 'circle',
- paint: {
- 'circle-color': '#116bda',
- 'circle-radius': 9,
- 'circle-stroke-width': 1,
- 'circle-stroke-color': '#fff'
+
+ }
+
+ public changeTheme = (map: mapboxgl.Map, themeName: string) => {
+ this.selectedTheme = themeName;
+ const theme = this.pickTheme();
+ if (theme && map.loaded()) {
+ map.setPaintProperty('points', 'circle-color', theme.site);
+ map.setPaintProperty('selectedPoints', 'circle-color', theme.selectedSite);
+ map.setPaintProperty('microwave-lines', 'line-color', theme.microwaveLink);
+ map.setPaintProperty('fibre-lines', 'line-color', theme.fiberLink);
}
- });
+ }
+}
+
+const mapLayerService = new MapLayerService();
+export default mapLayerService;
-} \ No newline at end of file