Skip to content

Commit 3aff12a

Browse files
hatsybnaul
authored andcommitted
Sticky notification for websocket connection problems (#174)
* Sticky error notification when websocket cannot connect * Fixed small bug on restart * Remove debugging statement * Changed architecture of sticky notifications to pass in type='websocket' * Renamed dispatcher to dispatch * Simplified notifications clearing such that there wouldn't be multiple notifications on reload * Updated clearing notification. Added support for orange status * Removed deprecated code * Removed mentions of websocket from notifications. Generalised to have callers define a key and filter by key * Renamed key to tag * Clear notifications from within websocket before setting a new notification * Ported promise to notification and simplified websocket notification code
1 parent 403aa64 commit 3aff12a

File tree

3 files changed

+63
-7
lines changed

3 files changed

+63
-7
lines changed

public/scripts/Notifications.jsx

Lines changed: 28 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import { connect } from 'react-redux';
44

55
export const SHOW_NOTIFICATION = 'cesium/SHOW_NOTIFICATION';
66
export const HIDE_NOTIFICATION = 'cesium/HIDE_NOTIFICATION';
7+
export const HIDE_NOTIFICATION_BY_TAG = 'cesium/HIDE_NOTIFICATION_BY_TAG';
8+
9+
export const MS_PER_YEAR = 31540000000;
10+
711

812
export function hideNotification(id) {
913
return {
@@ -12,6 +16,18 @@ export function hideNotification(id) {
1216
};
1317
}
1418

19+
export function hideNotificationByTag(tag) {
20+
return (dispatch) => {
21+
dispatch(
22+
{
23+
type: HIDE_NOTIFICATION_BY_TAG,
24+
payload: { tag }
25+
}
26+
);
27+
return Promise.resolve();
28+
};
29+
}
30+
1531
export let Notifications = (props) => {
1632
const style = {
1733
position: 'fixed',
@@ -39,6 +55,7 @@ export let Notifications = (props) => {
3955

4056
const noteColor = {
4157
error: 'Crimson',
58+
warning: 'Orange',
4259
info: 'MediumAquaMarine'
4360
};
4461

@@ -70,7 +87,7 @@ Notifications = connect(mapStateToProps)(Notifications);
7087

7188

7289
let nextNotificationId = 0;
73-
export function showNotification(note, type='info') {
90+
export function showNotification(note, type='info', duration=3000, tag='default') {
7491
const thisId = nextNotificationId++;
7592

7693
if (type === 'error') {
@@ -82,26 +99,31 @@ export function showNotification(note, type='info') {
8299
type: SHOW_NOTIFICATION,
83100
payload: {
84101
id: thisId,
85-
note,
86-
type
102+
note: note,
103+
type: type,
104+
tag: tag
87105
}
88106
});
89-
setTimeout(() => dispatch(hideNotification(thisId)), 3000);
107+
setTimeout(() => dispatch(hideNotification(thisId)), duration);
90108
};
91109
}
92110

93111
export function reducer(state={ notes: [] }, action) {
94112
switch (action.type) {
95113
case SHOW_NOTIFICATION: {
96-
let { id, note, type } = action.payload;
114+
let { id, note, type, tag } = action.payload;
97115
return {
98-
notes: state.notes.concat({ id, note, type })
116+
notes: state.notes.concat({ id, note, type, tag })
99117
};
100118
}
101119
case HIDE_NOTIFICATION:
102120
return {
103121
notes: state.notes.filter(n => (n.id !== action.payload.id))
104122
};
123+
case HIDE_NOTIFICATION_BY_TAG:
124+
return {
125+
notes: state.notes.filter(n => (n.tag !== action.payload.tag))
126+
}
105127
default:
106128
return state;
107129
}

public/scripts/WebSocket.jsx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import React from 'react';
22
import { connect } from 'react-redux';
33
import { createCookie, readCookie, eraseCookie } from './cookies';
44
import ReconnectingWebSocket from './reconnecting-websocket';
5+
import { showNotification, hideNotificationByTag, MS_PER_YEAR } from './Notifications';
56

67

78
function getTime() {
@@ -56,6 +57,17 @@ function getAuthToken(auth_url) {
5657
}
5758

5859

60+
function showWebsocketNotification(dispatch, msg, tag) {
61+
dispatch(hideNotificationByTag(tag))
62+
.then(dispatch(showNotification(msg, 'warning', 50 * MS_PER_YEAR, tag)));
63+
}
64+
65+
66+
function clearWebsocketNotification(dispatch, tag) {
67+
dispatch(hideNotificationByTag(tag));
68+
}
69+
70+
5971
class WebSocket extends React.Component {
6072
constructor(props) {
6173
super(props);
@@ -65,11 +77,21 @@ class WebSocket extends React.Component {
6577
};
6678

6779
const ws = new ReconnectingWebSocket(props.url);
80+
const tag = 'websocket';
6881

6982
ws.onopen = (event) => {
7083
this.setState({ connected: true });
84+
clearWebsocketNotification(this.props.dispatch, tag);
7185
};
7286

87+
ws.onerror = (event) => {
88+
showWebsocketNotification(
89+
this.props.dispatch,
90+
"No WebSocket connection: limited functionality may be available",
91+
tag
92+
);
93+
}
94+
7395
ws.onmessage = (event) => {
7496
const message = event.data;
7597

@@ -89,9 +111,15 @@ class WebSocket extends React.Component {
89111
case "AUTH FAILED":
90112
this.setState({ authenticated: false });
91113
eraseCookie('auth_token');
114+
showWebsocketNotification(
115+
this.props.dispatch,
116+
"WebSocket connection authentication failed: limited functionality may be available",
117+
tag
118+
);
92119
break;
93120
case "AUTH OK":
94121
this.setState({ authenticated: true });
122+
this.props.dispatch(hideNotificationByTag(tag));
95123
break;
96124
default:
97125
this.props.messageHandler(data);
@@ -101,6 +129,11 @@ class WebSocket extends React.Component {
101129
ws.onclose = (event) => {
102130
this.setState({ connected: false,
103131
authenticated: false });
132+
showWebsocketNotification(
133+
this.props.dispatch,
134+
"No WebSocket connection: limited functionality may be available",
135+
tag
136+
);
104137
};
105138
}
106139

@@ -130,7 +163,7 @@ class WebSocket extends React.Component {
130163
};
131164

132165
const connected_desc = (`WebSocket is
133-
${(this.state.connected ? 'connected' : 'disconnected')} &
166+
${(this.state.connected ? 'connected' : 'disconnected')} &
134167
${(this.state.authenticated ? 'authenticated' : 'unauthenticated')}.`);
135168
return (
136169
<div

public/scripts/main.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -296,6 +296,7 @@ class MainContent extends React.Component {
296296
url={`ws://${this.props.root}websocket`}
297297
auth_url={`${location.protocol}//${this.props.root}socket_auth_token`}
298298
messageHandler={messageHandler}
299+
dispatch={store.dispatch}
299300
/>
300301
</Tab>
301302
</TabList>

0 commit comments

Comments
 (0)