diff options
Diffstat (limited to 'sdnr/wt/odlux/apps/mediatorApp')
12 files changed, 443 insertions, 142 deletions
diff --git a/sdnr/wt/odlux/apps/mediatorApp/package.json b/sdnr/wt/odlux/apps/mediatorApp/package.json index cf9cb040d..718d2fd03 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/package.json +++ b/sdnr/wt/odlux/apps/mediatorApp/package.json @@ -20,22 +20,22 @@ ], "author": "Matthias Fischer", "license": "Apache-2.0", - "dependencies": { - "@odlux/framework": "*" - }, + "dependencies": { + "@odlux/framework": "*" + }, "peerDependencies": { "@fortawesome/free-solid-svg-icons": "5.6.3", - "@types/react": "16.4.14", - "@types/react-dom": "16.0.8", + "@types/react": "16.9.11", + "@types/react-dom": "16.9.4", "@types/react-router-dom": "4.3.1", - "@material-ui/core": "3.8.3", - "@material-ui/icons": "3.0.2", + "@material-ui/core": "4.6.1", + "@material-ui/icons": "4.5.1", "@types/classnames": "2.2.6", "@types/flux": "3.1.8", "@types/jquery": "3.3.10", "jquery": "3.3.1", - "react": "16.5.2", - "react-dom": "16.5.2", + "react": "16.11.0", + "react-dom": "16.11.0", "react-router-dom": "4.3.1" } }
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/mediatorApp/pom.xml b/sdnr/wt/odlux/apps/mediatorApp/pom.xml index e1ff2d5fc..80fdbf569 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/pom.xml +++ b/sdnr/wt/odlux/apps/mediatorApp/pom.xml @@ -1,5 +1,6 @@ <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.onap.ccsdk.parent</groupId> @@ -8,18 +9,19 @@ <relativePath/> </parent> - <modelVersion>4.0.0</modelVersion> <groupId>org.onap.ccsdk.features.sdnr.wt</groupId> <artifactId>sdnr-wt-odlux-app-mediatorApp</artifactId> <version>0.7.0-SNAPSHOT</version> <packaging>bundle</packaging> - <name>sdnr-wt-odlux-app-mediatorApp</name> + + <name>ccsdk-features :: ${project.artifactId}</name> <licenses> <license> <name>Apache License, Version 2.0</name> <url>http://www.apache.org/licenses/LICENSE-2.0</url> </license> </licenses> + <dependencies> <dependency> <groupId>${project.groupId}</groupId> @@ -38,8 +40,21 @@ <scope>test</scope> </dependency> </dependencies> + <build> <sourceDirectory>src2/main/java</sourceDirectory> + <resources> + <resource> + <directory>dist</directory> + <targetPath>odlux</targetPath> + </resource> + <resource> + <directory>src2/main/resources</directory> + </resource> + <resource> + <directory>src2/test/resources</directory> + </resource> + </resources> <plugins> <plugin> <artifactId>maven-clean-plugin</artifactId> @@ -62,10 +77,10 @@ <followSymlinks>false</followSymlinks> </fileset> <!-- eclipse bug build bin folder in basedir --> - <fileset> - <directory>bin</directory> - <followSymlinks>false</followSymlinks> - </fileset> + <fileset> + <directory>bin</directory> + <followSymlinks>false</followSymlinks> + </fileset> </filesets> </configuration> </plugin> @@ -88,7 +103,7 @@ </executions> </plugin> <plugin> - <groupId>de.jacksitlab</groupId> + <groupId>de.jacks-it-lab</groupId> <artifactId>frontend-maven-plugin</artifactId> <version>1.7.1</version> <executions> @@ -100,8 +115,8 @@ <!-- optional: default phase is "generate-resources" --> <phase>initialize</phase> <configuration> - <nodeVersion>v8.10.0</nodeVersion> - <yarnVersion>v1.12.3</yarnVersion> + <nodeVersion>v10.16.3</nodeVersion> + <yarnVersion>v1.19.0</yarnVersion> </configuration> </execution> <execution> @@ -131,27 +146,5 @@ </configuration> </plugin> </plugins> - <resources> - <resource> - <directory>dist</directory> - <targetPath>odlux</targetPath> - </resource> - <resource> - <directory>src2/main/resources</directory> - </resource> - <resource> - <directory>src2/test/resources</directory> - </resource> - </resources> </build> - <pluginRepositories> - <pluginRepository> - <id>highstreet repo</id> - <url>https://cloud-highstreet-technologies.com/mvn/</url> - <snapshots> - <enabled>true</enabled> - <updatePolicy>always</updatePolicy> - </snapshots> - </pluginRepository> - </pluginRepositories> </project> diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts b/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts index 143dd7d4a..79e46df0e 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts +++ b/sdnr/wt/odlux/apps/mediatorApp/src/actions/mediatorServerActions.ts @@ -73,6 +73,12 @@ export class SetMediatorServerSupportedDevices extends BaseAction { } } +export class SetMediatorServerReachable extends BaseAction { + constructor(public isReachable: boolean) { + super(); + } +} + export const initializeMediatorServerAsyncActionCreator = (serverId: string) => (dispatch: Dispatch) => { dispatch(new SetMediatorServerBusy(true)); mediatorService.getMediatorServerById(serverId).then(mediatorServer => { @@ -82,18 +88,25 @@ export const initializeMediatorServerAsyncActionCreator = (serverId: string) => dispatch(new NavigateToApplication("mediator")); return; } - dispatch(new SetMediatorServerInfo(mediatorServer._id, mediatorServer.name, mediatorServer.url)); - mediatorService.getMediatorServerVersion(mediatorServer._id).then(versionInfo => { - dispatch(new SetMediatorServerVersion(versionInfo)); - }); + dispatch(new SetMediatorServerInfo(mediatorServer.id, mediatorServer.name, mediatorServer.url)); Promise.all([ - mediatorService.getMediatorServerAllConfigs(mediatorServer._id), - mediatorService.getMediatorServerSupportedDevices(mediatorServer._id) - ]).then(([configurations, supportedDevices]) => { + mediatorService.getMediatorServerAllConfigs(mediatorServer.id), + mediatorService.getMediatorServerSupportedDevices(mediatorServer.id), + mediatorService.getMediatorServerVersion(mediatorServer.id) + ]).then(([configurations, supportedDevices, versionInfo]) => { + if (configurations === null && supportedDevices === null && versionInfo === null) { + dispatch(new SetMediatorServerReachable(false)); + } else { + dispatch(new SetMediatorServerReachable(true)); + } dispatch(new SetAllMediatorServerConfigurations(configurations)); dispatch(new SetMediatorServerSupportedDevices(supportedDevices)); + dispatch(new SetMediatorServerVersion(versionInfo)); + dispatch(new SetMediatorServerBusy(false)); + }).catch(error => { + dispatch(new SetMediatorServerReachable(false)); dispatch(new SetMediatorServerBusy(false)); }); }); diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx index 20ece4c22..bcbccccd7 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx +++ b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorConfigDialog.tsx @@ -55,8 +55,8 @@ const styles = (theme: Theme) => createStyles({ }, fab: { position: 'absolute', - bottom: theme.spacing.unit, - right: theme.spacing.unit, + bottom: theme.spacing(1), + right: theme.spacing(1), }, title: { fontSize: 14, @@ -72,7 +72,7 @@ const styles = (theme: Theme) => createStyles({ flexDirection: 'row' }, left: { - marginRight: theme.spacing.unit, + marginRight: theme.spacing(1), }, right: { marginLeft: 0, @@ -160,16 +160,18 @@ type EditMediatorConfigDialogComponentProps = WithStyles<typeof styles> & Connec onClose: () => void; }; -type EditMediatorConfigDialogComponentState = MediatorConfig & { activeTab: number; activeOdlConfig: string }; +type EditMediatorConfigDialogComponentState = MediatorConfig & { activeTab: number; activeOdlConfig: string, forceAddOdlConfig: boolean, isOdlConfigHostnameEmpty: boolean }; class EditMediatorConfigDialogComponent extends React.Component<EditMediatorConfigDialogComponentProps, EditMediatorConfigDialogComponentState> { - constructor (props: EditMediatorConfigDialogComponentProps) { + constructor(props: EditMediatorConfigDialogComponentProps) { super(props); this.state = { ...this.props.mediatorConfig, activeTab: 0, - activeOdlConfig: "" + activeOdlConfig: "", + forceAddOdlConfig: false, + isOdlConfigHostnameEmpty: false }; } @@ -195,7 +197,7 @@ class EditMediatorConfigDialogComponent extends React.Component<EditMediatorConf <DialogContentText> {setting.dialogDescription} </DialogContentText> - <Tabs value={this.state.activeTab} indicatorColor="primary" textColor="primary" onChange={(event, value) => this.setState({ activeTab: value })} > + <Tabs value={this.state.activeTab} indicatorColor="secondary" textColor="secondary" onChange={(event, value) => this.setState({ activeTab: value })} > <Tab label="Config" /> <Tab label="ODL AutoConnect" /> </Tabs> @@ -203,8 +205,8 @@ class EditMediatorConfigDialogComponent extends React.Component<EditMediatorConf <TextField disabled={setting.readonly || setting.readonlyName} spellCheck={false} autoFocus margin="dense" id="name" label="Name" type="text" fullWidth value={this.state.Name} onChange={(event) => { this.setState({ Name: event.target.value }); }} /> <FormControl fullWidth disabled={setting.readonly}> <InputLabel htmlFor="deviceType">Device</InputLabel> - <Select value={this.state.DeviceType} onChange={(event) => { - const device = this.props.supportedDevices.find(device => device.id === +event.target.value); + <Select value={this.state.DeviceType} onChange={(event, value) => { + const device = this.props.supportedDevices.find(device => device.id === event.target.value); if (device) { this.setState({ DeviceType: device.id, @@ -242,11 +244,11 @@ class EditMediatorConfigDialogComponent extends React.Component<EditMediatorConf }} ><DeleteIcon /></IconButton>) return ( <Panel title={cfg.Server && `${cfg.User ? `${cfg.User}@` : ''}${cfg.Protocol}://${cfg.Server}:${cfg.Port}` || "new odl config"} key={panelId} panelId={panelId} activePanel={this.state.activeOdlConfig} customActionButtons={[deleteButton]} - onToggle={(id) => this.setState({ activeOdlConfig: (this.state.activeOdlConfig === id) ? "" : (id || "") })} > + onToggle={(id) => { this.setState({ activeOdlConfig: (this.state.activeOdlConfig === id) ? "" : (id || "") }); console.log("activeOdlConfig " + id); this.hideHostnameErrormessage(id) }} > <div className={classes.alignInOneLine}> <FormControl className={classes.left} margin={"dense"} > <InputLabel htmlFor={`protocol-${ind}`}>Protocoll</InputLabel> - <Select value={cfg.Protocol} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Protocol", e => (e.target.value))} inputProps={{ name: `protocol-${ind}`, id: `protocol-${ind}` }} fullWidth > + <Select value={cfg.Protocol} onChange={(e, v) => this.odlConfigValueChangeHandlerCreator(ind, "Protocol", e => v)} inputProps={{ name: `protocol-${ind}`, id: `protocol-${ind}` }} fullWidth > <MenuItem value={"http"}>http</MenuItem> <MenuItem value={"https"}>https</MenuItem> </Select> @@ -254,6 +256,10 @@ class EditMediatorConfigDialogComponent extends React.Component<EditMediatorConf <TextField className={classes.left} spellCheck={false} margin="dense" id="hostname" label="Hostname" type="text" value={cfg.Server} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Server", e => e.target.value)} /> <TextField className={classes.right} style={{ maxWidth: "65px" }} spellCheck={false} margin="dense" id="port" label="Port" type="number" value={cfg.Port || ""} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Port", e => +e.target.value)} /> </div> + { + this.state.isOdlConfigHostnameEmpty && + <Typography component={"div"} className={classes.left} color="error" gutterBottom>Please add a hostname.</Typography> + } <div className={classes.alignInOneLine}> <TextField className={classes.left} spellCheck={false} margin="dense" id="username" label="Username" type="text" value={cfg.User} onChange={this.odlConfigValueChangeHandlerCreator(ind, "User", e => e.target.value)} /> <TextField className={classes.right} spellCheck={false} margin="dense" id="password" label="Password" type="password" value={cfg.Password} onChange={this.odlConfigValueChangeHandlerCreator(ind, "Password", e => e.target.value)} /> @@ -264,9 +270,15 @@ class EditMediatorConfigDialogComponent extends React.Component<EditMediatorConf </Panel> ); }) - : <div className={classes.center} > - <Typography component={"div"} className={classes.title} color="textSecondary" gutterBottom>Please add an ODL auto connect configuration.</Typography> - </div> + : (this.state.forceAddOdlConfig ? + <div className={classes.center} > + <Typography component={"div"} className={classes.title} color="error" gutterBottom>Please add at least one ODL auto connect configuration.</Typography> + </div> + : + <div className={classes.center} > + <Typography component={"div"} className={classes.title} color="textSecondary" gutterBottom>Please add an ODL auto connect configuration.</Typography> + </div> + ) } <Fab className={classes.fab} color="primary" aria-label="Add" onClick={() => this.setState({ ODLConfig: [...this.state.ODLConfig, { Server: '', Port: 8181, Protocol: 'https', User: 'admin', Password: 'admin', Trustall: false }] @@ -276,25 +288,76 @@ class EditMediatorConfigDialogComponent extends React.Component<EditMediatorConf </DialogContent> <DialogActions> - <Button onClick={(event) => { - this.onApply(Object.keys(this.state).reduce<MediatorConfig & { [kex: string]: any }>((acc, key) => { - // do not copy activeTab and activeOdlConfig - if (key !== "activeTab" && key !== "activeOdlConfig" && key !== "_initialMediatorConfig") acc[key] = (this.state as any)[key]; - return acc; - }, {} as MediatorConfig)); - event.preventDefault(); - event.stopPropagation(); - }} > {setting.applyButtonText} </Button> + <Button onClick={(event) => { this.addConfig(event) }} > {setting.applyButtonText} </Button> <Button onClick={(event) => { this.onCancel(); event.preventDefault(); event.stopPropagation(); + this.resetPanel(); }} color="secondary"> {setting.cancelButtonText} </Button> </DialogActions> </Dialog> ) } + private addConfig = (event: any) => { + event.preventDefault(); + event.stopPropagation(); + + if (this.state.ODLConfig.length === 0) { + this.setState({ activeTab: 1, forceAddOdlConfig: true }); + } + else + if (this.state.ODLConfig.length > 0) { + for (let i = 0; i <= this.state.ODLConfig.length; i++) { + if (this.isHostnameEmpty(i)) { + this.setState({ activeOdlConfig: 'panel-' + i }) + this.setState({ isOdlConfigHostnameEmpty: true }) + return; + } + } + + this.onApply(Object.keys(this.state).reduce<MediatorConfig & { [kex: string]: any }>((acc, key) => { + // do not copy additional state properties + if (key !== "activeTab" && key !== "activeOdlConfig" && key !== "isOdlConfigHostnameEmpty" + && key !== "forceAddOdlConfig" && key !== "_initialMediatorConfig") acc[key] = (this.state as any)[key]; + return acc; + }, {} as MediatorConfig)); + this.resetPanel(); + } + } + + private resetPanel = () => { + this.setState({ forceAddOdlConfig: false, isOdlConfigHostnameEmpty: false, activeTab: 0 }); + } + + + private hideHostnameErrormessage = (panelId: string | null) => { + + if (panelId) { + let id = Number(panelId.split('-')[1]); + if (!this.isHostnameEmpty(id)) { + this.setState({ isOdlConfigHostnameEmpty: false }) + } + } + } + + private isHostnameEmpty = (id: number) => { + + const element = this.state.ODLConfig[id]; + if (element) { + if (!element.Server) { + return true; + } + else { + return false + } + + } else { + return null; + } + } + private onApply = (config: MediatorConfig) => { this.props.onClose && this.props.onClose(); switch (this.props.mode) { diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx index d38fb0b6e..882a6b37e 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx +++ b/sdnr/wt/odlux/apps/mediatorApp/src/components/editMediatorServerDialog.tsx @@ -29,6 +29,7 @@ import { IDispatcher, connect, Connect } from '../../../../framework/src/flux/co import { addAvaliableMediatorServerAsyncActionCreator, removeAvaliableMediatorServerAsyncActionCreator, updateAvaliableMediatorServerAsyncActionCreator } from '../actions/avaliableMediatorServersActions'; import { MediatorServer } from '../models/mediatorServer'; +import { Typography } from '@material-ui/core'; export enum EditMediatorServerDialogMode { None = "none", @@ -94,19 +95,54 @@ type EditMediatorServerDialogComponentProps = Connect<undefined, typeof mapDispa onClose: () => void; }; -type EditMediatorServerDialogComponentState = MediatorServer; +const urlRegex = RegExp("^https?://"); + +type EditMediatorServerDialogComponentState = MediatorServer & { errorMessage: string[] }; class EditMediatorServerDialogComponent extends React.Component<EditMediatorServerDialogComponentProps, EditMediatorServerDialogComponentState> { - constructor (props: EditMediatorServerDialogComponentProps) { + constructor(props: EditMediatorServerDialogComponentProps) { super(props); this.state = { - ...this.props.mediatorServer + ...this.props.mediatorServer, + errorMessage: [] }; } + areFieldsValid = () => { + return this.state.name.trim().length > 0 && this.state.url.trim().length > 0 && urlRegex.test(this.state.url); + } + + createErrorMessages = () => { + + let messages = []; + if (this.state.name.trim().length === 0 && this.state.url.trim().length === 0) { + messages.push("The server name and the url must not be empty.") + } + else + if (this.state.url.trim().length === 0) { + messages.push("The server url must not be empty.") + + } else if (this.state.name.trim().length === 0) { + messages.push("The server name must not be empty.") + } + + if (!urlRegex.test(this.state.url)) { + if (messages.length > 0) { + return messages.concat(["The server url must start with 'http(s)://'."]) + } else { + return ["The server url must start with 'http(s)://'."] + } + } + + return messages; + } + + + render(): JSX.Element { const setting = settings[this.props.mode]; + return ( <Dialog open={this.props.mode !== EditMediatorServerDialogMode.None}> <DialogTitle id="form-dialog-title">{setting.dialogTitle}</DialogTitle> @@ -117,14 +153,25 @@ class EditMediatorServerDialogComponent extends React.Component<EditMediatorServ {/* <TextField disabled spellCheck={false} autoFocus margin="dense" id="id" label="Id" type="text" fullWidth value={ this.state._id } onChange={(event)=>{ this.setState({_id: event.target.value}); } } /> */} <TextField disabled={setting.readonly} spellCheck={false} margin="dense" id="name" label="Name" type="text" fullWidth value={this.state.name} onChange={(event) => { this.setState({ name: event.target.value }); }} /> <TextField disabled={setting.readonly} spellCheck={false} margin="dense" id="url" label="Url" type="text" fullWidth value={this.state.url} onChange={(event) => { this.setState({ url: event.target.value }); }} /> + + <Typography id="errorMessage" component={"div"} color="error">{this.state.errorMessage.map((error, index) => <div key={index}>{error}</div>)}</Typography> + </DialogContent> <DialogActions> <Button onClick={(event) => { - this.onApply({ - _id: this.state._id, - name: this.state.name, - url: this.state.url, - }); + + if (this.areFieldsValid()) { + this.setState({ errorMessage: [] }) + this.onApply({ + id: this.state.id, + name: this.state.name, + url: this.state.url + }); + } else { + const errorMessage = this.createErrorMessages() + this.setState({ errorMessage: errorMessage }) + } + event.preventDefault(); event.stopPropagation(); }} > {setting.applyButtonText} </Button> diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx new file mode 100644 index 000000000..fd8a2496a --- /dev/null +++ b/sdnr/wt/odlux/apps/mediatorApp/src/components/showMeditaorInfoDialog.tsx @@ -0,0 +1,107 @@ +/** + * ============LICENSE_START======================================================================== + * ONAP : ccsdk feature sdnr wt odlux + * ================================================================================================= + * Copyright (C) 2019 highstreet technologies GmbH Intellectual Property. All rights reserved. + * ================================================================================================= + * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except + * in compliance with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software distributed under the License + * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + * or implied. See the License for the specific language governing permissions and limitations under + * the License. + * ============LICENSE_END========================================================================== + */ + +import * as React from 'react' +import { Dialog, DialogTitle, DialogContent, DialogActions, TextField, DialogContentText, Checkbox, Button, FormControlLabel, FormGroup } from '@material-ui/core'; +import { IApplicationState } from '../../../../framework/src/handlers/applicationStateHandler'; +import { IApplicationStoreState } from '../../../../framework/src/store/applicationStore'; +import connect, { Connect } from '../../../../framework/src/flux/connect'; +import { MediatorConfigResponse } from 'models/mediatorServer'; +import { Panel } from '../../../../framework/src/components/material-ui/panel'; + +export enum MediatorInfoDialogMode { + None = "none", + ShowDetails = "showDetails" +} + +const mapProps = (state: IApplicationStoreState) => ({ supportedDevices: state.mediator.mediatorServerState.supportedDevices }) + +type ShowMediatorInfoDialogComponentProps = Connect<typeof mapProps, undefined> & +{ + config: MediatorConfigResponse, + mode: MediatorInfoDialogMode, + onClose: () => void +} + +type ShowMediatorInfoDialogComponentState = { + status: string, + devicetype: string, + activeOdlConfig: string +} + +/* +Displays all values of a mediator server +*/ +class ShowMediatorInfoDialogComponent extends React.Component<ShowMediatorInfoDialogComponentProps, ShowMediatorInfoDialogComponentState> { + + constructor(props: ShowMediatorInfoDialogComponentProps) { + super(props); + if (this.props.config) { + let deviceType = props.supportedDevices.find(element => element.id === this.props.config.DeviceType) + + this.state = { + status: props.config.pid > 0 ? "Running" : "Stopped", + devicetype: deviceType != undefined ? deviceType.device : 'none', + activeOdlConfig: '' + } + } + } + + onClose = (event: React.MouseEvent) => { + event.preventDefault(); + event.stopPropagation(); + this.props.onClose(); + } + + render() { + return ( + <Dialog open={this.props.mode !== MediatorInfoDialogMode.None} onBackdropClick={this.props.onClose} > + <DialogTitle>{this.props.config.Name}</DialogTitle> + <DialogContent> + <TextField disabled margin="dense" id="deviceIp" label="Device IP" fullWidth defaultValue={this.props.config.DeviceIp} /> + <TextField disabled margin="dense" id="deviceport" label="Device Port" fullWidth defaultValue={this.props.config.DevicePort} /> + <TextField disabled margin="dense" id="status" label="Status" fullWidth defaultValue={this.state.status} /> + <TextField disabled margin="dense" id="deviceType" label="Device Type" fullWidth defaultValue={this.state.devicetype} /> + <TextField disabled margin="dense" id="ncPort" label="Netconf Port" fullWidth defaultValue={this.props.config.NcPort} /> + <FormGroup> + <FormControlLabel control={<Checkbox disabled defaultChecked={this.props.config.IsNCConnected}></Checkbox>} label="Netconf Connection" /> + <FormControlLabel control={<Checkbox disabled defaultChecked={this.props.config.IsNeConnected}></Checkbox>} label="Network Element Connection" /> + <FormControlLabel control={<Checkbox disabled defaultChecked={this.props.config.fwactive}></Checkbox>} label="Firewall active" /> + </FormGroup> + { + this.props.config.ODLConfig.map((element, index) => + <Panel title={"ODL config " + (this.props.config.ODLConfig.length > 1 ? index + 1 : '')} key={index} panelId={'panel-' + index} activePanel={this.state.activeOdlConfig} onToggle={(id: string) => { this.setState({ activeOdlConfig: (this.state.activeOdlConfig === id) ? "" : (id || "") }); }}> + <TextField disabled margin="dense" defaultValue={element.Protocol + '://' + element.Server} label="Server" /> + <TextField disabled margin="dense" defaultValue={element.Port} label="Port" /> + <FormControlLabel control={<Checkbox disabled checked={element.Trustall} />} label="Trustall" /> + </Panel> + ) + } + + </DialogContent> + <DialogActions> + <Button onClick={this.onClose}>Close</Button> + </DialogActions> + </Dialog> + ) + } + +} + +export const ShowMediatorInfoDialog = connect(mapProps)(ShowMediatorInfoDialogComponent) +export default ShowMediatorInfoDialog;
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts index 0d137b396..246634cbe 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts +++ b/sdnr/wt/odlux/apps/mediatorApp/src/handlers/mediatorServerHandler.ts @@ -17,7 +17,7 @@ */ import { XmlFileInfo, MediatorConfig, BusySymbol, MediatorConfigResponse, MediatorServerDevice } from "../models/mediatorServer"; import { IActionHandler } from "../../../../framework/src/flux/action"; -import { SetMediatorServerVersion, SetMediatorServerInfo, SetAllMediatorServerConfigurations, SetMediatorServerBusy, SetMediatorServerSupportedDevices } from "../actions/mediatorServerActions"; +import { SetMediatorServerVersion, SetMediatorServerInfo, SetAllMediatorServerConfigurations, SetMediatorServerBusy, SetMediatorServerSupportedDevices, SetMediatorServerReachable } from "../actions/mediatorServerActions"; import { SetMediatorBusyByName, UpdateMediatorConfig, AddMediatorConfig, RemoveMediatorConfig } from "../actions/mediatorConfigActions"; export type MediatorServerState = { @@ -30,6 +30,7 @@ export type MediatorServerState = { nexmls: XmlFileInfo[]; configurations: MediatorConfigResponse[]; supportedDevices: MediatorServerDevice[]; + isReachable: boolean; } const mediatorServerInit: MediatorServerState = { @@ -41,7 +42,8 @@ const mediatorServerInit: MediatorServerState = { mediatorVersion: null, nexmls: [], configurations: [], - supportedDevices: [] + supportedDevices: [], + isReachable: true } export const mediatorServerHandler: IActionHandler<MediatorServerState> = (state = mediatorServerInit, action) => { @@ -111,6 +113,8 @@ export const mediatorServerHandler: IActionHandler<MediatorServerState> = (state ...state.configurations.slice(index + 1) ] }; + } else if( action instanceof SetMediatorServerReachable){ + state = {...state, isReachable: action.isReachable} } return state; }
\ No newline at end of file diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/models/mediatorServer.ts b/sdnr/wt/odlux/apps/mediatorApp/src/models/mediatorServer.ts index a2b54599c..6ab6db8b3 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/src/models/mediatorServer.ts +++ b/sdnr/wt/odlux/apps/mediatorApp/src/models/mediatorServer.ts @@ -16,7 +16,7 @@ * ============LICENSE_END========================================================================== */ export type MediatorServer = { - _id: string; + id: string; name: string; url: string; } diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/services/mediatorService.ts b/sdnr/wt/odlux/apps/mediatorApp/src/services/mediatorService.ts index b257fa92c..aee086689 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/src/services/mediatorService.ts +++ b/sdnr/wt/odlux/apps/mediatorApp/src/services/mediatorService.ts @@ -19,9 +19,9 @@ import * as $ from 'jquery'; import { requestRest, formEncode } from '../../../../framework/src/services/restService'; import { MediatorServer, MediatorServerVersionInfo, MediatorConfig, MediatorServerDevice, MediatorConfigResponse } from '../models/mediatorServer'; -import { HitEntry } from '../../../../framework/src/models'; +import { PostResponse, DeleteResponse, Result } from '../../../../framework/src/models'; -export const mediatorServerResourcePath = "mwtn/mediator-server"; +export const mediatorServerResourcePath = "mediator-server"; type MediatorServerResponse<TData> = { code: number, data: TData }; type IndexableMediatorServer = MediatorServer & { [key: string]: any; }; @@ -33,46 +33,68 @@ class MediatorService { /** * Inserts data into the mediator servers table. */ - public async insertMediatorServer(server: IndexableMediatorServer): Promise<MediatorServer | null> { - const path = `database/${mediatorServerResourcePath}`; - const data = Object.keys(server).reduce((acc, cur) => { - if (cur !== "_id") acc[cur] = server[cur]; - return acc; - }, {} as IndexableMediatorServer); - const result = await requestRest<MediatorServer>(path, { method: "POST", body: JSON.stringify(data) }); + public async insertMediatorServer(server: IndexableMediatorServer): Promise<PostResponse | null> { + const path = `/restconf/operations/data-provider:create-mediator-server`; + + const data = { + "url": server.url, + "name": server.name + } + + const result = await requestRest<PostResponse>(path, { method: "POST", body: JSON.stringify({ input: data }) }); return result || null; } /** * Updates data into the mediator servers table. */ - public async updateMediatorServer(server: IndexableMediatorServer): Promise<MediatorServer | null> { - const path = `database/${mediatorServerResourcePath}/${server._id}`; - const data = Object.keys(server).reduce((acc, cur) => { - if (cur !== "_id") { acc[cur] = server[cur] } else { acc["id"] = 0 }; - return acc; - }, {} as IndexableMediatorServer); - const result = await requestRest<MediatorServer>(path, { method: "PUT", body: JSON.stringify(data) }); + public async updateMediatorServer(server: IndexableMediatorServer): Promise<PostResponse | null> { + const path = `/restconf/operations/data-provider:update-mediator-server`; + + const data = { + "id": server.id, + "url": server.url, + "name": server.name + } + + const result = await requestRest<PostResponse>(path, { method: "POST", body: JSON.stringify({ input: data }) }); return result || null; } /** * Deletes data from the mediator servers table. */ - public async deleteMediatorServer(server: MediatorServer): Promise<MediatorServer | null> { - const path = `database/${mediatorServerResourcePath}/${server._id}`; - const result = await requestRest<MediatorServer>(path, { method: "DELETE" }); + public async deleteMediatorServer(server: MediatorServer): Promise<DeleteResponse | null> { + const path = `/restconf/operations/data-provider:delete-mediator-server`; + + const data = { + "id": server.id, + } + + const result = await requestRest<DeleteResponse>(path, { method: "POST", body: JSON.stringify({ input: data }) }); return result || null; } public async getMediatorServerById(serverId: string): Promise<MediatorServer | null> { - const path = `database/${mediatorServerResourcePath}/${serverId}`; - const result = await requestRest<HitEntry<MediatorServer> & { found: boolean }>(path, { method: "GET" }); - return result && result.found && result._source && { - _id: result._id, - name: result._source.name, - url: result._source.url, - } || null; + const path = `/restconf/operations/data-provider:read-mediator-server-list`; + + const data = { "filter": [{ "property": "id", "filtervalue": serverId }] } + + + const result = await requestRest<Result<MediatorServer>>(path, { method: "POST", body: JSON.stringify({ input: data }) }); + + if (result && result.output.data[0]) { + const firstResult = result.output.data[0]; + + return { + id: firstResult.id, + name: firstResult.name, + url: firstResult.url + } + } + else { + return null; + } } // https://cloud-highstreet-technologies.com/wiki/doku.php?id=att:ms:api diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx index fcb3fe46f..945e13507 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx +++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorApplication.tsx @@ -36,6 +36,7 @@ import { MediatorConfig, BusySymbol, MediatorConfigResponse } from '../models/me import EditMediatorConfigDialog, { EditMediatorConfigDialogMode } from '../components/editMediatorConfigDialog'; import { startMediatorByNameAsyncActionCreator, stopMediatorByNameAsyncActionCreator } from '../actions/mediatorConfigActions'; import mediatorService from '../services/mediatorService'; +import { ShowMediatorInfoDialog, MediatorInfoDialogMode } from '../components/showMeditaorInfoDialog' const styles = (theme: Theme) => createStyles({ root: { @@ -44,7 +45,7 @@ const styles = (theme: Theme) => createStyles({ flex: '1', }, formControl: { - margin: theme.spacing.unit, + margin: theme.spacing(1), minWidth: 300, }, button: { @@ -53,8 +54,8 @@ const styles = (theme: Theme) => createStyles({ minWidth: 'unset' }, spacer: { - marginLeft: theme.spacing.unit, - marginRight: theme.spacing.unit, + marginLeft: theme.spacing(1), + marginRight: theme.spacing(1), display: "inline" }, progress: { @@ -75,6 +76,7 @@ const mapProps = (state: IApplicationStoreState) => ({ configurations: state.mediator.mediatorServerState.configurations, supportedDevices: state.mediator.mediatorServerState.supportedDevices, busy: state.mediator.mediatorServerState.busy, + isReachable: state.mediator.mediatorServerState.isReachable }); const mapDispatch = (dispatcher: IDispatcher) => ({ @@ -96,13 +98,16 @@ const emptyMediatorConfig: MediatorConfig = { }; const MediatorServerConfigurationsTable = MaterialTable as MaterialTableCtorType<MediatorConfigResponse>; +const MediatorServerUnreachableTable = MaterialTable as MaterialTableCtorType<{ Name: string, status: string, ipAdress: string, device: string, actions: string }> type MediatorApplicationComponentProps = Connect<typeof mapProps, typeof mapDispatch> & WithStyles<typeof styles>; type MediatorServerSelectionComponentState = { busy: boolean, mediatorConfigToEdit: MediatorConfig, - mediatorConfigEditorMode: EditMediatorConfigDialogMode + mediatorConfigEditorMode: EditMediatorConfigDialogMode, + mediatorShowInfoMode: MediatorInfoDialogMode, + mediatorConfigToDisplay: MediatorConfigResponse | null } class MediatorApplicationComponent extends React.Component<MediatorApplicationComponentProps, MediatorServerSelectionComponentState> { @@ -114,6 +119,8 @@ class MediatorApplicationComponent extends React.Component<MediatorApplicationCo busy: false, mediatorConfigToEdit: emptyMediatorConfig, mediatorConfigEditorMode: EditMediatorConfigDialogMode.None, + mediatorShowInfoMode: MediatorInfoDialogMode.None, + mediatorConfigToDisplay: null } } @@ -135,7 +142,7 @@ class MediatorApplicationComponent extends React.Component<MediatorApplicationCo </Tooltip> </div> <div className={classes.spacer}> - <Tooltip title={"Info"} ><IconButton className={classes.button}><InfoIcon /></IconButton></Tooltip> + <Tooltip title={"Info"} ><IconButton className={classes.button} onClick={(event) => { this.onOpenInfoDialog(event, rowData) }}><InfoIcon /></IconButton></Tooltip> </div> <div className={classes.spacer}> {process.env.NODE_ENV === "development" ? <Tooltip title={"Edit"} ><IconButton disabled={rowData[BusySymbol]} className={classes.button} onClick={event => this.onOpenEditConfigurationDialog(event, rowData)}><EditIcon /></IconButton></Tooltip> : null} @@ -145,24 +152,38 @@ class MediatorApplicationComponent extends React.Component<MediatorApplicationCo ); const addMediatorConfigAction = { icon: AddIcon, tooltip: 'Add', onClick: this.onOpenAddConfigurationDialog }; + return ( <div className={classes.root}> {this.props.busy || this.state.busy ? <div className={classes.progress}> <CircularProgress color={"secondary"} size={48} /> </div> - : <MediatorServerConfigurationsTable title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[ - { property: "Name", title: "Mediator", type: ColumnType.text }, - { property: "Status", title: "Status", type: ColumnType.custom, customControl: ({ rowData }) => rowData.pid ? (<span>Running</span>) : (<span>Stopped</span>) }, - { property: "DeviceIp", title: "IP Adress", type: ColumnType.text }, - { - property: "Device", title: "Device", type: ColumnType.custom, customControl: ({ rowData }) => { - const dev = this.props.supportedDevices && this.props.supportedDevices.find(dev => dev.id === rowData.DeviceType); - return ( - <span> {dev && `${dev.vendor} - ${dev.device} (${dev.version || '0.0.0'})`} </span> - ) - } - }, - { property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => renderActions(rowData) }, - ]} /> + : + + this.props.isReachable ? + + <MediatorServerConfigurationsTable title={this.props.serverName || ''} customActionButtons={[addMediatorConfigAction]} idProperty={"Name"} rows={this.props.configurations} asynchronus columns={[ + { property: "Name", title: "Mediator", type: ColumnType.text }, + { property: "Status", title: "Status", type: ColumnType.custom, customControl: ({ rowData }) => rowData.pid ? (<span>Running</span>) : (<span>Stopped</span>) }, + { property: "DeviceIp", title: "IP Adress", type: ColumnType.text }, + { + property: "Device", title: "Device", type: ColumnType.custom, customControl: ({ rowData }) => { + const dev = this.props.supportedDevices && this.props.supportedDevices.find(dev => dev.id === rowData.DeviceType); + return ( + <span> {dev && `${dev.vendor} - ${dev.device} (${dev.version || '0.0.0'})`} </span> + ) + } + }, + { property: "actions", title: "Actions", type: ColumnType.custom, customControl: ({ rowData }) => renderActions(rowData) }, + ]} /> + : + <MediatorServerUnreachableTable title={this.props.serverName || ''} idProperty={"Name"} disableFilter={true} disableSorting={true} enableSelection={false} rows={[{ Name: '', status: "Mediator server not found.", ipAdress: '', device: '', actions: '' }]} columns={[ + { property: "Name", title: "Mediator", type: ColumnType.text }, + { property: "status", title: "Status", type: ColumnType.text }, + { property: "ipAdress", title: "IP Adress", type: ColumnType.text }, + { property: "device", title: "Device", type: ColumnType.text }, + { property: "actions", title: "Actions", type: ColumnType.text }, + + ]} /> } <EditMediatorConfigDialog @@ -170,17 +191,34 @@ class MediatorApplicationComponent extends React.Component<MediatorApplicationCo mode={this.state.mediatorConfigEditorMode} onClose={this.onCloseEditMediatorConfigDialog} /> + { + + this.state.mediatorShowInfoMode != MediatorInfoDialogMode.None && + <ShowMediatorInfoDialog + config={this.state.mediatorConfigToDisplay as MediatorConfigResponse} + mode={this.state.mediatorShowInfoMode} + onClose={this.onCloseInfoDialog} /> + } </div> ); } + private onOpenInfoDialog = (event: React.MouseEvent<HTMLElement>, configEntry: MediatorConfigResponse) => { + event.stopPropagation(); + event.preventDefault(); + this.setState({ mediatorShowInfoMode: MediatorInfoDialogMode.ShowDetails, mediatorConfigToDisplay: configEntry }) + } + + private onCloseInfoDialog = () => { + this.setState({ mediatorShowInfoMode: MediatorInfoDialogMode.None, mediatorConfigToDisplay: null }) + } + private onOpenAddConfigurationDialog = () => { // Tries to determine a free port for netconf listener and snpm listener // it it could not determine free ports the dialog will open any way // those ports should not be configured from the fontend, furthermore // the backend should auto configure them and tell the user the result // after the creation process. - this.setState({ busy: true, }); diff --git a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx index a23afb5f6..a5b34a2dc 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx +++ b/sdnr/wt/odlux/apps/mediatorApp/src/views/mediatorServerSelection.tsx @@ -42,8 +42,8 @@ const styles = (theme: Theme) => createStyles({ minWidth: 'unset', }, spacer: { - marginLeft: theme.spacing.unit, - marginRight: theme.spacing.unit, + marginLeft: theme.spacing(1), + marginRight: theme.spacing(1), display: "inline", }, }); @@ -58,7 +58,7 @@ const mapDispatch = (dispatcher: IDispatcher) => ({ }); const emptyMediatorServer: MediatorServer = { - _id: "", + id: "", name: "", url: "" }; @@ -72,7 +72,7 @@ type MediatorServerSelectionComponentState = { class MediatorServerSelectionComponent extends React.Component<MediatorServerSelectionComponentProps, MediatorServerSelectionComponentState> { - constructor (props: MediatorServerSelectionComponentProps) { + constructor(props: MediatorServerSelectionComponentProps) { super(props); this.state = { @@ -94,7 +94,7 @@ class MediatorServerSelectionComponent extends React.Component<MediatorServerSel }; return ( <> - <MediatorServersTable customActionButtons={[addMediatorServerActionButton]} idProperty={"_id"} + <MediatorServersTable title={"Mediator"} customActionButtons={[addMediatorServerActionButton]} idProperty={"id"} {...this.props.mediatorServersActions} {...this.props.mediatorServersProperties} columns={[ { property: "name", title: "Name", type: ColumnType.text }, { property: "url", title: "Url", type: ColumnType.text }, @@ -106,19 +106,23 @@ class MediatorServerSelectionComponent extends React.Component<MediatorServerSel </div> ) } - ]} onHandleClick={ this.onSelectMediatorServer } /> + ]} onHandleClick={this.onSelectMediatorServer} /> <EditMediatorServerDialog - mediatorServer={ this.state.mediatorServerToEdit } - mode={ this.state.mediatorServerEditorMode } - onClose={ this.onCloseEditMediatorServerDialog } /> + mediatorServer={this.state.mediatorServerToEdit} + mode={this.state.mediatorServerEditorMode} + onClose={this.onCloseEditMediatorServerDialog} /> </> ); } - private onSelectMediatorServer = (event: React.MouseEvent<HTMLElement>, server: MediatorServer) =>{ + public componentDidMount() { + this.props.mediatorServersActions.onToggleFilter(); + } + + private onSelectMediatorServer = (event: React.MouseEvent<HTMLElement>, server: MediatorServer) => { event.preventDefault(); event.stopPropagation(); - this.props.selectMediatorServer(server && server._id); + this.props.selectMediatorServer(server && server.id); } diff --git a/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js b/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js index 94943ecd5..3efe2d015 100644 --- a/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js +++ b/sdnr/wt/odlux/apps/mediatorApp/webpack.config.js @@ -127,19 +127,29 @@ module.exports = (env) => { }, proxy: { "/oauth2/": { - target: "http://localhost:3000", + target: "http://10.20.6.29:28181", secure: false }, "/database/": { - target: "http://localhost:3000", + target: "http://10.20.6.29:28181", secure: false }, "/restconf/": { - target: "http://localhost:3000", + target: "http://10.20.6.29:28181", secure: false }, "/help/": { - target: "http://localhost:3000", + target: "http://10.20.6.29:28181", + secure: false + }, + "/ms/": { + target: "http://10.20.6.29:28181", + secure: false + }, + "/websocket": { + target: "http://10.20.6.29:28181", + ws: true, + changeOrigin: true, secure: false } } |