From 8495d2b8d16d335555f1cf6a02378cd810c96477 Mon Sep 17 00:00:00 2001 From: shiva raj badu Date: Mon, 4 Aug 2025 18:08:00 +0545 Subject: [PATCH] feat(Nextjs): Custom Layout delete endpoint & ui implemented --- .../api/v1/ppt/endpoints/slide_to_html.py | 43 +++++++++++++++++- servers/fastapi/chroma/chroma.sqlite3 | Bin 4329472 -> 4329472 bytes .../components/ImageEditor.tsx | 4 +- .../context/LayoutContext.tsx | 3 +- .../nextjs/app/layout-preview/[slug]/page.tsx | 20 ++++++-- 5 files changed, 63 insertions(+), 7 deletions(-) diff --git a/servers/fastapi/api/v1/ppt/endpoints/slide_to_html.py b/servers/fastapi/api/v1/ppt/endpoints/slide_to_html.py index 221b3aa4..93b71e16 100644 --- a/servers/fastapi/api/v1/ppt/endpoints/slide_to_html.py +++ b/servers/fastapi/api/v1/ppt/endpoints/slide_to_html.py @@ -73,6 +73,11 @@ class GetLayoutsResponse(BaseModel): message: Optional[str] = None +class DeleteLayoutResponse(BaseModel): + success: bool + message: Optional[str] = None + + class PresentationSummary(BaseModel): presentation_id: str layout_count: int @@ -917,4 +922,40 @@ async def get_presentations_summary( raise HTTPException( status_code=500, detail=f"Internal server error while retrieving presentations summary: {str(e)}" - ) \ No newline at end of file + ) + + + +# ENDPOINT : Delete a layout +@LAYOUT_MANAGEMENT_ROUTER.delete( + "/delete-layouts/{presentation_id}", + response_model=DeleteLayoutResponse, + responses={ + 200: {"model": DeleteLayoutResponse, "description": "Layout deleted successfully"}, + 404: {"model": ErrorResponse, "description": "Presentation Layouts not found"}, + 500: {"model": ErrorResponse, "description": "Internal server error"} + } +) +async def delete_layouts(presentation_id: str, session: AsyncSession = Depends(get_async_session)): + try: + # Validate presentation_id format (basic UUID check) + if not presentation_id or len(presentation_id.strip()) == 0: + raise HTTPException( + status_code=400, + detail="Presentation ID cannot be empty" + ) + # Delete Presentation with all layouts + await session.execute(delete(PresentationLayoutCodeModel).where(PresentationLayoutCodeModel.presentation_id == presentation_id)) + await session.commit() + return DeleteLayoutResponse( + success=True, + message=f"Successfully deleted layout(s) for presentation {presentation_id}" + ) + except HTTPException: + raise + except Exception as e: + print(f"Error deleting layouts for presentation {presentation_id}: {str(e)}") + raise HTTPException( + status_code=500, + detail=f"Internal server error while deleting layouts: {str(e)}" + ) \ No newline at end of file diff --git a/servers/fastapi/chroma/chroma.sqlite3 b/servers/fastapi/chroma/chroma.sqlite3 index c35454c7e39142dab91db807cb46c2a859c5b2f7..4e0335039f3de3cc2016e823425a4a55498afef6 100644 GIT binary patch delta 306 zcmWm9M-ssR06<3*v>Z$-EM3`WP1y!95knjaB#}ZI3Npwdhdc@>qJ%OksG^2C8fc=0Hah5{hdu@vVuUd!m|})G P7FgncU%hp8z5o0G*s5;4 delta 300 zcmWm9HxdD10Dw^|=an-nXI9QE<02Y`TkMR2lEVD0!Uc@NH5|cFe2RB~r{B*;9han} zTvJ;~dF~#nIV=mq&0VO!{NKHN6xvB>5{xjx3=6EV!43zUaKQ}^ypZ989{~grLKqQ5 z5knjaB#}ZI87Rmihdc@>qJ%OksG^2C8fc=0HdJ)bMGt)pFvJLBOfba^b1bmL3jh21 JEws(y^8<42ZkYf8 diff --git a/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx b/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx index 820cf60c..29e67cc6 100644 --- a/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx +++ b/servers/nextjs/app/(presentation-generator)/components/ImageEditor.tsx @@ -275,7 +275,7 @@ const ImageEditor = ({ {/* Generate Tab */} - +

Current Prompt

@@ -333,7 +333,7 @@ const ImageEditor = ({

Previous Generated Images

-
+
{previousGeneratedImages.map((image) => (
handleImageChange(image.path)} diff --git a/servers/nextjs/app/(presentation-generator)/context/LayoutContext.tsx b/servers/nextjs/app/(presentation-generator)/context/LayoutContext.tsx index 6b8fe710..3609d8ef 100644 --- a/servers/nextjs/app/(presentation-generator)/context/LayoutContext.tsx +++ b/servers/nextjs/app/(presentation-generator)/context/LayoutContext.tsx @@ -85,7 +85,8 @@ const compileCustomLayout = (layoutCode: string, React: any, z: any) => { .replace(/import\s+.*\s+from\s+['"]zod['"];?/g, "") // remove every zod import (any style) .replace(/import\s+.*\s+from\s+['"]zod['"];?/g, "") - .replace(/const\s+[^=]*=\s*require\(['"]zod['"]\);?/g, ""); + .replace(/const\s+[^=]*=\s*require\(['"]zod['"]\);?/g, "") + .replace(/Looking at this HTML structure, I can see it's a slide layout with a header, title, description, and a 2x2 grid of images with captions, plus footer elements.?/g, "") const compiled = Babel.transform(cleanCode, { presets: [ ["react", { runtime: "classic" }], diff --git a/servers/nextjs/app/layout-preview/[slug]/page.tsx b/servers/nextjs/app/layout-preview/[slug]/page.tsx index 6dd7cd2c..22570da2 100644 --- a/servers/nextjs/app/layout-preview/[slug]/page.tsx +++ b/servers/nextjs/app/layout-preview/[slug]/page.tsx @@ -5,14 +5,14 @@ import { useParams, useRouter } from "next/navigation"; import LoadingStates from "../components/LoadingStates"; import { Card } from "@/components/ui/card"; import { Button } from "@/components/ui/button"; -import { ArrowLeft, Home } from "lucide-react"; +import { ArrowLeft, Home, Trash2 } from "lucide-react"; import { useLayout } from "@/app/(presentation-generator)/context/LayoutContext"; const GroupLayoutPreview = () => { const params = useParams(); const router = useRouter(); const slug = params.slug as string; - const { getFullDataByGroup, loading } = useLayout(); + const { getFullDataByGroup, loading,refetch } = useLayout(); const layoutGroup = getFullDataByGroup(slug); useEffect(() => { @@ -36,7 +36,17 @@ const GroupLayoutPreview = () => { if (!layoutGroup || layoutGroup.length === 0) { return ; } - + const deleteLayouts = async () => { + const presentationId = slug.replace('custom-',''); + refetch(); + router.back(); + const response = await fetch(`/api/v1/ppt/layout-management/delete-layouts/${presentationId}`, { + method: "DELETE", + }); + if (response.ok) { + router.push("/layout-preview"); + } + } return (
{/* Header */} @@ -62,6 +72,9 @@ const GroupLayoutPreview = () => { All Groups + {slug.includes('custom-') && }
@@ -73,6 +86,7 @@ const GroupLayoutPreview = () => { {layoutGroup[0].groupName}

+