From efe986502d814ad5432d9d1e3ce1edb9c7b93b3f Mon Sep 17 00:00:00 2001 From: sabarinathan Date: Mon, 2 Jun 2025 09:47:33 +0530 Subject: [PATCH] project ,trash events create in socket --- .../trashController/v1trashController.ts | 2 +- .../controller/simulation/productService.ts | 2 +- .../services/v1Project/v1projectservice.ts | 1 - src/shared/services/v1trash/v1trashservice.ts | 2 +- .../projectController/projectController.ts | 131 ++++++++++++++---- .../trashController/trash-Controller.ts | 68 +++++++++ src/socket-server/index.ts | 4 +- src/socket-server/manager/manager.ts | 63 +++++++-- src/socket-server/socket/events.ts | 6 + 9 files changed, 229 insertions(+), 50 deletions(-) create mode 100644 src/socket-server/controllers/trashController/trash-Controller.ts diff --git a/src/api-server/V1/v1Controllers/trashController/v1trashController.ts b/src/api-server/V1/v1Controllers/trashController/v1trashController.ts index 944c763..b87f600 100644 --- a/src/api-server/V1/v1Controllers/trashController/v1trashController.ts +++ b/src/api-server/V1/v1Controllers/trashController/v1trashController.ts @@ -146,7 +146,7 @@ export const DeleteTrashData = async ( message: "Project Already Deleted", }); break; - case "Trash Project Delete successfully": + case "Success": res.status(200).json({ message: "Trash Project Delete successfully", }); diff --git a/src/api-server/controller/simulation/productService.ts b/src/api-server/controller/simulation/productService.ts index 32e5257..e7dc450 100644 --- a/src/api-server/controller/simulation/productService.ts +++ b/src/api-server/controller/simulation/productService.ts @@ -5,7 +5,7 @@ import EventsDataModel from "../../../shared/model/simulation/eventsDataModel.ts export class ProductFlowservice { static async productAdd(req: Request, res: Response): Promise { try { - const { productName, productId, organization } = req.body; + const { productName, productId,eventDatas, organization } = req.body; if (!organization) { return res.json({ message: "organization not found" }); } diff --git a/src/shared/services/v1Project/v1projectservice.ts b/src/shared/services/v1Project/v1projectservice.ts index 5266fc6..1143fdb 100644 --- a/src/shared/services/v1Project/v1projectservice.ts +++ b/src/shared/services/v1Project/v1projectservice.ts @@ -57,7 +57,6 @@ export const createProject = async (data: CreateProjectInput) => { try { const { thumbnail, sharedUsers, projectUuid, userId, organization } = data; const userExisting = await existingUser(userId, organization); - console.log("userExisting: ", userExisting); if (!userExisting) { return { status: "user_not_found", diff --git a/src/shared/services/v1trash/v1trashservice.ts b/src/shared/services/v1trash/v1trashservice.ts index 08ee5d3..8df50a3 100644 --- a/src/shared/services/v1trash/v1trashservice.ts +++ b/src/shared/services/v1trash/v1trashservice.ts @@ -94,7 +94,7 @@ export const TrashDelete = async (data: IRestore) => { { new: true } ); if (!DeleteTrashData) return { status: "Project Already Deleted" }; - return { status: "Trash Project Delete successfully" }; + return { status: "Success",data:DeleteTrashData }; } catch (error) { return { status: error }; } diff --git a/src/socket-server/controllers/projectController/projectController.ts b/src/socket-server/controllers/projectController/projectController.ts index 57ff6c5..2ac857a 100644 --- a/src/socket-server/controllers/projectController/projectController.ts +++ b/src/socket-server/controllers/projectController/projectController.ts @@ -1,10 +1,16 @@ import { Socket, Server } from "socket.io"; -import { createProject, DeleteProject, updateProject } from "../../../shared/services/project/project-Services.ts"; import { EVENTS } from "../../socket/events.ts"; import { emitEventResponse, emitToSenderAndAdmins, } from "../../utils/emitEventResponse.ts"; +import { createProject, DeleteProject, DuplicateProject, updateProject } from "../../../shared/services/v1Project/v1projectservice.ts"; -export const projectHandleEvent = async ( event: string,socket: Socket,io:Server,data: any, connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, callback?: Function +export const projectHandleEvent = async ( + event: string, + socket: Socket, + io: Server, + data: any, + connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, callback?: Function ) => { + console.log('event: ', event); if (event !== EVENTS.addProject || !data?.organization) return; const requiredFields = ["projectUuid", "userId", "thumbnail", "organization"]; const missingFields = requiredFields.filter(field => !data?.[field]); @@ -18,25 +24,29 @@ export const projectHandleEvent = async ( event: string,socket: Socket,io:Server organization: data?.organization ?? "unknown", }; - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.projectResponse, response, connectedUsersByOrg) + emitToSenderAndAdmins(io, socket, data.organization, EVENTS.projectResponse, response, connectedUsersByOrg) return; } + console.log('data:controller ', data); const result = await createProject(data); - - const status = typeof result.status === "string" ? result.status : "unknown"; + const status = typeof result?.status === "string" ? result.status : "unknown"; const messages: Record = { Success: { message: "Project created successfully" }, - user_not_found: { message: "User not found" }, - project_exists: { message: "Project already exists" }, + "user_not_found": { message: "User not found" }, + "project_exists": { message: "Project already exists" }, }; const msg = messages[status] || { message: "Internal server error", }; - const projectDatas = { - projectUuid: result.project.projectUuid, - projectName: result.project.projectName, - thumbnail: result.project.thumbnail, - createdBy: result.project.createdBy, + + let projectDatas = undefined; + if (status === "Success" && result?.project) { + projectDatas = { + projectUuid: result.project.projectUuid, + projectName: result.project.projectName, + thumbnail: result.project.thumbnail, + createdBy: result.project.createdBy, + }; } const response = { success: status === "Success", @@ -53,12 +63,14 @@ export const projectHandleEvent = async ( event: string,socket: Socket,io:Server export const projectDeleteHandleEvent = async ( event: string, socket: Socket, - io:Server, + io: Server, data: any, connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, ) => { + console.log('event: ', event); + if (event !== EVENTS.deleteProject || !data?.organization) return; - const requiredFields = ["projectId", "userId", "organization"]; + const requiredFields = ["projectId", "userId", "organization"]; const missingFields = requiredFields.filter(field => !data?.[field]); if (missingFields.length > 0) { @@ -70,7 +82,7 @@ export const projectDeleteHandleEvent = async ( organization: data?.organization ?? "unknown", }; - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.deleteProjectResponse, response, connectedUsersByOrg) + emitToSenderAndAdmins(io, socket, data.organization, EVENTS.deleteProjectResponse, response, connectedUsersByOrg) return; } const result = await DeleteProject(data); @@ -103,17 +115,19 @@ export const projectDeleteHandleEvent = async ( }; -emitToSenderAndAdmins(io, socket, data.organization, EVENTS.deleteProjectResponse, response, connectedUsersByOrg)} + emitToSenderAndAdmins(io, socket, data.organization, EVENTS.deleteProjectResponse, response, connectedUsersByOrg) +} export const projecUpdateHandleEvent = async ( event: string, socket: Socket, - io:Server, + io: Server, data: any, - connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, + connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, ) => { + console.log('event: ', event); if (event !== EVENTS.ProjectUpdate || !data?.organization) return; - const requiredFields = ["projectId", "userId", "organization"]; + const requiredFields = ["projectId", "userId", "organization"]; const missingFields = requiredFields.filter(field => !data?.[field]); if (missingFields.length > 0) { @@ -125,7 +139,7 @@ export const projecUpdateHandleEvent = async ( organization: data?.organization ?? "unknown", }; - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.projectUpdateResponse, response, connectedUsersByOrg) + emitToSenderAndAdmins(io, socket, data.organization, EVENTS.projectUpdateResponse, response, connectedUsersByOrg) return; } const result = await updateProject(data); @@ -139,15 +153,15 @@ export const projecUpdateHandleEvent = async ( const msg = messages[status] || { message: "Internal server error" }; const projectDeleteDatas = - status === "Success" && result?.data - ? { - projectUuid: result.data.projectUuid, - projectName: result.data.projectName, - thumbnail: result.data.thumbnail, - projectId: result.data._id, - } - : undefined; - + status === "Success" && result?.data + ? { + projectUuid: result.data.projectUuid, + projectName: result.data.projectName, + thumbnail: result.data.thumbnail, + projectId: result.data._id, + } + : undefined; + const response = { success: status === "Success", @@ -159,6 +173,63 @@ export const projecUpdateHandleEvent = async ( }; - emitToSenderAndAdmins(io, socket, data.organization, EVENTS.projectUpdateResponse, response, connectedUsersByOrg) + emitToSenderAndAdmins(io, socket, data.organization, EVENTS.projectUpdateResponse, response, connectedUsersByOrg) + +} +export const DuplicateProjectHandleEvent = async ( + event: string, + socket: Socket, + io: Server, + data: any, + connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, callback?: Function +) => { + console.log('event: ', event); + if (event !== EVENTS.DuplicateProject || !data?.organization) return; + const requiredFields = ["projectUuid", "projectName","userId", "thumbnail", "organization"]; + const missingFields = requiredFields.filter(field => !data?.[field]); + + if (missingFields.length > 0) { + const response = { + success: false, + message: `Missing required field(s): ${missingFields.join(", ")}`, + status: "MissingFields", + socketId: socket.id, + organization: data?.organization ?? "unknown", + }; + + emitToSenderAndAdmins(io, socket, data.organization, EVENTS.DuplicateprojectResponse, response, connectedUsersByOrg) + return; + } + console.log('data:controller ', data); + const result = await DuplicateProject(data); + const status = typeof result?.status === "string" ? result.status : "unknown"; + + const messages: Record = { + Success: { message: "Project Duplicated successfully" }, + "user_not_found": { message: "User not found" }, + "project_exists": { message: "Project already exists" }, + }; + + const msg = messages[status] || { message: "Internal server error", }; + + let projectDatas = undefined; + if (status === "Success" && result?.project) { + projectDatas = { + projectUuid: result.project.projectUuid, + projectName: result.project.projectName, + thumbnail: result.project.thumbnail, + createdBy: result.project.createdBy, + }; + } + const response = { + success: status === "Success", + message: msg.message, + status, + socketId: socket.id, + organization: data.organization, + ...(status === "Success" ? { data: projectDatas, projectId: result.project._id } : {}), + }; + + emitToSenderAndAdmins(io, socket, data.organization, EVENTS.DuplicateprojectResponse, response, connectedUsersByOrg) } \ No newline at end of file diff --git a/src/socket-server/controllers/trashController/trash-Controller.ts b/src/socket-server/controllers/trashController/trash-Controller.ts new file mode 100644 index 0000000..e563a68 --- /dev/null +++ b/src/socket-server/controllers/trashController/trash-Controller.ts @@ -0,0 +1,68 @@ +import { Socket, Server } from "socket.io"; +import { EVENTS } from "../../socket/events.ts"; +import { emitEventResponse, emitToSenderAndAdmins, } from "../../utils/emitEventResponse.ts"; +import { + TrashDatas, + RestoreTrashData, + TrashDelete, +} from "../../../shared/services/v1trash/v1trashservice.ts"; +export const TrashDeleteHandleEvent = async ( + event: string, + socket: Socket, + io: Server, + data: any, + connectedUsersByOrg: { [org: string]: { socketId: string; userId: string; role: string }[] }, callback?: Function +) => { + console.log('event: ', event); + if (event !== EVENTS.deleteTrash_v1 || !data?.organization) return; + const requiredFields = ["projectId","userId", "organization"]; + const missingFields = requiredFields.filter(field => !data?.[field]); + + if (missingFields.length > 0) { + const response = { + success: false, + message: `Missing required field(s): ${missingFields.join(", ")}`, + status: "MissingFields", + socketId: socket.id, + organization: data?.organization ?? "unknown", + }; + + emitToSenderAndAdmins(io, socket, data.organization, EVENTS.Trash_v1DeleteResponse, response, connectedUsersByOrg) + return; + } + console.log('data:controller ', data); + const result = await TrashDelete(data); + const status = typeof result?.status === "string" ? result.status : "unknown"; + + const messages: Record = { + Success: { message: "Trash Project Delete successfully" }, + "user_not_found": { message: "User not found" }, + "project_exists": { message: "Project already exists" }, + }; + + const msg = messages[status] || { message: "Internal server error", }; + const trash_Datas = + status === "Success" && result?.data + + ? { + // widget: { + // id: result.data.widgetID, + // type: result.data.projectName, + // position: result.data.position, + // }, + // Data: result.data.Data, + // zoneId: result.data.zoneId, + } + : undefined; + const response = { + success: status === "Success", + message: msg.message, + status, + socketId: socket.id, + organization: data.organization, + ...(status === "Success" ? { data: trash_Datas, } : {}), + }; + + emitToSenderAndAdmins(io, socket, data.organization, EVENTS.Trash_v1DeleteResponse, response, connectedUsersByOrg) + +} \ No newline at end of file diff --git a/src/socket-server/index.ts b/src/socket-server/index.ts index 88dbdbd..0826465 100644 --- a/src/socket-server/index.ts +++ b/src/socket-server/index.ts @@ -15,8 +15,8 @@ const server = http.createServer(app); app.get('/', (req: Request, res: Response) => { res.send('Hello, I am Major-Dwinzo RealTime!'); }); -initSocketServer(server); -// SocketServer(server) +// initSocketServer(server); +SocketServer(server) server.listen(PORT, () => { console.log(`socket-Server is running on http://localhost:${PORT}`); }); diff --git a/src/socket-server/manager/manager.ts b/src/socket-server/manager/manager.ts index 370d6cf..f58b8b6 100644 --- a/src/socket-server/manager/manager.ts +++ b/src/socket-server/manager/manager.ts @@ -4,9 +4,10 @@ import dotenv from 'dotenv'; import AuthModel from '../../shared/V1Models/Auth/userAuthModel.ts'; dotenv.config(); import { addCommentHandleEvent, createThreadHandleEvent, deleteCommentHandleEvent, deleteThreadHandleEvent } from '../controllers/thread/threadController.ts'; -import { projectDeleteHandleEvent, projectHandleEvent, projecUpdateHandleEvent } from '../controllers/projectController/projectController.ts'; +import { DuplicateProjectHandleEvent, projectDeleteHandleEvent, projectHandleEvent, projecUpdateHandleEvent } from '../controllers/projectController/projectController.ts'; import { setAssetHandleEvent, deleteAssetHandleEvent, replaceEventDatasHandleEvent } from '../controllers/builderController/asset-Controller.ts'; import { SetCameraHandleEvent } from '../controllers/builderController/camera-Controller.ts'; +import { TrashDeleteHandleEvent } from '../controllers/trashController/trash-Controller.ts'; import { setEnvironmentHandleEvent } from '../controllers/builderController/environment-Controller.ts'; import { CreateLineHandleEvent, UpdateLineHandleEvent, DeleteLineHandleEvent, DeleteLayerHandleEvent, DeleteLinePointsHandleEvent } from '../controllers/builderController/line-Controller.ts'; import { deleteWallItemsHandleEvent, setWallItemsHandleEvent } from '../controllers/builderController/wall-Controller.ts'; @@ -16,7 +17,14 @@ import { AddFloatHandleEvent, DeleteFloatHandleEvent, DuplicateFloatHandleEvent import { AddPanelHandleEvent, ClearPanelHandleEvent, DeletePanelHandleEvent, LockedPanelHandleEvent } from '../controllers/vizualizationController/panel-Controller.ts'; import { AddTemplateHandleEvent, addTemplateZoneHandleEvent, TemplateDeleteHandleEvent } from '../controllers/vizualizationController/template-Controller.ts'; import { AddWidgetHandleEvent, WidgetDeleteHandleEvent } from '../controllers/vizualizationController/widget-Controller.ts'; +import { getUserRole } from '../utils/getUsers.ts'; +interface UserSocketInfo { + socketId: string; + userId: string; + role: string; // e.g., "admin" or "user" +} +const connectedUsersByOrg: { [organization: string]: UserSocketInfo[] } = {}; export const SocketServer = (httpServer: any) => { const io = new Server(httpServer, { cors: { @@ -28,6 +36,7 @@ export const SocketServer = (httpServer: any) => { const namespaces = { + dashboard: io.of('/dashboard'), project: io.of('/project'), thread: io.of('/thread'), Builder: io.of("/Builder"), @@ -40,6 +49,7 @@ export const SocketServer = (httpServer: any) => { const handleNamespace = (namespace: any, ...eventHandlers: Function[]) => { namespace.use(async (socket: Socket, next: any) => { + // console.log(`🔌 Connecting to namespace: ${namespace.name}`); const token = socket.handshake.auth.token; // const token = socket.handshake.query.token as string; const jwt_secret = process.env.JWT_SECRET as string; @@ -72,6 +82,7 @@ export const SocketServer = (httpServer: any) => { // ...user.toObject(), // convert Mongoose doc to plain object organization: decoded.organization, // manually add org Email: decoded.Email, // manually add org + userId: decoded.userId, // manually add org }; next(); @@ -81,11 +92,12 @@ export const SocketServer = (httpServer: any) => { } }); - namespace.on("connection", (socket: Socket) => { + namespace.on("connection",async (socket: Socket) => { // Extract organization from query parameters const user = (socket as any).user; const organization = user.organization; - const email = user.email; + const Email = user.Email; + const userId = user.userId; // namespace.on("connection", (socket: Socket) => { // console.log(`✅ Client connected to ${namespace.name}: ${socket.id}`); @@ -94,25 +106,49 @@ export const SocketServer = (httpServer: any) => { // const organization = socket.handshake.query.organization as string; // const email = socket.handshake.query.email as string; // // const {organization,email} = socket.handshake.auth - // console.log(`🔍 Received organization: ${organization}`); + // console.log(`🔍 Received organization: ${organization}`); if (organization) { socket.join(organization); // console.log(`🔹 Socket ${socket.id} joined room: ${organization}`); } - // Handle all events - if (organization && email) { - if (!onlineUsers[organization]) { - onlineUsers[organization] = new Set(); - } - onlineUsers[organization].add(socket.id); + // // Handle all events + // if (organization && email) { + // if (!onlineUsers[organization]) { + // onlineUsers[organization] = new Set(); + // } + // onlineUsers[organization].add(socket.id); + // } + const role = await getUserRole(userId, organization); + if (role === "Admin") { + socket.join(`${organization}_admins`); } + // Save user info somewhere + if (organization && userId && role) { + if (!connectedUsersByOrg[organization]) { + connectedUsersByOrg[organization] = []; + } + connectedUsersByOrg[organization].push({ + socketId: socket.id, + userId, + role, + }); + + // console.log(`🔗 User connected: ${userId} with role ${role} in ${organization}`); + // console.log("🧩 connectedUsersByOrg: ", connectedUsersByOrg); + } else { + console.warn(`❌ Cannot store user. Missing data:`,); + } // userStatus(EVENTS.connection, socket, socket.handshake.auth, socket); socket.onAny((event: string, data: any, callback: any) => { - eventHandlers.forEach(handler => handler(event, socket, data, namespace, io, callback)); + eventHandlers.forEach(handler => + handler(event, socket, io, data, connectedUsersByOrg, callback) // ✅ fixed + ); + // eventHandlers.forEach(handler => + // handler(event, socket,io,namespace, data, connectedUsersByOrg, callback)); }); // Handle disconnection @@ -136,14 +172,13 @@ export const SocketServer = (httpServer: any) => { - -handleNamespace(namespaces.project,projectHandleEvent,projectDeleteHandleEvent,projecUpdateHandleEvent) +handleNamespace(namespaces.dashboard); handleNamespace(namespaces.thread,createThreadHandleEvent,deleteThreadHandleEvent,addCommentHandleEvent,deleteCommentHandleEvent) - handleNamespace(namespaces.project, projectHandleEvent, projectDeleteHandleEvent, projecUpdateHandleEvent) + handleNamespace(namespaces.project, projectHandleEvent, projectDeleteHandleEvent, projecUpdateHandleEvent,DuplicateProjectHandleEvent,TrashDeleteHandleEvent ) handleNamespace(namespaces.Builder, setAssetHandleEvent, deleteAssetHandleEvent, diff --git a/src/socket-server/socket/events.ts b/src/socket-server/socket/events.ts index 0bb6736..8b7b26e 100644 --- a/src/socket-server/socket/events.ts +++ b/src/socket-server/socket/events.ts @@ -103,6 +103,8 @@ export const EVENTS = { //PROJECT addProject: "v1:project:add", projectResponse: "v1-project:response:add", + DuplicateProject: "v1:project:Duplicate", + DuplicateprojectResponse: "v1-project:response:Duplicate", deleteProject: "v1:project:delete", deleteProjectResponse: "v1-project:response:delete", ProjectUpdate: "v1:project:update", @@ -191,4 +193,8 @@ export const EVENTS = { deleteZone_v1: "v1:zone:delete", Zone_v1DeleteResponse: "v1:zone:response:delete", + //trash + deleteTrash_v1: "v1:trash:delete", + Trash_v1DeleteResponse: "v1:trash:response:delete", + } \ No newline at end of file