diff --git a/client/src/components/production-board-kanban/production-board-kanban.container.jsx b/client/src/components/production-board-kanban/production-board-kanban.container.jsx
index dd5d73d1e..643204469 100644
--- a/client/src/components/production-board-kanban/production-board-kanban.container.jsx
+++ b/client/src/components/production-board-kanban/production-board-kanban.container.jsx
@@ -47,7 +47,7 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser, subscriptionTyp
onError: (error) => console.error(`Error fetching jobs in production: ${error.message}`)
});
- const subscriptionEnabled = Websocket_Production?.treatment === "on";
+ const subscriptionEnabled = Websocket_Production?.treatment === "off";
const { data: updatedJobs } = useSubscription(
subscriptionType === "view" ? SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW : SUBSCRIPTION_JOBS_IN_PRODUCTION,
@@ -126,14 +126,19 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser, subscriptionTyp
}
};
+ const handleReconnect = () => {
+ //If we were disconnected from the board, we missed stuff. We need to refresh it entirely.
+ if (refetch) refetch();
+ };
// Listen for 'job-changed' events
socket.on("production-job-updated", handleJobUpdates);
-
+ socket.on("reconnect", handleReconnect);
// Clean up on unmount or when dependencies change
return () => {
socket.off("production-job-updated", handleJobUpdates);
+ socket.off("reconnect", handleReconnect);
};
- }, [subscriptionEnabled, socket, bodyshop, data, client]);
+ }, [subscriptionEnabled, socket, bodyshop, data, client, refetch]);
const filteredAssociationSettings = useMemo(() => {
return associationSettings?.associations[0] || null;
diff --git a/client/src/components/production-list-table/production-list-table.container.jsx b/client/src/components/production-list-table/production-list-table.container.jsx
index 3cb9d8b5e..fedcf3ff5 100644
--- a/client/src/components/production-list-table/production-list-table.container.jsx
+++ b/client/src/components/production-list-table/production-list-table.container.jsx
@@ -27,7 +27,7 @@ export default function ProductionListTableContainer({ bodyshop, subscriptionTyp
});
// Determine if subscription is enabled
- const subscriptionEnabled = Websocket_Production?.treatment === "on";
+ const subscriptionEnabled = Websocket_Production?.treatment === "off";
// Use GraphQL query
const { refetch, loading, data } = useQuery(QUERY_JOBS_IN_PRODUCTION, {
@@ -128,15 +128,20 @@ export default function ProductionListTableContainer({ bodyshop, subscriptionTyp
}
}
};
-
+ const handleReconnect = () => {
+ //If we were disconnected from the board, we missed stuff. We need to refresh it entirely.
+ if (refetch) refetch();
+ };
// Listen for 'production-job-updated' events
socket.on("production-job-updated", handleJobUpdates);
+ socket.on("reconnect", handleReconnect);
// Clean up on unmount or when dependencies change
return () => {
socket.off("production-job-updated", handleJobUpdates);
+ socket.off("reconnect", handleReconnect);
};
- }, [subscriptionEnabled, socket, bodyshop, client]);
+ }, [subscriptionEnabled, socket, bodyshop, client, refetch]);
// Functions to fetch updated job data
const getUpdatedJobData = async (jobId) => {
diff --git a/client/src/components/wss-status-display/wss-status-display.component.jsx b/client/src/components/wss-status-display/wss-status-display.component.jsx
new file mode 100644
index 000000000..40ff0e42a
--- /dev/null
+++ b/client/src/components/wss-status-display/wss-status-display.component.jsx
@@ -0,0 +1,18 @@
+import { connect } from "react-redux";
+import { GlobalOutlined } from "@ant-design/icons";
+import { createStructuredSelector } from "reselect";
+import React from "react";
+import { selectWssStatus } from "../../redux/application/application.selectors";
+const mapStateToProps = createStructuredSelector({
+ //currentUser: selectCurrentUser
+ wssStatus: selectWssStatus
+});
+const mapDispatchToProps = (dispatch) => ({
+ //setUserLanguage: language => dispatch(setUserLanguage(language))
+});
+export default connect(mapStateToProps, mapDispatchToProps)(WssStatusDisplay);
+
+export function WssStatusDisplay({ wssStatus }) {
+ console.log("🚀 ~ WssStatusDisplay ~ wssStatus:", wssStatus);
+ return ;
+}
diff --git a/client/src/contexts/SocketIO/useSocket.js b/client/src/contexts/SocketIO/useSocket.js
index e6b78748c..11577c906 100644
--- a/client/src/contexts/SocketIO/useSocket.js
+++ b/client/src/contexts/SocketIO/useSocket.js
@@ -1,7 +1,8 @@
import { useEffect, useState, useRef } from "react";
import SocketIO from "socket.io-client";
import { auth } from "../../firebase/firebase.utils";
-
+import { store } from "../../redux/store";
+import { setWssStatus } from "../../redux/application/application.actions";
const useSocket = (bodyshop) => {
const socketRef = useRef(null);
const [clientId, setClientId] = useState(null);
@@ -38,18 +39,22 @@ const useSocket = (bodyshop) => {
console.log("Socket connected:", socketInstance.id);
socketInstance.emit("join-bodyshop-room", bodyshop.id);
setClientId(socketInstance.id);
+ store.dispatch(setWssStatus("connected"))
};
const handleReconnect = (attempt) => {
console.log(`Socket reconnected after ${attempt} attempts`);
+ store.dispatch(setWssStatus("connected"))
};
const handleConnectionError = (err) => {
console.error("Socket connection error:", err);
+ store.dispatch(setWssStatus("error"))
};
const handleDisconnect = () => {
console.log("Socket disconnected");
+ store.dispatch(setWssStatus("disconnected"))
};
socketInstance.on("connect", handleConnect);
diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx
index e66f47398..46d66016f 100644
--- a/client/src/pages/manage/manage.page.component.jsx
+++ b/client/src/pages/manage/manage.page.component.jsx
@@ -25,6 +25,7 @@ import { selectBodyshop, selectInstanceConflict } from "../../redux/user/user.se
import UpdateAlert from "../../components/update-alert/update-alert.component";
import InstanceRenderManager from "../../utils/instanceRenderMgr.js";
import "./manage.page.styles.scss";
+import WssStatusDisplayComponent from "../../components/wss-status-display/wss-status-display.component.jsx";
const JobsPage = lazy(() => import("../jobs/jobs.page"));
@@ -604,6 +605,7 @@ export function Manage({ conflict, bodyshop }) {
}}
>
+
{`${InstanceRenderManager({
imex: t("titles.imexonline"),
diff --git a/client/src/redux/application/application.actions.js b/client/src/redux/application/application.actions.js
index 7c5485ac5..c8246022b 100644
--- a/client/src/redux/application/application.actions.js
+++ b/client/src/redux/application/application.actions.js
@@ -67,3 +67,7 @@ export const setUpdateAvailable = (isUpdateAvailable) => ({
type: ApplicationActionTypes.SET_UPDATE_AVAILABLE,
payload: isUpdateAvailable
});
+export const setWssStatus = (status) => ({
+ type: ApplicationActionTypes.SET_WSS_STATUS,
+ payload: status
+});
diff --git a/client/src/redux/application/application.reducer.js b/client/src/redux/application/application.reducer.js
index 421403f19..21878e52a 100644
--- a/client/src/redux/application/application.reducer.js
+++ b/client/src/redux/application/application.reducer.js
@@ -3,6 +3,7 @@ import ApplicationActionTypes from "./application.types";
const INITIAL_STATE = {
loading: false,
online: true,
+ wssStatus: "disconnected",
updateAvailable: false,
breadcrumbs: [],
recentItems: [],
@@ -87,6 +88,9 @@ const applicationReducer = (state = INITIAL_STATE, action) => {
case ApplicationActionTypes.SET_PROBLEM_JOBS: {
return { ...state, problemJobs: action.payload };
}
+ case ApplicationActionTypes.SET_WSS_STATUS: {
+ return { ...state, wssStatus: action.payload };
+ }
default:
return state;
}
diff --git a/client/src/redux/application/application.selectors.js b/client/src/redux/application/application.selectors.js
index d81699522..a4f434cfe 100644
--- a/client/src/redux/application/application.selectors.js
+++ b/client/src/redux/application/application.selectors.js
@@ -22,3 +22,4 @@ export const selectJobReadOnly = createSelector([selectApplication], (applicatio
export const selectOnline = createSelector([selectApplication], (application) => application.online);
export const selectProblemJobs = createSelector([selectApplication], (application) => application.problemJobs);
export const selectUpdateAvailable = createSelector([selectApplication], (application) => application.updateAvailable);
+export const selectWssStatus = createSelector([selectApplication], (application) => application.wssStatus);
diff --git a/client/src/redux/application/application.types.js b/client/src/redux/application/application.types.js
index 9b95dd6ee..1672cda0b 100644
--- a/client/src/redux/application/application.types.js
+++ b/client/src/redux/application/application.types.js
@@ -12,6 +12,7 @@ const ApplicationActionTypes = {
SET_ONLINE_STATUS: "SET_ONLINE_STATUS",
INSERT_AUDIT_TRAIL: "INSERT_AUDIT_TRAIL",
SET_PROBLEM_JOBS: "SET_PROBLEM_JOBS",
- SET_UPDATE_AVAILABLE: "SET_UPDATE_AVAILABLE"
+ SET_UPDATE_AVAILABLE: "SET_UPDATE_AVAILABLE",
+ SET_WSS_STATUS: "SET_WSS_STATUS"
};
export default ApplicationActionTypes;