From bb148f480163379987f7d3cecf132f67d9af4a5a Mon Sep 17 00:00:00 2001 From: Poovizhi99 Date: Thu, 16 Oct 2025 14:45:26 +0530 Subject: [PATCH 1/4] threads in sidebar --- .../layout/sidebarRight/SideBarRight.tsx | 150 +++++++++++++++--- .../components/ThreadDetails.tsx | 7 + .../collaboration/socket/builderResponses.tsx | 2 + .../socket/threadSocketResponses.dev.tsx | 19 ++- .../collab/comments/getAllThreads.ts | 1 + 5 files changed, 155 insertions(+), 24 deletions(-) create mode 100644 app/src/components/layout/sidebarRight/properties/eventProperties/components/ThreadDetails.tsx diff --git a/app/src/components/layout/sidebarRight/SideBarRight.tsx b/app/src/components/layout/sidebarRight/SideBarRight.tsx index e0d5904..b7607f8 100644 --- a/app/src/components/layout/sidebarRight/SideBarRight.tsx +++ b/app/src/components/layout/sidebarRight/SideBarRight.tsx @@ -1,13 +1,22 @@ import React, { useEffect, useState } from "react"; import Header from "./Header"; import useModuleStore, { useSubModuleStore } from "../../../store/ui/useModuleStore"; -import { AnalysisIcon, FilePackageIcon, MechanicsIcon, PropertiesIcon, SimulationIcon } from "../../icons/SimulationIcons"; +import { + AnalysisIcon, + FilePackageIcon, + MechanicsIcon, + PropertiesIcon, + SimulationIcon, +} from "../../icons/SimulationIcons"; import { useToggleStore } from "../../../store/ui/useUIToggleStore"; import Visualization from "./visualization/Visualization"; import Analysis from "./analysis/Analysis"; import Simulations from "./simulation/Simulations"; -import { useIsComparing, useToolMode } from "../../../store/builder/store"; -import { useSelectedEventData, useSelectedEventSphere } from "../../../store/simulation/useSimulationStore"; +import { useActiveTool, useIsComparing, useToolMode } from "../../../store/builder/store"; +import { + useSelectedEventData, + useSelectedEventSphere, +} from "../../../store/simulation/useSimulationStore"; import { useBuilderStore } from "../../../store/builder/useBuilderStore"; import GlobalProperties from "./properties/GlobalProperties"; import AssetProperties from "./properties/AssetProperties"; @@ -25,6 +34,7 @@ import SelectedZoneProperties from "./properties/SelectedZoneProperties"; import ResourceManagement from "./resourceManagement/ResourceManagement"; import { useSceneContext } from "../../../modules/scene/sceneContext"; +import ThreadDetails from "./properties/eventProperties/components/ThreadDetails"; type DisplayComponent = | "versionHistory" @@ -44,20 +54,26 @@ type DisplayComponent = | "analysis" | "visualization" | "resourceManagement" + | "threadDetails" | "none"; const SideBarRight: React.FC = () => { const { activeModule } = useModuleStore(); + const { activeTool } = useActiveTool(); + console.log("activeTool: ", activeTool); const { toggleUIRight } = useToggleStore(); const { toolMode } = useToolMode(); const { subModule, setSubModule } = useSubModuleStore(); - const { selectedWall, selectedFloor, selectedAisle, selectedZone, selectedDecal } = useBuilderStore(); + const { selectedWall, selectedFloor, selectedAisle, selectedZone, selectedDecal } = + useBuilderStore(); const { selectedEventData } = useSelectedEventData(); const { selectedEventSphere } = useSelectedEventSphere(); - const { versionStore, assetStore } = useSceneContext(); + const { versionStore, assetStore, threadStore } = useSceneContext(); const { selectedAssets } = assetStore(); const { viewVersionHistory, setVersionHistoryVisible } = versionStore(); const { isComparing } = useIsComparing(); + const { threads } = threadStore(); + console.log("threads: ", threads); const [displayComponent, setDisplayComponent] = useState("none"); @@ -104,7 +120,10 @@ const SideBarRight: React.FC = () => { } } - if (activeModule === "simulation" || activeModule === "builder") { + if ( + activeModule === "simulation" || + (activeModule === "builder" && activeTool !== "comment") + ) { if (subModule === "resourceManagement") { setDisplayComponent("resourceManagement"); return; @@ -116,31 +135,81 @@ const SideBarRight: React.FC = () => { setDisplayComponent("assetProperties"); return; } - if (selectedAssets.length !== 1 && !selectedFloor && !selectedAisle && !selectedDecal && !selectedZone && selectedWall) { + if ( + selectedAssets.length !== 1 && + !selectedFloor && + !selectedAisle && + !selectedDecal && + !selectedZone && + selectedWall + ) { setDisplayComponent("selectedWallProperties"); return; } - if (selectedAssets.length !== 1 && !selectedWall && !selectedAisle && !selectedDecal && !selectedZone && selectedFloor) { + if ( + selectedAssets.length !== 1 && + !selectedWall && + !selectedAisle && + !selectedDecal && + !selectedZone && + selectedFloor + ) { setDisplayComponent("selectedFloorProperties"); return; } - if (viewVersionHistory && selectedAssets.length !== 1 && !selectedWall && !selectedAisle && !selectedFloor && !selectedDecal && !selectedZone) { + if ( + viewVersionHistory && + selectedAssets.length !== 1 && + !selectedWall && + !selectedAisle && + !selectedFloor && + !selectedDecal && + !selectedZone + ) { setDisplayComponent("versionHistory"); return; } - if (selectedAssets.length !== 1 && !selectedFloor && !selectedAisle && !selectedWall && !selectedZone && selectedDecal) { + if ( + selectedAssets.length !== 1 && + !selectedFloor && + !selectedAisle && + !selectedWall && + !selectedZone && + selectedDecal + ) { setDisplayComponent("selectedDecalProperties"); return; } - if (selectedAssets.length !== 1 && !selectedFloor && !selectedWall && !selectedDecal && !selectedZone && selectedAisle) { + if ( + selectedAssets.length !== 1 && + !selectedFloor && + !selectedWall && + !selectedDecal && + !selectedZone && + selectedAisle + ) { setDisplayComponent("selectedAisleProperties"); return; } - if (selectedAssets.length !== 1 && !selectedFloor && !selectedWall && !selectedDecal && !selectedAisle && selectedZone) { + if ( + selectedAssets.length !== 1 && + !selectedFloor && + !selectedWall && + !selectedDecal && + !selectedAisle && + selectedZone + ) { setDisplayComponent("selectedZoneProperties"); return; } - if (selectedAssets.length !== 1 && !selectedFloor && !selectedWall && !selectedDecal && !selectedAisle && !selectedZone) { + if ( + selectedAssets.length !== 1 && + !selectedFloor && + !selectedWall && + !selectedDecal && + !selectedAisle && + !selectedZone + ) { if (toolMode === "Aisle") { setDisplayComponent("aisleProperties"); return; @@ -161,10 +230,26 @@ const SideBarRight: React.FC = () => { setDisplayComponent("globalProperties"); return; } + if (activeModule === "builder" && activeTool === "comment") { + setDisplayComponent("threadDetails"); + } } setDisplayComponent("none"); - }, [viewVersionHistory, activeModule, subModule, isComparing, selectedAssets, selectedWall, selectedFloor, selectedAisle, toolMode, selectedDecal, selectedZone]); + }, [ + viewVersionHistory, + activeModule, + subModule, + isComparing, + selectedAssets, + selectedWall, + selectedFloor, + selectedAisle, + toolMode, + selectedDecal, + selectedZone, + activeTool, + ]); const renderComponent = () => { switch (displayComponent) { @@ -202,13 +287,20 @@ const SideBarRight: React.FC = () => { return ; case "resourceManagement": return ; + case "threadDetails": + return ; default: return null; } }; return ( -
e.stopPropagation()}> +
e.stopPropagation()} + >
{toggleUIRight && ( <> @@ -218,7 +310,9 @@ const SideBarRight: React.FC = () => { <> )}
)} + {/* {activeModule === "builder" && + activeTool === "comment" && + threads && + threads.map((val) =>

{val.threadTitle}

)} */} {displayComponent !== "none" && (
diff --git a/app/src/components/layout/sidebarRight/properties/eventProperties/components/ThreadDetails.tsx b/app/src/components/layout/sidebarRight/properties/eventProperties/components/ThreadDetails.tsx new file mode 100644 index 0000000..4189ab0 --- /dev/null +++ b/app/src/components/layout/sidebarRight/properties/eventProperties/components/ThreadDetails.tsx @@ -0,0 +1,7 @@ +import React from "react"; + +const ThreadDetails = () => { + return
; +}; + +export default ThreadDetails; diff --git a/app/src/modules/collaboration/socket/builderResponses.tsx b/app/src/modules/collaboration/socket/builderResponses.tsx index 71acff3..6601528 100644 --- a/app/src/modules/collaboration/socket/builderResponses.tsx +++ b/app/src/modules/collaboration/socket/builderResponses.tsx @@ -546,6 +546,8 @@ function BuilderResponses() { }, [builderSocket, selectedZone]); //#endregion + + return null; } diff --git a/app/src/modules/collaboration/socket/threadSocketResponses.dev.tsx b/app/src/modules/collaboration/socket/threadSocketResponses.dev.tsx index abdb38f..d2c547a 100644 --- a/app/src/modules/collaboration/socket/threadSocketResponses.dev.tsx +++ b/app/src/modules/collaboration/socket/threadSocketResponses.dev.tsx @@ -14,7 +14,8 @@ interface ThreadSocketProps { const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSocketProps) => { const { threadSocket } = useSocketStore(); - const { selectedComment, setSelectedComment, setCommentPositionState, commentPositionState } = useSelectedComment(); + const { selectedComment, setSelectedComment, setCommentPositionState, commentPositionState } = + useSelectedComment(); const { threadStore } = useSceneContext(); const { threads, removeReply, addThread, addReply, updateThread, updateReply } = threadStore(); const { userId } = getUserData(); @@ -73,7 +74,9 @@ const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSock setMessages((prev) => prev.map((message) => { // 👈 log each message - return message.replyId === data.data?._id ? { ...message, comment: data.data?.comment } : message; + return message.replyId === data.data?._id + ? { ...message, comment: data.data?.comment } + : message; }) ); } @@ -143,7 +146,17 @@ const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSock threadSocket.off("v1-thread:response:delete", handleDeleteThread); threadSocket.off("v1-thread:response:updateTitle", handleEditThread); }; - }, [threadSocket, selectedComment, commentPositionState, userId, setSelectedComment, setCommentPositionState, threads, modeRef.current, messages]); + }, [ + threadSocket, + selectedComment, + commentPositionState, + userId, + setSelectedComment, + setCommentPositionState, + threads, + modeRef.current, + messages, + ]); return null; }; diff --git a/app/src/services/factoryBuilder/collab/comments/getAllThreads.ts b/app/src/services/factoryBuilder/collab/comments/getAllThreads.ts index 6222cf2..a22cfec 100644 --- a/app/src/services/factoryBuilder/collab/comments/getAllThreads.ts +++ b/app/src/services/factoryBuilder/collab/comments/getAllThreads.ts @@ -25,6 +25,7 @@ export const getAllThreads = async (projectId: string, versionId: string) => { } const result = await response.json(); + console.log('result: ', result); return result; } catch { From 6ce16483c6eba18d6dc1de97dad110188f743e92 Mon Sep 17 00:00:00 2001 From: Poovizhi99 Date: Wed, 22 Oct 2025 12:13:00 +0530 Subject: [PATCH 2/4] refactoring thread functionalities including socketresponses --- .../components/layout/scenes/MainScene.tsx | 76 +++++-- .../layout/sidebarRight/SideBarRight.tsx | 32 +-- .../properties/ThreadProperties.tsx | 124 ++++++++++++ .../components/ThreadDetails.tsx | 7 - .../collaboration/threads/CommentThreads.tsx | 82 +++++--- .../ui/collaboration/threads/Messages.tsx | 140 ++++++++----- .../ui/collaboration/threads/ThreadChat.tsx | 188 +++++++++++------- .../collaboration/functions/getAvatarColor.ts | 18 +- .../useThreadResponseHandler.ts | 67 +++++++ .../socket/collaborationResponses.tsx | 122 ++++++++++++ .../collaboration/socket/socketResponses.tsx | 3 + .../socket/threadSocketResponses.dev.tsx | 164 --------------- .../threadInstance/threadInstance.tsx | 50 +++-- .../threadInstances/threadInstances.tsx | 11 +- .../collaboration/threads/threadsGroup.tsx | 14 +- .../builder/collab/comments/addCommentApi.ts | 21 +- .../collab/comments/createThreadApi.ts | 9 +- .../collab/comments/deleteThreadApi.ts | 1 + .../builder/collab/comments/editCommentApi.ts | 11 +- app/src/store/builder/store.ts | 9 - app/src/store/collaboration/useThreadStore.ts | 17 ++ app/src/store/socket/useSocketStore.ts | 2 +- app/src/styles/layout/_sidebar.scss | 121 ++++++++++- app/src/types/collaborationTypes.d.ts | 4 +- .../utils/shortcutkeys/handleShortcutKeys.ts | 37 +++- 25 files changed, 909 insertions(+), 421 deletions(-) create mode 100644 app/src/components/layout/sidebarRight/properties/ThreadProperties.tsx delete mode 100644 app/src/components/layout/sidebarRight/properties/eventProperties/components/ThreadDetails.tsx create mode 100644 app/src/modules/collaboration/responseHandler/useThreadResponseHandler.ts create mode 100644 app/src/modules/collaboration/socket/collaborationResponses.tsx delete mode 100644 app/src/modules/collaboration/socket/threadSocketResponses.dev.tsx diff --git a/app/src/components/layout/scenes/MainScene.tsx b/app/src/components/layout/scenes/MainScene.tsx index ea2e800..927f34e 100644 --- a/app/src/components/layout/scenes/MainScene.tsx +++ b/app/src/components/layout/scenes/MainScene.tsx @@ -1,6 +1,13 @@ import { useEffect } from "react"; import { useParams } from "react-router-dom"; -import { useLoadingProgress, useRenameModeStore, useIsComparing, useSelectedComment, useWidgetSubOption, useToggleView, useCreateNewWindow } from "../../../store/builder/store"; +import { + useLoadingProgress, + useRenameModeStore, + useIsComparing, + useWidgetSubOption, + useToggleView, + useCreateNewWindow, +} from "../../../store/builder/store"; import useModuleStore from "../../../store/ui/useModuleStore"; import { useSocketStore } from "../../../store/socket/useSocketStore"; import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore"; @@ -44,16 +51,17 @@ function MainScene() { const { toggleView } = useToggleView(); const { isPlaying } = usePlayButtonStore(); const { widgetSubOption } = useWidgetSubOption(); - const { builderSocket, visualizationSocket } = useSocketStore(); + const { builderSocket, visualizationSocket, threadSocket } = useSocketStore(); const { selectedZone } = useSelectedZoneStore(); const { setFloatingWidget } = useFloatingWidget(); - const { assetStore, productStore, versionStore } = useSceneContext(); + const { assetStore, productStore, versionStore, threadStore } = useSceneContext(); const { products, selectedProduct } = productStore(); const { versionHistory, setVersions, selectedVersion, setSelectedVersion } = versionStore(); const { setName, selectedAssets, setSelectedAssets } = assetStore(); const { projectId } = useParams(); const { isRenameMode, setIsRenameMode } = useRenameModeStore(); - const { selectedComment, commentPositionState } = useSelectedComment(); + const { commentPositionState, selectedThread } = threadStore(); + const { resetStates } = useRestStates(); const { organization, userId } = getUserData(); const { createNewWindow } = useCreateNewWindow(); @@ -71,7 +79,12 @@ function MainScene() { builderSocket.emit("joinRoom", { projectId: projectId }); }, 1000); } - }, [builderSocket, projectId]); + if (threadSocket && projectId) { + setTimeout(() => { + threadSocket.emit("joinRoom", { projectId: projectId }); + }, 1000); + } + }, [builderSocket, threadSocket, projectId]); useEffect(() => { if (activeModule !== "simulation") { @@ -108,9 +121,13 @@ function MainScene() { useEffect(() => { if (versionHistory.length > 0) { recentlyViewedApi().then((projects) => { - const recent_opened_verisionID = (Object.values(projects?.RecentlyViewed || {})[0] as any)?.Present_version._id; + const recent_opened_verisionID = ( + Object.values(projects?.RecentlyViewed || {})[0] as any + )?.Present_version._id; if (recent_opened_verisionID && projects.RecentlyViewed[0]._id === projectId) { - const version = versionHistory.find((ver) => ver.versionId === recent_opened_verisionID); + const version = versionHistory.find( + (ver) => ver.versionId === recent_opened_verisionID + ); if (version) { setSelectedVersion(version); } @@ -188,7 +205,9 @@ function MainScene() { {!selectedUser && ( <> - {!createNewWindow && loadingProgress > 0 && } + {!createNewWindow && loadingProgress > 0 && ( + + )} {!isPlaying && ( <> {!toggleView && !isComparing && } @@ -203,27 +222,48 @@ function MainScene() { {/* */} {activeModule === "market" && } {activeModule !== "market" && !isPlaying && !isComparing && } - {isPlaying && activeModule === "simulation" && loadingProgress === 0 && } + {isPlaying && activeModule === "simulation" && loadingProgress === 0 && ( + + )} {isPlaying && activeModule !== "simulation" && } {activeModule === "visualization" && } - {isRenameMode && selectedAssets.length === 1 && } + {isRenameMode && selectedAssets.length === 1 && ( + + )} {activeModule === "builder" && toggleView && } - {selectedProduct && selectedVersion && isComparing && !isPlaying && activeModule === "simulation" && ( -
- v.versionName)} onSelect={handleSelectVersion} search={false} /> -
- l.productName)} onSelect={handleSelectProduct} search={false} /> -
- )} + {selectedProduct && + selectedVersion && + isComparing && + !isPlaying && + activeModule === "simulation" && ( +
+ v.versionName)} + onSelect={handleSelectVersion} + search={false} + /> +
+ l.productName)} + onSelect={handleSelectProduct} + search={false} + /> +
+ )} )} - {(commentPositionState !== null || selectedComment !== null) && } + {(commentPositionState !== null || selectedThread !== null) && } {activeModule !== "market" && !selectedUser &&