Skip to content

Commit

Permalink
moving outerbase router to dedicated outerbase route
Browse files Browse the repository at this point in the history
  • Loading branch information
invisal committed Feb 2, 2025
1 parent fcfc443 commit fafcf7e
Show file tree
Hide file tree
Showing 26 changed files with 379 additions and 163 deletions.
93 changes: 93 additions & 0 deletions src/app/(outerbase)/navigation.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { getDatabaseIcon } from "@/components/resource-card/utils";
import { Button, buttonVariants } from "@/components/ui/button";
import {
Popover,
PopoverContent,
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { useParams, useRouter } from "next/navigation";
import { useMemo, useState } from "react";
import { useWorkspaces } from "./workspace-provider";

function WorkspaceSelector() {
const router = useRouter();
const { workspaces } = useWorkspaces();
const { workspaceId } = useParams<{ workspaceId: string }>();
const [selectedWorkspaceId, setSelectedWorkspaceId] = useState(workspaceId);

const selectedWorkspace = workspaces.find(
(w) => w.id === selectedWorkspaceId || w.short_name === selectedWorkspaceId
);

const bases = useMemo(() => {
const currentBases = [...(selectedWorkspace?.bases ?? [])];
currentBases.sort((a, b) => a.name.localeCompare(b.name));
return currentBases;
}, [selectedWorkspace]);

return (
<div className="flex h-[400px] w-[500px]">
<div className="flex h-full w-1/2 flex-col gap-0.5 border-r p-1">
<label className="text-muted-foreground mt-1 px-3 py-1 text-xs font-bold">
WORKSPACES
</label>
{workspaces.map((workspace) => (
<div
onClick={() => router.push(`/w/${workspace.short_name}`)}
key={workspace.id}
onMouseEnter={() => setSelectedWorkspaceId(workspace.short_name)}
className={cn(
buttonVariants({ variant: "ghost", size: "sm" }),
"cursor-pointer justify-start py-0.5"
)}
>
{workspace.name}
</div>
))}
</div>
<div className="flex h-full w-1/2 flex-col gap-0.5 overflow-y-auto p-1 text-sm">
<label className="text-muted-foreground mt-1 px-3 py-1 text-xs font-bold">
BASES
</label>
{bases.map((base) => {
const IconComponent = getDatabaseIcon(base.sources[0]?.type);

return (
<div
onClick={() =>
router.push(`/w/${selectedWorkspaceId}/${base.short_name}`, {})
}
key={base.id}
className={cn(
buttonVariants({
variant: "ghost",
size: "sm",
}),
"cursor-pointer justify-start p-2"
)}
>
<IconComponent className="mr-2 h-4 w-4" />
{base.name}
</div>
);
})}
</div>
</div>
);
}

export function NavigationBar() {
return (
<div className="p-1">
<Popover open>
<PopoverTrigger asChild>
<Button>Workspace</Button>
</PopoverTrigger>
<PopoverContent className="h-[400px] w-[500px] p-0">
<WorkspaceSelector />
</PopoverContent>
</Popover>
</div>
);
}
56 changes: 56 additions & 0 deletions src/app/(outerbase)/session-provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
"use client";
import { useRouter } from "next/navigation";
import { createContext, PropsWithChildren, useContext } from "react";
import useSWR from "swr";
import { getOuterbaseSession } from "../../outerbase-cloud/api";
import {
OuterbaseAPISession,
OuterbaseAPIUser,
} from "../../outerbase-cloud/api-type";

interface OuterebaseSessionContextProps {
session: OuterbaseAPISession;
user: OuterbaseAPIUser;
}

const OuterbaseSessionContext = createContext<{
session: OuterbaseAPISession;
user: OuterbaseAPIUser;
}>({} as OuterebaseSessionContextProps);

export function useSession() {
return useContext(OuterbaseSessionContext);
}

export function OuterbaseSessionProvider({ children }: PropsWithChildren) {
const router = useRouter();

const { data, isLoading } = useSWR(
"session",
() => {
return getOuterbaseSession();
},
{
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false,
}
);

if (isLoading) {
return <div>Session Loading...</div>;
}

if (!data?.session || !data?.user) {
router.push("/signin");
return <div>Redirecting...</div>;
}

return (
<OuterbaseSessionContext.Provider
value={{ session: data?.session, user: data?.user }}
>
{children}
</OuterbaseSessionContext.Provider>
);
}
17 changes: 17 additions & 0 deletions src/app/(outerbase)/w/[workspaceId]/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { OuterbaseSessionProvider } from "@/app/(outerbase)/session-provider";
import ThemeLayout from "../../../(theme)/theme_layout";
import { WorkspaceProvider } from "../../workspace-provider";

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<ThemeLayout>
<OuterbaseSessionProvider>
<WorkspaceProvider>{children}</WorkspaceProvider>
</OuterbaseSessionProvider>
</ThemeLayout>
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,46 +9,25 @@ import {
getDatabaseVisual,
} from "@/components/resource-card/utils";
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
import {
getOuterbaseDashboardList,
getOuterbaseWorkspace,
} from "@/outerbase-cloud/api";
import {
CalendarDots,
SortAscending,
SortDescending,
} from "@phosphor-icons/react";
import useSWR from "swr";

export default function WorkspaceListPageClient({
workspaceId,
}: {
workspaceId: string;
}) {
const { data, isLoading } = useSWR(`workspace-${workspaceId}`, () => {
const fetching = async () => {
const [workspaces, boards] = await Promise.all([
getOuterbaseWorkspace(),
getOuterbaseDashboardList(workspaceId),
]);

return {
bases:
workspaces.items.find((w) => w.short_name === workspaceId)?.bases ??
[],
boards: (boards.items ?? []).filter((b) => b.base_id === null),
};
};
import { useParams } from "next/navigation";
import { NavigationBar } from "../../navigation";
import { useWorkspaces } from "../../workspace-provider";

return fetching();
});
export default function WorkspaceListPageClient() {
const { workspaces } = useWorkspaces();
const { workspaceId } = useParams<{ workspaceId: string }>();

// const boards = data?.boards ?? [];
const bases = data?.bases ?? [];

if (isLoading) {
return <div>Loading...</div>;
}
const bases =
workspaces.find(
(workspace) =>
workspace.short_name === workspaceId || workspace.id === workspaceId
)?.bases ?? [];

return (
<div className="min-h-screen bg-neutral-50 dark:bg-neutral-950">
Expand All @@ -66,6 +45,8 @@ export default function WorkspaceListPageClient({
</div>
<h1>Base</h1> */}
<NavigationBar />

<div className="container mx-auto p-4">
<div className="mb-8">
<Toolbar>
Expand Down
11 changes: 11 additions & 0 deletions src/app/(outerbase)/w/[workspaceId]/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
"use client";
import ClientOnly from "@/components/client-only";
import WorkspaceListPageClient from "./page-client";

export default function WorkspaceListPage() {
return (
<ClientOnly>
<WorkspaceListPageClient />
</ClientOnly>
);
}
36 changes: 36 additions & 0 deletions src/app/(outerbase)/workspace-provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"use client";
import { getOuterbaseWorkspace } from "@/outerbase-cloud/api";
import { OuterbaseAPIWorkspace } from "@/outerbase-cloud/api-type";
import { createContext, PropsWithChildren, useContext } from "react";
import useSWR from "swr";

const WorkspaceContext = createContext<{
workspaces: OuterbaseAPIWorkspace[];
loading: boolean;
}>({ workspaces: [], loading: true });

export function useWorkspaces() {
return useContext(WorkspaceContext);
}

export function WorkspaceProvider({ children }: PropsWithChildren) {
const { data, isLoading } = useSWR(
"workspaces",
() => {
return getOuterbaseWorkspace();
},
{
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false,
}
);

return (
<WorkspaceContext.Provider
value={{ workspaces: data?.items || [], loading: isLoading }}
>
{children}
</WorkspaceContext.Provider>
);
}
14 changes: 0 additions & 14 deletions src/app/(theme)/w/[workspaceId]/layout.tsx

This file was deleted.

16 changes: 0 additions & 16 deletions src/app/(theme)/w/[workspaceId]/page.tsx

This file was deleted.

19 changes: 19 additions & 0 deletions src/components/board/board-provider.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { BoardSourceDriver } from "@/drivers/board-source/base-source";
import { createContext, PropsWithChildren } from "react";

interface BoardContextProps {
sources?: BoardSourceDriver;
}

const BoardContext = createContext<BoardContextProps>({});

export function BoardProvider({
children,
sources,
}: PropsWithChildren<BoardContextProps>) {
return (
<BoardContext.Provider value={{ sources }}>
{children}
</BoardContext.Provider>
);
}
Loading

0 comments on commit fafcf7e

Please sign in to comment.