diff --git a/src/api-server/Routes/homepageRoutes.ts b/src/api-server/Routes/homepageRoutes.ts index f84e818..02cbf39 100644 --- a/src/api-server/Routes/homepageRoutes.ts +++ b/src/api-server/Routes/homepageRoutes.ts @@ -1,7 +1,10 @@ import * as express from "express"; -import { recentDataController } from "../controller/home/recentsControllers.ts"; +import { recentDataController, searchProjectController, searchTrashProjectController } from "../controller/home/homeControllers.ts"; +import { searchTrashProject } from "../../shared/services/home/homeService.ts"; const homePageRouter = express.Router(); homePageRouter.get("/RecentlyViewed/:userId/:organization", recentDataController); +homePageRouter.get("/searchProjects", searchProjectController); +homePageRouter.get("/searchTrashProjects", searchTrashProjectController); export default homePageRouter; diff --git a/src/api-server/controller/home/homeControllers.ts b/src/api-server/controller/home/homeControllers.ts new file mode 100644 index 0000000..a608482 --- /dev/null +++ b/src/api-server/controller/home/homeControllers.ts @@ -0,0 +1,140 @@ +import { Request, Response } from "express"; +import { RecentlyAdded, searchProject, searchTrashProject } from "../../../shared/services/home/homeService.ts"; + +export const recentDataController = async ( + req: Request, + res: Response +): Promise => { + try { + const { userId, organization } = req.params; + if (!userId || !organization) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const result = await RecentlyAdded({ userId, organization }); + + switch (result.status) { + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + case "Datas were empty": + res.status(200).json({ + RecentlyViewed: [], + }); + break; + case "Success": + res.status(200).json({ + RecentlyViewed: result.data, + }); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + return; + } +}; +export const searchProjectController = async (req: Request, res: Response): Promise => { + try { + const { searchName, organization, userId } = req.query as { + organization: string; + searchName: string; + userId: string; + }; + if (!userId || !organization || !searchName) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const result = await searchProject({ + searchName, + organization, + userId, + }); + switch (result?.status) { + case "Project not found": + res.status(200).json({ + message: "Project not found", + }); + break; + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + case "Success": + res.status(200).json({ + projectData: result.data, + }); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + return; + } +}; +export const searchTrashProjectController = async (req: Request, res: Response): Promise => { + try { + const { searchName, organization, userId } = req.query as { + organization: string; + searchName: string; + userId: string; + }; + if (!userId || !organization || !searchName) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const result = await searchTrashProject({ + searchName, + organization, + userId, + }); + switch (result?.status) { + case "Project not found": + res.status(200).json({ + message: "Project not found", + }); + break; + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + case "Success": + res.status(200).json({ + projectData: result.data, + }); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + return; + } +}; \ No newline at end of file diff --git a/src/api-server/controller/home/recentsControllers.ts b/src/api-server/controller/home/recentsControllers.ts deleted file mode 100644 index 34b43b3..0000000 --- a/src/api-server/controller/home/recentsControllers.ts +++ /dev/null @@ -1,46 +0,0 @@ -import { Request, Response } from "express"; -import { RecentlyAdded } from "../../../shared/services/home/recentDatasService.ts"; - -export const recentDataController = async ( - req: Request, - res: Response -): Promise => { - try { - const { userId, organization } = req.params; - if (!userId || !organization) { - res.status(400).json({ - message: "All fields are required", - }); - return; - } - const result = await RecentlyAdded({ userId, organization }); - - switch (result.status) { - case "User not found": - res.status(404).json({ - message: "User not found", - }); - break; - case "Datas were empty": - res.status(200).json({ - RecentlyViewed: [], - }); - break; - case "Success": - res.status(200).json({ - RecentlyViewed: result.data, - }); - break; - default: - res.status(500).json({ - message: "Internal server error", - }); - break; - } - } catch (error) { - res.status(500).json({ - message: "Unknown error", - }); - return; - } -}; diff --git a/src/api-server/controller/project/projectController.ts b/src/api-server/controller/project/projectController.ts index aa21ba9..a061d11 100644 --- a/src/api-server/controller/project/projectController.ts +++ b/src/api-server/controller/project/projectController.ts @@ -186,7 +186,6 @@ export const updateProjectController = async ( }; export const ViewData = async (req: Request, res: Response): Promise => { try { - console.log("req.query: ", req.query); const { projectId, organization, userId } = req.query as { organization: string; projectId: string; @@ -203,7 +202,6 @@ export const ViewData = async (req: Request, res: Response): Promise => { organization, userId, }); - console.log("result: ", result); switch (result?.status) { case "Project not found": res.status(404).json({ diff --git a/src/shared/services/helpers/ProjecthelperFn.ts b/src/shared/services/helpers/ProjecthelperFn.ts index 5749781..3f01f19 100644 --- a/src/shared/services/helpers/ProjecthelperFn.ts +++ b/src/shared/services/helpers/ProjecthelperFn.ts @@ -63,7 +63,6 @@ export const generateUntitledProjectName = async ( for (const proj of projects) { const match = proj.projectName.match(/^Untitled(?:\s?(\d+))?$/); - console.log("match: ", match); if (match) { const num = match[1] ? parseInt(match[1], 10) : 0; usedNumbers.add(num); diff --git a/src/shared/services/home/homeService.ts b/src/shared/services/home/homeService.ts new file mode 100644 index 0000000..04c26fd --- /dev/null +++ b/src/shared/services/home/homeService.ts @@ -0,0 +1,82 @@ +import projectModel from "../../model/project/project-model.ts"; +import userModel from "../../model/user-Model.ts"; +import { existingUser } from "../helpers/ProjecthelperFn.ts"; + +interface IRecentData { + organization: string; + userId: string; +} +interface IProject { + _id: string; + projectName: string; + createdBy: string; + thumbnail?: string; + createdAt: Date; + isViewed?: number; +} +interface searchProjectInterface { + searchName: string; + userId: string; + organization: string; +} +export const RecentlyAdded = async (data: IRecentData) => { + try { + const { userId, organization } = data; + const userExisting = await existingUser(userId, organization); + if (!userExisting) return { status: "User not found" }; + const userRecentData = await userModel(organization) + .findOne({ _id: userId }) + .populate({ + path: "recentlyViewed", + model: projectModel(organization), + select: "_id", + }); + const populatedProjects = userRecentData.recentlyViewed as IProject[]; + const RecentDatas = await Promise.all( + populatedProjects.map(async (project) => { + const projectExisting = await projectModel(organization) + .findOne({ + _id: project._id, + isArchive: false, + }) + .select("_id projectName createdBy thumbnail createdAt isViewed"); + return projectExisting; + }) + ); + + const filteredProjects = RecentDatas.filter(Boolean); + return { status: "Success", data: filteredProjects }; + } catch (error) { + return { status: error }; + } +}; +export const searchProject = async (data: searchProjectInterface) => { + try { + const { userId, organization, searchName } = data; + const userExisting = await existingUser(userId, organization); + if (!userExisting) return { status: "User not found" }; + const findprojectName = await projectModel(organization).find({ + projectName: { $regex: `${searchName}`, $options: "i" }, // 'i' makes it case-insensitive + isArchive: false, + }) + if (!findprojectName||findprojectName.length===0) return { status: "Project not found" } + return { status: "Success", data: findprojectName }; + } catch (error: unknown) { + return { status: error }; + } +} +export const searchTrashProject = async (data: searchProjectInterface) => { + try { + const { userId, organization, searchName } = data; + const userExisting = await existingUser(userId, organization); + if (!userExisting) return { status: "User not found" }; + const findprojectName = await projectModel(organization).find({ + projectName: { $regex: `${searchName}`, $options: "i" }, + isArchive: true,isDeleted:false + }) + if (!findprojectName||findprojectName.length===0) return { status: "Project not found" } + return { status: "Success", data: findprojectName }; + } catch (error: unknown) { + return { status: error }; + } +} \ No newline at end of file diff --git a/src/shared/services/home/recentDatasService.ts b/src/shared/services/home/recentDatasService.ts deleted file mode 100644 index b8a12d8..0000000 --- a/src/shared/services/home/recentDatasService.ts +++ /dev/null @@ -1,34 +0,0 @@ -import projectModel from "../../model/project/project-model.ts"; -import userModel from "../../model/user-Model.ts"; -import { existingUser } from "../helpers/ProjecthelperFn.ts"; - -interface IRecentData { - organization: string; - userId: string; -} -export const RecentlyAdded = async (data: IRecentData) => { - try { - const { userId, organization } = data; - const userExisting = await existingUser(userId, organization); - if (!userExisting) return { status: "User not found" }; - const userRecentData = await userModel(organization) - .findOne({ _id: userId }) - .populate({ - path: "recentlyViewed", - model: projectModel(organization), - select: "_id projectName createdBy thumbnail createdAt isViewed", - }); - let RecentDatas = []; - userRecentData.recentlyViewed.map(async (project: object) => { - console.log("project: ", typeof project); - const projectExisting = await projectModel(organization).findOne({ - _id: project, - isArchive: false, - }); - }); - if (!userRecentData) return { status: "Datas were empty" }; - return { status: "Success", data: userRecentData.recentlyViewed }; - } catch (error) { - return { status: error }; - } -}; diff --git a/src/shared/services/project/project-Services.ts b/src/shared/services/project/project-Services.ts index 66dd66a..7daefc1 100644 --- a/src/shared/services/project/project-Services.ts +++ b/src/shared/services/project/project-Services.ts @@ -33,6 +33,7 @@ interface ProjectInterface { userId: string; organization: string; } + export const createProject = async (data: CreateProjectInput) => { try { const { userId, thumbnail, sharedUsers, organization, projectUuid } = data; @@ -41,7 +42,7 @@ export const createProject = async (data: CreateProjectInput) => { return { status: "user_not_found", }; - } + } const projectExisting = await existingProject( projectUuid, organization, @@ -122,7 +123,7 @@ export const DeleteProject = async (data: ProjectInterface) => { { isArchive: true, DeletedAt: new Date() }, { new: true } ); - if (updateProject) return { status: "Success" }; + if (updateProject) return { status: "Success",project: updateProject }; } catch (error: unknown) { return { status: error }; } diff --git a/src/socket-server/controllers/project/projectController.ts b/src/socket-server/controllers/project/projectController.ts index 7c17519..96ae5ef 100644 --- a/src/socket-server/controllers/project/projectController.ts +++ b/src/socket-server/controllers/project/projectController.ts @@ -1,52 +1,126 @@ import { Socket, Server } from "socket.io"; -import { createProject } from "../../../shared/services/project/project-Services.ts"; +import { createProject, DeleteProject, updateProject } from "../../../shared/services/project/project-Services.ts"; import { EVENTS } from "../../socket/events.ts"; import { emitEventResponse } from "../../utils/emitEventResponse.ts"; -export const projectHandleEvent = async ( +export const projectHandleEvent = async ( event: string,socket: Socket,data: any,) => { + if (event !== EVENTS.addProject || !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", + }; + + emitEventResponse(socket, data?.organization, EVENTS.projectResponse, response); + return; + } + const result = await createProject(data); + + 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" }, + }; + + 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, + } + const response = { + success: status === "Success", + message: msg.message, + status, + socketId: socket.id, + organization: data.organization, + ...(status === "Success" ? { data: projectDatas, projectId: result.project._id } : {}), + }; + + emitEventResponse(socket, data.organization, EVENTS.projectResponse, response); + +} +export const projectDeleteHandleEvent = async ( event: string, socket: Socket, data: any, - namespace: any, - io: Server // Make sure this is passed in from the socket manager ) => { - if (!data?.organization) { - console.log(`Missing organization in event: ${event}`); - return; - } + if (event !== EVENTS.deleteProject || !data?.organization) return; - let result; + const result = await DeleteProject(data); + const status = typeof result?.status === "string" ? result.status : "unknown"; - switch (event) { - case EVENTS.addProject: { - result = await createProject(data); - console.log('result: ', result); - const isSuccess = result.status === "Success"; - // ✅ Build response object - const response = { - success: result.status === "Success", - message: - result.status === "project_exists" - ? "Project already exists" - : result.status === "user_not_found" - ? "User not found" - : result.status === "invalid_user_id" - ? "Invalid User ID" - : isSuccess - ? "Project created successfully" - : "Something went wrong", - ...(isSuccess ? { data: result.project } : {}), - status: String(result.status), - socketId: socket.id, - organization: data.organization, - }; + const messages: Record = { + Success: { message: "Project Deleted Successfully" }, + "User not found": { message: "User not found" }, + "Project not found": { message: "Project not found" }, + }; - // ✅ Emit response - emitEventResponse(socket, data.organization, EVENTS.projectResponse, response); - break; - } + const msg = messages[status] || { message: "Internal server error" }; + const projectDeleteDatas = + status === "Success" && result?.project + ? { + projectUuid: result.project.projectUuid, + projectName: result.project.projectName, + thumbnail: result.project.thumbnail, + createdBy: result.project.createdBy, + } + : undefined; - default: - console.warn(`Unknown project event: ${event}`); - } -}; + const response = { + success: status === "Success", + message: msg.message, + status, + socketId: socket.id, + organization: data.organization, + ...(projectDeleteDatas ? { data: projectDeleteDatas } : {}), + }; + + + emitEventResponse(socket, data.organization, EVENTS.deleteProjectResponse, response); +} +export const projecUpdateHandleEvent = async ( + event: string, + socket: Socket, + data: any, +) => { + console.log('data: ', data); + if (event !== EVENTS.ProjectUpdate || !data?.organization) return; + + const result = await updateProject(data); + const status = typeof result?.status === "string" ? result.status : "unknown"; + + const messages: Record = { + Success: { message: "Project updated Successfully" }, + "User not found": { message: "User not found" }, + "Project not found": { message: "Project not found" }, + }; + + const msg = messages[status] || { message: "Internal server error" }; + const projectDeleteDatas = + status === "Success" && result?.data + + + const response = { + success: status === "Success", + message: msg.message, + status, + socketId: socket.id, + organization: data.organization, + ...(projectDeleteDatas ? { data: projectDeleteDatas } : {}), + }; + + + emitEventResponse(socket, data.organization, EVENTS.projectUpdateResponse, response); + console.log('response: ', response); + +} \ No newline at end of file diff --git a/src/socket-server/manager/manager.ts b/src/socket-server/manager/manager.ts index 1ef2dc8..fe0adb2 100644 --- a/src/socket-server/manager/manager.ts +++ b/src/socket-server/manager/manager.ts @@ -1,5 +1,5 @@ import { Server, Socket } from 'socket.io'; -import { projectHandleEvent } from '../controllers/project/projectController.ts'; +import { projectDeleteHandleEvent, projectHandleEvent, projecUpdateHandleEvent } from '../controllers/project/projectController.ts'; export const SocketServer = (httpServer: any) => { const io = new Server(httpServer, { @@ -73,6 +73,6 @@ export const SocketServer = (httpServer: any) => { -handleNamespace(namespaces.project,projectHandleEvent) +handleNamespace(namespaces.project,projectHandleEvent,projectDeleteHandleEvent,projecUpdateHandleEvent) return io; }; \ No newline at end of file diff --git a/src/socket-server/socket/events.ts b/src/socket-server/socket/events.ts index 6d0dc31..a152c8d 100644 --- a/src/socket-server/socket/events.ts +++ b/src/socket-server/socket/events.ts @@ -100,6 +100,10 @@ export const EVENTS = { widget3DDeleteResponse:"viz-widget3D:response:delete", //PROJECT - addProject:"v1:project:add", - projectResponse:"v1-project:response:update", + addProject: "v1:project:add", + projectResponse: "v1-project:response:add", + deleteProject: "v1:project:delete", + deleteProjectResponse: "v1-project:response:delete", + ProjectUpdate: "v1:project:update", + projectUpdateResponse: "v1-project:response:update", } \ No newline at end of file diff --git a/src/socket-server/utils/emitEventResponse.ts b/src/socket-server/utils/emitEventResponse.ts index 8546ef8..6cbdd44 100644 --- a/src/socket-server/utils/emitEventResponse.ts +++ b/src/socket-server/utils/emitEventResponse.ts @@ -19,17 +19,16 @@ export const emitEventResponse = ( event: string, result: EmitOptions ) => { - console.log(`📤 emitEventResponse called for event: ${event}, organization: ${organization}`); if (!organization) { console.log(`Organization missing in response for event: ${event}`); return; } socket.emit(event, { - success: result.success, + // success: result.success, message: result.message, data: result.data , - error: result.error ?? null, + error: result.error, socketId: result.socketId, organization, });