feature/IO-2924-Refactor-Production-Board-For-Sockets - Checkpoint

Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
Dave Richer
2024-09-12 17:45:20 -04:00
parent 2f3056b49b
commit 08e1cf80c2
4 changed files with 80 additions and 53 deletions

View File

@@ -58,17 +58,40 @@ function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTr
const updatedLanes = cloneDeep(prevBoardLanes.lanes);
// Find the lane containing the card with the updated job ID
const sourceLane = updatedLanes.find((lane) => lane.cards.some((card) => card.id === updatedJob.id));
let sourceLane = updatedLanes.find((lane) => lane.cards.some((card) => card.id === updatedJob.id));
if (!sourceLane) {
console.error("Source lane not found for the updated job.");
return prevBoardLanes; // Return the previous state if no source lane is found
console.log("Card not found in any lane. Checking for valid status to add it.");
// Find the target lane based on the new status if the card does not exist
const targetLane = updatedLanes.find((lane) => lane.id === updatedJob.status);
if (targetLane && updatedJob.isInProduction) {
// Check if job is in production and status is valid
console.log(`Adding card to lane ${targetLane.title}`);
// Add the new card to the target lane
const newCard = {
id: updatedJob.id,
metadata: { ...updatedJob }
};
targetLane.cards.push(newCard);
// Update the lane title with the new card count
targetLane.title = `${targetLane.title.split(" ")[0]} (${targetLane.cards.length})`;
return { lanes: updatedLanes }; // Return early since the card is added
} else {
console.error("No valid lane or status to add the job to.");
return prevBoardLanes; // Return the previous state if no valid status or lane
}
}
// Find the card in the source lane
// If the card exists, find it in the source lane
const cardIndex = sourceLane.cards.findIndex((card) => card.id === updatedJob.id);
const currentCard = sourceLane.cards[cardIndex];
// If we somehow can't find the card, return
if (!currentCard) {
console.error("Card not found for the updated job.");
return prevBoardLanes; // Return the previous state if the card is not found
@@ -76,7 +99,6 @@ function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTr
// Iterate through the properties of updatedJob and update the corresponding values in currentCard.metadata
Object.keys(updatedJob).forEach((key) => {
// Ensure the field exists in currentCard.metadata before updating it
if (key in currentCard.metadata && currentCard.metadata[key] !== updatedJob[key]) {
console.log(`Updating ${key} from ${currentCard.metadata[key]} to ${updatedJob[key]}`);
currentCard.metadata[key] = updatedJob[key];
@@ -99,10 +121,7 @@ function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTr
// Find the target lane based on the new status
const targetLane = updatedLanes.find((lane) => lane.id === updatedJob.status);
if (targetLane) {
// Move the card to the target lane and update its data
targetLane.cards.push({ ...cardToMove, metadata: { ...currentCard.metadata } });
// Update the lane titles with the new card count
sourceLane.title = `${sourceLane.title.split(" ")[0]} (${sourceLane.cards.length})`;
targetLane.title = `${targetLane.title.split(" ")[0]} (${targetLane.cards.length})`;
} else {
@@ -112,12 +131,8 @@ function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTr
// Case 2: Only data has changed
else if (isDataChanged && !isLaneChanged) {
console.log("Case 2: Only Data Changed");
// Update the card's metadata in place
sourceLane.cards[cardIndex] = { ...currentCard, metadata: { ...currentCard.metadata } };
// Force a shallow change in the source lane to trigger re-render
sourceLane.cards = [...sourceLane.cards];
// sourceLane.cards = [...sourceLane.cards]; // Force shallow change for re-render
}
// Case 3: Only the lane has changed
else if (!isDataChanged && isLaneChanged) {
@@ -129,10 +144,7 @@ function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTr
// Find the target lane based on the new status
const targetLane = updatedLanes.find((lane) => lane.id === updatedJob.status);
if (targetLane) {
// Move the card to the new lane without changing its data
targetLane.cards.push(cardToMove);
// Update the lane titles with the new card count
sourceLane.title = `${sourceLane.title.split(" ")[0]} (${sourceLane.cards.length})`;
targetLane.title = `${targetLane.title.split(" ")[0]} (${targetLane.cards.length})`;
} else {
@@ -140,7 +152,6 @@ function ProductionBoardKanbanComponent({ data, bodyshop, refetch, insertAuditTr
}
}
// Return the updated lanes
return { lanes: updatedLanes };
});
},

View File

@@ -28,20 +28,26 @@ const useSocket = (bodyshop) => {
setSocket(socketInstance);
socketInstance.on("connect", () => {
// When the socket connects or reconnects, join the bodyshop room
const joinRoomOnConnect = () => {
console.log("Socket connected:", socketInstance.id);
setClientId(socketInstance.id);
if (bodyshop.id) {
socketInstance.on("bodyshop-message", handleBodyshopMessage);
socketInstance.emit("join-bodyshop-room", bodyshop.id);
console.log(`Joined bodyshop room: ${bodyshop.id}`);
}
});
};
// Set up the necessary socket event handlers
socketInstance.on("connect", joinRoomOnConnect);
socketInstance.on("reconnect", (attempt) => {
console.log(`Socket reconnected after ${attempt} attempts`);
});
socketInstance.on("bodyshop-message", handleBodyshopMessage);
socketInstance.on("connect_error", (err) => {
console.error("Socket connection error:", err);
});
@@ -50,15 +56,13 @@ const useSocket = (bodyshop) => {
console.log("Socket disconnected");
});
if (bodyshop?.id) {
return () => {
socketInstance.emit("leave-bodyshop-room", bodyshop.id);
socketInstance.off("bodyshop-message", handleBodyshopMessage);
socketInstance.disconnect();
};
}
// Clean up on component unmount or when bodyshop changes
return () => {
if (bodyshop?.id) {
socketInstance.emit("leave-bodyshop-room", bodyshop.id);
}
socketInstance.off("connect", joinRoomOnConnect);
socketInstance.off("bodyshop-message", handleBodyshopMessage);
socketInstance.disconnect();
};
}
@@ -69,24 +73,3 @@ const useSocket = (bodyshop) => {
};
export default useSocket;
// useEffect(() => {
// if (socket && bodyshop && bodyshop.id) {
// const handleConnect = () => {
// socket.emit("join-bodyshop-room", bodyshop.id);
// };
//
// const handleBodyshopMessage = (message) => {
// console.log(`Received message for bodyshop ${bodyshop.id}:`, message);
// };
//
// socket.on("connect", handleConnect);
// socket.on("bodyshop-message", handleBodyshopMessage);
//
// return () => {
// socket.emit("leave-bodyshop-room", bodyshop.id);
// socket.off("connect", handleConnect);
// socket.off("bodyshop-message", handleBodyshopMessage);
// };
// }
// }, [socket, bodyshop]);

View File

@@ -210,7 +210,8 @@ const applyRedisHelpers = (pubClient, app) => {
getMultipleSessionData,
setMultipleFromArraySessionData,
addItemToEndOfList,
addItemToBeginningOfList
addItemToBeginningOfList,
pubClient
});
app.use((req, res, next) => {
@@ -222,7 +223,8 @@ const applyRedisHelpers = (pubClient, app) => {
getMultipleSessionData,
setMultipleFromArraySessionData,
addItemToEndOfList,
addItemToBeginningOfList
addItemToBeginningOfList,
pubClient
};
next();
});

View File

@@ -3,7 +3,14 @@ require("dotenv").config({
path: path.resolve(process.cwd(), `.env.${process.env.NODE_ENV || "development"}`)
});
const { io, setSessionData, clearSessionData, getMultipleSessionData, addItemToEndOfList } = require("../../server");
const {
io,
setSessionData,
clearSessionData,
getMultipleSessionData,
addItemToEndOfList,
pubClient
} = require("../../server");
const { admin } = require("../firebase/firebase-handler");
const logger = require("../utils/logger");
@@ -130,15 +137,35 @@ function registerPbsApEvents(socket) {
});
}
const getRedisKeyForSocket = (socketId) => `socket:${socketId}:rooms`;
// Room management and broadcasting events
function registerRoomAndBroadcastEvents(socket) {
// Rejoin rooms on reconnect
pubClient.lRange(getRedisKeyForSocket(socket.id), 0, -1, (err, rooms) => {
if (rooms && rooms.length > 0) {
rooms.forEach((room) => {
socket.join(room);
createLogEvent(socket, "DEBUG", `Client rejoined bodyshop room: ${room}`);
});
}
});
socket.on("join-bodyshop-room", async (bodyshopUUID) => {
socket.join(bodyshopUUID);
// Store room in Redis
pubClient.rPush(getRedisKeyForSocket(socket.id), bodyshopUUID);
await createLogEvent(socket, "DEBUG", `Client joined bodyshop room: ${bodyshopUUID}`);
});
socket.on("leave-bodyshop-room", async (bodyshopUUID) => {
socket.leave(bodyshopUUID);
// Remove room from Redis
pubClient.lRem(getRedisKeyForSocket(socket.id), 0, bodyshopUUID);
await createLogEvent(socket, "DEBUG", `Client left bodyshop room: ${bodyshopUUID}`);
});
@@ -146,8 +173,12 @@ function registerRoomAndBroadcastEvents(socket) {
io.to(bodyshopUUID).emit("bodyshop-message", message);
await createLogEvent(socket, "INFO", `Broadcast message to bodyshop ${bodyshopUUID}`);
});
}
socket.on("disconnect", () => {
// Optional: Cleanup Redis entry on disconnect if needed
createLogEvent(socket, "DEBUG", `Client disconnected: ${socket.id}`);
});
}
// DMS session clearing event
function registerDmsClearSessionEvent(socket) {
socket.on("clear-dms-session", async () => {