summaryrefslogtreecommitdiffstats
path: root/sdnr/wt/odlux/apps/networkMapApp/src
diff options
context:
space:
mode:
Diffstat (limited to 'sdnr/wt/odlux/apps/networkMapApp/src')
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/actions/detailsAction.ts11
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/actions/mapActions.ts9
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/actions/popupActions.ts5
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/details/details.tsx17
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/details/linkDetails.tsx2
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/details/siteDetails.tsx121
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/map.tsx48
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/mapPopup.tsx12
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/components/searchBar.tsx12
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/config.ts4
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/handlers/detailsReducer.ts14
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/handlers/mapReducer.ts4
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/handlers/popupReducer.ts9
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/model/historyEntry.ts4
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/model/link.ts8
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/model/popupElements.ts22
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/model/site.ts34
-rw-r--r--sdnr/wt/odlux/apps/networkMapApp/src/utils/utils.ts6
18 files changed, 219 insertions, 123 deletions
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/actions/detailsAction.ts b/sdnr/wt/odlux/apps/networkMapApp/src/actions/detailsAction.ts
index afa8ee41e..34cf10915 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/actions/detailsAction.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/actions/detailsAction.ts
@@ -20,14 +20,14 @@ import { Action } from '../../../../framework/src/flux/action';
import { requestRest } from '../../../../framework/src/services/restService';
-import { site, Device } from "../model/site";
+import { Site, Device } from "../model/site";
import { link } from '../model/link';
import { HistoryEntry } from "../model/historyEntry";
import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore';
import { Dispatch } from '../../../../framework/src/flux/store';
export class SelectSiteAction extends Action {
- constructor(public site: site){
+ constructor(public site: Site){
super()
}
}
@@ -74,6 +74,12 @@ export class ClearLoadedDevicesAction extends Action{
}
}
+export class InitializeLoadedDevicesAction extends Action{
+ constructor(public devices: Device[]){
+ super();
+ }
+}
+
let running=false;
export const UpdateDetailsView = (nodeId: string) =>(dispatcher: Dispatch, getState: () => IApplicationStoreState) =>{
@@ -92,7 +98,6 @@ export const UpdateDetailsView = (nodeId: string) =>(dispatcher: Dispatch, getSt
dispatcher(new FinishedLoadingDeviceListAction(checkedDevices));
});
-
}
}
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/actions/mapActions.ts b/sdnr/wt/odlux/apps/networkMapApp/src/actions/mapActions.ts
index b8af40b0c..9830c06e4 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/actions/mapActions.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/actions/mapActions.ts
@@ -21,7 +21,7 @@ import { Dispatch } from '../../../../framework/src/flux/store';
import { link } from "../model/link";
-import { site } from "../model/site";
+import { Site } from "../model/site";
import { Feature } from '../model/Feature';
import { URL_API } from '../config';
@@ -33,7 +33,7 @@ export class HighlightLinkAction extends Action{
}
export class HighlightSiteAction extends Action{
- constructor(public site: site){
+ constructor(public site: Site){
super();
}
}
@@ -51,7 +51,7 @@ export class ZoomToSearchResultAction extends Action{
}
export class AddAlarmAction extends Action{
- constructor(public element: Feature){
+ constructor(public site: Site){
super();
}
}
@@ -75,7 +75,8 @@ export class SetIconSwitchAction extends Action{
}
export const findSiteToAlarm = (alarmedNodeId: string) => (dispatcher: Dispatch) =>{
- fetch(URL_API+"/site/geojson/device/"+alarmedNodeId)
+ //TODO: fix!
+ fetch(URL_API+"/sites/devices/"+alarmedNodeId)
.then(res => res.json())
.then(result=>{
dispatcher(new AddAlarmAction(result));
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/actions/popupActions.ts b/sdnr/wt/odlux/apps/networkMapApp/src/actions/popupActions.ts
index ff8d07921..a8c54d4df 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/actions/popupActions.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/actions/popupActions.ts
@@ -16,6 +16,7 @@
* ============LICENSE_END==========================================================================
*/
+import { PopupElement } from '../model/popupElements';
import { Action } from '../../../../framework/src/flux/action';
export class SetPopupPositionAction extends Action {
@@ -25,7 +26,7 @@ export class SetPopupPositionAction extends Action {
}
export class SelectMultipleLinksAction extends Action {
- constructor(public ids: string[]) {
+ constructor(public elements: PopupElement[]) {
super();
}
}
@@ -33,7 +34,7 @@ export class SelectMultipleLinksAction extends Action {
export class SelectMultipleSitesAction extends Action {
- constructor(public ids: string[]) {
+ constructor(public elements: PopupElement[]) {
super();
}
} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/details/details.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/details.tsx
index 081276b5c..2540b20a7 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/details/details.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/details.tsx
@@ -20,7 +20,7 @@ import * as React from 'react'
import connect, { IDispatcher, Connect } from '../../../../../framework/src/flux/connect';
-import { site, Device } from '../../model/site';
+import { Site, Device } from '../../model/site';
import Typography from '@material-ui/core/Typography';
import { link } from '../../model/link';
import { Breadcrumbs, Link, Paper } from '@material-ui/core';
@@ -76,7 +76,7 @@ const Details: React.FunctionComponent<porps> = (props) => {
}, [props.data])
const onLinkClick = async (id: string) => {
- const result = await fetch(`${URL_API}/link/${id}`);
+ const result = await fetch(`${URL_API}/links/${id}`);
if(result.ok){
const resultAsJson = await result.json();
const link = resultAsJson as link;
@@ -102,10 +102,9 @@ const Details: React.FunctionComponent<porps> = (props) => {
e.preventDefault();
}
- const createDetailPanel = (data: site | link) => {
-
+ const createDetailPanel = (data: Site | link) => {
if (isSite(data)) {
- return <SiteDetails navigate={props.navigateToApplication} updatedDevices={props.updatedDevices} loadDevices={props.loadDevices} site={data} onLinkClick={onLinkClick} />
+ return <SiteDetails site={data} onLinkClick={onLinkClick} />
} else {
return <LinkDetails link={data} />
}
@@ -120,7 +119,7 @@ const Details: React.FunctionComponent<porps> = (props) => {
const loadDetailsData = (id: string) =>{
- fetch(`${URL_API}/link/${id}`)
+ fetch(`${URL_API}/links/${id}`)
.then(res => {
if (res.ok)
return res.json()
@@ -135,7 +134,7 @@ const Details: React.FunctionComponent<porps> = (props) => {
})
.catch(error => {
- fetch(`${URL_API}/site/${id}`)
+ fetch(`${URL_API}/sites/name/${id}`)
.then(res => {
if (res.ok)
return res.json()
@@ -188,13 +187,13 @@ const mapStateToProps = (state: IApplicationStoreState) => ({
});
const mapDispatchToProps = (dispatcher: IDispatcher) => ({
- selectSite: (site: site) => dispatcher.dispatch(new SelectSiteAction(site)),
+ selectSite: (site: Site) => dispatcher.dispatch(new SelectSiteAction(site)),
selectLink: (link: link) => dispatcher.dispatch(new SelectLinkAction(link)),
clearDetails: () => dispatcher.dispatch(new ClearDetailsAction()),
addHistory: (newEntry: HistoryEntry) => dispatcher.dispatch(new AddToHistoryAction(newEntry)),
clearHistory: () => dispatcher.dispatch(new ClearHistoryAction()),
highlightLink: (link: link) => dispatcher.dispatch(new HighlightLinkAction(link)),
- highlightSite: (site: site) => dispatcher.dispatch(new HighlightSiteAction(site)),
+ highlightSite: (site: Site) => dispatcher.dispatch(new HighlightSiteAction(site)),
loadDevices: async (networkElements: Device[]) => { await dispatcher.dispatch(CheckDeviceList(networkElements)) },
navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path, "test3")),
undoMapSelection: () => dispatcher.dispatch(new RemoveHighlightingAction())
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/details/linkDetails.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/linkDetails.tsx
index 81f9bba90..b2c724636 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/details/linkDetails.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/linkDetails.tsx
@@ -77,7 +77,7 @@ const LinkDetails: React.FunctionComponent<props> = (props) => {
{name:"Site Name", val1: props.link.siteA, val2: props.link.siteB},
{name:"Latitude", val1: LatLonToDMS(props.link.locationA.lat), val2: LatLonToDMS(props.link.locationB.lat)},
{name:"Longitude", val1: LatLonToDMS(props.link.locationA.lon, true), val2: LatLonToDMS(props.link.locationB.lon, true)},
- {name:"Azimuth in °", val1: props.link.azimuthA.toFixed(2), val2: props.link.azimuthB.toFixed(2)}
+ props.link.azimuthA!= null && props.link.azimuthB != null && {name:"Azimuth in °", val1: props.link.azimuthA.toFixed(2), val2: props.link.azimuthB.toFixed(2)}
];
return (<div style={{ paddingLeft: "15px", paddingRight: "15px", paddingTop: "0px", display: 'flex', flexDirection: 'column' }}>
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/details/siteDetails.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/siteDetails.tsx
index 5e617be2d..3aa35c348 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/details/siteDetails.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/details/siteDetails.tsx
@@ -23,19 +23,28 @@ import { TextField, Tabs, Tab, Typography, AppBar, Button, Tooltip } from '@mate
import MaterialTable, { ColumnModel, ColumnType, MaterialTableCtorType } from "../../../../../framework/src/components/material-table";
-import { site, Device } from '../../model/site';
+import { Site, Device, Address } from '../../model/site';
import DenseTable from '../denseTable';
import { LatLonToDMS } from '../../utils/mapUtils';
+import { CheckDeviceList, InitializeLoadedDevicesAction } from '../../actions/detailsAction';
+import { NavigateToApplication } from '../../../../../framework/src/actions/navigationActions';
+import connect, { Connect, IDispatcher } from '../../../../../framework/src/flux/connect';
+import { IApplicationStoreState } from '../../../../../framework/src/store/applicationStore';
-type minLinks = { name: string, azimuth: string}
-
-const FaultAlarmNotificationTable = MaterialTable as MaterialTableCtorType<minLinks>;
+type linkRow = { name: string, azimuth?: string}
+type deviceRow = { id: string;type: string,name: string,manufacturer: string,owner: string,status?: string,port: number[]}
type panelId="links" | "nodes";
-type props = { site: site, updatedDevices: Device[]|null, navigate(applicationName: string, path?: string):void, onLinkClick(id: string): void, loadDevices(devices:Device[]): void };
+type siteDetailProps = {
+ site: Site,
+ onLinkClick(id: string): void,
+} & props;
+
+type props = Connect<typeof mapStateToProps, typeof mapDispatchToProps>;
+
-const SiteDetails: React.FunctionComponent<props> = (props) => {
+const SiteDetails: React.FunctionComponent<siteDetailProps> = (props) => {
const [value, setValue] = React.useState<panelId>("links");
const [height, setHeight] = React.useState(330);
@@ -59,21 +68,51 @@ const SiteDetails: React.FunctionComponent<props> = (props) => {
// on update
React.useEffect(()=>{
-
- props.loadDevices(props.site.devices);
+
+ if(props.site.devices!== null && props.site.devices.length>0){
+ props.initializeDevices(props.site.devices);
+ props.loadDevices(props.site.devices);
+ }
+
handleResize();
- }, [props.site])
+ }, [props.site]);
const onHandleTabChange = (event: React.ChangeEvent<{}>, newValue: panelId) => {
setValue(newValue);
}
- const linkRows: minLinks[] = props.site.links.map(link=>
+ //prepare link table
+
+ let hasAzimuth = false;
+ const linkRows: linkRow[] = props.site.links.map(link=>
{
- return {name: link.name, azimuth: link.azimuthB.toFixed(2) }
+ if(link.azimuthB!==null){
+ hasAzimuth=true;
+ return {name: link.name, azimuth: link.azimuthB.toFixed(2) }
+
+ }else{
+ return {name: link.name }
+ }
+
});
+
+ const linkTableHeader = hasAzimuth ? ["Link Name", "Azimuth in °"] : ["Link Name"];
+
+ //prepare device table
+ const deviceRows : deviceRow[] = props.updatedDevices.map(device=>{
+ return{
+ id: device.id,
+ name: device.name,
+ type: device.type,
+ status: device.status,
+ manufacturer: device.manufacturer,
+ owner: device.owner,
+ port: device.port
+ }
+ });
+ const adressString = props.site.address == null ? null : buildAdress(props.site.address);
return (<div style={{ padding: '15px', display: "flex", flexDirection:"column", minWidth:0, minHeight:0 }}>
@@ -88,20 +127,20 @@ const SiteDetails: React.FunctionComponent<props> = (props) => {
<TextField inputProps={{ 'aria-label': 'type' }} disabled={true} value={props.site.type} label="Type" style={{ marginTop: "5px" }} />
}
{
- props.site.address !== undefined && props.site.address.length > 0 &&
- <TextField inputProps={{ 'aria-label': 'adress' }} disabled={true} value={props.site.address} label="Adress" style={{ marginTop: "5px" }} />
+ adressString !== null &&
+ <TextField inputProps={{ 'aria-label': 'adress' }} disabled={true} value={adressString} label="Address" style={{ marginTop: "5px" }} />
}
{
- props.site.heighAGLInMeters !== undefined && props.site.heighAGLInMeters > 0 &&
- <TextField inputProps={{ 'aria-label': 'amsl-in-meters' }} disabled={true} value={props.site.heighAGLInMeters} label="AMSL in meters" style={{ marginTop: "5px" }} />
+ props.site.heightAmslInMeters !== undefined && props.site.heightAmslInMeters > 0 &&
+ <TextField inputProps={{ 'aria-label': 'amsl-in-meters' }} disabled={true} value={props.site.heightAmslInMeters} label="AMSL in meters" style={{ marginTop: "5px" }} />
}
{
- props.site.antennaHeightAGLInMeters !== undefined && props.site.antennaHeightAGLInMeters > 0 &&
- <TextField inputProps={{ 'aria-label': 'antenna-above-ground-in-meters' }} disabled={true} value={props.site.antennaHeightAGLInMeters} label="Atenna above ground in meters" style={{ marginTop: "5px" }} />
+ props.site.antennaHeightAmslInMeters !== undefined && props.site.antennaHeightAmslInMeters > 0 &&
+ <TextField inputProps={{ 'aria-label': 'antenna-above-ground-in-meters' }} disabled={true} value={props.site.antennaHeightAmslInMeters} label="Atenna above ground in meters" style={{ marginTop: "5px" }} />
}
- <TextField inputProps={{ 'aria-label': 'latitude' }} style={{ marginTop: "5px" }} disabled={true} value={LatLonToDMS(props.site.geoLocation.lat)} label="Latitude" />
- <TextField inputProps={{ 'aria-label': 'longitude' }} style={{ marginTop: "5px" }} disabled={true} value={LatLonToDMS(props.site.geoLocation.lon, true)} label="Longitude" />
+ <TextField inputProps={{ 'aria-label': 'latitude' }} style={{ marginTop: "5px" }} disabled={true} value={LatLonToDMS(props.site.location.lat)} label="Latitude" />
+ <TextField inputProps={{ 'aria-label': 'longitude' }} style={{ marginTop: "5px" }} disabled={true} value={LatLonToDMS(props.site.location.lon, true)} label="Longitude" />
<AppBar position="static" style={{ marginTop: "5px", background: '#2E3B55' }}>
<Tabs id="site-tabs" value={value} onChange={onHandleTabChange} aria-label="simple tabs example">
@@ -119,13 +158,8 @@ const SiteDetails: React.FunctionComponent<props> = (props) => {
{
props.site.links.length > 0 &&
- <DenseTable ariaLabelRow="available-links-table" ariaLabelColumn={["link-name", "azimuth"]} height={height} hover={true} headers={["Link Name", "Azimuth in °"]} data={linkRows} onClick={props.onLinkClick} ></DenseTable>
- /**
- *
- * */
-
-
- }
+ <DenseTable ariaLabelRow="available-links-table" ariaLabelColumn={["link-name", "azimuth"]} height={height} hover={true} headers={linkTableHeader} data={linkRows} onClick={props.onLinkClick} ></DenseTable>
+ }
</>
@@ -134,19 +168,46 @@ const SiteDetails: React.FunctionComponent<props> = (props) => {
value === "nodes" &&
<>
{
- props.site.devices.length === 0 &&
+ props.site.devices === null &&
<Typography aria-label="no-nodes-avilable" variant="body1" style={{ marginTop: '10px' }}>No nodes available.</Typography>
}
{
- props.site.devices.length>0 && props.updatedDevices !== null &&
- <DenseTable ariaLabelRow="available-nodes-table" ariaLabelColumn={["id","name","type", "manufacturer","owner","status", "ports", "actions"]} navigate={props.navigate} height={height} hover={false} headers={["ID","Name","Type", "Manufacturer","Owner","Status", "Ports", "Actions"]} actions={true} data={props.updatedDevices!} />
+ props.site.devices?.length>0 && props.updatedDevices !== null &&
+ <DenseTable ariaLabelRow="available-nodes-table" ariaLabelColumn={["id","name","type","status", "manufacturer","owner", "ports", "actions"]} navigate={props.navigateToApplication} height={height} hover={false} headers={["ID","Name","Type","Status", "Manufacturer","Owner", "Ports", "Actions"]} actions={true} data={deviceRows!} />
}
</>
}
</div>
)
+}
+
+const buildAdress = (adress: Address) =>{
+ switch(adress.country){
+ case "de":
+ return `${adress.streetAndNr}, ${adress.zipCode!== null? adress.zipCode : ''} ${adress.city}`
+
+ case "us":
+ return `${adress.streetAndNr}, ${adress.city} ${adress.zipCode!== null? adress.zipCode : ''}`
+
+ default:
+ console.log("address formatting for country {"+adress.country+"} not recognized, defaulting.");
+ return `${adress.streetAndNr}, ${adress.zipCode!== null? adress.zipCode : ''} ${adress.city}`
+ }
+
+
}
-export default SiteDetails; \ No newline at end of file
+const mapStateToProps = (state: IApplicationStoreState) => ({
+ updatedDevices: state.network.details.checkedDevices
+});
+
+const mapDispatchToProps = (dispatcher: IDispatcher) => ({
+ initializeDevices: (devices: Device[]) => {dispatcher.dispatch(new InitializeLoadedDevicesAction(devices))},
+ loadDevices: async (networkElements: Device[]) => { await dispatcher.dispatch(CheckDeviceList(networkElements)) },
+ navigateToApplication: (applicationName: string, path?: string) => dispatcher.dispatch(new NavigateToApplication(applicationName, path, "test3")),
+
+})
+
+export default connect(mapStateToProps, mapDispatchToProps)(SiteDetails); \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/map.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/map.tsx
index e2935f6b7..855e5cedf 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/map.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/map.tsx
@@ -21,7 +21,7 @@ import * as mapboxgl from 'mapbox-gl';
import { RouteComponentProps, withRouter } from 'react-router-dom';
-import { site } from '../model/site';
+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';
@@ -36,13 +36,10 @@ import SearchBar from './searchBar';
import { verifyResponse, IsTileServerReachableAction, handleConnectionError, setTileServerReachableAction } from '../actions/connectivityAction';
import ConnectionInfo from './connectionInfo'
import { showIconLayers, addBaseLayers, addBaseSources, addIconLayers } from '../utils/mapLayers';
-import lamp from '../../icons/lamp.png';
-import apartment from '../../icons/apartment.png';
-import datacenter from '../../icons/datacenter.png';
-import factory from '../../icons/factory.png';
import Statistics from './statistics';
import IconSwitch from './iconSwitch';
import { addImages } from '../services/mapImagesService';
+import { PopupElement } from '../model/popupElements';
type coordinates = { lat: number, lon: number, zoom: number }
@@ -86,7 +83,7 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
console.error("tileserver " + URL_TILE_API + " can't be reached.");
});
- fetch(URL_API + "/info")
+ fetch(URL_API + "/info/count/all")
.then(result => verifyResponse(result))
.catch(error => this.props.handleConnectionError(error));
}
@@ -132,7 +129,7 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
const boundingBox = increaseBoundingBox(map);
- fetch(`${URL_API}/links/geoJson/${boundingBox.west},${boundingBox.south},${boundingBox.east},${boundingBox.north}`)
+ fetch(`${URL_API}/links/geojson/${boundingBox.west},${boundingBox.south},${boundingBox.east},${boundingBox.north}`)
.then(result => verifyResponse(result))
.then(result => result.json())
.then(features => {
@@ -143,7 +140,7 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
.catch(error => this.props.handleConnectionError(error));
- fetch(`${URL_API}/sites/geoJson/${boundingBox.west},${boundingBox.south},${boundingBox.east},${boundingBox.north}`)
+ fetch(`${URL_API}/sites/geojson/${boundingBox.west},${boundingBox.south},${boundingBox.east},${boundingBox.north}`)
.then(result => verifyResponse(result))
.then(result => result.json())
.then(features => {
@@ -439,8 +436,8 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
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()}`);
+ 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
@@ -451,8 +448,8 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
//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}`);
+ 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
@@ -462,8 +459,8 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
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()}`);
+ 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()}`);
}
}
@@ -481,18 +478,18 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
showSitePopup = (sites: mapboxgl.MapboxGeoJSONFeature[], top: number, left: number) => {
if (sites.length > 1) {
- const ids = sites.map(feature => feature.properties!.id);
+ const elements: PopupElement[] = sites.map(feature => {return {name: feature.properties!.name, id: feature.properties!.id}});
this.props.setPopupPosition(top, left);
- this.props.selectMultipleSites(ids);
+ this.props.selectMultipleSites(elements); //name, id object container
this.setState({ isPopupOpen: true });
} else {
const id = sites[0].properties!.id;
- fetch(`${URL_API}/site/${id}`)
+ fetch(`${URL_API}/sites/${id}`)
.then(result => verifyResponse(result))
- .then(res => res.json() as Promise<site>)
+ .then(res => res.json() as Promise<Site>)
.then(result => {
this.props.selectSite(result);
this.props.highlightSite(result);
@@ -506,15 +503,16 @@ class Map extends React.Component<mapProps, { isPopupOpen: boolean }> {
if (links.length > 1) {
- const ids = links.map(feature => feature.properties!.id as string);
+ const elements: PopupElement[] = links.map(feature => {return {name: feature.properties!.name, id: feature.properties!.id}});
+
this.props.setPopupPosition(top, left);
- this.props.selectMultipleLinks(ids);
+ this.props.selectMultipleLinks(elements);
this.setState({ isPopupOpen: true });
} else {
var id = links[0].properties!.id;
- fetch(`${URL_API}/link/${id}`)
+ fetch(`${URL_API}/links/${id}`)
.then(result => verifyResponse(result))
.then(res => res.json() as Promise<link>)
.then(result => {
@@ -578,14 +576,14 @@ const mapStateToProps = (state: IApplicationStoreState) => ({
});
const mapDispatchToProps = (dispatcher: IDispatcher) => ({
- selectSite: (site: site) => dispatcher.dispatch(new SelectSiteAction(site)),
+ selectSite: (site: Site) => dispatcher.dispatch(new SelectSiteAction(site)),
selectLink: (link: link) => dispatcher.dispatch(new SelectLinkAction(link)),
clearDetailsHistory: () => dispatcher.dispatch(new ClearHistoryAction()),
- selectMultipleLinks: (ids: string[]) => dispatcher.dispatch(new SelectMultipleLinksAction(ids)),
- selectMultipleSites: (ids: string[]) => dispatcher.dispatch(new SelectMultipleSitesAction(ids)),
+ 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)),
+ 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)),
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/mapPopup.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/mapPopup.tsx
index 040024760..7435a0a3f 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/mapPopup.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/mapPopup.tsx
@@ -19,7 +19,7 @@
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 { Site } from '../model/site';
import { link } from '../model/link';
import { URL_API } from '../config';
import { HighlightLinkAction, HighlightSiteAction } from '../actions/mapActions';
@@ -40,7 +40,7 @@ const MapPopup: React.FunctionComponent<props> = (props) => {
const id = event.target.value;
- fetch(`${URL_API}/${props.type}/${id}`)
+ fetch(`${URL_API}/${props.type.toLocaleLowerCase()}s/${id}`)
.then(result => verifyResponse(result))
.then(res => res.json())
.then(result => {
@@ -64,7 +64,7 @@ const MapPopup: React.FunctionComponent<props> = (props) => {
<Select style={{ width: 300 }} onChange={handleChange} value={value} native>
<option value={""} disabled>{props.type} ids</option>
{
- props.ids.map(id => <option key={id} value={id}>{id}</option>)
+ props.elements.map(el => <option key={el.id} value={el.id}>{el.name}</option>)
}
</Select>
</Paper>
@@ -75,17 +75,17 @@ const MapPopup: React.FunctionComponent<props> = (props) => {
type props = Connect<typeof mapStateToProps, typeof mapDispatchToProps>& { onClose(): void }
const mapStateToProps = (state: IApplicationStoreState) => ({
- ids: state.network.popup.selectionPendingForIds,
+ elements: state.network.popup.selectionPendingForElements,
type: state.network.popup.pendingDataType,
position: state.network.popup.position
});
const mapDispatchToProps = (dispatcher: IDispatcher) => ({
- selectElement: (site: site) => dispatcher.dispatch(new SelectSiteAction(site)),
+ selectElement: (site: Site) => dispatcher.dispatch(new SelectSiteAction(site)),
clearDetailsHistory:()=> dispatcher.dispatch(new ClearHistoryAction()),
highlightLink: (link: link) => dispatcher.dispatch(new HighlightLinkAction(link)),
- highlightSite: (site: site) => dispatcher.dispatch(new HighlightSiteAction(site)),
+ highlightSite: (site: Site) => dispatcher.dispatch(new HighlightSiteAction(site)),
handleConnectionError: (error:Error) => dispatcher.dispatch(handleConnectionError(error)),
clearDetails: () => dispatcher.dispatch(new ClearDetailsAction()),
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/components/searchBar.tsx b/sdnr/wt/odlux/apps/networkMapApp/src/components/searchBar.tsx
index c825e5ae0..2e698158d 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/components/searchBar.tsx
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/components/searchBar.tsx
@@ -22,7 +22,7 @@ import SearchIcon from '@material-ui/icons/Search';
import { URL_API } from '../config';
import { isSite } from '../utils/utils';
-import { site } from '../model/site';
+import { Site } from '../model/site';
import { link } from '../model/link';
import { SelectSiteAction, SelectLinkAction } from '../actions/detailsAction';
import { HighlightLinkAction, HighlightSiteAction, ZoomToSearchResultAction } from '../actions/mapActions';
@@ -74,9 +74,9 @@ const SearchBar: React.FunctionComponent<searchBarProps> = (props) =>{
setAnchorEl(null);
if(props.searchterm.length>0){
- const siteResult = fetch(`${URL_API}/site/${props.searchterm}`)
+ const siteResult = fetch(`${URL_API}/sites/name/${props.searchterm}`)
- const linkResult = fetch(`${URL_API}/link/${props.searchterm}`);
+ const linkResult = fetch(`${URL_API}/links/${props.searchterm}`);
Promise.all([ siteResult, linkResult]).then((result)=>{
const suceededResults = result.filter(el=> el.ok);
@@ -92,7 +92,7 @@ const SearchBar: React.FunctionComponent<searchBarProps> = (props) =>{
if(isSite(result)){
props.selectSite(result);
props.highlightSite(result);
- props.zoomToSearchResult(result.geoLocation.lat, result.geoLocation.lon);
+ props.zoomToSearchResult(result.location.lat, result.location.lon);
}else{
props.selectLink(result);
props.highlightLink(result);
@@ -149,10 +149,10 @@ type searchBarProps = Connect<typeof mapStateToProps, typeof mapDispatchToProps>
const mapDispatchToProps = (dispatcher: IDispatcher) => ({
- selectSite:(site: site)=> dispatcher.dispatch(new SelectSiteAction(site)),
+ selectSite:(site: Site)=> dispatcher.dispatch(new SelectSiteAction(site)),
selectLink:(link: link) => dispatcher.dispatch(new SelectLinkAction(link)),
highlightLink:(link: link)=> dispatcher.dispatch(new HighlightLinkAction(link)),
- highlightSite: (site: site) => dispatcher.dispatch(new HighlightSiteAction(site)),
+ highlightSite: (site: Site) => dispatcher.dispatch(new HighlightSiteAction(site)),
setSearchTerm: (value: string) => dispatcher.dispatch(new SetSearchValueAction(value)),
zoomToSearchResult: (lat: number, lon: number) => dispatcher.dispatch(new ZoomToSearchResultAction(lat, lon)),
});;
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/config.ts b/sdnr/wt/odlux/apps/networkMapApp/src/config.ts
index a85259d47..633bd3732 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/config.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/config.ts
@@ -16,8 +16,8 @@
* ============LICENSE_END==========================================================================
*/
-export const URL_API="/topology"
-export const URL_TILE_API = '/tiles';
+export const URL_API="/topology/network"
+export const URL_TILE_API = '/tiles'; // http://tile.openstreetmap.org can be used for local testing, never commit with tile url changed! /tiles
export const OSM_STYLE = {
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/detailsReducer.ts b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/detailsReducer.ts
index f573009bd..67e10e629 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/detailsReducer.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/detailsReducer.ts
@@ -18,15 +18,15 @@
import { IActionHandler } from '../../../../framework/src/flux/action';
import { link } from "../model/link";
-import { site, Device } from "../model/site";
+import { Site, Device } from "../model/site";
import { HistoryEntry } from "../model/historyEntry";
-import { SelectSiteAction, SelectLinkAction, AddToHistoryAction, ClearHistoryAction, IsBusyCheckingDeviceListAction, FinishedLoadingDeviceListAction, ClearLoadedDevicesAction, ClearDetailsAction } from '../actions/detailsAction';
+import { SelectSiteAction, SelectLinkAction, AddToHistoryAction, ClearHistoryAction, IsBusyCheckingDeviceListAction, FinishedLoadingDeviceListAction, ClearLoadedDevicesAction, ClearDetailsAction, InitializeLoadedDevicesAction } from '../actions/detailsAction';
export type DetailsStoreState={
- data: site | link | null,
+ data: Site | link | null,
history: HistoryEntry[],
isBusyCheckingDeviceList: boolean,
- checkedDevices: Device[] | null
+ checkedDevices: Device[]
}
@@ -34,7 +34,7 @@ const initialState: DetailsStoreState = {
data: null,
history:[],
isBusyCheckingDeviceList: false,
- checkedDevices: null
+ checkedDevices: []
}
export const DetailsReducer:IActionHandler<DetailsStoreState>=(state = initialState, action)=>{
@@ -59,8 +59,10 @@ export const DetailsReducer:IActionHandler<DetailsStoreState>=(state = initialSt
state = Object.assign({}, state, {checkedDevices: action.devices});
}else if(action instanceof ClearLoadedDevicesAction){
- state = Object.assign({}, state, {checkedDevices: null});
+ state = Object.assign({}, state, {checkedDevices: []});
+ }else if(action instanceof InitializeLoadedDevicesAction){
+ state = Object.assign({}, state, {checkedDevices: action.devices});
}
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/mapReducer.ts b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/mapReducer.ts
index 5c1c6d285..b820746b5 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/mapReducer.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/mapReducer.ts
@@ -56,12 +56,12 @@ export const MapReducer: IActionHandler<mapState> = (state=initialState, action:
}
else if(action instanceof HighlightSiteAction){
- state = Object.assign({}, state, {selectedLink: null, selectedSite:{type: "Feature", properties: {id: action.site.name, type:action.site.type}, geometry:{type:"Point", coordinates:[action.site.geoLocation.lon,action.site.geoLocation.lat ]}}})
+ state = Object.assign({}, state, {selectedLink: null, selectedSite:{type: "Feature", properties: {id: action.site.name, type:action.site.type}, geometry:{type:"Point", coordinates:[action.site.location.lon,action.site.location.lat ]}}})
}else if (action instanceof ZoomToSearchResultAction){
state = Object.assign({}, state, {zoomToElement:{lat: action.lat, lon: action.lon}});
}else if (action instanceof AddAlarmAction){
- state = Object.assign({}, state, {alarmlement:action.element});
+ state = Object.assign({}, state, {alarmlement:{type: "Feature", properties: {id: action.site.name, type:action.site.type}, geometry:{type:"Point", coordinates:[action.site.location.lon,action.site.location.lat ]}}});
}else if(action instanceof SetCoordinatesAction){
state = Object.assign({}, state, {lat:action.lat, lon: action.lon, zoom:action.zoom});
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/popupReducer.ts b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/popupReducer.ts
index dcac9c9c2..deb366e09 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/handlers/popupReducer.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/handlers/popupReducer.ts
@@ -16,17 +16,18 @@
* ============LICENSE_END==========================================================================
*/
+import { PopupElement } from 'model/popupElements';
import { IActionHandler } from '../../../../framework/src/flux/action';
import { SelectMultipleLinksAction, SelectMultipleSitesAction, SetPopupPositionAction } from "../actions/popupActions";
export type popupStoreState = {
- selectionPendingForIds: string[],
+ selectionPendingForElements: PopupElement[],
pendingDataType: "link"|"site"| "",
position: { top: number, left: number }
};
const initialState: popupStoreState = {
- selectionPendingForIds: [],
+ selectionPendingForElements: [],
pendingDataType: "",
position: { top: 0, left: 0 }
};
@@ -34,10 +35,10 @@ const initialState: popupStoreState = {
export const PopupsReducer: IActionHandler<popupStoreState> = (state = initialState, action) => {
if(action instanceof SelectMultipleLinksAction){
- state = Object.assign({}, state, { selectionPendingForIds: action.ids, pendingDataType: "link", isSelectionNeeded: true });
+ state = Object.assign({}, state, { selectionPendingForElements: action.elements, pendingDataType: "link", isSelectionNeeded: true });
}else if(action instanceof SelectMultipleSitesAction){
- state = Object.assign({}, state, { selectionPendingForIds: action.ids, pendingDataType: "site", isSelectionNeeded: true });
+ state = Object.assign({}, state, { selectionPendingForElements: action.elements, pendingDataType: "site", isSelectionNeeded: true });
}else if(action instanceof SetPopupPositionAction){
state= Object.assign({}, state, {position:{top:action.top, left: action.left}})
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/model/historyEntry.ts b/sdnr/wt/odlux/apps/networkMapApp/src/model/historyEntry.ts
index 707ff3d2a..d7197a4d1 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/model/historyEntry.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/model/historyEntry.ts
@@ -16,7 +16,7 @@
* ============LICENSE_END==========================================================================
*/
-import { site } from "./site";
+import { Site } from "./site";
import { link } from "./link";
-export type HistoryEntry={id: string, data: site|link}; \ No newline at end of file
+export type HistoryEntry={id: string, data: Site|link}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/model/link.ts b/sdnr/wt/odlux/apps/networkMapApp/src/model/link.ts
index e11be1a68..d992c66db 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/model/link.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/model/link.ts
@@ -23,8 +23,8 @@ export type link = {id: string,
type: string,
siteA: string,
siteB: string,
- azimuthA: number,
- azimuthB: number,
- locationA: { lon: number, lat: number, amsl?:number, antennaHeight?: number },
- locationB: { lon: number, lat: number, amsl?:number, antennaHeight?: number },
+ azimuthA: number | null,
+ azimuthB: number | null,
+ locationA: { lon: number, lat: number, amsl:number | null, antennaHeight: number | null },
+ locationB: { lon: number, lat: number, amsl:number | null, antennaHeight: number | null },
}; \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/model/popupElements.ts b/sdnr/wt/odlux/apps/networkMapApp/src/model/popupElements.ts
new file mode 100644
index 000000000..320d7ca6e
--- /dev/null
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/model/popupElements.ts
@@ -0,0 +1,22 @@
+/**
+ * ============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==========================================================================
+ */
+
+export type PopupElement = {
+ name: string,
+ id: string
+} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/model/site.ts b/sdnr/wt/odlux/apps/networkMapApp/src/model/site.ts
index 79af65377..b9102e871 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/model/site.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/model/site.ts
@@ -18,26 +18,32 @@
import { link } from "./link";
-export type site = {
+export type Site = {
id: string,
name: string,
- address?: string,
- heighAGLInMeters?: number, //AboveGroundLevel
- antennaHeightAGLInMeters?: number,
+ address: Address,
+ heightAmslInMeters?: number, //AboveGroundLevel
+ antennaHeightAmslInMeters?: number,
type?: string,
operator: string,
- geoLocation:{lon: number, lat: number},
+ location:{lon: number, lat: number},
devices: Device[],
links: link[]
}
-export type Device = {
- id: string,
- type: string,
- name: string,
- manufacture: string,
- owner: string,
- status?: string,
- port: number[],
- simulatorId?: string,
+export type Address={
+ streetAndNr: string,
+ city: string,
+ zipCode: string | null,
+ country: string
+}
+
+export class Device {
+ id: string;
+ type: string;
+ name: string;
+ manufacturer: string;
+ owner: string;
+ status?: string;
+ port: number[];
} \ No newline at end of file
diff --git a/sdnr/wt/odlux/apps/networkMapApp/src/utils/utils.ts b/sdnr/wt/odlux/apps/networkMapApp/src/utils/utils.ts
index 20c4e5aad..59085d499 100644
--- a/sdnr/wt/odlux/apps/networkMapApp/src/utils/utils.ts
+++ b/sdnr/wt/odlux/apps/networkMapApp/src/utils/utils.ts
@@ -17,9 +17,9 @@
*/
import { link } from "../model/link";
-import { site } from "../model/site";
+import { Site } from "../model/site";
-export function isSite(data: link | site): data is site {
- return (data as site).geoLocation !== undefined;
+export function isSite(data: link | Site): data is Site {
+ return (data as Site).location !== undefined;
} \ No newline at end of file