Skip to content

Commit

Permalink
Added developer panel (#497)
Browse files Browse the repository at this point in the history
- Click on team dropdown > Developer
- Setting alternative API URL
- Setting alternative Billing URL
- Resetting the above to defaults (provided by env variable)
  • Loading branch information
mishushakov authored Dec 6, 2024
2 parents e8fa4be + 7360cfd commit 4a6e884
Show file tree
Hide file tree
Showing 13 changed files with 496 additions and 292 deletions.
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

0 comments on commit 4a6e884

Please sign in to comment.