Skip to content

Commit 5ec31ae

Browse files
Merge pull request #290 from cmu15122/preview
Merge websocket + notif fixes into prod
2 parents 0bb897e + e1af26b commit 5ec31ae

File tree

9 files changed

+119
-58
lines changed

9 files changed

+119
-58
lines changed

client/src/components/home/student/StudentMain.tsx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ function StudentMain() {
2929
'body': `${res.data.taData.taName} is ready to help you.`,
3030
'requireInteraction': true,
3131
});
32+
} else {
33+
console.log('Received help for other student');
3234
}
3335
});
3436

@@ -37,6 +39,8 @@ function StudentMain() {
3739
new Notification('Please update your question', {
3840
'requireInteraction': true,
3941
});
42+
} else {
43+
console.log('Received updateQRequest for other student');
4044
}
4145
});
4246

@@ -47,6 +51,8 @@ function StudentMain() {
4751
new Notification('You\'ve been messaged by a TA', {
4852
'requireInteraction': true,
4953
});
54+
} else {
55+
console.log('Received message for other student');
5056
}
5157
});
5258

@@ -55,6 +61,8 @@ function StudentMain() {
5561
new Notification('You\'ve been removed from the queue', {
5662
'requireInteraction': true,
5763
});
64+
} else {
65+
console.log('Received remove for other student');
5866
}
5967
});
6068

@@ -63,6 +71,8 @@ function StudentMain() {
6371
new Notification('Your entry been approved by a TA', {
6472
'requireInteraction': true,
6573
});
74+
} else {
75+
console.log('Received approveCooldown for other student');
6676
}
6777
});
6878
}, [userData.andrewID]);

client/src/components/navbar/Navbar.tsx

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import HomeService from '../../services/HomeService';
1616
import {UserDataContext} from '../../contexts/UserDataContext';
1717
import {QueueDataContext} from '../../contexts/QueueDataContext';
1818
import {StudentDataContext} from '../../contexts/StudentDataContext';
19+
import { NotificationsActive } from '@mui/icons-material';
1920

