Skip to content
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
Binary file added public/extension/chart-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/extension/chart-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/extension/definition-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/extension/definition-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/extension/term-dark.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added public/extension/term-light.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 21 additions & 6 deletions src/app/(outerbase)/navigation.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { OuterbaseIcon } from "@/components/icons/outerbase";
import { getDatabaseIcon } from "@/components/resource-card/utils";
import { Button, buttonVariants } from "@/components/ui/button";
import {
Expand All @@ -6,13 +7,14 @@ import {
PopoverTrigger,
} from "@/components/ui/popover";
import { cn } from "@/lib/utils";
import { CaretUpDown } from "@phosphor-icons/react";
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 { workspaces, currentWorkspace } = useWorkspaces();
const { workspaceId } = useParams<{ workspaceId: string }>();
const [selectedWorkspaceId, setSelectedWorkspaceId] = useState(workspaceId);

Expand All @@ -38,7 +40,11 @@ function WorkspaceSelector() {
key={workspace.id}
onMouseEnter={() => setSelectedWorkspaceId(workspace.short_name)}
className={cn(
buttonVariants({ variant: "ghost", size: "sm" }),
buttonVariants({
variant:
currentWorkspace?.id === workspace.id ? "secondary" : "ghost",
size: "sm",
}),
"cursor-pointer justify-start py-0.5"
)}
>
Expand Down Expand Up @@ -78,13 +84,22 @@ function WorkspaceSelector() {
}

export function NavigationBar() {
const { currentWorkspace } = useWorkspaces();

if (!currentWorkspace) {
return null;
}

return (
<div className="p-1">
<Popover open>
<div className="flex h-14 items-center gap-2 px-2">
<OuterbaseIcon className="h-8 w-8" />
<Popover>
<PopoverTrigger asChild>
<Button>Workspace</Button>
<Button variant={"ghost"}>
{currentWorkspace?.name} <CaretUpDown className="ml-2" />
</Button>
</PopoverTrigger>
<PopoverContent className="h-[400px] w-[500px] p-0">
<PopoverContent className="h-[400px] w-[500px] p-0" align="start">
<WorkspaceSelector />
</PopoverContent>
</Popover>
Expand Down
5 changes: 3 additions & 2 deletions src/app/(outerbase)/session-provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,11 @@ export function useSession() {
export function OuterbaseSessionProvider({ children }: PropsWithChildren) {
const router = useRouter();
const pathname = usePathname();
const token = localStorage.getItem("ob-token");
const token =
typeof window !== "undefined" ? localStorage.getItem("ob-token") : "";

const { data, isLoading } = useSWR(
token ? "session-" + localStorage.getItem("ob-token") : undefined,
token ? "session-" + token : undefined,
() => {
return getOuterbaseSession();
},
Expand Down
9 changes: 6 additions & 3 deletions src/app/(outerbase)/w/[workspaceId]/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { OuterbaseSessionProvider } from "@/app/(outerbase)/session-provider";
import ClientOnly from "@/components/client-only";
import ThemeLayout from "../../../(theme)/theme_layout";
import { WorkspaceProvider } from "../../workspace-provider";

Expand All @@ -9,9 +10,11 @@ export default function RootLayout({
}) {
return (
<ThemeLayout>
<OuterbaseSessionProvider>
<WorkspaceProvider>{children}</WorkspaceProvider>
</OuterbaseSessionProvider>
<ClientOnly>
<OuterbaseSessionProvider>
<WorkspaceProvider>{children}</WorkspaceProvider>
</OuterbaseSessionProvider>
</ClientOnly>
</ThemeLayout>
);
}
51 changes: 36 additions & 15 deletions src/app/(outerbase)/w/[workspaceId]/page-client.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,21 +8,36 @@ import {
getDatabaseIcon,
getDatabaseVisual,
} from "@/components/resource-card/utils";
import { BoardVisual } from "@/components/resource-card/visual";
import { DropdownMenuItem } from "@/components/ui/dropdown-menu";
import { getOuterbaseDashboardList } from "@/outerbase-cloud/api";
import {
CalendarDots,
ChartBar,
SortAscending,
SortDescending,
} from "@phosphor-icons/react";
import { useParams } from "next/navigation";
import useSWR from "swr";
import { NavigationBar } from "../../navigation";
import { useWorkspaces } from "../../workspace-provider";

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

// const boards = data?.boards ?? [];
const { data: boards } = useSWR(
`/workspace/${workspaceId}/boards`,
() => {
return getOuterbaseDashboardList(workspaceId);
},
{
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false,
}
);

const bases =
workspaces.find(
(workspace) =>
Expand All @@ -31,20 +46,6 @@ export default function WorkspaceListPageClient() {

return (
<div className="min-h-screen bg-neutral-50 dark:bg-neutral-950">
{/* <h1>Board</h1>
<div className="flex flex-wrap gap-4 p-4">
{boards.map((board) => (
<Link
key={board.id}
className="border p-4"
href={`/w/${workspaceId}/board/${board.id}`}
>
{board.name}
</Link>
))}
</div>

<h1>Base</h1> */}
<NavigationBar />

<div className="container mx-auto p-4">
Expand Down Expand Up @@ -75,6 +76,26 @@ export default function WorkspaceListPageClient() {
</Toolbar>
</div>

<h1 className="my-4">Board</h1>
<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-4">
{(boards?.items ?? [])
.filter((board) => board.base_id === null)
.map((board) => (
<ResourceCard
key={board.id}
className="w-full"
color="default"
icon={ChartBar}
title={board.name}
subtitle={"Board"}
visual={BoardVisual}
href={`/w/${workspaceId}/board/${board.id}`}
/>
))}
</div>

<h1 className="my-4">Base</h1>

<div className="grid grid-cols-1 gap-6 md:grid-cols-2 lg:grid-cols-4">
{bases.map((base) => (
<ResourceCard
Expand Down
24 changes: 22 additions & 2 deletions src/app/(outerbase)/workspace-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
"use client";
import { getOuterbaseWorkspace } from "@/outerbase-cloud/api";
import { OuterbaseAPIWorkspace } from "@/outerbase-cloud/api-type";
import { createContext, PropsWithChildren, useContext } from "react";
import { useParams } from "next/navigation";
import { createContext, PropsWithChildren, useContext, useMemo } from "react";
import useSWR from "swr";

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

Expand All @@ -26,9 +28,27 @@ export function WorkspaceProvider({ children }: PropsWithChildren) {
}
);

const { workspaceId } = useParams<{ workspaceId?: string }>();

const currentWorkspace = useMemo(() => {
if (!workspaceId) return;
if (!data) return;

return data?.items.find(
(workspace) =>
workspace.short_name === workspaceId || workspace.id === workspaceId
);
}, [workspaceId, data]);

console.log(data, workspaceId, currentWorkspace);

return (
<WorkspaceContext.Provider
value={{ workspaces: data?.items || [], loading: isLoading }}
value={{
workspaces: data?.items || [],
loading: isLoading,
currentWorkspace,
}}
>
{children}
</WorkspaceContext.Provider>
Expand Down
38 changes: 24 additions & 14 deletions src/components/gui/sql-editor/index.tsx
Original file line number Diff line number Diff line change
@@ -1,28 +1,33 @@
import CodeMirror, {
EditorView,
Extension,
ReactCodeMirrorRef,
} from "@uiw/react-codemirror";
import { indentUnit, LanguageSupport } from "@codemirror/language";
import {
acceptCompletion,
completionStatus,
startCompletion,
} from "@codemirror/autocomplete";
import { sql, SQLNamespace, MySQL as MySQLDialect } from "@codemirror/lang-sql";
import {
MySQL as MySQLDialect,
PostgreSQL as PostgresDialect,
sql,
SQLNamespace,
} from "@codemirror/lang-sql";
import { indentUnit, LanguageSupport } from "@codemirror/language";
import CodeMirror, {
EditorView,
Extension,
ReactCodeMirrorRef,
} from "@uiw/react-codemirror";
import { forwardRef, KeyboardEventHandler, useMemo } from "react";

import { SupportedDialect } from "@/drivers/base-driver";
import sqliteFunctionList from "@/drivers/sqlite/function-tooltip.json";
import { sqliteDialect } from "@/drivers/sqlite/sqlite-dialect";
import { KEY_BINDING } from "@/lib/key-matcher";
import { defaultKeymap, insertTab } from "@codemirror/commands";
import { keymap } from "@codemirror/view";
import { KEY_BINDING } from "@/lib/key-matcher";
import useCodeEditorTheme from "./use-editor-theme";
import createSQLTableNameHighlightPlugin from "./sql-tablename-highlight";
import { sqliteDialect } from "@/drivers/sqlite/sqlite-dialect";
import { functionTooltip } from "./function-tooltips";
import sqliteFunctionList from "@/drivers/sqlite/function-tooltip.json";
import { toast } from "sonner";
import { functionTooltip } from "./function-tooltips";
import createSQLTableNameHighlightPlugin from "./sql-tablename-highlight";
import SqlStatementHighlightPlugin from "./statement-highlight";
import { SupportedDialect } from "@/drivers/base-driver";
import useCodeEditorTheme from "./use-editor-theme";

interface SqlEditorProps {
value: string;
Expand Down Expand Up @@ -135,6 +140,11 @@ const SqlEditor = forwardRef<ReactCodeMirrorRef, SqlEditorProps>(
schema,
});
tooltipExtension = functionTooltip(sqliteFunctionList);
} else if (dialect === "postgres") {
sqlDialect = sql({
dialect: PostgresDialect,
schema,
});
} else {
sqlDialect = sql({
dialect: MySQLDialect,
Expand Down
11 changes: 11 additions & 0 deletions src/components/icons/outerbase.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
export function OuterbaseIcon(props: { className?: string }) {
return (
<svg
fill="currentColor"
viewBox="75 75 350 350"
className={props.className}
>
<path d="M249.51,146.58c-58.7,0-106.45,49.37-106.45,110.04c0,60.68,47.76,110.04,106.45,110.04 c58.7,0,106.46-49.37,106.46-110.04C355.97,195.95,308.21,146.58,249.51,146.58z M289.08,332.41l-0.02,0.04l-0.51,0.65 c-5.55,7.06-12.37,9.35-17.11,10.02c-1.23,0.17-2.5,0.26-3.78,0.26c-12.94,0-25.96-9.09-37.67-26.29 c-9.56-14.05-17.84-32.77-23.32-52.71c-9.78-35.61-8.67-68.08,2.83-82.74c5.56-7.07,12.37-9.35,17.11-10.02 c13.46-1.88,27.16,6.2,39.64,23.41c10.29,14.19,19.22,33.83,25.12,55.32C301,285.35,300.08,317.46,289.08,332.41z"></path>
</svg>
);
}
7 changes: 6 additions & 1 deletion src/components/sidebar-menu.tsx
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { cn } from "@/lib/utils";
import Link from "next/link";

interface SidebarMenuItemProps {
Expand All @@ -17,6 +18,7 @@ export function SidebarMenuItem({
onClick,
icon: IconComponent,
href,
selected,
}: SidebarMenuItemProps) {
const className =
"flex p-2 pl-4 text-xs hover:cursor-pointer hover:bg-secondary";
Expand Down Expand Up @@ -49,7 +51,10 @@ export function SidebarMenuItem({
}

return (
<button className={className} onClick={onClick}>
<button
className={cn(className, selected ? "bg-selected" : "")}
onClick={onClick}
>
{body}
</button>
);
Expand Down
Loading