Update NetworkMap and LinkCalculator
[ccsdk/features.git] / sdnr / wt / odlux / apps / networkMapApp / src / components / details / siteDetails.tsx
index 92643d0..3aa35c3 100644 (file)
@@ -23,25 +23,33 @@ 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);
 
     const handleResize = () =>{
-        //console.log("resize")
         const el = document.getElementById('site-details-panel')?.getBoundingClientRect();
         const el2 = document.getElementById('site-tabs')?.getBoundingClientRect();
 
@@ -60,49 +68,79 @@ 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 }}>
         <h2 >{props.site.name}</h2>
         {
             props.site.operator !== '' && props.site.operator !== null ?
-                <TextField aria-label="operator" disabled={true} value={props.site.operator} label="Operator" /> :
-                <TextField aria-label="operator" disabled={true} value="Unkown" label="Operator" style={{ marginTop: "5px" }} />
+                <TextField inputProps={{ 'aria-label': 'operator' }} disabled={true} value={props.site.operator} label="Operator" /> :
+                <TextField inputProps={{ 'aria-label': 'operator' }} disabled={true} value="Unkown" label="Operator" style={{ marginTop: "5px" }} />
         }
         {
             props.site.type !== undefined && props.site.type.length > 0 &&
-            <TextField aria-label="type" disabled={true} value={props.site.type} label="Type" style={{ marginTop: "5px" }} />
+            <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 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 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 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 aria-label="latitude" style={{ marginTop: "5px" }} disabled={true} value={LatLonToDMS(props.site.geoLocation.lat)} label="Latitude" />
-        <TextField 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">
@@ -120,13 +158,8 @@ const SiteDetails: React.FunctionComponent<props> = (props) => {
                
                 {
                     props.site.links.length > 0 &&
-                    <DenseTable ariaLabel="available-links-table-entry" 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>
+                }
 
             </>
 
@@ -135,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 ariaLabel="available-nodes-table-entry" 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