api's and threads refactor

This commit is contained in:
2025-09-10 11:44:15 +05:30
parent 060d7a7d82
commit f0fdad9dff
28 changed files with 209 additions and 221 deletions

View File

@@ -7,9 +7,9 @@ import { access } from "fs";
import MultiEmailInvite from "../ui/inputs/MultiEmailInvite";
import { useActiveUsers } from "../../store/builder/store";
import { getUserData } from "../../functions/getUserData";
import { getProjectSharedList } from "../../services/factoryBuilder/collab/getProjectSharedList";
import { getProjectSharedList } from "../../services/factoryBuilder/collab/project/getProjectSharedList";
import { useParams } from "react-router-dom";
import { shareAccess } from "../../services/factoryBuilder/collab/shareAccess";
import { shareAccess } from "../../services/factoryBuilder/collab/project/shareAccess";
import { getAvatarColor } from "../../modules/collaboration/functions/getAvatarColor";
interface UserListTemplateProps {

View File

@@ -5,10 +5,10 @@ import { getRelativeTime } from "../function/getRelativeTime";
interface CommentThreadsProps {
commentClicked: () => void;
comment?: CommentSchema;
thread?: ThreadSchema;
}
const CommentThreads: React.FC<CommentThreadsProps> = ({ commentClicked, comment }) => {
const CommentThreads: React.FC<CommentThreadsProps> = ({ commentClicked, thread }) => {
const [expand, setExpand] = useState(false);
const commentsedUsers = [{ creatorId: "1" }];
const { userName } = getUserData();
@@ -51,12 +51,12 @@ const CommentThreads: React.FC<CommentThreadsProps> = ({ commentClicked, comment
<div className={`last-comment-details ${expand ? "expand" : ""}`}>
<div className="header">
<div className="user-name">{userName}</div>
<div className="time">{comment?.createdAt && getRelativeTime(comment.createdAt)}</div>
<div className="time">{thread?.createdAt && getRelativeTime(thread.createdAt)}</div>
</div>
<div className="message">{comment?.threadTitle}</div>
{comment && comment?.comments.length > 0 && (
<div className="message">{thread?.threadTitle}</div>
{thread && thread?.comments.length > 0 && (
<div className="comments">
{comment?.comments.length} {comment?.comments.length === 1 ? "comment" : "replies"}
{thread?.comments.length} {thread?.comments.length === 1 ? "comment" : "replies"}
</div>
)}
</div>

View File

@@ -6,15 +6,14 @@ import { getUserData } from "../../../../functions/getUserData";
import { useParams } from "react-router-dom";
import { useSelectedComment, useSocketStore } from "../../../../store/builder/store";
import { getRelativeTime } from "../function/getRelativeTime";
import { editThreadTitleApi } from "../../../../services/factoryBuilder/comments/editThreadTitleApi";
import { editThreadTitleApi } from "../../../../services/factoryBuilder/collab/comments/editThreadTitleApi";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
import { deleteCommentApi } from "../../../../services/factoryBuilder/comments/deleteCommentApi";
import { addCommentsApi } from "../../../../services/factoryBuilder/comments/addCommentApi";
import { editCommentsApi } from "../../../../services/factoryBuilder/comments/editCommentApi";
import { deleteCommentApi } from "../../../../services/factoryBuilder/collab/comments/deleteCommentApi";
import { editCommentsApi } from "../../../../services/factoryBuilder/collab/comments/editCommentApi";
interface MessageProps {
val: Reply | CommentSchema;
val: Reply | ThreadSchema;
i: number;
setMessages?: React.Dispatch<React.SetStateAction<Reply[]>>;
setIsEditable?: React.Dispatch<React.SetStateAction<boolean>>;
@@ -33,8 +32,8 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
const { userName, userId, organization } = getUserData();
const [isEditComment, setIsEditComment] = useState(false);
const { selectedComment, setCommentPositionState } = useSelectedComment();
const { versionStore, commentStore } = useSceneContext();
const { updateComment, removeReply, updateReply } = commentStore();
const { versionStore, threadStore } = useSceneContext();
const { updateComment, removeReply, updateReply } = threadStore();
const { selectedVersion } = versionStore();
const [value, setValue] = useState<string>("comment" in val ? val.comment : val.threadTitle);
@@ -52,15 +51,15 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
}
const handleSaveAction = async () => {
if (!projectId || !selectedVersion || !setIsEditable || !setEditedThread) return;
if (!projectId || !selectedVersion) return;
if (isEditableThread && editedThread) {
if (!threadSocket?.active) {
// API
editThreadTitleApi(projectId, (val as CommentSchema).threadId, value, selectedVersion?.versionId || "").then((editThreadTitle) => {
editThreadTitleApi(projectId, (val as ThreadSchema).threadId, value, selectedVersion?.versionId || "").then((editThreadTitle) => {
if (editThreadTitle.message == "ThreadTitle updated Successfully") {
const editedThread: CommentSchema = {
const editedThread: ThreadSchema = {
state: "active",
threadId: editThreadTitle.data.replyId,
creatorId: userId,
@@ -71,7 +70,7 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
rotation: [0, 0, 0],
comments: [],
};
updateComment((val as CommentSchema).threadId, editedThread);
updateComment((val as ThreadSchema).threadId, editedThread);
}
});
} else {
@@ -82,7 +81,7 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
userId,
threadTitle: value,
organization,
threadId: (val as CommentSchema).threadId || selectedComment.threadId,
threadId: (val as ThreadSchema).threadId || selectedComment.threadId,
versionId: selectedVersion?.versionId || "",
};
@@ -101,9 +100,10 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
comment: value,
};
updateReply((val as CommentSchema).threadId, (val as Reply)?.replyId, commentData);
setIsEditable(true);
setEditedThread(false);
updateReply((val as ThreadSchema).threadId, (val as Reply)?.replyId, commentData);
if (setIsEditable) setIsEditable(true);
if (setEditedThread) setEditedThread(false);
});
} else {
// SOCKET
@@ -119,8 +119,8 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
};
threadSocket.emit("v1-Comment:add", editComment);
setIsEditable(true);
setEditedThread(false);
if (setIsEditable) setIsEditable(true);
if (setEditedThread) setEditedThread(false);
}
}
setIsEditComment(false);

View File

@@ -9,9 +9,9 @@ import { getUserData } from "../../../../functions/getUserData";
import ThreadSocketResponsesDev from "../../../../modules/collaboration/socket/threadSocketResponses.dev";
import { useSceneContext } from "../../../../modules/scene/sceneContext";
import { addCommentsApi } from "../../../../services/factoryBuilder/comments/addCommentApi";
import { deleteThreadApi } from "../../../../services/factoryBuilder/comments/deleteThreadApi";
import { createThreadApi } from "../../../../services/factoryBuilder/comments/createThreadApi";
import { addCommentsApi } from "../../../../services/factoryBuilder/collab/comments/addCommentApi";
import { deleteThreadApi } from "../../../../services/factoryBuilder/collab/comments/deleteThreadApi";
import { createThreadApi } from "../../../../services/factoryBuilder/collab/comments/createThreadApi";
import { getRelativeTime } from "../function/getRelativeTime";
const ThreadChat: React.FC = () => {
@@ -33,17 +33,17 @@ const ThreadChat: React.FC = () => {
const { threadSocket } = useSocketStore();
const modeRef = useRef<"create" | "edit" | null>(null);
const messagesRef = useRef<HTMLDivElement>(null);
const { versionStore, commentStore } = useSceneContext();
const { versionStore, threadStore } = useSceneContext();
const { selectedVersion } = versionStore();
const { addComment, removeComment, addReply, comments } = commentStore();
const { addComment, removeComment, addReply, threads } = threadStore();
useEffect(() => {
modeRef.current = mode;
}, [mode]);
useEffect(() => {
if (comments.length > 0 && selectedComment) {
const allMessages = comments
if (threads.length > 0 && selectedComment) {
const allMessages = threads
.flatMap((val: any) => (val?.threadId === selectedComment?.threadId ? val.comments : []))
.map((c) => {
return {
@@ -58,7 +58,7 @@ const ThreadChat: React.FC = () => {
setMessages(allMessages);
}
}, []);
}, [selectedComment]);
useEffect(() => {
if (textareaRef.current) adjustHeight(textareaRef.current);
@@ -207,7 +207,7 @@ const ThreadChat: React.FC = () => {
createThreadApi(projectId, "active", commentPositionState.position, [0, 0, 0], value, selectedVersion?.versionId || "").then((thread) => {
if (thread.message === "Thread created Successfully" && thread?.threadData) {
const comment: CommentSchema = {
const comment: ThreadSchema = {
state: "active",
threadId: thread?.threadData?._id,
creatorId: userId,

View File

@@ -1,8 +1,8 @@
import React, { useState } from "react";
import { useParams } from "react-router-dom";
import { getSearchUsers } from "../../../services/factoryBuilder/collab/getSearchUsers";
import { shareProject } from "../../../services/factoryBuilder/collab/shareProject";
import { getSearchUsers } from "../../../services/factoryBuilder/collab/project/getSearchUsers";
import { shareProject } from "../../../services/factoryBuilder/collab/project/shareProject";
import { getUserData } from "../../../functions/getUserData";
interface UserData {

View File

@@ -3,7 +3,7 @@ import { useEffect, useRef, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import camModel from "../../../assets/gltf-glb/camera face 2.gltf";
import getActiveUsersData from "../../../services/factoryBuilder/collab/getActiveUsers";
import getActiveUsersData from "../../../services/factoryBuilder/collab/users/getActiveUsers";
import { useActiveUsers, useCamMode, useSocketStore } from "../../../store/builder/store";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import { useNavigate } from "react-router-dom";

View File

@@ -1,6 +1,6 @@
import React from "react";
import CamModelsGroup from "./camera/collabCams";
import CommentsGroup from "./comments/commentsGroup";
import ThreadsGroup from "./threads/threadsGroup";
const Collaboration: React.FC = () => {
@@ -9,7 +9,7 @@ const Collaboration: React.FC = () => {
<CamModelsGroup />
<CommentsGroup />
<ThreadsGroup />
</>
);

View File

@@ -14,8 +14,8 @@ interface ThreadSocketProps {
const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSocketProps) => {
const { threadSocket } = useSocketStore();
const { selectedComment, setSelectedComment, setCommentPositionState, commentPositionState } = useSelectedComment();
const { commentStore } = useSceneContext();
const { comments, removeReply, addComment, addReply, updateComment, updateReply } = commentStore();
const { threadStore } = useSceneContext();
const { threads, removeReply, addComment, addReply, updateComment, updateReply } = threadStore();
const { userId } = getUserData();
useEffect(() => {
@@ -85,7 +85,7 @@ const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSock
// --- Create Thread Handler ---
const handleCreateThread = (data: any) => {
const comment: CommentSchema = {
const comment: ThreadSchema = {
state: "active",
threadId: data.data?._id,
creatorId: userId || data.data?.userId,
@@ -114,7 +114,7 @@ const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSock
threadSocket.on("v1-thread:response:delete", handleDeleteThread);
const handleEditThread = (data: any) => {
const editedThread: CommentSchema = {
const editedThread: ThreadSchema = {
state: "active",
threadId: data.data?._id,
creatorId: userId,
@@ -142,21 +142,7 @@ const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSock
threadSocket.off("v1-thread:response:delete", handleDeleteThread);
threadSocket.off("v1-thread:response:updateTitle", handleEditThread);
};
}, [
threadSocket,
selectedComment,
commentPositionState,
userId,
setMessages,
addReply,
addComment,
setSelectedComment,
setCommentPositionState,
updateComment,
comments,
modeRef.current,
messages,
]);
}, [threadSocket, selectedComment, commentPositionState, userId, setSelectedComment, setCommentPositionState, threads, modeRef.current, messages]);
return null;
};

View File

@@ -1,13 +1,14 @@
import { Html, TransformControls } from "@react-three/drei";
import { useEffect, useRef, useState } from "react";
import { usePlayButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import CommentThreads from "../../../../../components/ui/collaboration/threads/CommentThreads";
import { useSelectedComment } from "../../../../../store/builder/store";
import { Group, Object3D, Vector3 } from "three";
import { useThree } from "@react-three/fiber";
import { Html, TransformControls } from "@react-three/drei";
import { Group, Object3D, Vector3 } from "three";
import { usePlayButtonStore } from "../../../../../store/ui/usePlayButtonStore";
import { useSelectedComment } from "../../../../../store/builder/store";
import CommentThreads from "../../../../../components/ui/collaboration/threads/CommentThreads";
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
function ThreadInstance({ comment }: { readonly comment: CommentSchema }) {
function ThreadInstance({ thread }: { readonly thread: ThreadSchema }) {
const { isPlaying } = usePlayButtonStore();
const CommentRef = useRef(null);
const [selectedObject, setSelectedObject] = useState<Object3D | null>(null);
@@ -33,8 +34,8 @@ function ThreadInstance({ comment }: { readonly comment: CommentSchema }) {
// }, [selectedComment]);
const commentClicked = () => {
setSelectedComment(comment);
const position = new Vector3(comment.position[0], comment.position[1], comment.position[2]);
setSelectedComment(thread);
const position = new Vector3(thread.position[0], thread.position[1], thread.position[2]);
position.project(camera);
const x = (position.x * 0.5 + 0.5) * size.width;
@@ -47,15 +48,16 @@ function ThreadInstance({ comment }: { readonly comment: CommentSchema }) {
};
useEffect(() => {
if (!selectedComment || selectedComment.threadId !== comment.threadId) {
if (!selectedComment || selectedComment.threadId !== thread.threadId) {
setSelectedObject(null);
}
}, [selectedComment]);
if (comment.state === "inactive" || isPlaying) return null;
if (thread.state === "inactive" || isPlaying) return null;
return (
<>
<group ref={groupRef} position={comment.position} rotation={comment.rotation}>
<group ref={groupRef} position={thread.position} rotation={thread.rotation}>
<Html
ref={CommentRef}
zIndexRange={[1, 0]}
@@ -66,7 +68,7 @@ function ThreadInstance({ comment }: { readonly comment: CommentSchema }) {
// rotation={comment.rotation}
className="comments-main-wrapper"
>
<CommentThreads commentClicked={commentClicked} comment={comment} />
<CommentThreads commentClicked={commentClicked} thread={thread} />
</Html>
</group>
{/* {selectedObject && transformMode && (

View File

@@ -1,21 +1,21 @@
import React, { useEffect } from "react";
import CommentInstance from "./commentInstance/commentInstance";
import { getAllThreads } from "../../../../services/factoryBuilder/comments/getAllThreads";
import ThreadInstance from "./threadInstance/threadInstance";
import { getAllThreads } from "../../../../services/factoryBuilder/collab/comments/getAllThreads";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../functions/getUserData";
import { getRelativeTime } from "../../../../components/ui/collaboration/function/getRelativeTime";
import { useSceneContext } from "../../../scene/sceneContext";
function CommentInstances() {
function ThreadInstances() {
const { projectId } = useParams();
const { userId } = getUserData();
const { versionStore, commentStore } = useSceneContext();
const { comments, setComments } = commentStore();
const { versionStore, threadStore } = useSceneContext();
const { threads, setComments } = threadStore();
const { selectedVersion } = versionStore();
useEffect(() => {
// console.log("comments", comments);
}, [comments]);
// console.log("threads", threads);
}, [threads]);
useEffect(() => {
if (!projectId || !selectedVersion) return;
@@ -45,13 +45,13 @@ function CommentInstances() {
return (
<>
{comments?.map((comment: CommentSchema) => (
<React.Fragment key={comment.threadId}>
<CommentInstance comment={comment} />
{threads?.map((thread: ThreadSchema) => (
<React.Fragment key={thread.threadId}>
<ThreadInstance thread={thread} />
</React.Fragment>
))}
</>
);
}
export default CommentInstances;
export default ThreadInstances;

View File

@@ -1,11 +1,11 @@
import { useEffect, useState } from "react";
import { useThree } from "@react-three/fiber";
import { Vector3 } from "three";
import CommentInstances from "./instances/commentInstances";
import ThreadInstances from "./threadInstances/threadInstances";
import { Sphere } from "@react-three/drei";
import { useActiveTool, useSelectedComment } from "../../../store/builder/store";
function CommentsGroup() {
function ThreadsGroup() {
const { gl, raycaster, camera, scene, pointer, size } = useThree();
const { activeTool } = useActiveTool();
const [hoverPos, setHoverPos] = useState<Vector3 | null>(null);
@@ -112,7 +112,7 @@ function CommentsGroup() {
return (
<>
<CommentInstances />
<ThreadInstances />
{hoverPos && (
<Sphere name={"commentHolder"} args={[0.1, 16, 16]} position={hoverPos}>
<meshStandardMaterial color="orange" />
@@ -122,4 +122,4 @@ function CommentsGroup() {
);
}
export default CommentsGroup;
export default ThreadsGroup;

View File

@@ -24,7 +24,7 @@ import { createStorageUnitStore, StorageUnitStoreType } from "../../store/simula
import { createHumanStore, HumanStoreType } from "../../store/simulation/useHumanStore";
import { createCraneStore, CraneStoreType } from "../../store/simulation/useCraneStore";
import { createCommentsStore, CommentStoreType } from "../../store/collaboration/useCommentStore";
import { createThreadsStore, ThreadStoreType } from "../../store/collaboration/useCommentStore";
type SceneContextValue = {
versionStore: VersionStoreType;
@@ -51,7 +51,7 @@ type SceneContextValue = {
humanStore: HumanStoreType;
craneStore: CraneStoreType;
commentStore: CommentStoreType;
threadStore: ThreadStoreType;
humanEventManagerRef: React.RefObject<HumanEventManagerState>;
craneEventManagerRef: React.RefObject<CraneEventManagerState>;
@@ -88,7 +88,7 @@ export function SceneProvider({ children, layout }: { readonly children: React.R
const humanStore = useMemo(() => createHumanStore(), []);
const craneStore = useMemo(() => createCraneStore(), []);
const commentStore = useMemo(() => createCommentsStore(), []);
const threadStore = useMemo(() => createThreadsStore(), []);
const humanEventManagerRef = useRef<HumanEventManagerState>({ humanStates: [] });
const craneEventManagerRef = useRef<CraneEventManagerState>({ craneStates: [] });
@@ -114,7 +114,7 @@ export function SceneProvider({ children, layout }: { readonly children: React.R
storageUnitStore.getState().clearStorageUnits();
humanStore.getState().clearHumans();
craneStore.getState().clearCranes();
commentStore.getState().clearComments();
threadStore.getState().clearComments();
humanEventManagerRef.current.humanStates = [];
craneEventManagerRef.current.craneStates = [];
},
@@ -138,7 +138,7 @@ export function SceneProvider({ children, layout }: { readonly children: React.R
storageUnitStore,
humanStore,
craneStore,
commentStore,
threadStore,
]
);
@@ -163,7 +163,7 @@ export function SceneProvider({ children, layout }: { readonly children: React.R
storageUnitStore,
humanStore,
craneStore,
commentStore,
threadStore,
humanEventManagerRef,
craneEventManagerRef,
clearStores,
@@ -189,7 +189,7 @@ export function SceneProvider({ children, layout }: { readonly children: React.R
storageUnitStore,
humanStore,
craneStore,
commentStore,
threadStore,
clearStores,
layout,
]

View File

@@ -1,12 +1,12 @@
import { create } from "zustand";
import { immer } from "zustand/middleware/immer";
interface CommentStore {
comments: CommentsSchema;
interface ThreadStore {
threads: ThreadsSchema;
addComment: (comment: CommentSchema) => void;
setComments: (comments: CommentsSchema) => void;
updateComment: (threadId: string, updates: Partial<CommentSchema>) => void;
addComment: (thread: ThreadSchema) => void;
setComments: (threads: ThreadsSchema) => void;
updateComment: (threadId: string, updates: Partial<ThreadSchema>) => void;
removeComment: (threadId: string) => void;
clearComments: () => void;
@@ -14,65 +14,65 @@ interface CommentStore {
updateReply: (threadId: string, replyId: string, updates: Partial<Reply>) => void;
removeReply: (threadId: string, _id: string) => void;
getCommentById: (threadId: string) => CommentSchema | undefined;
getCommentById: (threadId: string) => ThreadSchema | undefined;
}
export const createCommentsStore = () => {
return create<CommentStore>()(
export const createThreadsStore = () => {
return create<ThreadStore>()(
immer((set, get) => ({
comments: [],
threads: [],
addComment: (comment) => {
addComment: (thread) => {
set((state) => {
if (!state.comments.find((c) => c.threadId === comment.threadId)) {
state.comments.push(JSON.parse(JSON.stringify(comment)));
if (!state.threads.find((c) => c.threadId === thread.threadId)) {
state.threads.push(JSON.parse(JSON.stringify(thread)));
}
});
},
setComments: (comments) => {
setComments: (threads) => {
set((state) => {
state.comments = comments;
state.threads = threads;
});
},
updateComment: (threadId, updates) => {
set((state) => {
const comment = state.comments.find((c) => c.threadId === threadId);
if (comment) {
Object.assign(comment, updates);
const thread = state.threads.find((c) => c.threadId === threadId);
if (thread) {
Object.assign(thread, updates);
}
});
},
removeComment: (threadId) => {
set((state) => {
state.comments = state.comments.filter((c) => c.threadId !== threadId);
state.threads = state.threads.filter((c) => c.threadId !== threadId);
});
},
clearComments: () => {
set((state) => {
state.comments = [];
state.threads = [];
});
},
addReply: (threadId, comment) => {
addReply: (threadId, thread) => {
set((state) => {
const reply = state.comments.find((c) => c.threadId === threadId);
const reply = state.threads.find((c) => c.threadId === threadId);
if (reply) {
reply.comments.push(comment);
reply.comments.push(thread);
}
});
},
updateReply: (threadId, replyId, updates) => {
set((state) => {
const reply = state.comments.find((c) => c.threadId === threadId);
const reply = state.threads.find((c) => c.threadId === threadId);
if (reply) {
const comment = reply.comments.find((r) => r.replyId === replyId);
if (comment) {
Object.assign(comment, updates);
const thread = reply.comments.find((r) => r.replyId === replyId);
if (thread) {
Object.assign(thread, updates);
}
}
});
@@ -80,18 +80,18 @@ export const createCommentsStore = () => {
removeReply: (threadId, _id) => {
set((state) => {
const comment = state.comments.find((c) => c.threadId === threadId);
if (comment) {
comment.comments = comment.comments.filter((r) => r.replyId !== _id);
const thread = state.threads.find((c) => c.threadId === threadId);
if (thread) {
thread.comments = thread.comments.filter((r) => r.replyId !== _id);
}
});
},
getCommentById: (threadId) => {
return get().comments.find((c) => c.threadId === threadId);
return get().threads.find((c) => c.threadId === threadId);
},
}))
);
};
export type CommentStoreType = ReturnType<typeof createCommentsStore>;
export type ThreadStoreType = ReturnType<typeof createThreadsStore>;

View File

@@ -1,4 +1,4 @@
interface CommentSchema {
interface ThreadSchema {
state: "active" | "inactive";
threadId: string;
creatorId: string;
@@ -18,4 +18,4 @@ interface Reply {
comment: string;
}
type CommentsSchema = CommentSchema[];
type ThreadsSchema = ThreadSchema[];