1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
import { ConnectionActions } from '../actions.js'
import { AppDispatcher } from '../dispatcher.js'
import * as eventLogActions from './eventLog'
import * as flowsActions from './flows'
import * as settingsActions from './settings'
export const CMD_ADD = 'add'
export const CMD_UPDATE = 'update'
export const CMD_REMOVE = 'remove'
export const CMD_RESET = 'reset'
export const SYM_SOCKET = Symbol('WEBSOCKET_SYM_SOCKET')
export const CONNECT = 'WEBSOCKET_CONNECT'
export const CONNECTED = 'WEBSOCKET_CONNECTED'
export const DISCONNECT = 'WEBSOCKET_DISCONNECT'
export const DISCONNECTED = 'WEBSOCKET_DISCONNECTED'
export const ERROR = 'WEBSOCKET_ERROR'
export const MESSAGE = 'WEBSOCKET_MESSAGE'
/* we may want to have an error message attribute here at some point */
const defaultState = { connected: false, socket: null }
export default function reduce(state = defaultState, action) {
switch (action.type) {
case CONNECT:
return { ...state, [SYM_SOCKET]: action.socket }
case CONNECTED:
return { ...state, connected: true }
case DISCONNECT:
return { ...state, connected: false }
case DISCONNECTED:
return { ...state, [SYM_SOCKET]: null, connected: false }
default:
return state
}
}
export function connect() {
return dispatch => {
const socket = new WebSocket(location.origin.replace('http', 'ws') + '/updates')
// @todo remove this
window.ws = socket
socket.addEventListener('open', () => dispatch(onConnect()))
socket.addEventListener('close', () => dispatch(onDisconnect()))
socket.addEventListener('message', msg => dispatch(onMessage(msg)))
socket.addEventListener('error', error => dispatch(onError(error)))
dispatch({ type: CONNECT, socket })
return socket
}
}
export function disconnect() {
return (dispatch, getState) => {
getState().settings[SYM_SOCKET].close()
dispatch({ type: DISCONNECT })
}
}
export function onConnect() {
// workaround to make sure that our state is already available.
return dispatch => {
dispatch({ type: CONNECTED })
dispatch(settingsActions.fetchSettings())
dispatch(flowsActions.fetchFlows()).then(() => ConnectionActions.open())
}
}
export function onMessage(msg) {
return dispatch => {
const data = JSON.parse(msg.data)
AppDispatcher.dispatchServerAction(data)
switch (data.type) {
case eventLogActions.WS_MSG_TYPE:
return dispatch(eventLogActions.handleWsMsg(data))
case flowsActions.WS_MSG_TYPE:
return dispatch(flowsActions.handleWsMsg(data))
case settingsActions.UPDATE_SETTINGS:
return dispatch(settingsActions.handleWsMsg(data))
default:
console.warn('unknown message', data)
}
dispatch({ type: MESSAGE, msg })
}
}
export function onDisconnect() {
return dispatch => {
ConnectionActions.close()
dispatch(eventLogActions.addLogEntry('WebSocket connection closed.'))
dispatch({ type: DISCONNECTED })
}
}
export function onError(error) {
// @todo let event log subscribe WebSocketActions.ERROR
return dispatch => {
ConnectionActions.error()
dispatch(eventLogActions.addLogEntry('WebSocket connection error.'))
dispatch({ type: ERROR, error })
}
}
|