Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added developer panel #497

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/web/src/app/(dashboard)/dashboard/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@ import { Toaster } from '@/components/ui/toaster'

export default async function Layout({ children }) {
return (
<div className="h-full w-full">
<main className="w-full h-full flex flex-col">
<div className="h-full w-full flex flex-col">
<main className="w-full flex flex-col flex-1">
{children}
<Toaster />
</main>
Expand Down
66 changes: 52 additions & 14 deletions apps/web/src/app/(dashboard)/dashboard/page.tsx
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
'use client'

import { Suspense, useEffect, useState } from 'react'
import { useLocalStorage } from 'usehooks-ts'

import {
BarChart,
CreditCard,
FileText,
Key,
LucideIcon,
PackageIcon,
PencilRuler,
Settings,
Users,
} from 'lucide-react'
Expand All @@ -23,6 +26,7 @@ import { useRouter, useSearchParams } from 'next/navigation'
import { PersonalContent } from '@/components/Dashboard/Personal'
import { TemplatesContent } from '@/components/Dashboard/Templates'
import { SandboxesContent } from '@/components/Dashboard/Sandboxes'
import { DeveloperContent } from '@/components/Dashboard/Developer'

function redirectToCurrentURL() {
const url = typeof window !== 'undefined' ? window.location.href : undefined
Expand All @@ -43,6 +47,7 @@ const menuLabels = [
'usage',
'billing',
'team',
'developer',
] as const
type MenuLabel = (typeof menuLabels)[number]

Expand All @@ -65,7 +70,7 @@ export default function Page() {

if (user) {
return (
<div className="flex min-h-screen flex-col md:flex-row pt-16 md:pt-32 px-2 md:px-32">
<div className="flex flex-col md:flex-row pt-16 md:pt-32 px-2 md:px-32">
<Suspense>
<Dashboard user={user} />
</Suspense>
Expand All @@ -82,6 +87,15 @@ const Dashboard = ({ user }) => {
const [teams, setTeams] = useState<Team[]>([])
const [currentTeam, setCurrentTeam] = useState<Team | null>(null)

const apiUrlState = useLocalStorage(
'apiUrl',
process.env.NEXT_PUBLIC_API_URL || ''
)
const billingUrlState = useLocalStorage(
'billingUrl',
process.env.NEXT_PUBLIC_BILLING_API_URL || ''
)

const initialTab =
tab && menuLabels.includes(tab as MenuLabel)
? (tab as MenuLabel)
Expand Down Expand Up @@ -140,7 +154,7 @@ const Dashboard = ({ user }) => {
setCurrentTeam={setCurrentTeam}
setTeams={setTeams}
/>
<div className="flex-1 md:pl-10">
<div className="flex-1 md:pl-10 pb-16">
<h2 className="text-2xl mb-2 font-bold">
{selectedItem[0].toUpperCase() + selectedItem.slice(1)}
</h2>
Expand All @@ -152,6 +166,8 @@ const Dashboard = ({ user }) => {
teams={teams}
setTeams={setTeams}
setCurrentTeam={setCurrentTeam}
apiUrlState={apiUrlState}
billingUrlState={billingUrlState}
/>
</div>
</>
Expand Down Expand Up @@ -199,6 +215,7 @@ const iconMap: { [key in MenuLabel]: LucideIcon } = {
team: Users,
templates: FileText,
sandboxes: PackageIcon,
developer: PencilRuler,
}

const MenuItem = ({
Expand All @@ -213,18 +230,16 @@ const MenuItem = ({
onClick: () => void
}) => (
<div
className={`flex w-fit md:w-full hover:bg-[#995100] hover:cursor-pointer rounded-lg items-center p-2 space-x-2 ${
selected ? 'bg-[#995100]' : ''
}`}
className={`flex w-fit md:w-full hover:bg-[#995100] hover:cursor-pointer rounded-lg items-center p-2 space-x-2 ${selected ? 'bg-[#995100]' : ''
}`}
onClick={onClick}
>
<Icon width={20} height={20} />
<p
className={`${
!label || !window.matchMedia('(min-width: 768)').matches
className={`${!label || !window.matchMedia('(min-width: 768)').matches
? 'sr-only sm:not-sr-only'
: ''
}`}
}`}
>
{label[0].toUpperCase() + label.slice(1)}
</p>
Expand All @@ -238,27 +253,43 @@ function MainContent({
teams,
setTeams,
setCurrentTeam,
apiUrlState,
billingUrlState,
}: {
selectedItem: MenuLabel
user: E2BUser
team: Team
teams: Team[]
setTeams: (teams: Team[]) => void
setCurrentTeam: (team: Team) => void
apiUrlState: [string, (value: string) => void]
billingUrlState: [string, (value: string) => void]
}) {
switch (selectedItem) {
case 'personal':
return <PersonalContent user={user} />
return <PersonalContent user={user} billingUrl={billingUrlState[0]} />
case 'keys':
return <KeysContent currentTeam={team} user={user} />
return (
<KeysContent
currentTeam={team}
user={user}
billingUrl={billingUrlState[0]}
/>
)
case 'sandboxes':
return <SandboxesContent team={team} />
return <SandboxesContent team={team} apiUrl={apiUrlState[0]} />
case 'templates':
return <TemplatesContent user={user} teamId={team.id} />
return (
<TemplatesContent
user={user}
teamId={team.id}
apiUrl={apiUrlState[0]}
/>
)
case 'usage':
return <UsageContent team={team} />
return <UsageContent team={team} billingUrl={billingUrlState[0]} />
case 'billing':
return <BillingContent team={team} />
return <BillingContent team={team} billingUrl={billingUrlState[0]} />
case 'team':
return (
<TeamContent
Expand All @@ -267,6 +298,13 @@ function MainContent({
teams={teams}
setTeams={setTeams}
setCurrentTeam={setCurrentTeam}
billingUrl={billingUrlState[0]}
/>
)
case 'developer':
return (
<DeveloperContent
apiUrlState={apiUrlState}
/>
)
default:
Expand Down
105 changes: 65 additions & 40 deletions apps/web/src/components/Dashboard/AccountSelector.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import {
} from '@/components/ui/dropdown-menu'
import { ChevronRight, PlusCircle } from 'lucide-react'
import { toast } from '../ui/use-toast'
import {
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
Expand All @@ -22,13 +22,18 @@ import { Button } from '../Button'

const createTeamUrl = `${process.env.NEXT_PUBLIC_BILLING_API_URL}/teams`

export const AccountSelector = ({ teams, user, currentTeam, setCurrentTeam, setTeams }) => {

export const AccountSelector = ({
teams,
user,
currentTeam,
setCurrentTeam,
setTeams,
}) => {
const [isDialogOpen, setIsDialogOpen] = useState(false)
const [teamName, setTeamName] = useState('')
const closeDialog = () => setIsDialogOpen(false)

const createNewTeam = async() => {
const createNewTeam = async () => {
const res = await fetch(createTeamUrl, {
method: 'POST',
headers: {
Expand All @@ -54,52 +59,72 @@ export const AccountSelector = ({ teams, user, currentTeam, setCurrentTeam, setT
toast({
title: `Team ${team.name} created`,
})

setTeams([...teams, team])
setCurrentTeam(team)
setTeamName('')
}
return(

return (
<>
<DropdownMenu>
<DropdownMenuTrigger
className='dropdown-trigger group outline-none flex w-full items-center justify-between rounded-lg p-2 mb-6 hover:bg-zinc-800 hover:cursor-pointer'
>
<div className='flex items-start flex-col'>
<p className='text-sm'>Current team</p>
<h3 className='font-bold text-left'>{currentTeam.name}</h3>
</div>
<ChevronRight className='transform transition-transform duration-300 group-hover:rotate-90' />
</DropdownMenuTrigger>
<DropdownMenuContent className='flex flex-col w-48 bg-zinc-900 border border-white/30'>
{teams?.map((team: any) => (
<DropdownMenuItem key={team.id} onClick={() => setCurrentTeam(team)}>
{team.name}
<DropdownMenuTrigger className="dropdown-trigger group outline-none flex w-full items-center justify-between rounded-lg p-2 mb-6 hover:bg-zinc-800 hover:cursor-pointer">
<div className="flex items-start flex-col">
<p className="text-sm">Current team</p>
<h3 className="font-bold text-left">{currentTeam.name}</h3>
</div>
<ChevronRight className="transform transition-transform duration-300 group-hover:rotate-90" />
</DropdownMenuTrigger>
<DropdownMenuContent className="flex flex-col w-48 bg-zinc-900 border border-white/30">
{teams?.map((team: any) => (
<DropdownMenuItem
key={team.id}
onClick={() => setCurrentTeam(team)}
>
{team.name}
</DropdownMenuItem>
))}
<DropdownMenuSeparator />
<DropdownMenuItem
className="flex items-center space-x-1"
onClick={() => setIsDialogOpen(true)}
>
<PlusCircle width={15} height={15} />
<span>Create Team</span>
</DropdownMenuItem>
))}
<DropdownMenuSeparator />
<DropdownMenuItem className='flex items-center space-x-1'>
<PlusCircle width={15} height={15} />
<p onClick={() => setIsDialogOpen(true)}>Create Team</p>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenuContent>
</DropdownMenu>

<AlertDialog open={isDialogOpen} onOpenChange={setIsDialogOpen}>
<AlertDialogTrigger asChild>
<Button variant="outline" style={{ display: 'none' }}>Show Dialog</Button>
</AlertDialogTrigger>
<AlertDialogContent className="bg-inherit text-white border-black">
<AlertDialogHeader>
<AlertDialogTitle>Give your team a name</AlertDialogTitle>
<input className='border border-white/10 text-sm focus:outline-none outline-none rounded-md p-2' value={teamName} onChange={(e) => setTeamName(e.target.value)} />
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel className='border-white/10' onClick={closeDialog}>Cancel</AlertDialogCancel>
<AlertDialogAction className='bg-[#995100] text-white hover:bg-[#995100]' onClick={() => createNewTeam()}>Create</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
<AlertDialogTrigger asChild>
<Button variant="outline" style={{ display: 'none' }}>
Show Dialog
</Button>
</AlertDialogTrigger>
<AlertDialogContent className="bg-inherit text-white border-black">
<AlertDialogHeader>
<AlertDialogTitle>Give your team a name</AlertDialogTitle>
<input
className="border border-white/10 text-sm focus:outline-none outline-none rounded-md p-2"
value={teamName}
onChange={(e) => setTeamName(e.target.value)}
/>
</AlertDialogHeader>
<AlertDialogFooter>
<AlertDialogCancel
className="border-white/10"
onClick={closeDialog}
>
Cancel
</AlertDialogCancel>
<AlertDialogAction
className="bg-[#995100] text-white hover:bg-[#995100]"
onClick={() => createNewTeam()}
>
Create
</AlertDialogAction>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
</>
)
Expand Down
Loading
Loading