Skip to content
Snippets Groups Projects
Commit cb872300 authored by Jörn Künsemöller's avatar Jörn Künsemöller
Browse files

TMSS-2688: add websocket updates to weekview

parent 06e04078
No related branches found
No related tags found
1 merge request!1195TMSS-2688: websockets
......@@ -69,6 +69,7 @@
"react-tooltip": "^4.5.1",
"react-transition-group": "^2.5.1",
"react-websocket": "^2.1.0",
"react-use-websocket": "^3.0.0",
"reactstrap": "^9.2.0",
"redux": "^4.2.1",
"replace-in-file": "^7.0.1",
......
......@@ -62,6 +62,7 @@
"react-tooltip": "^4.5.1",
"react-transition-group": "^2.5.1",
"react-websocket": "^2.1.0",
"react-use-websocket": "^3.0.0",
"reactstrap": "^9.2.0",
"redux": "^4.2.1",
"replace-in-file": "^7.0.1",
......
......@@ -46,9 +46,14 @@ import {
fetchSchedulerStatuses,
fetchSunTimings, fetchSUSummaryInformation,
fetchTimelineData,
fetchUserPermissions
fetchUserPermissions,
} from "./data/week.view.data";
import useWebSocket from 'react-use-websocket';
import _ from 'lodash';
import ScheduleService from "../../services/schedule.service";
import ReservationService from "../../services/reservation.service";
function getTimelineHeaders(headerSettings) {
return <TimelineHeaders className="sticky">
<SidebarHeader>
......@@ -243,6 +248,169 @@ export default function WeekView() {
}
}, [summaryItem]);
// websocket handling
/**
* Function to call wnen websocket is connected
*/
function onConnect() {
try{
console.log("WS Opened");
const userDets = localStorage.getItem("user");
if (userDets) {
sendMessage(JSON.stringify({"token": JSON.parse(userDets).websocket_token}));
console.log("Auth token submitted");
}
}catch (err) {
console.log('err',err)
}
}
/**
* Function to call when websocket is disconnected
*/
function onDisconnect() {
console.log("WS Closed")
}
/**
* Handles the message received through websocket
* @param {String} data - String of JSON data
*/
function handleData(event) {
const jsonData = JSON.parse(event?.data) || {};
console.log('received websocket data:', jsonData)
switch (jsonData.object_type) {
case 'scheduling_unit_blueprint': {
switch (jsonData.action) {
case 'delete': {
console.log('ws delete SU');
const schedulingUnits = data.schedulingUnits
_.remove(schedulingUnits, function (su) { return su.id === jsonData.object_details.id});
setData(prevData => ({
...prevData,
schedulingUnits: schedulingUnits
}))
if (summaryItem?.id === jsonData.object_details.id) {
setSummaryItem({});
}
break;
}
case 'update': {
console.log("ws update SU");
setData(prevData => ({
...prevData,
schedulingUnits: prevData.schedulingUnits.map(
unit => unit.id === jsonData.object_details.id? {...unit, ...jsonData.object_details}: unit
)
}));
if (summaryItem?.id === jsonData.object_details.id) {
// Note: we could also update details directly so we don't need to fetch again.
// However, we would have to send full deltas via websocket instead of the subset that is
// relevant for the timeline (like id, timestamps, and status).
// e.g.
//
// setSummarySettings(prevState => ({
// ...prevState,
// schedulingUnitItem: {...prevState.schedulingUnitItem, ...jsonData.object_details}
// }));
//
// Instead, trigger a full refresh of the details panel:
setSummaryItem({id: jsonData.object_details.id, type: "SCHEDULE"});
}
break;
}
case 'create': {
console.log("ws create SU");
// the ws message only contains a subset of the details we need, so fetch the full set
return async (dispatch) => { // todo: async here problematic?
const response = await ScheduleService.getTimelineSlimBlueprints(undefined, undefined, jsonData.object_details.id); // todo: check time
console.log('response:', response);
setData(prevData => ({
...prevData,
schedulingUnits: prevData.schedulingUnits.concat(response.results)
}));
};
break;
}
default: { break; }
}
break;
}
case 'reservation': {
switch (jsonData.action) {
case 'delete': {
console.log('ws delete reservation');
const reservations = data.reservations
_.remove(reservations, function (res) { return res.id === jsonData.object_details.id});
setData(prevData => ({
...prevData,
reservations: reservations
}))
if (summaryItem?.id === jsonData.object_details.id) {
setSummaryItem({});
}
break;
}
case 'update': {
console.log("ws update reservation");
setData(prevData => ({
...prevData,
reservations: prevData.reservations.map(
res => res.id === jsonData.object_details.id? {...res, ...jsonData.object_details}: res
),
}));
if (summaryItem?.id === jsonData.object_details.id) {
// Note: this triggers a full fetch again to get all details (see SU above).
setSummaryItem({id: jsonData.object_details.id, type: "RESERVATION"});
}
break;
}
case 'create': {
console.log("ws create reservation");
const shouldFetchReservations = getStore(UIConstants.STORE_KEY_TIMELINE).reservationsToggle;
if (shouldFetchReservations) {
// the ws message only contains a subset of the details we need, so fetch the full set
return async (dispatch) => { // todo: async here problematic?
const response = await ReservationService.getTimelineReservations(undefined, undefined, jsonData.object_details.id); // todo: check time
console.log('response:', response);
setData(prevData => ({
...prevData,
reservations: prevData.reservations.concat(response.results)
}));
};
}
break;
}
default: { break; }
}
break;
}
default: { break; }
}
}
// debug logging whenever the SU and reservation data gets updated
useEffect(() => {
console.log('data update:', data);
}, [data])
// websocket hook that opens and allows interaction via the wss connection
const {
sendMessage,
sendJsonMessage,
lastMessage,
lastJsonMessage,
readyState,
getWebSocket,
} = useWebSocket(process.env.REACT_APP_WEBSOCKET_URL, {
onOpen: () => onConnect(),
onClose: () => onDisconnect(),
onMessage: (event) => handleData(event),
onError: (event) => { console.error(event); },
shouldReconnect: (closeEvent) => true,
});
return <div>
<div className={(isLoading ? "" : "hide-element")}>
<ProgressBar className={isLoading ? "" : "hide-element"} mode="indeterminate"
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment