Skip to content

Commit

Permalink
feat+refactor(ui): Use single complete supabase provider + add user c…
Browse files Browse the repository at this point in the history
…ontext to nav elements
  • Loading branch information
daryllimyt committed Mar 9, 2024
1 parent e88ac34 commit feb161f
Show file tree
Hide file tree
Showing 10 changed files with 353 additions and 112 deletions.
11 changes: 5 additions & 6 deletions frontend/src/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import "@/styles/globals.css"

import { Metadata } from "next"
import SupabaseProvider from "@/providers/supabase"
import SupabaseListener from "@/providers/supabase-listener"
import { SessionContextProvider } from "@/providers/session"
import { WorkflowProvider } from "@/providers/workflow"
import { createClient } from "@/utils/supabase/server"

import { siteConfig } from "@/config/site"
Expand Down Expand Up @@ -39,10 +39,9 @@ export default async function RootLayout({ children }: RootLayoutProps) {
fontSans.className
)}
>
<SupabaseProvider session={session}>
<SupabaseListener serverAccessToken={session?.access_token} />
{children}
</SupabaseProvider>
<SessionContextProvider initialSession={session}>
<WorkflowProvider>{children}</WorkflowProvider>
</SessionContextProvider>
<Toaster />
</body>
</html>
Expand Down
19 changes: 8 additions & 11 deletions frontend/src/app/workflows/[id]/page.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Metadata } from "next"
import { cookies } from "next/headers"
import { DefaultQueryClientProvider } from "@/providers/query"
import { WorkflowProvider } from "@/providers/workflow"

