import { createContext, useEffect, useRef, useState } from "react"; import { useNavigate } from "react-router-dom"; /** * constants */ export const Constants = { COLORS: { PRIMARY: "#e67e22", SECONDARY: "#9b59b6", }, TEXT_EMPTY_PLACEHOLDER: "-/-", API_ADDRESS: "http://localhost:8080/v1", WS_ADDRESS: "ws://localhost:8080/ws", ROUTE_PATHS: { GROUP_TASKS: "/group-tasks", GROUP_TASKS_VIEW: "/group-tasks/", }, GROUP_TASKS_STATUS: { FINISHED: 1, RUNNING: 2, CANCELED: 3, FAILED: 4, INPUT_REQUIRED: 5, }, }; /** * user session */ export function UseUserSession() { const getUserSession = () => { return JSON.parse(localStorage.getItem("session")); }; const [userSession, setUserSession] = useState(getUserSession()); const saveUserSession = (session) => { setUserSession(session); if (session === undefined) { localStorage.removeItem("session"); } else { localStorage.setItem("session", JSON.stringify(session)); } }; return { setUserSession: saveUserSession, userSession, }; } /** * websocket */ let l = "loading..."; let webSocketContextPreview = { User: { Username: l, Email: l, }, ConnectionBadgeStatus: "error", ConnectedWebSocketUsersCount: 0, CategoryGroups: [], GroupTasks: [], GroupTasksSteps: [], }; export const WebSocketContext = createContext(webSocketContextPreview); // commands received from the backend server const ReceivedMessagesCommands = { InitUserSocketConnection: 1, UpdateConnectedUsers: 2, NewGroupTaskStarted: 3, NewGroupTaskStep: 4, UpdateGroupTaskStep: 5, UpdateGroupTask: 6, }; // commands sent to the backend server export const SentMessagesCommands = { StartGroupTasks: 1, TaskFailedTryAgainRunTaskStep: 2, }; export function WebSocketProvider({ children, userSession, setUserSession }) { const [isReady, setIsReady] = useState(false); const [connectionBadgeStatus, setConnectionBadgeStatus] = useState( webSocketContextPreview.ConnectionBadgeStatus ); const [connectedWebSocketUsersCount, setConnectedWebSocketUsersCount] = useState(0); const [user, setUser] = useState(webSocketContextPreview.User); const [categoryGroups, setCategoryGroups] = useState( webSocketContextPreview.CategoryGroups ); // these are all group tasks that are then filtered and displayed in the respective tables for the category const [groupTasks, setGroupTasks] = useState([]); const [groupTasksSteps, setGroupTasksSteps] = useState([]); const navigate = useNavigate(); const StartGroupTasksOpenModalRememberIdRef = useRef(null); let socket = null; const ws = useRef(null); const connect = () => { socket = new WebSocket(Constants.WS_ADDRESS + "?auth=" + userSession); ws.current = socket; socket.onopen = () => { console.log("connected"); setConnectionBadgeStatus("success"); setIsReady(true); }; socket.onmessage = (event) => { const data = JSON.parse(event.data); console.log("received message", data); const cmd = data.Cmd; const body = data.Body; switch (cmd) { case ReceivedMessagesCommands.InitUserSocketConnection: setUser(body.User); setCategoryGroups(body.CategoryGroups); setGroupTasks(body.GroupTasks); setGroupTasksSteps(body.GroupTasksSteps); break; case ReceivedMessagesCommands.UpdateConnectedUsers: setConnectedWebSocketUsersCount(body); break; case ReceivedMessagesCommands.NewGroupTaskStarted: setGroupTasks((arr) => [...arr, body]); if ( body.RememberId === StartGroupTasksOpenModalRememberIdRef.current ) { navigate(`${Constants.ROUTE_PATHS.GROUP_TASKS}/${body.Id}`); } break; case ReceivedMessagesCommands.NewGroupTaskStep: setGroupTasksSteps((arr) => [...arr, body]); break; case ReceivedMessagesCommands.UpdateGroupTaskStep: setGroupTasksSteps((arr) => { const newArr = [...arr]; newArr[arr.findIndex((arr1) => arr1.Id === body.Id)] = body; return newArr; }); break; case ReceivedMessagesCommands.UpdateGroupTask: setGroupTasks((arr) => { const newArr = [...arr]; newArr[arr.findIndex((arr1) => arr1.Id === body.Id)] = body; return newArr; }); break; default: console.log("unknown command", cmd); break; } }; socket.onclose = (event) => { setIsReady(false); setConnectionBadgeStatus("error"); console.log("closed", event); // custom code defined by the backend server if (event.code === 4001) { setUserSession(); window.location.href = "/"; return; } if (event.reason.code === 1005) return; console.log("reconnecting..."); setTimeout(() => connect(), 1000); }; }; useEffect(() => { connect(); return () => socket.close(); }, []); const SendSocketMessage = (cmd, body) => { if (isReady) { ws.current.send(JSON.stringify({ Cmd: cmd, Body: body })); } else { console.log("websocket not ready"); } }; return ( {children} ); } export function FormatDatetime(datetime) { return new Date(datetime).toLocaleString("de-DE"); }