diff --git a/src/app/client/page-client.tsx b/src/app/client/page-client.tsx
index f8e8f6bc..ecbaadbb 100644
--- a/src/app/client/page-client.tsx
+++ b/src/app/client/page-client.tsx
@@ -10,5 +10,5 @@ export default function ClientPageBody() {
return new DatabaseDriver(config.url, config.token as string);
}, []);
- return ;
+ return ;
}
diff --git a/src/app/client/r/page-client.tsx b/src/app/client/r/page-client.tsx
index 2cf995f7..6fd62679 100644
--- a/src/app/client/r/page-client.tsx
+++ b/src/app/client/r/page-client.tsx
@@ -1,5 +1,6 @@
"use client";
+import { SavedConnectionLabel } from "@/app/connect/saved-connection-storage";
import MainScreen from "@/components/main-connection";
import RemoteDriver from "@/drivers/remote-driver";
import { useSearchParams } from "next/navigation";
@@ -8,9 +9,11 @@ import { useMemo } from "react";
export default function ClientPageBody({
token,
name,
+ color,
}: Readonly<{
token: string;
name: string;
+ color: SavedConnectionLabel;
}>) {
const params = useSearchParams();
@@ -24,5 +27,5 @@ export default function ClientPageBody({
return
Something wrong
;
}
- return ;
+ return ;
}
diff --git a/src/app/client/r/page.tsx b/src/app/client/r/page.tsx
index 6e86ece2..38ab1950 100644
--- a/src/app/client/r/page.tsx
+++ b/src/app/client/r/page.tsx
@@ -1,3 +1,4 @@
+import { SavedConnectionLabel } from "@/app/connect/saved-connection-storage";
import { db } from "@/db";
import { database } from "@/db/schema";
import { getSessionFromCookie } from "@/lib/auth";
@@ -28,5 +29,11 @@ export default async function SessionPage({
return Not found
;
}
- return ;
+ return (
+
+ );
}
diff --git a/src/app/client/s/page-client.tsx b/src/app/client/s/page-client.tsx
index 4241b4c6..bd46a101 100644
--- a/src/app/client/s/page-client.tsx
+++ b/src/app/client/s/page-client.tsx
@@ -8,20 +8,22 @@ import { useMemo } from "react";
export default function ClientPageBody() {
const params = useSearchParams();
-
- const driver = useMemo(() => {
+ const conn = useMemo(() => {
const connectionParams = params.get("p");
if (!connectionParams) return null;
const conn = SavedConnectionLocalStorage.get(connectionParams);
- if (!conn) return null;
+ return conn;
+ }, [params]);
+ const driver = useMemo(() => {
+ if (!conn) return null;
return new DatabaseDriver(conn.config.url, conn.config.token);
- }, [params]);
+ }, [conn]);
if (!driver) {
return Something wrong
;
}
- return ;
+ return ;
}
diff --git a/src/components/database-gui.tsx b/src/components/database-gui.tsx
index a0add200..51200f13 100644
--- a/src/components/database-gui.tsx
+++ b/src/components/database-gui.tsx
@@ -5,7 +5,6 @@ import {
ResizablePanelGroup,
} from "@/components/ui/resizable";
import { useEffect, useState } from "react";
-import SchemaView from "./schema-sidebar";
import WindowTabs, { WindowTabItemProps } from "./windows-tab";
import TableDataContent from "./tabs/table-data-tab";
import useMessageListener from "@/hooks/useMessageListener";
@@ -13,9 +12,20 @@ import { MessageChannelName } from "@/messages/const";
import { OpenTabsProps } from "@/messages/openTabs";
import QueryWindow from "@/components/tabs/query-tab";
import SchemaEditorTab from "@/components/tabs/schema-editor-tab";
-import { LucideCode, LucideTable, LucideTableProperties } from "lucide-react";
+import {
+ LucideCode,
+ LucideDatabase,
+ LucideSettings,
+ LucideTable,
+ LucideTableProperties,
+} from "lucide-react";
+import SidebarTab from "./sidebar-tab";
+import SchemaView from "./schema-sidebar";
+import { SavedConnectionLabel } from "@/app/connect/saved-connection-storage";
-export default function DatabaseGui() {
+export default function DatabaseGui({
+ color,
+}: Readonly<{ color: SavedConnectionLabel }>) {
const DEFAULT_WIDTH = 300;
const [defaultWidthPercentage, setDefaultWidthPercentage] = useState(20);
@@ -101,9 +111,25 @@ export default function DatabaseGui() {
-
+ ,
+ icon: LucideDatabase,
+ },
+ {
+ key: "setting",
+ name: "Setting",
+ content: Coming Soon
,
+ icon: LucideSettings,
+ },
+ ]}
+ />
-
+
{
return () => {
driver.close();
@@ -27,7 +34,7 @@ function MainConnection({ driver }: { driver: BaseDriver }) {
-
+
@@ -44,7 +51,10 @@ function InvalidSession() {
return ;
}
-function MainConnectionContainer({ driver }: Readonly<{ driver: BaseDriver }>) {
+function MainConnectionContainer({
+ driver,
+ color,
+}: Readonly<{ driver: BaseDriver; color: SavedConnectionLabel }>) {
const router = useRouter();
/**
@@ -68,7 +78,7 @@ function MainConnectionContainer({ driver }: Readonly<{ driver: BaseDriver }>) {
<>
-
+
@@ -78,6 +88,12 @@ function MainConnectionContainer({ driver }: Readonly<{ driver: BaseDriver }>) {
);
}
-export default function MainScreen({ driver }: { driver: BaseDriver }) {
- return ;
+export default function MainScreen({
+ driver,
+ color,
+}: {
+ driver: BaseDriver;
+ color: SavedConnectionLabel;
+}) {
+ return ;
}
diff --git a/src/components/schema-sidebar.tsx b/src/components/schema-sidebar.tsx
index 1e75ad57..71f9057d 100644
--- a/src/components/schema-sidebar.tsx
+++ b/src/components/schema-sidebar.tsx
@@ -1,11 +1,4 @@
-import {
- LucidePlus,
- LucideSearch,
- LucideSun,
- LucideSunMoon,
-} from "lucide-react";
-import { appVersion } from "@/env";
-import { useTheme } from "@/context/theme-provider";
+import { LucidePlus, LucideSearch } from "lucide-react";
import { useCallback, useState } from "react";
import SchemaList from "./schema-sidebar-list";
import { buttonVariants } from "./ui/button";
@@ -20,7 +13,6 @@ import { openTabs } from "@/messages/openTabs";
export default function SchemaView() {
const [search, setSearch] = useState("");
- const { theme, toggleTheme } = useTheme();
const onNewTable = useCallback(() => {
openTabs({
@@ -31,7 +23,7 @@ export default function SchemaView() {
}, []);
return (
-
+
@@ -71,27 +63,6 @@ export default function SchemaView() {
-
-
-
LibSQL
-
Studio
-
v{appVersion}
-
-
{
- toggleTheme();
- }}
- >
- {theme === "dark" ? (
-
- ) : (
-
- )}
-
-
);
}
diff --git a/src/components/sidebar-tab.tsx b/src/components/sidebar-tab.tsx
new file mode 100644
index 00000000..ca6e0ef3
--- /dev/null
+++ b/src/components/sidebar-tab.tsx
@@ -0,0 +1,121 @@
+import { SavedConnectionLabel } from "@/app/connect/saved-connection-storage";
+import { useTheme } from "@/context/theme-provider";
+import { cn } from "@/lib/utils";
+import {
+ LucideArrowLeft,
+ LucideIcon,
+ LucideMoon,
+ LucideSun,
+} from "lucide-react";
+import Link from "next/link";
+import { ReactElement, useState } from "react";
+
+export interface SidebarTabItem {
+ key: string;
+ icon: LucideIcon;
+ name: string;
+ content: ReactElement;
+}
+
+interface SidebarTabProps {
+ color: SavedConnectionLabel;
+ tabs: SidebarTabItem[];
+}
+
+export default function SidebarTab({ tabs, color }: Readonly
) {
+ const [selectedIndex, setSelectedIndex] = useState(0);
+ const { theme, toggleTheme } = useTheme();
+ const [loadedIndex, setLoadedIndex] = useState(() => {
+ const a = new Array(tabs.length).fill(false);
+ a[0] = true;
+ return a;
+ });
+
+ let bgColor = "bg-blue-500 dark:bg-blue-700";
+ let textColor = "text-white";
+
+ if (color === "red") {
+ bgColor = "bg-red-500 dark:bg-red-700";
+ } else if (color === "yellow") {
+ bgColor = "bg-yellow-400 dark:bg-yellow-500";
+ textColor = "text-black";
+ } else if (color === "green") {
+ bgColor = "bg-green-500 dark:bg-green-600";
+ } else if (color === "gray") {
+ bgColor = "bg-gray-500 dark:bg-gray-800";
+ }
+
+ return (
+
+
+ {tabs.map(({ key, name, icon: Icon }, idx) => {
+ return (
+
+ );
+ })}
+
+
+
+
+
+
+
+
+
+
+ {tabs.map((tab, tabIndex) => {
+ const selected = selectedIndex === tabIndex;
+
+ return (
+
+ {loadedIndex[tabIndex] && tab.content}
+
+ );
+ })}
+
+
+ );
+}
diff --git a/src/drivers/remote-driver.ts b/src/drivers/remote-driver.ts
index a8fcb375..ab7f8b6a 100644
--- a/src/drivers/remote-driver.ts
+++ b/src/drivers/remote-driver.ts
@@ -1,4 +1,4 @@
-import { InStatement, ResultSet } from "@libsql/client/web";
+import { InStatement, ResultSet, Row } from "@libsql/client/web";
import {
BaseDriver,
DatabaseSchemaItem,
@@ -15,6 +15,20 @@ import {
} from "@/lib/api-response-types";
import { RequestOperationBody } from "@/lib/api/api-request-types";
+export function transformRawResult(raw: ResultSet): ResultSet {
+ const r = {
+ ...raw,
+ rows: raw.rows.map((r) =>
+ raw.columns.reduce((a, b, idx) => {
+ a[b] = r[idx];
+ return a;
+ }, {} as Row)
+ ),
+ };
+
+ return r;
+}
+
export default class RemoteDriver implements BaseDriver {
protected id: string = "";
protected authToken = "";
@@ -52,7 +66,7 @@ export default class RemoteDriver implements BaseDriver {
statement: stmt,
});
- return r.data;
+ return transformRawResult(r.data);
}
async transaction(stmt: InStatement[]) {
@@ -61,7 +75,7 @@ export default class RemoteDriver implements BaseDriver {
statements: stmt,
});
- return r.data;
+ return r.data.map(transformRawResult);
}
close() {}