diff options
Diffstat (limited to 'sdnr/wt')
24 files changed, 294 insertions, 188 deletions
diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts b/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts index 012e457e0..608367072 100644 --- a/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts +++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts @@ -45,8 +45,8 @@ export type ILinkCalculationAppStateState= { Lon2: number, rainVal : number, rainAtt : number, - siteA: any, - siteB: any, + siteA: string, + siteB: string, reachable: boolean, polarization : string | null, amslA: number, diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx index 7c54ed185..c498379b7 100644 --- a/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx +++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx @@ -56,7 +56,7 @@ const mapProps = (state: IApplicationStoreState) => ({ month : state.linkCalculation.calculations.month }); -const BASE_URL="/topology/services" +const BASE_URL="/topology/linkcalculator" const mapDispatch = (dispatcher: IDispatcher) => ({ @@ -107,17 +107,14 @@ const mapDispatch = (dispatcher: IDispatcher) => ({ UpdateWorstMonthRain : (month:string) => { dispatcher.dispatch (new UpdateWorstMonthRainAction(month)) } - - }); - - type linkCalculationProps = Connect<typeof mapProps, typeof mapDispatch>; interface initialState { rainMethodDisplay: boolean, + absorptionMethod : string; horizontalBoxChecked: boolean, latitude1Error: string, longitude1Error:string @@ -125,6 +122,7 @@ interface initialState { longitude2Error:string, frequencyError: string, rainMethodError: string, + attenuationMethodError : string, worstmonth : boolean, showWM : string @@ -137,19 +135,21 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState this.state = { rainMethodDisplay: false, horizontalBoxChecked: true, + absorptionMethod : '0', latitude1Error: '', longitude1Error:'', latitude2Error: '', longitude2Error:'', frequencyError: '', rainMethodError: '', + attenuationMethodError : '', worstmonth : false, showWM: '' }; } updateAutoDistance = async (lat1: number, lon1: number, lat2: number, lon2: number)=>{ - const result = await fetch(BASE_URL+'/calculations/distance/' + lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2) + const result = await fetch(BASE_URL+'/distance/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2) const json = await result.json() return json.distanceInKm } @@ -176,7 +176,7 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState const d = Math.floor(absoluteValue); const m = Math.floor((absoluteValue - d) * 60); const s = (absoluteValue - d - m / 60) * 3600; - const dms = `${d}° ${m}' ${s.toFixed(2)}"` + const dms = `${d}° ${m}' ${s.toFixed(2)}"`; const sign = Math.sign(value); @@ -187,44 +187,44 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState } } - rainAttCal = (lat1: any, lon1: any, lat2: any, lon2: any, frequency: any, distance: number, polarization : any, worstmonth:boolean) => { + rainAttCal = (lat1: any, lon1: any, lat2: any, lon2: any, frequency: any, distance: number, polarization : string, worstmonth:boolean) => { if(!worstmonth){ - fetch(BASE_URL+'/calculations/rain/Annual/' + lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2 + '/' + frequency+ '/'+ distance + '/' + polarization) + fetch(BASE_URL+'/rain/annual/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + frequency+ '/'+ distance + '/' + polarization.toUpperCase()) .then(res => res.json()) - .then(result => { this.props.UpdateRainAtt(result.RainAtt) ; this.props.updateRainValue(result.rainfall) }) + .then(result => { this.props.UpdateRainAtt(result.rainAttenuation) ; this.props.updateRainValue(result.rainFall.rainrate)}) } else { - fetch(BASE_URL+'/calculations/rain/WM/' + lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2 + '/' + frequency+ '/'+ distance + '/' + polarization) + fetch(BASE_URL+'/rain/worstmonth/' + lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + frequency+ '/'+ distance + '/' + polarization.toUpperCase()) .then(res => res.json()) - .then(result => { this.props.UpdateRainAtt(result.RainAtt) ; this.props.updateRainValue(result.rainfallWM); this.props.UpdateWorstMonthRain (result.month); this.setState({showWM: '- Wm is : '})}) + .then(result => { this.props.UpdateRainAtt(result.rainAttenuation) ; this.props.updateRainValue(result.rainFall.rainrate); this.props.UpdateWorstMonthRain (result.rainFall.period); this.setState({showWM: '- Wm is : '})}) } } - manualRain = (rainfall: number, frequency: number, distance:number, polarization : any) => { - fetch(BASE_URL+'/calculations/rain/' + rainfall + '/' + frequency + '/' + distance+ '/' + polarization) + manualRain = (rainfall: number, frequency: number, distance:number, polarization : string) => { + fetch(BASE_URL+'/rain/' + rainfall + '/' + frequency + '/' + distance+ '/' + polarization.toUpperCase()) .then(res => res.json()) - .then(result => { this.props.specificRain(result.RainAtt) }) + .then(result => { this.props.specificRain(result.rainAttenuation) }) } FSL = (distance:number, frequency:number) => { - fetch(BASE_URL+'/calculations/FSL/' + distance + '/' + frequency) + fetch(BASE_URL+'/fsl/' + distance + '/' + frequency) .then(res=>res.json()) - .then (result => {this.props.FSL(result.free)}) + .then (result => {this.props.FSL(result.fspl)}) } - AbsorptionAtt =(lat1: number, lon1: number, lat2: number, lon2: number, distance:number, frequency:number, worstmonth:boolean) => { + AbsorptionAtt =(lat1: number, lon1: number, lat2: number, lon2: number, distance:number, frequency:number, worstmonth:boolean, absorptionMethod : string) => { if(!worstmonth) { - fetch(BASE_URL+'/calculations/absorption/Annual/' +lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2 + '/' + distance + '/' + frequency) + fetch(BASE_URL+'/absorption/annual/' +lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + distance + '/' + frequency + '/' +absorptionMethod) .then(res=>res.json()) - .then (result => {this.props.UpdateAbsorption(result.OxLoss, result.WaterLoss)}) + .then (result => {this.props.UpdateAbsorption(result.oxygenLoss, result.waterLoss)}) } else { - fetch(BASE_URL+'/calculations/absorption/WM/' +lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2 + '/' + distance + '/' + frequency) + fetch(BASE_URL+'/absorption/annual/' +lat1 + ',' + lon1 + ',' + lat2 + ',' + lon2 + '/' + distance + '/' + frequency + '/' +absorptionMethod) .then(res=>res.json()) - .then (result => {this.props.UpdateAbsorption(result.OxLoss, result.WaterLoss)}) + .then (result => {this.props.UpdateAbsorption(result.oxygenLoss, result.waterLoss)}) } } @@ -236,11 +236,12 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState this.props.lon2 === 0 ? this.setState({longitude2Error: 'Enter a number between -180 to 180' }) : null this.props.frequency === 0 ? this.setState({frequencyError: 'Select a frequency' }) : this.setState({frequencyError: ''}) - this.state.rainMethodError === null && this.props.rainVal === 0 ? this.setState({rainMethodError: 'Select the rain method'}) : this.setState({rainMethodError: ''}) - - console.log(this.props.lat1 !== 0 && this.props.lat2 !== 0 && this.props.lon1 !== 0 && this.props.lon2 !==0 && this.props.frequency!==0); + this.state.rainMethodDisplay === null && this.props.rainVal === 0 ? this.setState({rainMethodError: 'Select the rain method'}) : this.setState({rainMethodError: ''}) + this.state.absorptionMethod === '0' ? this.setState({attenuationMethodError: 'Select the attenuation method'}) : this.setState({attenuationMethodError: ''}) + console.log(this.state); + console.log(this.props.lat1 !== 0 && this.props.lat2 !== 0 && this.props.lon1 !== 0 && this.props.lon2 !==0 && this.props.frequency!==0 && this.state.rainMethodError==='' && this.state.attenuationMethodError=== ''); - return this.props.lat1 !== 0 && this.props.lat2 !== 0 && this.props.lon1 !== 0 && this.props.lon2 !==0 && this.props.frequency!==0 + return this.props.lat1 !== 0 && this.props.lat2 !== 0 && this.props.lon1 !== 0 && this.props.lon2 !==0 && this.props.frequency!==0 && this.state.rainMethodError==='' && this.state.attenuationMethodError=== ''; } @@ -256,33 +257,33 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState if (this.state.worstmonth===false) { this.setState({showWM : ' '}) this.props.UpdateWorstMonthRain('') - this.AbsorptionAtt (this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.distance, this.props.frequency, this.state.worstmonth) + this.AbsorptionAtt (this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.distance, this.props.frequency, this.state.worstmonth, this.state.absorptionMethod) if (this.state.rainMethodDisplay === true){ - this.manualRain(this.props.rainVal, this.props.frequency, this.props.distance, this.props.polarization); + this.manualRain(this.props.rainVal, this.props.frequency, this.props.distance, this.props.polarization!); } else { // this.updateRainValue(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.state.worstmonth) - this.rainAttCal(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.frequency, this.props.distance, this.props.polarization, this.state.worstmonth); + this.rainAttCal(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.frequency, this.props.distance, this.props.polarization!, this.state.worstmonth); } } else { - this.AbsorptionAtt (this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.distance, this.props.frequency, this.state.worstmonth) + this.AbsorptionAtt (this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.distance, this.props.frequency, this.state.worstmonth, this.state.absorptionMethod) // this.updateRainValue(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.state.worstmonth) - this.rainAttCal(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.frequency, this.props.distance, this.props.polarization, this.state.worstmonth); + this.rainAttCal(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.frequency, this.props.distance, this.props.polarization!, this.state.worstmonth); } } - else null + else console.log('form is not valid') } componentDidMount = () => { - fetch (BASE_URL+'/calculations/fsl/0/0') - .then(res => {if (res.ok) {this.props.reachable===false && this.props.UpdateConectivity(true)}else {this.props.reachable===true && this.props.UpdateConectivity(false)} }) - .catch (res => {this.props.reachable===true && this.props.UpdateConectivity(false)} ) + fetch (BASE_URL+'/fsl/1/1') + .then(res => {if (res.ok) { this.props.UpdateConectivity(true)}else {this.props.UpdateConectivity(false)} }) + .catch (res => {this.props.UpdateConectivity(false)} ) } handleChange =(e:any) => { @@ -346,7 +347,7 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState <div className='column1'> <div> </div> - <div >Site Name</div> + {(this.props.siteA.length>0 || this.props.siteB.length>0) && <div >Site Name</div>} <div>Latitude</div> <div>Longitude</div> <div>Azimuth</div> @@ -359,6 +360,7 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState <div style={{marginTop:10}}>Rain Model</div> <div style={{marginTop:20}}>Rainfall Rate</div> <div>Rain Loss</div> + <div style={{marginTop:18}}>Absorption Model</div> <div>Oxygen Specific Attenuation</div> <div>Water Vapor Specific Attenuation</div> </div> @@ -366,7 +368,7 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState <div className='middlecolumn'> <div >Site A</div> - <div> {this.props.siteA }</div> + {this.props.siteA.length>0 &&<div> {this.props.siteA }</div>} <div> {this.props.lat1 && this.LatLonToDMS(this.props.lat1)}</div> <div>{this.props.lon1 && this.LatLonToDMS(this.props.lon1)}</div> <div>0</div> @@ -375,11 +377,11 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState <div className='column2'> - <div>{this.props.distance.toFixed(3)} km</div> + <div>{this.props.distance?.toFixed(3)} km</div> <div>{<form><input type='checkbox' id='Horizontal' value ="Horizontal" checked= {this.props.polarization==='Horizontal'} onClick= {(e: any) => this.props.updatePolarization(e.target.value)}></input>Horizontal <input style={{marginLeft:10}} type='checkbox' id='Vertical' value ="Vertical" checked= {this.props.polarization==='Vertical'} onClick= {(e:any)=>{this.props.updatePolarization(e.target.value)}}></input>Vertical</form>}</div> - <div> {<select className={this.state.frequencyError.length>0 ? 'error' : 'input'} onChange={(e) => {this.props.updateFrequency(Number(e.target.value)); e.target.value==='0'? this.setState({frequencyError: 'select a frequency'}): this.setState({frequencyError:''})}}> + <div> {<select className={this.state.frequencyError.length>0 ? 'error' : 'input'} onChange={(e) => { this.props.updateFrequency(Number(e.target.value)); e.target.value==='0'? this.setState({frequencyError: 'select a frequency'}): this.setState({frequencyError:''})}}> <option value='0' >Select Freq</option> <option value='7' >7 GHz</option> @@ -391,20 +393,28 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState <option value='38' >38 GHz</option> <option value='42' >42 GHz</option> <option value='80' >80 GHz</option> - </select>} <div style={{fontSize:12, color:'red'}}> {this.state.frequencyError} </div> </div> + </select>} <div style={{fontSize:12, color:'red'}}> {this.state.frequencyError} </div> </div> <div>{this.props.fsl.toFixed(3)} dB</div> - <div> {<select className={this.state.rainMethodError.length>0 ? 'error' : 'input'} onChange = {(e) => {e.target.value === 'itu' ? this.setState({ rainMethodDisplay: false}):this.setState({ rainMethodDisplay: true}); e.target.value===''? this.setState({rainMethodError: 'select a Rain model'}): this.setState({rainMethodError:''}) }}> - <option value='' >Select Rain Method</option> + <div> {<select className={this.state.rainMethodError.length>0 ? 'error' : 'input'} onChange = {(e) => {e.target.value === 'itu' ? this.setState({ rainMethodDisplay: false}):this.setState({ rainMethodDisplay: true}); e.target.value==='0'? this.setState({rainMethodError: 'select a Rain model'}): this.setState({rainMethodError:''}) }}> + <option value='0' >Select Rain Method</option> <option value='itu' >ITU-R P.837-7</option> - <option value='manual' >Specific Rain</option> + <option value='manual' >Specific Rain</option> </select>} <div style={{fontSize:12,color:'red'}}>{this.state.rainMethodError}</div> </div> <div> {<form><input type="number" style={{ width: 70, height: 15, fontSize: 14 }} onChange={(e) => { this.props.updateRainValue(Number(e.target.value)) }} value={this.props.rainVal} disabled={this.state.rainMethodDisplay === false ? true : false}> </input> mm/hr {this.state.showWM} {this.props.month}</form> } </div> <div>{this.props.rainAtt.toFixed(3)} dB</div> + + <div> {<select className={this.state.attenuationMethodError.length>0 ? 'error' : 'input'} onChange = {(e) => { if (e.target.value!== ''){ this.setState({absorptionMethod : e.target.value}); this.setState({attenuationMethodError:''}) }}}> + <option value='0' >Select Absorption Method</option> + <option value='ITURP67612' >ITU-R P.676-12</option> + <option value='ITURP67611' >ITU-R P.676-11</option> + <option value='ITURP67610' >ITU-R P.676-10</option> + </select>} <div style={{fontSize:12,color:'red'}}>{this.state.attenuationMethodError}</div> + </div> <div>{this.props.absorptionOxygen.toFixed(3)} dB</div> <div>{this.props.absorptionWater.toFixed(3)} dB</div> <div>{<button style={{color: '#222', fontFamily:'Arial', boxAlign: 'center', display:'inline-block', insetInlineStart: '20' , alignSelf:'center' }} @@ -415,7 +425,7 @@ class LinkCalculation extends React.Component<linkCalculationProps, initialState </div> <div className= 'middlecolumn'> <div >Site B</div> - <div> {this.props.siteB}</div> + {this.props.siteB.length>0 &&<div> {this.props.siteB}</div>} <div> {this.props.lat2 && this.LatLonToDMS(this.props.lat2)}</div> <div>{this.props.lon2 && this.LatLonToDMS(this.props.lon2)}</div> <div>0</div> diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/webpack.config.js b/sdnr/wt/odlux/apps/linkCalculationApp/webpack.config.js index 3c9093c4b..515c5826b 100644 --- a/sdnr/wt/odlux/apps/linkCalculationApp/webpack.config.js +++ b/sdnr/wt/odlux/apps/linkCalculationApp/webpack.config.js @@ -141,27 +141,27 @@ module.exports = (env) => { }, proxy: { "/oauth2/": { - target: "http://10.20.6.29:8181", + target: "http://sdnr:8181", secure: false }, "/database/": { - target: "http://10.20.6.29:8181", + target: "http://sdnr:8181", secure: false }, - "/restconf/": { - target: "http://10.20.6.29:8181", + "/rests/": { + target: "http://sdnr:8181", secure: false }, "/topology/": { - target: "http://localhost:3001", + target: "http://localhost:3002", secure: false }, "/help/": { - target: "http://10.20.6.29:8181", + target: "http://sdnr:8181", secure: false }, "/websocket/": { - target: "http://10.20.6.29:8181", + target: "http://sdnr:8181", ws: true, changeOrigin: true, secure: false 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 diff --git a/sdnr/wt/odlux/apps/networkMapApp/webpack.config.js b/sdnr/wt/odlux/apps/networkMapApp/webpack.config.js index 7e51f695e..e0f16d0e7 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/webpack.config.js +++ b/sdnr/wt/odlux/apps/networkMapApp/webpack.config.js @@ -137,27 +137,27 @@ module.exports = (env) => { }, proxy: { "/yang-schema/": { - target: "http://10.20.6.29:8181", + target: "http://sdnr:8181", secure: false }, "/oauth2/": { - target: "http://10.20.6.29:8181", + target: "http://sdnr:8181", secure: false }, "/database/": { - target: "http://10.20.6.29:8181", + target: "http://sdnr:8181", secure: false }, "/restconf/": { - target: "http://10.20.6.29:8181", + target: "http://sdnr:8181", secure: false }, "/rests/": { - target: "http://10.20.6.29:8181", + target: "http://sdnr:8181", secure: false }, "/topology/": { - target: "http://localhost:3001", + target: "http://localhost:3002", secure: false }, "/tiles/": { @@ -165,11 +165,11 @@ module.exports = (env) => { secure: false }, "/help/": { - target: "http://10.20.6.29:8181", + target: "http://sdnr:8181", secure: false }, "/websocket": { - target: "http://10.20.6.29:8181", + target: "http://sdnr:8181", ws: true, changeOrigin: true, secure: false diff --git a/sdnr/wt/odlux/framework/pom.xml b/sdnr/wt/odlux/framework/pom.xml index 23854b55a..a60c0af94 100644 --- a/sdnr/wt/odlux/framework/pom.xml +++ b/sdnr/wt/odlux/framework/pom.xml @@ -46,7 +46,7 @@ <properties> <buildtime>${maven.build.timestamp}</buildtime> <distversion>ONAP Frankfurt (Neon, mdsal ${odl.mdsal.version})</distversion> - <buildno>89.977e4de(21/02/10)</buildno> + <buildno>90.49cc396(21/02/17)</buildno> <odlux.version>ONAP SDN-R | ONF Wireless for ${distversion} - Build: ${buildtime} ${buildno} ${project.version}</odlux.version> </properties> diff --git a/sdnr/wt/odlux/odlux.properties b/sdnr/wt/odlux/odlux.properties index 11bffd45b..e4d7fdc01 100644 --- a/sdnr/wt/odlux/odlux.properties +++ b/sdnr/wt/odlux/odlux.properties @@ -1,12 +1,12 @@ -odlux.framework.buildno=89.977e4de(21/02/10) +odlux.framework.buildno=90.49cc396(21/02/17) odlux.apps.configurationApp.buildno=89.977e4de(21/02/10) odlux.apps.connectApp.buildno=89.977e4de(21/02/10) odlux.apps.eventLogApp.buildno=81.1c38886(20/12/04) odlux.apps.faultApp.buildno=81.1c38886(20/12/04) odlux.apps.helpApp.buildno=81.1c38886(20/12/04) odlux.apps.inventoryApp.buildno=89.977e4de(21/02/10) -odlux.apps.linkCalculationApp.buildno=81.1c38886(20/12/04) +odlux.apps.linkCalculationApp.buildno=90.49cc396(21/02/17) odlux.apps.maintenanceApp.buildno=81.1c38886(20/12/04) odlux.apps.mediatorApp.buildno=81.1c38886(20/12/04) -odlux.apps.networkMapApp.buildno=81.1c38886(20/12/04) +odlux.apps.networkMapApp.buildno=90.49cc396(21/02/17) odlux.apps.permanceHistoryApp.buildno=81.1c38886(20/12/04) |