diff --git a/src/api-server/Routes/projectRoutes.ts b/src/api-server/Routes/projectRoutes.ts index 80016d9..95d4373 100644 --- a/src/api-server/Routes/projectRoutes.ts +++ b/src/api-server/Routes/projectRoutes.ts @@ -1,7 +1,12 @@ import * as express from "express"; -import { createProjectController, GetProjects } from "../controller/project/projectController.ts"; +import { + createProjectController, + GetProjects, + RemoveProject, +} from "../controller/project/projectController.ts"; const projectRouter = express.Router(); -projectRouter.post("/upsertProject",createProjectController) -projectRouter.get("/Projects/:userId/:organization",GetProjects) -export default projectRouter \ No newline at end of file +projectRouter.post("/upsertProject", createProjectController); +projectRouter.get("/Projects/:userId/:organization", GetProjects); +projectRouter.patch("/Project/archive/:projectId", RemoveProject); +export default projectRouter; diff --git a/src/api-server/Routes/trashRoutes.ts b/src/api-server/Routes/trashRoutes.ts new file mode 100644 index 0000000..89709ca --- /dev/null +++ b/src/api-server/Routes/trashRoutes.ts @@ -0,0 +1,8 @@ +import * as express from "express"; +import { GetTrashList, RestoreTrash } from "../controller/trash/trashcontrollers.ts"; + +const trashRouter = express.Router(); +trashRouter.get("/Trash/Lists", GetTrashList); +trashRouter.patch("/restore",RestoreTrash) + +export default trashRouter; diff --git a/src/api-server/app.ts b/src/api-server/app.ts index 7e47001..aa446f2 100644 --- a/src/api-server/app.ts +++ b/src/api-server/app.ts @@ -20,6 +20,7 @@ import templateRoutes from "./Routes/templateRoutes.ts"; import widget3dRoutes from "./Routes/widget3dRoutes.ts"; import productRouter from "./Routes/productRoutes.ts"; import projectRouter from "./Routes/projectRoutes.ts"; +import trashRouter from "./Routes/trashRoutes.ts"; // import productFlowRoutes from "./Routes/productFlowRouts.ts"; const app = express(); @@ -87,4 +88,5 @@ app.use("/api/v2", widget3dRoutes); app.use("/api/v2", productRouter); // app.use("/api/v2", productFlowRoutes); app.use("/api/v1",projectRouter) +app.use("/api/v1",trashRouter) export default app; diff --git a/src/api-server/controller/project/projectController.ts b/src/api-server/controller/project/projectController.ts index c9e8bef..790861c 100644 --- a/src/api-server/controller/project/projectController.ts +++ b/src/api-server/controller/project/projectController.ts @@ -1,16 +1,25 @@ import { Request, Response } from "express"; -import { createProject,GetAllProjects } from "../../../shared/services/project/project-Services.ts"; +import { + createProject, + DeleteProject, + GetAllProjects, +} from "../../../shared/services/project/project-Services.ts"; export const createProjectController = async ( req: Request, res: Response ): Promise => { try { + const { projectName, userId, thumbnail, organization } = req.body; + if (!projectName || !userId || !thumbnail || !organization) + res.status(400).json({ + message: "All fields are required", + }); const result = await createProject(req.body); switch (result.status) { case "project_exists": - res.status(409).json({ + res.status(403).json({ message: "Project already exists", }); break; @@ -21,17 +30,12 @@ export const createProjectController = async ( }); break; - case "success": + case "Success": res.status(201).json({ - message: "Project created successfully", + message: "Project created Successfully", projectId: result.project._id, }); break; - case "All fields are required": - res.status(400).json({ - message: "All fields are required", - }); - break; default: res.status(500).json({ message: "Internal server error", @@ -50,25 +54,23 @@ export const GetProjects = async ( ): Promise => { try { const { userId, organization } = req.params; - const result = await GetAllProjects({ userId, organization}); + if (!userId || !organization) + res.status(400).json({ + message: "All fields are required", + }); + const result = await GetAllProjects({ userId, organization }); switch (result?.status) { - case "User not found": res.status(404).json({ message: "User not found", }); break; - case "success": + case "Success": res.status(201).json({ Projects: result?.Datas, }); break; - case "All fields are required": - res.status(400).json({ - message: "All fields are required", - }); - break; default: res.status(500).json({ message: "Internal server error", @@ -80,4 +82,44 @@ export const GetProjects = async ( message: "Unknown error", }); } -}; \ No newline at end of file +}; +export const RemoveProject = async ( + req: Request, + res: Response +): Promise => { + try { + const { projectId } = req.params; + const { organization, userId } = req.body; + if (!projectId || !organization || !userId) + res.status(400).json({ + message: "All fields are required", + }); + const result = await DeleteProject({ projectId, organization, userId }); + switch (result?.status) { + case "Project not found": + res.status(404).json({ + message: "Project not found", + }); + break; + case "User not found": + res.status(404).json({ + message: "User not found", + }); + break; + case "Success": + res.status(201).json({ + message: "Project Deleted Successfully", + }); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + res.status(500).json({ + message: "Unknown error", + }); + } +}; diff --git a/src/api-server/controller/trash/trashcontrollers.ts b/src/api-server/controller/trash/trashcontrollers.ts new file mode 100644 index 0000000..2e7b1d4 --- /dev/null +++ b/src/api-server/controller/trash/trashcontrollers.ts @@ -0,0 +1,96 @@ +import { Request, Response } from "express"; +import { + TrashDatas, + RestoreTrashData, +} from "../../../shared/services/trash/trashService.ts"; + +export const GetTrashList = async ( + req: Request, + res: Response +): Promise => { + try { + const { organization } = req.query as { organization?: string }; + console.log("organization: ", organization); + if (!organization) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const result = await TrashDatas({ organization }); + + switch (result.status) { + case "Trash is Empty": + res.status(200).json({ + message: "Trash is Empty", + TrashDatas: [], + }); + break; + + case "Success": + res.status(200).json({ + // message: "Project created Successfully", + TrashDatas: result.ListDatas, + }); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + console.log("error: ", error); + res.status(500).json({ + message: "Unknown error", + }); + } +}; + +export const RestoreTrash = async ( + req: Request, + res: Response +): Promise => { + try { + const { organization, projectId } = req.query as { + organization?: string; + projectId?: string; + }; + console.log("organization: ", organization); + if (!organization || !projectId) { + res.status(400).json({ + message: "All fields are required", + }); + return; + } + const result = await RestoreTrashData({ organization, projectId }); + + switch (result.status) { + case "Project not found": + res.status(404).json({ + message: "Project not found", + }); + break; + case "Project Restore unsuccessfull": + res.status(200).json({ + message: "Project Restore unsuccessfull", + }); + break; + case "Project Restored successfully": + res.status(200).json({ + message: "Project Restored successfully", + }); + break; + default: + res.status(500).json({ + message: "Internal server error", + }); + break; + } + } catch (error) { + console.log("error: ", error); + res.status(500).json({ + message: "Unknown error", + }); + } +}; diff --git a/src/shared/model/project/project-model.ts b/src/shared/model/project/project-model.ts index 3320391..09a8fd2 100644 --- a/src/shared/model/project/project-model.ts +++ b/src/shared/model/project/project-model.ts @@ -7,6 +7,7 @@ export interface Project extends Document { projectName: string; createdBy: User["_id"]; isArchive: boolean; + isDeleted: boolean; thumbnail: string; sharedUsers: []; DeletedAt: Date; @@ -22,6 +23,7 @@ const projectSchema: Schema = new Schema( createdBy: { type: Schema.Types.ObjectId, ref: "user" }, sharedUsers: [{ type: Schema.Types.ObjectId, ref: "user" }], DeletedAt: { type: Date, default: null }, + isDeleted: { type: Boolean, default: false }, total_versions: { type: String }, Present_version: { type: String }, }, diff --git a/src/shared/services/helpers/ProjecthelperFn.ts b/src/shared/services/helpers/ProjecthelperFn.ts new file mode 100644 index 0000000..1b16f94 --- /dev/null +++ b/src/shared/services/helpers/ProjecthelperFn.ts @@ -0,0 +1,49 @@ +import projectModel from "../../model/project/project-model.ts"; +import userModel from "../../model/user-Model.ts"; +import { Types } from "mongoose"; +import versionModel from "../../model/version/versionModel.ts"; +export const existingProject = async ( + projectName: string, + organization: string, + userId: string +) => { + const projectData = await projectModel(organization).findOne({ + projectName: projectName, + createdBy: userId, + isArchive: false, + }); + return projectData; +}; + +export const existingUser = async (userId: string, organization: string) => { + if (!Types.ObjectId.isValid(userId)) { + console.log("Invalid ObjectId format"); + return null; + } + const userData = await userModel(organization).findOne({ + _id: userId, + }); + return userData; +}; + +export const archiveProject = async ( + projectId: string, + organization: string +) => { + return await projectModel(organization).findByIdAndUpdate( + projectId, + { isArchive: true }, + { new: true } + ); +}; +export const previousVersion = async ( + projectId: string, + organization: string +) => { + const result = await versionModel(organization).findOne({ + projectId: projectId, + isArchive: false, + }); + // .sort({ version: -1 }); + return result; +}; diff --git a/src/shared/services/project/project-Services.ts b/src/shared/services/project/project-Services.ts index 90b8ac2..1b8c409 100644 --- a/src/shared/services/project/project-Services.ts +++ b/src/shared/services/project/project-Services.ts @@ -2,8 +2,12 @@ import projectModel from "../../model/project/project-model.ts"; import userModel from "../../model/user-Model.ts"; import { Types } from "mongoose"; import versionModel from "../../model/version/versionModel.ts"; -import { uploadProjectThumbnail } from "../blob/blobServices.ts"; - +import { + existingProject, + existingUser, + archiveProject, + previousVersion, +} from "../helpers/ProjecthelperFn.ts"; interface CreateProjectInput { projectName: string; projectUuid: string; @@ -12,8 +16,13 @@ interface CreateProjectInput { sharedUsers?: string[]; organization: string; } -interface GetInterface { - userId: string; +interface GetProjectsInterface { + userId: string; + organization: string; +} +interface DeleteProjectInterface { + projectId: string; + userId: string; organization: string; } export const createProject = async (data: CreateProjectInput) => { @@ -26,22 +35,17 @@ export const createProject = async (data: CreateProjectInput) => { sharedUsers, organization, } = data; - - if ( - !projectName || - !userId || - !thumbnail || - // !sharedUsers || - !organization - ) - return { status: "All fields are required" }; const userExisting = await existingUser(userId, organization); if (!userExisting) { return { status: "user_not_found", }; } - const projectExisting = await existingProject(projectName, organization,userId); + const projectExisting = await existingProject( + projectName, + organization, + userId + ); if (projectExisting) { return { @@ -60,26 +64,29 @@ export const createProject = async (data: CreateProjectInput) => { }); const versionData = await previousVersion(project._id, organization); if (!versionData || versionData.length === 0) { - const newVersion= await versionModel(organization).create({ + const newVersion = await versionModel(organization).create({ projectId: project._id, createdBy: userId, version: 0.01, }); - await projectModel(organization).findByIdAndUpdate({_id:project._id,isArchive:false},{total_versions:`v-${newVersion.version.toFixed(2)}`}) + await projectModel(organization).findByIdAndUpdate( + { _id: project._id, isArchive: false }, + { total_versions: `v-${newVersion.version.toFixed(2)}` } + ); } return { - status: "success", + status: "Success", project: project, }; } catch (error) { - console.log('error: ', error); + console.log("error: ", error); return { status: error, }; } }; -export const GetAllProjects = async (data: GetInterface) => { +export const GetAllProjects = async (data: GetProjectsInterface) => { try { const { userId, organization } = data; await existingUser(userId, organization); @@ -89,53 +96,30 @@ export const GetAllProjects = async (data: GetInterface) => { isArchive: false, }) .select("_id projectName createdBy thumbnail"); - if (projectDatas) return {status:"success", Datas: projectDatas }; + if (projectDatas) return { status: "Success", Datas: projectDatas }; } catch (error: unknown) { return { status: error }; } }; -export const existingProject = async ( - projectName: string, - organization: string, - userId:string -) => { - const projectData = await projectModel(organization).findOne({ - projectName: projectName, - createdBy:userId, - isArchive: false, - }); - return projectData; -}; - -export const existingUser = async (userId: string, organization: string) => { - if (!Types.ObjectId.isValid(userId)) { - console.log("Invalid ObjectId format"); - return null; +export const DeleteProject = async (data: DeleteProjectInterface) => { + try { + const { projectId, organization, userId } = data; + const ExistingUser = await existingUser(userId, organization); + if (!ExistingUser) return { status: "User not found" }; + const existingProject = await projectModel(organization).findOne({ + _id: projectId, + createdBy: userId, + isArchive: false, + }); + if (!existingProject) return { status: "Project not found" }; + const updateProject = await projectModel(organization).findOneAndUpdate( + { _id: projectId, isArchive: false }, + { isArchive: true, DeletedAt: new Date() }, + { new: true } + ); + if (updateProject) return { status: "Success" }; + } catch (error: unknown) { + return { status: error }; } - const userData = await userModel(organization).findOne({ - _id: userId, - }); - return userData; // ✅ Make sure you return it -}; - -export const archiveProject = async ( - projectId: string, - organization: string -) => { - return await projectModel(organization).findByIdAndUpdate( - projectId, - { isArchive: true }, - { new: true } - ); -}; -export const previousVersion = async ( - projectId: string, - organization: string -)=> { - console.log('projectId: ', projectId); - const result = await versionModel(organization).findOne({ projectId: projectId, isArchive: false}) - console.log('result: ', result); - // .sort({ version: -1 }); - return result; }; diff --git a/src/shared/services/trash/trashService.ts b/src/shared/services/trash/trashService.ts new file mode 100644 index 0000000..c1c1511 --- /dev/null +++ b/src/shared/services/trash/trashService.ts @@ -0,0 +1,68 @@ +import projectModel from "../../model/project/project-model.ts"; +interface IOrg { + organization: string; +} +interface IRestore { + projectId: string; + organization: string; +} +export const TrashDatas = async (data: IOrg) => { + try { + const { organization } = data; + + const TrashLists = await projectModel(organization).find({ + isArchive: true, + isDeleted: false, + }); + if (!TrashLists) return { staus: "Trash is Empty" }; + const TrashDocs: any[] = []; + for (const Trash of TrashLists) { + const now = new Date(); + const deletedPlus15 = new Date( + Trash.DeletedAt.getTime() + 15 * 24 * 60 * 60 * 1000 + ); + if (now > deletedPlus15) { + console.log("now > deletedPlus15: ", now > deletedPlus15); + await projectModel(organization).updateOne( + { _id: Trash._id }, + { $set: { isDeleted: true } } + ); + } else { + TrashDocs.push(Trash); + } + } + const ListDatas = TrashDocs.map((data) => { + return { + projectName: data.projectName, + thumbnail: data.thumbnail, + createdBy: data.createdBy, + _id: data._id, + }; + }); + + return { status: "Success", ListDatas }; + } catch (error) { + return { status: error }; + } +}; +export const RestoreTrashData = async (data: IRestore) => { + try { + const { projectId, organization } = data; + console.log("projectId: ", projectId); + const findProject = await projectModel(organization).findOne({ + _id: projectId, + isArchive: true, + }); + console.log("findProject: ", findProject); + if (!findProject) return { status: "Project not found" }; + const restoreData = await projectModel(organization).findOneAndUpdate( + { _id: projectId, isArchive: true }, + { isArchive: false, DeletedAt: null }, + { new: true } + ); + if (!restoreData) return { status: "Project Restore unsuccessfull" }; + return { status: "Project Restored successfully" }; + } catch (error) { + return { status: error }; + } +}; diff --git a/src/socket-server/controllers/project/projectController.ts b/src/socket-server/controllers/project/projectController.ts index df4ffa3..7c17519 100644 --- a/src/socket-server/controllers/project/projectController.ts +++ b/src/socket-server/controllers/project/projectController.ts @@ -21,10 +21,10 @@ export const projectHandleEvent = async ( case EVENTS.addProject: { result = await createProject(data); console.log('result: ', result); - const isSuccess = result.status === "success"; + const isSuccess = result.status === "Success"; // ✅ Build response object const response = { - success: result.status === "success", + success: result.status === "Success", message: result.status === "project_exists" ? "Project already exists"