add private functionality

This commit is contained in:
Ishaan Dey 2024-05-26 19:02:47 -07:00
parent 34afefcc4a
commit 089ab2b1df
3 changed files with 84 additions and 75 deletions

View File

@ -82,6 +82,10 @@ export default async function CodePage({ params }: { params: { id: string } }) {
return notFound()
}
if (isSharedUser && sandboxData.visibility === "private") {
return notFound()
}
return (
<div className="overflow-hidden overscroll-none w-screen flex flex-col h-screen bg-background">
<Room id={sandboxId}>

View File

@ -1,7 +1,7 @@
"use client";
"use client"
import CustomButton from "@/components/ui/customButton";
import { Button } from "@/components/ui/button";
import CustomButton from "@/components/ui/customButton"
import { Button } from "@/components/ui/button"
import {
Code2,
FolderDot,
@ -9,51 +9,51 @@ import {
Plus,
Settings,
Users,
} from "lucide-react";
import { useEffect, useState } from "react";
import { Sandbox } from "@/lib/types";
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";
} from "lucide-react"
import { useEffect, useState } from "react"
import { Sandbox } from "@/lib/types"
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";
type TScreen = "projects" | "shared" | "settings" | "search"
export default function Dashboard({
sandboxes,
shared,
}: {
sandboxes: Sandbox[];
sandboxes: Sandbox[]
shared: {
id: string;
name: string;
type: "react" | "node";
author: string;
sharedOn: Date;
}[];
id: string
name: string
type: "react" | "node"
author: string
sharedOn: Date
}[]
}) {
const [screen, setScreen] = useState<TScreen>("projects");
const [screen, setScreen] = useState<TScreen>("projects")
const [newProjectModalOpen, setNewProjectModalOpen] = useState(false);
const [aboutModalOpen, setAboutModalOpen] = useState(false);
const [newProjectModalOpen, setNewProjectModalOpen] = useState(false)
const [aboutModalOpen, setAboutModalOpen] = useState(false)
const activeScreen = (s: TScreen) => {
if (screen === s) return "justify-start";
else return "justify-start font-normal text-muted-foreground";
};
if (screen === s) return "justify-start"
else return "justify-start font-normal text-muted-foreground"
}
const searchParams = useSearchParams();
const q = searchParams.get("q");
const router = useRouter();
const searchParams = useSearchParams()
const q = searchParams.get("q")
const router = useRouter()
useEffect(() => {
if (!sandboxes) {
router.refresh();
router.refresh()
}
}, [sandboxes]);
}, [sandboxes])
return (
<>
@ -68,10 +68,10 @@ export default function Dashboard({
<CustomButton
onClick={() => {
if (sandboxes.length >= 8) {
toast.error("You reached the maximum # of sandboxes.");
return;
toast.error("You reached the maximum # of sandboxes.")
return
}
setNewProjectModalOpen(true);
setNewProjectModalOpen(true)
}}
className="mb-4"
>
@ -107,7 +107,7 @@ export default function Dashboard({
<a target="_blank" href="https://github.com/ishaan1013/sandbox">
<Button
variant="ghost"
className="justify-start font-normal text-muted-foreground"
className="justify-start w-full font-normal text-muted-foreground"
>
<Code2 className="w-4 h-4 mr-2" />
GitHub Repository
@ -134,5 +134,5 @@ export default function Dashboard({
) : screen === "settings" ? null : null}
</div>
</>
);
)
}

View File

@ -1,4 +1,4 @@
"use client";
"use client"
import {
Dialog,
@ -7,12 +7,12 @@ import {
DialogHeader,
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog";
import Image from "next/image";
import { useState } from "react";
import { set, z } from "zod";
import { zodResolver } from "@hookform/resolvers/zod";
import { useForm } from "react-hook-form";
} from "@/components/ui/dialog"
import Image from "next/image"
import { useState } from "react"
import { set, z } from "zod"
import { zodResolver } from "@hookform/resolvers/zod"
import { useForm } from "react-hook-form"
import {
Form,
@ -22,29 +22,29 @@ import {
FormItem,
FormLabel,
FormMessage,
} from "@/components/ui/form";
import { Input } from "@/components/ui/input";
} from "@/components/ui/form"
import { Input } from "@/components/ui/input"
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue,
} from "@/components/ui/select";
import { useUser } from "@clerk/nextjs";
import { createSandbox } from "@/lib/actions";
import { useRouter } from "next/navigation";
import { Loader2 } from "lucide-react";
import { Button } from "../ui/button";
} from "@/components/ui/select"
import { useUser } from "@clerk/nextjs"
import { createSandbox } from "@/lib/actions"
import { useRouter } from "next/navigation"
import { Loader2 } from "lucide-react"
import { Button } from "../ui/button"
type TOptions = "react" | "node" | "python" | "more";
type TOptions = "react" | "node" | "python" | "more"
const data: {
id: TOptions;
name: string;
icon: string;
description: string;
disabled: boolean;
id: TOptions
name: string
icon: string
description: string
disabled: boolean
}[] = [
{
id: "react",
@ -74,7 +74,7 @@ const data: {
description: "More coming soon, feel free to contribute on GitHub",
disabled: true,
},
];
]
const formSchema = z.object({
name: z
@ -86,20 +86,20 @@ const formSchema = z.object({
"Name must be alphanumeric and can contain underscores"
),
visibility: z.enum(["public", "private"]),
});
})
export default function NewProjectModal({
open,
setOpen,
}: {
open: boolean;
setOpen: (open: boolean) => void;
open: boolean
setOpen: (open: boolean) => void
}) {
const [selected, setSelected] = useState<TOptions>("react");
const [loading, setLoading] = useState(false);
const router = useRouter();
const [selected, setSelected] = useState<TOptions>("react")
const [loading, setLoading] = useState(false)
const router = useRouter()
const user = useUser();
const user = useUser()
const form = useForm<z.infer<typeof formSchema>>({
resolver: zodResolver(formSchema),
@ -107,23 +107,23 @@ export default function NewProjectModal({
name: "",
visibility: "public",
},
});
})
async function onSubmit(values: z.infer<typeof formSchema>) {
if (!user.isSignedIn) return;
if (!user.isSignedIn) return
const sandboxData = { type: selected, userId: user.user.id, ...values };
setLoading(true);
const sandboxData = { type: selected, userId: user.user.id, ...values }
setLoading(true)
const id = await createSandbox(sandboxData);
router.push(`/code/${id}`);
const id = await createSandbox(sandboxData)
router.push(`/code/${id}`)
}
return (
<Dialog
open={open}
onOpenChange={(open: boolean) => {
if (!loading) setOpen(open);
if (!loading) setOpen(open)
}}
>
<DialogContent>
@ -152,7 +152,7 @@ export default function NewProjectModal({
</div>
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)}>
<form autoComplete="off" onSubmit={form.handleSubmit(onSubmit)}>
<FormField
control={form.control}
name="name"
@ -191,6 +191,11 @@ export default function NewProjectModal({
<SelectItem value="private">Private</SelectItem>
</SelectContent>
</Select>
<FormDescription>
Note: All sandboxes cannot be seen by the public. Private
sandboxes cannot be accessed by shared users that you add,
while public sandboxes can.
</FormDescription>
<FormMessage />
</FormItem>
)}
@ -208,5 +213,5 @@ export default function NewProjectModal({
</Form>
</DialogContent>
</Dialog>
);
)
}