[WIFI-13203] Added new device tracking chart

Signed-off-by: Charles <charles.bourque96@gmail.com>
This commit is contained in:
Charles
2023-12-05 13:18:48 +00:00
parent ddb148b2bd
commit ba318f4537
8 changed files with 42 additions and 69 deletions

2
.env
View File

@@ -1 +1 @@
VITE_UCENTRALSEC_URL="https://openwifi-owls.wlan.local:16001" VITE_UCENTRALSEC_URL="https://ucentral.dpaas.arilia.com:16001"

4
package-lock.json generated
View File

@@ -1,12 +1,12 @@
{ {
"name": "owls-ui", "name": "owls-ui",
"version": "3.0.0(6)", "version": "3.0.0(7)",
"lockfileVersion": 2, "lockfileVersion": 2,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "owls-ui", "name": "owls-ui",
"version": "3.0.0(6)", "version": "3.0.0(7)",
"license": "BSD-3-Clause", "license": "BSD-3-Clause",
"dependencies": { "dependencies": {
"@chakra-ui/icons": "^2.0.18", "@chakra-ui/icons": "^2.0.18",

View File

@@ -1,6 +1,6 @@
{ {
"name": "owls-ui", "name": "owls-ui",
"version": "3.0.0(6)", "version": "3.0.0(7)",
"description": "", "description": "",
"private": true, "private": true,
"main": "index.tsx", "main": "index.tsx",

View File

@@ -33,10 +33,9 @@ const SimulatorSocketContext = React.createContext<SimulatorSocketContextReturn>
export const SimulatorSocketProvider = ({ children }: { children: React.ReactElement }) => { export const SimulatorSocketProvider = ({ children }: { children: React.ReactElement }) => {
const { token, isUserLoaded } = useAuth(); const { token, isUserLoaded } = useAuth();
const { addMessage, isOpen, setIsOpen, webSocket, onStartWebSocket } = useSimulatorStore((state) => ({ const { addMessage, webSocket, onStartWebSocket } = useSimulatorStore((state) => ({
addMessage: state.addMessage, addMessage: state.addMessage,
setIsOpen: state.setWebSocketOpen, isOpen: state.webSocket?.readyState === WebSocket.OPEN,
isOpen: state.isWebSocketOpen,
webSocket: state.webSocket, webSocket: state.webSocket,
onStartWebSocket: state.startWebSocket, onStartWebSocket: state.startWebSocket,
})); }));
@@ -64,9 +63,6 @@ export const SimulatorSocketProvider = ({ children }: { children: React.ReactEle
if (isUserLoaded && axiosOwls?.defaults?.baseURL !== axiosSec?.defaults?.baseURL) { if (isUserLoaded && axiosOwls?.defaults?.baseURL !== axiosSec?.defaults?.baseURL) {
onStartWebSocket(token ?? ''); onStartWebSocket(token ?? '');
} }
const wsCurrent = webSocket;
return () => wsCurrent?.close();
}, [isUserLoaded]); }, [isUserLoaded]);
// useEffect for generating global notifications // useEffect for generating global notifications
@@ -80,33 +76,6 @@ export const SimulatorSocketProvider = ({ children }: { children: React.ReactEle
}; };
}, [webSocket]); }, [webSocket]);
useEffect(() => {
const handleVisibilityChange = () => {
let timeoutId;
if (webSocket) {
if (document.visibilityState === 'hidden') {
timeoutId = setTimeout(() => {
if (webSocket) webSocket.onclose = () => {};
webSocket?.close();
setIsOpen(false);
}, 5000);
} else {
clearTimeout(timeoutId);
if (!isOpen && isUserLoaded && axiosOwls?.defaults?.baseURL !== axiosSec?.defaults?.baseURL) {
onStartWebSocket(token ?? '');
}
}
}
};
document.addEventListener('visibilitychange', handleVisibilityChange);
return () => {
document.removeEventListener('visibilitychange', handleVisibilityChange);
};
}, [webSocket, isOpen]);
const values: SimulatorSocketContextReturn = useMemo(() => ({}), []); const values: SimulatorSocketContextReturn = useMemo(() => ({}), []);
return <SimulatorSocketContext.Provider value={values}>{children}</SimulatorSocketContext.Provider>; return <SimulatorSocketContext.Provider value={values}>{children}</SimulatorSocketContext.Provider>;

View File

@@ -1,3 +1,4 @@
import ReconnectingWebSocket from 'reconnecting-websocket';
import create from 'zustand'; import create from 'zustand';
import { SocketEventCallback, WebSocketNotification } from './utils'; import { SocketEventCallback, WebSocketNotification } from './utils';
import { axiosOwls } from 'constants/axiosInstances'; import { axiosOwls } from 'constants/axiosInstances';
@@ -32,12 +33,9 @@ export type SimulatorStoreState = {
addMessage: (message: WebSocketNotification) => void; addMessage: (message: WebSocketNotification) => void;
eventListeners: SocketEventCallback[]; eventListeners: SocketEventCallback[];
addEventListeners: (callback: SocketEventCallback[]) => void; addEventListeners: (callback: SocketEventCallback[]) => void;
webSocket?: WebSocket; webSocket?: ReconnectingWebSocket;
websocketTimer: NodeJS.Timeout | null;
send: (str: string) => void; send: (str: string) => void;
startWebSocket: (token: string, tries?: number) => void; startWebSocket: (token: string, tries?: number) => void;
isWebSocketOpen: boolean;
setWebSocketOpen: (isOpen: boolean) => void;
currentSimulationsData: Record<string, SimulationOperationStatus[]>; currentSimulationsData: Record<string, SimulationOperationStatus[]>;
}; };
@@ -128,38 +126,47 @@ export const useSimulatorStore = create<SimulatorStoreState>((set, get) => ({
eventListeners: [] as SocketEventCallback[], eventListeners: [] as SocketEventCallback[],
addEventListeners: (events: SocketEventCallback[]) => addEventListeners: (events: SocketEventCallback[]) =>
set((state) => ({ eventListeners: [...state.eventListeners, ...events] })), set((state) => ({ eventListeners: [...state.eventListeners, ...events] })),
isWebSocketOpen: false,
setWebSocketOpen: (isOpen: boolean) => set({ isWebSocketOpen: isOpen }),
send: (str: string) => { send: (str: string) => {
const ws = get().webSocket; const ws = get().webSocket;
if (ws) ws.send(str); if (ws) ws.send(str);
}, },
websocketTimer: null,
startWebSocket: (token: string) => { startWebSocket: (token: string) => {
set({ const ws = get().webSocket;
webSocket: new WebSocket(
if (ws) {
// Close the previous websocket connection and remove it
ws.close();
set({ webSocket: undefined });
}
const newWs = new ReconnectingWebSocket(
`${ `${
axiosOwls?.defaults?.baseURL ? axiosOwls.defaults.baseURL.replace('https', 'wss').replace('http', 'ws') : '' axiosOwls?.defaults?.baseURL ? axiosOwls.defaults.baseURL.replace('https', 'wss').replace('http', 'ws') : ''
}/ws`, }/ws`,
), undefined,
{
startClosed: true,
},
);
newWs.removeEventListener('open', (e) => {
e.target?.send(`token:${token}`);
}); });
const ws = get().webSocket; newWs.addEventListener('open', (e) => {
if (ws) { e.target?.send(`token:${token}`);
ws.onopen = () => { });
const timer = get().websocketTimer; newWs.reconnect();
if (timer) clearTimeout(timer);
set({ isWebSocketOpen: true, websocketTimer: null });
ws.send(`token:${token}`);
};
ws.onclose = () => {
const timer = get().websocketTimer;
if (timer) clearTimeout(timer);
set({ set({
isWebSocketOpen: false, webSocket: newWs,
websocketTimer: setInterval(() => get().startWebSocket(token), 60 * 1000), });
// Add global event listener, on window focus, call startWebSocket
window.removeEventListener('focus', () => {
get().startWebSocket(token);
});
window.addEventListener('focus', () => {
get().startWebSocket(token);
}); });
};
}
}, },
currentSimulationsData: {}, currentSimulationsData: {},
})); }));

