From 35153c8c79ae42caf0326de2346969202bb3931a Mon Sep 17 00:00:00 2001 From: Poovizhi Date: Sat, 2 Aug 2025 18:23:42 +0530 Subject: [PATCH] updated dashboard duplication --- .../components/Dashboard/DashboardCard.tsx | 541 ++-- .../components/Dashboard/DashboardHome.tsx | 18 +- .../Dashboard/DashboardProjects.tsx | 73 +- app/src/components/ui/FileMenu.tsx | 169 +- app/src/modules/scene/scene.tsx | 146 +- app/src/pages/Project.tsx | 5 +- .../services/dashboard/duplicateProject.ts | 10 +- app/src/services/dashboard/updateProject.ts | 2 + app/src/store/simulation/useProductStore.ts | 2193 ++++++++++------- 9 files changed, 1782 insertions(+), 1375 deletions(-) diff --git a/app/src/components/Dashboard/DashboardCard.tsx b/app/src/components/Dashboard/DashboardCard.tsx index 68d91e7..0f75d19 100644 --- a/app/src/components/Dashboard/DashboardCard.tsx +++ b/app/src/components/Dashboard/DashboardCard.tsx @@ -2,289 +2,314 @@ import React, { useState, useRef, useEffect, act } from "react"; import img from "../../assets/image/image.png"; import { useNavigate } from "react-router-dom"; import { getUserData } from "../../functions/getUserData"; -import { useLoadingProgress, useProjectName, useSocketStore } from "../../store/builder/store"; +import { + useLoadingProgress, + useProjectName, + useSocketStore, +} from "../../store/builder/store"; import { viewProject } from "../../services/dashboard/viewProject"; import OuterClick from "../../utils/outerClick"; import { KebabIcon } from "../icons/ExportCommonIcons"; import { getAllProjects } from "../../services/dashboard/getAllProjects"; +import { updateProject } from "../../services/dashboard/updateProject"; interface DashBoardCardProps { - projectName: string; - thumbnail: any; - projectId: string; - createdAt?: string; - isViewed?: string; - createdBy?: { _id: string, userName: string }; - handleDeleteProject?: (projectId: string) => Promise; - handleTrashDeleteProject?: (projectId: string) => Promise; - handleRestoreProject?: (projectId: string) => Promise; - handleDuplicateWorkspaceProject?: ( - projectId: string, - projectName: string, - thumbnail: string, - userId?: string - ) => Promise; - handleDuplicateRecentProject?: ( - projectId: string, - projectName: string, - thumbnail: string - ) => Promise; - active?: string; - setIsSearchActive?: React.Dispatch>; - setRecentDuplicateData?: React.Dispatch>; - setProjectDuplicateData?: React.Dispatch>; - setActiveFolder?: React.Dispatch>; + projectName: string; + thumbnail: any; + projectId: string; + createdAt?: string; + isViewed?: string; + createdBy?: { _id: string; userName: string }; + handleDeleteProject?: (projectId: string) => Promise; + handleTrashDeleteProject?: (projectId: string) => Promise; + handleRestoreProject?: (projectId: string) => Promise; + handleDuplicateWorkspaceProject?: ( + projectId: string, + projectName: string, + thumbnail: string, + userId?: string + ) => Promise; + handleDuplicateRecentProject?: ( + projectId: string, + projectName: string, + thumbnail: string + ) => Promise; + active?: string; + setIsSearchActive?: React.Dispatch>; + setRecentDuplicateData?: React.Dispatch>; + setProjectDuplicateData?: React.Dispatch>; + setActiveFolder?: React.Dispatch>; } type RelativeTimeFormatUnit = any; const DashboardCard: React.FC = ({ - projectName, - thumbnail, - projectId, - active, - handleDeleteProject, - handleRestoreProject, - handleTrashDeleteProject, - handleDuplicateWorkspaceProject, - handleDuplicateRecentProject, - createdAt, - createdBy, - setRecentDuplicateData, - setProjectDuplicateData, - setActiveFolder + projectName, + thumbnail, + projectId, + active, + handleDeleteProject, + handleRestoreProject, + handleTrashDeleteProject, + handleDuplicateWorkspaceProject, + handleDuplicateRecentProject, + createdAt, + createdBy, + setRecentDuplicateData, + setProjectDuplicateData, + setActiveFolder, }) => { - const navigate = useNavigate(); - const { setProjectName } = useProjectName(); - const { userId, organization, userName } = getUserData(); - const [isKebabOpen, setIsKebabOpen] = useState(false); - const [renameValue, setRenameValue] = useState(projectName); - const [isRenaming, setIsRenaming] = useState(false); - const { projectSocket } = useSocketStore(); - const { setLoadingProgress } = useLoadingProgress(); - const kebabRef = useRef(null); + const navigate = useNavigate(); + const { setProjectName } = useProjectName(); + const { userId, organization, userName } = getUserData(); + const [isKebabOpen, setIsKebabOpen] = useState(false); + const [renameValue, setRenameValue] = useState(projectName); + const [isRenaming, setIsRenaming] = useState(false); + const { projectSocket } = useSocketStore(); + const { setLoadingProgress } = useLoadingProgress(); + const kebabRef = useRef(null); - const navigateToProject = async (e: any) => { - console.log('active: ', active); - if (active && active == "trash") return; - try { - const viewProjects = await viewProject(organization, projectId, userId) - console.log('viewProjects: ', viewProjects); - console.log('projectName: ', projectName); - setLoadingProgress(1) - setProjectName(projectName); - navigate(`/${projectId}`); - } catch { + const navigateToProject = async (e: any) => { + if (active && active == "trash") return; + try { + const viewProjects = await viewProject(organization, projectId, userId); + setLoadingProgress(1); + setProjectName(projectName); + navigate(`/${projectId}`); + } catch {} + }; + + const handleOptionClick = async (option: string) => { + switch (option) { + case "delete": + if (handleDeleteProject) { + handleDeleteProject(projectId); + } else if (handleTrashDeleteProject) { + handleTrashDeleteProject(projectId); } - }; - - const handleOptionClick = async (option: string) => { - switch (option) { - case "delete": - if (handleDeleteProject) { - handleDeleteProject(projectId); - } else if (handleTrashDeleteProject) { - handleTrashDeleteProject(projectId); - } - break; - case "restore": - if (handleRestoreProject) { - await handleRestoreProject(projectId); - } - break; - case "open in new tab": - try { - if (active === "shared" && createdBy) { - console.log("ihreq"); - const newTab = await viewProject(organization, projectId, createdBy?._id); - console.log('newTab: ', newTab); - } else { - const newTab = await viewProject(organization, projectId, userId); - console.log('newTab: ', newTab); - setProjectName(projectName); - setIsKebabOpen(false); - } - } catch (error) { - - } - window.open(`/${projectId}`, "_blank"); - break; - case "rename": - setIsRenaming(true); - break; - case "duplicate": - if (handleDuplicateWorkspaceProject) { - setProjectDuplicateData && - setProjectDuplicateData({ - projectId, - projectName, - thumbnail, - }); - await handleDuplicateWorkspaceProject(projectId, projectName, thumbnail, userId); - if (active === "shared" && setActiveFolder) { - setActiveFolder("myProjects") - } - } else if (handleDuplicateRecentProject) { - setRecentDuplicateData && - setRecentDuplicateData({ - projectId, - projectName, - thumbnail, - userId - }); - await handleDuplicateRecentProject(projectId, projectName, thumbnail); - } - break; - default: - break; + break; + case "restore": + if (handleRestoreProject) { + await handleRestoreProject(projectId); } - setIsKebabOpen(false); - }; - - OuterClick({ - contextClassName: ["kebab-wrapper", "kebab-options-wrapper"], - setMenuVisible: () => setIsKebabOpen(false), - }); - - const handleProjectName = async (projectName: string) => { - setRenameValue(projectName); - if (!projectId) return; + break; + case "open in new tab": try { - const projects = await getAllProjects(userId, organization); - if (!projects || !projects.Projects) return; - let projectUuid = projects.Projects.find( - (val: any) => val.projectUuid === projectId || val._id === projectId + if (active === "shared" && createdBy) { + const newTab = await viewProject( + organization, + projectId, + createdBy?._id ); - const updateProjects = { - projectId: projectUuid, - organization, - userId, - projectName, - thumbnail: undefined, - }; + } else { + const newTab = await viewProject(organization, projectId, userId); - if (projectSocket) { - projectSocket.emit("v1:project:update", updateProjects); - } - } catch (error) { } - }; - - function getRelativeTime(dateString: string): string { - const date = new Date(dateString); - const now = new Date(); - const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000); - - const intervals: Record = { - year: 31536000, - month: 2592000, - week: 604800, - day: 86400, - hour: 3600, - minute: 60, - second: 1, - }; - - const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" }); - - for (const key in intervals) { - const unit = key as RelativeTimeFormatUnit; - const diff = Math.floor(diffInSeconds / intervals[unit]); - if (diff >= 1) { - return rtf.format(-diff, unit); - } + setProjectName(projectName); + setIsKebabOpen(false); + } + } catch (error) {} + window.open(`/${projectId}`, "_blank"); + break; + case "rename": + setIsRenaming(true); + break; + case "duplicate": + if (handleDuplicateWorkspaceProject) { + setProjectDuplicateData && + setProjectDuplicateData({ + projectId, + projectName, + thumbnail, + }); + await handleDuplicateWorkspaceProject( + projectId, + projectName, + thumbnail, + userId + ); + if (active === "shared" && setActiveFolder) { + setActiveFolder("myProjects"); + } + } else if (handleDuplicateRecentProject) { + setRecentDuplicateData && + setRecentDuplicateData({ + projectId, + projectName, + thumbnail, + userId, + }); + await handleDuplicateRecentProject(projectId, projectName, thumbnail); } - return "just now"; + break; + default: + break; } + setIsKebabOpen(false); + }; - const kebabOptionsMap: Record = { - default: ["rename", "delete", "duplicate", "open in new tab"], - trash: ["restore", "delete"], - shared: ["duplicate", "open in new tab"], + OuterClick({ + contextClassName: ["kebab-wrapper", "kebab-options-wrapper"], + setMenuVisible: () => setIsKebabOpen(false), + }); + + const handleProjectName = async (projectName: string) => { + setRenameValue(projectName); + if (!projectId) return; + try { + const projects = await getAllProjects(userId, organization); + if (!projects || !projects.Projects) return; + let projectUuid = projects.Projects.find( + (val: any) => val.projectUuid === projectId || val._id === projectId + ); + const updateProjects = { + projectId: projectUuid?._id, + organization, + userId, + projectName, + thumbnail: undefined, + }; + // const updatedProjectName = await updateProject( + // projectUuid._id, + // userId, + // organization, + // undefined, + // projectName + // ); + if (projectSocket) { + projectSocket.emit("v1:project:update", updateProjects); + } + } catch (error) {} + }; + + function getRelativeTime(dateString: string): string { + const date = new Date(dateString); + const now = new Date(); + const diffInSeconds = Math.floor((now.getTime() - date.getTime()) / 1000); + + const intervals: Record = { + year: 31536000, + month: 2592000, + week: 604800, + day: 86400, + hour: 3600, + minute: 60, + second: 1, }; - const getOptions = () => { - if (active === "trash") return kebabOptionsMap.trash; - if (active === "shared") return kebabOptionsMap.shared; - if (createdBy && createdBy?._id !== userId) return kebabOptionsMap.shared; - return kebabOptionsMap.default; - }; + const rtf = new Intl.RelativeTimeFormat("en", { numeric: "auto" }); - return ( - - - - - {isKebabOpen && ( -
- {getOptions().map((option) => ( - - ))} -
+
+ {isRenaming ? ( + { + e.stopPropagation(); + handleProjectName(e.target.value); + }} + onBlur={() => { + setIsRenaming(false); + setProjectName(renameValue); + }} + onKeyDown={(e) => { + if (e.key === "Enter") { + setProjectName(renameValue); + setIsRenaming(false); + } + }} + autoFocus + /> + ) : ( + {renameValue} )} - - ); + {createdAt && ( +
+ {active && active == "trash" ? `Trashed by you` : `Edited `}{" "} + {getRelativeTime(createdAt)} +
+ )} +
+
+
+ {!createdBy + ? userName + ? userName?.charAt(0).toUpperCase() + : "A" + : createdBy?.userName?.charAt(0).toUpperCase()} +
+ +
+ + + {isKebabOpen && ( +
+ {getOptions().map((option) => ( + + ))} +
+ )} + + ); }; -export default DashboardCard; \ No newline at end of file +export default DashboardCard; diff --git a/app/src/components/Dashboard/DashboardHome.tsx b/app/src/components/Dashboard/DashboardHome.tsx index 6e9dce7..9e05994 100644 --- a/app/src/components/Dashboard/DashboardHome.tsx +++ b/app/src/components/Dashboard/DashboardHome.tsx @@ -13,10 +13,10 @@ interface Project { _id: string; projectName: string; thumbnail: string; - createdBy: { _id: string, userName: string }; + createdBy: { _id: string; userName: string }; projectUuid?: string; createdAt: string; - isViewed?: string + isViewed?: string; } interface RecentProjectsData { @@ -25,12 +25,12 @@ interface RecentProjectsData { const DashboardHome: React.FC = () => { const [recentProjects, setRecentProjects] = useState({}); + const [isSearchActive, setIsSearchActive] = useState(false); const { userId, organization } = getUserData(); const { projectSocket } = useSocketStore(); const [recentDuplicateData, setRecentDuplicateData] = useState({}); - const fetchRecentProjects = async () => { try { const projects = await recentlyViewed(organization, userId); @@ -38,9 +38,7 @@ const DashboardHome: React.FC = () => { if (JSON.stringify(projects) !== JSON.stringify(recentProjects)) { setRecentProjects(projects); } - } catch (error) { - console.error("Error fetching recent projects:", error); - } + } catch (error) {} }; const handleRecentProjectSearch = async (inputValue: string) => { @@ -65,7 +63,7 @@ const DashboardHome: React.FC = () => { // userId, // organization // ); - // console.log('deletedProject: ', deletedProject); + // //socket for delete Project const deleteProject = { @@ -91,9 +89,7 @@ const DashboardHome: React.FC = () => { }; }); setIsSearchActive(false); - } catch (error) { - console.error("Error deleting project:", error); - } + } catch (error) {} }; const handleDuplicateRecentProject = async ( @@ -163,4 +159,4 @@ const DashboardHome: React.FC = () => { ); }; -export default DashboardHome; \ No newline at end of file +export default DashboardHome; diff --git a/app/src/components/Dashboard/DashboardProjects.tsx b/app/src/components/Dashboard/DashboardProjects.tsx index ccb56b2..51888d0 100644 --- a/app/src/components/Dashboard/DashboardProjects.tsx +++ b/app/src/components/Dashboard/DashboardProjects.tsx @@ -9,6 +9,7 @@ import { deleteProject } from "../../services/dashboard/deleteProject"; import ProjectSocketRes from "./socket/projectSocketRes.dev"; import { sharedWithMeProjects } from "../../services/dashboard/sharedWithMeProject"; import { duplicateProject } from "../../services/dashboard/duplicateProject"; +import { generateUniqueId } from "../../functions/generateUniqueId"; interface Project { _id: string; @@ -27,7 +28,7 @@ const DashboardProjects: React.FC = () => { const [workspaceProjects, setWorkspaceProjects] = useState( {} ); - const [sharedwithMeProject, setSharedWithMeProjects] = useState([]) + const [sharedwithMeProject, setSharedWithMeProjects] = useState([]); const [projectDuplicateData, setProjectDuplicateData] = useState({}); const [isSearchActive, setIsSearchActive] = useState(false); const [activeFolder, setActiveFolder] = useState("myProjects"); @@ -41,7 +42,11 @@ const DashboardProjects: React.FC = () => { } if (!setWorkspaceProjects || !setIsSearchActive) return; - const searchedProject = await searchProject(organization, userId, inputValue); + const searchedProject = await searchProject( + organization, + userId, + inputValue + ); setIsSearchActive(true); setWorkspaceProjects(searchedProject.message ? {} : searchedProject); }; @@ -49,14 +54,13 @@ const DashboardProjects: React.FC = () => { const fetchAllProjects = async () => { try { const projects = await getAllProjects(userId, organization); + if (!projects || !projects.Projects) return; if (JSON.stringify(projects) !== JSON.stringify(workspaceProjects)) { setWorkspaceProjects(projects); } - } catch (error) { - console.error("Error fetching projects:", error); - } + } catch (error) {} }; const handleDeleteProject = async (projectId: any) => { @@ -66,7 +70,7 @@ const DashboardProjects: React.FC = () => { // userId, // organization // ); - // console.log('deletedProject: ', deletedProject); + // const deleteProjects = { projectId, organization, @@ -77,7 +81,6 @@ const DashboardProjects: React.FC = () => { if (projectSocket) { projectSocket.emit("v1:project:delete", deleteProjects); } else { - console.error("Socket is not connected."); } setWorkspaceProjects((prevDiscardedProjects: WorkspaceProjects) => { if (!Array.isArray(prevDiscardedProjects?.Projects)) { @@ -92,16 +95,21 @@ const DashboardProjects: React.FC = () => { }; }); setIsSearchActive(false); - } catch (error) { - console.error("Error deleting project:", error); - } + } catch (error) {} }; const handleDuplicateWorkspaceProject = async ( projectId: string, projectName: string, - thumbnail: string, + thumbnail: string ) => { + const duplicatedProject = await duplicateProject( + projectId, + generateUniqueId(), + thumbnail, + projectName + ); + console.log("duplicatedProject: ", duplicatedProject); const duplicateProjectData = { userId, @@ -110,7 +118,7 @@ const DashboardProjects: React.FC = () => { projectUuid: projectId, projectName, }; - projectSocket.emit("v1:project:Duplicate", duplicateProjectData); + // projectSocket.emit("v1:project:Duplicate", duplicateProjectData); }; const renderProjects = () => { @@ -153,16 +161,12 @@ const DashboardProjects: React.FC = () => { )); }; - const sharedProject = async () => { try { const sharedWithMe = await sharedWithMeProjects(); - setSharedWithMeProjects(sharedWithMe) - } catch { - - } - } - + setSharedWithMeProjects(sharedWithMe); + } catch {} + }; useEffect(() => { if (!isSearchActive) { @@ -172,10 +176,9 @@ const DashboardProjects: React.FC = () => { useEffect(() => { if (activeFolder === "shared") { - sharedProject() + sharedProject(); } - }, [activeFolder]) - + }, [activeFolder]); return (
@@ -184,7 +187,10 @@ const DashboardProjects: React.FC = () => { handleProjectsSearch={handleProjectsSearch} /> -
+
-
{activeFolder == "myProjects" ? renderProjects() : renderSharedProjects()}
+
+ {activeFolder == "myProjects" + ? renderProjects() + : renderSharedProjects()} +
- {projectDuplicateData && Object.keys(projectDuplicateData).length > 0 && ( - - )} + {projectDuplicateData && + Object.keys(projectDuplicateData).length > 0 && ( + + )}
); }; export default DashboardProjects; - - diff --git a/app/src/components/ui/FileMenu.tsx b/app/src/components/ui/FileMenu.tsx index 86146ba..0f0aabe 100644 --- a/app/src/components/ui/FileMenu.tsx +++ b/app/src/components/ui/FileMenu.tsx @@ -10,100 +10,101 @@ import { updateProject } from "../../services/dashboard/updateProject"; import { getUserData } from "../../functions/getUserData"; const FileMenu: React.FC = () => { - const [openMenu, setOpenMenu] = useState(false); - const containerRef = useRef(null); - let clickTimeout: NodeJS.Timeout | null = null; - const { projectName, setProjectName } = useProjectName(); - const { dashBoardSocket } = useSocketStore(); - const { projectId } = useParams(); - const { userId, organization, email } = getUserData(); + const [openMenu, setOpenMenu] = useState(false); + const containerRef = useRef(null); + let clickTimeout: NodeJS.Timeout | null = null; + const { projectName, setProjectName } = useProjectName(); + const { dashBoardSocket } = useSocketStore(); + const { projectId } = useParams(); + const { userId, organization, email } = getUserData(); - const handleClick = () => { - if (clickTimeout) return; - setOpenMenu((prev) => !prev); - clickTimeout = setTimeout(() => { - clickTimeout = null; - }, 800); + const handleClick = () => { + if (clickTimeout) return; + setOpenMenu((prev) => !prev); + clickTimeout = setTimeout(() => { + clickTimeout = null; + }, 800); + }; + + useEffect(() => { + const handleClickOutside = (event: MouseEvent) => { + if ( + containerRef.current && + !containerRef.current.contains(event.target as Node) + ) { + setOpenMenu(false); + } }; - useEffect(() => { - const handleClickOutside = (event: MouseEvent) => { - if ( - containerRef.current && - !containerRef.current.contains(event.target as Node) - ) { - setOpenMenu(false); - } - }; + document.addEventListener("mousedown", handleClickOutside); + return () => document.removeEventListener("mousedown", handleClickOutside); + }, []); - document.addEventListener("mousedown", handleClickOutside); - return () => document.removeEventListener("mousedown", handleClickOutside); - }, []); + const handleProjectRename = async (projectName: string) => { + setProjectName(projectName); + if (!projectId) return; - const handleProjectRename = async (projectName: string) => { - setProjectName(projectName); - if (!projectId) return + // localStorage.setItem("projectName", newName); - // localStorage.setItem("projectName", newName); + try { + if (!email || !userId) return; - try { + const projects = await getAllProjects(userId, organization); + if (!projects || !projects.Projects) return; + // console.log('projects: ', projects); + let projectUuid = projects.Projects.find( + (val: any) => val.projectUuid === projectId || val._id === projectId + ); - if (!email || !userId) return; + const updateProjects = { + projectId: projectUuid?._id, + organization, + userId, + projectName, + thumbnail: undefined, + }; - const projects = await getAllProjects(userId, organization); - if (!projects || !projects.Projects) return; - // console.log('projects: ', projects); - let projectUuid = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId) + // if (dashBoardSocket) { + // const handleResponse = (data: any) => { + // console.log('Project update response:', data); + // dashBoardSocket.off("v1-project:response:update", handleResponse); // Clean up + // }; + // dashBoardSocket.on("v1-project:response:update", handleResponse); + // dashBoardSocket.emit("v1:project:update", updateProjects); + // } - const updateProjects = { - projectId: projectUuid, - organization, - userId, - projectName, - thumbnail: undefined - } - - // if (dashBoardSocket) { - // const handleResponse = (data: any) => { - // console.log('Project update response:', data); - // dashBoardSocket.off("v1-project:response:update", handleResponse); // Clean up - // }; - // dashBoardSocket.on("v1-project:response:update", handleResponse); - // dashBoardSocket.emit("v1:project:update", updateProjects); - // } - - //API for projects rename - const updatedProjectName = await updateProject( - projectId, - userId, - organization, - undefined, - projectName - ); - // - } catch (error) { - console.error("Error updating project name:", error); - } - }; - return ( - - ); + //API for projects rename + const updatedProjectName = await updateProject( + projectId, + userId, + organization, + undefined, + projectName + ); + console.log("updatedProjectName: ", updatedProjectName, projectId); + } catch (error) { + console.error("Error updating project name:", error); + } + }; + return ( + + ); }; export default FileMenu; diff --git a/app/src/modules/scene/scene.tsx b/app/src/modules/scene/scene.tsx index 22e18ac..67f2ef2 100644 --- a/app/src/modules/scene/scene.tsx +++ b/app/src/modules/scene/scene.tsx @@ -16,69 +16,89 @@ import { useLoadingProgress, useSocketStore } from "../../store/builder/store"; import { Color, SRGBColorSpace } from "three"; import StatsHelper from "./helpers/StatsHelper"; -export default function Scene({ layout }: { readonly layout: 'Main Layout' | 'Comparison Layout' }) { - const map = useMemo(() => [ - { name: "forward", keys: ["ArrowUp", "w", "W"] }, - { name: "backward", keys: ["ArrowDown", "s", "S"] }, - { name: "left", keys: ["ArrowLeft", "a", "A"] }, - { name: "right", keys: ["ArrowRight", "d", "D"] }, - ], []); - const { assetStore } = useSceneContext(); - const { assets } = assetStore(); - const { userId, organization } = getUserData(); - const { projectId } = useParams(); - const { projectSocket } = useSocketStore(); - const { activeModule } = useModuleStore(); - const { loadingProgress } = useLoadingProgress(); +export default function Scene({ + layout, +}: { + readonly layout: "Main Layout" | "Comparison Layout"; +}) { + const map = useMemo( + () => [ + { name: "forward", keys: ["ArrowUp", "w", "W"] }, + { name: "backward", keys: ["ArrowDown", "s", "S"] }, + { name: "left", keys: ["ArrowLeft", "a", "A"] }, + { name: "right", keys: ["ArrowRight", "d", "D"] }, + ], + [] + ); + const { assetStore } = useSceneContext(); + const { assets } = assetStore(); + const { userId, organization } = getUserData(); + const { projectId } = useParams(); + const { projectSocket } = useSocketStore(); + const { activeModule } = useModuleStore(); + const { loadingProgress } = useLoadingProgress(); - useEffect(() => { - if (!projectId && loadingProgress > 1) return; - getAllProjects(userId, organization) - .then((projects) => { - if (!projects || !projects.Projects) return; - let project = projects.Projects.find((val: any) => val.projectUuid === projectId || val._id === projectId); - const canvas = document.getElementById("sceneCanvas")?.getElementsByTagName('canvas')[0]; - if (!canvas) return; - const screenshotDataUrl = (canvas as HTMLCanvasElement)?.toDataURL("image/png"); - const updateProjects = { - projectId: project?.projectUuid, - organization, - userId, - projectName: project?.projectName, - thumbnail: screenshotDataUrl, - }; - if (projectSocket) { - projectSocket.emit("v1:project:update", updateProjects); - } - }).catch((err) => { - console.error(err); - }); - // eslint-disable-next-line - }, [activeModule, assets, loadingProgress]) + useEffect(() => { + if (!projectId && loadingProgress > 1) return; + getAllProjects(userId, organization) + .then((projects) => { + if (!projects || !projects.Projects) return; + let project = projects.Projects.find( + (val: any) => val.projectUuid === projectId || val._id === projectId + ); + const canvas = document + .getElementById("sceneCanvas") + ?.getElementsByTagName("canvas")[0]; + if (!canvas) return; + const screenshotDataUrl = (canvas as HTMLCanvasElement)?.toDataURL( + "image/png" + ); + const updateProjects = { + projectId: project?._id, + organization, + userId, + projectName: project?.projectName, + thumbnail: screenshotDataUrl, + }; + if (projectSocket) { + projectSocket.emit("v1:project:update", updateProjects); + } + }) + .catch((err) => { + console.error(err); + }); + // eslint-disable-next-line + }, [activeModule, assets, loadingProgress]); - return ( - - { - e.preventDefault(); - }} - performance={{ min: 0.9, max: 1.0 }} - onCreated={(e) => { - e.scene.background = layout === 'Main Layout' ? null : new Color(0x19191d); - }} - gl={{ outputColorSpace: SRGBColorSpace, powerPreference: "high-performance", antialias: true, preserveDrawingBuffer: true }} - > - - - - - - - - - ); + return ( + + { + e.preventDefault(); + }} + performance={{ min: 0.9, max: 1.0 }} + onCreated={(e) => { + e.scene.background = + layout === "Main Layout" ? null : new Color(0x19191d); + }} + gl={{ + outputColorSpace: SRGBColorSpace, + powerPreference: "high-performance", + antialias: true, + preserveDrawingBuffer: true, + }} + > + + + + + + + + + ); } diff --git a/app/src/pages/Project.tsx b/app/src/pages/Project.tsx index 96c529f..2ee6b29 100644 --- a/app/src/pages/Project.tsx +++ b/app/src/pages/Project.tsx @@ -33,7 +33,8 @@ const Project: React.FC = () => { const { setUserName } = useUserName(); const { setOrganization } = useOrganization(); const { projectId } = useParams(); - const { setProjectName } = useProjectName(); + const { projectName, setProjectName } = useProjectName(); + console.log("projectName: ", projectName); const { userId, email, organization, userName } = getUserData(); const { selectedUser } = useSelectedUserStore(); const { isLogListVisible } = useLogger(); @@ -49,6 +50,7 @@ const Project: React.FC = () => { const fetchProjects = async () => { try { const projects = await getAllProjects(userId, organization); + console.log("projects: ", projects); const shared = await sharedWithMeProjects(); const allProjects = [...(projects?.Projects || []), ...(shared || [])]; @@ -56,7 +58,6 @@ const Project: React.FC = () => { const matchedProject = allProjects.find( (val: any) => val.projectUuid === projectId || val._id === projectId ); - if (matchedProject) { setProjectName(matchedProject.projectName); await viewProject(organization, matchedProject._id, userId); diff --git a/app/src/services/dashboard/duplicateProject.ts b/app/src/services/dashboard/duplicateProject.ts index 837bb0e..68fe5c6 100644 --- a/app/src/services/dashboard/duplicateProject.ts +++ b/app/src/services/dashboard/duplicateProject.ts @@ -1,6 +1,7 @@ let url_Backend_dwinzo = `http://${process.env.REACT_APP_SERVER_REST_API_BASE_URL}`; export const duplicateProject = async ( + refProjectID: string, projectUuid: string, thumbnail: string, projectName: string @@ -16,7 +17,12 @@ export const duplicateProject = async ( token: localStorage.getItem("token") || "", // Coerce null to empty string refresh_token: localStorage.getItem("refreshToken") || "", }, - body: JSON.stringify({ projectUuid, thumbnail, projectName }), + body: JSON.stringify({ + refProjectID, + projectUuid, + thumbnail, + projectName, + }), } ); const newAccessToken = response.headers.get("x-access-token"); @@ -24,7 +30,7 @@ export const duplicateProject = async ( //console.log("New token received:", newAccessToken); localStorage.setItem("token", newAccessToken); } - // console.log("response: ", response); + console.log("response: ", response); if (!response.ok) { console.error("Failed to add project"); } diff --git a/app/src/services/dashboard/updateProject.ts b/app/src/services/dashboard/updateProject.ts index 42e0d44..ab9ac0f 100644 --- a/app/src/services/dashboard/updateProject.ts +++ b/app/src/services/dashboard/updateProject.ts @@ -30,6 +30,7 @@ export const updateProject = async ( body: JSON.stringify(body), } ); + console.log('body: ', body); const newAccessToken = response.headers.get("x-access-token"); if (newAccessToken) { @@ -41,6 +42,7 @@ export const updateProject = async ( } const result = await response.json(); + console.log('result: ', result); return result; } catch (error) { if (error instanceof Error) { diff --git a/app/src/store/simulation/useProductStore.ts b/app/src/store/simulation/useProductStore.ts index 258a8cb..3c338b1 100644 --- a/app/src/store/simulation/useProductStore.ts +++ b/app/src/store/simulation/useProductStore.ts @@ -1,943 +1,1290 @@ -import { create } from 'zustand'; -import { immer } from 'zustand/middleware/immer'; +import { create } from "zustand"; +import { immer } from "zustand/middleware/immer"; type ProductsStore = { - products: productsSchema; + products: productsSchema; - // Product-level actions - addProduct: (productName: string, productUuid: string) => void; - setProducts: (products: productsSchema) => void; - clearProducts: () => void; - removeProduct: (productUuid: string) => void; - updateProduct: (productUuid: string, updates: Partial<{ productName: string; eventDatas: EventsSchema[] }>) => void; + // Product-level actions + addProduct: (productName: string, productUuid: string) => void; + setProducts: (products: productsSchema) => void; + clearProducts: () => void; + removeProduct: (productUuid: string) => void; + updateProduct: ( + productUuid: string, + updates: Partial<{ productName: string; eventDatas: EventsSchema[] }> + ) => void; - // Event-level actions - addEvent: (productUuid: string, event: EventsSchema) => void; - removeEvent: (productUuid: string, modelUuid: string) => void; - deleteEvent: (modelUuid: string) => EventsSchema[]; - updateEvent: (productUuid: string, modelUuid: string, updates: Partial) => EventsSchema | undefined; + // Event-level actions + addEvent: (productUuid: string, event: EventsSchema) => void; + removeEvent: (productUuid: string, modelUuid: string) => void; + deleteEvent: (modelUuid: string) => EventsSchema[]; + updateEvent: ( + productUuid: string, + modelUuid: string, + updates: Partial + ) => EventsSchema | undefined; - // Point-level actions - addPoint: (productUuid: string, modelUuid: string, point: ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema) => EventsSchema | undefined; - removePoint: (productUuid: string, modelUuid: string, pointUuid: string) => EventsSchema | undefined; - updatePoint: ( - productUuid: string, - modelUuid: string, - pointUuid: string, - updates: Partial - ) => EventsSchema | undefined; + // Point-level actions + addPoint: ( + productUuid: string, + modelUuid: string, + point: + | ConveyorPointSchema + | VehiclePointSchema + | RoboticArmPointSchema + | MachinePointSchema + | StoragePointSchema + | HumanPointSchema + ) => EventsSchema | undefined; + removePoint: ( + productUuid: string, + modelUuid: string, + pointUuid: string + ) => EventsSchema | undefined; + updatePoint: ( + productUuid: string, + modelUuid: string, + pointUuid: string, + updates: Partial< + | ConveyorPointSchema + | VehiclePointSchema + | RoboticArmPointSchema + | MachinePointSchema + | StoragePointSchema + | HumanPointSchema + > + ) => EventsSchema | undefined; - // Action-level actions - addAction: ( - productUuid: string, - modelUuid: string, - pointUuid: string, - action: ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0] - ) => EventsSchema | undefined; - removeAction: (productUuid: string, actionUuid: string) => EventsSchema | undefined; - updateAction: ( - productUuid: string, - actionUuid: string, - updates: Partial - ) => EventsSchema | undefined; + // Action-level actions + addAction: ( + productUuid: string, + modelUuid: string, + pointUuid: string, + action: + | ConveyorPointSchema["action"] + | VehiclePointSchema["action"] + | RoboticArmPointSchema["actions"][0] + | MachinePointSchema["action"] + | StoragePointSchema["action"] + | HumanPointSchema["actions"][0] + ) => EventsSchema | undefined; + removeAction: ( + productUuid: string, + actionUuid: string + ) => EventsSchema | undefined; + updateAction: ( + productUuid: string, + actionUuid: string, + updates: Partial< + | ConveyorPointSchema["action"] + | VehiclePointSchema["action"] + | RoboticArmPointSchema["actions"][0] + | MachinePointSchema["action"] + | StoragePointSchema["action"] + | HumanPointSchema["actions"][0] + > + ) => EventsSchema | undefined; - // Trigger-level actionss - addTrigger: ( - productUuid: string, - actionUuid: string, - trigger: TriggerSchema - ) => EventsSchema | undefined; - removeTrigger: (productUuid: string, triggerUuid: string) => EventsSchema | undefined; - updateTrigger: ( - productUuid: string, - triggerUuid: string, - updates: Partial - ) => EventsSchema | undefined; + // Trigger-level actionss + addTrigger: ( + productUuid: string, + actionUuid: string, + trigger: TriggerSchema + ) => EventsSchema | undefined; + removeTrigger: ( + productUuid: string, + triggerUuid: string + ) => EventsSchema | undefined; + updateTrigger: ( + productUuid: string, + triggerUuid: string, + updates: Partial + ) => EventsSchema | undefined; - // Renaming functions - renameProduct: (productUuid: string, newName: string) => void; - renameAction: (productUuid: string, actionUuid: string, newName: string) => EventsSchema | undefined; - renameTrigger: (productUuid: string, triggerUuid: string, newName: string) => EventsSchema | undefined; + // Renaming functions + renameProduct: (productUuid: string, newName: string) => void; + renameAction: ( + productUuid: string, + actionUuid: string, + newName: string + ) => EventsSchema | undefined; + renameTrigger: ( + productUuid: string, + triggerUuid: string, + newName: string + ) => EventsSchema | undefined; - // Helper functions - getProductById: (productUuid: string) => { productName: string; productUuid: string; eventDatas: EventsSchema[] } | undefined; - getEventByModelUuid: (productUuid: string, modelUuid: string) => EventsSchema | undefined; - getEventByActionUuid: (productUuid: string, actionUuid: string) => EventsSchema | undefined; - getEventByTriggerUuid: (productUuid: string, triggerUuid: string) => EventsSchema | undefined; - getEventByPointUuid: (productUuid: string, pointUuid: string) => EventsSchema | undefined; - getPointByUuid: (productUuid: string, modelUuid: string, pointUuid: string) => ConveyorPointSchema | VehiclePointSchema | RoboticArmPointSchema | MachinePointSchema | StoragePointSchema | HumanPointSchema | undefined; - getActionByUuid: (productUuid: string, actionUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]) | undefined; - getActionByPointUuid: (productUuid: string, pointUuid: string) => (ConveyorPointSchema['action'] | VehiclePointSchema['action'] | RoboticArmPointSchema['actions'][0] | MachinePointSchema['action'] | StoragePointSchema['action'] | HumanPointSchema['actions'][0]) | undefined; - getModelUuidByPointUuid: (productUuid: string, actionUuid: string) => (string) | undefined; - getModelUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined; - getPointUuidByActionUuid: (productUuid: string, actionUuid: string) => (string) | undefined; - getTriggerByUuid: (productUuid: string, triggerUuid: string) => TriggerSchema | undefined; - getTriggersByTriggeredPointUuid: (productUuid: string, triggeredPointUuid: string) => TriggerSchema[]; - getIsEventInProduct: (productUuid: string, modelUuid: string) => boolean; + // Helper functions + getProductById: ( + productUuid: string + ) => + | { productName: string; productUuid: string; eventDatas: EventsSchema[] } + | undefined; + getEventByModelUuid: ( + productUuid: string, + modelUuid: string + ) => EventsSchema | undefined; + getEventByActionUuid: ( + productUuid: string, + actionUuid: string + ) => EventsSchema | undefined; + getEventByTriggerUuid: ( + productUuid: string, + triggerUuid: string + ) => EventsSchema | undefined; + getEventByPointUuid: ( + productUuid: string, + pointUuid: string + ) => EventsSchema | undefined; + getPointByUuid: ( + productUuid: string, + modelUuid: string, + pointUuid: string + ) => + | ConveyorPointSchema + | VehiclePointSchema + | RoboticArmPointSchema + | MachinePointSchema + | StoragePointSchema + | HumanPointSchema + | undefined; + getActionByUuid: ( + productUuid: string, + actionUuid: string + ) => + | ( + | ConveyorPointSchema["action"] + | VehiclePointSchema["action"] + | RoboticArmPointSchema["actions"][0] + | MachinePointSchema["action"] + | StoragePointSchema["action"] + | HumanPointSchema["actions"][0] + ) + | undefined; + getActionByPointUuid: ( + productUuid: string, + pointUuid: string + ) => + | ( + | ConveyorPointSchema["action"] + | VehiclePointSchema["action"] + | RoboticArmPointSchema["actions"][0] + | MachinePointSchema["action"] + | StoragePointSchema["action"] + | HumanPointSchema["actions"][0] + ) + | undefined; + getModelUuidByPointUuid: ( + productUuid: string, + actionUuid: string + ) => string | undefined; + getModelUuidByActionUuid: ( + productUuid: string, + actionUuid: string + ) => string | undefined; + getPointUuidByActionUuid: ( + productUuid: string, + actionUuid: string + ) => string | undefined; + getTriggerByUuid: ( + productUuid: string, + triggerUuid: string + ) => TriggerSchema | undefined; + getTriggersByTriggeredPointUuid: ( + productUuid: string, + triggeredPointUuid: string + ) => TriggerSchema[]; + getIsEventInProduct: (productUuid: string, modelUuid: string) => boolean; }; export const createProductStore = () => { - return create()( - immer((set, get) => ({ - products: [], + return create()( + immer((set, get) => ({ + products: [], - // Product-level actions - addProduct: (productName, productUuid) => { - set((state) => { - const existingProduct = state.products.find(p => p.productUuid === productUuid); - if (!existingProduct) { - const newProduct = { - productName, - productUuid: productUuid, - eventDatas: [] - }; - state.products.push(newProduct); - } - }); - }, + // Product-level actions + addProduct: (productName, productUuid) => { + set((state) => { + const existingProduct = state.products.find( + (p) => p.productUuid === productUuid + ); + if (!existingProduct) { + const newProduct = { + productName, + productUuid: productUuid, + eventDatas: [], + }; + state.products.push(newProduct); + } + }); + }, - setProducts: (products) => { - set((state) => { - state.products = products; - }); - }, + setProducts: (products) => { + set((state) => { + state.products = products; + }); + }, - clearProducts: () => { - set((state) => { - state.products = []; - }); - }, + clearProducts: () => { + set((state) => { + state.products = []; + }); + }, - removeProduct: (productUuid) => { - set((state) => { - state.products = state.products.filter(p => p.productUuid !== productUuid); - }); - }, + removeProduct: (productUuid) => { + set((state) => { + state.products = state.products.filter( + (p) => p.productUuid !== productUuid + ); + }); + }, - updateProduct: (productUuid, updates) => { - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - Object.assign(product, updates); - } - }); - }, + updateProduct: (productUuid, updates) => { + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + Object.assign(product, updates); + } + }); + }, - // Event-level actions - addEvent: (productUuid, event) => { - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - const existingEvent = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === event.modelUuid); - if (!existingEvent) { - product.eventDatas.push(event); - } - } - }); - }, - - removeEvent: (productUuid, modelUuid) => { - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - product.eventDatas = product.eventDatas.filter(e => 'modelUuid' in e && e.modelUuid !== modelUuid); - } - }); - }, - - deleteEvent: (modelUuid) => { - let updatedEvents: EventsSchema[] = []; - set((state) => { - const actionsToDelete = new Set(); - - for (const product of state.products) { - const eventIndex = product.eventDatas.findIndex(e => 'modelUuid' in e && e.modelUuid === modelUuid); - if (eventIndex !== -1) { - const event = product.eventDatas[eventIndex]; - - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action) { - actionsToDelete.add(point.action.actionUuid); - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && point.action) { - actionsToDelete.add(point.action.actionUuid); - } else if ('actions' in point) { - for (const action of point.actions) { - actionsToDelete.add(action.actionUuid); - } - } - } - - product.eventDatas.splice(eventIndex, 1); - } - } - - for (const product of state.products) { - for (const event of product.eventDatas) { - let eventModified = false; - - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action?.triggers) { - const originalLength = point.action.triggers.length; - point.action.triggers = point.action.triggers.filter(trigger => { - return !( - (trigger.triggeredAsset?.triggeredModel?.modelUuid === modelUuid) || - (actionsToDelete.has(trigger.triggeredAsset?.triggeredAction?.actionUuid || '')) - ); - }); - if (point.action.triggers.length !== originalLength) { - eventModified = true; - } - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && point.action?.triggers) { - const originalLength = point.action.triggers.length; - point.action.triggers = point.action.triggers.filter((trigger: TriggerSchema) => { - return !( - (trigger.triggeredAsset?.triggeredModel?.modelUuid === modelUuid) || - (actionsToDelete.has(trigger.triggeredAsset?.triggeredAction?.actionUuid || '')) - ); - }); - if (point.action.triggers.length !== originalLength) { - eventModified = true; - } - } else if ('actions' in point) { - for (const action of point.actions) { - if (action.triggers) { - const originalLength = action.triggers.length; - action.triggers = action.triggers.filter((trigger: TriggerSchema) => { - return !( - (trigger.triggeredAsset?.triggeredModel?.modelUuid === modelUuid) || - (actionsToDelete.has(trigger.triggeredAsset?.triggeredAction?.actionUuid || '')) - ); - }); - if (action.triggers.length !== originalLength) { - eventModified = true; - } - } - } - } - } - - if (eventModified) { - updatedEvents.push(JSON.parse(JSON.stringify(event))); - } - } - } - }); - return updatedEvents; - }, - - updateEvent: (productUuid, modelUuid, updates) => { - let updatedEvent: EventsSchema | undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); - if (event) { - Object.assign(event, updates); - updatedEvent = JSON.parse(JSON.stringify(event)); - } - } - }); - return updatedEvent; - }, - - // Point-level actions - addPoint: (productUuid, modelUuid, point) => { - let updatedEvent: EventsSchema | undefined = undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); - if (event && 'points' in event) { - const existingPoint = (event as ConveyorEventSchema).points.find(p => p.uuid === point.uuid); - if (!existingPoint) { - (event as ConveyorEventSchema).points.push(point as ConveyorPointSchema); - updatedEvent = JSON.parse(JSON.stringify(event)); - } - } else if (event && 'point' in event) { - const existingPoint = (event as any).point?.uuid === point.uuid; - if (!existingPoint) { - (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point = point as any; - updatedEvent = JSON.parse(JSON.stringify(event)); - } - } - } - }); - return updatedEvent; - }, - - removePoint: (productUuid, modelUuid, pointUuid) => { - let updatedEvent: EventsSchema | undefined = undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); - if (event && 'points' in event) { - (event as ConveyorEventSchema).points = (event as ConveyorEventSchema).points.filter(p => p.uuid !== pointUuid); - updatedEvent = JSON.parse(JSON.stringify(event)); - } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) { - // For events with single point, we can't remove it, only reset to empty - } - } - }); - return updatedEvent; - }, - - updatePoint: (productUuid, modelUuid, pointUuid, updates) => { - let updatedEvent: EventsSchema | undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); - if (event && 'points' in event) { - const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid); - if (point) { - Object.assign(point, updates); - updatedEvent = JSON.parse(JSON.stringify(event)); - } - } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) { - Object.assign((event as any).point, updates); - updatedEvent = JSON.parse(JSON.stringify(event)); - } - } - }); - return updatedEvent; - }, - - // Action-level actions - addAction: (productUuid, modelUuid, pointUuid, action) => { - let updatedEvent: EventsSchema | undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - const event = product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); - if (event && 'points' in event) { - const point = (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid); - if (point && (!point.action || point.action.actionUuid !== action.actionUuid)) { - point.action = action as any; - updatedEvent = JSON.parse(JSON.stringify(event)); - } - } else if (event && 'point' in event && (event as any).point.uuid === pointUuid) { - if ('action' in (event as any).point) { - if (!(event as any).point.action || (event as any).point.action.actionUuid !== action.actionUuid) { - (event as any).point.action = action; - updatedEvent = JSON.parse(JSON.stringify(event)); - } - } else if ('actions' in (event as any).point) { - const existingAction = (event as any).point.actions.find((a: any) => a.actionUuid === action.actionUuid); - if (!existingAction) { - (event as any).point.actions.push(action); - updatedEvent = JSON.parse(JSON.stringify(event)); - } - } - } - } - }); - return updatedEvent; - }, - - removeAction: (productUuid, actionUuid) => { - let updatedEvent: EventsSchema | undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - for (const event of product.eventDatas) { - if ('points' in event) { - // Handle ConveyorEventSchema - for (const point of (event as ConveyorEventSchema).points) { - } - } else if ('point' in event) { - const point = (event as any).point; - if (event.type === "roboticArm") { - if ('actions' in point) { - const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid); - if (index !== -1) { - point.actions.splice(index, 1); - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } - } else if (event.type === "human") { - if ('actions' in point) { - const index = point.actions.findIndex((a: any) => a.actionUuid === actionUuid); - if (index !== -1) { - point.actions.splice(index, 1); - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } - } else if ('action' in point && point.action?.actionUuid === actionUuid) { - point.action = undefined; - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } - } - } - }); - return updatedEvent; - }, - - updateAction: (productUuid, actionUuid, updates) => { - let updatedEvent: EventsSchema | undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action && point.action.actionUuid === actionUuid) { - Object.assign(point.action, updates); - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && point.action.actionUuid === actionUuid) { - Object.assign(point.action, updates); - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } else if ('actions' in point) { - const action = point.actions.find((a: any) => a.actionUuid === actionUuid); - if (action) { - Object.assign(action, updates); - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } - } - } - } - }); - return updatedEvent; - }, - - // Trigger-level actions - addTrigger: (productUuid, actionUuid, trigger) => { - let updatedEvent: EventsSchema | undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action && point.action.actionUuid === actionUuid) { - const existingTrigger = point.action.triggers.find(t => t.triggerUuid === trigger.triggerUuid); - if (!existingTrigger) { - point.action.triggers.push(trigger); - updatedEvent = JSON.parse(JSON.stringify(event)); - } - return; - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && point.action.actionUuid === actionUuid) { - const existingTrigger = point.action.triggers.find((t: any) => t.triggerUuid === trigger.triggerUuid); - if (!existingTrigger) { - point.action.triggers.push(trigger); - updatedEvent = JSON.parse(JSON.stringify(event)); - } - return; - } else if ('actions' in point) { - const action = point.actions.find((a: any) => a.actionUuid === actionUuid); - if (action) { - const existingTrigger = action.triggers.find((t: any) => t.triggerUuid === trigger.triggerUuid); - if (!existingTrigger) { - action.triggers.push(trigger); - updatedEvent = JSON.parse(JSON.stringify(event)); - } - return; - } - } - } - } - } - }); - return updatedEvent; - }, - - removeTrigger: (productUuid, triggerUuid) => { - let updatedEvent: EventsSchema | undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action && 'triggers' in point.action) { - const Trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid); - if (Trigger) { - point.action.triggers = point.action.triggers.filter(t => t.triggerUuid !== triggerUuid); - updatedEvent = JSON.parse(JSON.stringify(event)); - } - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && 'triggers' in point.action) { - const Trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid); - if (Trigger) { - point.action.triggers = point.action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid); - updatedEvent = JSON.parse(JSON.stringify(event)); - } - } else if ('actions' in point) { - for (const action of point.actions) { - if ('triggers' in action) { - const Trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid); - if (Trigger) { - action.triggers = action.triggers.filter((t: any) => t.triggerUuid !== triggerUuid); - updatedEvent = JSON.parse(JSON.stringify(event)); - } - } - } - } - } - } - } - }); - return updatedEvent; - }, - - updateTrigger: (productUuid, triggerUuid, updates) => { - let updatedEvent: EventsSchema | undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action && 'triggers' in point.action) { - const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid); - if (trigger) { - Object.assign(trigger, updates); - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && 'triggers' in point.action) { - const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid); - if (trigger) { - Object.assign(trigger, updates); - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } else if ('actions' in point) { - for (const action of point.actions) { - if ('triggers' in action) { - const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid); - if (trigger) { - Object.assign(trigger, updates); - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } - } - } - } - } - } - }); - return updatedEvent; - }, - - // Renaming functions - renameProduct: (productUuid, newName) => { - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - product.productName = newName; - } - }); - }, - - renameAction: (productUuid, actionUuid, newName) => { - let updatedEvent: EventsSchema | undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action && point.action.actionUuid === actionUuid) { - point.action.actionName = newName; - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && point.action.actionUuid === actionUuid) { - point.action.actionName = newName; - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } else if ('actions' in point) { - const action = point.actions.find((a: any) => a.actionUuid === actionUuid); - if (action) { - action.actionName = newName; - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } - } - } - } - }); - return updatedEvent; - }, - - renameTrigger: (productUuid, triggerUuid, newName) => { - let updatedEvent: EventsSchema | undefined; - set((state) => { - const product = state.products.find(p => p.productUuid === productUuid); - if (product) { - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action && 'triggers' in point.action) { - const trigger = point.action.triggers.find(t => t.triggerUuid === triggerUuid); - if (trigger) { - trigger.triggerName = newName; - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && 'triggers' in point.action) { - const trigger = point.action.triggers.find((t: any) => t.triggerUuid === triggerUuid); - if (trigger) { - trigger.triggerName = newName; - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } else if ('actions' in point) { - for (const action of point.actions) { - if ('triggers' in action) { - const trigger = action.triggers.find((t: any) => t.triggerUuid === triggerUuid); - if (trigger) { - trigger.triggerName = newName; - updatedEvent = JSON.parse(JSON.stringify(event)); - return; - } - } - } - } - } - } - } - }); - return updatedEvent; - }, - - // Helper functions - getProductById: (productUuid) => { - return get().products.find(p => p.productUuid === productUuid); - }, - - getEventByModelUuid: (productUuid, modelUuid) => { - const product = get().getProductById(productUuid); - if (!product) return undefined; - return product.eventDatas.find(e => 'modelUuid' in e && e.modelUuid === modelUuid); - }, - - getEventByActionUuid: (productUuid, actionUuid) => { - const product = get().getProductById(productUuid); - if (!product) return undefined; - - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action?.actionUuid === actionUuid) { - return event; - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && point.action?.actionUuid === actionUuid) { - return event; - } else if ('actions' in point) { - const action = point.actions.find((a: any) => a.actionUuid === actionUuid); - if (action) { - return event; - } - } - } - } - return undefined; - }, - - getEventByTriggerUuid: (productUuid, triggerUuid) => { - const product = get().getProductById(productUuid); - if (!product) return undefined; - - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action?.triggers?.some(t => t.triggerUuid === triggerUuid)) { - return event; - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point) { - if (point.action?.triggers?.some((t: any) => t.triggerUuid === triggerUuid)) { - return event; - } - } else if ('actions' in point) { - for (const action of point.actions) { - if (action.triggers?.some((t: any) => t.triggerUuid === triggerUuid)) { - return event; - } - } - } - } - } - return undefined; - }, - - getEventByPointUuid: (productUuid, pointUuid) => { - const product = get().getProductById(productUuid); - if (!product) return undefined; - - for (const event of product.eventDatas) { - if ('points' in event) { - if ((event as ConveyorEventSchema).points.some(p => p.uuid === pointUuid)) { - return event; - } - } else if ('point' in event) { - if ((event as any).point?.uuid === pointUuid) { - return event; - } - } - } - return undefined; - }, - - getPointByUuid: (productUuid, modelUuid, pointUuid) => { - const event = get().getEventByModelUuid(productUuid, modelUuid); - if (!event) return undefined; - - if ('points' in event) { - return (event as ConveyorEventSchema).points.find(p => p.uuid === pointUuid); - } else if ('point' in event && (event as any).point.uuid === pointUuid) { - return (event as VehicleEventSchema | RoboticArmEventSchema | MachineEventSchema | StorageEventSchema).point; - } - return undefined; - }, - - getActionByUuid: (productUuid, actionUuid) => { - const product = get().products.find(p => p.productUuid === productUuid); - if (!product) return undefined; - - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action?.actionUuid === actionUuid) { - return point.action; - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && point.action?.actionUuid === actionUuid) { - return point.action; - } else if ('actions' in point) { - const action = point.actions.find((a: any) => a.actionUuid === actionUuid); - if (action) return action; - } - } - } - return undefined; - }, - - getActionByPointUuid: (productUuid, pointUuid) => { - const product = get().products.find(p => p.productUuid === productUuid); - if (!product) return undefined; - - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.uuid === pointUuid) { - return point.action; - } - } - } else if ('point' in event) { - const point = (event as any).point; - if (point.uuid === pointUuid) { - return point.action; - } - } - } - return undefined; - }, - - getModelUuidByPointUuid: (productUuid, pointUuid) => { - const product = get().products.find(p => p.productUuid === productUuid); - if (!product) return undefined; - - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.uuid === pointUuid) { - return event.modelUuid; - } - } - } else if ('point' in event) { - const point = (event as any).point; - if (point.uuid === pointUuid) { - return event.modelUuid; - } - } - } - return undefined; - }, - - getModelUuidByActionUuid: (productUuid, actionUuid) => { - const product = get().products.find(p => p.productUuid === productUuid); - if (!product) return undefined; - - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action?.actionUuid === actionUuid) { - return event.modelUuid; - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && point.action?.actionUuid === actionUuid) { - return event.modelUuid; - } else if ('actions' in point) { - const action = point.actions.find((a: any) => a.actionUuid === actionUuid); - if (action) return event.modelUuid; - } - } - } - return undefined; - }, - - getPointUuidByActionUuid: (productUuid, actionUuid) => { - const product = get().products.find(p => p.productUuid === productUuid); - if (!product) return undefined; - - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action?.actionUuid === actionUuid) { - return point.uuid; - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && point.action?.actionUuid === actionUuid) { - return point.uuid; - } else if ('actions' in point) { - const action = point.actions.find((a: any) => a.actionUuid === actionUuid); - if (action) return point.uuid; - } - } - } - return undefined; - }, - - getTriggerByUuid: (productUuid, triggerUuid) => { - const product = get().products.find(p => p.productUuid === productUuid); - if (!product) return undefined; - - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - for (const trigger of point.action?.triggers || []) { - if (trigger.triggerUuid === triggerUuid) { - return trigger; - } - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point) { - for (const trigger of point.action?.triggers || []) { - if (trigger.triggerUuid === triggerUuid) { - return trigger; - } - } - } else if ('actions' in point) { - for (const action of point.actions) { - for (const trigger of action.triggers || []) { - if (trigger.triggerUuid === triggerUuid) { - return trigger; - } - } - } - } - } - } - return undefined; - }, - - getTriggersByTriggeredPointUuid: (productUuid, triggeredPointUuid) => { - const product = get().products.find(p => p.productUuid === productUuid); - if (!product) return []; - - const triggers: TriggerSchema[] = []; - - for (const event of product.eventDatas) { - if ('points' in event) { - for (const point of (event as ConveyorEventSchema).points) { - if (point.action?.triggers) { - for (const trigger of point.action.triggers) { - if (trigger.triggeredAsset?.triggeredPoint?.pointUuid === triggeredPointUuid) { - triggers.push(trigger); - } - } - } - } - } else if ('point' in event) { - const point = (event as any).point; - if ('action' in point && point.action?.triggers) { - for (const trigger of point.action.triggers) { - if (trigger.triggeredAsset?.triggeredPoint?.pointUuid === triggeredPointUuid) { - triggers.push(trigger); - } - } - } else if ('actions' in point) { - for (const action of point.actions) { - if (action.triggers) { - for (const trigger of action.triggers) { - if (trigger.triggeredAsset?.triggeredPoint?.pointUuid === triggeredPointUuid) { - triggers.push(trigger); - } - } - } - } - } - } - } - - return triggers; - }, - - getIsEventInProduct: (productUuid, modelUuid) => { - const product = get().getProductById(productUuid); - if (!product) return false; - return product.eventDatas.some(e => 'modelUuid' in e && e.modelUuid === modelUuid); + // Event-level actions + addEvent: (productUuid, event) => { + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + const existingEvent = product.eventDatas.find( + (e) => "modelUuid" in e && e.modelUuid === event.modelUuid + ); + if (!existingEvent) { + product.eventDatas.push(event); } - })) - ) -} + } + }); + }, -export type ProductStoreType = ReturnType; \ No newline at end of file + removeEvent: (productUuid, modelUuid) => { + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + product.eventDatas = product.eventDatas.filter( + (e) => "modelUuid" in e && e.modelUuid !== modelUuid + ); + } + }); + }, + + deleteEvent: (modelUuid) => { + let updatedEvents: EventsSchema[] = []; + set((state) => { + const actionsToDelete = new Set(); + + for (const product of state.products) { + const eventIndex = product.eventDatas.findIndex( + (e) => "modelUuid" in e && e.modelUuid === modelUuid + ); + if (eventIndex !== -1) { + const event = product.eventDatas[eventIndex]; + + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action) { + actionsToDelete.add(point.action.actionUuid); + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point && point.action) { + actionsToDelete.add(point.action.actionUuid); + } else if ("actions" in point) { + for (const action of point.actions) { + actionsToDelete.add(action.actionUuid); + } + } + } + + product.eventDatas.splice(eventIndex, 1); + } + } + + for (const product of state.products) { + for (const event of product.eventDatas) { + let eventModified = false; + + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action?.triggers) { + const originalLength = point.action.triggers.length; + point.action.triggers = point.action.triggers.filter( + (trigger) => { + return !( + trigger.triggeredAsset?.triggeredModel?.modelUuid === + modelUuid || + actionsToDelete.has( + trigger.triggeredAsset?.triggeredAction + ?.actionUuid || "" + ) + ); + } + ); + if (point.action.triggers.length !== originalLength) { + eventModified = true; + } + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point && point.action?.triggers) { + const originalLength = point.action.triggers.length; + point.action.triggers = point.action.triggers.filter( + (trigger: TriggerSchema) => { + return !( + trigger.triggeredAsset?.triggeredModel?.modelUuid === + modelUuid || + actionsToDelete.has( + trigger.triggeredAsset?.triggeredAction?.actionUuid || + "" + ) + ); + } + ); + if (point.action.triggers.length !== originalLength) { + eventModified = true; + } + } else if ("actions" in point) { + for (const action of point.actions) { + if (action.triggers) { + const originalLength = action.triggers.length; + action.triggers = action.triggers.filter( + (trigger: TriggerSchema) => { + return !( + trigger.triggeredAsset?.triggeredModel + ?.modelUuid === modelUuid || + actionsToDelete.has( + trigger.triggeredAsset?.triggeredAction + ?.actionUuid || "" + ) + ); + } + ); + if (action.triggers.length !== originalLength) { + eventModified = true; + } + } + } + } + } + + if (eventModified) { + updatedEvents.push(JSON.parse(JSON.stringify(event))); + } + } + } + }); + return updatedEvents; + }, + + updateEvent: (productUuid, modelUuid, updates) => { + let updatedEvent: EventsSchema | undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + const event = product.eventDatas.find( + (e) => "modelUuid" in e && e.modelUuid === modelUuid + ); + if (event) { + Object.assign(event, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); + } + } + }); + return updatedEvent; + }, + + // Point-level actions + addPoint: (productUuid, modelUuid, point) => { + let updatedEvent: EventsSchema | undefined = undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + const event = product.eventDatas.find( + (e) => "modelUuid" in e && e.modelUuid === modelUuid + ); + if (event && "points" in event) { + const existingPoint = (event as ConveyorEventSchema).points.find( + (p) => p.uuid === point.uuid + ); + if (!existingPoint) { + (event as ConveyorEventSchema).points.push( + point as ConveyorPointSchema + ); + updatedEvent = JSON.parse(JSON.stringify(event)); + } + } else if (event && "point" in event) { + const existingPoint = (event as any).point?.uuid === point.uuid; + if (!existingPoint) { + ( + event as + | VehicleEventSchema + | RoboticArmEventSchema + | MachineEventSchema + | StorageEventSchema + ).point = point as any; + updatedEvent = JSON.parse(JSON.stringify(event)); + } + } + } + }); + return updatedEvent; + }, + + removePoint: (productUuid, modelUuid, pointUuid) => { + let updatedEvent: EventsSchema | undefined = undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + const event = product.eventDatas.find( + (e) => "modelUuid" in e && e.modelUuid === modelUuid + ); + if (event && "points" in event) { + (event as ConveyorEventSchema).points = ( + event as ConveyorEventSchema + ).points.filter((p) => p.uuid !== pointUuid); + updatedEvent = JSON.parse(JSON.stringify(event)); + } else if ( + event && + "point" in event && + (event as any).point.uuid === pointUuid + ) { + // For events with single point, we can't remove it, only reset to empty + } + } + }); + return updatedEvent; + }, + + updatePoint: (productUuid, modelUuid, pointUuid, updates) => { + let updatedEvent: EventsSchema | undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + const event = product.eventDatas.find( + (e) => "modelUuid" in e && e.modelUuid === modelUuid + ); + if (event && "points" in event) { + const point = (event as ConveyorEventSchema).points.find( + (p) => p.uuid === pointUuid + ); + if (point) { + Object.assign(point, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); + } + } else if ( + event && + "point" in event && + (event as any).point.uuid === pointUuid + ) { + Object.assign((event as any).point, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); + } + } + }); + return updatedEvent; + }, + + // Action-level actions + addAction: (productUuid, modelUuid, pointUuid, action) => { + let updatedEvent: EventsSchema | undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + const event = product.eventDatas.find( + (e) => "modelUuid" in e && e.modelUuid === modelUuid + ); + if (event && "points" in event) { + const point = (event as ConveyorEventSchema).points.find( + (p) => p.uuid === pointUuid + ); + if ( + point && + (!point.action || point.action.actionUuid !== action.actionUuid) + ) { + point.action = action as any; + updatedEvent = JSON.parse(JSON.stringify(event)); + } + } else if ( + event && + "point" in event && + (event as any).point.uuid === pointUuid + ) { + if ("action" in (event as any).point) { + if ( + !(event as any).point.action || + (event as any).point.action.actionUuid !== action.actionUuid + ) { + (event as any).point.action = action; + updatedEvent = JSON.parse(JSON.stringify(event)); + } + } else if ("actions" in (event as any).point) { + const existingAction = (event as any).point.actions.find( + (a: any) => a.actionUuid === action.actionUuid + ); + if (!existingAction) { + (event as any).point.actions.push(action); + updatedEvent = JSON.parse(JSON.stringify(event)); + } + } + } + } + }); + return updatedEvent; + }, + + removeAction: (productUuid, actionUuid) => { + let updatedEvent: EventsSchema | undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + for (const event of product.eventDatas) { + if ("points" in event) { + // Handle ConveyorEventSchema + for (const point of (event as ConveyorEventSchema).points) { + } + } else if ("point" in event) { + const point = (event as any).point; + if (event.type === "roboticArm") { + if ("actions" in point) { + const index = point.actions.findIndex( + (a: any) => a.actionUuid === actionUuid + ); + if (index !== -1) { + point.actions.splice(index, 1); + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } + } else if (event.type === "human") { + if ("actions" in point) { + const index = point.actions.findIndex( + (a: any) => a.actionUuid === actionUuid + ); + if (index !== -1) { + point.actions.splice(index, 1); + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } + } else if ( + "action" in point && + point.action?.actionUuid === actionUuid + ) { + point.action = undefined; + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } + } + } + }); + return updatedEvent; + }, + + updateAction: (productUuid, actionUuid, updates) => { + let updatedEvent: EventsSchema | undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action && point.action.actionUuid === actionUuid) { + Object.assign(point.action, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ( + "action" in point && + point.action.actionUuid === actionUuid + ) { + Object.assign(point.action, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } else if ("actions" in point) { + const action = point.actions.find( + (a: any) => a.actionUuid === actionUuid + ); + if (action) { + Object.assign(action, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } + } + } + } + }); + return updatedEvent; + }, + + // Trigger-level actions + addTrigger: (productUuid, actionUuid, trigger) => { + let updatedEvent: EventsSchema | undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action && point.action.actionUuid === actionUuid) { + const existingTrigger = point.action.triggers.find( + (t) => t.triggerUuid === trigger.triggerUuid + ); + if (!existingTrigger) { + point.action.triggers.push(trigger); + updatedEvent = JSON.parse(JSON.stringify(event)); + } + return; + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ( + "action" in point && + point.action.actionUuid === actionUuid + ) { + const existingTrigger = point.action.triggers.find( + (t: any) => t.triggerUuid === trigger.triggerUuid + ); + if (!existingTrigger) { + point.action.triggers.push(trigger); + updatedEvent = JSON.parse(JSON.stringify(event)); + } + return; + } else if ("actions" in point) { + const action = point.actions.find( + (a: any) => a.actionUuid === actionUuid + ); + if (action) { + const existingTrigger = action.triggers.find( + (t: any) => t.triggerUuid === trigger.triggerUuid + ); + if (!existingTrigger) { + action.triggers.push(trigger); + updatedEvent = JSON.parse(JSON.stringify(event)); + } + return; + } + } + } + } + } + }); + return updatedEvent; + }, + + removeTrigger: (productUuid, triggerUuid) => { + let updatedEvent: EventsSchema | undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action && "triggers" in point.action) { + const Trigger = point.action.triggers.find( + (t) => t.triggerUuid === triggerUuid + ); + if (Trigger) { + point.action.triggers = point.action.triggers.filter( + (t) => t.triggerUuid !== triggerUuid + ); + updatedEvent = JSON.parse(JSON.stringify(event)); + } + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point && "triggers" in point.action) { + const Trigger = point.action.triggers.find( + (t: any) => t.triggerUuid === triggerUuid + ); + if (Trigger) { + point.action.triggers = point.action.triggers.filter( + (t: any) => t.triggerUuid !== triggerUuid + ); + updatedEvent = JSON.parse(JSON.stringify(event)); + } + } else if ("actions" in point) { + for (const action of point.actions) { + if ("triggers" in action) { + const Trigger = action.triggers.find( + (t: any) => t.triggerUuid === triggerUuid + ); + if (Trigger) { + action.triggers = action.triggers.filter( + (t: any) => t.triggerUuid !== triggerUuid + ); + updatedEvent = JSON.parse(JSON.stringify(event)); + } + } + } + } + } + } + } + }); + return updatedEvent; + }, + + updateTrigger: (productUuid, triggerUuid, updates) => { + let updatedEvent: EventsSchema | undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action && "triggers" in point.action) { + const trigger = point.action.triggers.find( + (t) => t.triggerUuid === triggerUuid + ); + if (trigger) { + Object.assign(trigger, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point && "triggers" in point.action) { + const trigger = point.action.triggers.find( + (t: any) => t.triggerUuid === triggerUuid + ); + if (trigger) { + Object.assign(trigger, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } else if ("actions" in point) { + for (const action of point.actions) { + if ("triggers" in action) { + const trigger = action.triggers.find( + (t: any) => t.triggerUuid === triggerUuid + ); + if (trigger) { + Object.assign(trigger, updates); + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } + } + } + } + } + } + }); + return updatedEvent; + }, + + // Renaming functions + renameProduct: (productUuid, newName) => { + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + product.productName = newName; + } + }); + }, + + renameAction: (productUuid, actionUuid, newName) => { + let updatedEvent: EventsSchema | undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action && point.action.actionUuid === actionUuid) { + point.action.actionName = newName; + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ( + "action" in point && + point.action.actionUuid === actionUuid + ) { + point.action.actionName = newName; + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } else if ("actions" in point) { + const action = point.actions.find( + (a: any) => a.actionUuid === actionUuid + ); + if (action) { + action.actionName = newName; + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } + } + } + } + }); + return updatedEvent; + }, + + renameTrigger: (productUuid, triggerUuid, newName) => { + let updatedEvent: EventsSchema | undefined; + set((state) => { + const product = state.products.find( + (p) => p.productUuid === productUuid + ); + if (product) { + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action && "triggers" in point.action) { + const trigger = point.action.triggers.find( + (t) => t.triggerUuid === triggerUuid + ); + if (trigger) { + trigger.triggerName = newName; + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point && "triggers" in point.action) { + const trigger = point.action.triggers.find( + (t: any) => t.triggerUuid === triggerUuid + ); + if (trigger) { + trigger.triggerName = newName; + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } else if ("actions" in point) { + for (const action of point.actions) { + if ("triggers" in action) { + const trigger = action.triggers.find( + (t: any) => t.triggerUuid === triggerUuid + ); + if (trigger) { + trigger.triggerName = newName; + updatedEvent = JSON.parse(JSON.stringify(event)); + return; + } + } + } + } + } + } + } + }); + return updatedEvent; + }, + + // Helper functions + getProductById: (productUuid) => { + // console.log( + // "j", + // get().products.map((p) => p.productUuid) + // ); + + // console.log("productUuid: ", productUuid); + return get().products.find((p) => p.productUuid === productUuid); + }, + + getEventByModelUuid: (productUuid, modelUuid) => { + const product = get().getProductById(productUuid); + if (!product) return undefined; + return product.eventDatas.find( + (e) => "modelUuid" in e && e.modelUuid === modelUuid + ); + }, + + getEventByActionUuid: (productUuid, actionUuid) => { + const product = get().getProductById(productUuid); + if (!product) return undefined; + + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action?.actionUuid === actionUuid) { + return event; + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point && point.action?.actionUuid === actionUuid) { + return event; + } else if ("actions" in point) { + const action = point.actions.find( + (a: any) => a.actionUuid === actionUuid + ); + if (action) { + return event; + } + } + } + } + return undefined; + }, + + getEventByTriggerUuid: (productUuid, triggerUuid) => { + const product = get().getProductById(productUuid); + if (!product) return undefined; + + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if ( + point.action?.triggers?.some( + (t) => t.triggerUuid === triggerUuid + ) + ) { + return event; + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point) { + if ( + point.action?.triggers?.some( + (t: any) => t.triggerUuid === triggerUuid + ) + ) { + return event; + } + } else if ("actions" in point) { + for (const action of point.actions) { + if ( + action.triggers?.some( + (t: any) => t.triggerUuid === triggerUuid + ) + ) { + return event; + } + } + } + } + } + return undefined; + }, + + getEventByPointUuid: (productUuid, pointUuid) => { + const product = get().getProductById(productUuid); + if (!product) return undefined; + + for (const event of product.eventDatas) { + if ("points" in event) { + if ( + (event as ConveyorEventSchema).points.some( + (p) => p.uuid === pointUuid + ) + ) { + return event; + } + } else if ("point" in event) { + if ((event as any).point?.uuid === pointUuid) { + return event; + } + } + } + return undefined; + }, + + getPointByUuid: (productUuid, modelUuid, pointUuid) => { + const event = get().getEventByModelUuid(productUuid, modelUuid); + if (!event) return undefined; + + if ("points" in event) { + return (event as ConveyorEventSchema).points.find( + (p) => p.uuid === pointUuid + ); + } else if ( + "point" in event && + (event as any).point.uuid === pointUuid + ) { + return ( + event as + | VehicleEventSchema + | RoboticArmEventSchema + | MachineEventSchema + | StorageEventSchema + ).point; + } + return undefined; + }, + + getActionByUuid: (productUuid, actionUuid) => { + const product = get().products.find( + (p) => p.productUuid === productUuid + ); + if (!product) return undefined; + + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action?.actionUuid === actionUuid) { + return point.action; + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point && point.action?.actionUuid === actionUuid) { + return point.action; + } else if ("actions" in point) { + const action = point.actions.find( + (a: any) => a.actionUuid === actionUuid + ); + if (action) return action; + } + } + } + return undefined; + }, + + getActionByPointUuid: (productUuid, pointUuid) => { + const product = get().products.find( + (p) => p.productUuid === productUuid + ); + if (!product) return undefined; + + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.uuid === pointUuid) { + return point.action; + } + } + } else if ("point" in event) { + const point = (event as any).point; + if (point.uuid === pointUuid) { + return point.action; + } + } + } + return undefined; + }, + + getModelUuidByPointUuid: (productUuid, pointUuid) => { + const product = get().products.find( + (p) => p.productUuid === productUuid + ); + if (!product) return undefined; + + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.uuid === pointUuid) { + return event.modelUuid; + } + } + } else if ("point" in event) { + const point = (event as any).point; + if (point.uuid === pointUuid) { + return event.modelUuid; + } + } + } + return undefined; + }, + + getModelUuidByActionUuid: (productUuid, actionUuid) => { + const product = get().products.find( + (p) => p.productUuid === productUuid + ); + if (!product) return undefined; + + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action?.actionUuid === actionUuid) { + return event.modelUuid; + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point && point.action?.actionUuid === actionUuid) { + return event.modelUuid; + } else if ("actions" in point) { + const action = point.actions.find( + (a: any) => a.actionUuid === actionUuid + ); + if (action) return event.modelUuid; + } + } + } + return undefined; + }, + + getPointUuidByActionUuid: (productUuid, actionUuid) => { + const product = get().products.find( + (p) => p.productUuid === productUuid + ); + if (!product) return undefined; + + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action?.actionUuid === actionUuid) { + return point.uuid; + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point && point.action?.actionUuid === actionUuid) { + return point.uuid; + } else if ("actions" in point) { + const action = point.actions.find( + (a: any) => a.actionUuid === actionUuid + ); + if (action) return point.uuid; + } + } + } + return undefined; + }, + + getTriggerByUuid: (productUuid, triggerUuid) => { + const product = get().products.find( + (p) => p.productUuid === productUuid + ); + if (!product) return undefined; + + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + for (const trigger of point.action?.triggers || []) { + if (trigger.triggerUuid === triggerUuid) { + return trigger; + } + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point) { + for (const trigger of point.action?.triggers || []) { + if (trigger.triggerUuid === triggerUuid) { + return trigger; + } + } + } else if ("actions" in point) { + for (const action of point.actions) { + for (const trigger of action.triggers || []) { + if (trigger.triggerUuid === triggerUuid) { + return trigger; + } + } + } + } + } + } + return undefined; + }, + + getTriggersByTriggeredPointUuid: (productUuid, triggeredPointUuid) => { + const product = get().products.find( + (p) => p.productUuid === productUuid + ); + if (!product) return []; + + const triggers: TriggerSchema[] = []; + + for (const event of product.eventDatas) { + if ("points" in event) { + for (const point of (event as ConveyorEventSchema).points) { + if (point.action?.triggers) { + for (const trigger of point.action.triggers) { + if ( + trigger.triggeredAsset?.triggeredPoint?.pointUuid === + triggeredPointUuid + ) { + triggers.push(trigger); + } + } + } + } + } else if ("point" in event) { + const point = (event as any).point; + if ("action" in point && point.action?.triggers) { + for (const trigger of point.action.triggers) { + if ( + trigger.triggeredAsset?.triggeredPoint?.pointUuid === + triggeredPointUuid + ) { + triggers.push(trigger); + } + } + } else if ("actions" in point) { + for (const action of point.actions) { + if (action.triggers) { + for (const trigger of action.triggers) { + if ( + trigger.triggeredAsset?.triggeredPoint?.pointUuid === + triggeredPointUuid + ) { + triggers.push(trigger); + } + } + } + } + } + } + } + + return triggers; + }, + + getIsEventInProduct: (productUuid, modelUuid) => { + const product = get().getProductById(productUuid); + if (!product) return false; + return product.eventDatas.some( + (e) => "modelUuid" in e && e.modelUuid === modelUuid + ); + }, + })) + ); +}; + +export type ProductStoreType = ReturnType;