diff options
31 files changed, 531 insertions, 319 deletions
diff --git a/sdnr/northbound/ranSlice/model/src/main/yang/ran-network@2020-08-06.yang b/sdnr/northbound/ranSlice/model/src/main/yang/ran-network@2020-08-06.yang index 506565930..db859f40f 100644 --- a/sdnr/northbound/ranSlice/model/src/main/yang/ran-network@2020-08-06.yang +++ b/sdnr/northbound/ranSlice/model/src/main/yang/ran-network@2020-08-06.yang @@ -612,7 +612,7 @@ module ran-network { leaf-list nfType { type NfType; config false; - min-elements 1; + // min-elements 1; description "Type of the Network Function"; } @@ -714,13 +714,13 @@ module ran-network { "TS 28.622"; leaf host { type inet:host; - mandatory true; + // mandatory true; description "TODO"; } leaf port { type inet:port-number; - mandatory true; + // mandatory true; description "TODO"; } @@ -733,13 +733,13 @@ module ran-network { "TS 23.658"; leaf mcc { type Mcc; - mandatory true; + // mandatory true; description "TODO"; } leaf mnc { type Mnc; - mandatory true; + // mandatory true; description "TODO"; } @@ -867,7 +867,7 @@ module ran-network { leaf-list managedElementTypeList { type string; config false; - min-elements 1; + // min-elements 1; description "The type of functionality provided by the ManagedElement. It may represent one ME functionality or a combination of @@ -971,12 +971,12 @@ module ran-network { grouping SliceProfile{ leaf sliceProfileId{ type string; - mandatory true; + // mandatory true; description "slice profile id"; } leaf sNSSAI{ type SNssai; - mandatory false; + // mandatory false; description "The S-NSSAI may include both the SST and SD fields (in which case the S-NSSAI length is 32 bits in total), or the S-NSSAI may just include the SST field (in which case the S-NSSAI length is 8 bits only)"; } leaf maxNumberofUEs{ @@ -1180,7 +1180,7 @@ module ran-network { } list pLMNInfoList { key "mcc mnc"; - min-elements 1; + // min-elements 1; description "The PLMNInfoList is a list of PLMNInfo data type. It defines which PLMNs that can be served by the NR cell, and which S-NSSAIs that can be supported by the NR cell for @@ -1315,7 +1315,7 @@ module ran-network { } leaf-list nRSectorCarrierRef { type DistinguishedName; - min-elements 1; + // min-elements 1; description "Reference to corresponding NRSectorCarrier instance."; } @@ -1482,14 +1482,15 @@ module ran-network { "'gNB-CU-UP ID' in subclause 9.3.1.15 of 3GPP TS 38.463"; } leaf gNBId { - type int32 { - range "22..32"; + type int64 { + range "0..4294967295"; } mandatory false; description - "Indicates the number of bits for encoding the gNB Id."; + "Identifies a gNB within a PLMN. The gNB Identifier (gNB ID) + is part of the NR Cell Identifier (NCI) of the gNB cells."; reference - "gNB Id in 3GPP TS 38.300, Global gNB ID in 3GPP TS 38.413"; + "gNB ID in 3GPP TS 38.300, Global gNB ID in 3GPP TS 38.413"; } list pLMNInfoList { key "mcc mnc"; @@ -1559,8 +1560,8 @@ module ran-network { } list pLMNId { key "mcc mnc"; - min-elements 1; - max-elements 1; + // min-elements 1; + // max-elements 1; description "The PLMN identifier to be used as part of the global RAN node identity."; @@ -1614,7 +1615,7 @@ module ran-network { } list pLMNInfoList { key "mcc mnc"; - min-elements 1; + // min-elements 1; description "The PLMNInfoList is a list of PLMNInfo data type. It defines which PLMNs that can be served by the NR cell, and which S-NSSAIs that can be supported by the @@ -1990,8 +1991,8 @@ module ran-network { } list sAP { key "host port"; - min-elements 1; - max-elements 1; + // min-elements 1; + // max-elements 1; description "The service access point of the managed NF service instance"; uses SAP; diff --git a/sdnr/wt/odlux/apps/apiDemo/package.json b/sdnr/wt/odlux/apps/apiDemo/package.json index 8118f92c4..230e86aea 100644 --- a/sdnr/wt/odlux/apps/apiDemo/package.json +++ b/sdnr/wt/odlux/apps/apiDemo/package.json @@ -27,8 +27,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/configurationApp/package.json b/sdnr/wt/odlux/apps/configurationApp/package.json index 7b9dce688..d1ab86da7 100644 --- a/sdnr/wt/odlux/apps/configurationApp/package.json +++ b/sdnr/wt/odlux/apps/configurationApp/package.json @@ -27,8 +27,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx index 1cec754ab..278605144 100644 --- a/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx +++ b/sdnr/wt/odlux/apps/configurationApp/src/components/uiElementSelection.tsx @@ -50,7 +50,7 @@ export const UiElementSelection = (props: selectionProps) => { }} > {element.options.map(option => ( - <MenuItem key={option.key} title={option.description} value={option.key}>{option.key}</MenuItem> + <MenuItem key={option.key} title={option.description || ''} value={option.key}>{option.key}</MenuItem> ))} </Select> <FormHelperText>{error}</FormHelperText> diff --git a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx index 7b927785d..3b1df6f87 100644 --- a/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx +++ b/sdnr/wt/odlux/apps/configurationApp/src/views/configurationApplication.tsx @@ -397,7 +397,7 @@ class ConfigurationApplicationComponent extends React.Component<ConfigurationApp Object.keys(uiElement.cases).map(caseKey => { const caseElm = uiElement.cases[caseKey]; return ( - <MenuItem key={caseElm.id} value={caseKey}><Tooltip title={caseElm.description}><div style={{width:"100%"}}>{caseElm.label}</div></Tooltip></MenuItem> + <MenuItem key={caseElm.id} value={caseKey}><Tooltip title={caseElm.description || ''}><div style={{width:"100%"}}>{caseElm.label}</div></Tooltip></MenuItem> ); }) } diff --git a/sdnr/wt/odlux/apps/connectApp/package.json b/sdnr/wt/odlux/apps/connectApp/package.json index 1efd282c4..836af66ee 100644 --- a/sdnr/wt/odlux/apps/connectApp/package.json +++ b/sdnr/wt/odlux/apps/connectApp/package.json @@ -27,8 +27,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/demoApp/package.json b/sdnr/wt/odlux/apps/demoApp/package.json index f30a922fe..9505cfbb0 100644 --- a/sdnr/wt/odlux/apps/demoApp/package.json +++ b/sdnr/wt/odlux/apps/demoApp/package.json @@ -27,8 +27,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/eventLogApp/package.json b/sdnr/wt/odlux/apps/eventLogApp/package.json index f182374cf..4e98a1756 100644 --- a/sdnr/wt/odlux/apps/eventLogApp/package.json +++ b/sdnr/wt/odlux/apps/eventLogApp/package.json @@ -27,8 +27,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/faultApp/package.json b/sdnr/wt/odlux/apps/faultApp/package.json index c42d28986..70952530c 100644 --- a/sdnr/wt/odlux/apps/faultApp/package.json +++ b/sdnr/wt/odlux/apps/faultApp/package.json @@ -27,8 +27,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts b/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts index fea500dd3..cdcbf64d2 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts +++ b/sdnr/wt/odlux/apps/faultApp/src/actions/clearStuckAlarmsAction.ts @@ -29,8 +29,8 @@ export class AreStuckAlarmsCleared extends FaultApplicationBaseAction { export const clearStuckAlarmAsyncAction = (dispatch: Dispatch) => async (nodeNames: string[]) => { - dispatch(new AreStuckAlarmsCleared(true)) + dispatch(new AreStuckAlarmsCleared(true)); const result = await clearStuckAlarms(nodeNames).catch(error => { console.error(error); return undefined }); - dispatch(new AreStuckAlarmsCleared(false)) + dispatch(new AreStuckAlarmsCleared(false)); return result; }
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx b/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx index e131fa619..5155d2690 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx +++ b/sdnr/wt/odlux/apps/faultApp/src/components/clearStuckAlarmsDialog.tsx @@ -66,8 +66,8 @@ class ClearStuckAlarmsDialogComponent extends React.Component<clearStuckAlarmsPr event.preventDefault(); const result = await this.props.clearStuckAlarmsAsync(this.props.stuckAlarms); - if (result && result["data-provider:output"].nodenames && result["data-provider:output"].nodenames.length !== this.props.stuckAlarms.length) { //show errormessage if not all devices were cleared - const undeletedAlarm = this.props.stuckAlarms.filter(item => !result["data-provider:output"].nodenames.includes(item)); + if (result && result["devicemanager:output"].nodenames && result["devicemanager:output"].nodenames.length !== this.props.stuckAlarms.length) { //show errormessage if not all devices were cleared + const undeletedAlarm = this.props.stuckAlarms.filter(item => !result["devicemanager:output"].nodenames.includes(item)); const error = "The alarms of the following devices couldn't be refreshed: "; this.setState({ clearAlarmsSuccessful: false, errormessage: error, unclearedAlarms: undeletedAlarm }); return; diff --git a/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts b/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts index d1236d2e7..663def086 100644 --- a/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts +++ b/sdnr/wt/odlux/apps/faultApp/src/services/faultStatusService.ts @@ -47,7 +47,7 @@ export const getFaultStateFromDatabase = async (): Promise<FaultType | null> => export const clearStuckAlarms = async (nodeNames: string[]) => { const path = 'rests/operations/devicemanager:clear-current-fault-by-nodename' - const result = await requestRest<SingeResult<DeletedStuckAlarms>>(path, { method: 'Post', body: JSON.stringify({ input: { nodenames: nodeNames } }) }) + const result = await requestRest<any>(path, { method: 'Post', body: JSON.stringify({ input: { nodenames: nodeNames } }) }) return result; }
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/helpApp/package.json b/sdnr/wt/odlux/apps/helpApp/package.json index 1f516cec4..0a7593dcc 100644 --- a/sdnr/wt/odlux/apps/helpApp/package.json +++ b/sdnr/wt/odlux/apps/helpApp/package.json @@ -32,8 +32,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/inventoryApp/package.json b/sdnr/wt/odlux/apps/inventoryApp/package.json index 4b1f3f9f9..1e11f78d0 100644 --- a/sdnr/wt/odlux/apps/inventoryApp/package.json +++ b/sdnr/wt/odlux/apps/inventoryApp/package.json @@ -27,8 +27,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/package.json b/sdnr/wt/odlux/apps/linkCalculationApp/package.json index 40e1be913..22b2a6c0a 100644 --- a/sdnr/wt/odlux/apps/linkCalculationApp/package.json +++ b/sdnr/wt/odlux/apps/linkCalculationApp/package.json @@ -21,14 +21,16 @@ "author": "Mohammad Boroon", "license": "Apache-2.0", "dependencies": { - "@odlux/framework": "*" + "@odlux/framework": "*", + "formik": "^2.1.5", + "yup": "^0.29.3" }, "peerDependencies": { "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", @@ -36,5 +38,12 @@ "react": "16.12.0", "react-dom": "16.12.0", "react-router-dom": "4.3.1" + }, + "devDependencies": { + "@types/yup": "^0.29.7", + "node-sass": "^4.14.1", + "sass": "^1.26.11", + "sass-loader": "^10.0.2", + "webpack": "^4.44.2" } -}
\ No newline at end of file +} diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts b/sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts index 09887f27f..e7427e4cc 100644 --- a/sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts +++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/actions/commonLinkCalculationActions.ts @@ -101,4 +101,18 @@ export class updateAltitudeAction extends Action{ super(); } } +export class UpdateAbsorptionLossAction extends Action{ + constructor( + public absorptionOxygen:number, + public absorptionWater:number, + + ){ + super(); + } +} +export class UpdateWorstMonthRainAction extends Action{ + constructor(public month: string){ + super(); + } +} diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/components/connectionInfo.tsx b/sdnr/wt/odlux/apps/linkCalculationApp/src/components/connectionInfo.tsx index cae6fbd9e..e6d82e236 100644 --- a/sdnr/wt/odlux/apps/linkCalculationApp/src/components/connectionInfo.tsx +++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/components/connectionInfo.tsx @@ -36,6 +36,7 @@ const ConnectionInfo: React.FunctionComponent<props> = (props) => { {props.isCalculationServerReachable === false && <Typography> Calculation data can't be loaded.</Typography>} </div> </Paper> : null + )} const mapStateToProps = (state: IApplicationStoreState) => ({ diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts b/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts index 85c013572..012e457e0 100644 --- a/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts +++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/handlers/linkCalculationAppRootHandler.ts @@ -21,7 +21,7 @@ import { combineActionHandler } from '../../../../framework/src/flux/middleware' // ** do not remove ** import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; import { IActionHandler } from '../../../../framework/src/flux/action';; -import { UpdateLinkIdAction, UpdateFrequencyAction , UpdateLatLonAction, UpdateRainAttAction, UpdateRainValAction, updateHideForm, UpdateFslCalculation, UpdateSiteAction, UpdateDistanceAction, isCalculationServerReachableAction, UpdatePolAction, updateAltitudeAction} from '../actions/commonLinkCalculationActions'; +import { UpdateLinkIdAction, UpdateFrequencyAction , UpdateLatLonAction, UpdateRainAttAction, UpdateRainValAction, updateHideForm, UpdateFslCalculation, UpdateSiteAction, UpdateDistanceAction, isCalculationServerReachableAction, UpdatePolAction, updateAltitudeAction, UpdateAbsorptionLossAction, UpdateWorstMonthRainAction} from '../actions/commonLinkCalculationActions'; declare module '../../../../framework/src/store/applicationStore' { interface IApplicationStoreState { @@ -52,7 +52,10 @@ export type ILinkCalculationAppStateState= { amslA: number, amslB:number, aglA: number, - aglB:number + aglB:number, + absorptionWater:number, + absorptionOxygen: number, + month: string } const initialState: ILinkCalculationAppStateState ={ @@ -74,7 +77,10 @@ const initialState: ILinkCalculationAppStateState ={ amslA: 0, amslB:0, aglA: 0, - aglB:0 + aglB:0, + absorptionWater:0, + absorptionOxygen: 0, + month: '' } @@ -93,7 +99,7 @@ export const LinkCalculationHandler: IActionHandler<ILinkCalculationAppStateStat } else if (action instanceof UpdateFrequencyAction){ state = Object.assign({}, state, {frequency:action.frequency}) -} + } else if (action instanceof UpdateFslCalculation){ state = Object.assign({}, state, {fsl:action.fsl}) } @@ -114,9 +120,16 @@ export const LinkCalculationHandler: IActionHandler<ILinkCalculationAppStateStat } else if (action instanceof UpdatePolAction){ state = Object.assign({}, state, {polarization: action.polarization}) - }else if (action instanceof updateAltitudeAction){ + } + else if (action instanceof updateAltitudeAction){ state = Object.assign({}, state, {amslA:action.amslA, amslB:action.amslA, aglA:action.aglA, aglB:action.aglB}) } + else if (action instanceof UpdateAbsorptionLossAction){ + state = Object.assign({}, state, {absorptionOxygen:action.absorptionOxygen, absorptionWater:action.absorptionWater}) + } + else if (action instanceof UpdateWorstMonthRainAction){ + state = Object.assign({}, state, {month:action.month}) + } return state } diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/index.html b/sdnr/wt/odlux/apps/linkCalculationApp/src/index.html index c1cb3f9f3..2023ae365 100644 --- a/sdnr/wt/odlux/apps/linkCalculationApp/src/index.html +++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/index.html @@ -15,7 +15,7 @@ <script type="text/javascript" src="./config.js"></script> <script> // run the application - require(["app","connectApp", "networkMapApp", "linkCalculationApp"], function (app, connectApp, networkMapApp, linkCalculationApp) { + require(["app","connectApp", "linkCalculationApp", "networkMapApp"], function (app, connectApp, linkCalculationApp,networkMapApp) { connectApp.register(); linkCalculationApp.register(); networkMapApp.register(); diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/views/Style.scss b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/Style.scss new file mode 100644 index 000000000..35a9b9702 --- /dev/null +++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/Style.scss @@ -0,0 +1,73 @@ +.parent{ + + display: flex; + justify-content: space-evenly; + margin: auto; + + +} +.input { + width: 150px; + box-sizing: border-box; + // margin-bottom: 5px; + +} +.error { + border: 1px solid red; + width: 150px; + box-sizing: border-box; +} + + +.container-1 { + height: 50vh; + width: 80%; + justify-content: center; + align-items: baseline;; + display: flex; + flex-direction: row; + align-content: space-between; + padding: 20px 40px; + border-radius: 10px; + // box-shadow: 0px 10px 50px #555; + background-color: #ffffff; + // padding-top: 10px; + +} + + .column1 { + flex-direction: column; + width: 30%; + align-items: flex-end;; + // padding: 2em; + + } + .column1 div { + margin-top: 10px; + // align-items: space-between; + // flex-wrap: wrap; + border-bottom-style: solid; + border-bottom-width: thin; + border-color: silver; + } + .middlecolumn{ + + flex-direction: column; + flex-grow: 1; + // padding: 10px 10px; + } + + .middlecolumn div{ + margin-top: 10px; + border-bottom-style: solid; + border-bottom-width: thin; + border-color: silver; + } + + .column2 { + margin-left: 200px; + } + .column2 div{ + margin-top: 10px; + + }
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx index 9cbc771f4..7c54ed185 100644 --- a/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx +++ b/sdnr/wt/odlux/apps/linkCalculationApp/src/views/linkCalculationComponent.tsx @@ -21,12 +21,15 @@ import * as React from "react"; import { Connect, connect, IDispatcher } from '../../../../framework/src/flux/connect'; import { MaterialTable, MaterialTableCtorType } from '../../../../framework/src/components/material-table'; import { TextField, Tabs, Tab, Typography, AppBar, Button, Tooltip, Checkbox, Table, TableCell, TableHead, TableRow, TableBody, Paper } from '@material-ui/core'; -import DenseTable from '../components/denseTable' +import './Style.scss' import { IApplicationStoreState } from "../../../../framework/src/store/applicationStore"; -import { UpdateFrequencyAction, UpdateLatLonAction, UpdateRainAttAction, UpdateRainValAction, UpdateFslCalculation, isCalculationServerReachableAction, UpdatePolAction, UpdateDistanceAction, updateAltitudeAction } from "../actions/commonLinkCalculationActions"; -import { faPlaneArrival } from "@fortawesome/free-solid-svg-icons"; +import { UpdateFrequencyAction, UpdateLatLonAction, UpdateRainAttAction, UpdateRainValAction, UpdateFslCalculation, isCalculationServerReachableAction, UpdatePolAction, UpdateDistanceAction, updateAltitudeAction, UpdateAbsorptionLossAction, UpdateWorstMonthRainAction } from "../actions/commonLinkCalculationActions"; +import { faPlaneArrival, faAlignCenter } from "@fortawesome/free-solid-svg-icons"; import ConnectionInfo from '../components/connectionInfo' +import { red } from "@material-ui/core/colors"; + + const mapProps = (state: IApplicationStoreState) => ({ linkId: state.linkCalculation.calculations.linkId, @@ -47,7 +50,10 @@ const mapProps = (state: IApplicationStoreState) => ({ amslA:state.linkCalculation.calculations.amslA, amslB:state.linkCalculation.calculations.amslB, aglA:state.linkCalculation.calculations.aglA, - aglB:state.linkCalculation.calculations.aglB + aglB:state.linkCalculation.calculations.aglB, + absorptionOxygen : state.linkCalculation.calculations.absorptionOxygen, + absorptionWater : state.linkCalculation.calculations.absorptionWater, + month : state.linkCalculation.calculations.month }); const BASE_URL="/topology/services" @@ -89,38 +95,80 @@ const mapDispatch = (dispatcher: IDispatcher) => ({ updateAutoDistance : (distance:number)=>{ dispatcher.dispatch (new UpdateDistanceAction(distance)) - } + }, + + UpdateAbsorption : (OxLoss:number , WaterLoss:number) => { + dispatcher.dispatch (new UpdateAbsorptionLossAction (OxLoss, WaterLoss)) + }, + // UpdateWorstMonth : (worstmonth:boolean) => { + // dispatcher.dispatch (new UpdateWorstMonthAction(worstmonth)) + // }, + + UpdateWorstMonthRain : (month:string) => { + dispatcher.dispatch (new UpdateWorstMonthRainAction(month)) + } + + }); + + + type linkCalculationProps = Connect<typeof mapProps, typeof mapDispatch>; -class LinkCalculation extends React.Component<linkCalculationProps, {rainMethodDisplay: boolean, horizontalBoxChecked: boolean}> { +interface initialState { + rainMethodDisplay: boolean, + horizontalBoxChecked: boolean, + latitude1Error: string, + longitude1Error:string + latitude2Error: string, + longitude2Error:string, + frequencyError: string, + rainMethodError: string, + worstmonth : boolean, + showWM : string + + +} + +class LinkCalculation extends React.Component<linkCalculationProps, initialState> { constructor(props: any) { - super(props) - this.state = { rainMethodDisplay: false, - horizontalBoxChecked: true - } - } + super(props); + this.state = { + rainMethodDisplay: false, + horizontalBoxChecked: true, + latitude1Error: '', + longitude1Error:'', + latitude2Error: '', + longitude2Error:'', + frequencyError: '', + rainMethodError: '', + 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 json = await result.json() return json.distanceInKm } - updateLatLon = (e: any) => { + updateLatLon = (e:any) => { - if (e.target.id == 'Lat1') this.props.updateLatLon(e.target.value, this.props.lon1, this.props.lat2, this.props.lon2) - if (e.target.id == 'Lon1') this.props.updateLatLon(this.props.lat1, e.target.value, this.props.lat2, this.props.lon2) - if (e.target.id == 'Lat2') this.props.updateLatLon(this.props.lat1, this.props.lon1, e.target.value, this.props.lon2) - if (e.target.id == 'Lon2') this.props.updateLatLon(this.props.lat1, this.props.lon1, this.props.lat2, e.target.value) + e.target.id== 'Lat1'? this.props.updateLatLon(e.target.value, this.props.lon1, this.props.lat2, this.props.lon2) : null + e.target.id== 'Lon1'? this.props.updateLatLon(this.props.lat1, e.target.value, this.props.lat2, this.props.lon2) : null + e.target.id== 'Lat2'? this.props.updateLatLon(this.props.lat1, this.props.lon1, e.target.value, this.props.lon2) : null + e.target.id== 'Lon2'? this.props.updateLatLon(this.props.lat1, e.target.value, this.props.lat2, e.target.value) : null + } updatePoli = (val: string) =>{ this.setState({horizontalBoxChecked: !this.state.horizontalBoxChecked}); this.props.updatePolarization(val); - //this.forceUpdate(); + } LatLonToDMS = (value: number, isLon: boolean = false) => { @@ -139,10 +187,17 @@ class LinkCalculation extends React.Component<linkCalculationProps, {rainMethodD } } - rainAttCal = (lat1: any, lon1: any, lat2: any, lon2: any, frequency: any, distance: number, polarization : any) => { - fetch(BASE_URL+'/calculations/rain/' + lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2 + '/' + frequency+ '/'+ distance + '/' + polarization) + rainAttCal = (lat1: any, lon1: any, lat2: any, lon2: any, frequency: any, distance: number, polarization : any, worstmonth:boolean) => { + if(!worstmonth){ + fetch(BASE_URL+'/calculations/rain/Annual/' + lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2 + '/' + frequency+ '/'+ distance + '/' + polarization) .then(res => res.json()) - .then(result => { this.props.UpdateRainAtt(result.RainAtt) }) + .then(result => { this.props.UpdateRainAtt(result.RainAtt) ; this.props.updateRainValue(result.rainfall) }) + } + else { + fetch(BASE_URL+'/calculations/rain/WM/' + lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2 + '/' + frequency+ '/'+ distance + '/' + polarization) + .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 : '})}) + } } @@ -152,33 +207,75 @@ class LinkCalculation extends React.Component<linkCalculationProps, {rainMethodD .then(result => { this.props.specificRain(result.RainAtt) }) } - updateRainValue = (lat1: any, lon1: any, lat2: any, lon2: any) => { - fetch(BASE_URL+'/calculations/rainval/' + lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2) - .then(res => res.json()) - .then(result => {this.props.updateRainValue(result.rainFall) }) - } FSL = (distance:number, frequency:number) => { fetch(BASE_URL+'/calculations/FSL/' + distance + '/' + frequency) .then(res=>res.json()) .then (result => {this.props.FSL(result.free)}) } + + AbsorptionAtt =(lat1: number, lon1: number, lat2: number, lon2: number, distance:number, frequency:number, worstmonth:boolean) => { + if(!worstmonth) + { + fetch(BASE_URL+'/calculations/absorption/Annual/' +lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2 + '/' + distance + '/' + frequency) + .then(res=>res.json()) + .then (result => {this.props.UpdateAbsorption(result.OxLoss, result.WaterLoss)}) + } + else { + fetch(BASE_URL+'/calculations/absorption/WM/' +lat1 + '/' + lon1 + '/' + lat2 + '/' + lon2 + '/' + distance + '/' + frequency) + .then(res=>res.json()) + .then (result => {this.props.UpdateAbsorption(result.OxLoss, result.WaterLoss)}) + } + } - + formValid = () => { + + this.props.lat1 === 0 ? this.setState({latitude1Error: 'Enter a number between -90 to 90'}) : null + this.props.lat2 === 0 ? this.setState({latitude2Error: 'Enter a number between -90 to 90'}) : null + this.props.lon1 === 0 ? this.setState({longitude1Error: 'Enter a number between -180 to 180' }) : null + 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); + + return this.props.lat1 !== 0 && this.props.lat2 !== 0 && this.props.lon1 !== 0 && this.props.lon2 !==0 && this.props.frequency!==0 + + } + + buttonHandler = async () => { - this.props.updateAutoDistance(await this.updateAutoDistance(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2)) + + if (this.formValid()) { + this.props.updateAutoDistance(await this.updateAutoDistance(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2)) this.FSL(this.props.distance, this.props.frequency) - if (this.state.rainMethodDisplay === true){ + 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.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.rainAttCal(this.props.lat1, this.props.lon1, this.props.lat2, this.props.lon2, this.props.frequency, this.props.distance, this.props.polarization); + if (this.state.rainMethodDisplay === true){ + + 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); + } + } + 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.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); } + } + else null } @@ -189,177 +286,157 @@ class LinkCalculation extends React.Component<linkCalculationProps, {rainMethodD } handleChange =(e:any) => { - this.props.updatePolarization(e.target.value) + + switch (e.target.id){ + case 'Lat1' : if ( e.target.value >90 || e.target.value<-90 ) + { this.setState({latitude1Error: 'Enter a number between -90 to 90'})} + else {this.updateLatLon(e) + this.setState({latitude1Error: ''}) } + break; + case 'Lat2' : if ( e.target.value >90 || e.target.value<-90 ) + { this.setState({latitude2Error: 'Enter a number between -90 to 90'})} + else {this.updateLatLon(e) + this.setState({latitude2Error: ''}) } + break; + case 'Lon1' : if ( e.target.value >180 || e.target.value<-180 ) + { this.setState({longitude1Error: 'Enter a number between -180 to 180'})} + else {this.updateLatLon(e) + this.setState({longitude1Error: ''}) } + break; + case 'Lon2' : if ( e.target.value >180 || e.target.value<-180 ) + { this.setState({longitude2Error: 'Enter a number between -180 to 180'})} + else {this.updateLatLon(e) + this.setState({longitude2Error: ''}) } + break; + + } } - // AbsorptionAttW = () => { - // fetch(BASE_URL+'/calculations/FSL/' + distance + '/' + frequency) - // .then(res=>res.json()) - // .then (result => {this.props.FSL(result.free)}) - // } + render() { + return ( + + <div > + + {!this.props.formView && + + <div className = 'parent'> + + <div >Site A + <form > + <label>Latitude: <input className={this.state.latitude1Error.length>0 ? 'error' : 'input'} id='Lat1' type='number' onChange={(e: any) => {this.handleChange(e)} }/></label> + <div style={{fontSize:12, color:'red'}}> {this.state.latitude1Error} </div></form> + <form><label>Longitude: <input className={this.state.longitude1Error.length>0 ? 'error' : 'input'} id='Lon1' type='number' onChange={(e: any) => this.handleChange(e) } /></label><div style={{fontSize:12, color:'red'}}> {this.state.longitude1Error} </div> + </form> + </div> + + <div>Site B + <form> + <label>Latitude: <input className={this.state.latitude2Error.length>0 ? 'error' : 'input'} id='Lat2' type='number' onChange={(e: any) => {this.handleChange(e) }} /></label><div style={{fontSize:12, color:'red'}}> {this.state.latitude2Error} </div></form> + <form><label>Longitude: <input className={this.state.longitude2Error.length>0 ? 'error' : 'input'} id='Lon2' type='number' onChange={(e: any) => {this.handleChange(e) } }/></label><div style={{fontSize:12, color:'red'}}> {this.state.longitude2Error} </div></form> + </div> + + </div> + } - // AbsorptionAttOx =() => { - // fetch(BASE_URL+'/calculations/FSL/' + distance + '/' + frequency) - // .then(res=>res.json()) - // .then (result => {this.props.FSL(result.free)}) - // } + <div className='container-1'> + <div>{<form><input type='checkbox' id='Annual' value ="Annual" checked= {this.state.worstmonth===false} onClick= {(e: any) => this.setState ({worstmonth: false})}></input>Annual + <input style={{marginLeft:10}} type='checkbox' id='Worst Month' value ="Worst" checked= {this.state.worstmonth===true} onClick= {(e:any)=>this.setState ({worstmonth: true})}></input>WM</form>}</div> + + + <div className='column1'> + <div> </div> + <div >Site Name</div> + <div>Latitude</div> + <div>Longitude</div> + <div>Azimuth</div> + <div>Average Mean Sea Level</div> + <div>Antenna Height Above Ground</div> + <div>Distance</div> + <div style={{marginTop:20}}>Polarization</div> + <div style={{marginTop:20}}>Frequency</div> + <div>Free Space Loss</div> + <div style={{marginTop:10}}>Rain Model</div> + <div style={{marginTop:20}}>Rainfall Rate</div> + <div>Rain Loss</div> + <div>Oxygen Specific Attenuation</div> + <div>Water Vapor Specific Attenuation</div> + </div> + - render() { - - return <div style={{position: 'relative'}}> + <div className='middlecolumn'> + <div >Site A</div> + <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> + <div>{this.props.amslA.toFixed(2)} m</div> + <div>{this.props.aglA.toFixed(2)} m</div> + - {!this.props.formView && <form> - <div> + <div className='column2'> + <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> - <br />Site A - <br /> Site Id: - <label style={{ marginInlineStart: 20 }}> latitude - <input id='Lat1' type='number' onChange={(e: any) => this.updateLatLon(e)} /> - </label> - <label style={{ marginInlineStart: 20 }}>longitude - <input id='Lon1' type='number' onChange={(e: any) => this.updateLatLon(e)} /> - </label><br /><br /> + <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> + <option value='11' >11 GHz</option> + <option value='15' >15 GHz</option> + <option value='23' >23 GHz</option> + <option value='26' >26 GHz</option> + <option value='28' >28 GHz</option> + <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> + + <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> + <option value='itu' >ITU-R P.837-7</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>{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' }} + onClick = {(e) => this.buttonHandler()} >Calculate</button>} </div> + </div> - <div> <br />Site B<br /> Site Id: - <label style={{ marginInlineStart: 20 }}> latitude - <input id='Lat2' type='number' onChange={(e: any) => this.updateLatLon(e)} /> - </label> - <label style={{ marginInlineStart: 20 }}>longitude - <input id='Lon2' type='number' onChange={(e: any) => this.updateLatLon(e)} /> - </label> - <br /> </div> - </form> - } + <div className= 'middlecolumn'> + <div >Site B</div> + <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> + <div>{this.props.amslB.toFixed(2)} m</div> + <div>{this.props.aglB.toFixed(2)} m</div> -<Paper style={{borderRadius:"0px"}}> - <div style={{ height:600, overflow:"auto"}}> - <Table stickyHeader size="small" aria-label="a dense table" > - <TableHead> - <TableRow> - <TableCell >{""} </TableCell> - <TableCell >{"Site A"}</TableCell> - <TableCell > {""} </TableCell> - <TableCell >{"Site B"} </TableCell> - </TableRow> - </TableHead> - <TableBody> - <TableRow> - <TableCell >{"Site Name"} </TableCell> - <TableCell >{this.props.siteA}</TableCell> - <TableCell > {""} </TableCell> - <TableCell >{this.props.siteB} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Latitude"} </TableCell> - <TableCell >{this.props.lat1 && this.LatLonToDMS(this.props.lat1)} </TableCell> - <TableCell > {""} </TableCell> - <TableCell >{this.props.lat2 && this.LatLonToDMS(this.props.lat2)} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Longitude"} </TableCell> - <TableCell >{this.props.lon1 && this.LatLonToDMS(this.props.lon1)}</TableCell> - <TableCell > {""} </TableCell> - <TableCell >{this.props.lon2 && this.LatLonToDMS(this.props.lon2)} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Azimuth"} </TableCell> - <TableCell >{""}</TableCell> - <TableCell > {""} </TableCell> - <TableCell >{""} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Average Mean Sea Level"} </TableCell> - <TableCell >{this.props.amslA + ' m'}</TableCell> - <TableCell > {""} </TableCell> - <TableCell >{this.props.amslB+ ' m'} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Antenna Height Above Ground"} </TableCell> - <TableCell >{this.props.aglA+ ' m'}</TableCell> - <TableCell > {""} </TableCell> - <TableCell >{this.props.aglB+ ' m'} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Distance"} </TableCell> - <TableCell >{""}</TableCell> - <TableCell > {this.props.distance.toFixed(3)+ ' km'} </TableCell> - <TableCell >{""} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Polarization"} </TableCell> - <TableCell >{""}</TableCell> - <TableCell > {<form><input type='checkbox' id='Horizontal' value ="Horizontal" checked= {this.props.polarization==='Horizontal'} onClick= {(e: any) => this.props.updatePolarization(e.target.value)}></input>Horizontal<br /> - <input type='checkbox' id='Vertical' value ="Vertical" checked= {this.props.polarization==='Vertical'} onClick= {(e:any)=>{this.props.updatePolarization(e.target.value)}}></input>Vertical</form>} </TableCell> - <TableCell >{""} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Frequency"} </TableCell> - <TableCell >{""}</TableCell> - <TableCell > {<select onChange={(e) => this.props.updateFrequency(Number(e.target.value))}> - <option value='' >Select Freq</option> - <option value='7' >7 GHz</option> - <option value='11' >11 GHz</option> - <option value='15' >15 GHz</option> - <option value='23' >23 GHz</option> - <option value='26' >26 GHz</option> - <option value='28' >28 GHz</option> - <option value='38' >38 GHz</option> - <option value='42' >42 GHz</option> - <option value='80' >80 GHz</option> - </select>} - </TableCell> - <TableCell >{""} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Free Space Loss"} </TableCell> - <TableCell >{""}</TableCell> - <TableCell > {this.props.fsl + ' dB'} </TableCell> - <TableCell >{""} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Rain Model"} </TableCell> - <TableCell >{""}</TableCell> - <TableCell > {<select onChange = {(e) => {e.target.value === 'itu' ? this.setState({ rainMethodDisplay: false}):this.setState({ rainMethodDisplay: true}) }}> - <option >Select Rain Method</option> - <option value='itu' >ITU-R P.837-7</option> - <option value='manual' >Specific Rain</option> - </select>} </TableCell> - <TableCell >{""} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Rainfall Rate"} </TableCell> - <TableCell >{""}</TableCell> - <TableCell > {<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</form> } </TableCell> - <TableCell >{""} </TableCell> - </TableRow> - <TableRow> - <TableCell >{"Rain Loss"} </TableCell> - <TableCell >{""}</TableCell> - <TableCell > {this.props.rainAtt + ' dB'} </TableCell> - <TableCell >{""} </TableCell> - </TableRow> - <TableRow> - <TableCell >{""} </TableCell> - <TableCell >{""}</TableCell> - <TableCell > {<button style={{color: '#222', fontFamily:'Arial', boxAlign: 'center', display:'inline-block', insetInlineStart: '20' }} - onClick = {(e) => this.buttonHandler()} >Calculate</button>} </TableCell> - <TableCell >{""} </TableCell> - </TableRow> - - </TableBody> - </Table> - </div> - </Paper> - <ConnectionInfo /> + + </div> + + + </div> + + + <ConnectionInfo /> + </div> + ) } -} + + } export default connect(mapProps, mapDispatch)(LinkCalculation); diff --git a/sdnr/wt/odlux/apps/linkCalculationApp/webpack.config.js b/sdnr/wt/odlux/apps/linkCalculationApp/webpack.config.js index 4f2bd2ec9..3c9093c4b 100644 --- a/sdnr/wt/odlux/apps/linkCalculationApp/webpack.config.js +++ b/sdnr/wt/odlux/apps/linkCalculationApp/webpack.config.js @@ -49,7 +49,7 @@ module.exports = (env) => { use: [{ loader: "babel-loader" }, { - loader: "ts-loader" + loader: "ts-loader" }] }, { test: /\.jsx?$/, @@ -57,6 +57,20 @@ module.exports = (env) => { use: [{ loader: "babel-loader" }] + },{ + test: /\.scss$/, + include: /node_modules/, + use: ['style-loader', 'css-loader', 'sass-loader'], + },{ + test: /\.s[ac]ss$/i, + use: [ + // Creates `style` nodes from JS strings + 'style-loader', + // Translates CSS into CommonJS + 'css-loader', + // Compiles Sass to CSS + 'sass-loader', + ], }] }, diff --git a/sdnr/wt/odlux/apps/maintenanceApp/package.json b/sdnr/wt/odlux/apps/maintenanceApp/package.json index faaef753c..da5b3d288 100644 --- a/sdnr/wt/odlux/apps/maintenanceApp/package.json +++ b/sdnr/wt/odlux/apps/maintenanceApp/package.json @@ -28,8 +28,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/mediatorApp/package.json b/sdnr/wt/odlux/apps/mediatorApp/package.json index 1f1b7d578..ddce56757 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/package.json +++ b/sdnr/wt/odlux/apps/mediatorApp/package.json @@ -28,8 +28,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/minimumApp/package.json b/sdnr/wt/odlux/apps/minimumApp/package.json index d2b836979..069cb138c 100644 --- a/sdnr/wt/odlux/apps/minimumApp/package.json +++ b/sdnr/wt/odlux/apps/minimumApp/package.json @@ -27,8 +27,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/networkMapApp/package.json b/sdnr/wt/odlux/apps/networkMapApp/package.json index 0f05ffb6c..b1150c37c 100644 --- a/sdnr/wt/odlux/apps/networkMapApp/package.json +++ b/sdnr/wt/odlux/apps/networkMapApp/package.json @@ -30,8 +30,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/apps/performanceHistoryApp/package.json b/sdnr/wt/odlux/apps/performanceHistoryApp/package.json index 1a6415fbc..2b69cc3c7 100644 --- a/sdnr/wt/odlux/apps/performanceHistoryApp/package.json +++ b/sdnr/wt/odlux/apps/performanceHistoryApp/package.json @@ -30,8 +30,8 @@ "@types/react": "16.9.19", "@types/react-dom": "16.9.5", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", diff --git a/sdnr/wt/odlux/framework/package.json b/sdnr/wt/odlux/framework/package.json index 511b97778..3ecd34c23 100644 --- a/sdnr/wt/odlux/framework/package.json +++ b/sdnr/wt/odlux/framework/package.json @@ -28,8 +28,8 @@ "@types/react": "16.9.19",
"@types/react-dom": "16.9.5",
"@types/react-router-dom": "4.3.1",
- "@material-ui/core": "4.9.0",
- "@material-ui/icons": "4.5.1",
+ "@material-ui/core": "4.11.0",
+ "@material-ui/icons": "4.9.1",
"@types/classnames": "2.2.6",
"@types/flux": "3.1.8",
"@types/jquery": "3.3.10",
diff --git a/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx b/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx index a4080b51b..59dc49c50 100644 --- a/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx +++ b/sdnr/wt/odlux/framework/src/components/material-table/tableToolbar.tsx @@ -108,7 +108,7 @@ class TableToolbarComponent extends React.Component<ITableToolbarComponentProps, <div className={classes.actions}> {this.props.customActionButtons ? this.props.customActionButtons.map((action, ind) => ( - <Tooltip key={`custom-action-${ind}`} title={action.tooltip}> + <Tooltip key={`custom-action-${ind}`} title={action.tooltip || ''}> <IconButton aria-label={buttonPrefix + `custom-action-${ind}`} onClick={() => action.onClick()}> <action.icon /> </IconButton> diff --git a/sdnr/wt/odlux/package.json b/sdnr/wt/odlux/package.json index 4eaf5fc26..c5004ca72 100644 --- a/sdnr/wt/odlux/package.json +++ b/sdnr/wt/odlux/package.json @@ -14,8 +14,8 @@ "@fortawesome/fontawesome-svg-core": "1.2.12", "@fortawesome/free-solid-svg-icons": "5.6.3", "@fortawesome/react-fontawesome": "0.1.3", - "@material-ui/core": "4.9.0", - "@material-ui/icons": "4.5.1", + "@material-ui/core": "4.11.0", + "@material-ui/icons": "4.9.1", "@material-ui/lab": "4.0.0-alpha.41", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", diff --git a/sdnr/wt/odlux/yarn.lock b/sdnr/wt/odlux/yarn.lock index 9f1065b28..efb31777a 100644 --- a/sdnr/wt/odlux/yarn.lock +++ b/sdnr/wt/odlux/yarn.lock @@ -671,10 +671,10 @@ lodash "^4.17.13" to-fast-properties "^2.0.0" -"@emotion/hash@^0.7.4": - version "0.7.4" - resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.7.4.tgz#f14932887422c9056b15a8d222a9074a7dfa2831" - integrity sha512-fxfMSBMX3tlIbKUdtGKxqB1fyrH6gVrX39Gsv3y8lRYKUqlgDt3UMqQyGnR1bQMa2B8aGnhLZokZgg8vT0Le+A== +"@emotion/hash@^0.8.0": + version "0.8.0" + resolved "https://registry.yarnpkg.com/@emotion/hash/-/hash-0.8.0.tgz#bbbff68978fefdbe68ccb533bc8cbe1d1afb5413" + integrity sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow== "@fimbul/bifrost@^0.21.0": version "0.21.0" @@ -1392,30 +1392,28 @@ resolved "https://registry.yarnpkg.com/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz#497c67a1cef50d1a2459ba60f315e448d2ad87fe" integrity sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q== -"@material-ui/core@4.9.0": - version "4.9.0" - resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.9.0.tgz#96ca3281ee06216d44fd4d0e306dbe0429eb2ebe" - integrity sha512-zrrr8mPU5DDBYaVil4uJYauW41PjSn5otn7cqGsmWOY0t90fypr9nNgM7rRJaPz2AP6oRSDx1kBQt2igf5uelg== +"@material-ui/core@4.11.0": + version "4.11.0" + resolved "https://registry.yarnpkg.com/@material-ui/core/-/core-4.11.0.tgz#b69b26e4553c9e53f2bfaf1053e216a0af9be15a" + integrity sha512-bYo9uIub8wGhZySHqLQ833zi4ZML+XCBE1XwJ8EuUVSpTWWG57Pm+YugQToJNFsEyiKFhPh8DPD0bgupz8n01g== dependencies: "@babel/runtime" "^7.4.4" - "@material-ui/styles" "^4.9.0" - "@material-ui/system" "^4.7.1" - "@material-ui/types" "^5.0.0" - "@material-ui/utils" "^4.7.1" + "@material-ui/styles" "^4.10.0" + "@material-ui/system" "^4.9.14" + "@material-ui/types" "^5.1.0" + "@material-ui/utils" "^4.10.2" "@types/react-transition-group" "^4.2.0" - clsx "^1.0.2" - convert-css-length "^2.0.1" - hoist-non-react-statics "^3.2.1" - normalize-scroll-left "^0.2.0" - popper.js "^1.14.1" + clsx "^1.0.4" + hoist-non-react-statics "^3.3.2" + popper.js "1.16.1-lts" prop-types "^15.7.2" react-is "^16.8.0" - react-transition-group "^4.3.0" + react-transition-group "^4.4.0" -"@material-ui/icons@4.5.1": - version "4.5.1" - resolved "https://registry.yarnpkg.com/@material-ui/icons/-/icons-4.5.1.tgz#6963bad139e938702ece85ca43067688018f04f8" - integrity sha512-YZ/BgJbXX4a0gOuKWb30mBaHaoXRqPanlePam83JQPZ/y4kl+3aW0Wv9tlR70hB5EGAkEJGW5m4ktJwMgxQAeA== +"@material-ui/icons@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@material-ui/icons/-/icons-4.9.1.tgz#fdeadf8cb3d89208945b33dbc50c7c616d0bd665" + integrity sha512-GBitL3oBWO0hzBhvA9KxqcowRUsA0qzwKkURyC8nppnC3fw54KPKZ+d4V1Eeg/UnDRSzDaI9nGCdel/eh9AQMg== dependencies: "@babel/runtime" "^7.4.4" @@ -1430,18 +1428,18 @@ prop-types "^15.7.2" react-is "^16.8.0" -"@material-ui/styles@^4.9.0": - version "4.9.0" - resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.9.0.tgz#10c31859f6868cfa9d3adf6b6c3e32c9d676bc76" - integrity sha512-nJHum4RqYBPWsjL/9JET8Z02FZ9gSizlg/7LWVFpIthNzpK6OQ5OSRR4T4x9/p+wK3t1qNn3b1uI4XpnZaPxOA== +"@material-ui/styles@^4.10.0": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@material-ui/styles/-/styles-4.10.0.tgz#2406dc23aa358217aa8cc772e6237bd7f0544071" + integrity sha512-XPwiVTpd3rlnbfrgtEJ1eJJdFCXZkHxy8TrdieaTvwxNYj42VnnCyFzxYeNW9Lhj4V1oD8YtQ6S5Gie7bZDf7Q== dependencies: "@babel/runtime" "^7.4.4" - "@emotion/hash" "^0.7.4" - "@material-ui/types" "^5.0.0" - "@material-ui/utils" "^4.7.1" - clsx "^1.0.2" + "@emotion/hash" "^0.8.0" + "@material-ui/types" "^5.1.0" + "@material-ui/utils" "^4.9.6" + clsx "^1.0.4" csstype "^2.5.2" - hoist-non-react-statics "^3.2.1" + hoist-non-react-statics "^3.3.2" jss "^10.0.3" jss-plugin-camel-case "^10.0.3" jss-plugin-default-unit "^10.0.3" @@ -1452,19 +1450,29 @@ jss-plugin-vendor-prefixer "^10.0.3" prop-types "^15.7.2" -"@material-ui/system@^4.7.1": - version "4.7.1" - resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.7.1.tgz#d928dacc0eeae6bea569ff3ee079f409efb3517d" - integrity sha512-zH02p+FOimXLSKOW/OT2laYkl9bB3dD1AvnZqsHYoseUaq0aVrpbl2BGjQi+vJ5lg8w73uYlt9zOWzb3+1UdMQ== +"@material-ui/system@^4.9.14": + version "4.9.14" + resolved "https://registry.yarnpkg.com/@material-ui/system/-/system-4.9.14.tgz#4b00c48b569340cefb2036d0596b93ac6c587a5f" + integrity sha512-oQbaqfSnNlEkXEziDcJDDIy8pbvwUmZXWNqlmIwDqr/ZdCK8FuV3f4nxikUh7hvClKV2gnQ9djh5CZFTHkZj3w== dependencies: "@babel/runtime" "^7.4.4" - "@material-ui/utils" "^4.7.1" + "@material-ui/utils" "^4.9.6" + csstype "^2.5.2" prop-types "^15.7.2" -"@material-ui/types@^5.0.0": - version "5.0.0" - resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.0.0.tgz#26d6259dc6b39f4c2e1e9aceff7a11e031941741" - integrity sha512-UeH2BuKkwDndtMSS0qgx1kCzSMw+ydtj0xx/XbFtxNSTlXydKwzs5gVW5ZKsFlAkwoOOQ9TIsyoCC8hq18tOwg== +"@material-ui/types@^5.1.0": + version "5.1.0" + resolved "https://registry.yarnpkg.com/@material-ui/types/-/types-5.1.0.tgz#efa1c7a0b0eaa4c7c87ac0390445f0f88b0d88f2" + integrity sha512-7cqRjrY50b8QzRSYyhSpx4WRw2YuO0KKIGQEVk5J8uoz2BanawykgZGoWEqKm7pVIbzFDN0SpPcVV4IhOFkl8A== + +"@material-ui/utils@^4.10.2", "@material-ui/utils@^4.9.6": + version "4.10.2" + resolved "https://registry.yarnpkg.com/@material-ui/utils/-/utils-4.10.2.tgz#3fd5470ca61b7341f1e0468ac8f29a70bf6df321" + integrity sha512-eg29v74P7W5r6a4tWWDAAfZldXIzfyO1am2fIsC39hdUUHm/33k6pGOKPbgDjg/U/4ifmgAePy/1OjkKN6rFRw== + dependencies: + "@babel/runtime" "^7.4.4" + prop-types "^15.7.2" + react-is "^16.8.0" "@material-ui/utils@^4.7.1": version "4.7.1" @@ -3138,11 +3146,6 @@ clone@^2.1.1, clone@^2.1.2: resolved "https://registry.yarnpkg.com/clone/-/clone-2.1.2.tgz#1b7f4b9f591f1e8f83670401600345a02887435f" integrity sha1-G39Ln1kfHo+DZwQBYANFoCiHQ18= -clsx@^1.0.2: - version "1.0.4" - resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.0.4.tgz#0c0171f6d5cb2fe83848463c15fcc26b4df8c2ec" - integrity sha512-1mQ557MIZTrL/140j+JVdRM6e31/OA4vTYxXgqIIZlndyfjHpyawKZia1Im05Vp9BWmImkcNrNtFYQMyFcgJDg== - clsx@^1.0.4: version "1.1.0" resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.0.tgz#62937c6adfea771247c34b54d320fb99624f5702" @@ -3417,11 +3420,6 @@ conventional-recommended-bump@^4.0.4: meow "^4.0.0" q "^1.5.1" -convert-css-length@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/convert-css-length/-/convert-css-length-2.0.1.tgz#90a76bde5bfd24d72881a5b45d02249b2c1d257c" - integrity sha512-iGpbcvhLPRKUbBc0Quxx7w/bV14AC3ItuBEGMahA5WTYqB8lq9jH0kTXFheCBASsYnqeMFZhiTruNxr1N59Axg== - convert-source-map@^1.1.0, convert-source-map@^1.4.0, convert-source-map@^1.5.1: version "1.7.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.7.0.tgz#17a2cb882d7f77d3490585e2ce6c524424a3a442" @@ -5301,13 +5299,20 @@ hoist-non-react-statics@^2.5.0: resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-2.5.5.tgz#c5903cf409c0dfd908f388e619d86b9c1174cb47" integrity sha512-rqcy4pJo55FTTLWt+bU8ukscqHeE/e9KWvsOW2b/a3afxQZhwkQdT1rPPCJ0rYXdj4vNcasY8zHTH+jF/qStxw== -hoist-non-react-statics@^3.2.1, hoist-non-react-statics@^3.3.0: +hoist-non-react-statics@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.0.tgz#b09178f0122184fb95acf525daaecb4d8f45958b" integrity sha512-0XsbTXxgiaCDYDIWFcwkmerZPSwywfUqYmwT4jzewKTQSWoE6FCMoUVOeBJWK3E/CrWbxRG3m5GzY4lnIwGRBA== dependencies: react-is "^16.7.0" +hoist-non-react-statics@^3.3.2: + version "3.3.2" + resolved "https://registry.yarnpkg.com/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz#ece0acaf71d62c2969c2ec59feff42a4b1a85b45" + integrity sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw== + dependencies: + react-is "^16.7.0" + home-or-tmp@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/home-or-tmp/-/home-or-tmp-2.0.0.tgz#e36c3f2d2cae7d746a857e38d18d5f32a7882db8" @@ -7929,11 +7934,6 @@ normalize-range@^0.1.2: resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942" integrity sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= -normalize-scroll-left@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/normalize-scroll-left/-/normalize-scroll-left-0.2.0.tgz#9445d74275f303cc661e113329aefa492f58114c" - integrity sha512-t5oCENZJl8TGusJKoCJm7+asaSsPuNmK6+iEjrZ5TyBj2f02brCRsd4c83hwtu+e5d4LCSBZ0uoDlMjBo+A8yA== - normalize-url@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-3.3.0.tgz#b2e1c4dc4f7c6d57743df733a4f5978d18650559" @@ -8677,10 +8677,10 @@ pn@^1.1.0: resolved "https://registry.yarnpkg.com/pn/-/pn-1.1.0.tgz#e2f4cef0e219f463c179ab37463e4e1ecdccbafb" integrity sha512-2qHaIQr2VLRFoxe2nASzsV6ef4yOOH+Fi9FBOVH6cqeSgUnoyySPZkxzLuzd+RYOQTRpROA0ztTMqxROKSb/nA== -popper.js@^1.14.1: - version "1.16.0" - resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.0.tgz#2e1816bcbbaa518ea6c2e15a466f4cb9c6e2fbb3" - integrity sha512-+G+EkOPoE5S/zChTpmBSSDYmhXJ5PsW8eMhH8cP/CQHMFPBG/kC9Y5IIw6qNYgdJ+/COf0ddY2li28iHaZRSjw== +popper.js@1.16.1-lts: + version "1.16.1-lts" + resolved "https://registry.yarnpkg.com/popper.js/-/popper.js-1.16.1-lts.tgz#cf6847b807da3799d80ee3d6d2f90df8a3f50b05" + integrity sha512-Kjw8nKRl1m+VrSFCoVGPph93W/qrSO7ZkqPpTf7F4bk/sqcfWK019dWBUpE/fBOsOQY1dks/Bmcbfn1heM/IsA== portfinder@^1.0.13, portfinder@^1.0.9: version "1.0.25" @@ -9107,7 +9107,7 @@ react-router@^4.3.1: prop-types "^15.6.1" warning "^4.0.1" -react-transition-group@4.3.0, react-transition-group@^4.3.0: +react-transition-group@4.3.0: version "4.3.0" resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.3.0.tgz#fea832e386cf8796c58b61874a3319704f5ce683" integrity sha512-1qRV1ZuVSdxPlPf4O8t7inxUGpdyO5zG9IoNfJxSO0ImU2A1YWkEQvFPuIPZmMLkg5hYs7vv5mMOyfgSkvAwvw== @@ -9117,6 +9117,16 @@ react-transition-group@4.3.0, react-transition-group@^4.3.0: loose-envify "^1.4.0" prop-types "^15.6.2" +react-transition-group@^4.4.0: + version "4.4.1" + resolved "https://registry.yarnpkg.com/react-transition-group/-/react-transition-group-4.4.1.tgz#63868f9325a38ea5ee9535d828327f85773345c9" + integrity sha512-Djqr7OQ2aPUiYurhPalTrVy9ddmFCCzwhqQmtN+J3+3DzLO209Fdr70QrN8Z3DsglWql6iY1lDWAfpFiBtuKGw== + dependencies: + "@babel/runtime" "^7.5.5" + dom-helpers "^5.0.1" + loose-envify "^1.4.0" + prop-types "^15.6.2" + react@16.12.0: version "16.12.0" resolved "https://registry.yarnpkg.com/react/-/react-16.12.0.tgz#0c0a9c6a142429e3614834d5a778e18aa78a0b83" |