View File

@@ -30,7 +30,6 @@ const DevicesChart = ({ statusId }: Props) => {
const { colorMode } = useColorMode(); const { colorMode } = useColorMode();
const currentSimulationData = useSimulatorStore( const currentSimulationData = useSimulatorStore(
React.useCallback((state) => state.currentSimulationsData[statusId] ?? [], [statusId]), React.useCallback((state) => state.currentSimulationsData[statusId] ?? [], [statusId]),
(oldState, newState) => oldState?.length === newState?.length,
); );
const data = React.useMemo(() => { const data = React.useMemo(() => {

View File

@@ -28,7 +28,6 @@ const SingleSimulationCurrentlyRunning = ({
const { t } = useTranslation(); const { t } = useTranslation();
const currentStatus = useSimulatorStore( const currentStatus = useSimulatorStore(
React.useCallback((state) => state.currentSimulationsData[status.id] ?? [], [status.id]), React.useCallback((state) => state.currentSimulationsData[status.id] ?? [], [status.id]),
(oldState, newState) => oldState?.length === newState?.length,
); );
const latestStatus = currentStatus?.[currentStatus.length - 1]?.rawData ?? status; const latestStatus = currentStatus?.[currentStatus.length - 1]?.rawData ?? status;
@@ -55,7 +54,7 @@ const SingleSimulationCurrentlyRunning = ({
<Heading size="sm" my="auto"> <Heading size="sm" my="auto">
{t('common.started')} {t('common.started')}
</Heading> </Heading>
<FormattedDate key={currentStatus.length} date={latestStatus.startTime} /> <FormattedDate key={JSON.stringify(status)} date={latestStatus.startTime} />
</Box> </Box>
<Box> <Box>
<Heading size="sm" my="auto"> <Heading size="sm" my="auto">

View File

@@ -42,7 +42,6 @@ const TxRxChart = ({ statusId }: Props) => {
const { colorMode } = useColorMode(); const { colorMode } = useColorMode();
const currentSimulationData = useSimulatorStore( const currentSimulationData = useSimulatorStore(
React.useCallback((state) => state.currentSimulationsData[statusId] ?? [], [statusId]), React.useCallback((state) => state.currentSimulationsData[statusId] ?? [], [statusId]),
(oldState, newState) => oldState?.length === newState?.length,
); );
const { data, unit } = React.useMemo(() => { const { data, unit } = React.useMemo(() => {