Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merge websocket + notif fixes into prod #290

Merged
merged 4 commits into from
Feb 26, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions client/src/components/home/student/StudentMain.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ function StudentMain() {
'body': `${res.data.taData.taName} is ready to help you.`,
'requireInteraction': true,
});
} else {
console.log('Received help for other student');
}
});

Expand All @@ -37,6 +39,8 @@ function StudentMain() {
new Notification('Please update your question', {
'requireInteraction': true,
});
} else {
console.log('Received updateQRequest for other student');
}
});

Expand All @@ -47,6 +51,8 @@ function StudentMain() {
new Notification('You\'ve been messaged by a TA', {
'requireInteraction': true,
});
} else {
console.log('Received message for other student');
}
});

Expand All @@ -55,6 +61,8 @@ function StudentMain() {
new Notification('You\'ve been removed from the queue', {
'requireInteraction': true,
});
} else {
console.log('Received remove for other student');
}
});

Expand All @@ -63,6 +71,8 @@ function StudentMain() {
new Notification('Your entry been approved by a TA', {
'requireInteraction': true,
});
} else {
console.log('Received approveCooldown for other student');
}
});
}, [userData.andrewID]);
Expand Down
23 changes: 23 additions & 0 deletions client/src/components/navbar/Navbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import HomeService from '../../services/HomeService';
import {UserDataContext} from '../../contexts/UserDataContext';
import {QueueDataContext} from '../../contexts/QueueDataContext';
import {StudentDataContext} from '../../contexts/StudentDataContext';
import { NotificationsActive } from '@mui/icons-material';

