diff --git a/app/src/components/ConnectionSetup/Connection.tsx b/app/src/components/ConnectionSetup/Connection.tsx index fd3db40..2d04b5d 100644 --- a/app/src/components/ConnectionSetup/Connection.tsx +++ b/app/src/components/ConnectionSetup/Connection.tsx @@ -3,8 +3,13 @@ import * as React from 'react' import { Button, CircularProgress, + FormControl, FormControlLabel, Grid, + IconButton, + Input, + InputAdornment, + InputLabel, MenuItem, Modal, Paper, @@ -17,6 +22,10 @@ import { DataSourceState, MqttOptions } from '../../../../backend/src/DataSource import { StyleRulesCallback, Theme, withStyles } from '@material-ui/core/styles' import { addMqttConnectionEvent, makeConnectionStateEvent, removeConnection, rendererEvents } from '../../../../events' +import Notification from './Notification' +import Visibility from '@material-ui/icons/Visibility' +import VisibilityOff from '@material-ui/icons/VisibilityOff' + import sha1 = require('sha1') interface Props { @@ -34,7 +43,7 @@ const protocols = [ interface State { connecting: boolean connectionId?: string - error?: Error + error?: string visible: boolean host: string protocol: string @@ -44,6 +53,7 @@ interface State { clientId: string username: string password: string + showPassword: boolean } declare var window: any @@ -71,6 +81,7 @@ class Connection extends React.Component { password: '', connecting: false, connectionId: undefined, + showPassword: false, } this.state = Object.assign({}, defaultState, storedSettings) @@ -80,6 +91,10 @@ class Connection extends React.Component { window.localStorage.setItem('connectionSettings', JSON.stringify(this.state)) } + private handleClickShowPassword = () => { + this.setState({ showPassword: !this.state.showPassword }) + } + private optionsFromState(): MqttOptions { const protocol = this.state.protocol === 'tcp://' ? 'mqtt://' : this.state.protocol const url = `${protocol}${this.state.host}:${this.state.port}` @@ -87,7 +102,7 @@ class Connection extends React.Component { return { url, username: this.state.username || undefined, - password: this.state.username || undefined, + password: this.state.password || undefined, tls: this.state.tls, certValidation: this.state.certValidation, } @@ -110,8 +125,8 @@ class Connection extends React.Component { this.props.onConnection(connectionId) this.setState({ visible: false }) } else if (state.error) { - console.log('error', state.error) this.setState({ error: state.error }) + this.disconnect() } }) } @@ -150,6 +165,9 @@ class Connection extends React.Component { button: { margin: theme.spacing.unit, }, + passwordFormControl: { + marginTop: '16px', + }, } } @@ -163,108 +181,137 @@ class Connection extends React.Component { public render() { const { classes } = this.props - return { console.log('close') }}> - - - MQTT Connection - -
- - - - {protocols.map((value: string) => ( - - {value} - - ))} - - - - - - - - - - - - - - - -
- this.setState({ certValidation: !this.state.certValidation })} - color="primary" + const passwordVisibilityButton = ( + + + {this.state.showPassword ? : } + + + ) + + let renderError = null + if (this.state.error) { + renderError = ( + { this.setState({ error: undefined }) }} + /> + ) + } + + return ( +
+ {renderError} + + + + MQTT Connection + + + + + + {protocols.map((value: string) => ( + + {value} + + ))} + + + + + + + + + + + + + + Password + - )} - label="Validate certificate" - labelPlacement="bottom" - /> -
- - -
- this.setState({ tls: !this.state.tls })} - color="primary" + + + +
+ this.setState({ certValidation: !this.state.certValidation })} + color="primary" + /> + )} + label="Validate certificate" + labelPlacement="bottom" /> - )} - label="Encryption (tls)" - labelPlacement="bottom" - /> +
+
+ +
+ this.setState({ tls: !this.state.tls })} + color="primary" + /> + )} + label="Encryption (tls)" + labelPlacement="bottom" + /> +
+
+ + +
+
+ + {this.renderConnectButton()}
- - - -
-
- - { this.renderConnectButton() } -
- - - + + + +
+ ) } private renderConnectButton() { diff --git a/app/src/components/ConnectionSetup/Notification.tsx b/app/src/components/ConnectionSetup/Notification.tsx new file mode 100644 index 0000000..dd89e7a --- /dev/null +++ b/app/src/components/ConnectionSetup/Notification.tsx @@ -0,0 +1,55 @@ +import * as React from 'react' + +import { Snackbar, SnackbarContent } from '@material-ui/core' +import { Theme, withStyles } from '@material-ui/core/styles' +import { green, red } from '@material-ui/core/colors' + +enum MessageType { + success = 'success', + error = 'error', +} + +interface Props { + message?: string + type: MessageType + onClose: () => void + classes: any +} + +class Notification extends React.Component { + constructor(props: Props) { + super(props) + } + + public static styles = (theme: Theme) => ({ + success: { + backgroundColor: green[600], + color: theme.typography.button.color, + }, + error: { + backgroundColor: red[600], + color: theme.typography.button.color, + }, + }) + + public render() { + return ( + + + + ) + } +} + +export default withStyles(Notification.styles)(Notification) diff --git a/backend/src/DataSource/DataSourceState.ts b/backend/src/DataSource/DataSourceState.ts index 26535b3..1be3fc0 100644 --- a/backend/src/DataSource/DataSourceState.ts +++ b/backend/src/DataSource/DataSourceState.ts @@ -3,7 +3,7 @@ import { EventDispatcher } from '../../../events' export interface DataSourceState { connecting: boolean connected: boolean - error?: Error + error?: string } export class DataSourceStateMachine { @@ -25,7 +25,7 @@ export class DataSourceStateMachine { public setError(error: Error) { this.state = { - error, + error: error.message, connected: false, connecting: false, } diff --git a/backend/src/DataSource/MqttSource.ts b/backend/src/DataSource/MqttSource.ts index 4fc7d72..f0380c6 100644 --- a/backend/src/DataSource/MqttSource.ts +++ b/backend/src/DataSource/MqttSource.ts @@ -1,6 +1,7 @@ +import * as Url from 'url' + import { Client, connect as mqttConnect } from 'mqtt' import { DataSource, DataSourceStateMachine } from './' -import * as Url from 'url' export interface MqttOptions { url: string @@ -36,6 +37,8 @@ export class MqttSource implements DataSource { const client = mqttConnect(url, { resubscribe: false, rejectUnauthorized: !options.certValidation, + username: options.username, + password: options.password, }) this.client = client