@@ -358,9 +260,7 @@ const Tools: React.FC = () => {
setOpenDrop(false);
}}
>
-
- {activeSubTool === option && }
-
+
{activeSubTool === option && }
{getIconComponent(option)}
{option}
@@ -376,14 +276,7 @@ const Tools: React.FC = () => {
{["move", "rotate"].map((tool) => (
- setActiveTool(tool)}
- />
+ setActiveTool(tool)} />
))}
>
@@ -396,22 +289,8 @@ const Tools: React.FC = () => {
- setActiveTool("comment")}
- />
- {toggleThreeD && (
- setIsPlaying(!isPlaying)}
- />
- )}
+ setActiveTool("comment")} />
+ {toggleThreeD && setIsPlaying(!isPlaying)} />}
{activeModule === "builder" && (
diff --git a/app/src/components/ui/analysis/ProductionCapacity.tsx b/app/src/components/ui/analysis/ProductionCapacity.tsx
index 6ff0b42..d5b0951 100644
--- a/app/src/components/ui/analysis/ProductionCapacity.tsx
+++ b/app/src/components/ui/analysis/ProductionCapacity.tsx
@@ -1,12 +1,6 @@
import React, { useEffect, useState } from "react";
import { Line } from "react-chartjs-2";
-import {
- Chart as ChartJS,
- LineElement,
- CategoryScale,
- LinearScale,
- PointElement,
-} from "chart.js";
+import { Chart as ChartJS, LineElement, CategoryScale, LinearScale, PointElement } from "chart.js";
import { PowerIcon, ProductionCapacityIcon } from "../../icons/analysis";
import SkeletonUI from "../../templates/SkeletonUI";
import { useInputValues, useMachineUptime, useProductionCapacityData, useThroughPutData } from "../../../store/builder/store";
@@ -14,188 +8,181 @@ import { useInputValues, useMachineUptime, useProductionCapacityData, useThrough
ChartJS.register(LineElement, CategoryScale, LinearScale, PointElement);
const ThroughputSummary: React.FC = () => {
- // Define all data internally within the component
- const timeRange = {
- startTime: "08:00 AM",
- endTime: "06:00 PM",
- };
+ // Define all data internally within the component
+ const timeRange = {
+ startTime: "08:00 AM",
+ endTime: "06:00 PM",
+ };
- const { machineActiveTime } = useMachineUptime();
- const energyConsumption = {
- energyConsumed: 456,
- unit: "KWH",
- };
+ const { machineActiveTime } = useMachineUptime();
+ const energyConsumption = {
+ energyConsumed: 456,
+ unit: "KWH",
+ };
-
+ // Dynamic shift data
+ const shiftUtilization = [
+ { shift: 1, percentage: 30, color: "#F3C64D" },
+ { shift: 2, percentage: 40, color: "#67B3F4" },
+ { shift: 3, percentage: 30, color: "#7981F5" },
+ ];
- // Dynamic shift data
- const shiftUtilization = [
- { shift: 1, percentage: 30, color: "#F3C64D" },
- { shift: 2, percentage: 40, color: "#67B3F4" },
- { shift: 3, percentage: 30, color: "#7981F5" },
- ];
+ const { productionCapacityData } = useProductionCapacityData();
+ const { throughputData: data } = useThroughPutData();
- const { productionCapacityData } = useProductionCapacityData()
- const { throughputData: data } = useThroughPutData()
+ const chartOptions = {
+ responsive: true,
+ scales: {
+ x: {
+ display: false, // hide X axis completely
+ },
+ y: {
+ display: false, // hide Y axis completely
+ min: 0, // force Y axis to start at 0
+ },
+ },
+ plugins: {
+ legend: {
+ display: false,
+ },
+ tooltip: {
+ enabled: true,
+ },
+ },
+ };
+ const assetUsage = 85;
- const chartOptions = {
- responsive: true,
- scales: {
- x: {
- display: false, // hide X axis completely
- },
- y: {
- display: false, // hide Y axis completely
- min: 0, // force Y axis to start at 0
- },
- },
- plugins: {
- legend: {
- display: false,
- },
- tooltip: {
- enabled: true,
- },
- },
- };
+ // machineActiveTime => Throughput
+ // shiftUtilization.length => Shifts per day
+ // 8 => Shift length
+ // assetUsage => Yield rate
- const assetUsage = 85;
+ const throughtputMachineData = machineActiveTime * shiftUtilization.length * 8;
- // machineActiveTime => Throughput
- // shiftUtilization.length => Shifts per day
- // 8 => Shift length
- // assetUsage => Yield rate
+ const throughputData = {
+ labels: ["08:00", "08:10", "08:20", "08:30", "08:40", "08:50"],
+ data: [5, 10, 8, 10, 12, 10],
+ totalThroughput: (throughtputMachineData * assetUsage) / 100,
+ assetUsage: assetUsage,
+ };
- const throughtputMachineData = machineActiveTime * shiftUtilization.length * 8
+ const { inputValues } = useInputValues();
+ // Chart data configuration
+ const chartData = {
+ labels: throughputData.labels,
+ datasets: [
+ {
+ label: "Units/hour",
+ data: throughputData.data,
+ borderColor: "#B392F0",
+ tension: 0.4,
+ pointRadius: 0, // Hide points
+ },
+ ],
+ };
- const throughputData = {
- labels: ["08:00", "08:10", "08:20", "08:30", "08:40", "08:50"],
- data: [5, 10, 8, 10, 12, 10],
- totalThroughput: (throughtputMachineData) * assetUsage / 100,
- assetUsage: assetUsage,
- };
+ const [isLoading, setIsLoading] = useState(true);
- const { inputValues } = useInputValues();
- // Chart data configuration
- const chartData = {
- labels: throughputData.labels,
- datasets: [
- {
- label: "Units/hour",
- data: throughputData.data,
- borderColor: "#B392F0",
- tension: 0.4,
- pointRadius: 0, // Hide points
- },
- ],
- };
+ useEffect(() => {
+ //
+ if (productionCapacityData > 0) {
+ setTimeout(() => {
+ setIsLoading(false);
+ }, 3000);
+ } else {
+ setIsLoading(true);
+ }
+ }, [productionCapacityData]);
- const [isLoading, setIsLoading] = useState(true);
-
- useEffect(() => {
- //
- if (productionCapacityData > 0) {
- setTimeout(() => {
-
- setIsLoading(false);
- }, 3000)
-
- } else {
- setIsLoading(true);
- }
- }, [productionCapacityData]);
-
-
- return (
- <>
- {!isLoading &&
-
-
-
-
Production Capacity
-
- {timeRange.startTime} - {timeRange.endTime}
-
-
-
-
-
- {!isLoading ? (
- <>
-
-
- {productionCapacityData}{" "}
- Units/Month
-
-
-
-
Asset usage
-
{parseFloat(inputValues["Yield rate"])}%
-
-
-
-
-
-
-
-
Energy Consumption
-
-
-
-
- {energyConsumption.energyConsumed}
-
-
{energyConsumption.unit}
-
-
-
-
-
Shift Utilization
-
-
{throughputData.assetUsage}%
-
-
- {/* Dynamically create progress bars based on shiftUtilization array */}
- {shiftUtilization.map((shift, index) => (
-
- ))}
-
-
-
- {/* Dynamically create shift indicators with random colors */}
- {shiftUtilization.map((shift, index) => (
-
-
-
+ return (
+ <>
+ {!isLoading && (
+
+
+
+
+
Production Capacity
+
+ {timeRange.startTime} - {timeRange.endTime}
+
+
+
- ))}
+
+ {!isLoading ? (
+ <>
+
+
+ {productionCapacityData} Units/Month
+
+
+
+
Asset usage
+
{parseFloat(inputValues["Yield rate"])}%
+
+
+
+
+
+
+
+
Energy Consumption
+
+
+
+
{energyConsumption.energyConsumed}
+
{energyConsumption.unit}
+
+
+
+
+
Shift Utilization
+
+
{throughputData.assetUsage}%
+
+
+ {/* Dynamically create progress bars based on shiftUtilization array */}
+ {shiftUtilization.map((shift, index) => (
+
+ ))}
+
+
+
+ {/* Dynamically create shift indicators with random colors */}
+ {shiftUtilization.map((shift, index) => (
+
+
+
+
+ ))}
+
+
+
+
+ >
+ ) : (
+
+ )}
-
-
- >
- ) : (
-
- )}
-
-
}
- >
- );
+ )}
+ >
+ );
};
export default ThroughputSummary;
diff --git a/app/src/components/ui/collaboration/Messages.tsx b/app/src/components/ui/collaboration/Messages.tsx
index b02833a..063189a 100644
--- a/app/src/components/ui/collaboration/Messages.tsx
+++ b/app/src/components/ui/collaboration/Messages.tsx
@@ -4,287 +4,251 @@ import { KebabIcon } from "../../icons/ExportCommonIcons";
import { adjustHeight } from "./function/textAreaHeightAdjust";
import { getUserData } from "../../../functions/getUserData";
import { useParams } from "react-router-dom";
-import { deleteCommentApi } from "../../../services/factoryBuilder/comments/deleteCommentApi";
-import { addCommentsApi } from "../../../services/factoryBuilder/comments/addCommentsApi";
import { useCommentStore } from "../../../store/collaboration/useCommentStore";
import { useSelectedComment, useSocketStore } from "../../../store/builder/store";
import { getRelativeTime } from "./function/getRelativeTime";
import { editThreadTitleApi } from "../../../services/factoryBuilder/comments/editThreadTitleApi";
-import { useVersionContext } from "../../../modules/builder/version/versionContext";
+import { useSceneContext } from "../../../modules/scene/sceneContext";
+// import { deleteCommentApi } from "../../../services/factoryBuilder/comments/deleteCommentApi";
+// import { addCommentsApi } from "../../../services/factoryBuilder/comments/addCommentsApi";
interface MessageProps {
- val: Reply | CommentSchema;
- // val: Reply | CommentSchema;
- i: number;
- setMessages?: React.Dispatch
>
- setIsEditable?: React.Dispatch>
- setEditedThread?: React.Dispatch>
- setMode?: React.Dispatch>
- isEditable?: boolean;
- isEditableThread?: boolean
- editedThread?: boolean;
- mode?: 'create' | 'edit' | null
+ val: Reply | CommentSchema;
+ i: number;
+ setMessages?: React.Dispatch>;
+ setIsEditable?: React.Dispatch>;
+ setEditedThread?: React.Dispatch>;
+ setMode?: React.Dispatch>;
+ isEditable?: boolean;
+ isEditableThread?: boolean;
+ editedThread?: boolean;
+ mode?: "create" | "edit" | null;
}
const Messages: React.FC = ({ val, i, setMessages, mode, setIsEditable, setEditedThread, editedThread, isEditableThread, setMode }) => {
+ const { updateComment, removeReply, updateReply } = useCommentStore();
+ const [openOptions, setOpenOptions] = useState(false);
+ const { projectId } = useParams();
+ const { threadSocket } = useSocketStore();
+ const { userName, userId, organization } = getUserData();
+ const [isEditComment, setIsEditComment] = useState(false);
+ const { selectedComment, setCommentPositionState } = useSelectedComment();
+ const { versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
- const { comments, updateComment, updateReply, removeReply } = useCommentStore();
- const [openOptions, setOpenOptions] = useState(false);
- const { projectId } = useParams();
- const { threadSocket } = useSocketStore();
- const { userName, userId, organization } = getUserData();
- const [isEditComment, setIsEditComment] = useState(false)
- const { selectedComment, setCommentPositionState } = useSelectedComment();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const [value, setValue] = useState("comment" in val ? val.comment : val.threadTitle);
- // input
- const [value, setValue] = useState(
- "comment" in val ? val.comment : val.threadTitle
- );
+ const textareaRef = useRef(null);
- const textareaRef = useRef(null);
- const currentUser = "1";
+ useEffect(() => {
+ if (textareaRef.current) adjustHeight(textareaRef.current);
+ }, [value]);
- // const UserName = "username";
+ function handleCancelAction() {
+ setCommentPositionState(null);
+ if (setIsEditable) setIsEditable(true);
+ setIsEditComment(false);
+ }
- useEffect(() => {
- if (textareaRef.current) adjustHeight(textareaRef.current);
- }, [value]);
+ const handleSaveAction = async () => {
+ if (!projectId || !selectedVersion) return;
- function handleCancelAction() {
- setCommentPositionState(null)
- setIsEditable && setIsEditable(true);
- setIsEditComment(false)
- }
+ if (isEditableThread && editedThread) {
+ try {
+ if (!threadSocket?.active) {
+ const editThreadTitle = await editThreadTitleApi(projectId, (val as CommentSchema).threadId, value, selectedVersion?.versionId || "");
+ if (editThreadTitle.message == "ThreadTitle updated Successfully") {
+ const editedThread: CommentSchema = {
+ state: "active",
+ threadId: editThreadTitle.data.replyId,
+ creatorId: userId,
+ createdAt: getRelativeTime(editThreadTitle.data.createdAt),
+ threadTitle: value,
+ lastUpdatedAt: new Date().toISOString(),
+ position: editThreadTitle.data.position,
+ rotation: [0, 0, 0],
+ comments: [],
+ };
+ updateComment((val as CommentSchema).threadId, editedThread);
+ }
+ } else {
+ const threadEdit = {
+ projectId,
+ userId,
+ threadTitle: value,
+ organization,
+ threadId: (val as CommentSchema).threadId || selectedComment.threadId,
+ versionId: selectedVersion?.versionId || "",
+ };
- const handleSaveAction = async () => {
-
- if (!projectId || !selectedVersion) return
-
- if (isEditableThread && editedThread) {
- try {
- if (!threadSocket?.active) {
- const editThreadTitle = await editThreadTitleApi(projectId, (val as CommentSchema).threadId, value, selectedVersion?.versionId || "")
- if (editThreadTitle.message == "ThreadTitle updated Successfully") {
- const editedThread: CommentSchema = {
- state: 'active',
- threadId: editThreadTitle.data.replyId,
- creatorId: userId,
- createdAt: getRelativeTime(editThreadTitle.data.createdAt),
- threadTitle: value,
- lastUpdatedAt: new Date().toISOString(),
- position: editThreadTitle.data.position,
- rotation: [0, 0, 0],
- comments: [],
- }
- updateComment((val as CommentSchema).threadId, editedThread)
- }
+ threadSocket.emit("v1:thread:updateTitle", threadEdit);
+ }
+ } catch {}
} else {
- const threadEdit = {
- projectId,
- userId,
- threadTitle: value,
- organization,
- threadId: (val as CommentSchema).threadId || selectedComment.threadId,
- versionId: selectedVersion?.versionId || ""
- }
+ if (mode === "edit") {
+ try {
+ // const editComments = await addCommentsApi(projectId, value, selectedComment?.threadId, (val as Reply).replyId, selectedVersion?.versionId || "")
+ //
+ // const commentData = {
+ // replyId: `${editComments.data?.replyId}`,
+ // creatorId: `${userId}`,
+ // createdAt: getRelativeTime(editComments.data?.createdAt),
+ // lastUpdatedAt: "2 hrs ago",
+ // comment: value,
+ // }
- threadSocket.emit('v1:thread:updateTitle', threadEdit)
- }
- } catch {
- }
- } else {
- if (mode === "edit") {
- try {
- // const editComments = await addCommentsApi(projectId, value, selectedComment?.threadId, (val as Reply).replyId, selectedVersion?.versionId || "")
- //
- // const commentData = {
- // replyId: `${editComments.data?.replyId}`,
- // creatorId: `${userId}`,
- // createdAt: getRelativeTime(editComments.data?.createdAt),
- // lastUpdatedAt: "2 hrs ago",
- // comment: value,
- // }
+ // updateReply((val as CommentSchema).threadId, (val as Reply)?.replyId, commentData);
- // updateReply((val as CommentSchema).threadId, (val as Reply)?.replyId, commentData);
+ if (threadSocket) {
+ // projectId, userId, comment, organization, threadId
+ const editComment = {
+ projectId,
+ userId,
+ comment: value,
+ organization,
+ threadId: selectedComment?.threadId,
+ commentId: (val as Reply).replyId ?? "",
+ versionId: selectedVersion?.versionId || "",
+ };
- if (threadSocket) {
- // projectId, userId, comment, organization, threadId
- const editComment = {
- projectId,
- userId,
- comment: value,
- organization,
- threadId: selectedComment?.threadId,
- commentId: (val as Reply).replyId ?? "",
- versionId: selectedVersion?.versionId || ""
+ threadSocket.emit("v1-Comment:add", editComment);
+ setIsEditable && setIsEditable(true);
+ setEditedThread && setEditedThread(false);
+ }
+ } catch {}
}
-
-
- threadSocket.emit("v1-Comment:add", editComment);
- setIsEditable && setIsEditable(true);
- setEditedThread && setEditedThread(false)
- }
-
- } catch {
}
- }
+ // setValue("");
+ setIsEditComment(false);
+ };
- }
- // setValue("");
- setIsEditComment(false);
- }
+ const handleDeleteAction = async (replyID: any) => {
+ if (!projectId || !selectedVersion) return;
+ setOpenOptions(false);
+ try {
+ // const deletedComment = await deleteCommentApi(projectId, selectedComment?.threadId, (val as Reply).replyId , selectedVersion?.versionId || "")
+ //
+ // if (deletedComment === "'Thread comment deleted Successfully'") {
+ // setMessages && setMessages(prev => prev.filter(message => message.replyId !== replyID));
+ // removeReply(val.creatorId, replyID)
+ // }
+ if (threadSocket && setMessages) {
+ // projectId, userId, commentId, organization, threadId
+ const deleteComment = {
+ projectId,
+ userId,
+ commentId: (val as Reply).replyId,
+ organization,
+ threadId: selectedComment?.threadId,
+ versionId: selectedVersion?.versionId || "",
+ };
+ setMessages((prev) => {
+ // 👈 logs the current state
+ return prev.filter((message) => message.replyId !== (val as Reply).replyId);
+ });
+ removeReply(selectedComment?.threadId, (val as Reply).replyId); // Remove listener after response
- const handleDeleteAction = async (replyID: any) => {
- if (!projectId || !selectedVersion) return
- setOpenOptions(false);
- try {
- // const deletedComment = await deleteCommentApi(projectId, selectedComment?.threadId, (val as Reply).replyId , selectedVersion?.versionId || "")
- //
- // if (deletedComment === "'Thread comment deleted Successfully'") {
- // setMessages && setMessages(prev => prev.filter(message => message.replyId !== replyID));
- // removeReply(val.creatorId, replyID)
- // }
- if (threadSocket && setMessages) {
+ threadSocket.emit("v1-Comment:delete", deleteComment);
+ }
+ } catch {}
+ };
-
- // projectId, userId, commentId, organization, threadId
- const deleteComment = {
- projectId,
- userId,
- commentId: (val as Reply).replyId,
- organization,
- threadId: selectedComment?.threadId,
- versionId: selectedVersion?.versionId || ""
- }
- setMessages(prev => {
- // 👈 logs the current state
- return prev.filter(message => message.replyId !== (val as Reply).replyId);
+ const handleFocus = (e: React.FocusEvent) => {
+ requestAnimationFrame(() => {
+ if (textareaRef.current) {
+ const length = textareaRef.current.value.length;
+ textareaRef.current.setSelectionRange(length, length);
+ }
});
- removeReply(selectedComment?.threadId, (val as Reply).replyId); // Remove listener after response
+ };
+ return (
+ <>
+ {isEditComment ? (
+
+
+
+
+
+
+
+
+
+
+
+ ) : (
+
+
+ {userName?.charAt(0).toUpperCase() || "user"}
+
+
+
+
{userName}
+
{isEditableThread ? getRelativeTime(val.createdAt) : val.createdAt}
+
+ {(val as Reply).creatorId === userId && (
+
setOpenOptions(false)}>
+
- threadSocket.emit("v1-Comment:delete", deleteComment);
- }
- } catch {
+ {openOptions && (
+
+
- }
- }
+ {!isEditableThread && (
+
+ )}
+
+ )}
+
+ )}
- const handleFocus = (e: React.FocusEvent
) => {
- requestAnimationFrame(() => {
- if (textareaRef.current) {
- const length = textareaRef.current.value.length;
- textareaRef.current.setSelectionRange(length, length);
- }
- });
- };
-
- return (
- <>
- {isEditComment ? (
-
-
-
-
-
-
-
-
-
-
-
- ) : (
-
-
- {userName?.charAt(0).toUpperCase() || "user"}
-
-
-
-
{userName}
-
{isEditableThread ? getRelativeTime(val.createdAt) : val.createdAt}
-
- {(val as Reply).creatorId === userId && (
-
setOpenOptions(false)}
- >
-
-
- {openOptions && (
-
-
-
- {!isEditableThread && (
-
- )}
-
- )}
-
+
{"comment" in val ? val.comment : val.threadTitle}
+
+
)}
-
-
- {"comment" in val ? val.comment : val.threadTitle}
-
-
-
-
- )}
- >
- );
+ >
+ );
};
export default Messages;
diff --git a/app/src/components/ui/collaboration/ThreadChat.tsx b/app/src/components/ui/collaboration/ThreadChat.tsx
index 5370689..ddbbf46 100644
--- a/app/src/components/ui/collaboration/ThreadChat.tsx
+++ b/app/src/components/ui/collaboration/ThreadChat.tsx
@@ -8,393 +8,359 @@ import { useSelectedComment, useSocketStore } from "../../../store/builder/store
import { useCommentStore } from "../../../store/collaboration/useCommentStore";
import { getUserData } from "../../../functions/getUserData";
import ThreadSocketResponsesDev from "../../../modules/collaboration/socket/threadSocketResponses.dev";
-import { addCommentsApi } from "../../../services/factoryBuilder/comments/addCommentsApi";
-import { deleteThreadApi } from "../../../services/factoryBuilder/comments/deleteThreadApi";
-import { createThreadApi } from "../../../services/factoryBuilder/comments/createThreadApi";
-import { getRelativeTime } from "./function/getRelativeTime";
-import { useVersionContext } from "../../../modules/builder/version/versionContext";
+import { useSceneContext } from "../../../modules/scene/sceneContext";
+
+// import { addCommentsApi } from "../../../services/factoryBuilder/comments/addCommentsApi";
+// import { deleteThreadApi } from "../../../services/factoryBuilder/comments/deleteThreadApi";
+// import { createThreadApi } from "../../../services/factoryBuilder/comments/createThreadApi";
+// import { getRelativeTime } from "./function/getRelativeTime";
const ThreadChat: React.FC = () => {
- const { userId, organization } = getUserData();
- const [openThreadOptions, setOpenThreadOptions] = useState(false);
- const [inputActive, setInputActive] = useState(false);
- const [value, setValue] = useState("");
- const { addComment, removeReply, removeComment, addReply, comments } = useCommentStore();
- const { selectedComment, setSelectedComment, setCommentPositionState, commentPositionState, position2Dstate } = useSelectedComment()
- const [mode, setMode] = useState<'create' | 'edit' | null>('create');
- const [isEditable, setIsEditable] = useState(false);
- const [editedThread, setEditedThread] = useState(false);
- const textareaRef = useRef(null);
- const wrapperRef = useRef(null);
- const [messages, setMessages] = useState([])
- const { projectId } = useParams();
- const [dragging, setDragging] = useState(false);
- const [selectedDiv, setSelectedDiv] = useState(true);
- const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
- const [position, setPosition] = useState({ x: position2Dstate.x, y: position2Dstate.y });
- const { threadSocket } = useSocketStore();
- const modeRef = useRef<'create' | 'edit' | null>(null);
- const messagesRef = useRef(null);
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { userId, organization } = getUserData();
+ const [openThreadOptions, setOpenThreadOptions] = useState(false);
+ const [inputActive, setInputActive] = useState(false);
+ const [value, setValue] = useState("");
+ const { addComment, removeReply, removeComment, addReply, comments } = useCommentStore();
+ const { selectedComment, setSelectedComment, setCommentPositionState, commentPositionState, position2Dstate } = useSelectedComment();
+ const [mode, setMode] = useState<"create" | "edit" | null>("create");
+ const [isEditable, setIsEditable] = useState(false);
+ const [editedThread, setEditedThread] = useState(false);
+ const textareaRef = useRef(null);
+ const wrapperRef = useRef(null);
+ const [messages, setMessages] = useState([]);
+ const { projectId } = useParams();
+ const [dragging, setDragging] = useState(false);
+ const [dragOffset, setDragOffset] = useState({ x: 0, y: 0 });
+ const [position, setPosition] = useState({ x: position2Dstate.x, y: position2Dstate.y });
+ const { threadSocket } = useSocketStore();
+ const modeRef = useRef<"create" | "edit" | null>(null);
+ const messagesRef = useRef(null);
+ const { versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
- useEffect(() => {
- modeRef.current = mode;
- }, [mode]);
+ useEffect(() => {
+ modeRef.current = mode;
+ }, [mode]);
- useEffect(() => {
- if (comments.length > 0 && selectedComment) {
+ useEffect(() => {
+ if (comments.length > 0 && selectedComment) {
+ const allMessages = comments
+ .flatMap((val: any) => (val?.threadId === selectedComment?.threadId ? val.comments : []))
+ .map((c) => {
+ return {
+ replyId: c._id ?? c.replyId,
+ creatorId: c.creatorId || c.userId,
+ createdAt: c.createdAt,
+ lastUpdatedAt: "1 hr ago",
+ comment: c.comment,
+ _id: c._id ?? c.replyId,
+ };
+ });
- const allMessages = comments
- .flatMap((val: any) =>
- val?.threadId === selectedComment?.threadId ? val.comments : []
- )
- .map((c) => {
- return {
- replyId: c._id ?? c.replyId,
- creatorId: c.creatorId || c.userId,
- createdAt: c.createdAt,
- lastUpdatedAt: "1 hr ago",
- comment: c.comment,
- _id: c._id ?? c.replyId,
- };
- });
+ setMessages(allMessages);
+ }
+ }, []);
- setMessages(allMessages);
+ useEffect(() => {
+ if (textareaRef.current) adjustHeight(textareaRef.current);
+ }, [value]);
- }
-
- }, [])
-
- useEffect(() => {
- if (textareaRef.current) adjustHeight(textareaRef.current);
- }, [value]);
-
- const clamp = (val: number, min: number, max: number) => {
- return Math.min(Math.max(val, min), max);
- };
-
- const handlePointerDown = (event: React.PointerEvent) => {
- if (event.button !== 0) return;
- // Avoid dragging if a button, icon, textarea etc. was clicked
- const target = event.target as HTMLElement;
- if (
- target.closest("button") ||
- target.closest(".sent-button") ||
- target.closest("textarea") ||
- target.closest(".options-button") ||
- target.closest(".options-list") ||
- target.closest(".send-message-wrapper") ||
- target.closest(".options delete")
- ) {
- return;
- }
-
- const wrapper = wrapperRef.current;
- if (!wrapper) return;
-
- const rect = wrapper.getBoundingClientRect();
- const offsetX = event.clientX - rect.left;
- const offsetY = event.clientY - rect.top;
-
- setDragging(true);
- setDragOffset({ x: offsetX, y: offsetY });
-
- wrapper.setPointerCapture(event.pointerId);
- };
-
- const updatePosition = (
- { clientX, clientY }: { clientX: number; clientY: number },
- allowMove: boolean = true
- ) => {
- if (!allowMove || !wrapperRef.current) return;
-
- const container = document.getElementById("work-space-three-d-canvas");
- const wrapper = wrapperRef.current;
- if (!container || !wrapper) return;
-
- const containerRect = container.getBoundingClientRect();
-
- let newX = clientX - containerRect.left - dragOffset.x;
- let newY = clientY - containerRect.top - dragOffset.y;
-
- const maxX = containerRect.width - wrapper.offsetWidth;
- const maxY = containerRect.height - wrapper.offsetHeight;
-
- newX = clamp(newX, 0, maxX);
- newY = clamp(newY, 0, maxY);
-
- setPosition({ x: newX, y: newY });
- };
-
- const handlePointerMove = (e: { clientX: number; clientY: number }) => {
- if (dragging) updatePosition(e, true);
- };
-
- // Commented this useEffect to prevent offset after user saved the comment
- // useEffect(() => {
- // updatePosition({ clientX: position.x, clientY: position.y }, true);
- // }, [selectedComment]);
-
-
- const handlePointerUp = (event: React.PointerEvent) => {
- if (!dragging) return;
- setDragging(false);
- const wrapper = wrapperRef.current;
- if (wrapper) wrapper.releasePointerCapture(event.pointerId);
- };
-
- const handleCreateComments = async (e: any) => {
- // Continue send or create message only there is only value avalibale
- // To prevent empty value
-
- if (!value) return;
- e.preventDefault();
- try {
- // const createComments = await addCommentsApi(projectId, value, selectedComment?.threadId, selectedVersion?.versionId || "")/
- // if (createComments.message === 'Thread comments add Successfully' && createComments.data) {
- // const commentData = {
- // replyId: `${createComments.data?._id}`,
- // creatorId: `${selectedComment?.threadId}`,
- // createdAt: "2 hrs ago",
- // lastUpdatedAt: "2 hrs ago",
- // comment: value,
- // }
- // setMessages((prevMessages) => [
- // ...prevMessages,
- // commentData,
- // ]);
- // addReply(selectedComment?.threadId, commentData)
-
- // }
-
-
- if (threadSocket && mode === "create") {
- const addComment = {
- versionId: selectedVersion?.versionId || "",
- projectId,
- userId,
- comment: value,
- organization,
- threadId: selectedComment?.threadId,
+ const clamp = (val: number, min: number, max: number) => {
+ return Math.min(Math.max(val, min), max);
+ };
+ const handlePointerDown = (event: React.PointerEvent) => {
+ if (event.button !== 0) return;
+ // Avoid dragging if a button, icon, textarea etc. was clicked
+ const target = event.target as HTMLElement;
+ if (target.closest("button") || target.closest(".sent-button") || target.closest("textarea") || target.closest(".options-button") || target.closest(".options-list") || target.closest(".send-message-wrapper") || target.closest(".options delete")) {
+ return;
}
- threadSocket.emit("v1-Comment:add", addComment);
- }
- } catch {
+ const wrapper = wrapperRef.current;
+ if (!wrapper) return;
- }
- setInputActive(false)
- }
- const handleDeleteThread = async () => {
- if (!projectId) return;
- try {
- // const deleteThread = await deleteThreadApi(projectId, selectedComment?.threadId, selectedVersion?.versionId || "")
- //
- // if (deleteThread.message === "Thread deleted Successfully") {
- // removeComment(selectedComment?.threadId)
- // setSelectedComment([])
- // }
+ const rect = wrapper.getBoundingClientRect();
+ const offsetX = event.clientX - rect.left;
+ const offsetY = event.clientY - rect.top;
- if (threadSocket) {
- // projectId, userId, organization, threadId
- const deleteThread = {
- projectId,
- userId,
- organization,
- threadId: selectedComment?.threadId,
- versionId: selectedVersion?.versionId || ""
- }
- setSelectedComment(null)
- removeComment(selectedComment?.threadId)
- threadSocket.emit("v1:thread:delete", deleteThread);
- }
- }
- catch {
+ setDragging(true);
+ setDragOffset({ x: offsetX, y: offsetY });
- }
- }
+ wrapper.setPointerCapture(event.pointerId);
+ };
- const handleCreateThread = async (e: any) => {
- e.preventDefault();
- if (!projectId) return;
+ const updatePosition = ({ clientX, clientY }: { clientX: number; clientY: number }, allowMove: boolean = true) => {
+ if (!allowMove || !wrapperRef.current) return;
- try {
- // try {
- // const thread = await createThreadApi(
- // projectId,
- // "active",
- // commentPositionState[0].position,
- // [0, 0, 0],
- // value,
- // selectedVersion?.versionId || ""
- // );
- //
- //
+ const container = document.getElementById("work-space-three-d-canvas");
+ const wrapper = wrapperRef.current;
+ if (!container || !wrapper) return;
- // if (thread.message === "Thread created Successfully" && thread?.threadData) {
- //
- // const comment: CommentSchema = {
- // state: 'active',
- // threadId: thread?.threadData?._id,
- // creatorId: userId,
- // createdAt: getRelativeTime(thread.threadData?.createdAt),
- // threadTitle: value,
- // lastUpdatedAt: new Date().toISOString(),
- // position: commentPositionState[0].position,
- // rotation: [0, 0, 0],
- // comments: []
- // }
- // addComment(comment);
- // setCommentPositionState(null);
- // setInputActive(false);
- // setSelectedComment([])
- // }
+ const containerRect = container.getBoundingClientRect();
- const createThread = {
- projectId,
- versionId: selectedVersion?.versionId || "",
- userId,
- organization,
- state: "active",
- position: commentPositionState.position,
- rotation: [0, 0, 0],
- threadTitle: value,
- };
+ let newX = clientX - containerRect.left - dragOffset.x;
+ let newY = clientY - containerRect.top - dragOffset.y;
- if (threadSocket) {
+ const maxX = containerRect.width - wrapper.offsetWidth;
+ const maxY = containerRect.height - wrapper.offsetHeight;
+ newX = clamp(newX, 0, maxX);
+ newY = clamp(newY, 0, maxY);
+ setPosition({ x: newX, y: newY });
+ };
+
+ const handlePointerMove = (e: { clientX: number; clientY: number }) => {
+ if (dragging) updatePosition(e, true);
+ };
+
+ // Commented this useEffect to prevent offset after user saved the comment
+ // useEffect(() => {
+ // updatePosition({ clientX: position.x, clientY: position.y }, true);
+ // }, [selectedComment]);
+
+ const handlePointerUp = (event: React.PointerEvent) => {
+ if (!dragging) return;
+ setDragging(false);
+ const wrapper = wrapperRef.current;
+ if (wrapper) wrapper.releasePointerCapture(event.pointerId);
+ };
+
+ const handleCreateComments = async (e: any) => {
+ // Continue send or create message only there is only value avalibale
+ // To prevent empty value
+
+ if (!value) return;
+ e.preventDefault();
+ try {
+ // const createComments = await addCommentsApi(projectId, value, selectedComment?.threadId, selectedVersion?.versionId || "")/
+ // if (createComments.message === 'Thread comments add Successfully' && createComments.data) {
+ // const commentData = {
+ // replyId: `${createComments.data?._id}`,
+ // creatorId: `${selectedComment?.threadId}`,
+ // createdAt: "2 hrs ago",
+ // lastUpdatedAt: "2 hrs ago",
+ // comment: value,
+ // }
+ // setMessages((prevMessages) => [
+ // ...prevMessages,
+ // commentData,
+ // ]);
+ // addReply(selectedComment?.threadId, commentData)
+ // }
+
+ if (threadSocket && mode === "create") {
+ const addComment = {
+ versionId: selectedVersion?.versionId || "",
+ projectId,
+ userId,
+ comment: value,
+ organization,
+ threadId: selectedComment?.threadId,
+ };
+
+ threadSocket.emit("v1-Comment:add", addComment);
+ }
+ } catch {}
setInputActive(false);
- threadSocket.emit("v1:thread:create", createThread);
- }
- } catch (err) {
+ };
+ const handleDeleteThread = async () => {
+ if (!projectId) return;
+ try {
+ // const deleteThread = await deleteThreadApi(projectId, selectedComment?.threadId, selectedVersion?.versionId || "")
+ // if (deleteThread.message === "Thread deleted Successfully") {
+ // removeComment(selectedComment?.threadId)
+ // setSelectedComment([])
+ // }
- }
- };
+ if (threadSocket) {
+ // projectId, userId, organization, threadId
+ const deleteThread = {
+ projectId,
+ userId,
+ organization,
+ threadId: selectedComment?.threadId,
+ versionId: selectedVersion?.versionId || "",
+ };
+ setSelectedComment(null);
+ removeComment(selectedComment?.threadId);
+ threadSocket.emit("v1:thread:delete", deleteThread);
+ }
+ } catch {}
+ };
- const scrollToBottom = () => {
- const messagesWrapper = document.querySelector(".messages-wrapper");
- if (messagesWrapper) {
- messagesWrapper.scrollTop = messagesWrapper.scrollHeight;
- }
- };
+ const handleCreateThread = async (e: any) => {
+ e.preventDefault();
+ if (!projectId) return;
- useEffect(() => {
- if (messages.length > 0)
- scrollToBottom();
- }, [messages])
+ try {
+ // const thread = await createThreadApi(
+ // projectId,
+ // "active",
+ // commentPositionState[0].position,
+ // [0, 0, 0],
+ // value,
+ // selectedVersion?.versionId || ""
+ // );
+ //
+ // if (thread.message === "Thread created Successfully" && thread?.threadData) {
+ //
+ // const comment: CommentSchema = {
+ // state: 'active',
+ // threadId: thread?.threadData?._id,
+ // creatorId: userId,
+ // createdAt: getRelativeTime(thread.threadData?.createdAt),
+ // threadTitle: value,
+ // lastUpdatedAt: new Date().toISOString(),
+ // position: commentPositionState[0].position,
+ // rotation: [0, 0, 0],
+ // comments: []
+ // }
+ // addComment(comment);
+ // setCommentPositionState(null);
+ // setInputActive(false);
+ // setSelectedComment([])
+ // }
- return (
- handlePointerMove({ clientX: e.clientX, clientY: e.clientY })}
- onPointerUp={handlePointerUp}
- style={{
- position: "absolute",
- left: position.x,
- top: position.y,
- cursor: dragging ? "grabbing" : "grab",
- userSelect: "none",
- zIndex: 9999,
- }}
- >
-
-
-
Comment
-
-
{
- e.preventDefault();
- setOpenThreadOptions((prev) => !prev);
- }}
- >
-
+ const createThread = {
+ projectId,
+ versionId: selectedVersion?.versionId || "",
+ userId,
+ organization,
+ state: "active",
+ position: commentPositionState.position,
+ rotation: [0, 0, 0],
+ threadTitle: value,
+ };
+
+ if (threadSocket) {
+ setInputActive(false);
+ threadSocket.emit("v1:thread:create", createThread);
+ }
+ } catch {}
+ };
+
+ const scrollToBottom = () => {
+ const messagesWrapper = document.querySelector(".messages-wrapper");
+ if (messagesWrapper) {
+ messagesWrapper.scrollTop = messagesWrapper.scrollHeight;
+ }
+ };
+
+ useEffect(() => {
+ if (messages.length > 0) scrollToBottom();
+ }, [messages]);
+
+ return (
+
handlePointerMove({ clientX: e.clientX, clientY: e.clientY })}
+ onPointerUp={handlePointerUp}
+ style={{
+ position: "absolute",
+ left: position.x,
+ top: position.y,
+ cursor: dragging ? "grabbing" : "grab",
+ userSelect: "none",
+ zIndex: 9999,
+ }}
+ >
+
+
+
Comment
+
+
{
+ e.preventDefault();
+ setOpenThreadOptions((prev) => !prev);
+ }}
+ >
+
+
+ {openThreadOptions && (
+
+
Mark as Unread
+
Mark as Resolved
+
+ Delete Thread
+
+
+ )}
+
+
+
+
+
+ {selectedComment && }
+ {messages && messages.map((val, i) => )}
+
+
+
- {openThreadOptions && (
-
-
Mark as Unread
-
Mark as Resolved
-
Delete Thread
-
- )}
-
-
+
-
-
- {selectedComment &&
-
- }
- {messages && messages.map((val, i) => (
-
- ))}
-
-
-
-
-
-
-
- );
+ );
};
export default ThreadChat;
diff --git a/app/src/components/ui/compareVersion/CompareLayOut.tsx b/app/src/components/ui/compareVersion/CompareLayOut.tsx
index 29b062a..3c98b6f 100644
--- a/app/src/components/ui/compareVersion/CompareLayOut.tsx
+++ b/app/src/components/ui/compareVersion/CompareLayOut.tsx
@@ -1,208 +1,220 @@
+import { useParams } from "react-router-dom";
import React, { useState, useRef, useEffect, Suspense } from "react";
-import {
- CompareLayoutIcon,
- LayoutIcon,
- ResizerIcon,
-} from "../../icons/SimulationIcons";
-import {
- useLoadingProgress,
- useSaveVersion,
-} from "../../../store/builder/store";
+import { CompareLayoutIcon, LayoutIcon, ResizerIcon } from "../../icons/SimulationIcons";
+import { useLoadingProgress, useIsComparing } from "../../../store/builder/store";
+import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
+import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
+import { useSceneContext } from "../../../modules/scene/sceneContext";
+import { getAllProductsApi } from "../../../services/simulation/products/getallProductsApi";
import Search from "../inputs/Search";
import OuterClick from "../../../utils/outerClick";
import Scene from "../../../modules/scene/scene";
-import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
-import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
-import { useVersionHistoryStore } from "../../../store/builder/useVersionHistoryStore";
-import { useVersionContext } from "../../../modules/builder/version/versionContext";
-import { useSceneContext } from "../../../modules/scene/sceneContext";
-import { getAllProductsApi } from "../../../services/simulation/products/getallProductsApi";
-import { useParams } from "react-router-dom";
+import useRestStates from "../../../hooks/useResetStates";
+
+import { getVersionHistoryApi } from "../../../services/factoryBuilder/versionControl/getVersionHistoryApi";
const CompareLayOut = () => {
- const { clearComparisonProduct, comparisonProduct, setComparisonProduct } = useComparisonProduct();
- const { productStore } = useSceneContext();
- const { products } = productStore();
- const { versionHistory } = useVersionHistoryStore();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion, setSelectedVersion, clearSelectedVersion } = selectedVersionStore();
- const { setLoadingProgress } = useLoadingProgress();
- const [width, setWidth] = useState("50vw");
- const [isResizing, setIsResizing] = useState(false);
- const [showLayoutDropdown, setShowLayoutDropdown] = useState(false);
- const wrapperRef = useRef
(null);
- const startWidthRef = useRef(0);
- const startXRef = useRef(0);
- const { setIsVersionSaved } = useSaveVersion();
- const { loadingProgress } = useLoadingProgress();
- const { setIsPlaying } = usePlayButtonStore();
- const { projectId } = useParams();
+ const { clearComparisonProduct, comparisonProduct, setComparisonProduct } = useComparisonProduct();
+ const { versionStore } = useSceneContext();
+ const { versionHistory, selectedVersion, setSelectedVersion, clearSelectedVersion, setVersions } = versionStore();
+ const { setLoadingProgress } = useLoadingProgress();
+ const [width, setWidth] = useState("50vw");
+ const [isResizing, setIsResizing] = useState(false);
+ const [showLayoutDropdown, setShowLayoutDropdown] = useState(false);
+ const wrapperRef = useRef(null);
+ const startWidthRef = useRef(0);
+ const startXRef = useRef(0);
+ const { setIsComparing } = useIsComparing();
+ const { loadingProgress } = useLoadingProgress();
+ const { setIsPlaying } = usePlayButtonStore();
+ const { projectId } = useParams();
+ const { resetStates } = useRestStates();
- useEffect(() => {
- if (!comparisonProduct) {
- clearSelectedVersion();
- }
- }, [comparisonProduct])
+ useEffect(() => {
+ return () => {
+ if (selectedVersion?.versionId) {
+ resetStates();
+ }
+ };
+ }, [selectedVersion?.versionId]);
- OuterClick({
- contextClassName: ["displayLayouts-container", "selectLayout"],
- setMenuVisible: () => setShowLayoutDropdown(false),
- });
+ useEffect(() => {
+ if (!projectId) return;
- const handleStartResizing = (e: React.MouseEvent) => {
- e.preventDefault();
- setIsResizing(true);
- startXRef.current = e.clientX;
- if (wrapperRef.current) {
- startWidthRef.current = wrapperRef.current.getBoundingClientRect().width;
- }
- };
+ getVersionHistoryApi(projectId)
+ .then((data) => {
+ const versions: VersionHistory = [];
+ data.versions.forEach((version: any) => {
+ versions.push({
+ version: version.version,
+ versionId: version.versionId,
+ versionName: version.versionName,
+ versionDescription: version.description,
+ timeStamp: version.createdAt,
+ createdBy: version.createdBy.userName,
+ });
+ });
+ setVersions(versions);
+ })
+ .catch(() => {
+ console.error("Error fetching version history");
+ });
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [projectId]);
- const handleMouseMove = (e: MouseEvent) => {
- if (!isResizing || !wrapperRef.current) return;
+ useEffect(() => {
+ if (!comparisonProduct) {
+ clearSelectedVersion();
+ }
+ }, [comparisonProduct]);
- const dx = startXRef.current - e.clientX;
- const newWidthPx = startWidthRef.current + dx;
- const viewportWidth = window.innerWidth;
- const newWidthVw = (newWidthPx / viewportWidth) * 100;
+ OuterClick({
+ contextClassName: ["displayLayouts-container", "selectLayout"],
+ setMenuVisible: () => setShowLayoutDropdown(false),
+ });
- if (newWidthVw <= 10) {
- setWidth("0px");
- } else if (newWidthVw <= 90) {
- setWidth(`${newWidthPx}px`);
- }
- };
-
- const handleMouseUp = () => {
- if (!isResizing) return;
-
- if (wrapperRef.current) {
- const finalWidthPx = wrapperRef.current.getBoundingClientRect().width;
- const viewportWidth = window.innerWidth;
- const finalWidthVw = (finalWidthPx / viewportWidth) * 100;
-
- if (finalWidthVw <= 10) {
- setWidth("0px");
- setIsVersionSaved(false);
- clearComparisonProduct();
- setIsPlaying(false);
- } else {
- setWidth(`${finalWidthVw}vw`);
- }
- }
-
- setIsResizing(false);
- };
-
- useEffect(() => {
- if (isResizing) {
- window.addEventListener("mousemove", handleMouseMove);
- window.addEventListener("mouseup", handleMouseUp);
- document.body.classList.add("resizing-active");
- }
-
- return () => {
- window.removeEventListener("mousemove", handleMouseMove);
- window.removeEventListener("mouseup", handleMouseUp);
- document.body.classList.remove("resizing-active");
- };
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [isResizing]);
-
- // Maintain proportional width on window resize
- useEffect(() => {
- const handleResize = () => {
- if (!wrapperRef.current || isResizing) return;
-
- const currentWidth = wrapperRef.current.style.width;
- if (currentWidth === "0px" || currentWidth.endsWith("vw")) return;
-
- const pxWidth = parseFloat(currentWidth);
- const vwWidth = (pxWidth / window.innerWidth) * 100;
- setWidth(`${vwWidth}vw`);
+ const handleStartResizing = (e: React.MouseEvent) => {
+ e.preventDefault();
+ setIsResizing(true);
+ startXRef.current = e.clientX;
+ if (wrapperRef.current) {
+ startWidthRef.current = wrapperRef.current.getBoundingClientRect().width;
+ }
};
- window.addEventListener("resize", handleResize);
- return () => window.removeEventListener("resize", handleResize);
- }, [isResizing]);
+ const handleMouseMove = (e: MouseEvent) => {
+ if (!isResizing || !wrapperRef.current) return;
- const handleSelectLayout = (version: Version) => {
- getAllProductsApi(projectId || '', version.versionId || '').then((data) => {
- if (data && data.length > 0) {
- setSelectedVersion(version);
- setComparisonProduct(data[0].productUuid, data[0].productName);
- setLoadingProgress(1);
- }
- })
- };
+ const dx = startXRef.current - e.clientX;
+ const newWidthPx = startWidthRef.current + dx;
+ const viewportWidth = window.innerWidth;
+ const newWidthVw = (newWidthPx / viewportWidth) * 100;
- return (
-
- {loadingProgress == 0 && selectedVersion?.versionId && (
-
- )}
-
- {selectedVersion?.versionId && (
-
-
-
-
-
- )}
+ if (newWidthVw <= 10) {
+ setWidth("0px");
+ } else if (newWidthVw <= 90) {
+ setWidth(`${newWidthPx}px`);
+ }
+ };
- {width !== "0px" &&
- !selectedVersion?.versionId && ( // Show only if no layout selected
-
-
-
-
-
Choose Version to compare
-
+ const handleMouseUp = () => {
+ if (!isResizing) return;
- {showLayoutDropdown && (
-
-
Versions
-
{ }} />
-
- {versionHistory.map((version) => (
-
- ))}
-
-
- )}
+ if (wrapperRef.current) {
+ const finalWidthPx = wrapperRef.current.getBoundingClientRect().width;
+ const viewportWidth = window.innerWidth;
+ const finalWidthVw = (finalWidthPx / viewportWidth) * 100;
+
+ if (finalWidthVw <= 10) {
+ setWidth("0px");
+ setIsComparing(false);
+ clearComparisonProduct();
+ setIsPlaying(false);
+ } else {
+ setWidth(`${finalWidthVw}vw`);
+ }
+ }
+
+ setIsResizing(false);
+ };
+
+ useEffect(() => {
+ if (isResizing) {
+ window.addEventListener("mousemove", handleMouseMove);
+ window.addEventListener("mouseup", handleMouseUp);
+ document.body.classList.add("resizing-active");
+ }
+
+ return () => {
+ window.removeEventListener("mousemove", handleMouseMove);
+ window.removeEventListener("mouseup", handleMouseUp);
+ document.body.classList.remove("resizing-active");
+ };
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [isResizing]);
+
+ // Maintain proportional width on window resize
+ useEffect(() => {
+ const handleResize = () => {
+ if (!wrapperRef.current || isResizing) return;
+
+ const currentWidth = wrapperRef.current.style.width;
+ if (currentWidth === "0px" || currentWidth.endsWith("vw")) return;
+
+ const pxWidth = parseFloat(currentWidth);
+ const vwWidth = (pxWidth / window.innerWidth) * 100;
+ setWidth(`${vwWidth}vw`);
+ };
+
+ window.addEventListener("resize", handleResize);
+ return () => window.removeEventListener("resize", handleResize);
+ }, [isResizing]);
+
+ const handleSelectLayout = (version: Version) => {
+ getAllProductsApi(projectId || "", version.versionId || "").then((data) => {
+ if (data && data.length > 0) {
+ setSelectedVersion(version);
+ setComparisonProduct(data[0].productUuid, data[0].productName);
+ setLoadingProgress(1);
+ }
+ });
+ };
+
+ return (
+
+ {loadingProgress == 0 && selectedVersion?.versionId && (
+
+ )}
+
+ {selectedVersion?.versionId && (
+
+
+
+
+
+ )}
+
+ {width !== "0px" &&
+ !selectedVersion?.versionId && ( // Show only if no layout selected
+
+
+
+
+
Choose Version to compare
+
+
+ {showLayoutDropdown && (
+
+
Versions
+
{}} />
+
+ {versionHistory.map((version) => (
+
+ ))}
+
+
+ )}
+
+ )}
+
+ {/* Always show after layout is selected */}
- )}
-
- {/* Always show after layout is selected */}
-
-
- );
+
+ );
};
export default CompareLayOut;
diff --git a/app/src/components/ui/list/DropDownList.tsx b/app/src/components/ui/list/DropDownList.tsx
index bbf386d..ba5acdd 100644
--- a/app/src/components/ui/list/DropDownList.tsx
+++ b/app/src/components/ui/list/DropDownList.tsx
@@ -1,7 +1,7 @@
import React from "react";
-import List from "./List";
import { AddIcon, ArrowIcon, FocusIcon } from "../../icons/ExportCommonIcons";
import KebabMenuListMultiSelect from "./KebebMenuListMultiSelect";
+import List from "./OutlineList/ListNew";
interface DropDownListProps {
value?: string;
diff --git a/app/src/components/ui/list/List.tsx b/app/src/components/ui/list/List.tsx
deleted file mode 100644
index 8f38189..0000000
--- a/app/src/components/ui/list/List.tsx
+++ /dev/null
@@ -1,368 +0,0 @@
-import React, { useEffect, useState } from "react";
-import RenameInput from "../inputs/RenameInput";
-
-import { useSelectedZoneStore } from "../../../store/visualization/useZoneStore";
-import { getZoneData } from "../../../services/visulization/zone/getZones";
-import useModuleStore, {
- useSubModuleStore,
-} from "../../../store/useModuleStore";
-import {
- ArrowIcon,
- EyeIcon,
- LockIcon,
- RemoveIcon,
-} from "../../icons/ExportCommonIcons";
-import { useZoneAssetId } from "../../../store/builder/store";
-import { zoneCameraUpdate } from "../../../services/visulization/zone/zoneCameraUpdation";
-import { setAssetsApi } from "../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
-import { useParams } from "react-router-dom";
-import { getUserData } from "../../../functions/getUserData";
-import { useSceneContext } from "../../../modules/scene/sceneContext";
-import { useVersionContext } from "../../../modules/builder/version/versionContext";
-
-interface Asset {
- id: string;
- name: string;
- position?: [number, number, number]; // Proper 3D vector
- rotation?: { x: number; y: number; z: number }; // Proper rotation format
-}
-
-interface ZoneItem {
- id: string;
- name: string;
- assets?: Asset[];
- active?: boolean;
-}
-
-interface ListProps {
- items?: ZoneItem[];
- remove?: boolean;
-}
-
-const List: React.FC
= ({ items = [], remove }) => {
- const { activeModule } = useModuleStore();
- const { selectedZone, setSelectedZone } = useSelectedZoneStore();
- const { zoneAssetId, setZoneAssetId } = useZoneAssetId();
-
- const { setSubModule } = useSubModuleStore();
- const [expandedZones, setExpandedZones] = useState>(
- {}
- );
- const { projectId } = useParams();
- const { assetStore } = useSceneContext();
- const { setName } = assetStore();
- const { organization } = getUserData();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { zoneStore } = useSceneContext();
- const { zones, setZoneName } = zoneStore();
-
-
- useEffect(() => {
- useSelectedZoneStore.getState().setSelectedZone({
- zoneName: "",
- activeSides: [],
- panelOrder: [],
- lockedPanels: [],
- zoneUuid: "",
- zoneViewPortTarget: [],
- zoneViewPortPosition: [],
- widgets: [],
- });
- }, [activeModule]);
-
- useEffect(() => {
- const expanded: Record = { "unassigned-zone": true };
- if (zones.length > 0) {
- zones.forEach((zone: any) => {
- expanded[zone.zoneUuid] = true;
- });
- }
- setExpandedZones(expanded);
- // eslint-disable-next-line
- }, [zones.length]);
-
- const toggleZoneExpansion = (zoneUuid: string) => {
- setExpandedZones((prev) => ({
- ...prev,
- [zoneUuid]: !prev[zoneUuid],
- }));
- };
-
- async function handleSelectZone(id: string) {
- try {
- if (selectedZone?.zoneUuid === id || id === "unassigned-zone") {
- return;
- }
-
- setSubModule("zoneProperties");
-
- let response = await getZoneData(
- id,
- organization,
- projectId,
- selectedVersion?.versionId || ""
- );
-
- if (!response) return;
-
- setSelectedZone({
- zoneName: response?.zoneName,
- activeSides: response?.activeSides ?? [],
- panelOrder: response?.panelOrder ?? [],
- lockedPanels: response?.lockedPanels ?? [],
- widgets: response?.widgets ?? [],
- zoneUuid: response?.zoneUuid,
- zoneViewPortTarget: response?.viewPortTarget ?? [],
- zoneViewPortPosition: response?.viewPortPosition ?? [],
- });
- } catch (error) {
- echo.error("Failed to select zone");
- }
- }
-
- function handleAssetClick(asset: Asset) {
-
- setZoneAssetId(asset);
- }
-
- async function handleZoneNameChange(newName: string) {
- const isDuplicate = zones.some(
- (zone: any) =>
- zone.zoneName?.trim().toLowerCase() === newName?.trim().toLowerCase() &&
- zone.zoneUuid !== selectedZone.zoneUuid
- );
-
- if (isDuplicate) {
- alert("Zone name already exists. Please choose a different name.");
- return; // DO NOT update state
- }
- const zonesdata = {
- zoneUuid: selectedZone.zoneUuid,
- zoneName: newName,
- };
- const response = await zoneCameraUpdate(
- zonesdata,
- organization,
- projectId,
- selectedVersion?.versionId || ""
- );
- if (response.message === "zone updated") {
- setSelectedZone((prev) => ({ ...prev, zoneName: newName }));
- setZoneName(selectedZone.zoneUuid, newName);
- }
- }
-
- async function handleZoneAssetName(newName: string) {
- if (zoneAssetId?.id) {
- let response = await setAssetsApi({
- modelUuid: zoneAssetId.id,
- modelName: newName,
- projectId,
- versionId: selectedVersion?.versionId || ''
-
- });
-
- setName(zoneAssetId.id, response.modelName);
- }
- }
- const checkZoneNameDuplicate = (name: string) => {
- return zones.some(
- (zone: any) =>
- zone.zoneName?.trim().toLowerCase() === name?.trim().toLowerCase() &&
- zone.zoneUuid !== selectedZone.zoneUuid
- );
- };
-
- useEffect(() => {
- let drag = false;
- let isLeftMouseDown = false;
-
- const contextClassNames = [
- "list-wrapper",
- "zone-properties-container",
- "list-container",
- ];
-
- const isOutsideClick = (target: EventTarget | null) => {
- if (!(target instanceof HTMLElement)) return true;
- return !contextClassNames.some((className) =>
- target.closest(`.${className}`)
- );
- };
-
- const onMouseDown = (evt: MouseEvent) => {
- if (evt.button === 0) {
- isLeftMouseDown = true;
- drag = false;
- }
- };
-
- const onMouseMove = () => {
- if (isLeftMouseDown) {
- drag = true;
- }
- };
-
- const onMouseUp = (evt: MouseEvent) => {
- if (evt.button === 0) {
- isLeftMouseDown = false;
- if (drag) return;
-
- if (isOutsideClick(evt.target)) {
- // Clear selected zone
- setSelectedZone({
- zoneUuid: "",
- zoneName: "",
- activeSides: [],
- panelOrder: [],
- lockedPanels: [],
- widgets: [],
- zoneViewPortTarget: [],
- zoneViewPortPosition: [],
- });
- setZoneAssetId({
- id: "",
- name: "",
- });
- setSubModule("properties");
- }
- }
- };
-
- if (selectedZone.zoneName! === "" && activeModule === "Builder") {
- document.addEventListener("mousedown", onMouseDown);
- document.addEventListener("mousemove", onMouseMove);
- document.addEventListener("mouseup", onMouseUp);
- }
-
- return () => {
- document.removeEventListener("mousedown", onMouseDown);
- document.removeEventListener("mousemove", onMouseMove);
- document.removeEventListener("mouseup", onMouseUp);
- };
- // eslint-disable-next-line
- }, [selectedZone, activeModule]);
-
- return (
- <>
- {items?.length > 0 ? (
-
- {items?.map((item) => (
-
- - {
- handleSelectZone(item.id);
- toggleZoneExpansion(item.id);
- }}
- >
-
-
-
-
-
-
-
-
-
-
-
- {remove && (
-
-
-
- )}
- {item.assets && item.assets.length > 0 && (
-
- )}
-
-
-
- {/* Nested assets list - only shown when expanded */}
- {item.assets &&
- item.assets.length > 0 &&
- expandedZones[item.id] && (
-
- {item.assets.map((asset) => (
- - handleAssetClick(asset)}
- >
-
-
-
-
-
- {remove && (
-
- )}
-
-
-
- ))}
-
- )}
-
- ))}
-
- ) : (
-
- )}
- >
- );
-};
-
-export default List;
diff --git a/app/src/components/ui/list/OutlineList/AssetItem.tsx b/app/src/components/ui/list/OutlineList/AssetItem.tsx
new file mode 100644
index 0000000..e99080c
--- /dev/null
+++ b/app/src/components/ui/list/OutlineList/AssetItem.tsx
@@ -0,0 +1,15 @@
+import React from "react";
+import ListItemBase from "./ListItemBase";
+
+const AssetItem: React.FC = ({ asset, isActive, remove, onClick, onRename }) => (
+ onClick(asset)}
+ onRename={onRename}
+ />
+);
+
+export default AssetItem;
diff --git a/app/src/components/ui/list/OutlineList/ListItemBase.tsx b/app/src/components/ui/list/OutlineList/ListItemBase.tsx
new file mode 100644
index 0000000..0b2741f
--- /dev/null
+++ b/app/src/components/ui/list/OutlineList/ListItemBase.tsx
@@ -0,0 +1,83 @@
+import React from "react";
+import RenameInput from "../../inputs/RenameInput";
+import { ArrowIcon, EyeIcon, LockIcon, RemoveIcon } from "../../../icons/ExportCommonIcons";
+
+interface ListItemBaseProps {
+ id: string;
+ name: string;
+ isActive?: boolean;
+ canEdit?: boolean;
+ remove?: boolean;
+ expandable?: boolean;
+ expanded?: boolean;
+ onClick?: () => void;
+ onRename: (newName: string) => void;
+ onToggleExpand?: () => void;
+ children?: React.ReactNode; // For nested assets
+}
+
+const ListItemBase: React.FC = ({
+ id,
+ name,
+ isActive,
+ canEdit = true,
+ remove,
+ expandable,
+ expanded,
+ onClick,
+ onRename,
+ onToggleExpand,
+ children,
+}) => (
+ <>
+
+
+
+
+
+
+
+ {remove && (
+
+ )}
+ {expandable && (
+
+ )}
+
+
+
+
+ {expandable && expanded && }
+ >
+);
+
+export default ListItemBase;
diff --git a/app/src/components/ui/list/OutlineList/ListNew.tsx b/app/src/components/ui/list/OutlineList/ListNew.tsx
new file mode 100644
index 0000000..674ea37
--- /dev/null
+++ b/app/src/components/ui/list/OutlineList/ListNew.tsx
@@ -0,0 +1,49 @@
+import React from "react";
+import ZoneItemComponent from "./ZoneItem";
+import { useSelectedZoneStore } from "../../../../store/visualization/useZoneStore";
+import { useZoneAssetId } from "../../../../store/builder/store";
+import { useZoneAssetHandlers } from "../../../../functions/outlineHelpers/useZoneAssetHandlers";
+import { useZonesExpansion } from "../../../../functions/outlineHelpers/useZonesExpansion";
+
+const List: React.FC = ({ items = [], remove }) => {
+ const { selectedZone } = useSelectedZoneStore();
+ const { zoneAssetId } = useZoneAssetId();
+ const { expandedZones, toggleZoneExpansion } = useZonesExpansion(items);
+
+ const {
+ handleSelectZone,
+ handleZoneNameChange,
+ handleAssetClick,
+ handleZoneAssetName,
+ } = useZoneAssetHandlers();
+
+ if (items.length === 0) {
+ return (
+
+ );
+ }
+
+ return (
+
+ {items.map((item) => (
+
+ ))}
+
+ );
+};
+
+export default List;
diff --git a/app/src/components/ui/list/OutlineList/ZoneItem.tsx b/app/src/components/ui/list/OutlineList/ZoneItem.tsx
new file mode 100644
index 0000000..c515e68
--- /dev/null
+++ b/app/src/components/ui/list/OutlineList/ZoneItem.tsx
@@ -0,0 +1,45 @@
+import React from "react";
+import ListItemBase from "./ListItemBase";
+import AssetItem from "./AssetItem";
+
+const ZoneItemComponent: React.FC = ({
+ item,
+ isActive,
+ expanded,
+ remove,
+ activeAssetId,
+ onSelect,
+ onRename,
+ onToggleExpand,
+ onAssetClick,
+ onAssetRename,
+}) => (
+ {
+ onSelect(item.id);
+ onToggleExpand(item.id);
+ }}
+ onRename={onRename}
+ onToggleExpand={() => onToggleExpand(item.id)}
+ >
+ {item.assets?.map((asset) => (
+
+ ))}
+
+);
+
+export default ZoneItemComponent;
diff --git a/app/src/components/ui/menu/menu.tsx b/app/src/components/ui/menu/menu.tsx
index 3528176..babb9eb 100644
--- a/app/src/components/ui/menu/menu.tsx
+++ b/app/src/components/ui/menu/menu.tsx
@@ -2,266 +2,237 @@ import React, { useState } from "react";
import { useNavigate } from "react-router-dom";
import { ArrowIcon } from "../../icons/ExportCommonIcons";
import { toggleTheme } from "../../../utils/theme";
-import useVersionHistoryVisibleStore, {
- useShortcutStore,
-} from "../../../store/builder/store";
-import useModuleStore, {
- useSubModuleStore,
-} from "../../../store/useModuleStore";
-import { useVersionHistoryStore } from "../../../store/builder/useVersionHistoryStore";
+import useVersionHistoryVisibleStore, { useShortcutStore } from "../../../store/builder/store";
+import useModuleStore, { useSubModuleStore } from "../../../store/ui/useModuleStore";
+import { useSceneContext } from "../../../modules/scene/sceneContext";
interface MenuBarProps {
- setOpenMenu: (isOpen: boolean) => void;
+ setOpenMenu: (isOpen: boolean) => void;
}
interface MenuItem {
- label: string;
- onClick?: string;
- shortcut?: string;
- submenu?: MenuItem[];
- action?: () => void;
+ label: string;
+ onClick?: string;
+ shortcut?: string;
+ submenu?: MenuItem[];
+ action?: () => void;
}
const MenuBar: React.FC = ({ setOpenMenu }) => {
- const navigate = useNavigate();
- const [activeMenu, setActiveMenu] = useState(null);
- const [activeSubMenu, setActiveSubMenu] = useState(null);
- const [selectedItems, setSelectedItems] = useState>(
- {}
- );
+ const navigate = useNavigate();
+ const [activeMenu, setActiveMenu] = useState(null);
+ const [activeSubMenu, setActiveSubMenu] = useState(null);
+ const [selectedItems, setSelectedItems] = useState>({});
- const { setCreateNewVersion } = useVersionHistoryStore();
- const { setVersionHistoryVisible } = useVersionHistoryVisibleStore();
- const { setActiveModule } = useModuleStore();
- const { setSubModule } = useSubModuleStore();
- const { showShortcuts, setShowShortcuts } = useShortcutStore();
+ const { versionStore } = useSceneContext();
+ const { setCreateNewVersion } = versionStore();
+ const { setVersionHistoryVisible } = useVersionHistoryVisibleStore();
+ const { setActiveModule } = useModuleStore();
+ const { setSubModule } = useSubModuleStore();
+ const { showShortcuts, setShowShortcuts } = useShortcutStore();
- const savedTheme = localStorage.getItem("theme") ?? "light";
+ const savedTheme = localStorage.getItem("theme") ?? "light";
- const toggleSelection = (itemName: string) => {
- setSelectedItems((prev) => ({
- ...prev,
- [itemName]: !prev[itemName],
- }));
- };
+ const toggleSelection = (itemName: string) => {
+ setSelectedItems((prev) => ({
+ ...prev,
+ [itemName]: !prev[itemName],
+ }));
+ };
- // functions
- const handleThemeChange = () => {
- toggleTheme();
- window.location.reload();
- };
+ // functions
+ const handleThemeChange = () => {
+ toggleTheme();
+ window.location.reload();
+ };
- const handleLogout = () => {
- const theme = localStorage.getItem("theme") ?? "light";
- localStorage.clear();
- localStorage.setItem("theme", theme);
- navigate("/");
- };
+ const handleLogout = () => {
+ const theme = localStorage.getItem("theme") ?? "light";
+ localStorage.clear();
+ localStorage.setItem("theme", theme);
+ navigate("/");
+ };
- function handleShotcutsHelper() {
- setShowShortcuts(!showShortcuts);
- }
+ function handleShotcutsHelper() {
+ setShowShortcuts(!showShortcuts);
+ }
- function handleVersionCreation() {
- setCreateNewVersion(true);
- setVersionHistoryVisible(true);
- setSubModule("properties");
- setActiveModule("builder");
- }
+ function handleVersionCreation() {
+ setCreateNewVersion(true);
+ setVersionHistoryVisible(true);
+ setSubModule("properties");
+ setActiveModule("builder");
+ }
- const menus: Record = {
- File: [
- { label: "New File", shortcut: "Ctrl + N" },
- { label: "Open Local File", shortcut: "Ctrl + O" },
- {
- label: "Save Version",
- shortcut: "Ctrl + Alt + S",
- action: handleVersionCreation,
- },
- { label: "Make a Copy" },
- { label: "Share" },
- { label: "Rename" },
- { label: "Import" },
- { label: "Close File" },
- ],
- Edit: [
- { label: "Undo", shortcut: "Ctrl + Z" },
- { label: "Redo", shortcut: "Ctrl + Shift + Z" },
- { label: "Undo History" },
- { label: "Redo History" },
- { label: "Find", shortcut: "Ctrl + F" },
- { label: "Delete" },
- { label: "Select by..." },
- { label: "Keymap" },
- ],
- View: [
- { label: "Grid" },
- {
- label: "Gizmo",
- submenu: [
- { label: "Visibility" },
- { label: "Cube view" },
- { label: "Sphere view" },
+ const menus: Record = {
+ File: [
+ { label: "New File", shortcut: "Ctrl + N" },
+ { label: "Open Local File", shortcut: "Ctrl + O" },
+ {
+ label: "Save Version",
+ shortcut: "Ctrl + Alt + S",
+ action: handleVersionCreation,
+ },
+ { label: "Make a Copy" },
+ { label: "Share" },
+ { label: "Rename" },
+ { label: "Import" },
+ { label: "Close File" },
],
- },
- { label: "Zoom" },
- { label: "Full Screen", shortcut: "F11" },
- ],
- Help: [
- {
- label: "Shortcuts",
- shortcut: "Ctrl + Shift + ?",
- action: handleShotcutsHelper,
- },
- { label: "Manual" },
- { label: "Video Tutorials" },
- { label: "Report a bug" },
- ],
- };
+ Edit: [{ label: "Undo", shortcut: "Ctrl + Z" }, { label: "Redo", shortcut: "Ctrl + Shift + Z" }, { label: "Undo History" }, { label: "Redo History" }, { label: "Find", shortcut: "Ctrl + F" }, { label: "Delete" }, { label: "Select by..." }, { label: "Keymap" }],
+ View: [
+ { label: "Grid" },
+ {
+ label: "Gizmo",
+ submenu: [{ label: "Visibility" }, { label: "Cube view" }, { label: "Sphere view" }],
+ },
+ { label: "Zoom" },
+ { label: "Full Screen", shortcut: "F11" },
+ ],
+ Help: [
+ {
+ label: "Shortcuts",
+ shortcut: "Ctrl + Shift + ?",
+ action: handleShotcutsHelper,
+ },
+ { label: "Manual" },
+ { label: "Video Tutorials" },
+ { label: "Report a bug" },
+ ],
+ };
- // render menu item and sub menu item component
- const renderMenuItem = ({ label, shortcut, action }: MenuItem) => (
-
- );
-
- const renderSubMenu = (submenu: MenuItem[], parentLabel: string) => (
-
- {submenu.map((item) => (
+ // render menu item and sub menu item component
+ const renderMenuItem = ({ label, shortcut, action }: MenuItem) => (
- ))}
-
- );
-
- return (
- setOpenMenu(false)}>
-
- {Object.entries(menus).map(([menu, items]) => (
-
+ );
- {/* Theme */}
-
+ const renderSubMenu = (submenu: MenuItem[], parentLabel: string) => (
+
+ {submenu.map((item) => (
+
+ ))}
+
+ );
- {/* Log out */}
-
-
-
- );
+ return (
+ setOpenMenu(false)}>
+
+ {Object.entries(menus).map(([menu, items]) => (
+
+ ))}
+
+ {/* Version History */}
+
+
+ {/* Theme */}
+
+
+ {/* Log out */}
+
+
+
+ );
};
export default MenuBar;
diff --git a/app/src/components/ui/simulation/AssetDetailsCard.tsx b/app/src/components/ui/simulation/AssetDetailsCard.tsx
index 34dfb6f..f762a2b 100644
--- a/app/src/components/ui/simulation/AssetDetailsCard.tsx
+++ b/app/src/components/ui/simulation/AssetDetailsCard.tsx
@@ -5,7 +5,7 @@ import {
SimulationStatusIcon,
StorageCapacityIcon,
} from "../../icons/SimulationIcons";
-import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
+import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
interface AssetDetailsCardInterface {
name: string;
diff --git a/app/src/components/ui/simulation/simulationPlayer.tsx b/app/src/components/ui/simulation/simulationPlayer.tsx
index 5875ee5..53a7cf8 100644
--- a/app/src/components/ui/simulation/simulationPlayer.tsx
+++ b/app/src/components/ui/simulation/simulationPlayer.tsx
@@ -11,7 +11,7 @@ import {
usePauseButtonStore,
usePlayButtonStore,
useResetButtonStore,
-} from "../../../store/usePlayButtonStore";
+} from "../../../store/ui/usePlayButtonStore";
import {
DailyProductionIcon,
EndIcon,
@@ -26,15 +26,15 @@ import {
import { getAvatarColor } from "../../../modules/collaboration/functions/getAvatarColor";
import useModuleStore, {
useSubModuleStore,
-} from "../../../store/useModuleStore";
+} from "../../../store/ui/useModuleStore";
import ProductionCapacity from "../analysis/ThroughputSummary";
import ThroughputSummary from "../analysis/ProductionCapacity";
import ROISummary from "../analysis/ROISummary";
-import { usePlayerStore } from "../../../store/useUIToggleStore";
+import { usePlayerStore } from "../../../store/ui/useUIToggleStore";
import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
import InputToggle from "../inputs/InputToggle";
import { saveSimulationData } from "../../layout/scenes/functions/simulationStorage";
-import { useProductContext } from "../../../modules/simulation/products/productContext";
+import { useSceneContext } from "../../../modules/scene/sceneContext";
const SimulationPlayer: React.FC = () => {
const MAX_SPEED = 8; // Maximum speed
@@ -55,8 +55,8 @@ const SimulationPlayer: React.FC = () => {
const { materialData, setMaterialData } = comparsionMaterialData()
const { isPlaying } = usePlayButtonStore();
const { activeModule } = useModuleStore();
- const { selectedProductStore } = useProductContext();
- const { selectedProduct, setSelectedProduct } = selectedProductStore();
+ const { productStore } = useSceneContext();
+ const { selectedProduct, setSelectedProduct } = productStore();
useEffect(() => {
if (isReset) {
setTimeout(() => {
diff --git a/app/src/functions/outlineHelpers/useZoneAssetHandlers.ts b/app/src/functions/outlineHelpers/useZoneAssetHandlers.ts
new file mode 100644
index 0000000..482e4a1
--- /dev/null
+++ b/app/src/functions/outlineHelpers/useZoneAssetHandlers.ts
@@ -0,0 +1,95 @@
+import { useCallback } from "react";
+import { useParams } from "react-router-dom";
+import { getUserData } from "../getUserData";
+import { getZoneData } from "../../services/visulization/zone/getZones";
+import { zoneCameraUpdate } from "../../services/visulization/zone/zoneCameraUpdation";
+import { setAssetsApi } from "../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
+import { useSelectedZoneStore } from "../../store/visualization/useZoneStore";
+import { useSubModuleStore } from "../../store/ui/useModuleStore";
+import { useSceneContext } from "../../modules/scene/sceneContext";
+import { useZoneAssetId } from "../../store/builder/store";
+
+export const useZoneAssetHandlers = () => {
+ const { projectId } = useParams();
+ const { organization } = getUserData();
+
+ const { selectedZone, setSelectedZone } = useSelectedZoneStore();
+ const { setSubModule } = useSubModuleStore();
+ const { zoneAssetId, setZoneAssetId } = useZoneAssetId();
+ const { assetStore, zoneStore, versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
+ const { setName } = assetStore();
+ const { zones, setZoneName } = zoneStore();
+
+ // 🔹 Zone selection
+ const handleSelectZone = useCallback(
+ async (id: string) => {
+ if (selectedZone?.zoneUuid === id || id === "unassigned-zone") return;
+ setSubModule("zoneProperties");
+
+ const response = await getZoneData(id, organization, projectId, selectedVersion?.versionId || "");
+ if (!response) return;
+
+ setSelectedZone({
+ zoneName: response.zoneName,
+ activeSides: response.activeSides ?? [],
+ panelOrder: response.panelOrder ?? [],
+ lockedPanels: response.lockedPanels ?? [],
+ widgets: response.widgets ?? [],
+ zoneUuid: response.zoneUuid,
+ zoneViewPortTarget: response.viewPortTarget ?? [],
+ zoneViewPortPosition: response.viewPortPosition ?? [],
+ });
+ },
+ [organization, projectId, selectedVersion, selectedZone?.zoneUuid, setSelectedZone, setSubModule]
+ );
+
+ // 🔹 Zone rename
+ const handleZoneNameChange = useCallback(
+ async (newName: string) => {
+ const isDuplicate = zones.some((zone: any) => zone.zoneName?.trim().toLowerCase() === newName.trim().toLowerCase() && zone.zoneUuid !== selectedZone.zoneUuid);
+ if (isDuplicate) {
+ alert("Zone name already exists. Please choose a different name.");
+ return;
+ }
+
+ const response = await zoneCameraUpdate({ zoneUuid: selectedZone.zoneUuid, zoneName: newName }, organization, projectId, selectedVersion?.versionId || "");
+
+ if (response.message === "zone updated") {
+ setSelectedZone((prev) => ({ ...prev, zoneName: newName }));
+ setZoneName(selectedZone.zoneUuid, newName);
+ }
+ },
+ [organization, projectId, selectedVersion, selectedZone, setSelectedZone, setZoneName, zones]
+ );
+
+ // 🔹 Asset selection
+ const handleAssetClick = useCallback(
+ (asset: ListAsset) => {
+ setZoneAssetId(asset);
+ },
+ [setZoneAssetId]
+ );
+
+ // 🔹 Asset rename
+ const handleZoneAssetName = useCallback(
+ async (newName: string) => {
+ if (!zoneAssetId?.id) return;
+ const response = await setAssetsApi({
+ modelUuid: zoneAssetId.id,
+ modelName: newName,
+ projectId,
+ versionId: selectedVersion?.versionId || "",
+ });
+ setName(zoneAssetId.id, response.modelName);
+ },
+ [projectId, selectedVersion, setName, zoneAssetId]
+ );
+
+ return {
+ handleSelectZone,
+ handleZoneNameChange,
+ handleAssetClick,
+ handleZoneAssetName,
+ };
+};
diff --git a/app/src/functions/outlineHelpers/useZonesExpansion.ts b/app/src/functions/outlineHelpers/useZonesExpansion.ts
new file mode 100644
index 0000000..83db4d1
--- /dev/null
+++ b/app/src/functions/outlineHelpers/useZonesExpansion.ts
@@ -0,0 +1,22 @@
+import { useEffect, useState, useCallback } from "react";
+
+export const useZonesExpansion = (zones: any[]) => {
+ const [expandedZones, setExpandedZones] = useState>({});
+
+ useEffect(() => {
+ const expanded: Record = { "unassigned-zone": true };
+ zones.forEach((zone) => {
+ expanded[zone.zoneUuid] = true;
+ });
+ setExpandedZones(expanded);
+ }, [zones, zones.length]);
+
+ const toggleZoneExpansion = useCallback((zoneUuid: string) => {
+ setExpandedZones((prev) => ({
+ ...prev,
+ [zoneUuid]: !prev[zoneUuid],
+ }));
+ }, []);
+
+ return { expandedZones, toggleZoneExpansion };
+};
diff --git a/app/src/hooks/useResetStates.ts b/app/src/hooks/useResetStates.ts
index d620ca5..b7ddd2c 100644
--- a/app/src/hooks/useResetStates.ts
+++ b/app/src/hooks/useResetStates.ts
@@ -1,20 +1,9 @@
-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 { selectedProductStore } = useProductContext();
- const { clearSelectedVersion } = selectedVersionStore();
- const { clearSelectedProduct } = selectedProductStore();
- const { clearVersions } = useVersionHistoryStore();
const { clearStores } = useSceneContext();
const resetStates = () => {
- clearSelectedVersion();
- clearSelectedProduct();
- clearVersions();
clearStores();
};
@@ -23,4 +12,4 @@ const useRestStates = () => {
};
};
-export default useRestStates;
\ No newline at end of file
+export default useRestStates;
diff --git a/app/src/modules/builder/Decal/decalCreator/decalCreator.tsx b/app/src/modules/builder/Decal/decalCreator/decalCreator.tsx
index 5e9ebaa..bb25cec 100644
--- a/app/src/modules/builder/Decal/decalCreator/decalCreator.tsx
+++ b/app/src/modules/builder/Decal/decalCreator/decalCreator.tsx
@@ -1,27 +1,25 @@
-import { MathUtils } from 'three';
-import { useEffect } from 'react';
-import { useThree } from '@react-three/fiber';
-import { useParams } from 'react-router-dom';
-import { useSocketStore } from '../../../../store/builder/store';
-import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
-import useModuleStore from '../../../../store/useModuleStore';
-import { useSceneContext } from '../../../scene/sceneContext';
-import { useVersionContext } from '../../version/versionContext';
+import { MathUtils } from "three";
+import { useEffect } from "react";
+import { useThree } from "@react-three/fiber";
+import { useParams } from "react-router-dom";
+import { useSocketStore } from "../../../../store/builder/store";
+import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
+import useModuleStore from "../../../../store/ui/useModuleStore";
+import { useSceneContext } from "../../../scene/sceneContext";
-import { getUserData } from '../../../../functions/getUserData';
+import { getUserData } from "../../../../functions/getUserData";
-import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi';
-import { upsertFloorApi } from '../../../../services/factoryBuilder/floor/upsertFloorApi';
+import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi";
+import { upsertFloorApi } from "../../../../services/factoryBuilder/floor/upsertFloorApi";
function DecalCreator() {
- const { wallStore, floorStore } = useSceneContext();
+ const { wallStore, floorStore, versionStore } = useSceneContext();
const { addDecal: addDecalOnWall, getWallById } = wallStore();
const { addDecal: addDecalOnFloor, getFloorById } = floorStore();
const { droppedDecal, setDroppedDecal } = useBuilderStore();
const { activeModule } = useModuleStore();
const { userId, organization } = getUserData();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { selectedVersion } = versionStore();
const { projectId } = useParams();
const { socket } = useSocketStore();
const { controls, gl, pointer, camera, raycaster, scene } = useThree();
@@ -36,8 +34,8 @@ function DecalCreator() {
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObjects(scene.children, true);
- const wallIntersect = intersects.find(i => i.object.userData.wallUuid);
- const floorIntersect = intersects.find(i => i.object.userData.floorUuid);
+ const wallIntersect = intersects.find((i) => i.object.userData.wallUuid);
+ const floorIntersect = intersects.find((i) => i.object.userData.floorUuid);
if (wallIntersect) {
const wall = getWallById(wallIntersect.object.userData.wallUuid);
@@ -50,14 +48,14 @@ function DecalCreator() {
decalName: droppedDecal.decalName,
decalId: droppedDecal.decalId,
decalType: {
- type: 'Wall',
+ type: "Wall",
wallUuid: wallIntersect.object.userData.wallUuid,
},
decalPosition: [point.x, point.y, (wall.wallThickness / 2 + 0.001) * (wallIntersect.normal?.z || 1)],
decalRotation: 0,
decalOpacity: 1,
decalScale: 0.5,
- }
+ };
addDecalOnWall(wallIntersect.object.userData.wallUuid, decal);
@@ -68,24 +66,23 @@ function DecalCreator() {
if (!socket?.connected) {
// API
- upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
+ upsertWallApi(projectId, selectedVersion?.versionId || "", updatedWall);
} else {
-
- // SOCKET
+ // SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:add', data);
+ socket.emit("v1:model-Wall:add", data);
}
}
}
- }, 0)
+ }, 0);
} else if (floorIntersect) {
const floor = getFloorById(floorIntersect.object.userData.floorUuid);
if (!floor) return;
@@ -97,14 +94,14 @@ function DecalCreator() {
decalName: droppedDecal.decalName,
decalId: droppedDecal.decalId,
decalType: {
- type: 'Floor',
+ type: "Floor",
floorUuid: floorIntersect.object.userData.floorUuid,
},
decalPosition: [point.x, point.y, -0.001],
decalRotation: 0,
decalOpacity: 1,
decalScale: 0.5,
- }
+ };
addDecalOnFloor(floorIntersect.object.userData.floorUuid, decal);
@@ -114,23 +111,22 @@ function DecalCreator() {
if (!socket?.connected) {
// API
- upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
+ upsertFloorApi(projectId, selectedVersion?.versionId || "", updatedFloor);
} else {
-
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:add', data);
+ socket.emit("v1:model-Floor:add", data);
}
}
- }, 0)
+ }, 0);
}
}
};
@@ -150,10 +146,7 @@ function DecalCreator() {
};
}, [droppedDecal, camera, activeModule, controls]);
- return (
- <>
- >
- )
+ return <>>;
}
-export default DecalCreator
\ No newline at end of file
+export default DecalCreator;
diff --git a/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx b/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx
index 9a095d9..85d6c3e 100644
--- a/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx
+++ b/app/src/modules/builder/Decal/decalInstance/decalInstance.tsx
@@ -5,7 +5,7 @@ import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
import { retrieveImage, storeImage } from '../../../../utils/indexDB/idbUtils';
import defaultMaterial from '../../../../assets/image/fallback/fallback decal 1.png';
-import useModuleStore from '../../../../store/useModuleStore';
+import useModuleStore from '../../../../store/ui/useModuleStore';
import { useEffect, useRef, useState } from 'react';
import { useDecalEventHandlers } from '../eventHandler/useDecalEventHandlers';
diff --git a/app/src/modules/builder/Decal/eventHandler/useDecalEventHandlers.ts b/app/src/modules/builder/Decal/eventHandler/useDecalEventHandlers.ts
index c213d69..3e0c413 100644
--- a/app/src/modules/builder/Decal/eventHandler/useDecalEventHandlers.ts
+++ b/app/src/modules/builder/Decal/eventHandler/useDecalEventHandlers.ts
@@ -4,9 +4,8 @@ import { ThreeEvent, useFrame, useThree } from '@react-three/fiber';
import { useEffect, useState } from 'react';
import { useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
-import useModuleStore from '../../../../store/useModuleStore';
+import useModuleStore from '../../../../store/ui/useModuleStore';
import { getUserData } from '../../../../functions/getUserData';
-import { useVersionContext } from '../../version/versionContext';
import { useParams } from 'react-router-dom';
import { useSceneContext } from '../../../scene/sceneContext';
@@ -25,7 +24,7 @@ export function useDecalEventHandlers({
decal: Decal;
visible: boolean;
}) {
- const { wallStore, floorStore } = useSceneContext();
+ const { wallStore, floorStore, versionStore } = useSceneContext();
const { removeDecal: removeDecalInWall, updateDecalPosition: updateDecalPositionInWall, getWallById, addDecal: addDecalToWall } = wallStore();
const { removeDecal: removeDecalInFloor, updateDecalPosition: updateDecalPositionInFloor, getFloorById, addDecal: addDecalToFloor } = floorStore();
const { setSelectedWall, setSelectedFloor, setSelectedDecal, setDeletableDecal, deletableDecal, selectedDecal, setDecalDragState, decalDragState } = useBuilderStore();
@@ -33,8 +32,7 @@ export function useDecalEventHandlers({
const { toggleView } = useToggleView();
const { activeModule } = useModuleStore();
const { userId, organization } = getUserData();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { selectedVersion } = versionStore();
const { projectId } = useParams();
const { socket } = useSocketStore();
const [keyEvent, setKeyEvent] = useState<"Ctrl" | "">("");
diff --git a/app/src/modules/builder/aisle/aisleCreator/aisleCreator.tsx b/app/src/modules/builder/aisle/aisleCreator/aisleCreator.tsx
index 3af6f8f..3acdc83 100644
--- a/app/src/modules/builder/aisle/aisleCreator/aisleCreator.tsx
+++ b/app/src/modules/builder/aisle/aisleCreator/aisleCreator.tsx
@@ -1,16 +1,15 @@
-import * as THREE from 'three'
-import { useEffect, useMemo, useRef, useState } from 'react'
-import { useThree } from '@react-three/fiber';
-import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
-import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
-import { useParams } from 'react-router-dom';
-import { useVersionContext } from '../../version/versionContext';
-import { useSceneContext } from '../../../scene/sceneContext';
-import ReferenceAisle from './referenceAisle';
-import ReferencePoint from '../../point/reference/referencePoint';
-import { getUserData } from '../../../../functions/getUserData';
+import * as THREE from "three";
+import { useEffect, useMemo, useRef, useState } from "react";
+import { useThree } from "@react-three/fiber";
+import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from "../../../../store/builder/store";
+import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
+import { useParams } from "react-router-dom";
+import { useSceneContext } from "../../../scene/sceneContext";
+import ReferenceAisle from "./referenceAisle";
+import ReferencePoint from "../../point/reference/referencePoint";
+import { getUserData } from "../../../../functions/getUserData";
-import { upsertAisleApi } from '../../../../services/factoryBuilder/aisle/upsertAisleApi';
+import { upsertAisleApi } from "../../../../services/factoryBuilder/aisle/upsertAisleApi";
function AisleCreator() {
const { scene, camera, raycaster, gl, pointer } = useThree();
@@ -19,13 +18,12 @@ function AisleCreator() {
const { toolMode } = useToolMode();
const { activeLayer } = useActiveLayer();
const { socket } = useSocketStore();
- const { aisleStore, undoRedo2DStore } = useSceneContext();
+ const { aisleStore, undoRedo2DStore, versionStore } = useSceneContext();
const { addAisle, getAislePointById } = aisleStore();
const { push2D } = undoRedo2DStore();
const drag = useRef(false);
const isLeftMouseDown = useRef(false);
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { selectedVersion } = versionStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
@@ -63,13 +61,13 @@ function AisleCreator() {
let position = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (!position) return;
- const intersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Aisle-Point');
+ const intersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === "Aisle-Point");
const newPoint: Point = {
pointUuid: THREE.MathUtils.generateUUID(),
- pointType: 'Aisle',
+ pointType: "Aisle",
position: [position.x, position.y, position.z],
- layer: activeLayer
+ layer: activeLayer,
};
if (snappedPosition && snappedPoint) {
@@ -78,7 +76,9 @@ function AisleCreator() {
newPoint.layer = snappedPoint.layer;
}
- if (snappedPoint && snappedPoint.pointUuid === tempPoints[0]?.pointUuid) { return }
+ if (snappedPoint && snappedPoint.pointUuid === tempPoints[0]?.pointUuid) {
+ return;
+ }
if (snappedPosition && !snappedPoint) {
newPoint.position = snappedPosition;
@@ -101,7 +101,7 @@ function AisleCreator() {
"arrows-aisle": (color) => ({ aisleType: "arrows-aisle", aisleColor: color, aisleWidth, aisleLength, gapLength }),
"arc-aisle": (color) => ({ aisleType: "arc-aisle", aisleColor: color, aisleWidth, isFlipped }),
"circle-aisle": (color) => ({ aisleType: "circle-aisle", aisleColor: color, aisleWidth }),
- "junction-aisle": (color) => ({ aisleType: "junction-aisle", aisleColor: color, aisleWidth, isFlipped })
+ "junction-aisle": (color) => ({ aisleType: "junction-aisle", aisleColor: color, aisleWidth, isFlipped }),
};
if (!aisleType || !(aisleType in aisleConfigs)) return;
@@ -115,17 +115,19 @@ function AisleCreator() {
const aisle: Aisle = {
aisleUuid: THREE.MathUtils.generateUUID(),
points: [tempPoints[0], newPoint],
- type: aisleConfigs[aisleType](aisleColor)
+ type: aisleConfigs[aisleType](aisleColor),
};
addAisle(aisle);
push2D({
type: "Draw",
- actions: [{
- actionType: "Line-Create",
- point: { type: "Aisle", lineData: aisle, timeStamp: new Date().toISOString() }
- }]
+ actions: [
+ {
+ actionType: "Line-Create",
+ point: { type: "Aisle", lineData: aisle, timeStamp: new Date().toISOString() },
+ },
+ ],
});
addAilseToBackend(aisle);
@@ -136,13 +138,10 @@ function AisleCreator() {
const addAilseToBackend = (aisle: Aisle) => {
if (projectId) {
if (!socket?.connected) {
+ // API
- // API
-
- upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || '')
-
+ upsertAisleApi(aisle.aisleUuid, aisle.points, aisle.type, projectId, selectedVersion?.versionId || "");
} else {
-
// SOCKET
socket.emit("v1:model-aisle:add", {
@@ -152,11 +151,11 @@ function AisleCreator() {
organization,
aisleUuid: aisle.aisleUuid,
points: aisle.points,
- type: aisle.type
+ type: aisle.type,
});
}
}
- }
+ };
const onContext = (event: any) => {
event.preventDefault();
@@ -199,21 +198,19 @@ function AisleCreator() {
return (
<>
- {toggleView &&
+ {toggleView && (
<>
-
+
{tempPoints.map((point) => (
))}
- {tempPoints.length > 0 &&
-
- }
+ {tempPoints.length > 0 && }
>
- }
+ )}
>
);
}
-export default AisleCreator;
\ No newline at end of file
+export default AisleCreator;
diff --git a/app/src/modules/builder/aisle/aislesGroup.tsx b/app/src/modules/builder/aisle/aislesGroup.tsx
index 966a45b..7f9cdeb 100644
--- a/app/src/modules/builder/aisle/aislesGroup.tsx
+++ b/app/src/modules/builder/aisle/aislesGroup.tsx
@@ -1,44 +1,39 @@
-import { useEffect } from 'react'
-import AisleCreator from './aisleCreator/aisleCreator'
-import AisleInstances from './Instances/aisleInstances'
-import { useParams } from 'react-router-dom';
-import { getAisleApi } from '../../../services/factoryBuilder/aisle/getAisleApi';
-import { useVersionContext } from '../version/versionContext';
-import { useSceneContext } from '../../scene/sceneContext';
+import { useEffect } from "react";
+import AisleCreator from "./aisleCreator/aisleCreator";
+import AisleInstances from "./Instances/aisleInstances";
+import { useParams } from "react-router-dom";
+import { getAisleApi } from "../../../services/factoryBuilder/aisle/getAisleApi";
+import { useSceneContext } from "../../scene/sceneContext";
function AislesGroup() {
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { aisleStore } = useSceneContext();
+ const { aisleStore, versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
const { setAisles } = aisleStore();
const { projectId } = useParams();
useEffect(() => {
if (projectId && selectedVersion) {
- getAisleApi(projectId, selectedVersion?.versionId || '').then((aisles) => {
- if (aisles && aisles.length > 0) {
- setAisles(aisles);
- } else {
- setAisles([]);
- }
- }).catch((err) => {
- console.log(err);
- })
+ getAisleApi(projectId, selectedVersion?.versionId || "")
+ .then((aisles) => {
+ if (aisles && aisles.length > 0) {
+ setAisles(aisles);
+ } else {
+ setAisles([]);
+ }
+ })
+ .catch((err) => {
+ console.log(err);
+ });
}
- }, [projectId, selectedVersion?.versionId])
+ }, [projectId, selectedVersion?.versionId]);
return (
-
<>
-
-
-
>
-
- )
+ );
}
-export default AislesGroup
\ No newline at end of file
+export default AislesGroup;
diff --git a/app/src/modules/builder/asset/assetsGroup.tsx b/app/src/modules/builder/asset/assetsGroup.tsx
index ecdc926..0fcfcae 100644
--- a/app/src/modules/builder/asset/assetsGroup.tsx
+++ b/app/src/modules/builder/asset/assetsGroup.tsx
@@ -1,12 +1,12 @@
-import * as THREE from "three"
-import { useEffect } from 'react'
-import { getFloorAssets } from '../../../services/factoryBuilder/asset/floorAsset/getFloorItemsApi';
-import { useLoadingProgress, useRenameModeStore, useSelectedItem, useSocketStore } from '../../../store/builder/store';
+import * as THREE from "three";
+import { useEffect } from "react";
+import { getFloorAssets } from "../../../services/factoryBuilder/asset/floorAsset/getFloorItemsApi";
+import { useLoadingProgress, useRenameModeStore, useSelectedItem, useSocketStore } from "../../../store/builder/store";
import { GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import { FloorItems, RefMesh } from "../../../types/world/worldTypes";
import Models from "./models/models";
-import useModuleStore from "../../../store/useModuleStore";
+import useModuleStore from "../../../store/ui/useModuleStore";
import { useThree } from "@react-three/fiber";
import { CameraControls } from "@react-three/drei";
import addAssetModel from "./functions/addAssetModel";
@@ -14,7 +14,6 @@ import { useParams } from "react-router-dom";
import { useLeftData, useTopData } from "../../../store/visualization/useZone3DWidgetStore";
import { getUserData } from "../../../functions/getUserData";
import { useSceneContext } from "../../scene/sceneContext";
-import { useVersionContext } from "../version/versionContext";
import { useBuilderStore } from "../../../store/builder/useBuilderStore";
const gltfLoaderWorker = new Worker(new URL("../../../services/factoryBuilder/webWorkers/gltfLoaderWorker.js", import.meta.url));
@@ -24,9 +23,8 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
const { socket } = useSocketStore();
const { controls, gl, pointer, camera, raycaster, scene } = useThree();
const { setLoadingProgress } = useLoadingProgress();
- const { assetStore, eventStore } = useSceneContext();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { assetStore, eventStore, versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
const { setAssets, addAsset, clearAssets } = assetStore();
const { addEvent, clearEvents } = eventStore();
const { setSelectedFloorAsset } = useBuilderStore();
@@ -64,23 +62,25 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
}
};
- getFloorAssets(projectId, selectedVersion?.versionId || '').then((data) => {
- if (data && data.length > 0) {
- const uniqueItems = (data as FloorItems).filter((item, index, self) => index === self.findIndex((t) => t.assetId === item.assetId));
- totalAssets = uniqueItems.length;
- if (totalAssets === 0) {
+ getFloorAssets(projectId, selectedVersion?.versionId || "")
+ .then((data) => {
+ if (data && data.length > 0) {
+ const uniqueItems = (data as FloorItems).filter((item, index, self) => index === self.findIndex((t) => t.assetId === item.assetId));
+ totalAssets = uniqueItems.length;
+ if (totalAssets === 0) {
+ updateLoadingProgress(100);
+ return;
+ }
+ gltfLoaderWorker.postMessage({ floorItems: uniqueItems });
+ } else {
+ gltfLoaderWorker.postMessage({ floorItems: [] });
updateLoadingProgress(100);
- return;
+ clearAssets();
}
- gltfLoaderWorker.postMessage({ floorItems: uniqueItems });
- } else {
- gltfLoaderWorker.postMessage({ floorItems: [] });
- updateLoadingProgress(100);
- clearAssets();
- }
- }).catch((err) => {
- console.error(err);
- })
+ })
+ .catch((err) => {
+ console.error(err);
+ });
gltfLoaderWorker.onmessage = async (event) => {
if (event.data.message === "gltfLoaded" && event.data.modelBlob) {
@@ -96,7 +96,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
if (loadedAssets === totalAssets) {
const assets: Asset[] = [];
- getFloorAssets(projectId, selectedVersion.versionId || '').then((data: FloorItems) => {
+ getFloorAssets(projectId, selectedVersion.versionId || "").then((data: FloorItems) => {
data.forEach((item) => {
if (item.eventData) {
assets.push({
@@ -109,8 +109,8 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
isCollidable: false,
isVisible: item.isVisible,
opacity: 1,
- eventData: item.eventData
- })
+ eventData: item.eventData,
+ });
if (item.eventData.type === "Vehicle") {
const vehicleEvent: VehicleEventSchema = {
@@ -120,7 +120,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "vehicle",
- subType: item.eventData.subType as VehicleEventSchema['subType'] || '',
+ subType: (item.eventData.subType as VehicleEventSchema["subType"]) || "",
speed: 1,
point: {
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
@@ -140,9 +140,9 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
pickupDrop: [],
dropPickup: [],
},
- triggers: []
- }
- }
+ triggers: [],
+ },
+ },
};
addEvent(vehicleEvent);
} else if (item.eventData.type === "Conveyor") {
@@ -153,23 +153,24 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "transfer",
- subType: item.eventData.subType || '',
+ subType: item.eventData.subType || "",
speed: 1,
- points: item.eventData.points?.map((point: any, index: number) => ({
- uuid: point.uuid || THREE.MathUtils.generateUUID(),
- position: [point.position[0], point.position[1], point.position[2]],
- rotation: [point.rotation[0], point.rotation[1], point.rotation[2]],
- action: {
- actionUuid: THREE.MathUtils.generateUUID(),
- actionName: `Action 1`,
- actionType: 'default',
- material: 'Default material',
- delay: 0,
- spawnInterval: 5,
- spawnCount: 1,
- triggers: []
- }
- })) || [],
+ points:
+ item.eventData.points?.map((point: any, index: number) => ({
+ uuid: point.uuid || THREE.MathUtils.generateUUID(),
+ position: [point.position[0], point.position[1], point.position[2]],
+ rotation: [point.rotation[0], point.rotation[1], point.rotation[2]],
+ action: {
+ actionUuid: THREE.MathUtils.generateUUID(),
+ actionName: `Action 1`,
+ actionType: "default",
+ material: "Default material",
+ delay: 0,
+ spawnInterval: 5,
+ spawnCount: 1,
+ triggers: [],
+ },
+ })) || [],
};
addEvent(ConveyorEvent);
} else if (item.eventData.type === "StaticMachine") {
@@ -180,7 +181,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "machine",
- subType: item.eventData.subType || '',
+ subType: item.eventData.subType || "",
point: {
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
@@ -191,9 +192,9 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
actionType: "process",
processTime: 10,
swapMaterial: "Default Material",
- triggers: []
- }
- }
+ triggers: [],
+ },
+ },
};
addEvent(machineEvent);
} else if (item.eventData.type === "ArmBot") {
@@ -204,7 +205,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "roboticArm",
- subType: item.eventData.subType || '',
+ subType: item.eventData.subType || "",
speed: 1,
point: {
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
@@ -217,15 +218,15 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
actionType: "pickAndPlace",
process: {
startPoint: null,
- endPoint: null
+ endPoint: null,
},
- triggers: []
- }
- ]
- }
+ triggers: [],
+ },
+ ],
+ },
};
addEvent(roboticArmEvent);
- } else if (item.eventData.type === 'Storage') {
+ } else if (item.eventData.type === "Storage") {
const storageEvent: StorageEventSchema = {
modelUuid: item.modelUuid,
modelName: item.modelName,
@@ -236,7 +237,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
storageCapacity: 10,
storageCount: 10,
materialType: "Default material",
- subType: item.eventData.subType || '',
+ subType: item.eventData.subType || "",
point: {
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
@@ -246,13 +247,13 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Action 1",
actionType: "store",
- triggers: []
- }
- ]
- }
+ triggers: [],
+ },
+ ],
+ },
};
addEvent(storageEvent);
- } else if (item.eventData.type === 'Human') {
+ } else if (item.eventData.type === "Human") {
const humanEvent: HumanEventSchema = {
modelUuid: item.modelUuid,
modelName: item.modelName,
@@ -260,7 +261,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "human",
- subType: item.eventData.subType || '',
+ subType: item.eventData.subType || "",
speed: 1,
point: {
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
@@ -274,19 +275,19 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
loadCount: 1,
assemblyCount: 1,
assemblyCondition: {
- conditionType: 'material',
- materialType: "Default material"
+ conditionType: "material",
+ materialType: "Default material",
},
manufactureCount: 1,
loadCapacity: 1,
processTime: 10,
- triggers: []
- }
- ]
- }
- }
+ triggers: [],
+ },
+ ],
+ },
+ };
addEvent(humanEvent);
- } else if (item.eventData.type === 'Crane') {
+ } else if (item.eventData.type === "Crane") {
const craneEvent: CraneEventSchema = {
modelUuid: item.modelUuid,
modelName: item.modelName,
@@ -294,7 +295,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
rotation: [item.rotation.x, item.rotation.y, item.rotation.z],
state: "idle",
type: "crane",
- subType: item.eventData.subType as CraneEventSchema['subType'] || 'pillarJib',
+ subType: (item.eventData.subType as CraneEventSchema["subType"]) || "pillarJib",
point: {
uuid: item.eventData.point?.uuid || THREE.MathUtils.generateUUID(),
position: [item.eventData.point?.position[0] || 0, item.eventData.point?.position[1] || 0, item.eventData.point?.position[2] || 0],
@@ -305,11 +306,11 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
actionName: "Action 1",
actionType: "pickAndDrop",
maxPickUpCount: 1,
- triggers: []
- }
- ]
- }
- }
+ triggers: [],
+ },
+ ],
+ },
+ };
addEvent(craneEvent);
}
} else {
@@ -323,11 +324,11 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
isCollidable: false,
isVisible: item.isVisible,
opacity: 1,
- })
+ });
}
- })
+ });
setAssets(assets);
- })
+ });
updateLoadingProgress(100);
}
});
@@ -341,8 +342,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
const onDrop = (event: DragEvent) => {
if (!event.dataTransfer?.files[0]) return;
- if (selectedItem.id !== "" && event.dataTransfer?.files[0] && selectedItem.category !== 'Fenestration') {
-
+ if (selectedItem.id !== "" && event.dataTransfer?.files[0] && selectedItem.category !== "Fenestration") {
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
@@ -367,14 +367,14 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
const onMouseUp = (evt: any) => {
setIsRenameMode(false);
- }
+ };
if (activeModule === "builder") {
canvasElement.addEventListener("drop", onDrop);
canvasElement.addEventListener("dragover", onDragOver);
canvasElement.addEventListener("mousemove", onMouseMove);
canvasElement.addEventListener("mouseup", onMouseUp);
- } else if ((controls as CameraControls)) {
+ } else if (controls as CameraControls) {
const target = (controls as CameraControls).getTarget(new THREE.Vector3());
(controls as CameraControls).setTarget(target.x, 0, target.z, true);
setSelectedFloorAsset(null);
@@ -388,9 +388,7 @@ function AssetsGroup({ plane }: { readonly plane: RefMesh }) {
};
}, [selectedItem, camera, activeModule, controls, isRenameMode]);
- return (
-
- )
+ return ;
}
-export default AssetsGroup;
\ No newline at end of file
+export default AssetsGroup;
diff --git a/app/src/modules/builder/asset/models/model/animator/modelAnimator.tsx b/app/src/modules/builder/asset/models/model/animator/modelAnimator.tsx
index d79df60..88947a3 100644
--- a/app/src/modules/builder/asset/models/model/animator/modelAnimator.tsx
+++ b/app/src/modules/builder/asset/models/model/animator/modelAnimator.tsx
@@ -2,8 +2,8 @@ import { useEffect, useRef, useCallback, useState } from 'react';
import * as THREE from 'three';
import { useFrame } from '@react-three/fiber';
import { useSceneContext } from '../../../../../scene/sceneContext';
-import useModuleStore from '../../../../../../store/useModuleStore';
-import { usePauseButtonStore, useAnimationPlaySpeed } from '../../../../../../store/usePlayButtonStore';
+import useModuleStore from '../../../../../../store/ui/useModuleStore';
+import { usePauseButtonStore, useAnimationPlaySpeed } from '../../../../../../store/ui/usePlayButtonStore';
interface ModelAnimatorProps {
asset: Asset;
diff --git a/app/src/modules/builder/asset/models/model/eventHandlers/useEventHandlers.ts b/app/src/modules/builder/asset/models/model/eventHandlers/useModelEventHandlers.ts
similarity index 61%
rename from app/src/modules/builder/asset/models/model/eventHandlers/useEventHandlers.ts
rename to app/src/modules/builder/asset/models/model/eventHandlers/useModelEventHandlers.ts
index 4b97ddb..c3ca6f5 100644
--- a/app/src/modules/builder/asset/models/model/eventHandlers/useEventHandlers.ts
+++ b/app/src/modules/builder/asset/models/model/eventHandlers/useModelEventHandlers.ts
@@ -1,50 +1,37 @@
-import * as THREE from 'three';
-import { CameraControls } from '@react-three/drei';
-import { ThreeEvent, useThree } from '@react-three/fiber';
-import { useCallback, useEffect, useRef } from 'react';
+import * as THREE from "three";
+import { CameraControls } from "@react-three/drei";
+import { ThreeEvent, useThree } from "@react-three/fiber";
+import { useCallback, useEffect, useRef } from "react";
-import { useActiveTool, useResourceManagementId, useToggleView, useZoneAssetId, useSocketStore } from '../../../../../../store/builder/store';
-import useModuleStore, { useSubModuleStore } from '../../../../../../store/useModuleStore';
-import { useSceneContext } from '../../../../../scene/sceneContext';
-import { useProductContext } from '../../../../../simulation/products/productContext';
-import { useVersionContext } from '../../../../version/versionContext';
-import { useParams } from 'react-router-dom';
-import { getUserData } from '../../../../../../functions/getUserData';
-import { useLeftData, useTopData } from '../../../../../../store/visualization/useZone3DWidgetStore';
-import { useSelectedAsset } from '../../../../../../store/simulation/useSimulationStore';
-import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore';
+import { useActiveTool, useResourceManagementId, useToggleView, useZoneAssetId, useSocketStore } from "../../../../../../store/builder/store";
+import useModuleStore, { useSubModuleStore } from "../../../../../../store/ui/useModuleStore";
+import { useSceneContext } from "../../../../../scene/sceneContext";
+import { useParams } from "react-router-dom";
+import { getUserData } from "../../../../../../functions/getUserData";
+import { useLeftData, useTopData } from "../../../../../../store/visualization/useZone3DWidgetStore";
+import { useSelectedAsset } from "../../../../../../store/simulation/useSimulationStore";
+import { useBuilderStore } from "../../../../../../store/builder/useBuilderStore";
-import { upsertProductOrEventApi } from '../../../../../../services/simulation/products/UpsertProductOrEventApi';
-import { deleteFloorAssetApi } from '../../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorAssetApi';
+import { upsertProductOrEventApi } from "../../../../../../services/simulation/products/UpsertProductOrEventApi";
+import { deleteFloorAssetApi } from "../../../../../../services/factoryBuilder/asset/floorAsset/deleteFloorAssetApi";
-export function useModelEventHandlers({
- boundingBox,
- groupRef,
- asset
-}: {
- boundingBox: THREE.Box3 | null,
- groupRef: React.RefObject,
- asset: Asset
-}) {
+export function useModelEventHandlers({ boundingBox, groupRef, asset }: { boundingBox: THREE.Box3 | null; groupRef: React.RefObject; asset: Asset }) {
const { controls, gl, camera } = useThree();
const { activeTool } = useActiveTool();
const { activeModule } = useModuleStore();
const { toggleView } = useToggleView();
const { subModule } = useSubModuleStore();
const { socket } = useSocketStore();
- const { eventStore, productStore, assetStore, undoRedo3DStore } = useSceneContext();
+ const { eventStore, productStore, assetStore, undoRedo3DStore, versionStore } = useSceneContext();
const { push3D } = undoRedo3DStore();
const { removeAsset } = assetStore();
const { zoneAssetId, setZoneAssetId } = useZoneAssetId();
const { resourceManagementId, setResourceManagementId } = useResourceManagementId();
const { removeEvent, getEventByModelUuid } = eventStore();
- const { getIsEventInProduct, addPoint, deleteEvent } = productStore();
+ const { getIsEventInProduct, addPoint, deleteEvent, selectedProduct } = productStore();
const { setSelectedAsset, clearSelectedAsset } = useSelectedAsset();
const { deletableFloorAsset, setDeletableFloorAsset, selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
- const { selectedProductStore } = useProductContext();
- const { selectedProduct } = selectedProductStore();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { selectedVersion } = versionStore();
const { projectId } = useParams();
const { userId, organization } = getUserData();
const leftDrag = useRef(false);
@@ -54,47 +41,38 @@ export function useModelEventHandlers({
const { setTop } = useTopData();
const { setLeft } = useLeftData();
- const updateBackend = (
- productName: string,
- productUuid: string,
- projectId: string,
- eventData: EventsSchema
- ) => {
+ const updateBackend = (productName: string, productUuid: string, projectId: string, eventData: EventsSchema) => {
upsertProductOrEventApi({
productName: productName,
productUuid: productUuid,
projectId: projectId,
eventDatas: eventData,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
});
};
useEffect(() => {
- if (!zoneAssetId) return
+ if (!zoneAssetId) return;
if (zoneAssetId.id === asset.modelUuid) {
handleDblClick(asset);
}
-
- }, [zoneAssetId])
+ }, [zoneAssetId]);
useEffect(() => {
- if (!resourceManagementId) return
+ if (!resourceManagementId) return;
if (resourceManagementId === asset.modelUuid) {
-
-
handleDblClick(asset);
}
-
- }, [resourceManagementId])
+ }, [resourceManagementId]);
useEffect(() => {
if (!selectedFloorAsset) {
setZoneAssetId(null);
}
- }, [selectedFloorAsset])
+ }, [selectedFloorAsset]);
const handleDblClick = (asset: Asset) => {
- if (asset && activeTool === "cursor" && boundingBox && groupRef.current && (activeModule === 'builder' || (activeModule === 'simulation' && resourceManagementId))) {
+ if (asset && activeTool === "cursor" && boundingBox && groupRef.current && (activeModule === "builder" || (activeModule === "simulation" && resourceManagementId))) {
const frontView = false;
if (frontView) {
const size = boundingBox.getSize(new THREE.Vector3());
@@ -116,11 +94,10 @@ export function useModelEventHandlers({
paddingBottom: 5,
paddingRight: 5,
});
-
} else {
-
const collisionPos = new THREE.Vector3();
groupRef.current.getWorldPosition(collisionPos);
+ const size = boundingBox.getSize(new THREE.Vector3());
const currentPos = new THREE.Vector3().copy(camera.position);
@@ -133,7 +110,7 @@ export function useModelEventHandlers({
const newCameraPos = new THREE.Vector3().copy(collisionPos).sub(direction.multiplyScalar(offsetDistance));
camera.position.copy(newCameraPos);
- (controls as CameraControls).setLookAt(newCameraPos.x, newCameraPos.y, newCameraPos.z, collisionPos.x, 0, collisionPos.z, true);
+ (controls as CameraControls).setLookAt(newCameraPos.x, size.y > newCameraPos.y ? size.y : newCameraPos.y, newCameraPos.z, collisionPos.x, 0, collisionPos.z, true);
}
setSelectedFloorAsset(groupRef.current);
@@ -143,20 +120,18 @@ export function useModelEventHandlers({
const handleClick = async (evt: ThreeEvent, asset: Asset) => {
if (leftDrag.current || toggleView) return;
- if (activeTool === 'delete' && deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
-
+ if (activeTool === "delete" && deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
if (!socket?.connected) {
// REST
deleteFloorAssetApi({
modelUuid: asset.modelUuid,
modelName: asset.modelName,
- versionId: selectedVersion?.versionId || '',
- projectId: projectId || ''
+ versionId: selectedVersion?.versionId || "",
+ projectId: projectId || "",
});
-
} else {
- // SOCKET
+ // SOCKET
const data = {
organization,
@@ -164,29 +139,24 @@ export function useModelEventHandlers({
modelName: asset.modelName,
socketId: socket.id,
userId,
- versionId: selectedVersion?.versionId || '',
- projectId
- }
+ versionId: selectedVersion?.versionId || "",
+ projectId,
+ };
- socket.emit('v1:model-asset:delete', data)
+ socket.emit("v1:model-asset:delete", data);
}
removeEvent(asset.modelUuid);
const updatedEvents = deleteEvent(asset.modelUuid);
updatedEvents.forEach((event) => {
- updateBackend(
- selectedProduct.productName,
- selectedProduct.productUuid,
- projectId || '',
- event
- );
- })
+ updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
+ });
removeAsset(asset.modelUuid);
push3D({
- type: 'Scene',
+ type: "Scene",
actions: [
{
module: "builder",
@@ -194,16 +164,15 @@ export function useModelEventHandlers({
asset: {
type: "Asset",
assetData: asset,
- timeStap: new Date().toISOString()
- }
- }
- ]
+ timeStap: new Date().toISOString(),
+ },
+ },
+ ],
});
echo.success("Model Removed!");
-
- } else if (activeModule === 'simulation' && subModule === "simulations" && activeTool === 'pen') {
- if (asset.eventData && asset.eventData.type === 'Conveyor') {
+ } else if (activeModule === "simulation" && subModule === "simulations" && activeTool === "pen") {
+ if (asset.eventData && asset.eventData.type === "Conveyor") {
const intersectedPoint = evt.point;
const localPosition = groupRef.current?.worldToLocal(intersectedPoint.clone());
if (localPosition) {
@@ -214,49 +183,50 @@ export function useModelEventHandlers({
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: `Action 1`,
- actionType: 'default',
- material: 'Default Material',
+ actionType: "default",
+ material: "Default Material",
delay: 0,
spawnInterval: 5,
spawnCount: 1,
- triggers: []
- }
- }
+ triggers: [],
+ },
+ };
const event = addPoint(selectedProduct.productUuid, asset.modelUuid, conveyorPoint);
if (event) {
- updateBackend(
- selectedProduct.productName,
- selectedProduct.productUuid,
- projectId || '',
- event
- );
+ updateBackend(selectedProduct.productName, selectedProduct.productUuid, projectId || "", event);
}
}
}
}
};
- const handlePointerOver = useCallback((asset: Asset) => {
- if (activeTool === "delete" && activeModule === 'builder') {
- if (deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
- return;
- } else {
- setDeletableFloorAsset(groupRef.current);
+ const handlePointerOver = useCallback(
+ (asset: Asset) => {
+ if (activeTool === "delete" && activeModule === "builder") {
+ if (deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
+ return;
+ } else {
+ setDeletableFloorAsset(groupRef.current);
+ }
}
- }
- }, [activeTool, activeModule, deletableFloorAsset]);
+ },
+ [activeTool, activeModule, deletableFloorAsset]
+ );
- const handlePointerOut = useCallback((evt: ThreeEvent, asset: Asset) => {
- if (evt.intersections.length === 0 && activeTool === "delete" && deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
- setDeletableFloorAsset(null);
- }
- }, [activeTool, deletableFloorAsset]);
+ const handlePointerOut = useCallback(
+ (evt: ThreeEvent, asset: Asset) => {
+ if (evt.intersections.length === 0 && activeTool === "delete" && deletableFloorAsset && deletableFloorAsset.uuid === asset.modelUuid) {
+ setDeletableFloorAsset(null);
+ }
+ },
+ [activeTool, deletableFloorAsset]
+ );
const handleContextMenu = (asset: Asset, evt: ThreeEvent) => {
if (rightDrag.current || toggleView) return;
- if (activeTool === "cursor" && subModule === 'simulations') {
+ if (activeTool === "cursor" && subModule === "simulations") {
if (asset.modelUuid) {
const canvasElement = gl.domElement;
const isInProduct = getIsEventInProduct(selectedProduct.productUuid, asset.modelUuid);
@@ -272,12 +242,12 @@ export function useModelEventHandlers({
clearSelectedAsset();
}
} else {
- clearSelectedAsset()
+ clearSelectedAsset();
}
} else {
- clearSelectedAsset()
+ clearSelectedAsset();
}
- }
+ };
useEffect(() => {
const canvasElement = gl.domElement;
@@ -311,23 +281,22 @@ export function useModelEventHandlers({
}
};
- canvasElement.addEventListener('pointerdown', onPointerDown);
- canvasElement.addEventListener('pointermove', onPointerMove);
- canvasElement.addEventListener('pointerup', onPointerUp);
+ canvasElement.addEventListener("pointerdown", onPointerDown);
+ canvasElement.addEventListener("pointermove", onPointerMove);
+ canvasElement.addEventListener("pointerup", onPointerUp);
return () => {
- canvasElement.removeEventListener('pointerdown', onPointerDown);
- canvasElement.removeEventListener('pointermove', onPointerMove);
- canvasElement.removeEventListener('pointerup', onPointerUp);
- }
-
- }, [gl])
+ canvasElement.removeEventListener("pointerdown", onPointerDown);
+ canvasElement.removeEventListener("pointermove", onPointerMove);
+ canvasElement.removeEventListener("pointerup", onPointerUp);
+ };
+ }, [gl]);
return {
handleDblClick,
handleClick,
handlePointerOver,
handlePointerOut,
- handleContextMenu
+ handleContextMenu,
};
}
diff --git a/app/src/modules/builder/asset/models/model/model.tsx b/app/src/modules/builder/asset/models/model/model.tsx
index cc49d5a..666595d 100644
--- a/app/src/modules/builder/asset/models/model/model.tsx
+++ b/app/src/modules/builder/asset/models/model/model.tsx
@@ -1,17 +1,17 @@
-import * as THREE from 'three';
-import { useEffect, useRef, useState } from 'react';
-import { retrieveGLTF, storeGLTF } from '../../../../../utils/indexDB/idbUtils';
-import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
-import { useToggleView, useToolMode } from '../../../../../store/builder/store';
-import { AssetBoundingBox } from '../../functions/assetBoundingBox';
-import { useBuilderStore } from '../../../../../store/builder/useBuilderStore';
-import useModuleStore from '../../../../../store/useModuleStore';
-import { useSceneContext } from '../../../../scene/sceneContext';
-import { SkeletonUtils } from 'three-stdlib';
+import * as THREE from "three";
+import { useEffect, useRef, useState } from "react";
+import { retrieveGLTF, storeGLTF } from "../../../../../utils/indexDB/idbUtils";
+import { GLTF, GLTFLoader } from "three/examples/jsm/loaders/GLTFLoader";
+import { useToggleView, useToolMode } from "../../../../../store/builder/store";
+import { AssetBoundingBox } from "../../functions/assetBoundingBox";
+import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
+import useModuleStore from "../../../../../store/ui/useModuleStore";
+import { useSceneContext } from "../../../../scene/sceneContext";
+import { SkeletonUtils } from "three-stdlib";
-import { getAssetFieldApi } from '../../../../../services/factoryBuilder/asset/floorAsset/getAssetField';
-import { ModelAnimator } from './animator/modelAnimator';
-import { useModelEventHandlers } from './eventHandlers/useEventHandlers';
+import { getAssetFieldApi } from "../../../../../services/factoryBuilder/asset/floorAsset/getAssetField";
+import { ModelAnimator } from "./animator/modelAnimator";
+import { useModelEventHandlers } from "./eventHandlers/useModelEventHandlers";
function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendered: boolean; loader: GLTFLoader }>) {
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
@@ -31,33 +31,33 @@ function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendere
useEffect(() => {
if (!fieldData && asset.eventData) {
getAssetFieldApi(asset.assetId).then((data) => {
- if (data.type === 'ArmBot') {
+ if (data.type === "ArmBot") {
if (data.data) {
const fieldData: IK[] = data.data;
setFieldData(fieldData);
}
- } else if (data.type === 'Conveyor' || data.type === 'Crane') {
+ } else if (data.type === "Conveyor" || data.type === "Crane") {
if (data.data) {
const fieldData = data.data;
setFieldData(fieldData);
}
}
- })
+ });
}
- }, [asset.modelUuid, fieldData])
+ }, [asset.modelUuid, fieldData]);
useEffect(() => {
setDeletableFloorAsset(null);
if (selectedFloorAsset === null || selectedFloorAsset.userData.modelUuid !== asset.modelUuid) {
resetAnimation(asset.modelUuid);
}
- }, [activeModule, toolMode, selectedFloorAsset])
+ }, [activeModule, toolMode, selectedFloorAsset]);
useEffect(() => {
if (selectedFloorAsset && selectedFloorAsset.userData.modelUuid === asset.modelUuid) {
setSelectedFloorAsset(groupRef.current);
}
- }, [isRendered, selectedFloorAsset])
+ }, [isRendered, selectedFloorAsset]);
useEffect(() => {
if (selectedAssets.length > 0) {
@@ -69,7 +69,7 @@ function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendere
} else {
setIsSelected(false);
}
- }, [selectedAssets])
+ }, [selectedAssets]);
useEffect(() => {
if (gltfScene) {
@@ -78,13 +78,13 @@ function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendere
child.castShadow = true;
child.receiveShadow = true;
}
- })
+ });
}
}, [gltfScene]);
const logModelStatus = (modelId: string, status: string) => {
// console.log(modelId, status);
- }
+ };
useEffect(() => {
// Calculate Bounding Box
@@ -101,62 +101,61 @@ function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendere
clone.animations = cachedModel.animations || [];
setGltfScene(clone);
calculateBoundingBox(clone);
- logModelStatus(assetId, 'cache-loaded');
+ logModelStatus(assetId, "cache-loaded");
return;
}
// Check IndexedDB
- retrieveGLTF(assetId).then((indexedDBModel) => {
- if (indexedDBModel) {
- const blobUrl = URL.createObjectURL(indexedDBModel);
- loader.load(
- blobUrl,
- (gltf) => {
- URL.revokeObjectURL(blobUrl);
- THREE.Cache.remove(blobUrl);
- THREE.Cache.add(assetId, gltf);
- setGltfScene(gltf.scene.clone());
- calculateBoundingBox(gltf.scene);
- logModelStatus(assetId, 'indexedDB-loaded');
- },
- undefined,
- (error) => {
- echo.error(`[IndexedDB] Error loading ${asset.modelName}:`);
- URL.revokeObjectURL(blobUrl);
- }
- );
- return;
- }
-
- // Fetch from Backend
- const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${assetId}`;
- loader.load(
- modelUrl,
- (gltf: GLTF) => {
- fetch(modelUrl)
- .then((response) => response.blob())
- .then((modelBlob) => storeGLTF(assetId, modelBlob))
- .then(() => {
+ retrieveGLTF(assetId)
+ .then((indexedDBModel) => {
+ if (indexedDBModel) {
+ const blobUrl = URL.createObjectURL(indexedDBModel);
+ loader.load(
+ blobUrl,
+ (gltf) => {
+ URL.revokeObjectURL(blobUrl);
+ THREE.Cache.remove(blobUrl);
THREE.Cache.add(assetId, gltf);
setGltfScene(gltf.scene.clone());
calculateBoundingBox(gltf.scene);
- logModelStatus(assetId, 'backend-loaded');
- })
- .catch((error) => {
- console.error(
- `[Backend] Error storing/loading ${asset.modelName}:`,
- error
- );
- });
- },
- undefined,
- (error) => {
- echo.error(`[Backend] Error loading ${asset.modelName}:`);
+ logModelStatus(assetId, "indexedDB-loaded");
+ },
+ undefined,
+ () => {
+ echo.error(`[IndexedDB] Error loading ${asset.modelName}:`);
+ URL.revokeObjectURL(blobUrl);
+ }
+ );
+ return;
}
- );
- }).catch((err) => {
- console.error("Failed to load model:", asset.assetId, err);
- });
+
+ // Fetch from Backend
+ const modelUrl = `${url_Backend_dwinzo}/api/v2/AssetFile/${assetId}`;
+ loader.load(
+ modelUrl,
+ (gltf: GLTF) => {
+ fetch(modelUrl)
+ .then((response) => response.blob())
+ .then((modelBlob) => storeGLTF(assetId, modelBlob))
+ .then(() => {
+ THREE.Cache.add(assetId, gltf);
+ setGltfScene(gltf.scene.clone());
+ calculateBoundingBox(gltf.scene);
+ logModelStatus(assetId, "backend-loaded");
+ })
+ .catch((error) => {
+ console.error(`[Backend] Error storing/loading ${asset.modelName}:`, error);
+ });
+ },
+ undefined,
+ () => {
+ echo.error(`[Backend] Error loading ${asset.modelName}:`);
+ }
+ );
+ })
+ .catch((err) => {
+ console.error("Failed to load model:", asset.assetId, err);
+ });
}, []);
const { handleDblClick, handleClick, handlePointerOver, handlePointerOut, handleContextMenu } = useModelEventHandlers({ boundingBox, groupRef, asset });
@@ -164,7 +163,7 @@ function Model({ asset, isRendered, loader }: Readonly<{ asset: Asset; isRendere
return (
{isRendered ? (
<>
-
-
>
) : (
- <>
- {!isSelected &&
-
- }
- >
+ <>{!isSelected && }>
)}
- {isSelected &&
-
- }
+ {isSelected && }
>
)}
);
}
-export default Model;
\ No newline at end of file
+export default Model;
diff --git a/app/src/modules/builder/asset/models/models.tsx b/app/src/modules/builder/asset/models/models.tsx
index 78eacab..61be1b2 100644
--- a/app/src/modules/builder/asset/models/models.tsx
+++ b/app/src/modules/builder/asset/models/models.tsx
@@ -1,13 +1,13 @@
import { useEffect, useRef, useState } from "react";
import { useThree, useFrame } from "@react-three/fiber";
import { Group, Vector3 } from "three";
-import { CameraControls } from '@react-three/drei';
-import { useLimitDistance, useRenderDistance } from '../../../../store/builder/store';
-import { useSelectedAsset } from '../../../../store/simulation/useSimulationStore';
-import { useSceneContext } from '../../../scene/sceneContext';
+import { CameraControls } from "@react-three/drei";
+import { useLimitDistance, useRenderDistance } from "../../../../store/builder/store";
+import { useSelectedAsset } from "../../../../store/simulation/useSimulationStore";
+import { useSceneContext } from "../../../scene/sceneContext";
import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
-import Model from './model/model';
+import Model from "./model/model";
import { GLTFLoader } from "three/examples/jsm/Addons";
const distanceWorker = new Worker(new URL("../../../../services/factoryBuilder/webWorkers/distanceWorker.js", import.meta.url));
@@ -15,7 +15,7 @@ const distanceWorker = new Worker(new URL("../../../../services/factoryBuilder/w
function Models({ loader }: { readonly loader: GLTFLoader }) {
const { controls, camera } = useThree();
const assetGroupRef = useRef(null);
- const { assetStore } = useSceneContext();
+ const { assetStore, layout } = useSceneContext();
const { assets } = assetStore();
const { selectedFloorAsset, setSelectedFloorAsset } = useBuilderStore();
const { selectedAsset, clearSelectedAsset } = useSelectedAsset();
@@ -40,13 +40,13 @@ function Models({ loader }: { readonly loader: GLTFLoader }) {
camera.getWorldPosition(cameraPos.current);
for (const asset of assets) {
const isRendered = renderMap[asset.modelUuid] ?? false;
- distanceWorker.postMessage({ modelUuid: asset.modelUuid, assetPosition: { x: asset.position[0], y: asset.position[1], z: asset.position[2], }, cameraPosition: cameraPos.current, limitDistance, renderDistance, isRendered, });
+ distanceWorker.postMessage({ modelUuid: asset.modelUuid, assetPosition: { x: asset.position[0], y: asset.position[1], z: asset.position[2] }, cameraPosition: cameraPos.current, limitDistance, renderDistance, isRendered });
}
});
return (
{
e.stopPropagation();
@@ -67,4 +67,4 @@ function Models({ loader }: { readonly loader: GLTFLoader }) {
);
}
-export default Models;
\ No newline at end of file
+export default Models;
diff --git a/app/src/modules/builder/dfx/LoadBlueprint.tsx b/app/src/modules/builder/dfx/LoadBlueprint.tsx
index f960388..f99b2d3 100644
--- a/app/src/modules/builder/dfx/LoadBlueprint.tsx
+++ b/app/src/modules/builder/dfx/LoadBlueprint.tsx
@@ -1,15 +1,14 @@
-import { useEffect, useRef } from 'react';
-import { useActiveLayer, useDfxUpload, useSocketStore, useToggleView } from '../../../store/builder/store';
-import { LineBasicMaterial, Line } from 'three';
-import { TransformControls } from '@react-three/drei';
-import { getWallPointsFromBlueprint } from './functions/getWallPointsFromBlueprint';
-import { useParams } from 'react-router-dom';
-import { getUserData } from '../../../functions/getUserData';
-import { useVersionContext } from '../version/versionContext';
-import { useBuilderStore } from '../../../store/builder/useBuilderStore';
-import { useSceneContext } from '../../scene/sceneContext';
+import { useEffect, useRef } from "react";
+import { useActiveLayer, useDfxUpload, useSocketStore, useToggleView } from "../../../store/builder/store";
+import { LineBasicMaterial, Line } from "three";
+import { TransformControls } from "@react-three/drei";
+import { getWallPointsFromBlueprint } from "./functions/getWallPointsFromBlueprint";
+import { useParams } from "react-router-dom";
+import { getUserData } from "../../../functions/getUserData";
+import { useBuilderStore } from "../../../store/builder/useBuilderStore";
+import { useSceneContext } from "../../scene/sceneContext";
-import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
+import { upsertWallApi } from "../../../services/factoryBuilder/wall/upsertWallApi";
/**
* DxfFile component handles the rendering and manipulation of DXf file data in a 3D scene.
@@ -21,46 +20,43 @@ const DxfFile = () => {
const { dfxuploaded, dfxWallGenerate, setObjValue, objValue, setDfxUploaded } = useDfxUpload();
const { toggleView } = useToggleView();
const { socket } = useSocketStore();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { versionStore, wallStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
+ const { addWall } = wallStore();
+ const { walls } = wallStore();
const { projectId } = useParams();
const { userId, organization } = getUserData();
const { activeLayer } = useActiveLayer();
- const { wallThickness, wallHeight, insideMaterial, outsideMaterial, } = useBuilderStore();
- // Refs for storing line objects
+ const { wallThickness, wallHeight, insideMaterial, outsideMaterial } = useBuilderStore();
const lineRefs = useRef([]);
- const { wallStore } = useSceneContext();
- const { addWall, } = wallStore();
- const { walls } = wallStore();
/**
* Effect hook that runs when DXF wall generation is triggered.
* Loads initial points and lines from the DXF data and updates the scene.
*/
useEffect(() => {
-
if (dfxWallGenerate) {
dfxWallGenerate.map((wall: Wall) => {
if (projectId) {
if (!socket?.connected) {
// API
- upsertWallApi(projectId, selectedVersion?.versionId || '', wall);
+ upsertWallApi(projectId, selectedVersion?.versionId || "", wall);
} else {
// SOCKET
const data = {
wallData: wall,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
addWall(wall);
- socket.emit('v1:model-Wall:add', data);
+ socket.emit("v1:model-Wall:add", data);
}
}
- })
+ });
}
}, [dfxWallGenerate]);
@@ -80,17 +76,13 @@ const DxfFile = () => {
setObjValue({ x: position.x, y: position.y, z: position.z });
// Recalculate wall points based on new position
- getWallPointsFromBlueprint({
- objValue: { x: position.x, y: position.y, z: position.z },
- setDxfWallGenerate: () => { },
- wallThickness, wallHeight, outsideMaterial, insideMaterial, activeLayer, addWall, walls
- });
+ getWallPointsFromBlueprint({ objValue: { x: position.x, y: position.y, z: position.z }, setDxfWallGenerate: () => {}, wallThickness, wallHeight, outsideMaterial, insideMaterial, activeLayer, addWall, walls });
};
useEffect(() => {
if (!toggleView) {
- setDfxUploaded([])
+ setDfxUploaded([]);
}
- }, [toggleView])
+ }, [toggleView]);
return (
<>
{/* Render DXF lines with transform controls when DXF data is available and view is toggled */}
@@ -99,19 +91,14 @@ const DxfFile = () => {
toggleView &&
dfxuploaded?.map((geometry: any, index: number) => {
// Create a new line object for each geometry in the DXF data
- const line = new Line(geometry, new LineBasicMaterial({ color: 'red' }));
+ const line = new Line(geometry, new LineBasicMaterial({ color: "red" }));
line.rotation.set(-Math.PI / 2, 0, 0);
// Store line reference
lineRefs.current[index] = line;
return (
- handleTransformChange(index)}
- >
+ handleTransformChange(index)}>
{/* Render the line with current position from state */}
@@ -121,4 +108,4 @@ const DxfFile = () => {
);
};
-export default DxfFile;
\ No newline at end of file
+export default DxfFile;
diff --git a/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx
index 3559128..924dcba 100644
--- a/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx
+++ b/app/src/modules/builder/floor/Instances/Instance/floorInstance.tsx
@@ -1,7 +1,7 @@
import { useMemo } from "react";
import { Shape, Vector2, DoubleSide, TextureLoader, RepeatWrapping, SRGBColorSpace, NoColorSpace, ExtrudeGeometry } from "three";
import { useLoader } from "@react-three/fiber";
-import useModuleStore from "../../../../../store/useModuleStore";
+import useModuleStore from "../../../../../store/ui/useModuleStore";
import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
import { useToggleView } from "../../../../../store/builder/store";
import * as Constants from "../../../../../types/world/worldConstants";
diff --git a/app/src/modules/builder/floor/Instances/floorInstances.tsx b/app/src/modules/builder/floor/Instances/floorInstances.tsx
index 9ad65db..b19a10d 100644
--- a/app/src/modules/builder/floor/Instances/floorInstances.tsx
+++ b/app/src/modules/builder/floor/Instances/floorInstances.tsx
@@ -7,7 +7,7 @@ import Line from '../../line/line';
import Point from '../../point/point';
import FloorInstance from './Instance/floorInstance';
import Floor2DInstance from './Instance/floor2DInstance';
-import useModuleStore from '../../../../store/useModuleStore';
+import useModuleStore from '../../../../store/ui/useModuleStore';
import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
function FloorInstances() {
diff --git a/app/src/modules/builder/floor/floorCreator/floorCreator.tsx b/app/src/modules/builder/floor/floorCreator/floorCreator.tsx
index d63bd38..ee899bc 100644
--- a/app/src/modules/builder/floor/floorCreator/floorCreator.tsx
+++ b/app/src/modules/builder/floor/floorCreator/floorCreator.tsx
@@ -1,16 +1,15 @@
-import * as THREE from 'three'
-import { useEffect, useMemo, useRef, useState } from 'react'
-import { useThree } from '@react-three/fiber';
-import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
-import { useSceneContext } from '../../../scene/sceneContext';
-import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
-import { useParams } from 'react-router-dom';
-import { useVersionContext } from '../../version/versionContext';
-import { getUserData } from '../../../../functions/getUserData';
-import ReferencePoint from '../../point/reference/referencePoint';
-import ReferenceFloor from './referenceFloor';
+import * as THREE from "three";
+import { useEffect, useMemo, useRef, useState } from "react";
+import { useThree } from "@react-three/fiber";
+import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from "../../../../store/builder/store";
+import { useSceneContext } from "../../../scene/sceneContext";
+import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
+import { useParams } from "react-router-dom";
+import { getUserData } from "../../../../functions/getUserData";
+import ReferencePoint from "../../point/reference/referencePoint";
+import ReferenceFloor from "./referenceFloor";
-import { upsertFloorApi } from '../../../../services/factoryBuilder/floor/upsertFloorApi';
+import { upsertFloorApi } from "../../../../services/factoryBuilder/floor/upsertFloorApi";
function FloorCreator() {
const { scene, camera, raycaster, gl, pointer } = useThree();
@@ -19,13 +18,12 @@ function FloorCreator() {
const { toolMode } = useToolMode();
const { activeLayer } = useActiveLayer();
const { socket } = useSocketStore();
- const { floorStore, undoRedo2DStore } = useSceneContext();
+ const { floorStore, undoRedo2DStore, versionStore } = useSceneContext();
const { addFloor, getFloorPointById } = floorStore();
const { push2D } = undoRedo2DStore();
const drag = useRef(false);
const isLeftMouseDown = useRef(false);
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { selectedVersion } = versionStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
@@ -63,7 +61,7 @@ function FloorCreator() {
let position = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (!position) return;
- const pointIntersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Floor-Point');
+ const pointIntersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === "Floor-Point");
// const floorIntersect = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Floor-Line');
@@ -73,9 +71,9 @@ function FloorCreator() {
const newPoint: Point = {
pointUuid: THREE.MathUtils.generateUUID(),
- pointType: 'Floor',
+ pointType: "Floor",
position: [position.x, position.y, position.z],
- layer: activeLayer
+ layer: activeLayer,
};
if (snappedPosition && snappedPoint) {
@@ -84,7 +82,9 @@ function FloorCreator() {
newPoint.layer = snappedPoint.layer;
}
- if (snappedPoint && snappedPoint.pointUuid === tempPoints[tempPoints.length - 1]?.pointUuid) { return }
+ if (snappedPoint && snappedPoint.pointUuid === tempPoints[tempPoints.length - 1]?.pointUuid) {
+ return;
+ }
if (snappedPosition && !snappedPoint) {
newPoint.position = snappedPosition;
@@ -106,44 +106,42 @@ function FloorCreator() {
addFloor(floor);
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Line-Create',
+ actionType: "Line-Create",
point: {
- type: 'Floor',
+ type: "Floor",
lineData: floor,
timeStamp: new Date().toISOString(),
- }
- }
+ },
+ },
],
- })
+ });
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
+ upsertFloorApi(projectId, selectedVersion?.versionId || "", floor);
} else {
-
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:add', data);
+ socket.emit("v1:model-Floor:add", data);
}
}
setTempPoints([]);
setIsCreating(false);
- } else if (isCreating && snappedPoint && !tempPoints.some(p => p.pointUuid === snappedPoint.pointUuid)) {
- setTempPoints(prev => [...prev, newPoint]);
+ } else if (isCreating && snappedPoint && !tempPoints.some((p) => p.pointUuid === snappedPoint.pointUuid)) {
+ setTempPoints((prev) => [...prev, newPoint]);
setIsCreating(true);
} else if (pointIntersects) {
if (tempPoints.length > 2 && isCreating && pointIntersects.object.uuid === tempPoints[0].pointUuid) {
@@ -162,48 +160,46 @@ function FloorCreator() {
addFloor(floor);
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Line-Create',
+ actionType: "Line-Create",
point: {
- type: 'Floor',
+ type: "Floor",
lineData: floor,
timeStamp: new Date().toISOString(),
- }
- }
+ },
+ },
],
- })
+ });
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
+ upsertFloorApi(projectId, selectedVersion?.versionId || "", floor);
} else {
-
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:add', data);
+ socket.emit("v1:model-Floor:add", data);
}
}
setTempPoints([]);
setIsCreating(false);
- } else if (tempPoints.length === 0 || (tempPoints.length > 1 && !tempPoints.slice(1).some(p => p.pointUuid === pointIntersects.object.uuid))) {
+ } else if (tempPoints.length === 0 || (tempPoints.length > 1 && !tempPoints.slice(1).some((p) => p.pointUuid === pointIntersects.object.uuid))) {
tempPoints.push(pointIntersects.object.userData as Point);
setIsCreating(true);
}
} else {
- setTempPoints(prev => [...prev, newPoint]);
+ setTempPoints((prev) => [...prev, newPoint]);
setIsCreating(true);
}
};
@@ -227,38 +223,36 @@ function FloorCreator() {
addFloor(floor);
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Line-Create',
+ actionType: "Line-Create",
point: {
- type: 'Floor',
+ type: "Floor",
lineData: floor,
timeStamp: new Date().toISOString(),
- }
- }
+ },
+ },
],
- })
+ });
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
+ upsertFloorApi(projectId, selectedVersion?.versionId || "", floor);
} else {
-
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:add', data);
+ socket.emit("v1:model-Floor:add", data);
}
}
}
@@ -298,21 +292,19 @@ function FloorCreator() {
return (
<>
- {toggleView &&
+ {toggleView && (
<>
-
+
{tempPoints.map((point) => (
))}
- {tempPoints.length > 0 &&
-
- }
+ {tempPoints.length > 0 && }
>
- }
+ )}
>
- )
+ );
}
-export default FloorCreator
\ No newline at end of file
+export default FloorCreator;
diff --git a/app/src/modules/builder/floor/floorGroup.tsx b/app/src/modules/builder/floor/floorGroup.tsx
index d782e1a..c54668e 100644
--- a/app/src/modules/builder/floor/floorGroup.tsx
+++ b/app/src/modules/builder/floor/floorGroup.tsx
@@ -1,55 +1,53 @@
-import { useEffect } from 'react';
-import { useActiveTool, useToggleView } from '../../../store/builder/store'
-import { useBuilderStore } from '../../../store/builder/useBuilderStore';
-import { useVersionContext } from '../version/versionContext';
-import { useSceneContext } from '../../scene/sceneContext';
-import { useParams } from 'react-router-dom';
-import useModuleStore from '../../../store/useModuleStore';
-import FloorCreator from './floorCreator/floorCreator';
-import FloorInstances from './Instances/floorInstances';
-import { getFloorsApi } from '../../../services/factoryBuilder/floor/getFloorsApi';
+import { useEffect } from "react";
+import { useActiveTool, useToggleView } from "../../../store/builder/store";
+import { useBuilderStore } from "../../../store/builder/useBuilderStore";
+import { useSceneContext } from "../../scene/sceneContext";
+import { useParams } from "react-router-dom";
+import useModuleStore from "../../../store/ui/useModuleStore";
+import FloorCreator from "./floorCreator/floorCreator";
+import FloorInstances from "./Instances/floorInstances";
+import { getFloorsApi } from "../../../services/factoryBuilder/floor/getFloorsApi";
function FloorGroup() {
const { toggleView } = useToggleView();
const { setSelectedFloor, setSelectedDecal } = useBuilderStore();
const { activeModule } = useModuleStore();
const { activeTool } = useActiveTool();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { floorStore } = useSceneContext();
+ const { floorStore, versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
const { setFloors } = floorStore();
const { projectId } = useParams();
useEffect(() => {
- if (toggleView || activeModule !== 'builder') {
+ if (toggleView || activeModule !== "builder") {
setSelectedFloor(null);
setSelectedDecal(null);
}
- }, [toggleView, activeModule, activeTool])
+ }, [toggleView, activeModule, activeTool]);
useEffect(() => {
if (projectId && selectedVersion) {
- getFloorsApi(projectId, selectedVersion?.versionId || '').then((floors) => {
- if (floors && floors.length > 0) {
- setFloors(floors);
- } else {
- setFloors([]);
- }
- }).catch((err) => {
- console.log(err);
- })
+ getFloorsApi(projectId, selectedVersion?.versionId || "")
+ .then((floors) => {
+ if (floors && floors.length > 0) {
+ setFloors(floors);
+ } else {
+ setFloors([]);
+ }
+ })
+ .catch((err) => {
+ console.log(err);
+ });
}
- }, [projectId, selectedVersion?.versionId])
+ }, [projectId, selectedVersion?.versionId]);
return (
<>
-
-
>
- )
+ );
}
-export default FloorGroup
\ No newline at end of file
+export default FloorGroup;
diff --git a/app/src/modules/builder/line/line.tsx b/app/src/modules/builder/line/line.tsx
index dad7728..3977f8f 100644
--- a/app/src/modules/builder/line/line.tsx
+++ b/app/src/modules/builder/line/line.tsx
@@ -1,26 +1,25 @@
-import * as THREE from 'three';
-import { useThree } from '@react-three/fiber';
+import * as THREE from "three";
+import { useThree } from "@react-three/fiber";
import { useEffect, useMemo, useState } from "react";
-import { DragControls, Tube } from '@react-three/drei';
-import { useSocketStore, useToolMode } from '../../../store/builder/store';
-import { useBuilderStore } from '../../../store/builder/useBuilderStore';
-import { useSceneContext } from '../../scene/sceneContext';
-import * as Constants from '../../../types/world/worldConstants';
-import { useVersionContext } from '../version/versionContext';
-import { useParams } from 'react-router-dom';
-import { getUserData } from '../../../functions/getUserData';
-import { handleCanvasCursors } from '../../../utils/mouseUtils/handleCanvasCursors';
-import { useSelectedPoints } from '../../../store/simulation/useSimulationStore';
-import { calculateAssetTransformationOnWall } from '../wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall';
+import { DragControls, Tube } from "@react-three/drei";
+import { useSocketStore, useToolMode } from "../../../store/builder/store";
+import { useBuilderStore } from "../../../store/builder/useBuilderStore";
+import { useSceneContext } from "../../scene/sceneContext";
+import * as Constants from "../../../types/world/worldConstants";
+import { useParams } from "react-router-dom";
+import { getUserData } from "../../../functions/getUserData";
+import { handleCanvasCursors } from "../../../utils/mouseUtils/handleCanvasCursors";
+import { useSelectedPoints } from "../../../store/simulation/useSimulationStore";
+import { calculateAssetTransformationOnWall } from "../wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall";
-import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
-import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
-import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
-import { deleteFloorApi } from '../../../services/factoryBuilder/floor/deleteFloorApi';
-import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi';
-import { upsertZoneApi } from '../../../services/factoryBuilder/zone/upsertZoneApi';
-import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
-import { deleteWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi';
+import { upsertWallApi } from "../../../services/factoryBuilder/wall/upsertWallApi";
+import { deleteWallApi } from "../../../services/factoryBuilder/wall/deleteWallApi";
+import { upsertFloorApi } from "../../../services/factoryBuilder/floor/upsertFloorApi";
+import { deleteFloorApi } from "../../../services/factoryBuilder/floor/deleteFloorApi";
+import { deleteZoneApi } from "../../../services/factoryBuilder/zone/deleteZoneApi";
+import { upsertZoneApi } from "../../../services/factoryBuilder/zone/upsertZoneApi";
+import { upsertWallAssetApi } from "../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi";
+import { deleteWallAssetApi } from "../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi";
interface LineProps {
points: [Point, Point];
@@ -33,65 +32,64 @@ function Line({ points }: Readonly) {
const [isDeletable, setIsDeletable] = useState(false);
const { socket } = useSocketStore();
const { toolMode } = useToolMode();
- const { wallStore, floorStore, zoneStore, undoRedo2DStore, wallAssetStore } = useSceneContext();
+ const { wallStore, floorStore, zoneStore, undoRedo2DStore, wallAssetStore, versionStore } = useSceneContext();
const { push2D } = undoRedo2DStore();
const { getWallAssetsByWall, updateWallAsset, removeWallAsset } = wallAssetStore();
const { removeWallByPoints, setPosition: setWallPosition, getWallByPoints, getConnectedWallsByWallId } = wallStore();
const { removeFloorByPoints, setPosition: setFloorPosition, getFloorsByPointId, getFloorsByPoints } = floorStore();
const { removeZoneByPoints, setPosition: setZonePosition, getZonesByPointId, getZonesByPoints } = zoneStore();
- const { userId, organization } = getUserData();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { projectId } = useParams();
- const [dragOffset, setDragOffset] = useState(null);
+ const { selectedVersion } = versionStore();
const { hoveredLine, setHoveredLine, hoveredPoint } = useBuilderStore();
+ const [dragOffset, setDragOffset] = useState(null);
const { selectedPoints } = useSelectedPoints();
+ const { projectId } = useParams();
+ const { userId, organization } = getUserData();
const [initialPositions, setInitialPositions] = useState<{
- aisles?: Aisle[],
- walls?: Wall[],
- floors?: Floor[],
- zones?: Zone[]
+ aisles?: Aisle[];
+ walls?: Wall[];
+ floors?: Floor[];
+ zones?: Zone[];
}>({});
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);
}, [points]);
const colors = getColor(points[0]);
function getColor(point: Point) {
- if (point.pointType === 'Aisle') {
+ if (point.pointType === "Aisle") {
return {
defaultLineColor: Constants.lineConfig.aisleColor,
defaultDeleteColor: Constants.lineConfig.deleteColor,
- }
- } else if (point.pointType === 'Floor') {
+ };
+ } else if (point.pointType === "Floor") {
return {
defaultLineColor: Constants.lineConfig.floorColor,
defaultDeleteColor: Constants.lineConfig.deleteColor,
- }
- } else if (point.pointType === 'Wall') {
+ };
+ } else if (point.pointType === "Wall") {
return {
defaultLineColor: Constants.lineConfig.wallColor,
defaultDeleteColor: Constants.lineConfig.deleteColor,
- }
- } else if (point.pointType === 'Zone') {
+ };
+ } else if (point.pointType === "Zone") {
return {
defaultLineColor: Constants.lineConfig.zoneColor,
defaultDeleteColor: Constants.lineConfig.deleteColor,
- }
+ };
} else {
return {
defaultLineColor: Constants.lineConfig.defaultColor,
defaultDeleteColor: Constants.lineConfig.deleteColor,
- }
+ };
}
}
useEffect(() => {
- if (toolMode === '2D-Delete') {
+ if (toolMode === "2D-Delete") {
if (isHovered && !hoveredPoint) {
setIsDeletable(true);
} else {
@@ -106,103 +104,95 @@ function Line({ points }: Readonly) {
if (hoveredLine && (hoveredLine[0].pointUuid !== points[0].pointUuid || hoveredLine[1].pointUuid !== points[1].pointUuid)) {
setIsHovered(false);
}
- }, [hoveredLine])
+ }, [hoveredLine]);
const handlePointClick = (points: [Point, Point]) => {
- if (toolMode === '2D-Delete') {
- if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
+ if (toolMode === "2D-Delete") {
+ if (points[0].pointType === "Wall" && points[1].pointType === "Wall") {
const removedWall = removeWallByPoints(points);
if (removedWall && projectId) {
-
const assetsOnWall = getWallAssetsByWall(removedWall.wallUuid);
assetsOnWall.forEach((asset) => {
if (projectId && asset) {
-
removeWallAsset(asset.modelUuid);
if (!socket?.connected) {
-
// API
- deleteWallAssetApi(projectId, selectedVersion?.versionId || '', asset.modelUuid, asset.wallUuid);
+ deleteWallAssetApi(projectId, selectedVersion?.versionId || "", asset.modelUuid, asset.wallUuid);
} else {
-
// SOCKET
const data = {
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
organization: organization,
modelUuid: asset.modelUuid,
- wallUuid: asset.wallUuid
- }
+ wallUuid: asset.wallUuid,
+ };
- socket.emit('v1:wall-asset:delete', data);
+ socket.emit("v1:wall-asset:delete", data);
}
}
- })
+ });
if (!socket?.connected) {
-
// API
- deleteWallApi(projectId, selectedVersion?.versionId || '', removedWall.wallUuid);
+ deleteWallApi(projectId, selectedVersion?.versionId || "", removedWall.wallUuid);
} else {
-
// SOCKET
const data = {
wallUuid: removedWall.wallUuid,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:delete', data);
+ socket.emit("v1:model-Wall:delete", data);
}
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Line-Delete',
+ actionType: "Line-Delete",
point: {
- type: 'Wall',
+ type: "Wall",
lineData: removedWall,
timeStamp: new Date().toISOString(),
- }
- }
- ]
+ },
+ },
+ ],
});
}
setHoveredLine(null);
}
- if (points[0].pointType === 'Floor' && points[1].pointType === 'Floor') {
+ if (points[0].pointType === "Floor" && points[1].pointType === "Floor") {
const Floors = getFloorsByPoints(points);
const { removedFloors, updatedFloors } = removeFloorByPoints(points);
if (removedFloors.length > 0) {
- removedFloors.forEach(floor => {
+ removedFloors.forEach((floor) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- deleteFloorApi(projectId, selectedVersion?.versionId || '', floor.floorUuid);
+ deleteFloorApi(projectId, selectedVersion?.versionId || "", floor.floorUuid);
} else {
-
// SOCKET
const data = {
floorUuid: floor.floorUuid,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:delete', data);
+ socket.emit("v1:model-Floor:delete", data);
}
}
});
@@ -214,84 +204,80 @@ function Line({ points }: Readonly) {
}));
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Delete',
- points: removedFloorsData
- }
- ]
+ actionType: "Lines-Delete",
+ points: removedFloorsData,
+ },
+ ],
});
}
if (updatedFloors.length > 0) {
- updatedFloors.forEach(floor => {
+ updatedFloors.forEach((floor) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
+ upsertFloorApi(projectId, selectedVersion?.versionId || "", floor);
} else {
-
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:add', data);
+ socket.emit("v1:model-Floor:add", data);
}
}
});
const updatedFloorsData = updatedFloors.map((floor) => ({
type: "Floor" as const,
- lineData: Floors.find(f => f.floorUuid === floor.floorUuid) || floor,
+ lineData: Floors.find((f) => f.floorUuid === floor.floorUuid) || floor,
newData: floor,
timeStamp: new Date().toISOString(),
}));
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Update',
- points: updatedFloorsData
- }
- ]
+ actionType: "Lines-Update",
+ points: updatedFloorsData,
+ },
+ ],
});
}
setHoveredLine(null);
}
- if (points[0].pointType === 'Zone' && points[1].pointType === 'Zone') {
+ if (points[0].pointType === "Zone" && points[1].pointType === "Zone") {
const Zones = getZonesByPoints(points);
const { removedZones, updatedZones } = removeZoneByPoints(points);
if (removedZones.length > 0) {
- removedZones.forEach(zone => {
+ removedZones.forEach((zone) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- deleteZoneApi(projectId, selectedVersion?.versionId || '', zone.zoneUuid);
+ deleteZoneApi(projectId, selectedVersion?.versionId || "", zone.zoneUuid);
} else {
-
// SOCKET
const data = {
zoneUuid: zone.zoneUuid,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:zone:delete', data);
+ socket.emit("v1:zone:delete", data);
}
}
});
@@ -303,72 +289,70 @@ function Line({ points }: Readonly) {
}));
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Delete',
- points: removedZonesData
- }
- ]
+ actionType: "Lines-Delete",
+ points: removedZonesData,
+ },
+ ],
});
}
if (updatedZones.length > 0) {
- updatedZones.forEach(zone => {
+ updatedZones.forEach((zone) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
+ upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
} else {
-
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:zone:add', data);
+ socket.emit("v1:zone:add", data);
}
}
});
const updatedZonesData = updatedZones.map((zone) => ({
type: "Zone" as const,
- lineData: Zones.find(z => z.zoneUuid === zone.zoneUuid) || zone,
+ lineData: Zones.find((z) => z.zoneUuid === zone.zoneUuid) || zone,
newData: zone,
timeStamp: new Date().toISOString(),
}));
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Update',
- points: updatedZonesData
- }
- ]
+ actionType: "Lines-Update",
+ points: updatedZonesData,
+ },
+ ],
});
}
setHoveredLine(null);
}
- handleCanvasCursors('default');
+ handleCanvasCursors("default");
}
- }
+ };
const handleDrag = (points: [Point, Point]) => {
- if (toolMode === 'move' && isHovered && dragOffset) {
+ if (toolMode === "move" && isHovered && dragOffset) {
raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3();
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
- handleCanvasCursors('grabbing');
+ handleCanvasCursors("grabbing");
const positionWithOffset = new THREE.Vector3().addVectors(hit, dragOffset);
const start = new THREE.Vector3(...points[0].position);
@@ -380,15 +364,15 @@ function Line({ points }: Readonly) {
const newStart = new THREE.Vector3().addVectors(start, delta);
const newEnd = new THREE.Vector3().addVectors(end, delta);
- if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
+ if (points[0].pointType === "Wall" && points[1].pointType === "Wall") {
setWallPosition(points[0].pointUuid, [newStart.x, newStart.y, newStart.z]);
setWallPosition(points[1].pointUuid, [newEnd.x, newEnd.y, newEnd.z]);
}
- if (points[0].pointType === 'Floor' && points[1].pointType === 'Floor') {
+ if (points[0].pointType === "Floor" && points[1].pointType === "Floor") {
setFloorPosition(points[0].pointUuid, [newStart.x, newStart.y, newStart.z]);
setFloorPosition(points[1].pointUuid, [newEnd.x, newEnd.y, newEnd.z]);
}
- if (points[0].pointType === 'Zone' && points[1].pointType === 'Zone') {
+ if (points[0].pointType === "Zone" && points[1].pointType === "Zone") {
setZonePosition(points[0].pointUuid, [newStart.x, newStart.y, newStart.z]);
setZonePosition(points[1].pointUuid, [newEnd.x, newEnd.y, newEnd.z]);
}
@@ -409,16 +393,16 @@ function Line({ points }: Readonly) {
const offset = new THREE.Vector3().subVectors(midPoint, hit);
setDragOffset(offset);
- if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
+ if (points[0].pointType === "Wall" && points[1].pointType === "Wall") {
const wall = getWallByPoints(points);
if (wall) {
const walls = getConnectedWallsByWallId(wall.wallUuid, false);
setInitialPositions({ walls });
}
- } else if (points[0].pointType === 'Floor') {
+ } else if (points[0].pointType === "Floor") {
const floors = getFloorsByPointId(points[0].pointUuid);
setInitialPositions({ floors });
- } else if (points[0].pointType === 'Zone') {
+ } else if (points[0].pointType === "Zone") {
const zones = getZonesByPointId(points[0].pointUuid);
setInitialPositions({ zones });
}
@@ -426,193 +410,185 @@ function Line({ points }: Readonly) {
};
const handleDragEnd = (points: [Point, Point]) => {
- if (toolMode !== 'move' || !dragOffset) return;
- handleCanvasCursors('default');
+ if (toolMode !== "move" || !dragOffset) return;
+ handleCanvasCursors("default");
setDragOffset(null);
- if (points[0].pointType === 'Wall' && points[1].pointType === 'Wall') {
+ if (points[0].pointType === "Wall" && points[1].pointType === "Wall") {
const wall = getWallByPoints(points);
if (!wall) return;
const updatedWalls = getConnectedWallsByWallId(wall.wallUuid, false);
if (updatedWalls.length > 0 && projectId) {
- updatedWalls.forEach(updatedWall => {
-
- const initialWall = initialPositions.walls?.find(w => w.wallUuid === updatedWall.wallUuid);
+ updatedWalls.forEach((updatedWall) => {
+ const initialWall = initialPositions.walls?.find((w) => w.wallUuid === updatedWall.wallUuid);
if (initialWall) {
const assetsOnWall = getWallAssetsByWall(updatedWall.wallUuid);
- assetsOnWall.forEach(asset => {
+ assetsOnWall.forEach((asset) => {
const { position, rotation } = calculateAssetTransformationOnWall(asset, initialWall, updatedWall);
const updatedWallAsset = updateWallAsset(asset.modelUuid, {
position: [position[0], asset.position[1], position[2]],
- rotation: rotation
+ rotation: rotation,
});
if (projectId && updatedWallAsset) {
if (!socket?.connected) {
// API
- upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
+ upsertWallAssetApi(projectId, selectedVersion?.versionId || "", updatedWallAsset);
} else {
-
// SOCKET
const data = {
wallAssetData: updatedWallAsset,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:wall-asset:add', data);
+ socket.emit("v1:wall-asset:add", data);
}
}
});
}
if (!socket?.connected) {
-
// API
- upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
+ upsertWallApi(projectId, selectedVersion?.versionId || "", updatedWall);
} else {
-
// SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:add', data);
+ socket.emit("v1:model-Wall:add", data);
}
- })
+ });
if (initialPositions.walls && initialPositions.walls.length > 0) {
const updatedPoints = initialPositions.walls.map((wall) => ({
type: "Wall" as const,
lineData: wall,
- newData: updatedWalls.find(w => w.wallUuid === wall.wallUuid),
+ newData: updatedWalls.find((w) => w.wallUuid === wall.wallUuid),
timeStamp: new Date().toISOString(),
}));
push2D({
- type: 'Draw',
- actions: [{
- actionType: 'Lines-Update',
- points: updatedPoints,
- }]
+ type: "Draw",
+ actions: [
+ {
+ actionType: "Lines-Update",
+ points: updatedPoints,
+ },
+ ],
});
}
}
- } else if (points[0].pointType === 'Floor' && points[1].pointType === 'Floor') {
+ } else if (points[0].pointType === "Floor" && points[1].pointType === "Floor") {
const updatedFloors1 = getFloorsByPointId(points[0].pointUuid);
const updatedFloors2 = getFloorsByPointId(points[1].pointUuid);
const updatedFloors = [...updatedFloors1, ...updatedFloors2].filter((floor, index, self) => index === self.findIndex((f) => f.floorUuid === floor.floorUuid));
if (updatedFloors.length > 0 && projectId) {
- updatedFloors.forEach(updatedFloor => {
+ updatedFloors.forEach((updatedFloor) => {
if (!socket?.connected) {
-
// API
- upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
+ upsertFloorApi(projectId, selectedVersion?.versionId || "", updatedFloor);
} else {
-
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:add', data);
+ socket.emit("v1:model-Floor:add", data);
}
- })
+ });
if (initialPositions.floors && initialPositions.floors.length > 0) {
const updatedPoints = initialPositions.floors.map((floor) => ({
type: "Floor" as const,
lineData: floor,
- newData: updatedFloors.find(f => f.floorUuid === floor.floorUuid),
+ newData: updatedFloors.find((f) => f.floorUuid === floor.floorUuid),
timeStamp: new Date().toISOString(),
}));
push2D({
- type: 'Draw',
- actions: [{
- actionType: 'Lines-Update',
- points: updatedPoints,
- }]
+ type: "Draw",
+ actions: [
+ {
+ actionType: "Lines-Update",
+ points: updatedPoints,
+ },
+ ],
});
}
}
- } else if (points[0].pointType === 'Zone' && points[1].pointType === 'Zone') {
+ } else if (points[0].pointType === "Zone" && points[1].pointType === "Zone") {
const updatedZones1 = getZonesByPointId(points[0].pointUuid);
const updatedZones2 = getZonesByPointId(points[1].pointUuid);
const updatedZones = [...updatedZones1, ...updatedZones2].filter((zone, index, self) => index === self.findIndex((z) => z.zoneUuid === zone.zoneUuid));
if (updatedZones.length > 0 && projectId) {
- updatedZones.forEach(updatedZone => {
+ updatedZones.forEach((updatedZone) => {
if (!socket?.connected) {
-
// API
- upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone);
+ upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone);
} else {
-
// SOCKET
const data = {
zoneData: updatedZone,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:zone:add', data);
+ socket.emit("v1:zone:add", data);
}
- })
+ });
if (initialPositions.zones && initialPositions.zones.length > 0) {
const updatedPoints = initialPositions.zones.map((zone) => ({
type: "Zone" as const,
lineData: zone,
- newData: updatedZones.find(z => z.zoneUuid === zone.zoneUuid),
+ newData: updatedZones.find((z) => z.zoneUuid === zone.zoneUuid),
timeStamp: new Date().toISOString(),
}));
push2D({
- type: 'Draw',
- actions: [{
- actionType: 'Lines-Update',
- points: updatedPoints,
- }]
+ type: "Draw",
+ actions: [
+ {
+ actionType: "Lines-Update",
+ points: updatedPoints,
+ },
+ ],
});
}
}
}
- }
+ };
return (
- handleDragStart(points)}
- onDrag={() => handleDrag(points)}
- onDragEnd={() => handleDragEnd(points)}
- >
+ handleDragStart(points)} onDrag={() => handleDrag(points)} onDragEnd={() => handleDragEnd(points)}>
) {
onPointerOver={(e) => {
if (selectedPoints.length === 0 && e.buttons === 0 && !e.ctrlKey) {
setHoveredLine(points);
- setIsHovered(true)
- if (toolMode === 'move' && !hoveredPoint) {
- handleCanvasCursors('grab');
+ setIsHovered(true);
+ if (toolMode === "move" && !hoveredPoint) {
+ handleCanvasCursors("grab");
}
}
}}
@@ -635,16 +611,16 @@ function Line({ points }: Readonly) {
if (hoveredLine && isHovered) {
setHoveredLine(null);
if (!hoveredPoint) {
- handleCanvasCursors('default');
+ handleCanvasCursors("default");
}
}
- setIsHovered(false)
+ setIsHovered(false);
}}
>
-
+
);
}
-export default Line;
\ No newline at end of file
+export default Line;
diff --git a/app/src/modules/builder/point/point.tsx b/app/src/modules/builder/point/point.tsx
index 0b1e3cc..d6a9b92 100644
--- a/app/src/modules/builder/point/point.tsx
+++ b/app/src/modules/builder/point/point.tsx
@@ -1,30 +1,29 @@
-import * as THREE from 'three';
-import * as Constants from '../../../types/world/worldConstants';
-import { useRef, useState, useEffect, useMemo } from 'react';
-import { useSocketStore, useToolMode } from '../../../store/builder/store';
-import { DragControls } from '@react-three/drei';
-import { useThree } from '@react-three/fiber';
-import { useBuilderStore } from '../../../store/builder/useBuilderStore';
-import { useSelectedPoints } from '../../../store/simulation/useSimulationStore';
-import { usePointSnapping } from './helpers/usePointSnapping';
-import { useParams } from 'react-router-dom';
-import { useVersionContext } from '../version/versionContext';
-import { useSceneContext } from '../../scene/sceneContext';
+import * as THREE from "three";
+import * as Constants from "../../../types/world/worldConstants";
+import { useRef, useState, useEffect, useMemo } from "react";
+import { useSocketStore, useToolMode } from "../../../store/builder/store";
+import { DragControls } from "@react-three/drei";
+import { useThree } from "@react-three/fiber";
+import { useBuilderStore } from "../../../store/builder/useBuilderStore";
+import { useSelectedPoints } from "../../../store/simulation/useSimulationStore";
+import { usePointSnapping } from "./helpers/usePointSnapping";
+import { useParams } from "react-router-dom";
+import { useSceneContext } from "../../scene/sceneContext";
-import { upsertAisleApi } from '../../../services/factoryBuilder/aisle/upsertAisleApi';
-import { deleteAisleApi } from '../../../services/factoryBuilder/aisle/deleteAisleApi';
-import { upsertWallApi } from '../../../services/factoryBuilder/wall/upsertWallApi';
-import { deleteWallApi } from '../../../services/factoryBuilder/wall/deleteWallApi';
-import { upsertFloorApi } from '../../../services/factoryBuilder/floor/upsertFloorApi';
-import { deleteFloorApi } from '../../../services/factoryBuilder/floor/deleteFloorApi';
-import { upsertZoneApi } from '../../../services/factoryBuilder/zone/upsertZoneApi';
-import { deleteZoneApi } from '../../../services/factoryBuilder/zone/deleteZoneApi';
-import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
-import { deleteWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi';
+import { upsertAisleApi } from "../../../services/factoryBuilder/aisle/upsertAisleApi";
+import { deleteAisleApi } from "../../../services/factoryBuilder/aisle/deleteAisleApi";
+import { upsertWallApi } from "../../../services/factoryBuilder/wall/upsertWallApi";
+import { deleteWallApi } from "../../../services/factoryBuilder/wall/deleteWallApi";
+import { upsertFloorApi } from "../../../services/factoryBuilder/floor/upsertFloorApi";
+import { deleteFloorApi } from "../../../services/factoryBuilder/floor/deleteFloorApi";
+import { upsertZoneApi } from "../../../services/factoryBuilder/zone/upsertZoneApi";
+import { deleteZoneApi } from "../../../services/factoryBuilder/zone/deleteZoneApi";
+import { upsertWallAssetApi } from "../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi";
+import { deleteWallAssetApi } from "../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi";
-import { getUserData } from '../../../functions/getUserData';
-import { handleCanvasCursors } from '../../../utils/mouseUtils/handleCanvasCursors';
-import { calculateAssetTransformationOnWall } from '../wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall';
+import { getUserData } from "../../../functions/getUserData";
+import { handleCanvasCursors } from "../../../utils/mouseUtils/handleCanvasCursors";
+import { calculateAssetTransformationOnWall } from "../wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall";
function Point({ point }: { readonly point: Point }) {
const materialRef = useRef(null);
@@ -35,75 +34,74 @@ function Point({ point }: { readonly point: Point }) {
const [dragOffset, setDragOffset] = useState(null);
const { socket } = useSocketStore();
const { toolMode } = useToolMode();
- const { aisleStore, wallStore, floorStore, zoneStore, undoRedo2DStore, wallAssetStore } = useSceneContext();
+ const { aisleStore, wallStore, floorStore, zoneStore, undoRedo2DStore, wallAssetStore, versionStore } = useSceneContext();
const { push2D } = undoRedo2DStore();
const { setPosition: setAislePosition, removePoint: removeAislePoint, getAislesByPointId } = aisleStore();
const { setPosition: setWallPosition, removePoint: removeWallPoint, getWallsByPointId } = wallStore();
const { setPosition: setFloorPosition, removePoint: removeFloorPoint, getFloorsByPointId } = floorStore();
const { setPosition: setZonePosition, removePoint: removeZonePoint, getZonesByPointId } = zoneStore();
const { getWallAssetsByWall, updateWallAsset, removeWallAsset } = wallAssetStore();
+ const { selectedVersion } = versionStore();
const { snapAislePoint, snapAisleAngle, snapWallPoint, snapWallAngle, snapFloorPoint, snapFloorAngle, snapZonePoint, snapZoneAngle } = usePointSnapping({ uuid: point.pointUuid, pointType: point.pointType, position: point.position });
const { hoveredPoint, hoveredLine, setHoveredPoint } = useBuilderStore();
const { selectedPoints } = useSelectedPoints();
const { userId, organization } = getUserData();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams();
const boxScale: [number, number, number] = Constants.pointConfig.boxScale;
const colors = getColor(point);
const [initialStates, setInitialStates] = useState<{
- aisles?: Aisle[],
- walls?: Wall[],
- floors?: Floor[],
- zones?: Zone[]
+ aisles?: Aisle[];
+ walls?: Wall[];
+ floors?: Floor[];
+ zones?: Zone[];
}>({});
useEffect(() => {
- handleCanvasCursors('default');
- }, [toolMode])
+ handleCanvasCursors("default");
+ }, [toolMode]);
function getColor(point: Point) {
- if (point.pointType === 'Aisle') {
+ if (point.pointType === "Aisle") {
return {
defaultInnerColor: Constants.pointConfig.defaultInnerColor,
defaultOuterColor: Constants.pointConfig.aisleOuterColor,
defaultDeleteColor: Constants.pointConfig.deleteColor,
- }
- } else if (point.pointType === 'Floor') {
+ };
+ } else if (point.pointType === "Floor") {
return {
defaultInnerColor: Constants.pointConfig.defaultInnerColor,
defaultOuterColor: Constants.pointConfig.floorOuterColor,
defaultDeleteColor: Constants.pointConfig.deleteColor,
- }
- } else if (point.pointType === 'Wall') {
+ };
+ } else if (point.pointType === "Wall") {
return {
defaultInnerColor: Constants.pointConfig.defaultInnerColor,
defaultOuterColor: Constants.pointConfig.wallOuterColor,
defaultDeleteColor: Constants.pointConfig.deleteColor,
- }
- } else if (point.pointType === 'Zone') {
+ };
+ } else if (point.pointType === "Zone") {
return {
defaultInnerColor: Constants.pointConfig.defaultInnerColor,
defaultOuterColor: Constants.pointConfig.zoneOuterColor,
defaultDeleteColor: Constants.pointConfig.deleteColor,
- }
+ };
} else {
return {
defaultInnerColor: Constants.pointConfig.defaultInnerColor,
defaultOuterColor: Constants.pointConfig.defaultOuterColor,
defaultDeleteColor: Constants.pointConfig.deleteColor,
- }
+ };
}
}
useEffect(() => {
- if (materialRef.current && (toolMode === 'move' || toolMode === '2D-Delete')) {
+ if (materialRef.current && (toolMode === "move" || toolMode === "2D-Delete")) {
let innerColor;
let outerColor;
if (isHovered) {
- innerColor = toolMode === '2D-Delete' ? colors.defaultDeleteColor : colors.defaultOuterColor;
- outerColor = toolMode === '2D-Delete' ? colors.defaultDeleteColor : colors.defaultOuterColor;
+ innerColor = toolMode === "2D-Delete" ? colors.defaultDeleteColor : colors.defaultOuterColor;
+ outerColor = toolMode === "2D-Delete" ? colors.defaultDeleteColor : colors.defaultOuterColor;
} else {
innerColor = colors.defaultInnerColor;
outerColor = colors.defaultOuterColor;
@@ -111,42 +109,45 @@ function Point({ point }: { readonly point: Point }) {
materialRef.current.uniforms.uInnerColor.value.set(innerColor);
materialRef.current.uniforms.uOuterColor.value.set(outerColor);
materialRef.current.uniformsNeedUpdate = true;
- } else if (materialRef.current && toolMode !== 'move') {
+ } else if (materialRef.current && toolMode !== "move") {
materialRef.current.uniforms.uInnerColor.value.set(colors.defaultInnerColor);
materialRef.current.uniforms.uOuterColor.value.set(colors.defaultOuterColor);
materialRef.current.uniformsNeedUpdate = true;
}
}, [isHovered, colors.defaultInnerColor, colors.defaultOuterColor, colors.defaultDeleteColor, toolMode]);
- const uniforms = useMemo(() => ({
- uOuterColor: { value: new THREE.Color(colors.defaultOuterColor) },
- uInnerColor: { value: new THREE.Color(colors.defaultInnerColor) },
- }), [colors.defaultInnerColor, colors.defaultOuterColor]);
+ const uniforms = useMemo(
+ () => ({
+ uOuterColor: { value: new THREE.Color(colors.defaultOuterColor) },
+ uInnerColor: { value: new THREE.Color(colors.defaultInnerColor) },
+ }),
+ [colors.defaultInnerColor, colors.defaultOuterColor]
+ );
const handleDrag = (point: Point) => {
- if (toolMode === 'move' && isHovered && dragOffset) {
+ if (toolMode === "move" && isHovered && dragOffset) {
raycaster.setFromCamera(pointer, camera);
const intersectionPoint = new THREE.Vector3();
const hit = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (hit) {
- handleCanvasCursors('grabbing');
+ handleCanvasCursors("grabbing");
const positionWithOffset = new THREE.Vector3().addVectors(hit, dragOffset);
const newPosition: [number, number, number] = [positionWithOffset.x, positionWithOffset.y, positionWithOffset.z];
- if (point.pointType === 'Aisle') {
+ if (point.pointType === "Aisle") {
const aisleSnapped = snapAisleAngle(newPosition);
const finalSnapped = snapAislePoint(aisleSnapped.position);
setAislePosition(point.pointUuid, finalSnapped.position);
- } else if (point.pointType === 'Wall') {
+ } else if (point.pointType === "Wall") {
const wallSnapped = snapWallAngle(newPosition);
const finalSnapped = snapWallPoint(wallSnapped.position);
setWallPosition(point.pointUuid, finalSnapped.position);
- } else if (point.pointType === 'Floor') {
+ } else if (point.pointType === "Floor") {
const floorSnapped = snapFloorAngle(newPosition);
const finalSnapped = snapFloorPoint(floorSnapped.position);
setFloorPosition(point.pointUuid, finalSnapped.position);
- } else if (point.pointType === 'Zone') {
+ } else if (point.pointType === "Zone") {
const zoneSnapped = snapZoneAngle(newPosition);
const finalSnapped = snapZonePoint(zoneSnapped.position);
setZonePosition(point.pointUuid, finalSnapped.position);
@@ -165,16 +166,16 @@ function Point({ point }: { readonly point: Point }) {
const offset = new THREE.Vector3().subVectors(currentPosition, hit);
setDragOffset(offset);
- if (point.pointType === 'Aisle') {
+ if (point.pointType === "Aisle") {
const aisles = getAislesByPointId(point.pointUuid);
setInitialStates({ aisles });
- } else if (point.pointType === 'Wall') {
+ } else if (point.pointType === "Wall") {
const walls = getWallsByPointId(point.pointUuid);
setInitialStates({ walls });
- } else if (point.pointType === 'Floor') {
+ } else if (point.pointType === "Floor") {
const floors = getFloorsByPointId(point.pointUuid);
setInitialStates({ floors });
- } else if (point.pointType === 'Zone') {
+ } else if (point.pointType === "Zone") {
const zones = getZonesByPointId(point.pointUuid);
setInitialStates({ zones });
}
@@ -182,111 +183,107 @@ function Point({ point }: { readonly point: Point }) {
};
const handleDragEnd = (point: Point) => {
- handleCanvasCursors('default');
+ handleCanvasCursors("default");
setDragOffset(null);
- if (toolMode !== 'move') return;
+ if (toolMode !== "move") return;
- if (point.pointType === 'Aisle') {
+ if (point.pointType === "Aisle") {
const updatedAisles = getAislesByPointId(point.pointUuid);
if (updatedAisles.length > 0 && projectId) {
updatedAisles.forEach((updatedAisle) => {
if (!socket?.connected) {
-
// API
- upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '');
+ upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || "");
} else {
+ // SOCKET
- // SOCKET
-
- socket.emit('v1:model-aisle:add', {
+ socket.emit("v1:model-aisle:add", {
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
organization: organization,
aisleUuid: updatedAisle.aisleUuid,
points: updatedAisle.points,
- type: updatedAisle.type
- })
+ type: updatedAisle.type,
+ });
}
- })
+ });
if (initialStates.aisles && initialStates.aisles.length > 0) {
const updatedPoints = initialStates.aisles.map((aisle) => ({
type: "Aisle" as const,
lineData: aisle,
- newData: updatedAisles.find(a => a.aisleUuid === aisle.aisleUuid),
+ newData: updatedAisles.find((a) => a.aisleUuid === aisle.aisleUuid),
timeStamp: new Date().toISOString(),
}));
push2D({
- type: 'Draw',
- actions: [{
- actionType: 'Lines-Update',
- points: updatedPoints,
- }]
+ type: "Draw",
+ actions: [
+ {
+ actionType: "Lines-Update",
+ points: updatedPoints,
+ },
+ ],
});
}
}
- } else if (point.pointType === 'Wall') {
+ } else if (point.pointType === "Wall") {
const updatedWalls = getWallsByPointId(point.pointUuid);
if (updatedWalls && updatedWalls.length > 0 && projectId) {
updatedWalls.forEach((updatedWall) => {
-
- const initialWall = initialStates.walls?.find(w => w.wallUuid === updatedWall.wallUuid);
+ const initialWall = initialStates.walls?.find((w) => w.wallUuid === updatedWall.wallUuid);
if (initialWall) {
const assetsOnWall = getWallAssetsByWall(updatedWall.wallUuid);
- assetsOnWall.forEach(asset => {
+ assetsOnWall.forEach((asset) => {
const { position, rotation } = calculateAssetTransformationOnWall(asset, initialWall, updatedWall);
const updatedWallAsset = updateWallAsset(asset.modelUuid, {
position: [position[0], asset.position[1], position[2]],
- rotation: rotation
+ rotation: rotation,
});
if (projectId && updatedWallAsset) {
if (!socket?.connected) {
// API
- upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
+ upsertWallAssetApi(projectId, selectedVersion?.versionId || "", updatedWallAsset);
} else {
-
// SOCKET
const data = {
wallAssetData: updatedWallAsset,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:wall-asset:add', data);
+ socket.emit("v1:wall-asset:add", data);
}
}
});
}
if (!socket?.connected) {
-
// API
- upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
+ upsertWallApi(projectId, selectedVersion?.versionId || "", updatedWall);
} else {
-
- // SOCKET
+ // SOCKET
const data = {
wallData: updatedWall,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:add', data);
+ socket.emit("v1:model-Wall:add", data);
}
});
}
@@ -295,40 +292,40 @@ function Point({ point }: { readonly point: Point }) {
const updatedPoints = initialStates.walls.map((wall) => ({
type: "Wall" as const,
lineData: wall,
- newData: updatedWalls.find(w => w.wallUuid === wall.wallUuid),
+ newData: updatedWalls.find((w) => w.wallUuid === wall.wallUuid),
timeStamp: new Date().toISOString(),
}));
push2D({
- type: 'Draw',
- actions: [{
- actionType: 'Lines-Update',
- points: updatedPoints,
- }]
+ type: "Draw",
+ actions: [
+ {
+ actionType: "Lines-Update",
+ points: updatedPoints,
+ },
+ ],
});
}
- } else if (point.pointType === 'Floor') {
+ } else if (point.pointType === "Floor") {
const updatedFloors = getFloorsByPointId(point.pointUuid);
if (updatedFloors && updatedFloors.length > 0 && projectId) {
updatedFloors.forEach((updatedFloor) => {
if (!socket?.connected) {
-
// API
- upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
+ upsertFloorApi(projectId, selectedVersion?.versionId || "", updatedFloor);
} else {
-
// SOCKET
const data = {
floorData: updatedFloor,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:add', data);
+ socket.emit("v1:model-Floor:add", data);
}
});
}
@@ -337,40 +334,40 @@ function Point({ point }: { readonly point: Point }) {
const updatedPoints = initialStates.floors.map((floor) => ({
type: "Floor" as const,
lineData: floor,
- newData: updatedFloors.find(f => f.floorUuid === floor.floorUuid),
+ newData: updatedFloors.find((f) => f.floorUuid === floor.floorUuid),
timeStamp: new Date().toISOString(),
}));
push2D({
- type: 'Draw',
- actions: [{
- actionType: 'Lines-Update',
- points: updatedPoints,
- }]
+ type: "Draw",
+ actions: [
+ {
+ actionType: "Lines-Update",
+ points: updatedPoints,
+ },
+ ],
});
}
- } else if (point.pointType === 'Zone') {
+ } else if (point.pointType === "Zone") {
const updatedZones = getZonesByPointId(point.pointUuid);
if (updatedZones && updatedZones.length > 0 && projectId) {
updatedZones.forEach((updatedZone) => {
if (!socket?.connected) {
-
// API
- upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone);
+ upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone);
} else {
-
// SOCKET
const data = {
zoneData: updatedZone,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:zone:add', data);
+ socket.emit("v1:zone:add", data);
}
});
}
@@ -379,51 +376,50 @@ function Point({ point }: { readonly point: Point }) {
const updatedPoints = initialStates.zones.map((zone) => ({
type: "Zone" as const,
lineData: zone,
- newData: updatedZones.find(z => z.zoneUuid === zone.zoneUuid),
+ newData: updatedZones.find((z) => z.zoneUuid === zone.zoneUuid),
timeStamp: new Date().toISOString(),
}));
push2D({
- type: 'Draw',
- actions: [{
- actionType: 'Lines-Update',
- points: updatedPoints,
- }]
+ type: "Draw",
+ actions: [
+ {
+ actionType: "Lines-Update",
+ points: updatedPoints,
+ },
+ ],
});
}
}
setInitialStates({});
- }
+ };
const handlePointClick = (point: Point) => {
- if (toolMode === '2D-Delete') {
- if (point.pointType === 'Aisle') {
+ if (toolMode === "2D-Delete") {
+ if (point.pointType === "Aisle") {
const removedAisles = removeAislePoint(point.pointUuid);
setHoveredPoint(null);
if (removedAisles.length > 0) {
- removedAisles.forEach(aisle => {
+ removedAisles.forEach((aisle) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || '');
+ deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || "");
} else {
-
// SOCKET
const data = {
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
organization: organization,
- aisleUuid: aisle.aisleUuid
- }
+ aisleUuid: aisle.aisleUuid,
+ };
- socket.emit('v1:model-aisle:delete', data);
+ socket.emit("v1:model-aisle:delete", data);
}
-
}
});
@@ -434,70 +430,64 @@ function Point({ point }: { readonly point: Point }) {
}));
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Delete',
- points: removedAislesData
- }
- ]
+ actionType: "Lines-Delete",
+ points: removedAislesData,
+ },
+ ],
});
}
}
- if (point.pointType === 'Wall') {
+ if (point.pointType === "Wall") {
const removedWalls = removeWallPoint(point.pointUuid);
if (removedWalls.length > 0) {
setHoveredPoint(null);
- removedWalls.forEach(wall => {
+ removedWalls.forEach((wall) => {
const assetsOnWall = getWallAssetsByWall(wall.wallUuid);
assetsOnWall.forEach((asset) => {
if (projectId && asset) {
-
removeWallAsset(asset.modelUuid);
if (!socket?.connected) {
-
// API
- deleteWallAssetApi(projectId, selectedVersion?.versionId || '', asset.modelUuid, asset.wallUuid);
+ deleteWallAssetApi(projectId, selectedVersion?.versionId || "", asset.modelUuid, asset.wallUuid);
} else {
-
// SOCKET
const data = {
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
organization: organization,
modelUuid: asset.modelUuid,
- wallUuid: asset.wallUuid
- }
+ wallUuid: asset.wallUuid,
+ };
- socket.emit('v1:wall-asset:delete', data);
+ socket.emit("v1:wall-asset:delete", data);
}
-
}
- })
+ });
if (projectId) {
if (!socket?.connected) {
-
// API
- deleteWallApi(projectId, selectedVersion?.versionId || '', wall.wallUuid);
+ deleteWallApi(projectId, selectedVersion?.versionId || "", wall.wallUuid);
} else {
-
// SOCKET
const data = {
wallUuid: wall.wallUuid,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:delete', data);
+ socket.emit("v1:model-Wall:delete", data);
}
}
});
@@ -509,41 +499,39 @@ function Point({ point }: { readonly point: Point }) {
}));
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Delete',
- points: removedWallsData
- }
- ]
+ actionType: "Lines-Delete",
+ points: removedWallsData,
+ },
+ ],
});
}
}
- if (point.pointType === 'Floor') {
+ if (point.pointType === "Floor") {
const Floors = getFloorsByPointId(point.pointUuid);
const { removedFloors, updatedFloors } = removeFloorPoint(point.pointUuid);
setHoveredPoint(null);
if (removedFloors.length > 0) {
- removedFloors.forEach(floor => {
+ removedFloors.forEach((floor) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- deleteFloorApi(projectId, selectedVersion?.versionId || '', floor.floorUuid);
+ deleteFloorApi(projectId, selectedVersion?.versionId || "", floor.floorUuid);
} else {
-
// SOCKET
const data = {
floorUuid: floor.floorUuid,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:delete', data);
+ socket.emit("v1:model-Floor:delete", data);
}
}
});
@@ -555,83 +543,79 @@ function Point({ point }: { readonly point: Point }) {
}));
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Delete',
- points: removedFloorsData
- }
- ]
+ actionType: "Lines-Delete",
+ points: removedFloorsData,
+ },
+ ],
});
}
if (updatedFloors.length > 0) {
- updatedFloors.forEach(floor => {
+ updatedFloors.forEach((floor) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
+ upsertFloorApi(projectId, selectedVersion?.versionId || "", floor);
} else {
-
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:add', data);
+ socket.emit("v1:model-Floor:add", data);
}
}
});
const updatedFloorsData = updatedFloors.map((floor) => ({
type: "Floor" as const,
- lineData: Floors.find(f => f.floorUuid === floor.floorUuid) || floor,
+ lineData: Floors.find((f) => f.floorUuid === floor.floorUuid) || floor,
newData: floor,
timeStamp: new Date().toISOString(),
}));
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Update',
- points: updatedFloorsData
- }
- ]
+ actionType: "Lines-Update",
+ points: updatedFloorsData,
+ },
+ ],
});
}
}
- if (point.pointType === 'Zone') {
+ if (point.pointType === "Zone") {
const Zones = getZonesByPointId(point.pointUuid);
const { removedZones, updatedZones } = removeZonePoint(point.pointUuid);
setHoveredPoint(null);
if (removedZones.length > 0) {
- removedZones.forEach(zone => {
+ removedZones.forEach((zone) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- deleteZoneApi(projectId, selectedVersion?.versionId || '', zone.zoneUuid);
+ deleteZoneApi(projectId, selectedVersion?.versionId || "", zone.zoneUuid);
} else {
-
// SOCKET
const data = {
zoneUuid: zone.zoneUuid,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:zone:delete', data);
+ socket.emit("v1:zone:delete", data);
}
}
});
@@ -643,75 +627,73 @@ function Point({ point }: { readonly point: Point }) {
}));
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Delete',
- points: removedZonesData
- }
- ]
+ actionType: "Lines-Delete",
+ points: removedZonesData,
+ },
+ ],
});
}
if (updatedZones.length > 0) {
- updatedZones.forEach(zone => {
+ updatedZones.forEach((zone) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
+ upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
} else {
-
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:zone:add', data);
+ socket.emit("v1:zone:add", data);
}
}
});
const updatedZonesData = updatedZones.map((zone) => ({
type: "Zone" as const,
- lineData: Zones.find(z => z.zoneUuid === zone.zoneUuid) || zone,
+ lineData: Zones.find((z) => z.zoneUuid === zone.zoneUuid) || zone,
newData: zone,
timeStamp: new Date().toISOString(),
}));
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Update',
- points: updatedZonesData
- }
- ]
+ actionType: "Lines-Update",
+ points: updatedZonesData,
+ },
+ ],
});
}
}
- handleCanvasCursors('default');
+ handleCanvasCursors("default");
}
- }
+ };
useEffect(() => {
if (hoveredPoint && hoveredPoint.pointUuid !== point.pointUuid) {
setIsHovered(false);
}
- }, [hoveredPoint])
+ }, [hoveredPoint]);
useEffect(() => {
- if (selectedPoints.length > 0 && selectedPoints.some((selectedPoint) => (selectedPoint.userData.pointUuid && selectedPoint.userData.pointUuid === point.pointUuid))) {
+ if (selectedPoints.length > 0 && selectedPoints.some((selectedPoint) => selectedPoint.userData.pointUuid && selectedPoint.userData.pointUuid === point.pointUuid)) {
setIsSelected(true);
} else {
setIsSelected(false);
}
- }, [selectedPoints])
+ }, [selectedPoints]);
if (!point) {
return null;
@@ -719,14 +701,8 @@ function Point({ point }: { readonly point: Point }) {
return (
<>
- {!isSelected ?
- handleDragStart(point)}
- onDrag={() => handleDrag(point)}
- onDragEnd={() => handleDragEnd(point)}
- >
+ {!isSelected ? (
+ handleDragStart(point)} onDrag={() => handleDrag(point)} onDragEnd={() => handleDragEnd(point)}>
@@ -760,18 +736,15 @@ function Point({ point }: { readonly point: Point }) {
- :
-
+ ) : (
+
@@ -809,9 +774,9 @@ function Point({ point }: { readonly point: Point }) {
- }
+ )}
>
);
}
-export default Point;
\ No newline at end of file
+export default Point;
diff --git a/app/src/modules/builder/version/versionContext.tsx b/app/src/modules/builder/version/versionContext.tsx
deleted file mode 100644
index 31aa21e..0000000
--- a/app/src/modules/builder/version/versionContext.tsx
+++ /dev/null
@@ -1,37 +0,0 @@
-import { createContext, useContext, useMemo } from 'react';
-import { createSelectedVersionStore, SelectedVersionType } from '../../../store/simulation/useSimulationStore';
-
-type VersionContextValue = {
- selectedVersionStore: SelectedVersionType,
-};
-
-const VersionContext = createContext(null);
-
-export function VersionProvider({
- children,
-}: {
- readonly children: React.ReactNode;
-}) {
- const selectedVersionStore = useMemo(() => createSelectedVersionStore(), []);
-
- const contextValue = useMemo(() => (
- {
- selectedVersionStore
- }
- ), [selectedVersionStore]);
-
- return (
-
- {children}
-
- );
-}
-
-// Base hook to get the context
-export function useVersionContext() {
- const context = useContext(VersionContext);
- if (!context) {
- throw new Error('useVersionContext must be used within a VersionProvider');
- }
- return context;
-}
\ No newline at end of file
diff --git a/app/src/modules/builder/wall/Instances/instance/wall.tsx b/app/src/modules/builder/wall/Instances/instance/wall.tsx
index 293be01..47b5f21 100644
--- a/app/src/modules/builder/wall/Instances/instance/wall.tsx
+++ b/app/src/modules/builder/wall/Instances/instance/wall.tsx
@@ -3,7 +3,7 @@ import { Base } from '@react-three/csg';
import { useMemo, useRef, useState } from 'react';
import { MeshDiscardMaterial } from '@react-three/drei';
import { useFrame, useThree } from '@react-three/fiber';
-import useModuleStore from '../../../../../store/useModuleStore';
+import useModuleStore from '../../../../../store/ui/useModuleStore';
import { useSceneContext } from '../../../../scene/sceneContext';
import { useWallClassification } from './helpers/useWallClassification';
import { useToggleView, useWallVisibility } from '../../../../../store/builder/store';
diff --git a/app/src/modules/builder/wall/Instances/wallInstances.tsx b/app/src/modules/builder/wall/Instances/wallInstances.tsx
index 6461225..98eac59 100644
--- a/app/src/modules/builder/wall/Instances/wallInstances.tsx
+++ b/app/src/modules/builder/wall/Instances/wallInstances.tsx
@@ -13,7 +13,7 @@ import * as Constants from '../../../../types/world/worldConstants';
import texturePath from "../../../../assets/textures/floor/white.png";
import texturePathDark from "../../../../assets/textures/floor/black.png";
-import useModuleStore from '../../../../store/useModuleStore';
+import useModuleStore from '../../../../store/ui/useModuleStore';
function WallInstances() {
const { wallStore } = useSceneContext();
diff --git a/app/src/modules/builder/wall/wallCreator/wallCreator.tsx b/app/src/modules/builder/wall/wallCreator/wallCreator.tsx
index a0729fd..b009e1d 100644
--- a/app/src/modules/builder/wall/wallCreator/wallCreator.tsx
+++ b/app/src/modules/builder/wall/wallCreator/wallCreator.tsx
@@ -1,19 +1,18 @@
-import * as THREE from 'three'
-import { useEffect, useMemo, useRef, useState } from 'react'
-import { useThree } from '@react-three/fiber';
-import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
-import * as Constants from '../../../../types/world/worldConstants';
-import { useSceneContext } from '../../../scene/sceneContext';
-import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
-import { useParams } from 'react-router-dom';
-import { useVersionContext } from '../../version/versionContext';
-import { getUserData } from '../../../../functions/getUserData';
-import getClosestIntersection from '../../line/helpers/getClosestIntersection';
-import ReferencePoint from '../../point/reference/referencePoint';
-import ReferenceWall from './referenceWall';
+import * as THREE from "three";
+import { useEffect, useMemo, useRef, useState } from "react";
+import { useThree } from "@react-three/fiber";
+import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from "../../../../store/builder/store";
+import * as Constants from "../../../../types/world/worldConstants";
+import { useSceneContext } from "../../../scene/sceneContext";
+import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
+import { useParams } from "react-router-dom";
+import { getUserData } from "../../../../functions/getUserData";
+import getClosestIntersection from "../../line/helpers/getClosestIntersection";
+import ReferencePoint from "../../point/reference/referencePoint";
+import ReferenceWall from "./referenceWall";
-import { upsertWallApi } from '../../../../services/factoryBuilder/wall/upsertWallApi';
-import { deleteWallApi } from '../../../../services/factoryBuilder/wall/deleteWallApi';
+import { upsertWallApi } from "../../../../services/factoryBuilder/wall/upsertWallApi";
+import { deleteWallApi } from "../../../../services/factoryBuilder/wall/deleteWallApi";
function WallCreator() {
const { scene, camera, raycaster, gl, pointer } = useThree();
@@ -22,13 +21,12 @@ function WallCreator() {
const { toolMode } = useToolMode();
const { activeLayer } = useActiveLayer();
const { socket } = useSocketStore();
- const { wallStore, undoRedo2DStore } = useSceneContext();
+ const { wallStore, undoRedo2DStore, versionStore } = useSceneContext();
const { addWall, getWallPointById, removeWall, getWallByPoints } = wallStore();
const { push2D } = undoRedo2DStore();
const drag = useRef(false);
const isLeftMouseDown = useRef(false);
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { selectedVersion } = versionStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
@@ -66,9 +64,9 @@ function WallCreator() {
let position = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (!position) return;
- const pointIntersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Wall-Point');
+ const pointIntersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === "Wall-Point");
- const wallIntersect = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Wall-Line');
+ const wallIntersect = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === "Wall-Line");
if (wallIntersect && !pointIntersects) {
const wall = getWallByPoints(wallIntersect.object.userData.points);
@@ -95,46 +93,43 @@ function WallCreator() {
if (projectId) {
if (!socket?.connected) {
-
// API
- deleteWallApi(projectId, selectedVersion?.versionId || '', wall.wallUuid);
+ deleteWallApi(projectId, selectedVersion?.versionId || "", wall.wallUuid);
} else {
-
// SOCKET
const data = {
wallUuid: wall.wallUuid,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:delete', data);
+ socket.emit("v1:model-Wall:delete", data);
}
-
}
const point1: Point = {
pointUuid: wall.points[0].pointUuid,
- pointType: 'Wall',
+ pointType: "Wall",
position: wall.points[0].position,
- layer: wall.points[0].layer
+ layer: wall.points[0].layer,
};
const point2: Point = {
pointUuid: wall.points[1].pointUuid,
- pointType: 'Wall',
+ pointType: "Wall",
position: wall.points[1].position,
- layer: wall.points[1].layer
+ layer: wall.points[1].layer,
};
const newPoint: Point = {
pointUuid: THREE.MathUtils.generateUUID(),
- pointType: 'Wall',
+ pointType: "Wall",
position: closestPoint.toArray(),
- layer: activeLayer
+ layer: activeLayer,
};
if (tempPoints.length === 0) {
@@ -145,8 +140,8 @@ function WallCreator() {
insideMaterial: outsideMaterial,
wallThickness: wallThickness,
wallHeight: wallHeight,
- decals: []
- }
+ decals: [],
+ };
addWall(wall2);
@@ -154,20 +149,19 @@ function WallCreator() {
if (!socket?.connected) {
// API
- upsertWallApi(projectId, selectedVersion?.versionId || '', wall2);
+ upsertWallApi(projectId, selectedVersion?.versionId || "", wall2);
} else {
-
// SOCKET
const data = {
wallData: wall2,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:add', data);
+ socket.emit("v1:model-Wall:add", data);
}
}
@@ -178,56 +172,57 @@ function WallCreator() {
insideMaterial: outsideMaterial,
wallThickness: wallThickness,
wallHeight: wallHeight,
- decals: []
- }
+ decals: [],
+ };
addWall(wall3);
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Create',
+ actionType: "Lines-Create",
points: [
{
- type: 'Wall',
+ type: "Wall",
lineData: wall3,
timeStamp: new Date().toISOString(),
- }, {
- type: 'Wall',
+ },
+ {
+ type: "Wall",
lineData: wall2,
timeStamp: new Date().toISOString(),
- }
- ]
- }, {
- actionType: 'Line-Delete',
+ },
+ ],
+ },
+ {
+ actionType: "Line-Delete",
point: {
- type: 'Wall',
+ type: "Wall",
lineData: wall,
timeStamp: new Date().toISOString(),
- }
- }
+ },
+ },
],
- })
+ });
if (projectId) {
if (!socket?.connected) {
// API
- upsertWallApi(projectId, selectedVersion?.versionId || '', wall3);
+ upsertWallApi(projectId, selectedVersion?.versionId || "", wall3);
} else {
-
// SOCKET
const data2 = {
wallData: wall3,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:add', data2);
+ socket.emit("v1:model-Wall:add", data2);
}
}
@@ -241,8 +236,8 @@ function WallCreator() {
insideMaterial: outsideMaterial,
wallThickness: wallThickness,
wallHeight: wallHeight,
- decals: []
- }
+ decals: [],
+ };
addWall(wall1);
@@ -250,20 +245,19 @@ function WallCreator() {
if (!socket?.connected) {
// API
- upsertWallApi(projectId, selectedVersion?.versionId || '', wall1);
+ upsertWallApi(projectId, selectedVersion?.versionId || "", wall1);
} else {
-
// SOCKET
const data = {
wallData: wall1,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:add', data);
+ socket.emit("v1:model-Wall:add", data);
}
}
@@ -274,8 +268,8 @@ function WallCreator() {
insideMaterial: outsideMaterial,
wallThickness: wallThickness,
wallHeight: wallHeight,
- decals: []
- }
+ decals: [],
+ };
addWall(wall2);
@@ -283,20 +277,19 @@ function WallCreator() {
if (!socket?.connected) {
// API
- upsertWallApi(projectId, selectedVersion?.versionId || '', wall2);
+ upsertWallApi(projectId, selectedVersion?.versionId || "", wall2);
} else {
-
// SOCKET
const data1 = {
wallData: wall2,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:add', data1);
+ socket.emit("v1:model-Wall:add", data1);
}
}
@@ -307,60 +300,62 @@ function WallCreator() {
insideMaterial: outsideMaterial,
wallThickness: wallThickness,
wallHeight: wallHeight,
- decals: []
- }
+ decals: [],
+ };
addWall(wall3);
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Create',
+ actionType: "Lines-Create",
points: [
{
- type: 'Wall',
+ type: "Wall",
lineData: wall3,
timeStamp: new Date().toISOString(),
- }, {
- type: 'Wall',
+ },
+ {
+ type: "Wall",
lineData: wall1,
timeStamp: new Date().toISOString(),
- }, {
- type: 'Wall',
+ },
+ {
+ type: "Wall",
lineData: wall2,
timeStamp: new Date().toISOString(),
- }
- ]
- }, {
- actionType: 'Line-Delete',
+ },
+ ],
+ },
+ {
+ actionType: "Line-Delete",
point: {
- type: 'Wall',
+ type: "Wall",
lineData: wall,
timeStamp: new Date().toISOString(),
- }
- }
+ },
+ },
],
- })
+ });
if (projectId) {
if (!socket?.connected) {
// API
- upsertWallApi(projectId, selectedVersion?.versionId || '', wall3);
+ upsertWallApi(projectId, selectedVersion?.versionId || "", wall3);
} else {
-
// SOCKET
const data3 = {
wallData: wall3,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:add', data3);
+ socket.emit("v1:model-Wall:add", data3);
}
}
@@ -373,9 +368,9 @@ function WallCreator() {
const newPoint: Point = {
pointUuid: THREE.MathUtils.generateUUID(),
- pointType: 'Wall',
+ pointType: "Wall",
position: [position.x, position.y, position.z],
- layer: activeLayer
+ layer: activeLayer,
};
if (snappedPosition && snappedPoint) {
@@ -384,7 +379,9 @@ function WallCreator() {
newPoint.layer = snappedPoint.layer;
}
- if (snappedPoint && snappedPoint.pointUuid === tempPoints[0]?.pointUuid) { return }
+ if (snappedPoint && snappedPoint.pointUuid === tempPoints[0]?.pointUuid) {
+ return;
+ }
if (snappedPosition && !snappedPoint) {
newPoint.position = snappedPosition;
@@ -410,49 +407,47 @@ function WallCreator() {
insideMaterial: outsideMaterial,
wallThickness: wallThickness,
wallHeight: wallHeight,
- decals: []
- }
+ decals: [],
+ };
addWall(wall);
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Line-Create',
+ actionType: "Line-Create",
point: {
- type: 'Wall',
+ type: "Wall",
lineData: wall,
timeStamp: new Date().toISOString(),
- }
- }
+ },
+ },
],
- })
+ });
if (projectId) {
if (!socket?.connected) {
// API
- upsertWallApi(projectId, selectedVersion?.versionId || '', wall);
+ upsertWallApi(projectId, selectedVersion?.versionId || "", wall);
} else {
-
// SOCKET
const data = {
wallData: wall,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:add', data);
+ socket.emit("v1:model-Wall:add", data);
}
}
setTempPoints([newPoint]);
}
-
};
const onContext = (event: any) => {
@@ -494,21 +489,19 @@ function WallCreator() {
return (
<>
- {toggleView &&
+ {toggleView && (
<>
-
+
{tempPoints.map((point) => (
))}
- {tempPoints.length > 0 &&
-
- }
+ {tempPoints.length > 0 && }
>
- }
+ )}
>
- )
+ );
}
-export default WallCreator
\ No newline at end of file
+export default WallCreator;
diff --git a/app/src/modules/builder/wall/wallGroup.tsx b/app/src/modules/builder/wall/wallGroup.tsx
index 3561751..de9ee35 100644
--- a/app/src/modules/builder/wall/wallGroup.tsx
+++ b/app/src/modules/builder/wall/wallGroup.tsx
@@ -1,56 +1,54 @@
-import { useEffect } from 'react';
-import { useActiveTool, useToggleView } from '../../../store/builder/store';
-import { useBuilderStore } from '../../../store/builder/useBuilderStore';
-import { useVersionContext } from '../version/versionContext';
-import { useSceneContext } from '../../scene/sceneContext';
-import { useParams } from 'react-router-dom';
-import useModuleStore from '../../../store/useModuleStore';
-import WallCreator from './wallCreator/wallCreator';
-import WallInstances from './Instances/wallInstances';
+import { useEffect } from "react";
+import { useActiveTool, useToggleView } from "../../../store/builder/store";
+import { useBuilderStore } from "../../../store/builder/useBuilderStore";
+import { useSceneContext } from "../../scene/sceneContext";
+import { useParams } from "react-router-dom";
+import useModuleStore from "../../../store/ui/useModuleStore";
+import WallCreator from "./wallCreator/wallCreator";
+import WallInstances from "./Instances/wallInstances";
-import { getWallsApi } from '../../../services/factoryBuilder/wall/getWallsApi';
+import { getWallsApi } from "../../../services/factoryBuilder/wall/getWallsApi";
function WallGroup() {
const { toggleView } = useToggleView();
const { setSelectedWall, setSelectedDecal } = useBuilderStore();
const { activeModule } = useModuleStore();
const { activeTool } = useActiveTool();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { wallStore } = useSceneContext();
+ const { wallStore, versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
const { setWalls } = wallStore();
const { projectId } = useParams();
useEffect(() => {
- if (toggleView || activeModule !== 'builder') {
+ if (toggleView || activeModule !== "builder") {
setSelectedWall(null);
setSelectedDecal(null);
}
- }, [toggleView, activeModule, activeTool])
+ }, [toggleView, activeModule, activeTool]);
useEffect(() => {
if (projectId && selectedVersion) {
- getWallsApi(projectId, selectedVersion?.versionId || '').then((walls) => {
- if (walls && walls.length > 0) {
- setWalls(walls);
- } else {
- setWalls([]);
- }
- }).catch((err) => {
- console.log(err);
- })
+ getWallsApi(projectId, selectedVersion?.versionId || "")
+ .then((walls) => {
+ if (walls && walls.length > 0) {
+ setWalls(walls);
+ } else {
+ setWalls([]);
+ }
+ })
+ .catch((err) => {
+ console.log(err);
+ });
}
- }, [projectId, selectedVersion?.versionId])
+ }, [projectId, selectedVersion?.versionId]);
return (
<>
-
-
>
- )
+ );
}
-export default WallGroup
\ No newline at end of file
+export default WallGroup;
diff --git a/app/src/modules/builder/wallAsset/Instances/Instance/eventHandler/useWallAssetEventHandler.ts b/app/src/modules/builder/wallAsset/Instances/Instance/eventHandler/useWallAssetEventHandler.ts
new file mode 100644
index 0000000..e755515
--- /dev/null
+++ b/app/src/modules/builder/wallAsset/Instances/Instance/eventHandler/useWallAssetEventHandler.ts
@@ -0,0 +1,211 @@
+import * as THREE from 'three';
+import { useCallback, useEffect, useRef } from 'react';
+import { ThreeEvent, useThree } from '@react-three/fiber';
+import { useParams } from 'react-router-dom';
+import { useActiveTool, useSocketStore, useToggleView } from '../../../../../../store/builder/store';
+import useModuleStore from '../../../../../../store/ui/useModuleStore';
+import { useSceneContext } from '../../../../../scene/sceneContext';
+import { useBuilderStore } from '../../../../../../store/builder/useBuilderStore';
+import { getUserData } from '../../../../../../functions/getUserData';
+import closestPointOnLineSegment from '../../../../line/helpers/getClosestPointOnLineSegment';
+import { upsertWallAssetApi } from '../../../../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
+import { deleteWallAssetApi } from '../../../../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi';
+
+export function useWallAssetEventHandler({
+ wallAsset,
+ groupRef,
+ wall,
+}: {
+ wallAsset: WallAsset;
+ groupRef: React.RefObject;
+ wall: Wall | undefined;
+}) {
+ const { socket } = useSocketStore();
+ const { raycaster, pointer, camera, scene, controls, gl } = useThree();
+ const { wallAssetStore, versionStore } = useSceneContext();
+ const { updateWallAsset, removeWallAsset, getWallAssetById } = wallAssetStore();
+ const { toggleView } = useToggleView();
+ const { activeTool } = useActiveTool();
+ const { activeModule } = useModuleStore();
+ const { selectedWallAsset, setSelectedWallAsset, setDeletableWallAsset, deletableWallAsset } = useBuilderStore();
+ const { selectedVersion } = versionStore();
+ const { userId, organization } = getUserData();
+ const { projectId } = useParams();
+
+ const draggingRef = useRef(false);
+
+ useEffect(() => {
+ const canvasElement = gl.domElement;
+
+ const onPointerUp = (e: PointerEvent) => {
+ if (draggingRef.current) {
+ draggingRef.current = false;
+ if (controls) {
+ (controls as any).enabled = true;
+ }
+
+ if (selectedWallAsset) {
+ const updatedWallAsset = getWallAssetById(wallAsset.modelUuid);
+
+ if (projectId && updatedWallAsset) {
+ if (!socket?.connected) {
+
+ // API
+
+ upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
+ } else {
+
+ // SOCKET
+
+ const data = {
+ wallAssetData: updatedWallAsset,
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization
+ }
+ socket.emit('v1:wall-asset:add', data);
+ }
+ }
+ }
+ }
+ };
+
+ const onPointerMove = (e: any) => {
+ if (!draggingRef.current || !wall || !selectedWallAsset) return;
+ if (controls) {
+ (controls as any).enabled = false;
+ }
+
+ pointer.x = (e.clientX / window.innerWidth) * 2 - 1;
+ pointer.y = -(e.clientY / window.innerHeight) * 2 + 1;
+
+ raycaster.setFromCamera(pointer, camera);
+ const intersects = raycaster.intersectObjects(scene.children, true);
+ const intersect = intersects.find((i: any) => i.object.name.includes('WallReference'));
+
+ if (intersect?.object.userData.wallUuid) {
+ const newPoint = closestPointOnLineSegment(
+ new THREE.Vector3(intersect.point.x, 0, intersect.point.z),
+ new THREE.Vector3(...intersect.object.userData.points[0].position),
+ new THREE.Vector3(...intersect.object.userData.points[1].position)
+ );
+
+ const wallRotation = intersect.object.rotation.clone();
+
+ updateWallAsset(wallAsset.modelUuid, {
+ wallUuid: intersect.object.userData.wallUuid,
+ position: [newPoint.x, wallAsset.wallAssetType === 'fixedMove' ? 0 : intersect.point.y, newPoint.z],
+ rotation: [wallRotation.x, wallRotation.y, wallRotation.z],
+ });
+ }
+ };
+
+ if (selectedWallAsset && !toggleView && activeModule === 'builder') {
+ canvasElement.addEventListener('mousemove', onPointerMove);
+ canvasElement.addEventListener('pointerup', onPointerUp);
+ }
+
+ return () => {
+ canvasElement.removeEventListener('mousemove', onPointerMove);
+ canvasElement.removeEventListener('pointerup', onPointerUp);
+ };
+ }, [gl, camera, toggleView, activeModule, selectedWallAsset, socket, wall, wallAsset]);
+
+ const handlePointerEnter = useCallback((evt: ThreeEvent) => {
+ if (!toggleView) {
+ evt.stopPropagation();
+ let currentObject = evt.object;
+ while (currentObject) {
+ if (currentObject.userData.wallUuid) {
+ break;
+ }
+ currentObject = currentObject.parent as THREE.Object3D;
+ }
+ if (activeTool === "delete" && activeModule === 'builder') {
+ if (deletableWallAsset && deletableWallAsset.userData.modelUuid === wallAsset.modelUuid) {
+ return;
+ } else {
+ setDeletableWallAsset(currentObject);
+ }
+ }
+ }
+ }, [activeTool, activeModule, deletableWallAsset, toggleView]);
+
+ const handlePointerLeave = useCallback((evt: ThreeEvent) => {
+ if (!toggleView) {
+ evt.stopPropagation();
+ if (evt.intersections.length === 0 && activeTool === "delete" && deletableWallAsset && deletableWallAsset.userData.modelUuid === wallAsset.modelUuid) {
+ setDeletableWallAsset(null);
+ }
+ }
+ }, [activeTool, deletableWallAsset, toggleView]);
+
+ const handlePointerDown = useCallback((e: ThreeEvent) => {
+ if (!toggleView && activeModule === 'builder' && selectedWallAsset && selectedWallAsset.userData.modelUuid === wallAsset.modelUuid) {
+ draggingRef.current = true;
+ e.stopPropagation();
+ setSelectedWallAsset(groupRef.current);
+ if (controls) {
+ (controls as any).enabled = false;
+ }
+ }
+ }, [toggleView, activeModule, selectedWallAsset, wallAsset]);
+
+ const handleClick = useCallback((e: ThreeEvent) => {
+ if (!toggleView && activeModule === 'builder' && activeTool !== 'delete') {
+ if (e.object) {
+ e.stopPropagation();
+ let currentObject = e.object;
+ while (currentObject) {
+ if (currentObject.userData.wallUuid) {
+ break;
+ }
+ currentObject = currentObject.parent as THREE.Object3D;
+ }
+ setSelectedWallAsset(currentObject);
+ }
+ } else if (!toggleView && activeModule === 'builder' && activeTool === 'delete') {
+ if (activeTool === 'delete' && deletableWallAsset && deletableWallAsset.userData.modelUuid === wallAsset.modelUuid) {
+ const removedWallAsset = removeWallAsset(wallAsset.modelUuid);
+
+ if (projectId && removedWallAsset) {
+ if (!socket?.connected) {
+
+ // API
+
+ deleteWallAssetApi(projectId, selectedVersion?.versionId || '', removedWallAsset.modelUuid, removedWallAsset.wallUuid);
+ } else {
+
+ // SOCKET
+
+ const data = {
+ projectId: projectId,
+ versionId: selectedVersion?.versionId || '',
+ userId: userId,
+ organization: organization,
+ modelUuid: removedWallAsset.modelUuid,
+ wallUuid: removedWallAsset.wallUuid
+ }
+ socket.emit('v1:wall-asset:delete', data);
+ }
+ }
+ }
+ }
+ }, [toggleView, activeModule, activeTool, wallAsset, deletableWallAsset, socket]);
+
+ const handlePointerMissed = useCallback(() => {
+ if (selectedWallAsset && selectedWallAsset.userData.modelUuid === wallAsset.modelUuid) {
+ setSelectedWallAsset(null);
+ }
+ }, [selectedWallAsset, wallAsset]);
+
+ return {
+ handlePointerDown,
+ handleClick,
+ handlePointerMissed,
+ handlePointerEnter,
+ handlePointerLeave,
+ draggingRef
+ };
+}
\ No newline at end of file
diff --git a/app/src/modules/builder/wallAsset/Instances/Instance/wallAssetInstance.tsx b/app/src/modules/builder/wallAsset/Instances/Instance/wallAssetInstance.tsx
index 73503ff..7d88a96 100644
--- a/app/src/modules/builder/wallAsset/Instances/Instance/wallAssetInstance.tsx
+++ b/app/src/modules/builder/wallAsset/Instances/Instance/wallAssetInstance.tsx
@@ -1,42 +1,22 @@
import * as THREE from 'three';
-import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
-import { ThreeEvent, useThree } from '@react-three/fiber';
+import { useEffect, useMemo, useRef, useState } from 'react';
import { Base, Geometry, Subtraction } from '@react-three/csg';
-import { retrieveGLTF, storeGLTF } from '../../../../../utils/indexDB/idbUtils';
import { GLTF, GLTFLoader } from 'three/examples/jsm/loaders/GLTFLoader';
import { DRACOLoader } from 'three/examples/jsm/loaders/DRACOLoader';
-import useModuleStore from '../../../../../store/useModuleStore';
+import { retrieveGLTF, storeGLTF } from '../../../../../utils/indexDB/idbUtils';
import { useSceneContext } from '../../../../scene/sceneContext';
-import { useBuilderStore } from '../../../../../store/builder/useBuilderStore';
-import { useActiveTool, useSocketStore, useToggleView } from '../../../../../store/builder/store';
-import { useParams } from 'react-router-dom';
-import { useVersionContext } from '../../../version/versionContext';
-import { getUserData } from '../../../../../functions/getUserData';
-import closestPointOnLineSegment from '../../../line/helpers/getClosestPointOnLineSegment';
-import { upsertWallAssetApi } from '../../../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
-import { deleteWallAssetApi } from '../../../../../services/factoryBuilder/asset/wallAsset/deleteWallAssetApi';
+import { useWallAssetEventHandler } from './eventHandler/useWallAssetEventHandler';
function WallAssetInstance({ wallAsset }: { readonly wallAsset: WallAsset }) {
const url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_MARKETPLACE_URL}`;
- const { socket } = useSocketStore();
- const { raycaster, pointer, camera, scene, controls, gl } = useThree();
- const { wallStore, wallAssetStore } = useSceneContext();
+ const { wallStore } = useSceneContext();
const { walls, getWallById } = wallStore();
- const { updateWallAsset, removeWallAsset, getWallAssetById } = wallAssetStore();
- const { toggleView } = useToggleView();
- const { activeTool } = useActiveTool();
- const { activeModule } = useModuleStore();
- const { selectedWallAsset, setSelectedWallAsset, setDeletableWallAsset, deletableWallAsset } = useBuilderStore();
const [gltfScene, setGltfScene] = useState(null);
const [boundingBox, setBoundingBox] = useState(null);
const groupRef = useRef(null);
const wall = useMemo(() => getWallById(wallAsset.wallUuid), [getWallById, wallAsset.wallUuid, walls]);
- const draggingRef = useRef(false);
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { userId, organization } = getUserData();
- const { projectId } = useParams();
+ const { handlePointerDown, handleClick, handlePointerMissed, handlePointerEnter, handlePointerLeave } = useWallAssetEventHandler({ wallAsset, groupRef, wall });
useEffect(() => {
const loader = new GLTFLoader();
@@ -112,130 +92,6 @@ function WallAssetInstance({ wallAsset }: { readonly wallAsset: WallAsset }) {
}, []);
- useEffect(() => {
- const canvasElement = gl.domElement;
-
- const onPointerUp = (e: PointerEvent) => {
- if (draggingRef.current) {
- draggingRef.current = false;
- if (controls) {
- (controls as any).enabled = true;
- }
-
- if (selectedWallAsset) {
- const updatedWallAsset = getWallAssetById(wallAsset.modelUuid);
-
- if (projectId && updatedWallAsset) {
- if (!socket?.connected) {
-
- // API
-
- upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
- } else {
-
- // SOCKET
-
- const data = {
- wallAssetData: updatedWallAsset,
- projectId: projectId,
- versionId: selectedVersion?.versionId || '',
- userId: userId,
- organization: organization
- }
-
- socket.emit('v1:wall-asset:add', data);
- }
- }
- }
- }
- };
-
- const onPointerMove = (e: any) => {
- if (!draggingRef.current || !wall || !selectedWallAsset) return;
- if (controls) {
- (controls as any).enabled = false;
- }
- pointer.x = (e.clientX / window.innerWidth) * 2 - 1;
- pointer.y = -(e.clientY / window.innerHeight) * 2 + 1;
-
- raycaster.setFromCamera(pointer, camera);
- const intersects = raycaster.intersectObjects(scene.children, true);
- const intersect = intersects.find((i: any) => i.object.name.includes('WallReference'));
-
- if (intersect?.object.userData.wallUuid) {
- const newPoint = closestPointOnLineSegment(
- new THREE.Vector3(intersect.point.x, 0, intersect.point.z),
- new THREE.Vector3(...intersect.object.userData.points[0].position),
- new THREE.Vector3(...intersect.object.userData.points[1].position)
- );
-
- const wallRotation = intersect.object.rotation.clone();
-
- updateWallAsset(wallAsset.modelUuid, {
- wallUuid: intersect.object.userData.wallUuid,
- position: [newPoint.x, wallAsset.wallAssetType === 'fixedMove' ? 0 : intersect.point.y, newPoint.z],
- rotation: [wallRotation.x, wallRotation.y, wallRotation.z],
- });
- }
- };
-
- if (selectedWallAsset && !toggleView && activeModule === 'builder') {
- canvasElement.addEventListener('mousemove', onPointerMove);
- canvasElement.addEventListener('pointerup', onPointerUp);
- }
-
- return () => {
- canvasElement.removeEventListener('mousemove', onPointerMove);
- canvasElement.removeEventListener('pointerup', onPointerUp);
- };
-
- }, [gl, camera, toggleView, activeModule, selectedWallAsset, socket])
-
- const handlePointerClick = useCallback((wallAsset: WallAsset) => {
- if (activeTool === 'delete' && deletableWallAsset && deletableWallAsset.userData.modelUuid === wallAsset.modelUuid) {
- const removedWallAsset = removeWallAsset(wallAsset.modelUuid);
-
- if (projectId && removedWallAsset) {
- if (!socket?.connected) {
-
- // API
-
- deleteWallAssetApi(projectId, selectedVersion?.versionId || '', removedWallAsset.modelUuid, removedWallAsset.wallUuid);
- } else {
-
- // SOCKET
-
- const data = {
- projectId: projectId,
- versionId: selectedVersion?.versionId || '',
- userId: userId,
- organization: organization,
- modelUuid: removedWallAsset.modelUuid,
- wallUuid: removedWallAsset.wallUuid
- }
-
- socket.emit('v1:wall-asset:delete', data);
- }
- }
- }
- }, [activeTool, activeModule, deletableWallAsset, socket])
-
- const handlePointerOver = useCallback((wallAsset: WallAsset, currentObject: THREE.Object3D) => {
- if (activeTool === "delete" && activeModule === 'builder') {
- if (deletableWallAsset && deletableWallAsset.userData.modelUuid === wallAsset.modelUuid) {
- return;
- } else {
- setDeletableWallAsset(currentObject);
- }
- }
- }, [activeTool, activeModule, deletableWallAsset]);
-
- const handlePointerOut = useCallback((evt: ThreeEvent, wallAsset: WallAsset) => {
- if (evt.intersections.length === 0 && activeTool === "delete" && deletableWallAsset && deletableWallAsset.userData.modelUuid === wallAsset.modelUuid) {
- setDeletableWallAsset(null);
- }
- }, [activeTool, deletableWallAsset]);
-
if (!gltfScene || !boundingBox) { return null }
const size = new THREE.Vector3();
boundingBox.getSize(size);
@@ -259,57 +115,11 @@ function WallAssetInstance({ wallAsset }: { readonly wallAsset: WallAsset }) {
{gltfScene && (
{
- if (!toggleView && activeModule === 'builder' && selectedWallAsset && selectedWallAsset.userData.modelUuid === wallAsset.modelUuid) {
- draggingRef.current = true;
- e.stopPropagation();
- setSelectedWallAsset(groupRef.current);
- if (controls) {
- (controls as any).enabled = false;
- }
- }
- }}
- onClick={(e) => {
- if (!toggleView && activeModule === 'builder' && activeTool !== 'delete') {
- if (e.object) {
- e.stopPropagation();
- let currentObject = e.object as THREE.Object3D;
- while (currentObject) {
- if (currentObject.userData.wallUuid) {
- break;
- }
- currentObject = currentObject.parent as THREE.Object3D;
- }
- setSelectedWallAsset(currentObject);
- }
- } else if (!toggleView && activeModule === 'builder' && activeTool === 'delete') {
- handlePointerClick(wallAsset);
- }
- }}
- onPointerMissed={() => {
- if (selectedWallAsset && selectedWallAsset.userData.modelUuid === wallAsset.modelUuid) {
- setSelectedWallAsset(null);
- }
- }}
- onPointerEnter={(e) => {
- if (!toggleView) {
- e.stopPropagation();
- let currentObject = e.object as THREE.Object3D;
- while (currentObject) {
- if (currentObject.userData.wallUuid) {
- break;
- }
- currentObject = currentObject.parent as THREE.Object3D;
- }
- handlePointerOver(wallAsset, currentObject);
- }
- }}
- onPointerLeave={(e) => {
- if (!toggleView) {
- e.stopPropagation();
- handlePointerOut(e, wallAsset);
- }
- }}
+ onPointerDown={handlePointerDown}
+ onClick={handleClick}
+ onPointerMissed={handlePointerMissed}
+ onPointerEnter={handlePointerEnter}
+ onPointerLeave={handlePointerLeave}
userData={wallAsset}
>
diff --git a/app/src/modules/builder/wallAsset/wallAssetCreator.tsx b/app/src/modules/builder/wallAsset/wallAssetCreator.tsx
index effc0ed..8e6f0d6 100644
--- a/app/src/modules/builder/wallAsset/wallAssetCreator.tsx
+++ b/app/src/modules/builder/wallAsset/wallAssetCreator.tsx
@@ -1,26 +1,24 @@
-import { useThree } from '@react-three/fiber';
-import { useEffect } from 'react'
-import useModuleStore from '../../../store/useModuleStore';
-import { useSelectedItem, useSocketStore, useToggleView } from '../../../store/builder/store';
-import { MathUtils, Vector3 } from 'three';
-import { useSceneContext } from '../../scene/sceneContext';
-import { useParams } from 'react-router-dom';
-import { useVersionContext } from '../version/versionContext';
-import { getUserData } from '../../../functions/getUserData';
-import closestPointOnLineSegment from '../line/helpers/getClosestPointOnLineSegment';
+import { useThree } from "@react-three/fiber";
+import { useEffect } from "react";
+import useModuleStore from "../../../store/ui/useModuleStore";
+import { useSelectedItem, useSocketStore, useToggleView } from "../../../store/builder/store";
+import { MathUtils, Vector3 } from "three";
+import { useSceneContext } from "../../scene/sceneContext";
+import { useParams } from "react-router-dom";
+import { getUserData } from "../../../functions/getUserData";
+import closestPointOnLineSegment from "../line/helpers/getClosestPointOnLineSegment";
-import { upsertWallAssetApi } from '../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi';
+import { upsertWallAssetApi } from "../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi";
function WallAssetCreator() {
const { socket } = useSocketStore();
const { pointer, camera, raycaster, scene, gl } = useThree();
const { toggleView } = useToggleView();
const { activeModule } = useModuleStore();
- const { wallAssetStore } = useSceneContext();
+ const { wallAssetStore, versionStore } = useSceneContext();
const { addWallAsset } = wallAssetStore();
const { selectedItem, setSelectedItem } = useSelectedItem();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { selectedVersion } = versionStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
@@ -29,21 +27,17 @@ function WallAssetCreator() {
const onDrop = (event: DragEvent) => {
if (!event.dataTransfer?.files[0]) return;
- if (selectedItem.id !== "" && event.dataTransfer?.files[0] && selectedItem.category === 'Fenestration') {
+ if (selectedItem.id !== "" && event.dataTransfer?.files[0] && selectedItem.category === "Fenestration") {
pointer.x = (event.clientX / window.innerWidth) * 2 - 1;
pointer.y = -(event.clientY / window.innerHeight) * 2 + 1;
raycaster.setFromCamera(pointer, camera);
const intersects = raycaster.intersectObjects(scene.children, true);
- const intersect = intersects.find((intersect) => intersect.object.name.includes('WallReference'));
+ const intersect = intersects.find((intersect) => intersect.object.name.includes("WallReference"));
if (intersect) {
const wall = intersect.object.userData as Wall;
- const closestPoint = closestPointOnLineSegment(
- new Vector3(intersect.point.x, 0, intersect.point.z),
- new Vector3(...wall.points[0].position),
- new Vector3(...wall.points[1].position)
- )
+ const closestPoint = closestPointOnLineSegment(new Vector3(intersect.point.x, 0, intersect.point.z), new Vector3(...wall.points[0].position), new Vector3(...wall.points[1].position));
const wallRotation = intersect.object.rotation.clone();
@@ -63,43 +57,37 @@ function WallAssetCreator() {
addWallAsset(newWallAsset);
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertWallAssetApi(projectId, selectedVersion?.versionId || '', newWallAsset);
+ upsertWallAssetApi(projectId, selectedVersion?.versionId || "", newWallAsset);
} else {
-
// SOCKET
const data = {
wallAssetData: newWallAsset,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:wall-asset:add', data);
+ socket.emit("v1:wall-asset:add", data);
}
}
}
}
};
- if (!toggleView && activeModule === 'builder') {
- canvasElement.addEventListener('drop', onDrop);
+ if (!toggleView && activeModule === "builder") {
+ canvasElement.addEventListener("drop", onDrop);
}
return () => {
- canvasElement.removeEventListener('drop', onDrop);
+ canvasElement.removeEventListener("drop", onDrop);
};
-
}, [gl, camera, toggleView, activeModule, socket, selectedItem, setSelectedItem]);
- return (
- <>
- >
- )
+ return <>>;
}
-export default WallAssetCreator
\ No newline at end of file
+export default WallAssetCreator;
diff --git a/app/src/modules/builder/wallAsset/wallAssetGroup.tsx b/app/src/modules/builder/wallAsset/wallAssetGroup.tsx
index 95e2e90..c2d40ce 100644
--- a/app/src/modules/builder/wallAsset/wallAssetGroup.tsx
+++ b/app/src/modules/builder/wallAsset/wallAssetGroup.tsx
@@ -1,55 +1,53 @@
-import { useEffect } from 'react';
-import { useToggleView, useToolMode } from '../../../store/builder/store';
-import { useBuilderStore } from '../../../store/builder/useBuilderStore';
-import { useVersionContext } from '../version/versionContext';
-import { useSceneContext } from '../../scene/sceneContext';
-import { useParams } from 'react-router-dom';
-import useModuleStore from '../../../store/useModuleStore';
-import WallAssetCreator from './wallAssetCreator'
-import WallAssetInstances from './Instances/wallAssetInstances'
-import { getWallAssetsApi } from '../../../services/factoryBuilder/asset/wallAsset/getWallAssetsApi';
+import { useEffect } from "react";
+import { useToggleView, useToolMode } from "../../../store/builder/store";
+import { useBuilderStore } from "../../../store/builder/useBuilderStore";
+import { useSceneContext } from "../../scene/sceneContext";
+import { useParams } from "react-router-dom";
+import useModuleStore from "../../../store/ui/useModuleStore";
+import WallAssetCreator from "./wallAssetCreator";
+import WallAssetInstances from "./Instances/wallAssetInstances";
+import { getWallAssetsApi } from "../../../services/factoryBuilder/asset/wallAsset/getWallAssetsApi";
function WallAssetGroup() {
const { toggleView } = useToggleView();
const { setSelectedWallAsset, setDeletableWallAsset } = useBuilderStore();
const { activeModule } = useModuleStore();
const { toolMode } = useToolMode();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { wallAssetStore } = useSceneContext();
+ const { wallAssetStore, versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
const { setWallAssets } = wallAssetStore();
const { projectId } = useParams();
useEffect(() => {
- if (toggleView || activeModule !== 'builder' || toolMode !== 'cursor') {
+ if (toggleView || activeModule !== "builder" || toolMode !== "cursor") {
setSelectedWallAsset(null);
}
setDeletableWallAsset(null);
- }, [toggleView, activeModule, toolMode])
+ }, [toggleView, activeModule, toolMode]);
useEffect(() => {
if (projectId && selectedVersion) {
- getWallAssetsApi(projectId, selectedVersion?.versionId || '').then((wallAssets) => {
- if (wallAssets && wallAssets.length > 0) {
- setWallAssets(wallAssets);
- } else {
- setWallAssets([]);
- }
- }).catch((err) => {
- console.log(err);
- })
+ getWallAssetsApi(projectId, selectedVersion?.versionId || "")
+ .then((wallAssets) => {
+ if (wallAssets && wallAssets.length > 0) {
+ setWallAssets(wallAssets);
+ } else {
+ setWallAssets([]);
+ }
+ })
+ .catch((err) => {
+ console.log(err);
+ });
}
- }, [projectId, selectedVersion?.versionId])
+ }, [projectId, selectedVersion?.versionId]);
return (
<>
-
-
>
- )
+ );
}
-export default WallAssetGroup
\ No newline at end of file
+export default WallAssetGroup;
diff --git a/app/src/modules/builder/zone/zoneCreator/zoneCreator.tsx b/app/src/modules/builder/zone/zoneCreator/zoneCreator.tsx
index c7cce3c..a0c7767 100644
--- a/app/src/modules/builder/zone/zoneCreator/zoneCreator.tsx
+++ b/app/src/modules/builder/zone/zoneCreator/zoneCreator.tsx
@@ -1,16 +1,15 @@
-import * as THREE from 'three'
-import { useEffect, useMemo, useRef, useState } from 'react'
-import { useThree } from '@react-three/fiber';
-import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from '../../../../store/builder/store';
-import { useSceneContext } from '../../../scene/sceneContext';
-import { useBuilderStore } from '../../../../store/builder/useBuilderStore';
-import { useParams } from 'react-router-dom';
-import { useVersionContext } from '../../version/versionContext';
-import { getUserData } from '../../../../functions/getUserData';
-import ReferencePoint from '../../point/reference/referencePoint';
-import ReferenceZone from './referenceZone';
+import * as THREE from "three";
+import { useEffect, useMemo, useRef, useState } from "react";
+import { useThree } from "@react-three/fiber";
+import { useActiveLayer, useSocketStore, useToggleView, useToolMode } from "../../../../store/builder/store";
+import { useSceneContext } from "../../../scene/sceneContext";
+import { useBuilderStore } from "../../../../store/builder/useBuilderStore";
+import { useParams } from "react-router-dom";
+import { getUserData } from "../../../../functions/getUserData";
+import ReferencePoint from "../../point/reference/referencePoint";
+import ReferenceZone from "./referenceZone";
-import { upsertZoneApi } from '../../../../services/factoryBuilder/zone/upsertZoneApi';
+import { upsertZoneApi } from "../../../../services/factoryBuilder/zone/upsertZoneApi";
function ZoneCreator() {
const { scene, camera, raycaster, gl, pointer } = useThree();
@@ -19,13 +18,12 @@ function ZoneCreator() {
const { toolMode } = useToolMode();
const { activeLayer } = useActiveLayer();
const { socket } = useSocketStore();
- const { zoneStore, undoRedo2DStore } = useSceneContext();
+ const { zoneStore, undoRedo2DStore, versionStore } = useSceneContext();
const { addZone, getZonePointById } = zoneStore();
const { push2D } = undoRedo2DStore();
const drag = useRef(false);
const isLeftMouseDown = useRef(false);
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { selectedVersion } = versionStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
@@ -63,7 +61,7 @@ function ZoneCreator() {
let position = raycaster.ray.intersectPlane(plane, intersectionPoint);
if (!position) return;
- const pointIntersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Zone-Point');
+ const pointIntersects = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === "Zone-Point");
// const zoneIntersect = raycaster.intersectObjects(scene.children).find((intersect) => intersect.object.name === 'Zone-Line');
@@ -73,9 +71,9 @@ function ZoneCreator() {
const newPoint: Point = {
pointUuid: THREE.MathUtils.generateUUID(),
- pointType: 'Zone',
+ pointType: "Zone",
position: [position.x, position.y, position.z],
- layer: activeLayer
+ layer: activeLayer,
};
if (snappedPosition && snappedPoint) {
@@ -84,7 +82,9 @@ function ZoneCreator() {
newPoint.layer = snappedPoint.layer;
}
- if (snappedPoint && snappedPoint.pointUuid === tempPoints[tempPoints.length - 1]?.pointUuid) { return }
+ if (snappedPoint && snappedPoint.pointUuid === tempPoints[tempPoints.length - 1]?.pointUuid) {
+ return;
+ }
if (snappedPosition && !snappedPoint) {
newPoint.position = snappedPosition;
@@ -98,50 +98,48 @@ function ZoneCreator() {
zoneColor,
zoneHeight,
viewPortPosition: [0, 0, 0],
- viewPortTarget: [0, 0, 0]
+ viewPortTarget: [0, 0, 0],
};
addZone(zone);
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Line-Create',
+ actionType: "Line-Create",
point: {
- type: 'Zone',
+ type: "Zone",
lineData: zone,
timeStamp: new Date().toISOString(),
- }
- }
+ },
+ },
],
- })
+ });
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
+ upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
} else {
-
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:zone:add', data);
+ socket.emit("v1:zone:add", data);
}
}
setTempPoints([]);
setIsCreating(false);
- } else if (isCreating && snappedPoint && !tempPoints.some(p => p.pointUuid === snappedPoint.pointUuid)) {
- setTempPoints(prev => [...prev, newPoint]);
+ } else if (isCreating && snappedPoint && !tempPoints.some((p) => p.pointUuid === snappedPoint.pointUuid)) {
+ setTempPoints((prev) => [...prev, newPoint]);
setIsCreating(true);
} else if (pointIntersects) {
if (tempPoints.length > 2 && isCreating && pointIntersects.object.uuid === tempPoints[0].pointUuid) {
@@ -152,54 +150,52 @@ function ZoneCreator() {
zoneColor,
zoneHeight,
viewPortPosition: [0, 0, 0],
- viewPortTarget: [0, 0, 0]
+ viewPortTarget: [0, 0, 0],
};
addZone(zone);
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Line-Create',
+ actionType: "Line-Create",
point: {
- type: 'Zone',
+ type: "Zone",
lineData: zone,
timeStamp: new Date().toISOString(),
- }
- }
+ },
+ },
],
- })
+ });
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
+ upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
} else {
-
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:zone:add', data);
+ socket.emit("v1:zone:add", data);
}
}
setTempPoints([]);
setIsCreating(false);
- } else if (tempPoints.length === 0 || (tempPoints.length > 1 && !tempPoints.slice(1).some(p => p.pointUuid === pointIntersects.object.uuid))) {
+ } else if (tempPoints.length === 0 || (tempPoints.length > 1 && !tempPoints.slice(1).some((p) => p.pointUuid === pointIntersects.object.uuid))) {
tempPoints.push(pointIntersects.object.userData as Point);
setIsCreating(true);
}
} else {
- setTempPoints(prev => [...prev, newPoint]);
+ setTempPoints((prev) => [...prev, newPoint]);
setIsCreating(true);
}
};
@@ -215,44 +211,42 @@ function ZoneCreator() {
zoneColor,
zoneHeight,
viewPortPosition: [0, 0, 0],
- viewPortTarget: [0, 0, 0]
+ viewPortTarget: [0, 0, 0],
};
addZone(zone);
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Line-Create',
+ actionType: "Line-Create",
point: {
- type: 'Zone',
+ type: "Zone",
lineData: zone,
timeStamp: new Date().toISOString(),
- }
- }
+ },
+ },
],
- })
+ });
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
+ upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
} else {
-
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:zone:add', data);
+ socket.emit("v1:zone:add", data);
}
}
}
@@ -292,21 +286,19 @@ function ZoneCreator() {
return (
<>
- {toggleView &&
+ {toggleView && (
<>
-
+
{tempPoints.map((point) => (
))}
- {tempPoints.length > 0 &&
-
- }
+ {tempPoints.length > 0 && }
>
- }
+ )}
>
- )
+ );
}
-export default ZoneCreator
\ No newline at end of file
+export default ZoneCreator;
diff --git a/app/src/modules/builder/zone/zoneGroup.tsx b/app/src/modules/builder/zone/zoneGroup.tsx
index 08d3e9c..a855bd0 100644
--- a/app/src/modules/builder/zone/zoneGroup.tsx
+++ b/app/src/modules/builder/zone/zoneGroup.tsx
@@ -1,55 +1,53 @@
-import { useEffect } from 'react';
-import { useActiveTool, useToggleView } from '../../../store/builder/store';
-import { useBuilderStore } from '../../../store/builder/useBuilderStore';
-import { useVersionContext } from '../version/versionContext';
-import { useSceneContext } from '../../scene/sceneContext';
-import { useParams } from 'react-router-dom';
-import useModuleStore from '../../../store/useModuleStore';
-import ZoneCreator from './zoneCreator/zoneCreator';
-import ZoneInstances from './Instances/zoneInstances';
+import { useEffect } from "react";
+import { useActiveTool, useToggleView } from "../../../store/builder/store";
+import { useBuilderStore } from "../../../store/builder/useBuilderStore";
+import { useSceneContext } from "../../scene/sceneContext";
+import { useParams } from "react-router-dom";
+import useModuleStore from "../../../store/ui/useModuleStore";
+import ZoneCreator from "./zoneCreator/zoneCreator";
+import ZoneInstances from "./Instances/zoneInstances";
-import { getZonesApi } from '../../../services/factoryBuilder/zone/getZonesApi';
+import { getZonesApi } from "../../../services/factoryBuilder/zone/getZonesApi";
function ZoneGroup() {
const { toggleView } = useToggleView();
const { setSelectedZone } = useBuilderStore();
const { activeModule } = useModuleStore();
const { activeTool } = useActiveTool();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { zoneStore } = useSceneContext();
+ const { zoneStore, versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
const { setZones } = zoneStore();
const { projectId } = useParams();
useEffect(() => {
- if (toggleView || activeModule !== 'builder') {
+ if (toggleView || activeModule !== "builder") {
setSelectedZone(null);
}
- }, [toggleView, activeModule, activeTool])
+ }, [toggleView, activeModule, activeTool]);
useEffect(() => {
if (projectId && selectedVersion) {
- getZonesApi(projectId, selectedVersion?.versionId || '').then((zones) => {
- if (zones && zones.length > 0) {
- setZones(zones);
- } else {
- setZones([]);
- }
- }).catch((err) => {
- console.log(err);
- })
+ getZonesApi(projectId, selectedVersion?.versionId || "")
+ .then((zones) => {
+ if (zones && zones.length > 0) {
+ setZones(zones);
+ } else {
+ setZones([]);
+ }
+ })
+ .catch((err) => {
+ console.log(err);
+ });
}
- }, [projectId, selectedVersion?.versionId])
+ }, [projectId, selectedVersion?.versionId]);
return (
<>
-
-
>
- )
+ );
}
-export default ZoneGroup
\ No newline at end of file
+export default ZoneGroup;
diff --git a/app/src/modules/collaboration/camera/collabCams.tsx b/app/src/modules/collaboration/camera/collabCams.tsx
index 02cd535..2e4c536 100644
--- a/app/src/modules/collaboration/camera/collabCams.tsx
+++ b/app/src/modules/collaboration/camera/collabCams.tsx
@@ -9,10 +9,10 @@ import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";
import { useNavigate } from "react-router-dom";
import { Html } from "@react-three/drei";
import CollabUserIcon from "./collabUserIcon";
-import useModuleStore from "../../../store/useModuleStore";
+import useModuleStore from "../../../store/ui/useModuleStore";
import { getAvatarColor } from "../functions/getAvatarColor";
import { useSelectedUserStore } from "../../../store/collaboration/useCollabStore";
-import { usePlayButtonStore } from "../../../store/usePlayButtonStore";
+import { usePlayButtonStore } from "../../../store/ui/usePlayButtonStore";
import setCameraView from "../functions/setCameraView";
import { getUserData } from "../../../functions/getUserData";
diff --git a/app/src/modules/collaboration/comments/instances/commentInstance/commentInstance.tsx b/app/src/modules/collaboration/comments/instances/commentInstance/commentInstance.tsx
index 5740b6e..824f8de 100644
--- a/app/src/modules/collaboration/comments/instances/commentInstance/commentInstance.tsx
+++ b/app/src/modules/collaboration/comments/instances/commentInstance/commentInstance.tsx
@@ -1,6 +1,6 @@
import { Html, TransformControls } from '@react-three/drei';
import { useEffect, useRef, useState } from 'react'
-import { usePlayButtonStore } from '../../../../../store/usePlayButtonStore';
+import { usePlayButtonStore } from '../../../../../store/ui/usePlayButtonStore';
import CommentThreads from '../../../../../components/ui/collaboration/CommentThreads';
import { useSelectedComment } from '../../../../../store/builder/store';
import { Group, Object3D, Vector2, Vector3 } from 'three';
diff --git a/app/src/modules/collaboration/comments/instances/commentInstances.tsx b/app/src/modules/collaboration/comments/instances/commentInstances.tsx
index a8d5ed8..dbcc09f 100644
--- a/app/src/modules/collaboration/comments/instances/commentInstances.tsx
+++ b/app/src/modules/collaboration/comments/instances/commentInstances.tsx
@@ -1,45 +1,47 @@
-import React, { useEffect } from 'react'
-import CommentInstance from './commentInstance/commentInstance'
-import { useCommentStore } from '../../../../store/collaboration/useCommentStore'
-import { getAllThreads } from '../../../../services/factoryBuilder/comments/getAllThreads';
-import { useParams } from 'react-router-dom';
-import { getUserData } from '../../../../functions/getUserData';
-import { getRelativeTime } from '../../../../components/ui/collaboration/function/getRelativeTime';
-import { useVersionContext } from '../../../builder/version/versionContext';
+import React, { useEffect } from "react";
+import CommentInstance from "./commentInstance/commentInstance";
+import { useCommentStore } from "../../../../store/collaboration/useCommentStore";
+import { getAllThreads } from "../../../../services/factoryBuilder/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() {
const { comments, setComments } = useCommentStore();
const { projectId } = useParams();
const { userId } = getUserData();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
useEffect(() => {
// console.log("comments", comments);
- }, [comments])
+ }, [comments]);
useEffect(() => {
if (!projectId || !selectedVersion) return;
- getAllThreads(projectId, selectedVersion?.versionId).then((fetchedComments) => {
- const formattedThreads = Array.isArray(fetchedComments.data)
- ? fetchedComments.data.map((thread: any) => ({
- ...thread,
- comments: Array.isArray(thread.comments)
- ? thread.comments.map((val: any) => ({
- replyId: val._id ?? "",
- creatorId: userId,
- createdAt: getRelativeTime(val.createdAt),
- lastUpdatedAt: "1 hr ago",
- comment: val.comment,
- _id: val._id ?? "",
- }))
- : [],
- }))
- : [];
- setComments(formattedThreads);
- }).catch((err) => {
- console.error("Failed to fetch threads:", err);
- })
+ getAllThreads(projectId, selectedVersion?.versionId)
+ .then((fetchedComments) => {
+ const formattedThreads = Array.isArray(fetchedComments.data)
+ ? fetchedComments.data.map((thread: any) => ({
+ ...thread,
+ comments: Array.isArray(thread.comments)
+ ? thread.comments.map((val: any) => ({
+ replyId: val._id ?? "",
+ creatorId: userId,
+ createdAt: getRelativeTime(val.createdAt),
+ lastUpdatedAt: "1 hr ago",
+ comment: val.comment,
+ _id: val._id ?? "",
+ }))
+ : [],
+ }))
+ : [];
+ setComments(formattedThreads);
+ })
+ .catch((err) => {
+ console.error("Failed to fetch threads:", err);
+ });
}, []);
return (
@@ -50,7 +52,7 @@ function CommentInstances() {
))}
>
- )
+ );
}
-export default CommentInstances
\ No newline at end of file
+export default CommentInstances;
diff --git a/app/src/modules/scene/camera/syncCam.tsx b/app/src/modules/scene/camera/syncCam.tsx
new file mode 100644
index 0000000..3847a3b
--- /dev/null
+++ b/app/src/modules/scene/camera/syncCam.tsx
@@ -0,0 +1,38 @@
+import { Vector3 } from "three";
+import { useFrame, useThree } from "@react-three/fiber";
+import { CameraControls } from "@react-three/drei";
+import { useSceneContext } from "../sceneContext";
+import { useIsComparing } from "../../../store/builder/store";
+import { useSceneStore } from "../../../store/scene/useSceneStore";
+import { useComparisonProduct } from "../../../store/simulation/useSimulationStore";
+import useModuleStore from "../../../store/ui/useModuleStore";
+
+import * as CONSTANTS from "../../../types/world/worldConstants";
+
+function SyncCam() {
+ const { layout } = useSceneContext();
+ const { controls } = useThree();
+ const { isComparing } = useIsComparing();
+ const { activeModule } = useModuleStore();
+ const { comparisonProduct } = useComparisonProduct();
+ const { setCamera, camState } = useSceneStore();
+
+ useFrame(() => {
+ if (layout === "Comparison Layout" && controls && camState) {
+ (controls as any).mouseButtons.left = CONSTANTS.controlsTransition.leftMouse;
+ (controls as any).mouseButtons.right = CONSTANTS.controlsTransition.rightMouse;
+ (controls as any).mouseButtons.wheel = CONSTANTS.controlsTransition.wheelMouse;
+ (controls as any).mouseButtons.middle = CONSTANTS.controlsTransition.middleMouse;
+ (controls as CameraControls).setLookAt(camState.position.x, camState.position.y, camState.position.z, camState.target.x, camState.target.y, camState.target.z, true);
+ }
+ if (layout === "Main Layout" && controls && isComparing && activeModule === "simulation" && comparisonProduct) {
+ const position = (controls as CameraControls).getPosition(new Vector3());
+ const target = (controls as CameraControls).getTarget(new Vector3());
+ setCamera(position, target);
+ }
+ });
+
+ return <>>;
+}
+
+export default SyncCam;
diff --git a/app/src/modules/scene/controls/contextControls/contextControls.tsx b/app/src/modules/scene/controls/contextControls/contextControls.tsx
index 7b99956..95d602e 100644
--- a/app/src/modules/scene/controls/contextControls/contextControls.tsx
+++ b/app/src/modules/scene/controls/contextControls/contextControls.tsx
@@ -3,7 +3,7 @@ import { useThree } from "@react-three/fiber";
import { CameraControls, Html, ScreenSpace } from "@react-three/drei";
import { useContextActionStore, useRenameModeStore, useToggleView, useToolMode, } from "../../../../store/builder/store";
import ContextMenu from "../../../../components/ui/menu/contextMenu";
-import useModuleStore from "../../../../store/useModuleStore";
+import useModuleStore from "../../../../store/ui/useModuleStore";
import { useSceneContext } from "../../sceneContext";
function ContextControls() {
diff --git a/app/src/modules/scene/controls/controls.tsx b/app/src/modules/scene/controls/controls.tsx
index 3e34faf..942b7f1 100644
--- a/app/src/modules/scene/controls/controls.tsx
+++ b/app/src/modules/scene/controls/controls.tsx
@@ -2,7 +2,7 @@ import { CameraControls } from "@react-three/drei";
import { useRef, useEffect } from "react";
import { useThree } from "@react-three/fiber";
import * as THREE from "three";
-import * as CONSTANTS from '../../../types/world/worldConstants';
+import * as CONSTANTS from "../../../types/world/worldConstants";
import { useSocketStore, useToggleView, useResetCamera } from "../../../store/builder/store";
import CamMode from "../camera/camMode";
@@ -20,6 +20,7 @@ import { getUserData } from "../../../functions/getUserData";
import { getCameraApi } from "../../../services/factoryBuilder/camera/getCameraApi";
import { setCameraApi } from "../../../services/factoryBuilder/camera/setCameraApi";
import updateCamPosition from "../camera/functions/updateCameraPosition";
+import SyncCam from "../camera/syncCam";
export default function Controls() {
const controlsRef = useRef(null);
@@ -38,15 +39,17 @@ export default function Controls() {
}
if (!projectId) return;
- getCameraApi(projectId).then((data) => {
- if (data?.position && data?.target) {
- controlsRef.current?.setPosition(data.position.x, data.position.y, data.position.z);
- controlsRef.current?.setTarget(data.target.x, data.target.y, data.target.z);
- } else {
- controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition);
- controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget);
- }
- }).catch((error) => console.error("Failed to fetch camera data:", error));
+ getCameraApi(projectId)
+ .then((data) => {
+ if (data?.position && data?.target) {
+ controlsRef.current?.setPosition(data.position.x, data.position.y, data.position.z);
+ controlsRef.current?.setTarget(data.target.x, data.target.y, data.target.z);
+ } else {
+ controlsRef.current?.setPosition(...CONSTANTS.threeDimension.defaultPosition);
+ controlsRef.current?.setTarget(...CONSTANTS.threeDimension.defaultTarget);
+ }
+ })
+ .catch((error) => console.error("Failed to fetch camera data:", error));
}, [projectId]);
useEffect(() => {
@@ -56,12 +59,7 @@ export default function Controls() {
controlsRef.current?.rotateAzimuthTo(CONSTANTS.threeDimension.defaultAzimuth);
if (!socket?.connected) {
- setCameraApi(
- projectId,
- new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition),
- new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget),
- new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation),
- )
+ setCameraApi(projectId, new THREE.Vector3(...CONSTANTS.threeDimension.defaultPosition), new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget), new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation));
} else {
const camData = {
organization,
@@ -70,9 +68,9 @@ export default function Controls() {
target: new THREE.Vector3(...CONSTANTS.threeDimension.defaultTarget),
rotation: new THREE.Vector3(...CONSTANTS.threeDimension.defaultRotation),
socketId: socket.id,
- projectId
+ projectId,
};
- socket.emit('v1:Camera:set', camData)
+ socket.emit("v1:Camera:set", camData);
}
setResetCamera(false);
@@ -152,6 +150,7 @@ export default function Controls() {
+
@@ -165,7 +164,6 @@ export default function Controls() {
-
>
);
-}
\ No newline at end of file
+}
diff --git a/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx
index 413e26f..c45631b 100644
--- a/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selection2D/moveControls2D.tsx
@@ -1,14 +1,13 @@
import * as THREE from "three";
import { useCallback, useEffect, useMemo, useState } from "react";
import { useFrame, useThree } from "@react-three/fiber";
-import { useSocketStore, useToggleView, useToolMode, } from "../../../../../store/builder/store";
+import { useSocketStore, useToggleView, useToolMode } from "../../../../../store/builder/store";
import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModifierKeys";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
-import { useVersionContext } from "../../../../builder/version/versionContext";
import { useSelectedPoints } from "../../../../../store/simulation/useSimulationStore";
-import useModuleStore from "../../../../../store/useModuleStore";
+import useModuleStore from "../../../../../store/ui/useModuleStore";
import { calculateAssetTransformationOnWall } from "../../../../builder/wallAsset/Instances/Instance/functions/calculateAssetTransformationOnWall";
import { upsertAisleApi } from "../../../../../services/factoryBuilder/aisle/upsertAisleApi";
@@ -17,16 +16,7 @@ import { upsertFloorApi } from "../../../../../services/factoryBuilder/floor/ups
import { upsertZoneApi } from "../../../../../services/factoryBuilder/zone/upsertZoneApi";
import { upsertWallAssetApi } from "../../../../../services/factoryBuilder/asset/wallAsset/upsertWallAssetApi";
-function MoveControls2D({
- movedObjects,
- setMovedObjects,
- pastedObjects,
- setPastedObjects,
- duplicatedObjects,
- setDuplicatedObjects,
- rotatedObjects,
- setRotatedObjects,
-}: any) {
+function MoveControls2D({ movedObjects, setMovedObjects, pastedObjects, setPastedObjects, duplicatedObjects, setDuplicatedObjects, rotatedObjects, setRotatedObjects }: any) {
const { camera, controls, gl, scene, pointer, raycaster } = useThree();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const { toolMode } = useToolMode();
@@ -36,9 +26,8 @@ function MoveControls2D({
const { socket } = useSocketStore();
const { userId, organization } = getUserData();
const { projectId } = useParams();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
- const { aisleStore, wallStore, floorStore, zoneStore, undoRedo2DStore, wallAssetStore } = useSceneContext();
+ const { aisleStore, wallStore, floorStore, zoneStore, undoRedo2DStore, wallAssetStore, versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
const { getWallAssetsByWall, updateWallAsset } = wallAssetStore();
const { push2D } = undoRedo2DStore();
const { setPosition: setAislePosition, getAislesByPointId, getAisleById } = aisleStore();
@@ -47,12 +36,12 @@ function MoveControls2D({
const { setPosition: setZonePosition, getZonesByPointId, getZoneById } = zoneStore();
const [dragOffset, setDragOffset] = useState(null);
const [initialPositions, setInitialPositions] = useState>({});
- const [initialStates, setInitialStates] = useState>({});
+ const [initialStates, setInitialStates] = useState>({});
const [initial, setInitial] = useState<{
- aisles?: Aisle[],
- walls?: Wall[],
- floors?: Floor[],
- zones?: Zone[]
+ aisles?: Aisle[];
+ walls?: Wall[];
+ floors?: Floor[];
+ zones?: Zone[];
}>({});
const [isMoving, setIsMoving] = useState(false);
@@ -122,7 +111,7 @@ function MoveControls2D({
}, [camera, controls, scene, toggleView, selectedPoints, socket, pastedObjects, duplicatedObjects, movedObjects, rotatedObjects, initial]);
useEffect(() => {
- if (toolMode !== 'move' || !toggleView) {
+ if (toolMode !== "move" || !toggleView) {
if (movedObjects.length > 0) {
resetToInitialPositions();
}
@@ -146,21 +135,18 @@ function MoveControls2D({
const initialPosition = initialPositions[movedPoint.uuid];
if (initialPosition) {
- const relativeOffset = new THREE.Vector3().subVectors(
- initialPosition,
- initialPositions[movedObjects[0].uuid]
- );
+ const relativeOffset = new THREE.Vector3().subVectors(initialPosition, initialPositions[movedObjects[0].uuid]);
const newPosition = new THREE.Vector3().addVectors(baseNewPosition, relativeOffset);
const positionArray: [number, number, number] = [newPosition.x, newPosition.y, newPosition.z];
- if (point.pointType === 'Aisle') {
+ if (point.pointType === "Aisle") {
setAislePosition(point.pointUuid, positionArray);
- } else if (point.pointType === 'Wall') {
+ } else if (point.pointType === "Wall") {
setWallPosition(point.pointUuid, positionArray);
- } else if (point.pointType === 'Floor') {
+ } else if (point.pointType === "Floor") {
setFloorPosition(point.pointUuid, positionArray);
- } else if (point.pointType === 'Zone') {
+ } else if (point.pointType === "Zone") {
setZonePosition(point.pointUuid, positionArray);
}
}
@@ -174,43 +160,45 @@ function MoveControls2D({
return new THREE.Vector3().subVectors(pointPosition, hitPoint);
}, []);
- const movePoints = (() => {
+ const movePoints = () => {
if (selectedPoints.length === 0) return;
- const states: Record = {};
+ const states: Record = {};
const initials: {
aisles?: Aisle[] | undefined;
walls?: Wall[];
floors?: Floor[];
zones?: Zone[];
- } = {}
+ } = {};
selectedPoints.forEach((point: THREE.Object3D) => {
states[point.uuid] = {
position: new THREE.Vector3().copy(point.position),
- rotation: point.rotation ? new THREE.Euler().copy(point.rotation) : undefined
+ rotation: point.rotation ? new THREE.Euler().copy(point.rotation) : undefined,
};
if (point.userData.pointType === "Aisle") {
const aisles = getAislesByPointId(point.userData.pointUuid);
- initials.aisles = [...(initials.aisles ?? []), ...aisles,].filter((aisle, index, self) => index === self.findIndex((a) => a.aisleUuid === aisle.aisleUuid));
+ initials.aisles = [...(initials.aisles ?? []), ...aisles].filter((aisle, index, self) => index === self.findIndex((a) => a.aisleUuid === aisle.aisleUuid));
} else if (point.userData.pointType === "Wall") {
const walls = getWallsByPointId(point.userData.pointUuid);
- initials.walls = [...(initials.walls ?? []), ...walls,].filter((wall, index, self) => index === self.findIndex((w) => w.wallUuid === wall.wallUuid));
+ initials.walls = [...(initials.walls ?? []), ...walls].filter((wall, index, self) => index === self.findIndex((w) => w.wallUuid === wall.wallUuid));
} else if (point.userData.pointType === "Floor") {
const floors = getFloorsByPointId(point.userData.pointUuid);
- initials.floors = [...(initials.floors ?? []), ...floors,].filter((floor, index, self) => index === self.findIndex((f) => f.floorUuid === floor.floorUuid));
+ initials.floors = [...(initials.floors ?? []), ...floors].filter((floor, index, self) => index === self.findIndex((f) => f.floorUuid === floor.floorUuid));
} else if (point.userData.pointType === "Zone") {
const zones = getZonesByPointId(point.userData.pointUuid);
- initials.zones = [...(initials.zones ?? []), ...zones,].filter((zone, index, self) => index === self.findIndex((z) => z.zoneUuid === zone.zoneUuid));
+ initials.zones = [...(initials.zones ?? []), ...zones].filter((zone, index, self) => index === self.findIndex((z) => z.zoneUuid === zone.zoneUuid));
}
});
- setInitial(initials)
+ setInitial(initials);
setInitialStates(states);
const positions: Record = {};
- selectedPoints.forEach((point: THREE.Object3D) => { positions[point.uuid] = new THREE.Vector3().copy(point.position); });
+ selectedPoints.forEach((point: THREE.Object3D) => {
+ positions[point.uuid] = new THREE.Vector3().copy(point.position);
+ });
setInitialPositions(positions);
raycaster.setFromCamera(pointer, camera);
@@ -224,7 +212,7 @@ function MoveControls2D({
setMovedObjects(selectedPoints);
setIsMoving(true);
- });
+ };
const resetToInitialPositions = () => {
setTimeout(() => {
@@ -232,24 +220,20 @@ function MoveControls2D({
if (movedPoint.userData.pointUuid && initialStates[movedPoint.uuid]) {
const point: Point = movedPoint.userData as Point;
const initialState = initialStates[movedPoint.uuid];
- const positionArray: [number, number, number] = [
- initialState.position.x,
- initialState.position.y,
- initialState.position.z
- ];
+ const positionArray: [number, number, number] = [initialState.position.x, initialState.position.y, initialState.position.z];
- if (point.pointType === 'Aisle') {
+ if (point.pointType === "Aisle") {
setAislePosition(point.pointUuid, positionArray);
- } else if (point.pointType === 'Wall') {
+ } else if (point.pointType === "Wall") {
setWallPosition(point.pointUuid, positionArray);
- } else if (point.pointType === 'Floor') {
+ } else if (point.pointType === "Floor") {
setFloorPosition(point.pointUuid, positionArray);
- } else if (point.pointType === 'Zone') {
+ } else if (point.pointType === "Zone") {
setZonePosition(point.pointUuid, positionArray);
}
}
});
- }, 0)
+ }, 0);
};
const placeMovedPoints = () => {
@@ -266,44 +250,35 @@ function MoveControls2D({
if (movedObject.userData.pointUuid) {
const point: Point = movedObject.userData as Point;
- if (point.pointType === 'Aisle') {
+ if (point.pointType === "Aisle") {
const updatedAisles = getAislesByPointId(point.pointUuid);
if (updatedAisles.length > 0 && projectId) {
updatedAisles.forEach((updatedAisle) => {
-
if (!socket?.connected) {
// API
- upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || '');
+ upsertAisleApi(updatedAisle.aisleUuid, updatedAisle.points, updatedAisle.type, projectId, selectedVersion?.versionId || "");
} else {
-
// SOCKET
- socket.emit('v1:model-aisle:add', {
+ socket.emit("v1:model-aisle:add", {
projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId,
organization,
aisleUuid: updatedAisle.aisleUuid,
points: updatedAisle.points,
- type: updatedAisle.type
+ type: updatedAisle.type,
});
}
const old = initialStates[movedObject.uuid];
if (old) {
processedAisles.push({
- type: 'Aisle',
+ type: "Aisle",
lineData: {
...updatedAisle,
- points: [
- initialStates[updatedAisle.points[0].pointUuid] ?
- { ...updatedAisle.points[0], position: initialStates[updatedAisle.points[0].pointUuid].position }
- : updatedAisle.points[0],
- initialStates[updatedAisle.points[1].pointUuid] ?
- { ...updatedAisle.points[1], position: initialStates[updatedAisle.points[1].pointUuid].position }
- : updatedAisle.points[1]
- ] as [Point, Point],
+ points: [initialStates[updatedAisle.points[0].pointUuid] ? { ...updatedAisle.points[0], position: initialStates[updatedAisle.points[0].pointUuid].position } : updatedAisle.points[0], initialStates[updatedAisle.points[1].pointUuid] ? { ...updatedAisle.points[1], position: initialStates[updatedAisle.points[1].pointUuid].position } : updatedAisle.points[1]] as [Point, Point],
},
newData: updatedAisle,
timeStamp: new Date().toISOString(),
@@ -311,12 +286,11 @@ function MoveControls2D({
}
});
}
- } else if (point.pointType === 'Wall') {
+ } else if (point.pointType === "Wall") {
const updatedWalls = getWallsByPointId(point.pointUuid);
if (updatedWalls?.length && projectId) {
- updatedWalls.forEach(updatedWall => {
-
- const initialWall = initial.walls?.find(w => w.wallUuid === updatedWall.wallUuid);
+ updatedWalls.forEach((updatedWall) => {
+ const initialWall = initial.walls?.find((w) => w.wallUuid === updatedWall.wallUuid);
if (initialWall) {
const assetsOnWall = getWallAssetsByWall(updatedWall.wallUuid);
@@ -337,34 +311,26 @@ function MoveControls2D({
if (!socket?.connected) {
// API
- upsertWallApi(projectId, selectedVersion?.versionId || '', updatedWall);
+ upsertWallApi(projectId, selectedVersion?.versionId || "", updatedWall);
} else {
-
// SOCKET
- socket.emit('v1:model-Wall:add', {
+ socket.emit("v1:model-Wall:add", {
wallData: updatedWall,
projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId,
- organization
+ organization,
});
}
const old = initialStates[movedObject.uuid];
if (old) {
processedWalls.push({
- type: 'Wall',
+ type: "Wall",
lineData: {
...updatedWall,
- points: [
- initialStates[updatedWall.points[0].pointUuid] ?
- { ...updatedWall.points[0], position: initialStates[updatedWall.points[0].pointUuid].position }
- : updatedWall.points[0],
- initialStates[updatedWall.points[1].pointUuid] ?
- { ...updatedWall.points[1], position: initialStates[updatedWall.points[1].pointUuid].position }
- : updatedWall.points[1]
- ] as [Point, Point],
+ points: [initialStates[updatedWall.points[0].pointUuid] ? { ...updatedWall.points[0], position: initialStates[updatedWall.points[0].pointUuid].position } : updatedWall.points[0], initialStates[updatedWall.points[1].pointUuid] ? { ...updatedWall.points[1], position: initialStates[updatedWall.points[1].pointUuid].position } : updatedWall.points[1]] as [Point, Point],
},
newData: updatedWall,
timeStamp: new Date().toISOString(),
@@ -372,31 +338,29 @@ function MoveControls2D({
}
});
}
- } else if (point.pointType === 'Floor') {
+ } else if (point.pointType === "Floor") {
const Floors = getFloorsByPointId(point.pointUuid);
const updatedFloors = getFloorsByPointId(point.pointUuid);
if (updatedFloors?.length && projectId) {
- updatedFloors.forEach(updatedFloor => {
-
+ updatedFloors.forEach((updatedFloor) => {
if (!socket?.connected) {
// API
- upsertFloorApi(projectId, selectedVersion?.versionId || '', updatedFloor);
+ upsertFloorApi(projectId, selectedVersion?.versionId || "", updatedFloor);
} else {
-
// SOCKET
- socket.emit('v1:model-Floor:add', {
+ socket.emit("v1:model-Floor:add", {
floorData: updatedFloor,
projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId,
- organization
+ organization,
});
}
const updatedFloorsData = updatedFloors.map((floor) => {
- const originalFloor = Floors.find(f => f.floorUuid === floor.floorUuid) || floor;
+ const originalFloor = Floors.find((f) => f.floorUuid === floor.floorUuid) || floor;
const updatedPoints = originalFloor.points.map((pt: Point) => {
const init = initialStates[pt.pointUuid];
@@ -414,31 +378,29 @@ function MoveControls2D({
processedFloors.push(...updatedFloorsData);
});
}
- } else if (point.pointType === 'Zone') {
+ } else if (point.pointType === "Zone") {
const Zones = getZonesByPointId(point.pointUuid);
const updatedZones = getZonesByPointId(point.pointUuid);
if (updatedZones?.length && projectId) {
- updatedZones.forEach(updatedZone => {
-
+ updatedZones.forEach((updatedZone) => {
if (!socket?.connected) {
// API
- upsertZoneApi(projectId, selectedVersion?.versionId || '', updatedZone);
+ upsertZoneApi(projectId, selectedVersion?.versionId || "", updatedZone);
} else {
-
// SOCKET
- socket.emit('v1:zone:add', {
+ socket.emit("v1:zone:add", {
zoneData: updatedZone,
projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId,
- organization
+ organization,
});
}
const updatedZonesData = updatedZones.map((zone) => {
- const originalZone = Zones.find(z => z.zoneUuid === zone.zoneUuid) || zone;
+ const originalZone = Zones.find((z) => z.zoneUuid === zone.zoneUuid) || zone;
const updatedPoints = originalZone.points.map((pt: Point) => {
const init = initialStates[pt.pointUuid];
@@ -461,34 +423,31 @@ function MoveControls2D({
});
setTimeout(() => {
-
if (wallAssetUpdates.length > 0) {
wallAssetUpdates.filter((wallAssets, index, self) => index === self.findIndex((w) => w.modelUuid === wallAssets.modelUuid));
wallAssetUpdates.forEach((updatedWallAsset) => {
if (projectId && updatedWallAsset) {
-
updateWallAsset(updatedWallAsset.modelUuid, {
position: updatedWallAsset.position,
- rotation: updatedWallAsset.rotation
+ rotation: updatedWallAsset.rotation,
});
if (!socket?.connected) {
// API
- upsertWallAssetApi(projectId, selectedVersion?.versionId || '', updatedWallAsset);
+ upsertWallAssetApi(projectId, selectedVersion?.versionId || "", updatedWallAsset);
} else {
-
// SOCKET
const data = {
wallAssetData: updatedWallAsset,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:wall-asset:add', data);
+ socket.emit("v1:wall-asset:add", data);
}
}
});
@@ -498,22 +457,22 @@ function MoveControls2D({
const wallMap = new Map();
for (const wall of processedWalls) {
- if (wall.type !== 'Wall' || !wall.lineData.wallUuid) continue;
+ if (wall.type !== "Wall" || !wall.lineData.wallUuid) continue;
const uuid = wall.lineData.wallUuid;
if (!wallMap.has(uuid)) wallMap.set(uuid, []);
wallMap.get(uuid)!.push(wall);
}
wallMap.forEach((actions, uuid) => {
- const hasUpdate = actions.some(action => 'newData' in action);
+ const hasUpdate = actions.some((action) => "newData" in action);
if (hasUpdate) {
const wallData = getWallById(uuid);
if (wallData) {
undoPoints.push({
- type: 'Wall',
+ type: "Wall",
lineData: actions[0].lineData as Wall,
newData: wallData,
- timeStamp: new Date().toISOString()
+ timeStamp: new Date().toISOString(),
});
}
}
@@ -524,22 +483,22 @@ function MoveControls2D({
const aisleMap = new Map();
for (const aisle of processedAisles) {
- if (aisle.type !== 'Aisle' || !aisle.lineData.aisleUuid) continue;
+ if (aisle.type !== "Aisle" || !aisle.lineData.aisleUuid) continue;
const uuid = aisle.lineData.aisleUuid;
if (!aisleMap.has(uuid)) aisleMap.set(uuid, []);
aisleMap.get(uuid)!.push(aisle);
}
aisleMap.forEach((actions, uuid) => {
- const hasUpdate = actions.some(action => 'newData' in action);
+ const hasUpdate = actions.some((action) => "newData" in action);
if (hasUpdate) {
const aisleData = getAisleById(uuid);
if (aisleData) {
undoPoints.push({
- type: 'Aisle',
+ type: "Aisle",
lineData: actions[0].lineData as Aisle,
newData: aisleData,
- timeStamp: new Date().toISOString()
+ timeStamp: new Date().toISOString(),
});
}
}
@@ -550,7 +509,7 @@ function MoveControls2D({
const floorMap = new Map();
for (const floor of processedFloors) {
- if (floor.type !== 'Floor' || !floor.lineData.floorUuid) continue;
+ if (floor.type !== "Floor" || !floor.lineData.floorUuid) continue;
const uuid = floor.lineData.floorUuid;
if (!floorMap.has(uuid)) {
floorMap.set(uuid, []);
@@ -559,15 +518,15 @@ function MoveControls2D({
}
floorMap.forEach((actions, uuid) => {
- const hasUpdate = actions.some(action => 'newData' in action);
+ const hasUpdate = actions.some((action) => "newData" in action);
if (hasUpdate) {
const floorData = getFloorById(uuid);
if (floorData) {
undoPoints.push({
- type: 'Floor',
+ type: "Floor",
lineData: actions[0].lineData as Floor,
newData: floorData,
- timeStamp: new Date().toISOString()
+ timeStamp: new Date().toISOString(),
});
}
}
@@ -578,7 +537,7 @@ function MoveControls2D({
const zoneMap = new Map();
for (const zone of processedZones) {
- if (zone.type !== 'Zone' || !zone.lineData.zoneUuid) continue;
+ if (zone.type !== "Zone" || !zone.lineData.zoneUuid) continue;
const uuid = zone.lineData.zoneUuid;
if (!zoneMap.has(uuid)) {
zoneMap.set(uuid, []);
@@ -587,15 +546,15 @@ function MoveControls2D({
}
zoneMap.forEach((actions, uuid) => {
- const hasUpdate = actions.some(action => 'newData' in action);
+ const hasUpdate = actions.some((action) => "newData" in action);
if (hasUpdate) {
const zoneData = getZoneById(uuid);
if (zoneData) {
undoPoints.push({
- type: 'Zone',
+ type: "Zone",
lineData: actions[0].lineData as Zone,
newData: zoneData,
- timeStamp: new Date().toISOString()
+ timeStamp: new Date().toISOString(),
});
}
}
@@ -604,13 +563,13 @@ function MoveControls2D({
if (undoPoints.length > 0) {
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Update',
- points: undoPoints
- }
- ]
+ actionType: "Lines-Update",
+ points: undoPoints,
+ },
+ ],
});
}
}, 0);
@@ -627,10 +586,7 @@ function MoveControls2D({
clearSelectedPoints();
};
- return (
- <>
- >
- );
+ return <>>;
}
export default MoveControls2D;
diff --git a/app/src/modules/scene/controls/selectionControls/selection2D/selectionControls2D.tsx b/app/src/modules/scene/controls/selectionControls/selection2D/selectionControls2D.tsx
index 6cf9307..72a29f9 100644
--- a/app/src/modules/scene/controls/selectionControls/selection2D/selectionControls2D.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selection2D/selectionControls2D.tsx
@@ -4,12 +4,11 @@ import { useThree } from "@react-three/fiber";
import { SelectionHelper } from "../helper/selectionHelper";
import { SelectionBox } from "three/examples/jsm/interactive/SelectionBox";
-import useModuleStore from "../../../../../store/useModuleStore";
+import useModuleStore from "../../../../../store/ui/useModuleStore";
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
-import { useVersionContext } from "../../../../builder/version/versionContext";
-import { useSocketStore, useToggleView, useToolMode, } from "../../../../../store/builder/store";
+import { useSocketStore, useToggleView, useToolMode } from "../../../../../store/builder/store";
import { useSelectedPoints } from "../../../../../store/simulation/useSimulationStore";
import { useBuilderStore } from "../../../../../store/builder/useBuilderStore";
import MoveControls2D from "./moveControls2D";
@@ -35,11 +34,10 @@ const SelectionControls2D: React.FC = () => {
const { socket } = useSocketStore();
const selectionBox = useMemo(() => new SelectionBox(camera, scene), [camera, scene]);
const { toolMode } = useToolMode();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
const { projectId } = useParams();
const { hoveredLine, hoveredPoint } = useBuilderStore();
- const { aisleStore, wallStore, floorStore, zoneStore, undoRedo2DStore, wallAssetStore } = useSceneContext();
+ const { aisleStore, wallStore, floorStore, zoneStore, undoRedo2DStore, wallAssetStore, versionStore } = useSceneContext();
+ const { selectedVersion } = versionStore();
const { getWallAssetsByWall, removeWallAsset } = wallAssetStore();
const { push2D } = undoRedo2DStore();
const { removePoint: removeAislePoint } = aisleStore();
@@ -121,7 +119,6 @@ const SelectionControls2D: React.FC = () => {
isShiftSelecting.current = false;
isLeftMouseDown.current = false;
isDragging.current = false;
-
} else if (controls) {
(controls as any).enabled = true;
}
@@ -147,7 +144,7 @@ const SelectionControls2D: React.FC = () => {
rightClickMoved.current = false;
};
- if (toggleView && toolMode === 'move') {
+ if (toggleView && toolMode === "move") {
helper.enabled = true;
canvasElement.addEventListener("pointermove", onPointerMove);
canvasElement.addEventListener("pointerup", onPointerUp);
@@ -171,7 +168,7 @@ const SelectionControls2D: React.FC = () => {
}, [camera, controls, scene, toggleView, selectedPoints, copiedObjects, pastedObjects, duplicatedObjects, movedObjects, socket, rotatedObjects, toolMode, hoveredLine, hoveredPoint]);
useEffect(() => {
- if (toolMode !== 'move' || !toggleView) {
+ if (toolMode !== "move" || !toggleView) {
clearSelection();
}
}, [activeModule, toolMode, toggleView]);
@@ -214,7 +211,6 @@ const SelectionControls2D: React.FC = () => {
const selected = Array.from(updatedSelections);
setSelectedPoints(selected);
-
}, [selectionBox, pointer, controls, selectedPoints, setSelectedPoints]);
const clearSelection = () => {
@@ -225,7 +221,6 @@ const SelectionControls2D: React.FC = () => {
const deleteSelection = () => {
if (selectedPoints.length > 0 && duplicatedObjects.length === 0) {
-
const deletedPoints: UndoRedo2DDataTypeSchema[] = [];
const updatedPoints: UndoRedo2DDataTypeSchema[] = [];
const processedAisles: UndoRedo2DDataTypeSchema[] = [];
@@ -236,29 +231,27 @@ const SelectionControls2D: React.FC = () => {
selectedPoints.forEach((selectedPoint) => {
if (selectedPoint.userData.pointUuid) {
const point: Point = selectedPoint.userData as Point;
- if (point.pointType === 'Aisle') {
+ if (point.pointType === "Aisle") {
const removedAisles = removeAislePoint(point.pointUuid);
if (removedAisles.length > 0) {
- removedAisles.forEach(aisle => {
+ removedAisles.forEach((aisle) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || '');
+ deleteAisleApi(aisle.aisleUuid, projectId, selectedVersion?.versionId || "");
} else {
-
// SOCKET
const data = {
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
organization: organization,
- aisleUuid: aisle.aisleUuid
- }
+ aisleUuid: aisle.aisleUuid,
+ };
- socket.emit('v1:model-aisle:delete', data);
+ socket.emit("v1:model-aisle:delete", data);
}
}
});
@@ -272,60 +265,54 @@ const SelectionControls2D: React.FC = () => {
processedAisles.push(...removedAislesData);
}
}
- if (point.pointType === 'Wall') {
+ if (point.pointType === "Wall") {
const removedWalls = removeWallPoint(point.pointUuid);
if (removedWalls.length > 0) {
- removedWalls.forEach(wall => {
-
+ removedWalls.forEach((wall) => {
const assetsOnWall = getWallAssetsByWall(wall.wallUuid);
assetsOnWall.forEach((asset) => {
if (projectId && asset) {
-
removeWallAsset(asset.modelUuid);
if (!socket?.connected) {
-
// API
- deleteWallAssetApi(projectId, selectedVersion?.versionId || '', asset.modelUuid, asset.wallUuid);
+ deleteWallAssetApi(projectId, selectedVersion?.versionId || "", asset.modelUuid, asset.wallUuid);
} else {
-
// SOCKET
const data = {
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
organization: organization,
modelUuid: asset.modelUuid,
- wallUuid: asset.wallUuid
- }
+ wallUuid: asset.wallUuid,
+ };
- socket.emit('v1:wall-asset:delete', data);
+ socket.emit("v1:wall-asset:delete", data);
}
}
- })
+ });
if (projectId) {
if (!socket?.connected) {
-
// API
- deleteWallApi(projectId, selectedVersion?.versionId || '', wall.wallUuid);
+ deleteWallApi(projectId, selectedVersion?.versionId || "", wall.wallUuid);
} else {
-
// SOCKET
const data = {
wallUuid: wall.wallUuid,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Wall:delete', data);
+ socket.emit("v1:model-Wall:delete", data);
}
}
});
@@ -339,30 +326,28 @@ const SelectionControls2D: React.FC = () => {
processedWalls.push(...removedWallsData);
}
}
- if (point.pointType === 'Floor') {
+ if (point.pointType === "Floor") {
const Floors = getFloorsByPointId(point.pointUuid);
const { removedFloors, updatedFloors } = removeFloorPoint(point.pointUuid);
if (removedFloors.length > 0) {
- removedFloors.forEach(floor => {
+ removedFloors.forEach((floor) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- deleteFloorApi(projectId, selectedVersion?.versionId || '', floor.floorUuid);
+ deleteFloorApi(projectId, selectedVersion?.versionId || "", floor.floorUuid);
} else {
-
// SOCKET
const data = {
floorUuid: floor.floorUuid,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:delete', data);
+ socket.emit("v1:model-Floor:delete", data);
}
}
});
@@ -376,33 +361,31 @@ const SelectionControls2D: React.FC = () => {
processedFloors.push(...removedFloorsData);
}
if (updatedFloors.length > 0) {
- updatedFloors.forEach(floor => {
+ updatedFloors.forEach((floor) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertFloorApi(projectId, selectedVersion?.versionId || '', floor);
+ upsertFloorApi(projectId, selectedVersion?.versionId || "", floor);
} else {
-
// SOCKET
const data = {
floorData: floor,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:model-Floor:add', data);
+ socket.emit("v1:model-Floor:add", data);
}
}
});
const updatedFloorsData = updatedFloors.map((floor) => ({
type: "Floor" as const,
- lineData: Floors.find(f => f.floorUuid === floor.floorUuid) || floor,
+ lineData: Floors.find((f) => f.floorUuid === floor.floorUuid) || floor,
newData: floor,
timeStamp: new Date().toISOString(),
}));
@@ -410,30 +393,28 @@ const SelectionControls2D: React.FC = () => {
processedFloors.push(...updatedFloorsData);
}
}
- if (point.pointType === 'Zone') {
+ if (point.pointType === "Zone") {
const Zones = getZonesByPointId(point.pointUuid);
const { removedZones, updatedZones } = removeZonePoint(point.pointUuid);
if (removedZones.length > 0) {
- removedZones.forEach(zone => {
+ removedZones.forEach((zone) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- deleteZoneApi(projectId, selectedVersion?.versionId || '', zone.zoneUuid);
+ deleteZoneApi(projectId, selectedVersion?.versionId || "", zone.zoneUuid);
} else {
-
// SOCKET
const data = {
zoneUuid: zone.zoneUuid,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:zone:delete', data);
+ socket.emit("v1:zone:delete", data);
}
}
});
@@ -447,33 +428,31 @@ const SelectionControls2D: React.FC = () => {
processedZones.push(...removedZonesData);
}
if (updatedZones.length > 0) {
- updatedZones.forEach(zone => {
+ updatedZones.forEach((zone) => {
if (projectId) {
if (!socket?.connected) {
-
// API
- upsertZoneApi(projectId, selectedVersion?.versionId || '', zone);
+ upsertZoneApi(projectId, selectedVersion?.versionId || "", zone);
} else {
-
// SOCKET
const data = {
zoneData: zone,
projectId: projectId,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId: userId,
- organization: organization
- }
+ organization: organization,
+ };
- socket.emit('v1:zone:add', data);
+ socket.emit("v1:zone:add", data);
}
}
});
const updatedZonesData = updatedZones.map((zone) => ({
type: "Zone" as const,
- lineData: Zones.find(z => z.zoneUuid === zone.zoneUuid) || zone,
+ lineData: Zones.find((z) => z.zoneUuid === zone.zoneUuid) || zone,
newData: zone,
timeStamp: new Date().toISOString(),
}));
@@ -482,26 +461,26 @@ const SelectionControls2D: React.FC = () => {
}
}
}
- })
+ });
setTimeout(() => {
if (processedWalls.length > 0) {
const wallMap = new Map();
for (const wall of processedWalls) {
- if (wall.type !== 'Wall' || !wall.lineData.wallUuid) continue;
+ if (wall.type !== "Wall" || !wall.lineData.wallUuid) continue;
const uuid = wall.lineData.wallUuid;
if (!wallMap.has(uuid)) wallMap.set(uuid, []);
wallMap.get(uuid)!.push(wall);
}
wallMap.forEach((actions) => {
- const hasDelete = actions.some(action => !('newData' in action));
+ const hasDelete = actions.some((action) => !("newData" in action));
if (hasDelete) {
deletedPoints.push({
- type: 'Wall',
+ type: "Wall",
lineData: actions[0].lineData as Wall,
- timeStamp: new Date().toISOString()
+ timeStamp: new Date().toISOString(),
});
}
});
@@ -511,19 +490,19 @@ const SelectionControls2D: React.FC = () => {
const aisleMap = new Map();
for (const aisle of processedAisles) {
- if (aisle.type !== 'Aisle' || !aisle.lineData.aisleUuid) continue;
+ if (aisle.type !== "Aisle" || !aisle.lineData.aisleUuid) continue;
const uuid = aisle.lineData.aisleUuid;
if (!aisleMap.has(uuid)) aisleMap.set(uuid, []);
aisleMap.get(uuid)!.push(aisle);
}
aisleMap.forEach((actions) => {
- const hasDelete = actions.some(action => !('newData' in action));
+ const hasDelete = actions.some((action) => !("newData" in action));
if (hasDelete) {
deletedPoints.push({
- type: 'Aisle',
+ type: "Aisle",
lineData: actions[0].lineData as Aisle,
- timeStamp: new Date().toISOString()
+ timeStamp: new Date().toISOString(),
});
}
});
@@ -533,7 +512,7 @@ const SelectionControls2D: React.FC = () => {
const floorMap = new Map();
for (const floor of processedFloors) {
- if (floor.type !== 'Floor' || !floor.lineData.floorUuid) return;
+ if (floor.type !== "Floor" || !floor.lineData.floorUuid) return;
const uuid = floor.lineData.floorUuid;
if (!floorMap.has(uuid)) {
floorMap.set(uuid, []);
@@ -542,23 +521,23 @@ const SelectionControls2D: React.FC = () => {
}
floorMap.forEach((actions, uuid) => {
- const hasDelete = actions.some(action => !('newData' in action));
- const hasUpdate = actions.some(action => 'newData' in action);
+ const hasDelete = actions.some((action) => !("newData" in action));
+ const hasUpdate = actions.some((action) => "newData" in action);
if (hasDelete) {
deletedPoints.push({
- type: 'Floor',
+ type: "Floor",
lineData: actions[0].lineData as Floor,
- timeStamp: new Date().toISOString()
+ timeStamp: new Date().toISOString(),
});
} else if (!hasDelete && hasUpdate) {
const floorData = getFloorById(uuid);
if (floorData) {
updatedPoints.push({
- type: 'Floor',
+ type: "Floor",
lineData: actions[0].lineData as Floor,
newData: floorData,
- timeStamp: new Date().toISOString()
+ timeStamp: new Date().toISOString(),
});
}
}
@@ -569,7 +548,7 @@ const SelectionControls2D: React.FC = () => {
const zoneMap = new Map();
for (const zone of processedZones) {
- if (zone.type !== 'Zone' || !zone.lineData.zoneUuid) return;
+ if (zone.type !== "Zone" || !zone.lineData.zoneUuid) return;
const uuid = zone.lineData.zoneUuid;
if (!zoneMap.has(uuid)) {
zoneMap.set(uuid, []);
@@ -578,23 +557,23 @@ const SelectionControls2D: React.FC = () => {
}
zoneMap.forEach((actions, uuid) => {
- const hasDelete = actions.some(action => !('newData' in action));
- const hasUpdate = actions.some(action => 'newData' in action);
+ const hasDelete = actions.some((action) => !("newData" in action));
+ const hasUpdate = actions.some((action) => "newData" in action);
if (hasDelete) {
deletedPoints.push({
- type: 'Zone',
+ type: "Zone",
lineData: actions[0].lineData as Zone,
- timeStamp: new Date().toISOString()
+ timeStamp: new Date().toISOString(),
});
} else if (!hasDelete && hasUpdate) {
const zoneData = getZoneById(uuid);
if (zoneData) {
updatedPoints.push({
- type: 'Zone',
+ type: "Zone",
lineData: actions[0].lineData as Zone,
newData: zoneData,
- timeStamp: new Date().toISOString()
+ timeStamp: new Date().toISOString(),
});
}
}
@@ -603,37 +582,37 @@ const SelectionControls2D: React.FC = () => {
if (deletedPoints.length > 0 && updatedPoints.length > 0) {
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Delete',
- points: deletedPoints
+ actionType: "Lines-Delete",
+ points: deletedPoints,
},
{
- actionType: 'Lines-Update',
- points: updatedPoints
- }
- ]
+ actionType: "Lines-Update",
+ points: updatedPoints,
+ },
+ ],
});
} else if (deletedPoints.length > 0 && updatedPoints.length === 0) {
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Delete',
- points: deletedPoints
- }
- ]
+ actionType: "Lines-Delete",
+ points: deletedPoints,
+ },
+ ],
});
} else if (updatedPoints.length > 0 && deletedPoints.length === 0) {
push2D({
- type: 'Draw',
+ type: "Draw",
actions: [
{
- actionType: 'Lines-Update',
- points: updatedPoints
- }
- ]
+ actionType: "Lines-Update",
+ points: updatedPoints,
+ },
+ ],
});
}
}, 0);
@@ -642,11 +621,7 @@ const SelectionControls2D: React.FC = () => {
clearSelection();
};
- return (
-
-
-
- );
+ return ;
};
export default SelectionControls2D;
diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx
index 4b9ae71..2181a24 100644
--- a/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selection3D/copyPasteControls3D.tsx
@@ -8,7 +8,6 @@ import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModi
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
-import { useVersionContext } from "../../../../builder/version/versionContext";
import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
@@ -17,30 +16,29 @@ const CopyPasteControls3D = () => {
const { toggleView } = useToggleView();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const { socket } = useSocketStore();
- const { assetStore, eventStore, undoRedo3DStore } = useSceneContext();
+ const { assetStore, eventStore, undoRedo3DStore, versionStore } = useSceneContext();
const { push3D } = undoRedo3DStore();
const { addEvent } = eventStore();
const { projectId } = useParams();
const { assets, addAsset, updateAsset, removeAsset, getAssetById, selectedAssets, setSelectedAssets, copiedObjects, setCopiedObjects, pastedObjects, setPastedObjects, setDuplicatedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects } = assetStore();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { selectedVersion } = versionStore();
const { userId, organization } = getUserData();
const [isPasting, setIsPasting] = useState(false);
const [relativePositions, setRelativePositions] = useState([]);
const [centerOffset, setCenterOffset] = useState(null);
- const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({ left: false, right: false, });
- const { contextAction, setContextAction } = useContextActionStore()
+ const mouseButtonsDown = useRef<{ left: boolean; right: boolean }>({ left: false, right: false });
+ const { contextAction, setContextAction } = useContextActionStore();
const calculateRelativePositions = useCallback((objects: THREE.Object3D[]) => {
if (objects.length === 0) return { center: new THREE.Vector3(), relatives: [] };
const box = new THREE.Box3();
- objects.forEach(obj => box.expandByObject(obj));
+ objects.forEach((obj) => box.expandByObject(obj));
const center = new THREE.Vector3();
box.getCenter(center);
- const relatives = objects.map(obj => {
+ const relatives = objects.map((obj) => {
const relativePos = new THREE.Vector3().subVectors(obj.position, center);
return relativePos;
});
@@ -51,12 +49,12 @@ const CopyPasteControls3D = () => {
useEffect(() => {
if (contextAction === "copyAsset") {
setContextAction(null);
- copySelection()
+ copySelection();
} else if (contextAction === "pasteAsset") {
setContextAction(null);
- pasteCopiedObjects()
+ pasteCopiedObjects();
}
- }, [contextAction])
+ }, [contextAction]);
useEffect(() => {
if (!camera || !scene || toggleView) return;
@@ -238,8 +236,8 @@ const CopyPasteControls3D = () => {
position: newFloorItem.position,
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
state: "idle",
- type: 'transfer',
- subType: pastedAsset.userData.eventData.subType || '',
+ type: "transfer",
+ subType: pastedAsset.userData.eventData.subType || "",
speed: 1,
points: updatedEventData.points.map((point: any, index: number) => ({
uuid: THREE.MathUtils.generateUUID(),
@@ -248,22 +246,21 @@ const CopyPasteControls3D = () => {
action: {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: `Action 1`,
- actionType: 'default',
- material: 'Default Material',
+ actionType: "default",
+ material: "Default Material",
delay: 0,
spawnInterval: 5,
spawnCount: 1,
- triggers: []
- }
- }))
+ triggers: [],
+ },
+ })),
};
addEvent(ConveyorEvent);
- eventData.points = ConveyorEvent.points.map(point => ({
+ eventData.points = ConveyorEvent.points.map((point) => ({
uuid: point.uuid,
position: point.position,
- rotation: point.rotation
+ rotation: point.rotation,
}));
-
} else if (pastedAsset.userData.eventData.type === "Vehicle") {
const vehicleEvent: VehicleEventSchema = {
modelUuid: newFloorItem.modelUuid,
@@ -272,7 +269,7 @@ const CopyPasteControls3D = () => {
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
state: "idle",
type: "vehicle",
- subType: pastedAsset.userData.eventData.subType || '',
+ subType: pastedAsset.userData.eventData.subType || "",
speed: 1,
point: {
uuid: THREE.MathUtils.generateUUID(),
@@ -292,17 +289,16 @@ const CopyPasteControls3D = () => {
pickupDrop: [],
dropPickup: [],
},
- triggers: []
- }
- }
+ triggers: [],
+ },
+ },
};
addEvent(vehicleEvent);
eventData.point = {
uuid: vehicleEvent.point.uuid,
position: vehicleEvent.point.position,
- rotation: vehicleEvent.point.rotation
+ rotation: vehicleEvent.point.rotation,
};
-
} else if (pastedAsset.userData.eventData.type === "ArmBot") {
const roboticArmEvent: RoboticArmEventSchema = {
modelUuid: newFloorItem.modelUuid,
@@ -311,7 +307,7 @@ const CopyPasteControls3D = () => {
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
state: "idle",
type: "roboticArm",
- subType: pastedAsset.userData.eventData.subType || '',
+ subType: pastedAsset.userData.eventData.subType || "",
speed: 1,
point: {
uuid: THREE.MathUtils.generateUUID(),
@@ -324,20 +320,19 @@ const CopyPasteControls3D = () => {
actionType: "pickAndPlace",
process: {
startPoint: null,
- endPoint: null
+ endPoint: null,
},
- triggers: []
- }
- ]
- }
+ triggers: [],
+ },
+ ],
+ },
};
addEvent(roboticArmEvent);
eventData.point = {
uuid: roboticArmEvent.point.uuid,
position: roboticArmEvent.point.position,
- rotation: roboticArmEvent.point.rotation
+ rotation: roboticArmEvent.point.rotation,
};
-
} else if (pastedAsset.userData.eventData.type === "StaticMachine") {
const machineEvent: MachineEventSchema = {
modelUuid: newFloorItem.modelUuid,
@@ -346,7 +341,7 @@ const CopyPasteControls3D = () => {
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
state: "idle",
type: "machine",
- subType: pastedAsset.userData.eventData.subType || '',
+ subType: pastedAsset.userData.eventData.subType || "",
point: {
uuid: THREE.MathUtils.generateUUID(),
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
@@ -357,15 +352,15 @@ const CopyPasteControls3D = () => {
actionType: "process",
processTime: 10,
swapMaterial: "Default Material",
- triggers: []
- }
- }
+ triggers: [],
+ },
+ },
};
addEvent(machineEvent);
eventData.point = {
uuid: machineEvent.point.uuid,
position: machineEvent.point.position,
- rotation: machineEvent.point.rotation
+ rotation: machineEvent.point.rotation,
};
} else if (pastedAsset.userData.eventData.type === "Storage") {
const storageEvent: StorageEventSchema = {
@@ -378,7 +373,7 @@ const CopyPasteControls3D = () => {
storageCapacity: 10,
storageCount: 10,
materialType: "Default material",
- subType: pastedAsset.userData.eventData.subType || '',
+ subType: pastedAsset.userData.eventData.subType || "",
point: {
uuid: THREE.MathUtils.generateUUID(),
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
@@ -388,16 +383,16 @@ const CopyPasteControls3D = () => {
actionUuid: THREE.MathUtils.generateUUID(),
actionName: "Action 1",
actionType: "store",
- triggers: []
- }
- ]
- }
- }
+ triggers: [],
+ },
+ ],
+ },
+ };
addEvent(storageEvent);
eventData.point = {
uuid: storageEvent.point.uuid,
position: storageEvent.point.position,
- rotation: storageEvent.point.rotation
+ rotation: storageEvent.point.rotation,
};
} else if (pastedAsset.userData.eventData.type === "Human") {
const humanEvent: HumanEventSchema = {
@@ -407,7 +402,7 @@ const CopyPasteControls3D = () => {
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
state: "idle",
type: "human",
- subType: pastedAsset.userData.eventData.subType || '',
+ subType: pastedAsset.userData.eventData.subType || "",
speed: 1,
point: {
uuid: THREE.MathUtils.generateUUID(),
@@ -421,22 +416,22 @@ const CopyPasteControls3D = () => {
loadCapacity: 1,
assemblyCount: 1,
assemblyCondition: {
- conditionType: 'material',
- materialType: "Default material"
+ conditionType: "material",
+ materialType: "Default material",
},
manufactureCount: 1,
loadCount: 1,
processTime: 10,
- triggers: []
- }
- ]
- }
- }
+ triggers: [],
+ },
+ ],
+ },
+ };
addEvent(humanEvent);
eventData.point = {
uuid: humanEvent.point.uuid,
position: humanEvent.point.position,
- rotation: humanEvent.point.rotation
+ rotation: humanEvent.point.rotation,
};
} else if (pastedAsset.userData.eventData.type === "Crane") {
const craneEvent: CraneEventSchema = {
@@ -446,7 +441,7 @@ const CopyPasteControls3D = () => {
rotation: [newFloorItem.rotation.x, newFloorItem.rotation.y, newFloorItem.rotation.z],
state: "idle",
type: "crane",
- subType: pastedAsset.userData.eventData.subType || '',
+ subType: pastedAsset.userData.eventData.subType || "",
point: {
uuid: THREE.MathUtils.generateUUID(),
position: [updatedEventData.point.position[0], updatedEventData.point.position[1], updatedEventData.point.position[2]],
@@ -457,16 +452,16 @@ const CopyPasteControls3D = () => {
actionName: "Action 1",
actionType: "pickAndDrop",
maxPickUpCount: 1,
- triggers: []
- }
- ]
- }
- }
+ triggers: [],
+ },
+ ],
+ },
+ };
addEvent(craneEvent);
eventData.point = {
uuid: craneEvent.point.uuid,
position: craneEvent.point.position,
- rotation: craneEvent.point.rotation
+ rotation: craneEvent.point.rotation,
};
}
@@ -483,9 +478,9 @@ const CopyPasteControls3D = () => {
isVisible: true,
socketId: socket?.id,
eventData: eventData,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
userId,
- projectId
+ projectId,
};
if (!socket?.connected) {
@@ -500,11 +495,10 @@ const CopyPasteControls3D = () => {
isLocked: false,
isVisible: true,
eventData: eventData,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
projectId: projectId,
});
} else {
-
// SOCKET
socket.emit("v1:model-asset:add", data);
@@ -520,7 +514,7 @@ const CopyPasteControls3D = () => {
isCollidable: false,
isVisible: data.isVisible,
opacity: 1,
- eventData: data.eventData
+ eventData: data.eventData,
};
updateAsset(asset.modelUuid, asset);
@@ -535,9 +529,9 @@ const CopyPasteControls3D = () => {
isLocked: false,
isVisible: true,
socketId: socket?.id,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
projectId,
- userId
+ userId,
};
if (!socket?.connected) {
@@ -551,11 +545,10 @@ const CopyPasteControls3D = () => {
rotation: { x: pastedAsset.rotation.x, y: pastedAsset.rotation.y, z: pastedAsset.rotation.z },
isLocked: false,
isVisible: true,
- versionId: selectedVersion?.versionId || '',
+ versionId: selectedVersion?.versionId || "",
projectId: projectId,
});
} else {
-
// SOCKET
socket.emit("v1:model-asset:add", data);
@@ -588,9 +581,9 @@ const CopyPasteControls3D = () => {
isVisible: true,
isCollidable: false,
opacity: 1,
- eventData: newFloorItem.eventData || undefined
+ eventData: newFloorItem.eventData || undefined,
},
- timeStap: new Date().toISOString()
+ timeStap: new Date().toISOString(),
});
}
});
@@ -599,19 +592,19 @@ const CopyPasteControls3D = () => {
undoActions.push({
module: "builder",
actionType: "Asset-Copied",
- asset: assetsToCopy[0]
+ asset: assetsToCopy[0],
});
} else {
undoActions.push({
module: "builder",
actionType: "Assets-Copied",
- assets: assetsToCopy
+ assets: assetsToCopy,
});
}
push3D({
- type: 'Scene',
- actions: undoActions
+ type: "Scene",
+ actions: undoActions,
});
echo.success("Object added!");
@@ -631,4 +624,4 @@ const CopyPasteControls3D = () => {
return null;
};
-export default CopyPasteControls3D;
\ No newline at end of file
+export default CopyPasteControls3D;
diff --git a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx
index 17a369e..2e68cb6 100644
--- a/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx
+++ b/app/src/modules/scene/controls/selectionControls/selection3D/duplicationControls3D.tsx
@@ -8,7 +8,6 @@ import { detectModifierKeys } from "../../../../../utils/shortcutkeys/detectModi
import { useParams } from "react-router-dom";
import { getUserData } from "../../../../../functions/getUserData";
import { useSceneContext } from "../../../sceneContext";
-import { useVersionContext } from "../../../../builder/version/versionContext";
import { handleAssetPositionSnap } from "./functions/handleAssetPositionSnap";
import { setAssetsApi } from "../../../../../services/factoryBuilder/asset/floorAsset/setAssetsApi";
@@ -18,13 +17,12 @@ const DuplicationControls3D = () => {
const { toggleView } = useToggleView();
const plane = useMemo(() => new THREE.Plane(new THREE.Vector3(0, 1, 0), 0), []);
const { socket } = useSocketStore();
- const { assetStore, eventStore, undoRedo3DStore } = useSceneContext();
+ const { assetStore, eventStore, undoRedo3DStore, versionStore } = useSceneContext();
const { push3D } = undoRedo3DStore();
const { addEvent } = eventStore();
const { projectId } = useParams();
const { assets, addAsset, updateAsset, removeAsset, getAssetById, selectedAssets, setSelectedAssets, duplicatedObjects, setDuplicatedObjects, setPastedObjects, movedObjects, setMovedObjects, rotatedObjects, setRotatedObjects } = assetStore();
- const { selectedVersionStore } = useVersionContext();
- const { selectedVersion } = selectedVersionStore();
+ const { selectedVersion } = versionStore();
const { userId, organization } = getUserData();
const [keyEvent, setKeyEvent] = useState<"Ctrl" | "Shift" | "Ctrl+Shift" | "">("");
@@ -32,8 +30,8 @@ const DuplicationControls3D = () => {
const [dragOffset, setDragOffset] = useState