diff --git a/.prettierignore b/.prettierignore index df26bac..4563529 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,4 +1,3 @@ -# frontend/** backend/ai/** backend/database/** backend/storage/** \ No newline at end of file diff --git a/backend/ai/wrangler.example.toml b/backend/ai/wrangler.example.toml index ede189b..8dcd480 100644 --- a/backend/ai/wrangler.example.toml +++ b/backend/ai/wrangler.example.toml @@ -5,3 +5,6 @@ compatibility_flags = ["nodejs_compat"] [ai] binding = "AI" + +[vars] +ANTHROPIC_API_KEY = "" diff --git a/backend/server/src/index.ts b/backend/server/src/index.ts index f69a303..293f802 100644 --- a/backend/server/src/index.ts +++ b/backend/server/src/index.ts @@ -207,7 +207,7 @@ io.on("connection", async (socket) => { } } catch (e: any) { console.error(`Error creating container ${data.sandboxId}:`, e) - io.emit("error", `Error: container creation. ${e.message ?? e}`) + socket.emit("error", `Error: container creation. ${e.message ?? e}`) } } ) @@ -244,7 +244,7 @@ io.on("connection", async (socket) => { await containers[data.sandboxId].setTimeout(CONTAINER_TIMEOUT) } catch (e: any) { console.error("Error setting timeout:", e) - io.emit("error", `Error: set timeout. ${e.message ?? e}`) + socket.emit("error", `Error: set timeout. ${e.message ?? e}`) } }) @@ -255,7 +255,7 @@ io.on("connection", async (socket) => { callback(fileContent) } catch (e: any) { console.error("Error getting file:", e) - io.emit("error", `Error: get file. ${e.message ?? e}`) + socket.emit("error", `Error: get file. ${e.message ?? e}`) } }) @@ -266,7 +266,7 @@ io.on("connection", async (socket) => { callback(files) } catch (e: any) { console.error("Error getting folder:", e) - io.emit("error", `Error: get folder. ${e.message ?? e}`) + socket.emit("error", `Error: get folder. ${e.message ?? e}`) } }) @@ -277,7 +277,7 @@ io.on("connection", async (socket) => { await fileManager.saveFile(fileId, body) } catch (e: any) { console.error("Error saving file:", e) - io.emit("error", `Error: file saving. ${e.message ?? e}`) + socket.emit("error", `Error: file saving. ${e.message ?? e}`) } }) @@ -290,7 +290,7 @@ io.on("connection", async (socket) => { callback(newFiles) } catch (e: any) { console.error("Error moving file:", e) - io.emit("error", `Error: file moving. ${e.message ?? e}`) + socket.emit("error", `Error: file moving. ${e.message ?? e}`) } } ) @@ -361,7 +361,7 @@ io.on("connection", async (socket) => { callback({ success }) } catch (e: any) { console.error("Error creating file:", e) - io.emit("error", `Error: file creation. ${e.message ?? e}`) + socket.emit("error", `Error: file creation. ${e.message ?? e}`) } }) @@ -373,7 +373,7 @@ io.on("connection", async (socket) => { callback() } catch (e: any) { console.error("Error creating folder:", e) - io.emit("error", `Error: folder creation. ${e.message ?? e}`) + socket.emit("error", `Error: folder creation. ${e.message ?? e}`) } }) @@ -384,7 +384,7 @@ io.on("connection", async (socket) => { await fileManager.renameFile(fileId, newName) } catch (e: any) { console.error("Error renaming file:", e) - io.emit("error", `Error: file renaming. ${e.message ?? e}`) + socket.emit("error", `Error: file renaming. ${e.message ?? e}`) } }) @@ -396,7 +396,7 @@ io.on("connection", async (socket) => { callback(newFiles) } catch (e: any) { console.error("Error deleting file:", e) - io.emit("error", `Error: file deletion. ${e.message ?? e}`) + socket.emit("error", `Error: file deletion. ${e.message ?? e}`) } }) @@ -407,7 +407,7 @@ io.on("connection", async (socket) => { callback(newFiles) } catch (e: any) { console.error("Error deleting folder:", e) - io.emit("error", `Error: folder deletion. ${e.message ?? e}`) + socket.emit("error", `Error: folder deletion. ${e.message ?? e}`) } }) @@ -416,10 +416,10 @@ io.on("connection", async (socket) => { try { await lockManager.acquireLock(data.sandboxId, async () => { await terminalManager.createTerminal(id, (responseString: string) => { - io.emit("terminalResponse", { id, data: responseString }) + socket.emit("terminalResponse", { id, data: responseString }) const port = extractPortNumber(responseString) if (port) { - io.emit( + socket.emit( "previewURL", "https://" + containers[data.sandboxId].getHost(port) ) @@ -429,7 +429,7 @@ io.on("connection", async (socket) => { callback() } catch (e: any) { console.error(`Error creating terminal ${id}:`, e) - io.emit("error", `Error: terminal creation. ${e.message ?? e}`) + socket.emit("error", `Error: terminal creation. ${e.message ?? e}`) } }) @@ -441,7 +441,7 @@ io.on("connection", async (socket) => { terminalManager.resizeTerminal(dimensions) } catch (e: any) { console.error("Error resizing terminal:", e) - io.emit("error", `Error: terminal resizing. ${e.message ?? e}`) + socket.emit("error", `Error: terminal resizing. ${e.message ?? e}`) } } ) @@ -452,7 +452,7 @@ io.on("connection", async (socket) => { await terminalManager.sendTerminalData(id, data) } catch (e: any) { console.error("Error writing to terminal:", e) - io.emit("error", `Error: writing to terminal. ${e.message ?? e}`) + socket.emit("error", `Error: writing to terminal. ${e.message ?? e}`) } }) @@ -463,7 +463,7 @@ io.on("connection", async (socket) => { callback() } catch (e: any) { console.error("Error closing terminal:", e) - io.emit("error", `Error: closing terminal. ${e.message ?? e}`) + socket.emit("error", `Error: closing terminal. ${e.message ?? e}`) } }) @@ -488,7 +488,7 @@ io.on("connection", async (socket) => { callback(result) } catch (e: any) { console.error("Error generating code:", e) - io.emit("error", `Error: code generation. ${e.message ?? e}`) + socket.emit("error", `Error: code generation. ${e.message ?? e}`) } } ) @@ -511,12 +511,12 @@ io.on("connection", async (socket) => { } } catch (e: any) { console.log("Error disconnecting:", e) - io.emit("error", `Error: disconnecting. ${e.message ?? e}`) + socket.emit("error", `Error: disconnecting. ${e.message ?? e}`) } }) } catch (e: any) { console.error("Error connecting:", e) - io.emit("error", `Error: connection. ${e.message ?? e}`) + socket.emit("error", `Error: connection. ${e.message ?? e}`) } }) diff --git a/frontend/.prettierrc b/frontend/.prettierrc index 42830e2..6449bfb 100644 --- a/frontend/.prettierrc +++ b/frontend/.prettierrc @@ -1,5 +1,6 @@ { "tabWidth": 2, "semi": false, - "singleQuote": false + "singleQuote": false, + "insertFinalNewline": true } \ No newline at end of file diff --git a/frontend/app/(app)/code/[id]/page.tsx b/frontend/app/(app)/code/[id]/page.tsx index 9681a5b..d193d39 100644 --- a/frontend/app/(app)/code/[id]/page.tsx +++ b/frontend/app/(app)/code/[id]/page.tsx @@ -1,12 +1,11 @@ -import Navbar from "@/components/editor/navbar" import { Room } from "@/components/editor/live/room" +import Loading from "@/components/editor/loading" +import Navbar from "@/components/editor/navbar" +import { TerminalProvider } from "@/context/TerminalContext" import { Sandbox, User, UsersToSandboxes } from "@/lib/types" import { currentUser } from "@clerk/nextjs" -import { notFound, redirect } from "next/navigation" -import Loading from "@/components/editor/loading" import dynamic from "next/dynamic" -import fs from "fs" -import { TerminalProvider } from "@/context/TerminalContext" +import { notFound, redirect } from "next/navigation" export const revalidate = 0 @@ -89,19 +88,20 @@ export default async function CodePage({ params }: { params: { id: string } }) { return ( <> -
- - - -
- -
-
-
-
+
+ + + +
+ +
+
+
+
) } diff --git a/frontend/app/(app)/dashboard/page.tsx b/frontend/app/(app)/dashboard/page.tsx index 1f29f96..52f8c3f 100644 --- a/frontend/app/(app)/dashboard/page.tsx +++ b/frontend/app/(app)/dashboard/page.tsx @@ -1,8 +1,8 @@ -import { UserButton, currentUser } from "@clerk/nextjs" -import { redirect } from "next/navigation" import Dashboard from "@/components/dashboard" import Navbar from "@/components/dashboard/navbar" -import { Sandbox, User } from "@/lib/types" +import { User } from "@/lib/types" +import { currentUser } from "@clerk/nextjs" +import { redirect } from "next/navigation" export default async function DashboardPage() { const user = await currentUser() diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index c93b647..494079e 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -15,7 +15,7 @@ export const metadata: Metadata = { } export default function RootLayout({ - children + children, }: Readonly<{ children: React.ReactNode }>) { @@ -29,9 +29,7 @@ export default function RootLayout({ disableTransitionOnChange > - - {children} - + {children} @@ -40,4 +38,4 @@ export default function RootLayout({ ) -} \ No newline at end of file +} diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index 3f99044..8041367 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -1,13 +1,13 @@ -import { currentUser } from "@clerk/nextjs"; -import { redirect } from "next/navigation"; -import Landing from "@/components/landing"; +import Landing from "@/components/landing" +import { currentUser } from "@clerk/nextjs" +import { redirect } from "next/navigation" export default async function Home() { - const user = await currentUser(); + const user = await currentUser() if (user) { - redirect("/dashboard"); + redirect("/dashboard") } - return ; + return } diff --git a/frontend/components/dashboard/about.tsx b/frontend/components/dashboard/about.tsx index 33b0daa..7accef0 100644 --- a/frontend/components/dashboard/about.tsx +++ b/frontend/components/dashboard/about.tsx @@ -3,16 +3,9 @@ import { Dialog, DialogContent, - DialogDescription, DialogHeader, DialogTitle, - DialogTrigger, } from "@/components/ui/dialog" -import Image from "next/image" -import { useState } from "react" - -import { Button } from "../ui/button" -import { ChevronRight } from "lucide-react" export default function AboutModal({ open, diff --git a/frontend/components/dashboard/index.tsx b/frontend/components/dashboard/index.tsx index a7094ec..a1599c7 100644 --- a/frontend/components/dashboard/index.tsx +++ b/frontend/components/dashboard/index.tsx @@ -1,24 +1,16 @@ "use client" -import CustomButton from "@/components/ui/customButton" import { Button } from "@/components/ui/button" -import { - Code2, - FolderDot, - HelpCircle, - Plus, - Settings, - Users, -} from "lucide-react" -import { useEffect, useState } from "react" +import CustomButton from "@/components/ui/customButton" import { Sandbox } from "@/lib/types" +import { Code2, FolderDot, HelpCircle, Plus, Users } from "lucide-react" +import { useRouter, useSearchParams } from "next/navigation" +import { useEffect, useState } from "react" +import { toast } from "sonner" +import AboutModal from "./about" +import NewProjectModal from "./newProject" import DashboardProjects from "./projects" import DashboardSharedWithMe from "./shared" -import NewProjectModal from "./newProject" -import Link from "next/link" -import { useRouter, useSearchParams } from "next/navigation" -import AboutModal from "./about" -import { toast } from "sonner" type TScreen = "projects" | "shared" | "settings" | "search" @@ -49,8 +41,9 @@ export default function Dashboard({ const q = searchParams.get("q") const router = useRouter() - useEffect(() => { // update the dashboard to show a new project - router.refresh() + useEffect(() => { + // update the dashboard to show a new project + router.refresh() }, []) return ( diff --git a/frontend/components/dashboard/navbar/index.tsx b/frontend/components/dashboard/navbar/index.tsx index 8b1f02e..2f983af 100644 --- a/frontend/components/dashboard/navbar/index.tsx +++ b/frontend/components/dashboard/navbar/index.tsx @@ -1,9 +1,9 @@ +import Logo from "@/assets/logo.svg" +import { User } from "@/lib/types" import Image from "next/image" import Link from "next/link" -import Logo from "@/assets/logo.svg" -import DashboardNavbarSearch from "./search" import UserButton from "../../ui/userButton" -import { User } from "@/lib/types" +import DashboardNavbarSearch from "./search" export default function DashboardNavbar({ userData }: { userData: User }) { return ( diff --git a/frontend/components/dashboard/navbar/search.tsx b/frontend/components/dashboard/navbar/search.tsx index f254efe..75f314e 100644 --- a/frontend/components/dashboard/navbar/search.tsx +++ b/frontend/components/dashboard/navbar/search.tsx @@ -1,13 +1,12 @@ -"use client"; +"use client" -import { Input } from "../../ui/input"; -import { Search } from "lucide-react"; -import { useEffect, useState } from "react"; -import { useRouter } from "next/navigation"; +import { Search } from "lucide-react" +import { useRouter } from "next/navigation" +import { Input } from "../../ui/input" export default function DashboardNavbarSearch() { // const [search, setSearch] = useState(""); - const router = useRouter(); + const router = useRouter() // useEffect(() => { // const delayDebounceFn = setTimeout(() => { @@ -29,14 +28,14 @@ export default function DashboardNavbarSearch() { // onChange={(e) => setSearch(e.target.value)} onChange={(e) => { if (e.target.value === "") { - router.push(`/dashboard`); - return; + router.push(`/dashboard`) + return } - router.push(`/dashboard?q=${e.target.value}`); + router.push(`/dashboard?q=${e.target.value}`) }} placeholder="Search projects..." className="pl-8" /> - ); + ) } diff --git a/frontend/components/dashboard/projectCard/dropdown.tsx b/frontend/components/dashboard/projectCard/dropdown.tsx index 24a93f8..522d5bc 100644 --- a/frontend/components/dashboard/projectCard/dropdown.tsx +++ b/frontend/components/dashboard/projectCard/dropdown.tsx @@ -1,30 +1,30 @@ -"use client"; +"use client" -import { Sandbox } from "@/lib/types"; -import { Ellipsis, Globe, Lock, Trash2 } from "lucide-react"; +import { Sandbox } from "@/lib/types" +import { Ellipsis, Globe, Lock, Trash2 } from "lucide-react" import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, -} from "@/components/ui/dropdown-menu"; +} from "@/components/ui/dropdown-menu" export default function ProjectCardDropdown({ sandbox, onVisibilityChange, onDelete, }: { - sandbox: Sandbox; - onVisibilityChange: (sandbox: Sandbox) => void; - onDelete: (sandbox: Sandbox) => void; + sandbox: Sandbox + onVisibilityChange: (sandbox: Sandbox) => void + onDelete: (sandbox: Sandbox) => void }) { return ( { - e.preventDefault(); - e.stopPropagation(); + e.preventDefault() + e.stopPropagation() }} className="h-6 w-6 flex items-center justify-center transition-colors bg-transparent hover:bg-muted-foreground/25 rounded-sm outline-foreground" > @@ -33,8 +33,8 @@ export default function ProjectCardDropdown({ { - e.stopPropagation(); - onVisibilityChange(sandbox); + e.stopPropagation() + onVisibilityChange(sandbox) }} className="cursor-pointer" > @@ -52,8 +52,8 @@ export default function ProjectCardDropdown({ { - e.stopPropagation(); - onDelete(sandbox); + e.stopPropagation() + onDelete(sandbox) }} className="!text-destructive cursor-pointer" > @@ -62,5 +62,5 @@ export default function ProjectCardDropdown({ - ); + ) } diff --git a/frontend/components/dashboard/projectCard/index.tsx b/frontend/components/dashboard/projectCard/index.tsx index 9cc3729..a463e84 100644 --- a/frontend/components/dashboard/projectCard/index.tsx +++ b/frontend/components/dashboard/projectCard/index.tsx @@ -1,14 +1,14 @@ "use client" +import { Card } from "@/components/ui/card" +import { projectTemplates } from "@/lib/data" +import { Sandbox } from "@/lib/types" import { AnimatePresence, motion } from "framer-motion" +import { Clock, Globe, Lock } from "lucide-react" import Image from "next/image" +import { useRouter } from "next/navigation" import { useEffect, useState } from "react" import ProjectCardDropdown from "./dropdown" -import { Clock, Globe, Lock } from "lucide-react" -import { Sandbox } from "@/lib/types" -import { Card } from "@/components/ui/card" -import { useRouter } from "next/navigation" -import { projectTemplates } from "@/lib/data" export default function ProjectCard({ children, diff --git a/frontend/components/dashboard/projectCard/revealEffect.tsx b/frontend/components/dashboard/projectCard/revealEffect.tsx index 3786394..fcda16c 100644 --- a/frontend/components/dashboard/projectCard/revealEffect.tsx +++ b/frontend/components/dashboard/projectCard/revealEffect.tsx @@ -1,8 +1,8 @@ -"use client"; -import { cn } from "@/lib/utils"; -import { Canvas, useFrame, useThree } from "@react-three/fiber"; -import React, { useMemo, useRef } from "react"; -import * as THREE from "three"; +"use client" +import { cn } from "@/lib/utils" +import { Canvas, useFrame, useThree } from "@react-three/fiber" +import React, { useMemo, useRef } from "react" +import * as THREE from "three" export const CanvasRevealEffect = ({ animationSpeed = 0.4, @@ -12,12 +12,12 @@ export const CanvasRevealEffect = ({ dotSize, showGradient = true, }: { - animationSpeed?: number; - opacities?: number[]; - colors?: number[][]; - containerClassName?: string; - dotSize?: number; - showGradient?: boolean; + animationSpeed?: number + opacities?: number[] + colors?: number[][] + containerClassName?: string + dotSize?: number + showGradient?: boolean }) => { return (
@@ -41,16 +41,16 @@ export const CanvasRevealEffect = ({
)}
- ); -}; + ) +} interface DotMatrixProps { - colors?: number[][]; - opacities?: number[]; - totalSize?: number; - dotSize?: number; - shader?: string; - center?: ("x" | "y")[]; + colors?: number[][] + opacities?: number[] + totalSize?: number + dotSize?: number + shader?: string + center?: ("x" | "y")[] } const DotMatrix: React.FC = ({ @@ -69,7 +69,7 @@ const DotMatrix: React.FC = ({ colors[0], colors[0], colors[0], - ]; + ] if (colors.length === 2) { colorsArray = [ colors[0], @@ -78,7 +78,7 @@ const DotMatrix: React.FC = ({ colors[1], colors[1], colors[1], - ]; + ] } else if (colors.length === 3) { colorsArray = [ colors[0], @@ -87,7 +87,7 @@ const DotMatrix: React.FC = ({ colors[1], colors[2], colors[2], - ]; + ] } return { @@ -111,8 +111,8 @@ const DotMatrix: React.FC = ({ value: dotSize, type: "uniform1f", }, - }; - }, [colors, opacities, totalSize, dotSize]); + } + }, [colors, opacities, totalSize, dotSize]) return ( = ({ uniforms={uniforms} maxFps={60} /> - ); -}; + ) +} type Uniforms = { [key: string]: { - value: number[] | number[][] | number; - type: string; - }; -}; + value: number[] | number[][] | number + type: string + } +} const ShaderMaterial = ({ source, uniforms, maxFps = 60, }: { - source: string; - hovered?: boolean; - maxFps?: number; - uniforms: Uniforms; + source: string + hovered?: boolean + maxFps?: number + uniforms: Uniforms }) => { - const { size } = useThree(); - const ref = useRef(); - let lastFrameTime = 0; + const { size } = useThree() + const ref = useRef() + let lastFrameTime = 0 useFrame(({ clock }) => { - if (!ref.current) return; - const timestamp = clock.getElapsedTime(); + if (!ref.current) return + const timestamp = clock.getElapsedTime() if (timestamp - lastFrameTime < 1 / maxFps) { - return; + return } - lastFrameTime = timestamp; + lastFrameTime = timestamp - const material: any = ref.current.material; - const timeLocation = material.uniforms.u_time; - timeLocation.value = timestamp; - }); + const material: any = ref.current.material + const timeLocation = material.uniforms.u_time + timeLocation.value = timestamp + }) const getUniforms = () => { - const preparedUniforms: any = {}; + const preparedUniforms: any = {} for (const uniformName in uniforms) { - const uniform: any = uniforms[uniformName]; + const uniform: any = uniforms[uniformName] switch (uniform.type) { case "uniform1f": - preparedUniforms[uniformName] = { value: uniform.value, type: "1f" }; - break; + preparedUniforms[uniformName] = { value: uniform.value, type: "1f" } + break case "uniform3f": preparedUniforms[uniformName] = { value: new THREE.Vector3().fromArray(uniform.value), type: "3f", - }; - break; + } + break case "uniform1fv": - preparedUniforms[uniformName] = { value: uniform.value, type: "1fv" }; - break; + preparedUniforms[uniformName] = { value: uniform.value, type: "1fv" } + break case "uniform3fv": preparedUniforms[uniformName] = { value: uniform.value.map((v: number[]) => new THREE.Vector3().fromArray(v) ), type: "3fv", - }; - break; + } + break case "uniform2f": preparedUniforms[uniformName] = { value: new THREE.Vector2().fromArray(uniform.value), type: "2f", - }; - break; + } + break default: - console.error(`Invalid uniform type for '${uniformName}'.`); - break; + console.error(`Invalid uniform type for '${uniformName}'.`) + break } } - preparedUniforms["u_time"] = { value: 0, type: "1f" }; + preparedUniforms["u_time"] = { value: 0, type: "1f" } preparedUniforms["u_resolution"] = { value: new THREE.Vector2(size.width * 2, size.height * 2), - }; // Initialize u_resolution - return preparedUniforms; - }; + } // Initialize u_resolution + return preparedUniforms + } // Shader material const material = useMemo(() => { @@ -272,33 +272,33 @@ const ShaderMaterial = ({ blending: THREE.CustomBlending, blendSrc: THREE.SrcAlphaFactor, blendDst: THREE.OneFactor, - }); + }) - return materialObject; - }, [size.width, size.height, source]); + return materialObject + }, [size.width, size.height, source]) return ( - ); -}; + ) +} const Shader: React.FC = ({ source, uniforms, maxFps = 60 }) => { return ( - ); -}; + ) +} interface ShaderProps { - source: string; + source: string uniforms: { [key: string]: { - value: number[] | number[][] | number; - type: string; - }; - }; - maxFps?: number; + value: number[] | number[][] | number + type: string + } + } + maxFps?: number } diff --git a/frontend/components/dashboard/projects.tsx b/frontend/components/dashboard/projects.tsx index 9953e19..7c9705d 100644 --- a/frontend/components/dashboard/projects.tsx +++ b/frontend/components/dashboard/projects.tsx @@ -1,16 +1,12 @@ -"use client"; +"use client" -import { Sandbox } from "@/lib/types"; -import ProjectCard from "./projectCard"; -import Image from "next/image"; -import ProjectCardDropdown from "./projectCard/dropdown"; -import { Clock, Globe, Lock } from "lucide-react"; -import Link from "next/link"; -import { Card } from "../ui/card"; -import { deleteSandbox, updateSandbox } from "@/lib/actions"; -import { toast } from "sonner"; -import { useEffect, useState } from "react"; -import { CanvasRevealEffect } from "./projectCard/revealEffect"; +import { deleteSandbox, updateSandbox } from "@/lib/actions" +import { Sandbox } from "@/lib/types" +import Link from "next/link" +import { useEffect, useState } from "react" +import { toast } from "sonner" +import ProjectCard from "./projectCard" +import { CanvasRevealEffect } from "./projectCard/revealEffect" const colors: { [key: string]: number[][] } = { react: [ @@ -21,38 +17,37 @@ const colors: { [key: string]: number[][] } = { [86, 184, 72], [59, 112, 52], ], -}; +} export default function DashboardProjects({ sandboxes, q, }: { - sandboxes: Sandbox[]; - q: string | null; + sandboxes: Sandbox[] + q: string | null }) { - const [deletingId, setDeletingId] = useState(""); + const [deletingId, setDeletingId] = useState("") const onDelete = async (sandbox: Sandbox) => { - setDeletingId(sandbox.id); - toast(`Project ${sandbox.name} deleted.`); - await deleteSandbox(sandbox.id); - }; + setDeletingId(sandbox.id) + toast(`Project ${sandbox.name} deleted.`) + await deleteSandbox(sandbox.id) + } useEffect(() => { if (deletingId) { - setDeletingId(""); + setDeletingId("") } - }, [sandboxes]); + }, [sandboxes]) const onVisibilityChange = async (sandbox: Sandbox) => { - const newVisibility = - sandbox.visibility === "public" ? "private" : "public"; - toast(`Project ${sandbox.name} is now ${newVisibility}.`); + const newVisibility = sandbox.visibility === "public" ? "private" : "public" + toast(`Project ${sandbox.name} is now ${newVisibility}.`) await updateSandbox({ id: sandbox.id, visibility: newVisibility, - }); - }; + }) + } return (
@@ -65,7 +60,7 @@ export default function DashboardProjects({ {sandboxes.map((sandbox) => { if (q && q.length > 0) { if (!sandbox.name.toLowerCase().includes(q.toLowerCase())) { - return null; + return null } } return ( @@ -93,7 +88,7 @@ export default function DashboardProjects({
- ); + ) })}
) : ( @@ -103,5 +98,5 @@ export default function DashboardProjects({ )}
- ); + ) } diff --git a/frontend/components/dashboard/shared.tsx b/frontend/components/dashboard/shared.tsx index 9e5eb03..d9d4d39 100644 --- a/frontend/components/dashboard/shared.tsx +++ b/frontend/components/dashboard/shared.tsx @@ -1,29 +1,27 @@ -import { Sandbox } from "@/lib/types"; import { Table, TableBody, - TableCaption, TableCell, TableHead, TableHeader, TableRow, -} from "@/components/ui/table"; -import Image from "next/image"; -import Button from "../ui/customButton"; -import { ChevronRight } from "lucide-react"; -import Avatar from "../ui/avatar"; -import Link from "next/link"; +} from "@/components/ui/table" +import { ChevronRight } from "lucide-react" +import Image from "next/image" +import Link from "next/link" +import Avatar from "../ui/avatar" +import Button from "../ui/customButton" export default function DashboardSharedWithMe({ shared, }: { shared: { - id: string; - name: string; - type: "react" | "node"; - author: string; - sharedOn: Date; - }[]; + id: string + name: string + type: "react" | "node" + author: string + sharedOn: Date + }[] }) { return (
@@ -86,5 +84,5 @@ export default function DashboardSharedWithMe({
)} - ); + ) } diff --git a/frontend/components/editor/AIChat/ChatInput.tsx b/frontend/components/editor/AIChat/ChatInput.tsx index a40e0b5..380b6a4 100644 --- a/frontend/components/editor/AIChat/ChatInput.tsx +++ b/frontend/components/editor/AIChat/ChatInput.tsx @@ -1,36 +1,51 @@ -import React from 'react'; -import { Button } from '../../ui/button'; -import { Send, StopCircle } from 'lucide-react'; +import { Send, StopCircle } from "lucide-react" +import { Button } from "../../ui/button" interface ChatInputProps { - input: string; - setInput: (input: string) => void; - isGenerating: boolean; - handleSend: () => void; - handleStopGeneration: () => void; + input: string + setInput: (input: string) => void + isGenerating: boolean + handleSend: () => void + handleStopGeneration: () => void } -export default function ChatInput({ input, setInput, isGenerating, handleSend, handleStopGeneration }: ChatInputProps) { +export default function ChatInput({ + input, + setInput, + isGenerating, + handleSend, + handleStopGeneration, +}: ChatInputProps) { return (
- setInput(e.target.value)} - onKeyPress={(e) => e.key === 'Enter' && !isGenerating && handleSend()} + onKeyPress={(e) => e.key === "Enter" && !isGenerating && handleSend()} className="flex-grow p-2 border rounded-lg min-w-0 bg-input" placeholder="Type your message..." disabled={isGenerating} /> {isGenerating ? ( - ) : ( - )}
- ); + ) } diff --git a/frontend/components/editor/AIChat/ChatMessage.tsx b/frontend/components/editor/AIChat/ChatMessage.tsx index 7eac365..6b0fa72 100644 --- a/frontend/components/editor/AIChat/ChatMessage.tsx +++ b/frontend/components/editor/AIChat/ChatMessage.tsx @@ -1,25 +1,31 @@ -import React, { useState } from 'react'; -import { Button } from '../../ui/button'; -import { ChevronUp, ChevronDown, Copy, Check, CornerUpLeft } from 'lucide-react'; -import ReactMarkdown from 'react-markdown'; -import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; -import { vscDarkPlus } from 'react-syntax-highlighter/dist/esm/styles/prism'; -import remarkGfm from 'remark-gfm'; -import { copyToClipboard, stringifyContent } from './lib/chatUtils'; +import { Check, ChevronDown, ChevronUp, Copy, CornerUpLeft } from "lucide-react" +import React, { useState } from "react" +import ReactMarkdown from "react-markdown" +import { Prism as SyntaxHighlighter } from "react-syntax-highlighter" +import { vscDarkPlus } from "react-syntax-highlighter/dist/esm/styles/prism" +import remarkGfm from "remark-gfm" +import { Button } from "../../ui/button" +import { copyToClipboard, stringifyContent } from "./lib/chatUtils" interface MessageProps { message: { - role: 'user' | 'assistant'; - content: string; - context?: string; - }; - setContext: (context: string | null) => void; - setIsContextExpanded: (isExpanded: boolean) => void; + role: "user" | "assistant" + content: string + context?: string + } + setContext: (context: string | null) => void + setIsContextExpanded: (isExpanded: boolean) => void } -export default function ChatMessage({ message, setContext, setIsContextExpanded }: MessageProps) { - const [expandedMessageIndex, setExpandedMessageIndex] = useState(null); - const [copiedText, setCopiedText] = useState(null); +export default function ChatMessage({ + message, + setContext, + setIsContextExpanded, +}: MessageProps) { + const [expandedMessageIndex, setExpandedMessageIndex] = useState< + number | null + >(null) + const [copiedText, setCopiedText] = useState(null) const renderCopyButton = (text: any) => ( - ); + ) const askAboutCode = (code: any) => { - const contextString = stringifyContent(code); - setContext(`Regarding this code:\n${contextString}`); - setIsContextExpanded(false); - }; + const contextString = stringifyContent(code) + setContext(`Regarding this code:\n${contextString}`) + setIsContextExpanded(false) + } const renderMarkdownElement = (props: any) => { - const { node, children } = props; - const content = stringifyContent(children); + const { node, children } = props + const content = stringifyContent(children) return (
@@ -59,22 +65,30 @@ export default function ChatMessage({ message, setContext, setIsContextExpanded
- {React.createElement(node.tagName, { - ...props, - className: `${props.className || ''} hover:bg-transparent rounded p-1 transition-colors` - }, children)} + {React.createElement( + node.tagName, + { + ...props, + className: `${ + props.className || "" + } hover:bg-transparent rounded p-1 transition-colors`, + }, + children + )} - ); - }; + ) + } return (
-
- {message.role === 'user' && ( +
+ {message.role === "user" && (
{renderCopyButton(message.content)}