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 6182b3ffb..dd5d73d1e 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
@@ -3,7 +3,7 @@ import { useApolloClient, useQuery, useSubscription } from "@apollo/client";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import {
- GET_JOB_BY_PK,
+ QUERY_EXACT_JOB_IN_PRODUCTION,
QUERY_JOBS_IN_PRODUCTION,
SUBSCRIPTION_JOBS_IN_PRODUCTION,
SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW
@@ -100,7 +100,7 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser, subscriptionTyp
query: QUERY_JOBS_IN_PRODUCTION,
data: {
jobs: existingJobs.map((job) =>
- job.id === jobId ? { ...existingJob, ...jobChangedData, __typename: "Job" } : job
+ job.id === jobId ? { ...existingJob, ...jobChangedData, __typename: "jobs" } : job
)
}
});
@@ -108,7 +108,7 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser, subscriptionTyp
// If the job doesn't exist, fetch it from the server and then add it to the cache
try {
const { data: jobData } = await client.query({
- query: GET_JOB_BY_PK,
+ query: QUERY_EXACT_JOB_IN_PRODUCTION,
variables: { id: jobId },
fetchPolicy: "network-only"
});
@@ -117,7 +117,7 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser, subscriptionTyp
client.writeQuery({
query: QUERY_JOBS_IN_PRODUCTION,
data: {
- jobs: [...existingJobs, { ...jobData.job, __typename: "Job" }]
+ jobs: [...existingJobs, { ...jobData.job, __typename: "jobs" }]
}
});
} catch (error) {
@@ -127,11 +127,11 @@ function ProductionBoardKanbanContainer({ bodyshop, currentUser, subscriptionTyp
};
// Listen for 'job-changed' events
- socket.on("job-updated", handleJobUpdates);
+ socket.on("production-job-updated", handleJobUpdates);
// Clean up on unmount or when dependencies change
return () => {
- socket.off("job-updated", handleJobUpdates);
+ socket.off("production-job-updated", handleJobUpdates);
};
}, [subscriptionEnabled, socket, bodyshop, data, client]);
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 9f564bde7..3cb9d8b5e 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
@@ -1,5 +1,5 @@
import { useApolloClient, useQuery, useSubscription } from "@apollo/client";
-import React, { useEffect, useState } from "react";
+import React, { useContext, useEffect, useState } from "react";
import {
QUERY_EXACT_JOB_IN_PRODUCTION,
QUERY_EXACT_JOBS_IN_PRODUCTION,
@@ -9,19 +9,42 @@ import {
} from "../../graphql/jobs.queries";
import ProductionListTable from "./production-list-table.component";
import _ from "lodash";
+import { useSplitTreatments } from "@splitsoftware/splitio-react";
+import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
-export default function ProductionListTableContainer({ subscriptionType = "direct" }) {
+export default function ProductionListTableContainer({ bodyshop, subscriptionType = "direct" }) {
+ const client = useApolloClient();
+ const { socket } = useContext(SocketContext);
+ const [joblist, setJoblist] = useState([]);
+
+ // Get Split treatment
+ const {
+ treatments: { Websocket_Production }
+ } = useSplitTreatments({
+ attributes: {},
+ names: ["Websocket_Production"],
+ splitKey: bodyshop && bodyshop.imexshopid
+ });
+
+ // Determine if subscription is enabled
+ const subscriptionEnabled = Websocket_Production?.treatment === "on";
+
+ // Use GraphQL query
const { refetch, loading, data } = useQuery(QUERY_JOBS_IN_PRODUCTION, {
pollInterval: 3600000,
fetchPolicy: "network-only",
nextFetchPolicy: "network-only"
});
- const client = useApolloClient();
- const [joblist, setJoblist] = useState([]);
+
+ // Use GraphQL subscription when subscription is enabled
const { data: updatedJobs } = useSubscription(
- subscriptionType === "view" ? SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW : SUBSCRIPTION_JOBS_IN_PRODUCTION
+ subscriptionType === "view" ? SUBSCRIPTION_JOBS_IN_PRODUCTION_VIEW : SUBSCRIPTION_JOBS_IN_PRODUCTION,
+ {
+ skip: !subscriptionEnabled
+ }
);
+ // Update joblist when data changes
useEffect(() => {
if (!(data && data.jobs)) return;
setJoblist(
@@ -31,34 +54,99 @@ export default function ProductionListTableContainer({ subscriptionType = "direc
);
}, [data]);
+ // Handle updates from GraphQL subscription
useEffect(() => {
- if (!updatedJobs || joblist.length === 0) return;
+ if (subscriptionEnabled) {
+ if (!updatedJobs || joblist.length === 0) return;
- const jobDiff = _.differenceWith(
- joblist,
- updatedJobs.jobs,
- (a, b) => a.id === b.id && a.updated_at === b.updated_at
- );
+ const jobDiff = _.differenceWith(
+ joblist,
+ updatedJobs.jobs,
+ (a, b) => a.id === b.id && a.updated_at === b.updated_at
+ );
- if (jobDiff.length > 1) {
- getUpdatedJobsData(jobDiff.map((j) => j.id));
- } else if (jobDiff.length === 1) {
- jobDiff.forEach((job) => {
- getUpdatedJobData(job.id);
- });
+ if (jobDiff.length > 1) {
+ getUpdatedJobsData(jobDiff.map((j) => j.id));
+ } else if (jobDiff.length === 1) {
+ jobDiff.forEach((job) => {
+ getUpdatedJobData(job.id);
+ });
+ }
+
+ setJoblist(updatedJobs.jobs);
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [updatedJobs, subscriptionEnabled]);
+
+ // Handle updates from Socket.IO when subscription is disabled
+ useEffect(() => {
+ if (subscriptionEnabled || !socket || !bodyshop || !bodyshop.id) {
+ return;
}
- setJoblist(updatedJobs.jobs);
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [updatedJobs]);
+ const handleJobUpdates = async (jobChangedData) => {
+ const jobId = jobChangedData.id;
+ // Access the existing cache for QUERY_JOBS_IN_PRODUCTION
+ const existingJobsCache = client.readQuery({
+ query: QUERY_JOBS_IN_PRODUCTION
+ });
+
+ const existingJobs = existingJobsCache?.jobs || [];
+
+ // Check if the job already exists in the cached jobs
+ const existingJob = existingJobs.find((job) => job.id === jobId);
+
+ if (existingJob) {
+ // If the job exists, we update the cache without making any additional queries
+ client.writeQuery({
+ query: QUERY_JOBS_IN_PRODUCTION,
+ data: {
+ jobs: existingJobs.map((job) =>
+ job.id === jobId ? { ...existingJob, ...jobChangedData, __typename: "jobs" } : job
+ )
+ }
+ });
+ } else {
+ // If the job doesn't exist, fetch it from the server and then add it to the cache
+ try {
+ const { data: jobData } = await client.query({
+ query: QUERY_EXACT_JOB_IN_PRODUCTION,
+ variables: { id: jobId },
+ fetchPolicy: "network-only"
+ });
+
+ // Add the job to the existing cached jobs
+ client.writeQuery({
+ query: QUERY_JOBS_IN_PRODUCTION,
+ data: {
+ jobs: [...existingJobs, { ...jobData.job, __typename: "jobs" }]
+ }
+ });
+ } catch (error) {
+ console.error(`Error fetching job ${jobId}: ${error.message}`);
+ }
+ }
+ };
+
+ // Listen for 'production-job-updated' events
+ socket.on("production-job-updated", handleJobUpdates);
+
+ // Clean up on unmount or when dependencies change
+ return () => {
+ socket.off("production-job-updated", handleJobUpdates);
+ };
+ }, [subscriptionEnabled, socket, bodyshop, client]);
+
+ // Functions to fetch updated job data
const getUpdatedJobData = async (jobId) => {
- client.query({
+ await client.query({
query: QUERY_EXACT_JOB_IN_PRODUCTION,
- variables: { id: jobId }
+ variables: { id: jobId },
+ fetchPolicy: "network-only"
});
};
- const getUpdatedJobsData = async (jobIds) => {
+ const getUpdatedJobsData = (jobIds) => {
client.query({
query: QUERY_EXACT_JOBS_IN_PRODUCTION,
variables: { ids: jobIds }
diff --git a/client/src/pages/production-list/production-list.component.jsx b/client/src/pages/production-list/production-list.component.jsx
index 177108f6d..aa6e4e1b1 100644
--- a/client/src/pages/production-list/production-list.component.jsx
+++ b/client/src/pages/production-list/production-list.component.jsx
@@ -26,7 +26,7 @@ export function ProductionListComponent({ bodyshop }) {
return (
<>
-
+
>
);
}
diff --git a/server/job/job-updated.js b/server/job/job-updated.js
index bec619837..f218f83bc 100644
--- a/server/job/job-updated.js
+++ b/server/job/job-updated.js
@@ -24,7 +24,7 @@ const jobUpdated = async (req, res) => {
const bodyshopID = updatedJob.shopid;
// Emit the job-updated event only to the room corresponding to the bodyshop
- ioRedis.to(ioHelpers.getBodyshopRoom(bodyshopID)).emit("job-updated", updatedJob);
+ ioRedis.to(ioHelpers.getBodyshopRoom(bodyshopID)).emit("production-job-updated", updatedJob);
return res.json({ message: "Job updated and event emitted" });
};