Refactor connection reducer & tree
This commit is contained in:
@@ -87,7 +87,7 @@ class App extends React.Component<Props, {}> {
|
||||
<TitleBar />
|
||||
<div style={centerContent}>
|
||||
<div style={this.getStyles().left}>
|
||||
<Tree connectionId={this.props.connectionId} />
|
||||
<Tree />
|
||||
</div>
|
||||
<div style={this.getStyles().right}>
|
||||
<Sidebar connectionId={this.props.connectionId} />
|
||||
@@ -105,7 +105,7 @@ class App extends React.Component<Props, {}> {
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
return {
|
||||
settingsVisible: state.tooBigReducer.settings.visible,
|
||||
connectionId: state.tooBigReducer.connectionId,
|
||||
connectionId: state.connection.connectionId,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { ActionTypes, NodeOrder, CustomAction, AppState } from '../reducers'
|
||||
import { ActionTypes, Action, ConnectionState } from '../reducers/Connection'
|
||||
import { MqttOptions } from '../../../backend/src/DataSource'
|
||||
import { Dispatch } from 'redux'
|
||||
import { rendererEvents, addMqttConnectionEvent, makeConnectionStateEvent, removeConnection } from '../../../events'
|
||||
import { AppState } from '../reducers'
|
||||
import * as q from '../../../backend/src/Model'
|
||||
|
||||
export const connect = (options: MqttOptions, connectionId: string) => (dispatch: Dispatch<any>, getState: () => AppState) => {
|
||||
dispatch(connecting(connectionId))
|
||||
@@ -9,7 +11,9 @@ export const connect = (options: MqttOptions, connectionId: string) => (dispatch
|
||||
const event = makeConnectionStateEvent(connectionId)
|
||||
rendererEvents.subscribe(event, (dataSourceState) => {
|
||||
if (dataSourceState.connected) {
|
||||
dispatch(connected())
|
||||
const tree = new q.Tree()
|
||||
tree.updateWithConnection(rendererEvents, connectionId)
|
||||
dispatch(connected(tree))
|
||||
} else if (dataSourceState.error) {
|
||||
dispatch(showError(dataSourceState.error))
|
||||
dispatch(disconnect())
|
||||
@@ -17,24 +21,27 @@ export const connect = (options: MqttOptions, connectionId: string) => (dispatch
|
||||
})
|
||||
}
|
||||
|
||||
export const connected: () => CustomAction = () => ({
|
||||
type: ActionTypes.connected,
|
||||
export const connected: (tree: q.Tree) => Action = (tree: q.Tree) => ({
|
||||
tree,
|
||||
type: ActionTypes.CONNECTION_SET_CONNECTED,
|
||||
})
|
||||
|
||||
export const connecting: (connectionId: string) => CustomAction = (connectionId: string) => ({
|
||||
export const connecting: (connectionId: string) => Action = (connectionId: string) => ({
|
||||
connectionId,
|
||||
type: ActionTypes.connecting,
|
||||
type: ActionTypes.CONNECTION_SET_CONNECTING,
|
||||
})
|
||||
|
||||
export const showError = (error?: string) => ({
|
||||
error,
|
||||
type: ActionTypes.showError,
|
||||
type: ActionTypes.CONNECTION_SET_SHOW_ERROR,
|
||||
})
|
||||
|
||||
export const disconnect = () => (dispatch: Dispatch<CustomAction>, getState: () => AppState) => {
|
||||
rendererEvents.emit(removeConnection, getState().tooBigReducer.connectionId)
|
||||
export const disconnect = () => (dispatch: Dispatch<Action>, getState: () => AppState) => {
|
||||
const { connectionId, tree } = getState().connection
|
||||
rendererEvents.emit(removeConnection, connectionId)
|
||||
tree && tree.stopUpdating()
|
||||
|
||||
dispatch({
|
||||
type: ActionTypes.disconnect,
|
||||
type: ActionTypes.CONNECTION_SET_DISCONNECTED,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -3,7 +3,9 @@ import { AppState } from '../reducers'
|
||||
import { makePublishEvent, rendererEvents } from '../../../events'
|
||||
|
||||
export const clearRetainedTopic = () => (dispatch: Dispatch<Action>, getState: () => AppState) => {
|
||||
const { selectedTopic, connectionId } = getState().tooBigReducer
|
||||
const { selectedTopic } = getState().tooBigReducer
|
||||
const { connectionId } = getState().connection
|
||||
|
||||
if (!selectedTopic || !connectionId) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -380,10 +380,10 @@ class Connection extends React.Component<Props, State> {
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
return {
|
||||
visible: !state.tooBigReducer.connected,
|
||||
connected: state.tooBigReducer.connected,
|
||||
connecting: state.tooBigReducer.connecting,
|
||||
error: state.tooBigReducer.error,
|
||||
visible: !state.connection.connected,
|
||||
connected: state.connection.connected,
|
||||
connecting: state.connection.connecting,
|
||||
error: state.connection.error,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import * as React from 'react'
|
||||
import * as q from '../../../../backend/src/Model'
|
||||
|
||||
import { Badge, Typography } from '@material-ui/core'
|
||||
import { Theme, withStyles } from '@material-ui/core/styles'
|
||||
|
||||
@@ -18,22 +18,17 @@ interface Props {
|
||||
autoExpandLimit: number
|
||||
didSelectNode?: (node: q.TreeNode) => void
|
||||
connectionId?: string
|
||||
connected: boolean
|
||||
tree?: q.Tree
|
||||
}
|
||||
|
||||
interface TreeState {
|
||||
tree: q.Tree
|
||||
msg: any
|
||||
}
|
||||
|
||||
class Tree extends React.Component<Props, TreeState> {
|
||||
class Tree extends React.Component<Props, {}> {
|
||||
private updateTimer?: any
|
||||
private lastUpdate: number = 0
|
||||
private perf: number = 0
|
||||
|
||||
constructor(props: any) {
|
||||
super(props)
|
||||
this.state = { tree: new q.Tree(), msg: {} }
|
||||
this.state = { }
|
||||
}
|
||||
|
||||
public time(): number {
|
||||
@@ -43,11 +38,18 @@ class Tree extends React.Component<Props, TreeState> {
|
||||
return time
|
||||
}
|
||||
|
||||
private performanceCallback = (ms: number) => {
|
||||
average.push(Date.now(), ms)
|
||||
public componentWillReceiveProps(nextProps: Props) {
|
||||
if (this.props.tree !== nextProps.tree) {
|
||||
if (this.props.tree) {
|
||||
this.props.tree.onMerge.unsubscribe(this.throttledTreeUpdate)
|
||||
}
|
||||
if (nextProps.tree) {
|
||||
nextProps.tree.onMerge.subscribe(this.throttledTreeUpdate)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public throttledTreeUpdate() {
|
||||
public throttledTreeUpdate = () => {
|
||||
if (this.updateTimer) {
|
||||
return
|
||||
}
|
||||
@@ -66,23 +68,6 @@ class Tree extends React.Component<Props, TreeState> {
|
||||
}, Math.max(0, timeUntilNextUpdate))
|
||||
}
|
||||
|
||||
public componentWillReceiveProps(nextProps: Props) {
|
||||
this.registerAndUnregisterEventSubscriptionsForNewProps(nextProps)
|
||||
}
|
||||
|
||||
private registerAndUnregisterEventSubscriptionsForNewProps(nextProps: Props) {
|
||||
if (this.props.connectionId !== nextProps.connectionId) {
|
||||
if (this.props.connectionId) {
|
||||
this.setState({ tree: new q.Tree() })
|
||||
rendererEvents.unsubscribeAll(makeConnectionMessageEvent(this.props.connectionId))
|
||||
this.updateTimer && clearTimeout(this.updateTimer)
|
||||
}
|
||||
if (nextProps.connectionId) {
|
||||
rendererEvents.subscribe(makeConnectionMessageEvent(nextProps.connectionId), this.handleNewData)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public componentWillUnmount() {
|
||||
if (this.props.connectionId) {
|
||||
const event = makeConnectionMessageEvent(this.props.connectionId)
|
||||
@@ -90,17 +75,8 @@ class Tree extends React.Component<Props, TreeState> {
|
||||
}
|
||||
}
|
||||
|
||||
private handleNewData = (msg: MqttMessage) => {
|
||||
const edges = msg.topic.split('/')
|
||||
const node = q.TreeNodeFactory.fromEdgesAndValue(edges, msg.payload)
|
||||
node.mqttMessage = msg
|
||||
this.state.tree.updateWithNode(node.firstNode())
|
||||
|
||||
this.throttledTreeUpdate()
|
||||
}
|
||||
|
||||
public render() {
|
||||
if (!this.props.connected) {
|
||||
if (!this.props.tree) {
|
||||
return null
|
||||
}
|
||||
|
||||
@@ -116,22 +92,26 @@ class Tree extends React.Component<Props, TreeState> {
|
||||
autoExpandLimit={this.props.autoExpandLimit}
|
||||
isRoot={true}
|
||||
didSelectNode={this.props.didSelectNode}
|
||||
treeNode={this.state.tree}
|
||||
treeNode={this.props.tree}
|
||||
name="/"
|
||||
collapsed={false}
|
||||
key="rootNode"
|
||||
lastUpdate={this.state.tree.lastUpdate}
|
||||
lastUpdate={this.props.tree.lastUpdate}
|
||||
performanceCallback={this.performanceCallback}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
private performanceCallback = (ms: number) => {
|
||||
average.push(Date.now(), ms)
|
||||
}
|
||||
}
|
||||
|
||||
const mapStateToProps = (state: AppState) => {
|
||||
return {
|
||||
autoExpandLimit: state.tooBigReducer.settings.autoExpandLimit,
|
||||
connected: state.tooBigReducer.connected,
|
||||
tree: state.connection.tree,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
88
app/src/reducers/Connection.ts
Normal file
88
app/src/reducers/Connection.ts
Normal file
@@ -0,0 +1,88 @@
|
||||
import { Action } from 'redux'
|
||||
import { createReducer } from './lib'
|
||||
import * as q from '../../../backend/src/Model'
|
||||
import { MqttOptions } from '../../../backend/src/DataSource'
|
||||
|
||||
export interface ConnectionState {
|
||||
tree?: q.Tree
|
||||
connectionOptions?: MqttOptions
|
||||
connectionId?: string
|
||||
error?: string
|
||||
connected: boolean
|
||||
connecting: boolean
|
||||
}
|
||||
|
||||
export type Action = SetConnecting | SetConnected | SetDisconnected | ShowError
|
||||
|
||||
export enum ActionTypes {
|
||||
CONNECTION_SET_CONNECTING = 'CONNECTION_SET_CONNECTING',
|
||||
CONNECTION_SET_CONNECTED = 'CONNECTION_SET_CONNECTED',
|
||||
CONNECTION_SET_DISCONNECTED = 'CONNECTION_SET_DISCONNECTED',
|
||||
CONNECTION_SET_SHOW_ERROR = 'CONNECTION_SET_SHOW_ERROR',
|
||||
}
|
||||
|
||||
export interface SetConnecting {
|
||||
type: ActionTypes.CONNECTION_SET_CONNECTING,
|
||||
connectionId: string
|
||||
}
|
||||
|
||||
export interface SetConnected {
|
||||
type: ActionTypes.CONNECTION_SET_CONNECTED
|
||||
tree: q.Tree
|
||||
}
|
||||
|
||||
export interface SetDisconnected {
|
||||
type: ActionTypes.CONNECTION_SET_DISCONNECTED
|
||||
}
|
||||
|
||||
export interface ShowError {
|
||||
type: ActionTypes.CONNECTION_SET_SHOW_ERROR
|
||||
error?: Error
|
||||
}
|
||||
|
||||
const initialState: ConnectionState = {
|
||||
connected: false,
|
||||
connecting: false,
|
||||
}
|
||||
|
||||
export const connectionReducer = createReducer(initialState, {
|
||||
CONNECTION_SET_CONNECTING: setConnecting,
|
||||
CONNECTION_SET_CONNECTED: setConnected,
|
||||
CONNECTION_SET_DISCONNECTED: setDisconnected,
|
||||
CONNECTION_SET_SHOW_ERROR: showError,
|
||||
})
|
||||
|
||||
function setConnecting(state: ConnectionState, action: SetConnecting) {
|
||||
return {
|
||||
...state,
|
||||
connecting: true,
|
||||
connected: false,
|
||||
connectionId: action.connectionId,
|
||||
}
|
||||
}
|
||||
|
||||
function setConnected(state: ConnectionState, action: SetConnected) {
|
||||
return {
|
||||
...state,
|
||||
connecting: false,
|
||||
connected: true,
|
||||
tree: action.tree,
|
||||
}
|
||||
}
|
||||
|
||||
function setDisconnected(state: ConnectionState, action: SetDisconnected) {
|
||||
return {
|
||||
...state,
|
||||
connecting: false,
|
||||
connected: false,
|
||||
connectionId: undefined,
|
||||
tree: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
function showError(state: ConnectionState, action: ShowError) {
|
||||
return {
|
||||
...state,
|
||||
error: action.error,
|
||||
}
|
||||
}
|
||||
@@ -3,20 +3,18 @@ import * as q from '../../../backend/src/Model'
|
||||
import { Action, Reducer, combineReducers } from 'redux'
|
||||
|
||||
import { trackEvent } from '../tracking'
|
||||
import { MqttOptions } from '../../../backend/src/DataSource'
|
||||
import { PublishState, publishReducer } from './Publish'
|
||||
import { ConnectionState, connectionReducer } from './Connection'
|
||||
|
||||
export enum ActionTypes {
|
||||
disconnect = 'DISCONNECT',
|
||||
showError = 'SHOW_ERROR',
|
||||
|
||||
setAutoExpandLimit = 'SET_AUTO_EXPAND_LIMIT',
|
||||
toggleSettingsVisibility = 'TOGGLE_SETTINGS_VISIBILITY',
|
||||
setNodeOrder = 'SET_NODE_ORDER',
|
||||
selectTopic = 'SELECT_TOPIC',
|
||||
showUpdateNotification = 'SHOW_UPDATE_NOTIFICATION',
|
||||
showUpdateDetails = 'SHOW_UPDATE_DETAILS',
|
||||
connecting = 'CONNECTING',
|
||||
connected = 'CONNECTED',
|
||||
|
||||
}
|
||||
|
||||
export interface CustomAction extends Action {
|
||||
@@ -26,14 +24,12 @@ export interface CustomAction extends Action {
|
||||
selectedTopic?: q.TreeNode
|
||||
showUpdateNotification?: boolean
|
||||
showUpdateDetails?: boolean
|
||||
connectionOptions?: MqttOptions
|
||||
connectionId?: string
|
||||
error?: string
|
||||
}
|
||||
|
||||
export interface AppState {
|
||||
tooBigReducer: TooBigOfState
|
||||
publish: PublishState
|
||||
connection: ConnectionState
|
||||
}
|
||||
|
||||
export interface TooBigOfState {
|
||||
@@ -41,10 +37,6 @@ export interface TooBigOfState {
|
||||
selectedTopic?: q.TreeNode
|
||||
showUpdateNotification?: boolean
|
||||
showUpdateDetails: boolean
|
||||
connecting: boolean
|
||||
connected: boolean
|
||||
error?: string
|
||||
connectionId?: string
|
||||
}
|
||||
|
||||
export interface SettingsState {
|
||||
@@ -68,9 +60,6 @@ const initialBigState: TooBigOfState = {
|
||||
},
|
||||
selectedTopic: undefined,
|
||||
showUpdateDetails: false,
|
||||
connected: false,
|
||||
connecting: false,
|
||||
error: undefined,
|
||||
}
|
||||
|
||||
const tooBigReducer: Reducer<TooBigOfState | undefined, CustomAction> = (state = initialBigState, action) => {
|
||||
@@ -134,38 +123,6 @@ const tooBigReducer: Reducer<TooBigOfState | undefined, CustomAction> = (state =
|
||||
showUpdateDetails: action.showUpdateDetails,
|
||||
}
|
||||
|
||||
case ActionTypes.connecting:
|
||||
if (!action.connectionId) {
|
||||
return state
|
||||
}
|
||||
return {
|
||||
...state,
|
||||
connected: false,
|
||||
connecting: true,
|
||||
connectionId: action.connectionId,
|
||||
}
|
||||
|
||||
case ActionTypes.disconnect:
|
||||
return {
|
||||
...state,
|
||||
connected: false,
|
||||
connecting: false,
|
||||
connectionId: undefined,
|
||||
}
|
||||
|
||||
case ActionTypes.connected:
|
||||
return {
|
||||
...state,
|
||||
connected: true,
|
||||
connecting: false,
|
||||
}
|
||||
|
||||
case ActionTypes.showError:
|
||||
return {
|
||||
...state,
|
||||
error: action.error,
|
||||
}
|
||||
|
||||
default:
|
||||
return state
|
||||
}
|
||||
@@ -174,6 +131,7 @@ const tooBigReducer: Reducer<TooBigOfState | undefined, CustomAction> = (state =
|
||||
const reducer = combineReducers({
|
||||
tooBigReducer,
|
||||
publish: publishReducer,
|
||||
connection: connectionReducer,
|
||||
})
|
||||
|
||||
export default reducer
|
||||
|
||||
Reference in New Issue
Block a user