2021
function createPage(page, link) {
2122
return {page, link};
@@ -100,6 +101,8 @@ export default function Navbar(props) {
100101
HomeService.unfreezeQueue();
101102
};
102103

104+
const [notificationPermission, setNotificationPermission] = useState(Notification.permission);
105+
103106
const unfreezeButton = <Button color="secondary" variant="contained" sx={{mx: 2}} onClick={unfreezeQueue}>Unfreeze</Button>;
104107
const freezeButton = <Button color="secondary" variant="contained" sx={{mx: 2}} onClick={freezeQueue}>Freeze</Button>;
105108

@@ -147,6 +150,17 @@ export default function Navbar(props) {
147150
</MenuItem>
148151
)
149152
}
153+
{
154+
notificationPermission !== 'granted' && (
155+
<MenuItem onClick={() => Notification.requestPermission((permission) => {
156+
setNotificationPermission(permission);
157+
})}>
158+
<Typography variant='subtitle2' sx={{mx: 2}}>
159+
Enable Notifications
160+
</Typography>
161+
</MenuItem>
162+
)
163+
}
150164
{
151165
pages?.map((page) => (
152166
<MenuItem key={page.page} onClick={goToPage(page.link)}>
@@ -194,6 +208,15 @@ export default function Navbar(props) {
194208
{
195209
userData.isTA && isHome && (queueData.queueFrozen ? unfreezeButton : freezeButton)
196210
}
211+
{
212+
notificationPermission !== 'granted' && (
213+
<IconButton color="secondary" onClick={() => Notification.requestPermission((permission) => {
214+
setNotificationPermission(permission);
215+
})}>
216+
<NotificationsActive />
217+
</IconButton>
218+
)
219+
}
197220
</Box>
198221
<Box sx={{flexGrow: 0, display: 'flex', color: '#FFFFFF'}}>
199222
{

client/src/contexts/AllStudentsContext.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, {createContext, useEffect, useState, useContext} from 'react';
22
import {StudentData} from '../../../types/StudentData';
33
import {UserDataContext} from '../contexts/UserDataContext';
44
import HomeService from '../services/HomeService';
5-
import {socketSubscribeTo} from '../services/SocketsService';
5+
import {ensureSocketConnected, socketSubscribeTo} from '../services/SocketsService';
66

77
/**
88
* Context object for all students on the queue
@@ -35,14 +35,15 @@ const AllStudentsContextProvider = ({children}: {children: React.ReactNode}) =>
3535
setAllStudents(data.allStudents);
3636
});
3737

38-
// const handleVisibilityChange = () => {
39-
// if (document.visibilityState === 'visible') {
40-
// HomeService.getAllStudents().then((res) => {
41-
// setAllStudents(res.data.allStudents);
42-
// });
43-
// }
44-
// };
45-
// document.addEventListener('visibilitychange', handleVisibilityChange);
38+
const handleVisibilityChange = () => {
39+
if (document.visibilityState === 'visible') {
40+
HomeService.getAllStudents().then((res) => {
41+
setAllStudents(res.data.allStudents);
42+
});
43+
ensureSocketConnected();
44+
}
45+
};
46+
document.addEventListener('visibilitychange', handleVisibilityChange);
4647
}
4748
}, [userData.isTA]);
4849

client/src/contexts/QueueDataContext.tsx

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { QueueData } from '../../../types/QueueData';
22
import React, { createContext, useEffect, useState } from 'react';
33
import HomeService from '../services/HomeService';
4-
import { socketSubscribeTo } from '../services/SocketsService';
4+
import { ensureSocketConnected, socketSubscribeTo } from '../services/SocketsService';
55

66
/**
77
* Context object for queue data
@@ -61,14 +61,15 @@ const QueueDataContextProvider = ({
6161
setQueueData(data);
6262
});
6363

64-
// const handleVisibilityChange = () => {
65-
// if (document.visibilityState === 'visible') {
66-
// HomeService.getAll().then((res) => {
67-
// setQueueData(res.data);
68-
// });
69-
// }
70-
// };
71-
// document.addEventListener('visibilitychange', handleVisibilityChange);
64+
const handleVisibilityChange = () => {
65+
if (document.visibilityState === 'visible') {
66+
HomeService.getAll().then((res) => {
67+
setQueueData(res.data);
68+
});
69+
ensureSocketConnected();
70+
}
71+
};
72+
document.addEventListener('visibilitychange', handleVisibilityChange);
7273
}, []);
7374

7475
return (

client/src/contexts/StudentDataContext.tsx

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, {createContext, useEffect, useState, useContext} from 'react';
22
import {StudentData} from '../../../types/StudentData';
33
import {UserDataContext} from '../contexts/UserDataContext';
44
import HomeService from '../services/HomeService';
5-
import {socketSubscribeTo} from '../services/SocketsService';
5+
import {ensureSocketConnected, socketSubscribeTo} from '../services/SocketsService';
66
import {StudentStatusValues} from '../services/StudentStatus';
77

88
/**
@@ -65,19 +65,24 @@ const StudentDataContextProvider = ({children}: {children: React.ReactNode}) =>
6565
socketSubscribeTo('studentData', (data: StudentData) => {
6666
if (data.andrewID === userData.andrewID) {
6767
setStudentData(data);
68+
} else {
69+
console.log('Student data id doesn\'t match andrewID');
6870
}
6971
});
7072

71-
// const handleVisibilityChange = () => {
72-
// if (document.visibilityState === 'visible') {
73-
// HomeService.getStudentData().then((res) => {
74-
// if (res.status === 200 && res.data.andrewID === userData.andrewID) {
75-
// setStudentData(res.data);
76-
// }
77-
// });
78-
// }
79-
// };
80-
// document.addEventListener('visibilitychange', handleVisibilityChange);
73+
const handleVisibilityChange = () => {
74+
if (document.visibilityState === 'visible') {
75+
HomeService.getStudentData().then((res) => {
76+
if (res.status === 200 && res.data.andrewID === userData.andrewID) {
77+
setStudentData(res.data);
78+
} else if (res.data.andrewID === userData.andrewID) {
79+
console.log('Student data id doesn\'t match andrewID');
80+
}
81+
ensureSocketConnected();
82+
});
83+
}
84+
};
85+
document.addEventListener('visibilitychange', handleVisibilityChange);
8186
}
8287
}, [userData.isAuthenticated]);
8388

client/src/http-common.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ httpInstance.interceptors.response.use(
3838
return res;
3939
},
4040
(err) => {
41+
if (!err.response) {
42+
showErrorToast('Server error, no response');
43+
return Promise.reject(err);
44+
}
4145
if (err.response.status >= 500) {
4246
const message = 'Server Error: ' + err.response.data.message;
4347
showErrorToast(message);

client/src/services/SocketsService.tsx

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
1-
import io from 'socket.io-client';
1+
import io, { Socket } from 'socket.io-client';
22
import Cookies from 'universal-cookie';
33

44
const cookies = new Cookies();
55

6-
let socket;
6+
let socket : Socket;
77
const SOCKET_URL = process.env.REACT_APP_PROTOCOL + '://' + process.env.REACT_APP_DOMAIN;
88
const SOCKET_PATH = process.env.REACT_APP_SOCKET_PATH;
99

@@ -18,6 +18,23 @@ export const initiateSocket = () => {
1818
if (userCookies != null) {
1919
socket.emit('authenticate', userCookies.access_token);
2020
}
21+
22+
socket.on('disconnect', (reason, details) => {
23+
console.log('Client disconnected', reason, details);
24+
25+
if (!socket.active) {
26+
console.log('Inactive socket connection');
27+
socket.connect();
28+
}
29+
});
30+
31+
socket.on('connect_error', (error) => {
32+
console.log('Connection error', error.message);
33+
if (!socket.active) {
34+
console.log('Inactive socket connection');
35+
socket.connect();
36+
}
37+
});
2138
};
2239

2340
export const socketSubscribeTo = (emission, callback) => {
@@ -37,3 +54,15 @@ export const socketUnsubscribeFrom = (emission) => {
3754

3855
socket.off(emission);
3956
};
57+
58+
export const ensureSocketConnected = () => {
59+
if (!socket) {
60+
console.log('No existing socket, initiating');
61+
initiateSocket();
62+
}
63+
64+
if (!socket.connected || !socket.active) {
65+
console.log('Existing socket not connected or inactive, reconnecting');
66+
socket.connect();
67+
}
68+
};

server/controllers/home.js

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1014,7 +1014,6 @@ exports.post_dismiss_message = function (req, res) {
10141014

10151015
ohq.dismissMessage(id);
10161016

1017-
sockets.dismiss_message(id);
10181017
emitNewStudentData(id);
10191018
emitNewAllStudents();
10201019

0 commit comments

Comments
 (0)