function createPage(page, link) {
return {page, link};
Expand Down Expand Up @@ -100,6 +101,8 @@ export default function Navbar(props) {
HomeService.unfreezeQueue();
};

const [notificationPermission, setNotificationPermission] = useState(Notification.permission);

const unfreezeButton = <Button color="secondary" variant="contained" sx={{mx: 2}} onClick={unfreezeQueue}>Unfreeze</Button>;
const freezeButton = <Button color="secondary" variant="contained" sx={{mx: 2}} onClick={freezeQueue}>Freeze</Button>;

Expand Down Expand Up @@ -147,6 +150,17 @@ export default function Navbar(props) {
</MenuItem>
)
}
{
notificationPermission !== 'granted' && (
<MenuItem onClick={() => Notification.requestPermission((permission) => {
setNotificationPermission(permission);
})}>
<Typography variant='subtitle2' sx={{mx: 2}}>
Enable Notifications
</Typography>
</MenuItem>
)
}
{
pages?.map((page) => (
<MenuItem key={page.page} onClick={goToPage(page.link)}>
Expand Down Expand Up @@ -194,6 +208,15 @@ export default function Navbar(props) {
{
userData.isTA && isHome && (queueData.queueFrozen ? unfreezeButton : freezeButton)
}
{
notificationPermission !== 'granted' && (
<IconButton color="secondary" onClick={() => Notification.requestPermission((permission) => {
setNotificationPermission(permission);
})}>
<NotificationsActive />
</IconButton>
)
}
</Box>
<Box sx={{flexGrow: 0, display: 'flex', color: '#FFFFFF'}}>
{
Expand Down
19 changes: 10 additions & 9 deletions client/src/contexts/AllStudentsContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, {createContext, useEffect, useState, useContext} from 'react';
import {StudentData} from '../../../types/StudentData';
import {UserDataContext} from '../contexts/UserDataContext';
import HomeService from '../services/HomeService';
import {socketSubscribeTo} from '../services/SocketsService';
import {ensureSocketConnected, socketSubscribeTo} from '../services/SocketsService';

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

// const handleVisibilityChange = () => {
// if (document.visibilityState === 'visible') {
// HomeService.getAllStudents().then((res) => {
// setAllStudents(res.data.allStudents);
// });
// }
// };
// document.addEventListener('visibilitychange', handleVisibilityChange);
const handleVisibilityChange = () => {
if (document.visibilityState === 'visible') {
HomeService.getAllStudents().then((res) => {
setAllStudents(res.data.allStudents);
});
ensureSocketConnected();
}
};
document.addEventListener('visibilitychange', handleVisibilityChange);
}
}, [userData.isTA]);

Expand Down
19 changes: 10 additions & 9 deletions client/src/contexts/QueueDataContext.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { QueueData } from '../../../types/QueueData';
import React, { createContext, useEffect, useState } from 'react';
import HomeService from '../services/HomeService';
import { socketSubscribeTo } from '../services/SocketsService';
import { ensureSocketConnected, socketSubscribeTo } from '../services/SocketsService';

/**
* Context object for queue data
Expand Down Expand Up @@ -61,14 +61,15 @@ const QueueDataContextProvider = ({
setQueueData(data);
});

// const handleVisibilityChange = () => {
// if (document.visibilityState === 'visible') {
// HomeService.getAll().then((res) => {
// setQueueData(res.data);
// });
// }
// };
// document.addEventListener('visibilitychange', handleVisibilityChange);
const handleVisibilityChange = () => {
if (document.visibilityState === 'visible') {
HomeService.getAll().then((res) => {
setQueueData(res.data);
});
ensureSocketConnected();
}
};
document.addEventListener('visibilitychange', handleVisibilityChange);
}, []);

return (
Expand Down
27 changes: 16 additions & 11 deletions client/src/contexts/StudentDataContext.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React, {createContext, useEffect, useState, useContext} from 'react';
import {StudentData} from '../../../types/StudentData';
import {UserDataContext} from '../contexts/UserDataContext';
import HomeService from '../services/HomeService';
import {socketSubscribeTo} from '../services/SocketsService';
import {ensureSocketConnected, socketSubscribeTo} from '../services/SocketsService';
import {StudentStatusValues} from '../services/StudentStatus';

/**
Expand Down Expand Up @@ -65,19 +65,24 @@ const StudentDataContextProvider = ({children}: {children: React.ReactNode}) =>
socketSubscribeTo('studentData', (data: StudentData) => {
if (data.andrewID === userData.andrewID) {
setStudentData(data);
} else {
console.log('Student data id doesn\'t match andrewID');
}
});

// const handleVisibilityChange = () => {
// if (document.visibilityState === 'visible') {
// HomeService.getStudentData().then((res) => {
// if (res.status === 200 && res.data.andrewID === userData.andrewID) {
// setStudentData(res.data);
// }
// });
// }
// };
// document.addEventListener('visibilitychange', handleVisibilityChange);
const handleVisibilityChange = () => {
if (document.visibilityState === 'visible') {
HomeService.getStudentData().then((res) => {
if (res.status === 200 && res.data.andrewID === userData.andrewID) {
setStudentData(res.data);
} else if (res.data.andrewID === userData.andrewID) {
console.log('Student data id doesn\'t match andrewID');
}
ensureSocketConnected();
});
}
};
document.addEventListener('visibilitychange', handleVisibilityChange);
}
}, [userData.isAuthenticated]);

Expand Down
4 changes: 4 additions & 0 deletions client/src/http-common.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ httpInstance.interceptors.response.use(
return res;
},
(err) => {
if (!err.response) {
showErrorToast('Server error, no response');
return Promise.reject(err);
}
if (err.response.status >= 500) {
const message = 'Server Error: ' + err.response.data.message;
showErrorToast(message);
Expand Down
33 changes: 31 additions & 2 deletions client/src/services/SocketsService.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import io from 'socket.io-client';
import io, { Socket } from 'socket.io-client';
import Cookies from 'universal-cookie';

const cookies = new Cookies();

let socket;
let socket : Socket;
const SOCKET_URL = process.env.REACT_APP_PROTOCOL + '://' + process.env.REACT_APP_DOMAIN;
const SOCKET_PATH = process.env.REACT_APP_SOCKET_PATH;

Expand All @@ -18,6 +18,23 @@ export const initiateSocket = () => {
if (userCookies != null) {
socket.emit('authenticate', userCookies.access_token);
}

socket.on('disconnect', (reason, details) => {
console.log('Client disconnected', reason, details);

if (!socket.active) {
console.log('Inactive socket connection');
socket.connect();
}
});

socket.on('connect_error', (error) => {
console.log('Connection error', error.message);
if (!socket.active) {
console.log('Inactive socket connection');
socket.connect();
}
});
};

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

socket.off(emission);
};

export const ensureSocketConnected = () => {
if (!socket) {
console.log('No existing socket, initiating');
initiateSocket();
}

if (!socket.connected || !socket.active) {
console.log('Existing socket not connected or inactive, reconnecting');
socket.connect();
}
};
1 change: 0 additions & 1 deletion server/controllers/home.js
Original file line number Diff line number Diff line change
Expand Up @@ -1014,7 +1014,6 @@ exports.post_dismiss_message = function (req, res) {

ohq.dismissMessage(id);

sockets.dismiss_message(id);
emitNewStudentData(id);
emitNewAllStudents();

Expand Down
Loading