import { Navbar } from "@/components/navbar"
import { Workspace } from "@/components/workspace"
Expand Down Expand Up @@ -31,16 +30,14 @@ export default function DashboardPage() {
return (
<>
<DefaultQueryClientProvider>
<WorkflowProvider>
<div className="flex h-screen flex-col">
<Navbar />
<Workspace
defaultLayout={defaultLayout}
defaultCollapsed={defaultCollapsed}
navCollapsedSize={4}
/>
</div>
</WorkflowProvider>
<div className="flex h-screen flex-col">
<Navbar />
<Workspace
defaultLayout={defaultLayout}
defaultCollapsed={defaultCollapsed}
navCollapsedSize={4}
/>
</div>
</DefaultQueryClientProvider>
</>
)
Expand Down
50 changes: 14 additions & 36 deletions frontend/src/app/workflows/page.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,26 @@
"use client"

import React, { useEffect } from "react"
import React, { useEffect, useState } from "react"
import Link from "next/link"
import { useRouter } from "next/navigation"
import { useSupabase } from "@/providers/supabase"
import { User } from "@supabase/supabase-js"
import { useSessionContext } from "@/providers/session"
import { Loader2 } from "lucide-react"

import { fetchWorkflows, WorkflowMetadata } from "@/lib/flow"
import { WorkflowMetadata } from "@/types/schemas"
import { fetchWorkflows } from "@/lib/flow"
import { cn } from "@/lib/utils"
import { Button } from "@/components/ui/button"
import NoSSR from "@/components/no-ssr"

export default function Page() {
return <WorkflowsPage suppressHydrationWarning />
return (
<NoSSR>
<WorkflowsPage suppressHydrationWarning />
</NoSSR>
)
}
function WorkflowsPage(props: React.HTMLAttributes<HTMLElement>) {
const { supabase, session } = useSupabase()
const { supabaseClient, session, isLoading } = useSessionContext()
if (!session) {
return (
<div
Expand All @@ -26,19 +31,14 @@ function WorkflowsPage(props: React.HTMLAttributes<HTMLElement>) {
</div>
)
}
const { user } = session
const router = useRouter()
const [userWorkflows, setUserWorkflows] = React.useState<WorkflowMetadata[]>(
[]
)
const [user, setUser] = React.useState<User | null>(null)
const [isLoading, setIsLoading] = React.useState(true)
const [error, setError] = React.useState<Error | null>(null)
const [userWorkflows, setUserWorkflows] = useState<WorkflowMetadata[]>([])

const signOut = async () => {
await supabase.auth.signOut()
await supabaseClient.auth.signOut()
router.push("/login")
router.refresh()
setUser(null)
}

useEffect(() => {
Expand All @@ -49,17 +49,6 @@ function WorkflowsPage(props: React.HTMLAttributes<HTMLElement>) {
}
}, [user])

useEffect(() => {
async function getUser() {
const {
data: { user },
} = await supabase.auth.getUser()
setUser(user)
setIsLoading(false)
}
getUser()
}, [])

if (isLoading || !user) {
return (
<div
Expand All @@ -71,17 +60,6 @@ function WorkflowsPage(props: React.HTMLAttributes<HTMLElement>) {
)
}

if (error) {
return (
<div
className="container flex h-full w-full items-center justify-center"
{...props}
>
<div>Error: {error.message}</div>
</div>
)
}

return (
userWorkflows.length > 0 && (
<div
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/components/forms/action.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,9 @@ export function ActionForm({
}

const { mutate } = useUpdateAction(actionId)

function onSubmit(values: actionFormSchemaType) {
mutate(values)
// TODO: Update the workflow switcher with the new action data
}

// Loading state to defend in a user friendly way
Expand Down
21 changes: 13 additions & 8 deletions frontend/src/components/navbar.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
"use client"

import { useEffect, useState } from "react"
import React, { useEffect, useState } from "react"
import Link from "next/link"
import { useParams, usePathname } from "next/navigation"
import axios from "axios"
Expand All @@ -9,14 +9,16 @@ import { BellRingIcon, WorkflowIcon } from "lucide-react"
import { Label } from "@/components/ui/label"
import { Switch } from "@/components/ui/switch"
import { Tabs, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Icons } from "@/components/icons"
import { UserNav } from "@/components/user-nav"
import WorkflowSwitcher from "@/components/workflow-switcher"

export function Navbar() {
const [enableWorkflow, setEnableWorkflow] = useState(false)
interface NavbarProps extends React.HTMLAttributes<HTMLDivElement> {}
export function Navbar(props: NavbarProps) {
const params = useParams()
const workflowId = params["id"]
const [workflowId, setWorkflowId] = useState<string>(params["id"] as string)
const pathname = usePathname()
const [enableWorkflow, setEnableWorkflow] = useState(false)

useEffect(() => {
const updateWorkflowStatus = async () => {
Expand All @@ -42,16 +44,19 @@ export function Navbar() {
}

updateWorkflowStatus()
}, [enableWorkflow, workflowId])
}, [enableWorkflow])

return (
<div className="border-b">
<div className="border-b" {...props}>
<div className="flex h-16 items-center px-4">
<div className="flex space-x-8">
<div className="flex items-center space-x-8">
{/* TODO: Ensure that workflow switcher doesn't make an API call to update
workflows when page is switched between workflow view and cases view
*/}
<WorkflowSwitcher />
<Link href="/workflows">
<Icons.logo className="ml-4 h-5 w-5" />
</Link>
<WorkflowSwitcher defaultValue={workflowId} />
<Tabs value={pathname.endsWith("/cases") ? "cases" : "workflow"}>
<TabsList className="grid w-full grid-cols-2">
<Link
Expand Down
13 changes: 13 additions & 0 deletions frontend/src/components/user-avatar.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"

export default function UserAvatar() {
return (
<Avatar>
<AvatarImage
src="https://media.licdn.com/dms/image/C5103AQEXlYZeTKuwyQ/profile-displayphoto-shrink_200_200/0/1582770649112?e=1715212800&v=beta&t=wqVZfVV4YwedybQFzKazeWmlQslMQ11t_NGMCqwpN-k"
alt="@daryllimyt"
/>
<AvatarFallback>CN</AvatarFallback>
</Avatar>
)
}
35 changes: 20 additions & 15 deletions frontend/src/components/user-nav.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { KeyRound, LogOut, Settings, UserRound, UsersRound } from "lucide-react"
import { useSessionContext, useUser } from "@/providers/session"
import { KeyRound, LogOut, Settings, UsersRound } from "lucide-react"

import { Avatar, AvatarFallback, AvatarImage } from "@/components/ui/avatar"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
Expand All @@ -11,46 +11,51 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import UserAvatar from "@/components/user-avatar"

const userDefaults = {
name: "Test User",
email: "[email protected]",
}
export function UserNav() {
const { signOut } = useSessionContext()
const user = useUser()
console.log("user", user)
return (
<DropdownMenu>
<DropdownMenuTrigger asChild>
<Button variant="ghost" className="relative h-8 w-8 rounded-full">
<Avatar className="h-8 w-8">
<AvatarImage src="" alt="" />
<AvatarFallback>
<UserRound className="h-5 w-5" />
</AvatarFallback>
</Avatar>
<UserAvatar />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent className="w-56 p-2" align="end" forceMount>
<DropdownMenuLabel className="font-normal">
<div className="flex flex-col space-y-1">
<p className="text-sm font-medium leading-none">shadcn</p>
<p className="text-sm font-medium leading-none">
{user?.user_metadata.name ?? userDefaults.name}
</p>
<p className="text-xs leading-none text-muted-foreground">
[email protected]
{user?.email ?? userDefaults.email}
</p>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuGroup>
<DropdownMenuItem>
<DropdownMenuItem className="hover:cursor-pointer">
<Settings className="mr-2 h-4 w-4" />
<span>Settings</span>
Settings
</DropdownMenuItem>
<DropdownMenuItem>
<DropdownMenuItem className="hover:cursor-pointer">
<KeyRound className="mr-2 h-4 w-4" />
<span>Credentials</span>
</DropdownMenuItem>
<DropdownMenuItem>
<DropdownMenuItem className="hover:cursor-pointer">
<UsersRound className="mr-2 h-4 w-4" />
<span>Manage users</span>
</DropdownMenuItem>
</DropdownMenuGroup>
<DropdownMenuSeparator />
<DropdownMenuItem>
<DropdownMenuItem className="hover:cursor-pointer" onClick={signOut}>
<LogOut className="mr-2 h-4 w-4" />
<span>Logout</span>
</DropdownMenuItem>
Expand Down
Loading

0 comments on commit feb161f

Please sign in to comment.