Merge branch 'main-dev' into dev-refactor

This commit is contained in:
2025-06-24 15:41:18 +05:30
114 changed files with 591 additions and 273 deletions

View File

@@ -127,6 +127,7 @@ const DashboardCard: React.FC<DashBoardCardProps> = ({
if (!projectId) return; if (!projectId) return;
try { try {
const projects = await getAllProjects(userId, organization); const projects = await getAllProjects(userId, organization);
if (!projects || !projects.Projects) return;
// console.log("projects: ", projects); // console.log("projects: ", projects);
let projectUuid = projects.Projects.find( let projectUuid = projects.Projects.find(
(val: any) => val.projectUuid === projectId || val._id === projectId (val: any) => val.projectUuid === projectId || val._id === projectId

View File

@@ -34,6 +34,7 @@ const DashboardProjects: React.FC = () => {
const fetchAllProjects = async () => { const fetchAllProjects = async () => {
try { try {
const projects = await getAllProjects(userId, organization); const projects = await getAllProjects(userId, organization);
if (!projects || !projects.Projects) return;
if (JSON.stringify(projects) !== JSON.stringify(workspaceProjects)) { if (JSON.stringify(projects) !== JSON.stringify(workspaceProjects)) {
setWorkspaceProjects(projects); setWorkspaceProjects(projects);

View File

@@ -3,6 +3,7 @@ import {
useLoadingProgress, useLoadingProgress,
useRenameModeStore, useRenameModeStore,
useSaveVersion, useSaveVersion,
useSelectedComment,
useSelectedFloorItem, useSelectedFloorItem,
useSocketStore, useSocketStore,
useWidgetSubOption, useWidgetSubOption,
@@ -39,6 +40,7 @@ import { useVersionHistoryStore } from "../../../store/builder/useVersionHistory
import { useVersionContext } from "../../../modules/builder/version/versionContext"; import { useVersionContext } from "../../../modules/builder/version/versionContext";
import VersionSaved from "../sidebarRight/versionHisory/VersionSaved"; import VersionSaved from "../sidebarRight/versionHisory/VersionSaved";
import Footer from "../../footer/Footer"; import Footer from "../../footer/Footer";
import ThreadChat from "../../ui/collaboration/ThreadChat";
function MainScene() { function MainScene() {
const { setMainProduct } = useMainProduct(); const { setMainProduct } = useMainProduct();
@@ -64,6 +66,7 @@ function MainScene() {
const { versionHistory } = useVersionHistoryStore(); const { versionHistory } = useVersionHistoryStore();
const { selectedVersionStore } = useVersionContext(); const { selectedVersionStore } = useVersionContext();
const { selectedVersion, setSelectedVersion } = selectedVersionStore(); const { selectedVersion, setSelectedVersion } = selectedVersionStore();
const { selectedComment, commentPositionState } = useSelectedComment();
useEffect(() => { useEffect(() => {
if (activeModule !== 'simulation') { if (activeModule !== 'simulation') {
@@ -185,6 +188,7 @@ function MainScene() {
{activeModule !== "market" && !selectedUser && <Footer />} {activeModule !== "market" && !selectedUser && <Footer />}
<VersionSaved /> <VersionSaved />
{(commentPositionState !== null || selectedComment !== null) && <ThreadChat/>}
</> </>
); );

View File

@@ -5,16 +5,25 @@ import FileMenu from "../../ui/FileMenu";
import { useToggleStore } from "../../../store/useUIToggleStore"; import { useToggleStore } from "../../../store/useUIToggleStore";
import useModuleStore from "../../../store/useModuleStore"; import useModuleStore from "../../../store/useModuleStore";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import useRestStates from "../../../hooks/useResetStates";
const Header: React.FC = () => { const Header: React.FC = () => {
const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore(); const { toggleUILeft, toggleUIRight, setToggleUI } = useToggleStore();
const { activeModule } = useModuleStore(); const { activeModule } = useModuleStore();
const navigate = useNavigate(); const navigate = useNavigate();
const { resetStates } = useRestStates();
return ( return (
<div className="header-container"> <div className="header-container">
<div className="header-content"> <div className="header-content">
<button className="logo-container" onClick={() => navigate("/Dashboard")} title="Back to Dashboard"> <button
className="logo-container"
onClick={() => {
resetStates();
navigate("/Dashboard")
}}
title="Back to Dashboard"
>
<LogoIcon /> <LogoIcon />
</button> </button>
<div className="header-title"> <div className="header-title">

View File

@@ -23,6 +23,7 @@ const LoadingPage: React.FC<LoadingPageProps> = ({ progress }) => {
if (!userId) return; if (!userId) return;
getAllProjects(userId, organization).then((projects) => { getAllProjects(userId, organization).then((projects) => {
if (!projects || !projects.Projects) return;
const filterProject = projects?.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId); const filterProject = projects?.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId);
if (filterProject) { if (filterProject) {
setProjectName(filterProject.projectName); setProjectName(filterProject.projectName);

View File

@@ -51,6 +51,7 @@ const FileMenu: React.FC = () => {
if (!email || !userId) return; if (!email || !userId) return;
const projects = await getAllProjects(userId, organization); const projects = await getAllProjects(userId, organization);
if (!projects || !projects.Projects) return;
// console.log('projects: ', projects); // console.log('projects: ', projects);
let projectUuid = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId) let projectUuid = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId)

View File

@@ -10,6 +10,7 @@ import { useCommentStore } from "../../../store/collaboration/useCommentStore";
import { useSelectedComment, useSocketStore } from "../../../store/builder/store"; import { useSelectedComment, useSocketStore } from "../../../store/builder/store";
import { getRelativeTime } from "./function/getRelativeTime"; import { getRelativeTime } from "./function/getRelativeTime";
import { editThreadTitleApi } from "../../../services/factoryBuilder/comments/editThreadTitleApi"; import { editThreadTitleApi } from "../../../services/factoryBuilder/comments/editThreadTitleApi";
import { useVersionContext } from "../../../modules/builder/version/versionContext";
interface MessageProps { interface MessageProps {
@@ -34,8 +35,9 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
const { threadSocket } = useSocketStore(); const { threadSocket } = useSocketStore();
const { userName, userId, organization } = getUserData(); const { userName, userId, organization } = getUserData();
const [isEditComment, setIsEditComment] = useState(false) const [isEditComment, setIsEditComment] = useState(false)
const { selectedComment, setCommentPositionState } = useSelectedComment(); const { selectedComment, setCommentPositionState } = useSelectedComment();
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
// input // input
const [value, setValue] = useState<string>( const [value, setValue] = useState<string>(
@@ -59,11 +61,11 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
const handleSaveAction = async () => { const handleSaveAction = async () => {
if (!projectId) return if (!projectId || !selectedVersion) return
if (isEditableThread && editedThread) { if (isEditableThread && editedThread) {
try { try {
// const editThreadTitle = await editThreadTitleApi(projectId, (val as CommentSchema).threadId, value) // const editThreadTitle = await editThreadTitleApi(projectId, (val as CommentSchema).threadId, value, selectedVersion?.versionId || "")
// if (editThreadTitle.message == "ThreadTitle updated Successfully") { // if (editThreadTitle.message == "ThreadTitle updated Successfully") {
// const editedThread: CommentSchema = { // const editedThread: CommentSchema = {
// state: 'active', // state: 'active',
@@ -74,7 +76,7 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
// lastUpdatedAt: new Date().toISOString(), // lastUpdatedAt: new Date().toISOString(),
// position: editThreadTitle.data.position, // position: editThreadTitle.data.position,
// rotation: [0, 0, 0], // rotation: [0, 0, 0],
// comments: [] // comments: [],
// } // }
// updateComment((val as CommentSchema).threadId, editedThread) // updateComment((val as CommentSchema).threadId, editedThread)
// } // }
@@ -84,17 +86,17 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
userId, userId,
threadTitle: value, threadTitle: value,
organization, organization,
threadId: (val as CommentSchema).threadId threadId: (val as CommentSchema).threadId || selectedComment.threadId,
versionId: selectedVersion?.versionId || ""
} }
threadSocket.emit('v1:thread:updateTitle', threadEdit) threadSocket.emit('v1:thread:updateTitle', threadEdit)
} catch { } catch {
} }
} else { } else {
if (mode === "edit") { if (mode === "edit") {
try { try {
// const editComments = await addCommentsApi(projectId, value, selectedComment?.threadId, (val as Reply).replyId) // const editComments = await addCommentsApi(projectId, value, selectedComment?.threadId, (val as Reply).replyId, selectedVersion?.versionId || "")
// //
// const commentData = { // const commentData = {
// replyId: `${editComments.data?.replyId}`, // replyId: `${editComments.data?.replyId}`,
@@ -114,7 +116,8 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
comment: value, comment: value,
organization, organization,
threadId: selectedComment?.threadId, threadId: selectedComment?.threadId,
commentId: (val as Reply).replyId ?? "" commentId: (val as Reply).replyId ?? "",
versionId: selectedVersion?.versionId || ""
} }
@@ -133,10 +136,10 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
} }
const handleDeleteAction = async (replyID: any) => { const handleDeleteAction = async (replyID: any) => {
if (!projectId) return if (!projectId || !selectedVersion) return
setOpenOptions(false); setOpenOptions(false);
try { try {
// const deletedComment = await deleteCommentApi(projectId, selectedComment?.threadId, (val as Reply).replyId) // const deletedComment = await deleteCommentApi(projectId, selectedComment?.threadId, (val as Reply).replyId , selectedVersion?.versionId || "")
// //
// if (deletedComment === "'Thread comment deleted Successfully'") { // if (deletedComment === "'Thread comment deleted Successfully'") {
// setMessages && setMessages(prev => prev.filter(message => message.replyId !== replyID)); // setMessages && setMessages(prev => prev.filter(message => message.replyId !== replyID));
@@ -151,13 +154,16 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
userId, userId,
commentId: (val as Reply).replyId, commentId: (val as Reply).replyId,
organization, organization,
threadId: selectedComment?.threadId threadId: selectedComment?.threadId,
versionId: selectedVersion?.versionId || ""
} }
setMessages(prev => {
// 👈 logs the current state
setMessages(prev => prev.filter(message => message.replyId !== (val as Reply).replyId)) return prev.filter(message => message.replyId !== (val as Reply).replyId);
});
removeReply(selectedComment?.threadId, (val as Reply).replyId); // Remove listener after response removeReply(selectedComment?.threadId, (val as Reply).replyId); // Remove listener after response
threadSocket.emit("v1-Comment:delete", deleteComment); threadSocket.emit("v1-Comment:delete", deleteComment);
} }
} catch { } catch {
@@ -173,7 +179,7 @@ const Messages: React.FC<MessageProps> = ({ val, i, setMessages, mode, setIsEdit
} }
}); });
}; };
return ( return (
<> <>
{isEditComment ? ( {isEditComment ? (

View File

@@ -12,7 +12,7 @@ import { addCommentsApi } from "../../../services/factoryBuilder/comments/addCom
import { deleteThreadApi } from "../../../services/factoryBuilder/comments/deleteThreadApi"; import { deleteThreadApi } from "../../../services/factoryBuilder/comments/deleteThreadApi";
import { createThreadApi } from "../../../services/factoryBuilder/comments/createThreadApi"; import { createThreadApi } from "../../../services/factoryBuilder/comments/createThreadApi";
import { getRelativeTime } from "./function/getRelativeTime"; import { getRelativeTime } from "./function/getRelativeTime";
import { useVersionContext } from "../../../modules/builder/version/versionContext";
const ThreadChat: React.FC = () => { const ThreadChat: React.FC = () => {
const { userId, organization } = getUserData(); const { userId, organization } = getUserData();
@@ -35,6 +35,8 @@ const ThreadChat: React.FC = () => {
const { threadSocket } = useSocketStore(); const { threadSocket } = useSocketStore();
const modeRef = useRef<'create' | 'edit' | null>(null); const modeRef = useRef<'create' | 'edit' | null>(null);
const messagesRef = useRef<HTMLDivElement>(null); const messagesRef = useRef<HTMLDivElement>(null);
const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore();
useEffect(() => { useEffect(() => {
modeRef.current = mode; modeRef.current = mode;
@@ -42,7 +44,6 @@ const ThreadChat: React.FC = () => {
useEffect(() => { useEffect(() => {
if (comments.length > 0 && selectedComment) { if (comments.length > 0 && selectedComment) {
const allMessages = comments const allMessages = comments
.flatMap((val: any) => .flatMap((val: any) =>
@@ -50,20 +51,20 @@ const ThreadChat: React.FC = () => {
) )
.map((c) => { .map((c) => {
return { return {
replyId: c._id ?? "", replyId: c._id ?? c.replyId,
creatorId: c.creatorId || c.userId, creatorId: c.creatorId || c.userId,
createdAt: c.createdAt, createdAt: c.createdAt,
lastUpdatedAt: "1 hr ago", lastUpdatedAt: "1 hr ago",
comment: c.comment, comment: c.comment,
_id: c._id ?? "", _id: c._id ?? c.replyId,
}; };
}); });
setMessages(allMessages); setMessages(allMessages);
} }
}, [selectedComment]) }, [])
useEffect(() => { useEffect(() => {
if (textareaRef.current) adjustHeight(textareaRef.current); if (textareaRef.current) adjustHeight(textareaRef.current);
@@ -145,7 +146,7 @@ const ThreadChat: React.FC = () => {
const handleCreateComments = async (e: any) => { const handleCreateComments = async (e: any) => {
e.preventDefault(); e.preventDefault();
try { try {
// const createComments = await addCommentsApi(projectId, value, selectedComment?.threadId)/ // const createComments = await addCommentsApi(projectId, value, selectedComment?.threadId, selectedVersion?.versionId || "")/
// if (createComments.message === 'Thread comments add Successfully' && createComments.data) { // if (createComments.message === 'Thread comments add Successfully' && createComments.data) {
// const commentData = { // const commentData = {
// replyId: `${createComments.data?._id}`, // replyId: `${createComments.data?._id}`,
@@ -164,11 +165,13 @@ const ThreadChat: React.FC = () => {
if (threadSocket && mode === "create") { if (threadSocket && mode === "create") {
const addComment = { const addComment = {
versionId: selectedVersion?.versionId || "",
projectId, projectId,
userId, userId,
comment: value, comment: value,
organization, organization,
threadId: selectedComment?.threadId threadId: selectedComment?.threadId,
} }
threadSocket.emit("v1-Comment:add", addComment); threadSocket.emit("v1-Comment:add", addComment);
@@ -181,21 +184,22 @@ const ThreadChat: React.FC = () => {
const handleDeleteThread = async () => { const handleDeleteThread = async () => {
if (!projectId) return; if (!projectId) return;
try { try {
// const deleteThread = await deleteThreadApi(projectId, selectedComment?.threadId) // const deleteThread = await deleteThreadApi(projectId, selectedComment?.threadId, selectedVersion?.versionId || "")
// //
// if (deleteThread.message === "Thread deleted Successfully") { // if (deleteThread.message === "Thread deleted Successfully") {
// removeComment(selectedComment?.threadId) // removeComment(selectedComment?.threadId)
// setSelectedComment([]) // setSelectedComment([])
// } // }
console.log('threadSocket:threadChat ', threadSocket);
if (threadSocket) { if (threadSocket) {
// projectId, userId, organization, threadId // projectId, userId, organization, threadId
const deleteThread = { const deleteThread = {
projectId, projectId,
userId, userId,
organization, organization,
threadId: selectedComment?.threadId threadId: selectedComment?.threadId,
versionId: selectedVersion?.versionId || ""
} }
setSelectedComment(null) setSelectedComment(null)
removeComment(selectedComment?.threadId) removeComment(selectedComment?.threadId)
threadSocket.emit("v1:thread:delete", deleteThread); threadSocket.emit("v1:thread:delete", deleteThread);
@@ -213,11 +217,12 @@ const ThreadChat: React.FC = () => {
try { try {
// try { // try {
// const thread = await createThreadApi( // const thread = await createThreadApi(
// projectId, // projectId,
// "active", // "active",
// commentPositionState[0].position, // commentPositionState[0].position,
// [0, 0, 0], // [0, 0, 0],
// value // value,
// selectedVersion?.versionId || ""
// ); // );
// //
// //
@@ -243,18 +248,17 @@ const ThreadChat: React.FC = () => {
const createThread = { const createThread = {
projectId, projectId,
versionId: selectedVersion?.versionId || "",
userId, userId,
organization, organization,
state: "active", state: "active",
position: commentPositionState.position, position: commentPositionState.position,
rotation: [0, 0, 0], rotation: [0, 0, 0],
threadTitle: value threadTitle: value,
}; };
if (threadSocket) { if (threadSocket) {
console.log('createThread: ', createThread);
setInputActive(false); setInputActive(false);
threadSocket.emit("v1:thread:create", createThread); threadSocket.emit("v1:thread:create", createThread);

View File

@@ -22,7 +22,7 @@ export const getUserData = (): UserData => {
const [_, emailDomain] = email.split("@"); const [_, emailDomain] = email.split("@");
if (!emailDomain) { if (!emailDomain) {
throw new Error("Invalid email format"); console.error("Invalid email format");
} }
const [organization] = emailDomain.split("."); const [organization] = emailDomain.split(".");

View File

View File

@@ -0,0 +1,26 @@
import { useVersionContext } from "../modules/builder/version/versionContext";
import { useSceneContext } from "../modules/scene/sceneContext";
import { useProductContext } from "../modules/simulation/products/productContext";
import { useVersionHistoryStore } from "../store/builder/useVersionHistoryStore";
const useRestStates = () => {
const { selectedVersionStore } = useVersionContext();
const { clearSelectedVersion } = selectedVersionStore();
const { selectedProductStore } = useProductContext();
const { clearSelectedProduct } = selectedProductStore();
const { clearVersions } = useVersionHistoryStore();
const { clearStores } = useSceneContext();
const resetStates = () => {
clearSelectedVersion();
clearSelectedProduct();
clearVersions();
clearStores();
};
return {
resetStates,
};
};
export default useRestStates;

View File

@@ -16,7 +16,7 @@ async function loadInitialWallItems(
const { organization, email } = getUserData(); const { organization, email } = getUserData();
if (!email) { if (!email) {
throw new Error("No email found in localStorage"); console.error("No email found in localStorage");
} }
const items = await getWallItems(organization, projectId, versionId); const items = await getWallItems(organization, projectId, versionId);

View File

@@ -48,14 +48,11 @@ function AisleInstances() {
{toggleView && {toggleView &&
<Html <Html
// data
key={`${aisle.points[0].pointUuid}_${aisle.points[1].pointUuid}`} key={`${aisle.points[0].pointUuid}_${aisle.points[1].pointUuid}`}
userData={aisle} userData={aisle}
position={[textPosition.x, 1, textPosition.z]} position={[textPosition.x, 1, textPosition.z]}
// class
wrapperClass="distance-text-wrapper" wrapperClass="distance-text-wrapper"
className="distance-text" className="distance-text"
// other
zIndexRange={[1, 0]} zIndexRange={[1, 0]}
prepend prepend
sprite sprite
@@ -68,7 +65,6 @@ function AisleInstances() {
</div> </div>
</Html> </Html>
} }
</React.Fragment> </React.Fragment>
) )
})} })}

View File

@@ -104,7 +104,7 @@ export default function Builder() {
const { setWalls } = useWalls(); const { setWalls } = useWalls();
const { refTextupdate, setRefTextUpdate } = useRefTextUpdate(); const { refTextupdate, setRefTextUpdate } = useRefTextUpdate();
const { projectId } = useParams(); const { projectId } = useParams();
const { setHoveredPoint } = useBuilderStore(); const { setHoveredPoint, setHoveredLine } = useBuilderStore();
const { userId, organization } = getUserData(); const { userId, organization } = getUserData();
// const loader = new GLTFLoader(); // const loader = new GLTFLoader();
@@ -127,7 +127,9 @@ export default function Builder() {
dragPointControls dragPointControls
); );
} else { } else {
setHoveredLine(null);
setHoveredPoint(null); setHoveredPoint(null);
state.gl.domElement.style.cursor = 'default';
setToolMode('cursor'); setToolMode('cursor');
loadWalls(lines, setWalls); loadWalls(lines, setWalls);
setUpdateScene(true); setUpdateScene(true);

View File

@@ -123,7 +123,7 @@ function loadOnlyFloors(
const originalPoint = originalLines.flat().find(([point]) => point.x === x && point.z === z); const originalPoint = originalLines.flat().find(([point]) => point.x === x && point.z === z);
if (!originalPoint) { if (!originalPoint) {
throw new Error(`Original point for coordinate [${x}, ${z}] not found.`); console.error(`Original point for coordinate [${x}, ${z}] not found.`);
} }
return originalPoint; return originalPoint;

View File

@@ -39,7 +39,7 @@ const ZoneGroup: React.FC = () => {
const { selectedVersionStore } = useVersionContext(); const { selectedVersionStore } = useVersionContext();
const { selectedVersion } = selectedVersionStore(); const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams(); const { projectId } = useParams();
const { userId, organization, email } = getUserData(); const { userId, organization } = getUserData();
const groupsRef = useRef<any>(); const groupsRef = useRef<any>();
@@ -384,13 +384,7 @@ const ZoneGroup: React.FC = () => {
drag = true; drag = true;
} }
raycaster.setFromCamera(pointer, camera); raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObjects(groupsRef.current.children, true);
if (intersects.length > 0 && intersects[0].object.name.includes("point")) {
gl.domElement.style.cursor = toolMode === "move" ? "pointer" : "default";
} else {
gl.domElement.style.cursor = "default";
}
if (isDragging && draggedSphere) { if (isDragging && draggedSphere) {
raycaster.setFromCamera(pointer, camera); raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3(); const intersectionPoint = new THREE.Vector3();

View File

@@ -1,13 +1,26 @@
import * as THREE from 'three'; import * as THREE from 'three';
import { useMemo } from "react"; import { useEffect, useMemo, useState } from "react";
import * as Constants from '../../../types/world/worldConstants'; import * as Constants from '../../../types/world/worldConstants';
import { Tube } from '@react-three/drei'; import { DragControls, Tube } from '@react-three/drei';
import { useToolMode } from '../../../store/builder/store';
import { useBuilderStore } from '../../../store/builder/useBuilderStore';
import { useWallStore } from '../../../store/builder/useWallStore';
import { useThree } from '@react-three/fiber';
interface LineProps { interface LineProps {
points: [Point, Point]; points: [Point, Point];
} }
function Line({ points }: Readonly<LineProps>) { function Line({ points }: Readonly<LineProps>) {
const [isHovered, setIsHovered] = useState(false);
const { raycaster, camera, pointer, gl } = useThree();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const [isDeletable, setIsDeletable] = useState(false);
const { toolMode } = useToolMode();
const { removeWallByPoints, setPosition } = useWallStore();
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
const { hoveredLine, setHoveredLine, hoveredPoint } = useBuilderStore();
const path = useMemo(() => { const path = useMemo(() => {
const [start, end] = points.map(p => new THREE.Vector3(...p.position)); const [start, end] = points.map(p => new THREE.Vector3(...p.position));
return new THREE.LineCurve3(start, end); return new THREE.LineCurve3(start, end);
@@ -44,16 +57,119 @@ function Line({ points }: Readonly<LineProps>) {
} }
} }
useEffect(() => {
if (toolMode === '2D-Delete') {
if (isHovered && !hoveredPoint) {
setIsDeletable(true);
} else {
setIsDeletable(false);
}
} else {
setIsDeletable(false);
}
}, [isHovered, colors.defaultLineColor, colors.defaultDeleteColor, toolMode, hoveredPoint]);
useEffect(() => {
if (hoveredLine && (hoveredLine[0].pointUuid !== points[0].pointUuid || hoveredLine[1].pointUuid !== points[1].pointUuid)) {
setIsHovered(false);
}
}, [hoveredLine])
const handlePointClick = (points: [Point, Point]) => {
if (toolMode === '2D-Delete') {
if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
removeWallByPoints(points);
}
gl.domElement.style.cursor = 'default';
}
}
const handleDrag = (points: [Point, Point]) => {
if (toolMode === 'move' && isHovered && dragOffset) {
raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3();
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
gl.domElement.style.cursor = 'move';
const positionWithOffset = new THREE.Vector3().addVectors(hit, dragOffset);
const start = new THREE.Vector3(...points[0].position);
const end = new THREE.Vector3(...points[1].position);
const midPoint = new THREE.Vector3().addVectors(start, end).multiplyScalar(0.5);
const delta = new THREE.Vector3().subVectors(positionWithOffset, midPoint);
const newStart = new THREE.Vector3().addVectors(start, delta);
const newEnd = new THREE.Vector3().addVectors(end, delta);
setPosition(points[0].pointUuid, [newStart.x, newStart.y, newStart.z]);
setPosition(points[1].pointUuid, [newEnd.x, newEnd.y, newEnd.z]);
}
}
};
const handleDragStart = (points: [Point, Point]) => {
raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3();
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit && !hoveredPoint) {
const start = new THREE.Vector3(...points[0].position);
const end = new THREE.Vector3(...points[1].position);
const midPoint = new THREE.Vector3().addVectors(start, end).multiplyScalar(0.5);
const offset = new THREE.Vector3().subVectors(midPoint, hit);
setDragOffset(offset);
}
};
const handleDragEnd = (points: [Point, Point]) => {
gl.domElement.style.cursor = 'default';
setDragOffset(null);
if (toolMode !== 'move') return;
if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
// console.log('Wall after drag: ', points);
}
}
return ( return (
<Tube <DragControls
name={`${points[0].pointType}-Line`} axisLock="y"
key={`${points[0].pointUuid}-${points[1].pointUuid}`} autoTransform={false}
uuid={`${points[0].pointUuid}-${points[1].pointUuid}`} onDragStart={() => handleDragStart(points)}
userData={{ points, path }} onDrag={() => handleDrag(points)}
args={[path, Constants.lineConfig.tubularSegments, Constants.lineConfig.radius, Constants.lineConfig.radialSegments, false]} onDragEnd={() => handleDragEnd(points)}
> >
<meshStandardMaterial color={colors.defaultLineColor} /> <Tube
</Tube> name={`${points[0].pointType}-Line`}
key={`${points[0].pointUuid}-${points[1].pointUuid}`}
uuid={`${points[0].pointUuid}-${points[1].pointUuid}`}
userData={{ points, path }}
args={[path, Constants.lineConfig.tubularSegments, Constants.lineConfig.radius, Constants.lineConfig.radialSegments, false]}
onClick={() => {
handlePointClick(points);
}}
onPointerOver={() => {
if (!hoveredLine) {
setHoveredLine(points);
setIsHovered(true)
if (toolMode === 'move' && !hoveredPoint) {
gl.domElement.style.cursor = 'pointer';
}
}
}}
onPointerOut={() => {
if (hoveredLine) {
setHoveredLine(null);
gl.domElement.style.cursor = 'default';
}
setIsHovered(false)
}}
>
<meshStandardMaterial color={isDeletable ? colors.defaultDeleteColor : colors.defaultLineColor} />
</Tube>
</DragControls >
); );
} }

View File

@@ -15,9 +15,10 @@ import { useSceneContext } from '../../scene/sceneContext';
function Point({ point }: { readonly point: Point }) { function Point({ point }: { readonly point: Point }) {
const materialRef = useRef<THREE.ShaderMaterial>(null); const materialRef = useRef<THREE.ShaderMaterial>(null);
const { raycaster, camera, pointer } = useThree(); const { raycaster, camera, pointer, gl } = useThree();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []); const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const [isHovered, setIsHovered] = useState(false); const [isHovered, setIsHovered] = useState(false);
const [dragOffset, setDragOffset] = useState<THREE.Vector3 | null>(null);
const { toolMode } = useToolMode(); const { toolMode } = useToolMode();
const { aisleStore } = useSceneContext(); const { aisleStore } = useSceneContext();
const { setPosition: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = aisleStore(); const { setPosition: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = aisleStore();
@@ -91,33 +92,45 @@ function Point({ point }: { readonly point: Point }) {
}), [colors.defaultInnerColor, colors.defaultOuterColor]); }), [colors.defaultInnerColor, colors.defaultOuterColor]);
const handleDrag = (point: Point) => { const handleDrag = (point: Point) => {
if (toolMode === 'move' && isHovered) { if (toolMode === 'move' && isHovered && dragOffset) {
raycaster.setFromCamera(pointer, camera); raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3(); const intersectionPoint = new THREE.Vector3();
const position = raycaster.ray.intersectPlane(plane, intersectionPoint); const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (point.pointType === 'Aisle') {
if (position) {
const newPosition: [number, number, number] = [position.x, position.y, position.z];
const aisleSnappedPosition = snapAisleAngle(newPosition);
const finalSnappedPosition = snapAislePoint(aisleSnappedPosition.position);
setAislePosition(point.pointUuid, finalSnappedPosition.position); if (hit) {
gl.domElement.style.cursor = 'move';
const positionWithOffset = new THREE.Vector3().addVectors(hit, dragOffset);
const newPosition: [number, number, number] = [positionWithOffset.x, positionWithOffset.y, positionWithOffset.z];
} if (point.pointType === 'Aisle') {
} else if (point.pointType === 'Wall') { const aisleSnapped = snapAisleAngle(newPosition);
if (position) { const finalSnapped = snapAislePoint(aisleSnapped.position);
const newPosition: [number, number, number] = [position.x, position.y, position.z]; setAislePosition(point.pointUuid, finalSnapped.position);
const wallSnappedPosition = snapWallAngle(newPosition); } else if (point.pointType === 'Wall') {
const finalSnappedPosition = snapWallPoint(wallSnappedPosition.position); const wallSnapped = snapWallAngle(newPosition);
const finalSnapped = snapWallPoint(wallSnapped.position);
setWallPosition(point.pointUuid, finalSnappedPosition.position); setWallPosition(point.pointUuid, finalSnapped.position);
} }
} }
} }
} };
const handleDragStart = (point: Point) => {
raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3();
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
const currentPosition = new THREE.Vector3(...point.position);
const offset = new THREE.Vector3().subVectors(currentPosition, hit);
setDragOffset(offset);
}
};
const handleDragEnd = (point: Point) => { const handleDragEnd = (point: Point) => {
if (toolMode === '2D-Delete') return; gl.domElement.style.cursor = 'default';
setDragOffset(null);
if (toolMode !== 'move') return;
if (point.pointType === 'Aisle') { if (point.pointType === 'Aisle') {
const updatedAisles = getAislesByPointId(point.pointUuid); const updatedAisles = getAislesByPointId(point.pointUuid);
if (updatedAisles.length > 0 && projectId) { if (updatedAisles.length > 0 && projectId) {
@@ -148,6 +161,7 @@ function Point({ point }: { readonly point: Point }) {
setHoveredPoint(null); setHoveredPoint(null);
} }
} }
gl.domElement.style.cursor = 'default';
} }
} }
@@ -165,8 +179,9 @@ function Point({ point }: { readonly point: Point }) {
<DragControls <DragControls
axisLock='y' axisLock='y'
autoTransform={false} autoTransform={false}
onDrag={() => { handleDrag(point) }} onDragStart={() => handleDragStart(point)}
onDragEnd={() => { handleDragEnd(point) }} onDrag={() => handleDrag(point)}
onDragEnd={() => handleDragEnd(point)}
> >
<mesh <mesh
key={point.pointUuid} key={point.pointUuid}
@@ -179,12 +194,16 @@ function Point({ point }: { readonly point: Point }) {
onPointerOver={() => { onPointerOver={() => {
if (!hoveredPoint) { if (!hoveredPoint) {
setHoveredPoint(point); setHoveredPoint(point);
setIsHovered(true) setIsHovered(true);
if (toolMode === 'move') {
gl.domElement.style.cursor = 'pointer';
}
} }
}} }}
onPointerOut={() => { onPointerOut={() => {
if (hoveredPoint) { if (hoveredPoint) {
setHoveredPoint(null); setHoveredPoint(null);
gl.domElement.style.cursor = 'default';
} }
setIsHovered(false) setIsHovered(false)
}} }}

View File

@@ -120,7 +120,6 @@ export function useWallClassification(walls: Walls) {
} }
}); });
console.log('rooms: ', rooms);
return rooms; return rooms;
}; };

View File

@@ -8,17 +8,17 @@ import { useWallStore } from '../../../../../store/builder/useWallStore';
import { useWallClassification } from './helpers/useWallClassification'; import { useWallClassification } from './helpers/useWallClassification';
import { useFrame, useThree } from '@react-three/fiber'; import { useFrame, useThree } from '@react-three/fiber';
import { useWallVisibility } from '../../../../../store/builder/store'; import { useWallVisibility } from '../../../../../store/builder/store';
import { Decal, PivotControls } from '@react-three/drei'; import { Decal } from '@react-three/drei';
import { Base, Geometry, Subtraction } from '@react-three/csg'; import { Base } from '@react-three/csg';
function Wall({ wall }: { readonly wall: Wall }) { function Wall({ wall }: { readonly wall: Wall }) {
const { walls } = useWallStore(); const { walls } = useWallStore();
const { getWallType, isWallFlipped } = useWallClassification(walls);
const wallType = getWallType(wall);
const [visible, setVisible] = useState(true);
const { wallVisibility } = useWallVisibility();
const meshRef = useRef<any>();
const { camera } = useThree(); const { camera } = useThree();
const { wallVisibility } = useWallVisibility();
const { getWallType, isWallFlipped } = useWallClassification(walls);
const [visible, setVisible] = useState(true);
const meshRef = useRef<any>();
const wallType = getWallType(wall);
const wallFlipped = isWallFlipped(wall); const wallFlipped = isWallFlipped(wall);
@@ -84,7 +84,6 @@ function Wall({ wall }: { readonly wall: Wall }) {
camera.getWorldDirection(u); camera.getWorldDirection(u);
if (!u || !v) return; if (!u || !v) return;
setVisible((2 * v.dot(u)) <= 0.1); setVisible((2 * v.dot(u)) <= 0.1);
} else { } else {
setVisible(true); setVisible(true);
} }

View File

@@ -1,13 +1,22 @@
import React, { useEffect, useMemo, useRef } from 'react'; import React, { useEffect, useMemo } from 'react';
import { DoubleSide, RepeatWrapping, Shape, SRGBColorSpace, TextureLoader, Vector2, Vector3 } from 'three';
import { Geometry } from '@react-three/csg';
import { Html, Extrude } from '@react-three/drei';
import { useWallStore } from '../../../../store/builder/useWallStore' import { useWallStore } from '../../../../store/builder/useWallStore'
import WallInstance from './instance/wallInstance'; import { useWallClassification } from './instance/helpers/useWallClassification';
import { useToggleView } from '../../../../store/builder/store';
import Line from '../../line/line'; import Line from '../../line/line';
import Point from '../../point/point'; import Point from '../../point/point';
import { useToggleView } from '../../../../store/builder/store'; import WallInstance from './instance/wallInstance';
import { Geometry } from '@react-three/csg'; import * as Constants from '../../../../types/world/worldConstants';
import texturePath from "../../../../assets/textures/floor/white.png";
import texturePathDark from "../../../../assets/textures/floor/black.png";
import { useLoader } from '@react-three/fiber';
function WallInstances() { function WallInstances() {
const { walls } = useWallStore(); const { walls } = useWallStore();
const { rooms } = useWallClassification(walls)
const { toggleView } = useToggleView(); const { toggleView } = useToggleView();
useEffect(() => { useEffect(() => {
@@ -32,24 +41,22 @@ function WallInstances() {
return ( return (
<> <>
{!toggleView && ( {!toggleView && (
<>
<mesh name='Walls-Group'> <mesh name='Walls-Group'>
{/* <Base name="base" geometry={box} scale={[3, 3, 3]} /> */} <Geometry useGroups>
{walls.map((wall) => (
<Geometry useGroups> <WallInstance key={wall.wallUuid} wall={wall} />
{walls.map((wall) => ( ))}
<WallInstance key={wall.wallUuid} wall={wall} />
))}
</Geometry>
{/* <Subtraction rotation={[0, Math.PI / 2, 0]} position={[-1.425, -0.45, 0]} scale={[1, 3, 1]}>
<Geometry>
<Base geometry={box} />
</Geometry> </Geometry>
</Subtraction> */} </mesh>
</mesh>
<group name='Wall-Floors-Group'>
{rooms.map((room, index) => (
<Floor key={index} room={room} />
))}
</group>
</>
)} )}
{toggleView && ( {toggleView && (
@@ -61,11 +68,42 @@ function WallInstances() {
</group> </group>
<group name='Wall-Lines-Group'> <group name='Wall-Lines-Group'>
{walls.map((wall) => ( {walls.map((wall) => (
<React.Fragment key={wall.wallUuid}> <React.Fragment key={wall.wallUuid}>
<Line points={wall.points} /> <Line points={wall.points} />
</React.Fragment> </React.Fragment>
))} ))}
{walls.map((wall) => {
const textPosition = new Vector3().addVectors(new Vector3(...wall.points[0].position), new Vector3(...wall.points[1].position)).divideScalar(2);
const distance = new Vector3(...wall.points[0].position).distanceTo(new Vector3(...wall.points[1].position));
return (
< React.Fragment key={wall.wallUuid}>
{toggleView &&
<Html
key={`${wall.points[0].pointUuid}_${wall.points[1].pointUuid}`}
userData={wall}
position={[textPosition.x, 1, textPosition.z]}
wrapperClass="distance-text-wrapper"
className="distance-text"
zIndexRange={[1, 0]}
prepend
sprite
>
<div
key={wall.wallUuid}
className={`distance ${wall.wallUuid}`}
>
{distance.toFixed(2)} m
</div>
</Html>
}
</React.Fragment>
)
})}
</group> </group>
</> </>
)} )}
@@ -73,4 +111,36 @@ function WallInstances() {
) )
} }
export default WallInstances export default WallInstances;
function Floor({ room }: { room: Point[] }) {
const savedTheme: string | null = localStorage.getItem('theme');
const textureScale = Constants.floorConfig.textureScale;
const floorTexture = useLoader(TextureLoader, savedTheme === "dark" ? texturePathDark : texturePath);
floorTexture.wrapS = floorTexture.wrapT = RepeatWrapping;
floorTexture.repeat.set(textureScale, textureScale);
floorTexture.colorSpace = SRGBColorSpace;
const shape = useMemo(() => {
const shape = new Shape();
const points = room.map(p => new Vector2(p.position[0], p.position[2]));
if (points.length < 3) return null;
shape.moveTo(points[0].x, points[0].y);
points.forEach((pt) => { shape.lineTo(pt.x, pt.y); });
return shape;
}, [room]);
if (!shape) return null;
return (
<group name="Wall-Floor" rotation={[Math.PI / 2, 0, 0]}>
<Extrude
args={[shape, { depth: Constants.floorConfig.height, bevelEnabled: false }]}
position={[0, 0, 0]}
receiveShadow
>
<meshStandardMaterial color={Constants.floorConfig.defaultColor} map={floorTexture} side={DoubleSide} />
</Extrude>
</group>
);
}

View File

@@ -243,7 +243,7 @@ function WallCreator() {
canvasElement.removeEventListener("click", onMouseClick); canvasElement.removeEventListener("click", onMouseClick);
canvasElement.removeEventListener("contextmenu", onContext); canvasElement.removeEventListener("contextmenu", onContext);
}; };
}, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addWall, getWallPointById, snappedPosition, snappedPoint]); }, [gl, camera, scene, raycaster, pointer, plane, toggleView, toolMode, activeLayer, socket, tempPoints, isCreating, addWall, getWallPointById, wallThickness, wallHeight, insideMaterial, outsideMaterial, snappedPosition, snappedPoint]);
return ( return (
<> <>

View File

@@ -1,18 +1,16 @@
import { useEffect, useState } from "react"; import { useEffect, useState } from "react";
import { useThree } from "@react-three/fiber"; import { useThree } from "@react-three/fiber";
import { MathUtils, Vector3 } from "three"; import { Vector3 } from "three";
import CommentInstances from "./instances/commentInstances"; import CommentInstances from "./instances/commentInstances";
import { Sphere } from "@react-three/drei"; import { Sphere } from "@react-three/drei";
import { useActiveTool, useSelectedComment } from "../../../store/builder/store"; import { useActiveTool, useSelectedComment } from "../../../store/builder/store";
function CommentsGroup() { function CommentsGroup() {
const { gl, raycaster, camera, scene, pointer, size } = useThree(); const { gl, raycaster, camera, scene, pointer, size } = useThree();
const { activeTool } = useActiveTool(); const { activeTool } = useActiveTool();
const [hoverPos, setHoverPos] = useState<Vector3 | null>(null); const [hoverPos, setHoverPos] = useState<Vector3 | null>(null);
const { setSelectedComment, setCommentPositionState, setPosition2Dstate } = useSelectedComment(); const { setSelectedComment, setCommentPositionState, setPosition2Dstate } = useSelectedComment();
useEffect(() => { useEffect(() => {
const canvasElement = gl.domElement; const canvasElement = gl.domElement;

View File

@@ -5,17 +5,19 @@ import { getAllThreads } from '../../../../services/factoryBuilder/comments/getA
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { getUserData } from '../../../../functions/getUserData'; import { getUserData } from '../../../../functions/getUserData';
import { getRelativeTime } from '../../../../components/ui/collaboration/function/getRelativeTime'; import { getRelativeTime } from '../../../../components/ui/collaboration/function/getRelativeTime';
import { useVersionContext } from '../../../builder/version/versionContext';
function CommentInstances() { function CommentInstances() {
const { comments, setComments } = useCommentStore(); const { comments, setComments } = useCommentStore();
const { projectId } = useParams(); const { projectId } = useParams();
const { userId } = getUserData() const { userId } = getUserData();
const getThreads = async () => { const { selectedVersionStore } = useVersionContext();
if (!projectId) return; const { selectedVersion } = selectedVersionStore();
try {
const getComments = await getAllThreads(projectId);
const getThreads = async () => {
if (!projectId || !selectedVersion) return;
try {
const getComments = await getAllThreads(projectId, selectedVersion?.versionId);
const formattedThreads = Array.isArray(getComments.data) const formattedThreads = Array.isArray(getComments.data)
? getComments.data.map((thread: any) => ({ ? getComments.data.map((thread: any) => ({
@@ -32,14 +34,12 @@ function CommentInstances() {
: [], : [],
})) }))
: []; : [];
// console.log('formattedThreads: ', formattedThreads);
setComments(formattedThreads); setComments(formattedThreads);
} catch (err) { } catch (err) {
// console.error("Failed to fetch threads:", err); // console.error("Failed to fetch threads:", err);
} }
} }
useEffect(() => { useEffect(() => {
getThreads(); getThreads();
}, []); }, []);

View File

@@ -14,12 +14,13 @@ interface ThreadSocketProps {
const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSocketProps) => { const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSocketProps) => {
const { threadSocket } = useSocketStore(); const { threadSocket } = useSocketStore();
const { selectedComment, setSelectedComment, setCommentPositionState, commentPositionState } = useSelectedComment(); const { selectedComment, setSelectedComment, setCommentPositionState, commentPositionState } = useSelectedComment();
const { comments, addComment, addReply, updateComment, updateReply } = useCommentStore(); const { comments, removeReply, addComment, addReply, updateComment, updateReply } = useCommentStore();
const { userId } = getUserData(); const { userId } = getUserData();
useEffect(() => { useEffect(() => {
if (!threadSocket) return; if (!threadSocket) return;
// --- Add Comment Handler --- // --- Add Comment Handler ---
// const handleAddComment = (data: any) => { // const handleAddComment = (data: any) => {
// //
@@ -55,23 +56,21 @@ const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSock
// }; // };
// threadSocket.on('v1-Comment:response:add', handleAddComment); // threadSocket.on('v1-Comment:response:add', handleAddComment);
const handleAddComment = (data: any) => { const handleAddComment = (data: any) => {
// console.log('Add: ', data);
const commentData = { const commentData = {
replyId: data.data?._id, replyId: data.data?._id,
creatorId: data.data?.userId, creatorId: data.data?.userId,
createdAt: getRelativeTime(data.data?.createdAt), createdAt: getRelativeTime(data.data?.createdAt),
lastUpdatedAt: "2 hrs ago", lastUpdatedAt: "2 hrs ago",
comment: data.data.comment, comment: data.data?.comment,
}; };
if (modeRef.current === "create") { if (modeRef.current === "create") {
addReply(selectedComment?.threadId, commentData); addReply(selectedComment?.threadId, commentData);
setMessages((prevMessages) => [...prevMessages, commentData]); setMessages((prevMessages) => [...prevMessages, commentData]);
} else if (modeRef.current === "edit") { } else if (modeRef.current === "edit") {
updateReply(selectedComment?.threadId, data.data?._id, commentData); updateReply(selectedComment?.threadId, data.data?._id, commentData);
setMessages((prev) => setMessages((prev) =>
prev.map((message) => { prev.map((message) => {
@@ -81,26 +80,22 @@ const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSock
: message; : message;
}) })
); );
// console.log('data.data?.comment: ', data.data?.comment);
} else { } else {
} }
threadSocket.off("v1-Comment:response:add", handleAddComment);
}; };
threadSocket.on('v1-Comment:response:add', handleAddComment); threadSocket.on('v1-Comment:response:add', handleAddComment);
// --- Delete Comment Handler --- // --- Delete Comment Handler ---
const handleDeleteComment = (data: any) => { const handleDeleteComment = (data: any) => {
// console.log('delete: ', data);
threadSocket.off('v1-Comment:response:delete', handleDeleteComment);
}; };
threadSocket.on('v1-Comment:response:delete', handleDeleteComment); threadSocket.on('v1-Comment:response:delete', handleDeleteComment);
// --- Create Thread Handler --- // --- Create Thread Handler ---
const handleCreateThread = (data: any) => { const handleCreateThread = (data: any) => {
// console.log('createThread: ', data);
const comment: CommentSchema = { const comment: CommentSchema = {
state: 'active', state: 'active',
@@ -117,20 +112,26 @@ const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSock
addComment(comment); addComment(comment);
setCommentPositionState(null); setCommentPositionState(null);
// setSelectedComment(null); // setSelectedComment(null);
threadSocket.off('v1-thread:response:create', handleCreateThread);
}; };
threadSocket.on('v1-thread:response:create', handleCreateThread); threadSocket.on('v1-thread:response:create', handleCreateThread);
// --- Delete Thread Handler --- // --- Delete Thread Handler ---
// const handleDeleteThread = (data: any) => {
//
// };
// threadSocket.on("v1-thread:response:delete", handleDeleteThread);
const handleDeleteThread = (data: any) => { const handleDeleteThread = (data: any) => {
threadSocket.off('v1-thread:response:delete', handleDeleteThread);
}; };
threadSocket.on('v1-thread:response:delete', handleDeleteThread); threadSocket.on("v1-thread:response:delete", handleDeleteThread);
const handleEditThread = (data: any) => { const handleEditThread = (data: any) => {
const editedThread: CommentSchema = { const editedThread: CommentSchema = {
state: 'active', state: 'active',
threadId: data.data?._id, threadId: data.data?._id,
@@ -138,17 +139,16 @@ const ThreadSocketResponsesDev = ({ setMessages, modeRef, messages }: ThreadSock
createdAt: data.data?.createdAt, createdAt: data.data?.createdAt,
threadTitle: data.data?.threadTitle, threadTitle: data.data?.threadTitle,
lastUpdatedAt: new Date().toISOString(), lastUpdatedAt: new Date().toISOString(),
position: data.data.position, position: data.data?.position,
rotation: [0, 0, 0], rotation: [0, 0, 0],
comments: data.data.comments, comments: data.data?.comments,
}; };
// console.log('data.data?._id: ', data.data?._id); //
updateComment(data.data?._id, editedThread); updateComment(data.data?._id, editedThread);
setSelectedComment(editedThread) setSelectedComment(editedThread)
// setSelectedComment(null); // setSelectedComment(null);
}; };
threadSocket.on('v1-thread:response:updateTitle', handleEditThread); threadSocket.on('v1-thread:response:updateTitle', handleEditThread);

View File

@@ -34,6 +34,7 @@ export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Co
if (!projectId && loadingProgress > 1) return; if (!projectId && loadingProgress > 1) return;
getAllProjects(userId, organization) getAllProjects(userId, organization)
.then((projects) => { .then((projects) => {
if (!projects || !projects.Projects) return;
let project = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId); let project = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId);
const canvas = document.getElementById("sceneCanvas")?.getElementsByTagName('canvas')[0]; const canvas = document.getElementById("sceneCanvas")?.getElementsByTagName('canvas')[0];
if (!canvas) return; if (!canvas) return;

View File

@@ -28,6 +28,8 @@ type SceneContextValue = {
vehicleStore: VehicleStoreType; vehicleStore: VehicleStoreType;
storageUnitStore: StorageUnitStoreType; storageUnitStore: StorageUnitStoreType;
clearStores: () => void;
layout: 'Main Layout' | 'Comparison Layout'; layout: 'Main Layout' | 'Comparison Layout';
}; };
@@ -55,8 +57,17 @@ export function SceneProvider({
const storageUnitStore = useMemo(() => createStorageUnitStore(), []); const storageUnitStore = useMemo(() => createStorageUnitStore(), []);
const clearStores = useMemo(() => () => { const clearStores = useMemo(() => () => {
assetStore().clearAssets(); assetStore.getState().clearAssets();
}, [assetStore]); aisleStore.getState().clearAisles();
eventStore.getState().clearEvents();
productStore.getState().clearProducts();
materialStore.getState().clearMaterials();
armBotStore.getState().clearArmBots();
machineStore.getState().clearMachines();
conveyorStore.getState().clearConveyors();
vehicleStore.getState().clearVehicles();
storageUnitStore.getState().clearStorageUnits();
}, [assetStore, aisleStore, eventStore, productStore, materialStore, armBotStore, machineStore, conveyorStore, vehicleStore, storageUnitStore]);
const contextValue = useMemo(() => ( const contextValue = useMemo(() => (
{ {

View File

@@ -33,7 +33,7 @@ export const createHandleDrop = ({
const droppedData = JSON.parse(data); const droppedData = JSON.parse(data);
const canvasElement = document.getElementById("work-space-three-d-canvas"); const canvasElement = document.getElementById("work-space-three-d-canvas");
if (!canvasElement) throw new Error("Canvas element not found"); if (!canvasElement) return;
const rect = canvasElement.getBoundingClientRect(); const rect = canvasElement.getBoundingClientRect();
const relativeX = event.clientX - rect.left; const relativeX = event.clientX - rect.left;

View File

@@ -683,7 +683,7 @@ export default function Dropped3dWidgets() {
event.preventDefault(); event.preventDefault();
const canvasElement = document.getElementById("work-space-three-d-canvas"); const canvasElement = document.getElementById("work-space-three-d-canvas");
if (!canvasElement) throw new Error("Canvas element not found"); if (!canvasElement) return;
const canvasRect = canvasElement.getBoundingClientRect(); const canvasRect = canvasElement.getBoundingClientRect();
const relativeX = event.clientX - canvasRect.left; const relativeX = event.clientX - canvasRect.left;
@@ -747,7 +747,7 @@ export default function Dropped3dWidgets() {
const canvasElement = document.getElementById( const canvasElement = document.getElementById(
"work-space-three-d-canvas" "work-space-three-d-canvas"
); );
if (!canvasElement) throw new Error("Canvas element not found"); if (!canvasElement) return;
const canvasRect = canvasElement.getBoundingClientRect(); const canvasRect = canvasElement.getBoundingClientRect();
const relativeX = event.clientX - canvasRect.left; const relativeX = event.clientX - canvasRect.left;
const relativeY = event.clientY - canvasRect.top; const relativeY = event.clientY - canvasRect.top;

View File

@@ -29,7 +29,6 @@ import { SceneProvider } from "../modules/scene/sceneContext";
import { getVersionHistoryApi } from "../services/factoryBuilder/versionControl/getVersionHistoryApi"; import { getVersionHistoryApi } from "../services/factoryBuilder/versionControl/getVersionHistoryApi";
import { useVersionHistoryStore } from "../store/builder/useVersionHistoryStore"; import { useVersionHistoryStore } from "../store/builder/useVersionHistoryStore";
import { VersionProvider } from "../modules/builder/version/versionContext"; import { VersionProvider } from "../modules/builder/version/versionContext";
import ThreadChat from "../components/ui/collaboration/ThreadChat";
const Project: React.FC = () => { const Project: React.FC = () => {
let navigate = useNavigate(); let navigate = useNavigate();
@@ -47,7 +46,7 @@ const Project: React.FC = () => {
const { selectedUser } = useSelectedUserStore(); const { selectedUser } = useSelectedUserStore();
const { isLogListVisible } = useLogger(); const { isLogListVisible } = useLogger();
const { setVersions } = useVersionHistoryStore(); const { setVersions } = useVersionHistoryStore();
const { selectedComment, commentPositionState } = useSelectedComment();
useEffect(() => { useEffect(() => {
if (!email || !userId) { if (!email || !userId) {
@@ -56,11 +55,14 @@ const Project: React.FC = () => {
} }
getAllProjects(userId, organization).then((projects) => { getAllProjects(userId, organization).then((projects) => {
if (!projects || !projects.Projects) return;
const filterProject = projects?.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId) const filterProject = projects?.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId)
setProjectName(filterProject.projectName) setProjectName(filterProject.projectName)
viewProject(organization, filterProject._id, userId).then((viewedProject) => { viewProject(organization, filterProject._id, userId).then((viewedProject) => {
}); });
}); }).catch(() => {
console.error("Error fetching projects")
})
}, []); }, []);
@@ -79,6 +81,8 @@ const Project: React.FC = () => {
}) })
}) })
setVersions(versions); setVersions(versions);
}).catch(() => {
console.error("Error fetching version history")
}) })
}, [projectId]) }, [projectId])
@@ -127,8 +131,6 @@ const Project: React.FC = () => {
<LogList /> <LogList />
</RenderOverlay> </RenderOverlay>
)} )}
{(commentPositionState !== null || selectedComment !== null) && <ThreadChat />}
</div> </div>
); );
}; };

View File

@@ -43,7 +43,6 @@ const UserAuth: React.FC = () => {
const organization = email.split("@")[1].split(".")[0]; const organization = email.split("@")[1].split(".")[0];
try { try {
const res = await signInApi(email, password, organization, fingerprint); const res = await signInApi(email, password, organization, fingerprint);
console.log('res: ', res);
if (res.message.message === "login successfull") { if (res.message.message === "login successfull") {
setError(""); setError("");
setOrganization(organization); setOrganization(organization);
@@ -57,6 +56,7 @@ const UserAuth: React.FC = () => {
try { try {
const projects = await recentlyViewed(organization, res.message.userId); const projects = await recentlyViewed(organization, res.message.userId);
console.log('projects: ', projects);
if (res.message.isShare) { if (res.message.isShare) {
if (Object.values(projects.RecentlyViewed).length > 0) { if (Object.values(projects.RecentlyViewed).length > 0) {
const firstId = (Object.values(projects?.RecentlyViewed || {})[0] as any)?._id; const firstId = (Object.values(projects?.RecentlyViewed || {})[0] as any)?._id;
@@ -72,7 +72,6 @@ const UserAuth: React.FC = () => {
} }
} }
} catch (error) { } catch (error) {
console.error("Error fetching recent projects:", error); console.error("Error fetching recent projects:", error);
} }

View File

@@ -19,7 +19,7 @@ export const createProject = async (projectUuid: string, userId: string, thumbna
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to add project"); console.error("Failed to add project");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -28,7 +28,7 @@ export const deleteProject = async (
} }
console.log("response: ", response); console.log("response: ", response);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to clearPanel in the zone"); console.error("Failed to clearPanel in the zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -23,13 +23,13 @@ export const deleteTrash = async (organization: string, projectId: string) => {
console.log("restore: ", response); console.log("restore: ", response);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch trash data"); console.error("Failed to fetch trash data");
} }
const data = await response.json(); const data = await response.json();
return data; return data;
} catch (error: any) { } catch (error: any) {
console.error("Failed to fetch trash data:", error); console.error("Failed to fetch trash data:", error);
throw new Error(error.message || "Unknown error"); console.error(error.message || "Unknown error");
} }
}; };

View File

@@ -26,7 +26,7 @@ export const duplicateProject = async (
} }
// console.log("response: ", response); // console.log("response: ", response);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to add project"); console.error("Failed to add project");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -22,13 +22,13 @@ export const getTrash = async (organization: string) => {
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch trash data"); console.error("Failed to fetch trash data");
} }
const data = await response.json(); const data = await response.json();
return data; return data;
} catch (error: any) { } catch (error: any) {
console.error("Failed to fetch trash data:", error); console.error("Failed to fetch trash data:", error);
throw new Error(error.message || "Unknown error"); console.error(error.message || "Unknown error");
} }
}; };

View File

@@ -19,7 +19,7 @@ export const projectTutorial = async () => {
// console.log("response: ", response); // console.log("response: ", response);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to add project"); console.error("Failed to add project");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -20,7 +20,7 @@ export const recentlyViewed = async (organization: string, userId: string) => {
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch project"); console.error("Failed to fetch project");
} }
return await response.json(); return await response.json();

View File

@@ -22,7 +22,7 @@ export const restoreTrash = async (organization: string, projectId: string) => {
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch trash data"); console.error("Failed to fetch trash data");
} }
const data = await response.json(); const data = await response.json();
@@ -30,6 +30,6 @@ export const restoreTrash = async (organization: string, projectId: string) => {
return data; return data;
} catch (error: any) { } catch (error: any) {
console.error("Failed to fetch trash data:", error); console.error("Failed to fetch trash data:", error);
throw new Error(error.message || "Unknown error"); console.error(error.message || "Unknown error");
} }
}; };

View File

@@ -26,7 +26,7 @@ export const searchProject = async (
console.log("response: ", response); console.log("response: ", response);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to Search project"); console.error("Failed to Search project");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -24,7 +24,7 @@ export const trashSearchProject = async (
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to add project"); console.error("Failed to add project");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -37,7 +37,7 @@ export const updateProject = async (
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to clearPanel in the zone"); console.error("Failed to clearPanel in the zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -25,7 +25,7 @@ export const viewProject = async (
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch"); console.error("Failed to fetch");
} }
return await response.json(); return await response.json();

View File

@@ -25,7 +25,7 @@ export const createAisleApi = async (
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to add project"); console.error("Failed to add project");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -18,7 +18,7 @@ export const deleteAisleApi = async (aisleUuid: string, projectId: string, versi
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to clearPanel in the zone"); console.error("Failed to clearPanel in the zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -22,7 +22,7 @@ export const getAisleApi = async (projectId: string, versionId: string) => {
// console.log("response: ", response); // console.log("response: ", response);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch"); console.error("Failed to fetch");
} }
return await response.json(); return await response.json();

View File

@@ -13,7 +13,7 @@ export const getAssetImages = async (cursor?: string) => {
); );
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch assets"); console.error("Failed to fetch assets");
} }
return await response.json(); return await response.json();

View File

@@ -13,7 +13,7 @@ export const getAssetModel = async (modelId: string) => {
); );
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch model"); console.error("Failed to fetch model");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -26,7 +26,7 @@ export const deleteFloorItem = async (
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete Floor Item"); console.error("Failed to delete Floor Item");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -22,7 +22,7 @@ export const getFloorAssets = async (organization: string, projectId?: string, v
// console.log('response: ', response); // console.log('response: ', response);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get assets"); console.error("Failed to get assets");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -18,7 +18,7 @@ export const setAssetsApi = async (data: any) => {
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to set or update Floor Item"); console.error("Failed to set or update Floor Item");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -26,7 +26,7 @@ export const deleteWallItem = async (
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete Wall Item"); console.error("Failed to delete Wall Item");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -21,7 +21,7 @@ export const getWallItems = async (organization: string, projectId?: string, ver
} }
// console.log('response: ', response); // console.log('response: ', response);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get Wall Items"); console.error("Failed to get Wall Items");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -39,7 +39,7 @@ export const setWallItem = async (
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to set or update Wall Item"); console.error("Failed to set or update Wall Item");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -21,7 +21,7 @@ export const getCamera = async (organization: string, userId: string, projectId?
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get Camera position and target"); console.error("Failed to get Camera position and target");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -31,7 +31,7 @@ export const setCamera = async (
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to set Camera Position and Target"); console.error("Failed to set Camera Position and Target");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -21,11 +21,11 @@ export default async function getActiveUsersData(organization: string) {
} }
if (!response.ok) { if (!response.ok) {
throw new Error(`Error: ${response.status} - ${response.statusText}`); console.error(`Error: ${response.status} - ${response.statusText}`);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get active cameras "); console.error("Failed to get active cameras ");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -20,11 +20,11 @@ export default async function fetchShareUsers(organization: string) {
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error(`Error: ${response.status} - ${response.statusText}`); console.error(`Error: ${response.status} - ${response.statusText}`);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get users "); console.error("Failed to get users ");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -23,7 +23,7 @@ export default async function giveCollabAccess(
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to set Camera Position and Target"); console.error("Failed to set Camera Position and Target");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -4,18 +4,20 @@ export const addCommentsApi = async (
projectId: any, projectId: any,
comment: string, comment: string,
threadId?: string, threadId?: string,
commentId?: string commentId?: string,
versionId?: string
) => { ) => {
console.log( console.log(
" projectId, comments, threadId: ", " projectId, comments, threadId: ",
projectId, projectId,
comment, comment,
threadId, threadId,
commentId commentId,
versionId
); );
try { try {
const response = await fetch( const response = await fetch(
`${url_Backend_dwinzo}/api/v1/Thread/addComment`, `${url_Backend_dwinzo}/api/V1/Thread/addComment`,
{ {
method: "POST", method: "POST",
headers: { headers: {
@@ -33,9 +35,9 @@ export const addCommentsApi = async (
//console.log("New token received:", newAccessToken); //console.log("New token received:", newAccessToken);
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
console.log('response: ', response);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to add project"); console.error("Failed to add project");
} }
const result = await response.json(); const result = await response.json();
@@ -44,9 +46,9 @@ export const addCommentsApi = async (
return result; return result;
} catch (error) { } catch (error) {
if (error instanceof Error) { if (error instanceof Error) {
throw new Error(error.message); console.error(error.message);
} else { } else {
throw new Error("An unknown error occurred"); console.error("An unknown error occurred");
} }
} }
}; };

View File

@@ -5,10 +5,11 @@ export const createThreadApi = async (
state: string, state: string,
position: any, position: any,
rotation: any, rotation: any,
threadTitle: any threadTitle: any,
versionId?: string
) => { ) => {
try { try {
const response = await fetch(`${url_Backend_dwinzo}/api/v1/upsetThread`, { const response = await fetch(`${url_Backend_dwinzo}/api/V1/upsetThread`, {
method: "POST", method: "POST",
headers: { headers: {
Authorization: "Bearer <access_token>", Authorization: "Bearer <access_token>",
@@ -16,7 +17,14 @@ export const createThreadApi = async (
token: localStorage.getItem("token") || "", token: localStorage.getItem("token") || "",
refresh_token: localStorage.getItem("refreshToken") || "", refresh_token: localStorage.getItem("refreshToken") || "",
}, },
body: JSON.stringify({ projectId, state, position, rotation, threadTitle }), body: JSON.stringify({
projectId,
state,
position,
rotation,
threadTitle,
versionId,
}),
}); });
const newAccessToken = response.headers.get("x-access-token"); const newAccessToken = response.headers.get("x-access-token");
if (newAccessToken) { if (newAccessToken) {
@@ -24,16 +32,16 @@ export const createThreadApi = async (
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to add project"); console.error("Failed to add project");
} }
const result = await response.json(); const result = await response.json();
console.log('result: ', result); console.log("result: ", result);
return result; return result;
} catch (error) { } catch (error) {
if (error instanceof Error) { if (error instanceof Error) {
throw new Error(error.message); console.error(error.message);
} else { } else {
throw new Error("An unknown error occurred"); console.error("An unknown error occurred");
} }
} }
}; };

View File

@@ -4,17 +4,19 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_UR
export const deleteCommentApi = async ( export const deleteCommentApi = async (
projectId: string, projectId: string,
threadId: string, threadId: string,
commentId: string commentId: string,
versionId?: string
) => { ) => {
const body: any = { const body: any = {
projectId, projectId,
threadId, threadId,
commentId, commentId,
versionId,
}; };
try { try {
const response = await fetch( const response = await fetch(
`${url_Backend_dwinzo}/api/v1/Thread/deleteComment`, `${url_Backend_dwinzo}/api/V1/Thread/deleteComment`,
{ {
method: "PATCH", method: "PATCH",
headers: { headers: {
@@ -32,16 +34,16 @@ export const deleteCommentApi = async (
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to clearPanel in the zone"); console.error("Failed to clearPanel in the zone");
} }
const result = await response.json(); const result = await response.json();
return result; return result;
} catch (error) { } catch (error) {
if (error instanceof Error) { if (error instanceof Error) {
throw new Error(error.message); console.error(error.message);
} else { } else {
throw new Error("An unknown error occurred"); console.error("An unknown error occurred");
} }
} }
}; };

View File

@@ -1,14 +1,19 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
// let url_Backend_dwinzo = `http://192.168.0.102:5000`; // let url_Backend_dwinzo = `http://192.168.0.102:5000`;
export const deleteThreadApi = async (projectId: string, threadId: string) => { export const deleteThreadApi = async (
projectId: string,
threadId: string,
versionId: string
) => {
const body: any = { const body: any = {
projectId, projectId,
threadId, threadId,
versionId,
}; };
try { try {
const response = await fetch(`${url_Backend_dwinzo}/api/v1/Thread/delete`, { const response = await fetch(`${url_Backend_dwinzo}/api/V1/Thread/delete`, {
method: "PATCH", method: "PATCH",
headers: { headers: {
Authorization: "Bearer <access_token>", Authorization: "Bearer <access_token>",
@@ -24,16 +29,16 @@ export const deleteThreadApi = async (projectId: string, threadId: string) => {
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to clearPanel in the zone"); console.error("Failed to clearPanel in the zone");
} }
const result = await response.json(); const result = await response.json();
return result; return result;
} catch (error) { } catch (error) {
if (error instanceof Error) { if (error instanceof Error) {
throw new Error(error.message); console.error(error.message);
} else { } else {
throw new Error("An unknown error occurred"); console.error("An unknown error occurred");
} }
} }
}; };

View File

@@ -4,17 +4,19 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_UR
export const editThreadTitleApi = async ( export const editThreadTitleApi = async (
projectId: string, projectId: string,
threadId: string, threadId: string,
threadTitle: string threadTitle: string,
versionId?: string
) => { ) => {
const body: any = { const body: any = {
projectId, projectId,
threadId, threadId,
threadTitle, threadTitle,
versionId,
}; };
try { try {
const response = await fetch( const response = await fetch(
`${url_Backend_dwinzo}/api/v1/Thread/updateTitle`, `${url_Backend_dwinzo}/api/V1/Thread/updateTitle`,
{ {
method: "PATCH", method: "PATCH",
headers: { headers: {
@@ -32,16 +34,16 @@ export const editThreadTitleApi = async (
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to clearPanel in the zone"); console.error("Failed to clearPanel in the zone");
} }
const result = await response.json(); const result = await response.json();
return result; return result;
} catch (error) { } catch (error) {
if (error instanceof Error) { if (error instanceof Error) {
throw new Error(error.message); console.error(error.message);
} else { } else {
throw new Error("An unknown error occurred"); console.error("An unknown error occurred");
} }
} }
}; };

View File

@@ -1,9 +1,9 @@
let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`;
export const getAllThreads = async (projectId: string) => { export const getAllThreads = async (projectId: string, versionId: string) => {
try { try {
const response = await fetch( const response = await fetch(
`${url_Backend_dwinzo}/api/v1/Threads/${projectId}`, `${url_Backend_dwinzo}/api/V1/Threads/${projectId}/${versionId}`,
{ {
method: "GET", method: "GET",
headers: { headers: {
@@ -21,19 +21,19 @@ export const getAllThreads = async (projectId: string) => {
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get assets"); console.error("Failed to get assets");
return;
} }
const result = await response.json(); const result = await response.json();
// console.log('result: ', result);
return result; return result;
} catch (error) { } catch (error) {
echo.error("Failed to get floor asset"); echo.error("Failed to get floor asset");
if (error instanceof Error) { if (error instanceof Error) {
throw new Error(error.message); console.error(error.message);
} else { } else {
throw new Error("An unknown error occurred"); console.error("An unknown error occurred");
} }
} }
}; };

View File

@@ -22,7 +22,7 @@ export const findEnvironment = async (organization: string, userId: string, proj
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get wall and roof visibility"); console.error("Failed to get wall and roof visibility");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -41,7 +41,7 @@ export const setEnvironment = async (
} }
// console.log('responseenv: ', response); // console.log('responseenv: ', response);
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to set wall and roof visibility"); console.error("Failed to set wall and roof visibility");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -18,7 +18,7 @@ export const deleteLayer = async (organization: string, layer: number) => {
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete line"); console.error("Failed to delete line");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -18,7 +18,7 @@ export const deleteLineApi = async (organization: string, line: Object) => {
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete line"); console.error("Failed to delete line");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -19,7 +19,7 @@ export const deletePointApi = async (organization: string, uuid: string) => {
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete point"); console.error("Failed to delete point");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -21,7 +21,7 @@ export const getLines = async (organization: string, projectId?: string, version
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get Lines"); console.error("Failed to get Lines");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -25,7 +25,7 @@ export const setLine = async (
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to set line"); console.error("Failed to set line");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -22,7 +22,7 @@ export const updatePoint = async (
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to update point"); console.error("Failed to update point");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -14,7 +14,7 @@ export const signUpApi = async (
}); });
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to signUpApi"); console.error("Failed to signUpApi");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -28,7 +28,7 @@ export const createVersionApi = async (projectId: string, createdBy: string, hie
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to create Version History"); console.error("Failed to create Version History");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -21,7 +21,7 @@ export const getVersionDataApi = async (projectId: string, versionId: string) =>
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get Version Data"); console.error("Failed to get Version Data");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -21,7 +21,7 @@ export const getVersionHistoryApi = async (projectId: string, page?: number, lim
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get Version History"); console.error("Failed to get Version History");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -22,7 +22,7 @@ export const deleteZonesApi = async (
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete zone"); console.error("Failed to delete zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -22,7 +22,7 @@ export const getZonesApi = async (organization: string, projectId?: string, vers
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to get Zones"); console.error("Failed to get Zones");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -22,7 +22,7 @@ export const setZonesApi = async (
localStorage.setItem("token", newAccessToken); localStorage.setItem("token", newAccessToken);
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to set zone"); console.error("Failed to set zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -11,7 +11,7 @@ export const getAssetDetails = async (filename: string) => {
}); });
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch asset details"); console.error("Failed to fetch asset details");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -3,7 +3,7 @@ export const fetchAssets = async () => {
try { try {
const response = await fetch(`${BackEnd_url}/api/v1/getAllAssets`); const response = await fetch(`${BackEnd_url}/api/v1/getAllAssets`);
if (!response.ok) { if (!response.ok) {
throw new Error("Network response was not ok"); console.error("Network response was not ok");
} }
const result = await response.json(); const result = await response.json();
// const last10Assets = result.slice(-10); // const last10Assets = result.slice(-10);

View File

@@ -13,7 +13,7 @@ export const fetchGltfUrl = async (filename: string, AssetID: string) => {
); );
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch asset details"); console.error("Failed to fetch asset details");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -12,7 +12,7 @@ export const getSortedAssets = async (category: any, orders: any) => {
); );
if (!response.ok) { if (!response.ok) {
throw new Error(`Error: ${response.statusText}`); console.error(`Error: ${response.statusText}`);
} }
const result = await response.json(); const result = await response.json();

View File

@@ -22,7 +22,7 @@ export const upsertProductOrEventApi = async (body: any) => {
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to add product or event"); console.error("Failed to add product or event");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -24,7 +24,7 @@ export const deleteEventDataApi = async (body: any) => {
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete event data"); console.error("Failed to delete event data");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -22,7 +22,7 @@ export const deleteProductApi = async (body: any) => {
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete product data"); console.error("Failed to delete product data");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -24,7 +24,7 @@ export const getProductApi = async (
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch product data"); console.error("Failed to fetch product data");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -21,7 +21,7 @@ export const getAllProductsApi = async (projectId: string, versionId: string) =>
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to fetch all products data"); console.error("Failed to fetch all products data");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -24,7 +24,7 @@ export const renameProductApi = async (body: {
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to rename product"); console.error("Failed to rename product");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -28,7 +28,7 @@ export const adding3dWidgets = async (
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to add 3dwidget in the zone"); console.error("Failed to add 3dwidget in the zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -22,7 +22,7 @@ export const addingFloatingWidgets = async (zoneUuid: string,organization: strin
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to add Floatingwidget in the zone"); console.error("Failed to add Floatingwidget in the zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -27,7 +27,7 @@ export const addingWidgets = async (
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to add widget in the zone"); console.error("Failed to add widget in the zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -25,7 +25,7 @@ export const clearPanel = async (
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to clearPanel in the zone"); console.error("Failed to clearPanel in the zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -29,7 +29,7 @@ export const delete3dWidgetApi = async (
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete floating widget in the zone"); console.error("Failed to delete floating widget in the zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -27,7 +27,7 @@ export const deleteFloatingWidgetApi = async (
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete floating widget in the zone"); console.error("Failed to delete floating widget in the zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -26,7 +26,7 @@ export const deletePanelApi = async (
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete widget in the zone"); console.error("Failed to delete widget in the zone");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -25,7 +25,7 @@ export const deleteTemplateApi = async (
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete template "); console.error("Failed to delete template ");
} }
const result = await response.json(); const result = await response.json();

View File

@@ -25,7 +25,7 @@ export const deleteWidgetApi = async (
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to delete widget in the zone"); console.error("Failed to delete widget in the zone");
} }
const result = await response.json(); const result = await response.json();
return result; return result;

View File

@@ -23,7 +23,7 @@ export const duplicateWidgetApi = async (
} }
if (!response.ok) { if (!response.ok) {
throw new Error("Failed to duplicate widget in the zone"); console.error("Failed to duplicate widget in the zone");
} }
const result = await response.json(); const result = await response.json();

Some files were not shown because too many files have changed in this diff Show More