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
3 changes: 1 addition & 2 deletions src/app/(outerbase)/local/edit-base/[baseId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,11 @@ export default function LocalEditBasePage() {
setValidateErrors(errors);
if (Object.keys(errors).length > 0) return;

setLoading(true);
const tmp = await updateLocalConnection(baseId, template.localTo(value));
router.push(
tmp?.content.driver === "sqlite-filehandler"
? `/playground/client?s=${tmp?.content.id}`
: `/client/s/${tmp?.content.driver ?? "turso"}?p=${tmp?.content.id}`
: `/client/s/${tmp?.content.driver ?? "turso"}?p=${baseId}`
);
}, [template, value, router, baseId]);

Expand Down
10 changes: 8 additions & 2 deletions src/app/(outerbase)/local/hooks.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { SavedConnectionRawLocalStorage } from "@/app/(theme)/connect/saved-connection-storage";
import { LocalConnectionData, LocalDashboardData, localDb } from "@/indexdb";
import { generateId } from "@/lib/generate-id";
import parseSafeJson from "@/lib/json-safe";
import useSWR, { mutate } from "swr";

Expand All @@ -18,7 +19,7 @@ export function useLocalDashboardList() {
}

export async function createLocalDashboard(boardName: string) {
const id = crypto.randomUUID();
const id = generateId();
const now = Date.now();

const data: LocalDashboardData = {
Expand Down Expand Up @@ -103,7 +104,7 @@ export async function removeLocalConnection(id: string) {
export async function createLocalConnection(
config: SavedConnectionRawLocalStorage
): Promise<LocalConnectionData> {
const id = crypto.randomUUID();
const id = generateId();

const data = {
id,
Expand Down Expand Up @@ -133,7 +134,12 @@ export async function updateLocalConnection(
};

await localDb.connection.put(data);

mutate("/connections/local");
mutate("/connections/local/" + id, data, {
optimisticData: data,
revalidate: false,
});

return data;
}
Expand Down
144 changes: 85 additions & 59 deletions src/app/(outerbase)/nav-layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,86 +4,112 @@ import {
SidebarMenuItem,
SidebarMenuLoadingItem,
} from "@/components/sidebar-menu";
import { Database, Plus } from "@phosphor-icons/react";
import { cn } from "@/lib/utils";
import { Database, List, Plus } from "@phosphor-icons/react";
import { useParams, usePathname, useRouter } from "next/navigation";
import { PropsWithChildren } from "react";
import { PropsWithChildren, useState } from "react";
import NavigationProfile from "./nav-profile";
import NavigationSigninBanner from "./nav-signin-banner";
import { useSession } from "./session-provider";
import { useWorkspaces } from "./workspace-provider";

export default function NavigationLayout({ children }: PropsWithChildren) {
const router = useRouter();
const [mobileToggle, setMobileToggle] = useState(false);
const { session } = useSession();
const { workspaces, loading: workspaceLoading } = useWorkspaces();
const pathname = usePathname();
const { workspaceId } = useParams<{ workspaceId?: string }>();

return (
<div className="flex h-screen w-screen">
<div className="flex w-[250px] shrink-0 flex-col overflow-hidden border-r">
<div className="px-2 py-2">
<div className="flex w-screen flex-col lg:h-screen lg:flex-row">
<div className="bg-background sticky top-0 z-25 flex w-full shrink-0 flex-col overflow-hidden border-r-0 border-b lg:w-[250px] lg:border-r lg:border-b-0">
<div className="flex items-center justify-between px-2 py-2">
<NavigationProfile />
</div>

<div className="flex flex-1 flex-col overflow-scroll border-b pb-2">
<SidebarMenuHeader text="Workspace" />
<SidebarMenuItem
selected={pathname === "/local" || pathname === "/local-setting"}
text="Local Workspace"
icon={Database}
href="/local"
<List
className="mr-2 block h-6 w-6 cursor-pointer lg:hidden"
onClick={() => {
setMobileToggle(!mobileToggle);
}}
/>
</div>

{workspaces.map((workspace) => {
return (
<SidebarMenuItem
key={workspace.id}
text={workspace.name}
icon={Database}
onClick={
workspace.short_name === workspaceId
? undefined
: () => {
router.push(`/w/${workspace.short_name}`);
}
}
selected={workspace.short_name === workspaceId}
badge={
!workspace.is_enterprise &&
workspace.subscription.plan === "starter" ? (
<span className="mr-2 rounded border border-neutral-200 bg-white px-1.5 py-0.5 text-sm font-medium text-neutral-600 dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-200">
Free
</span>
) : undefined
}
/>
);
})}
{mobileToggle && (
<div
className="fixed top-0 right-0 bottom-0 left-0 z-25 backdrop-blur-md lg:hidden"
onClick={() => {
setMobileToggle(false);
}}
></div>
)}

{workspaceLoading && (
<>
<SidebarMenuLoadingItem />
<SidebarMenuLoadingItem />
<SidebarMenuLoadingItem />
</>
<div
className={cn(
"bg-background fixed right-0 z-50 flex hidden h-screen w-2/3 flex-1 overflow-scroll border-b border-l pb-2 md:w-1/2 lg:relative lg:z-0 lg:block lg:h-auto lg:w-auto",
{
block: mobileToggle,
}
)}
>
<div className="flex flex-1 flex-col">
<SidebarMenuHeader text="Workspace" />
<SidebarMenuItem
selected={pathname === "/local" || pathname === "/local-setting"}
text="Local Workspace"
icon={Database}
href="/local"
/>

<SidebarMenuItem
text={"New Workspace"}
icon={Plus}
onClick={() => {
if (session?.user) {
router.push("/new-workspace");
} else {
localStorage.setItem("continue-redirect", "/new-workspace");
router.push("/signin");
}
}}
/>
</div>
{workspaces.map((workspace) => {
return (
<SidebarMenuItem
key={workspace.id}
text={workspace.name}
icon={Database}
onClick={
workspace.short_name === workspaceId
? undefined
: () => {
router.push(`/w/${workspace.short_name}`);
}
}
selected={workspace.short_name === workspaceId}
badge={
!workspace.is_enterprise &&
workspace.subscription.plan === "starter" ? (
<span className="mr-2 rounded border border-neutral-200 bg-white px-1.5 py-0.5 text-sm font-medium text-neutral-600 dark:border-neutral-700 dark:bg-neutral-800 dark:text-neutral-200">
Free
</span>
) : undefined
}
/>
);
})}

<NavigationSigninBanner />
{workspaceLoading && (
<>
<SidebarMenuLoadingItem />
<SidebarMenuLoadingItem />
<SidebarMenuLoadingItem />
</>
)}

<SidebarMenuItem
text={"New Workspace"}
icon={Plus}
onClick={() => {
if (session?.user) {
router.push("/new-workspace");
} else {
localStorage.setItem("continue-redirect", "/new-workspace");
router.push("/signin");
}
}}
/>
</div>

<NavigationSigninBanner />
</div>
</div>
<div className="flex min-h-screen w-full flex-col overflow-y-auto bg-neutral-50 dark:bg-neutral-950">
{children}
Expand Down
16 changes: 10 additions & 6 deletions src/app/(outerbase)/w/[workspaceId]/[baseId]/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ import {
createPostgreSQLExtensions,
createSQLiteExtensions,
} from "@/core/standard-extension";
import MySQLLikeDriver from "@/drivers/mysql/mysql-driver";
import PostgresLikeDriver from "@/drivers/postgres/postgres-driver";
import { SqliteLikeBaseDriver } from "@/drivers/sqlite-base-driver";
import DataCatalogExtension from "@/extensions/data-catalog";
import OuterbaseExtension from "@/extensions/outerbase";
import {
Expand All @@ -17,9 +20,7 @@ import {
import { OuterbaseAPIBaseCredential } from "@/outerbase-cloud/api-type";
import { getOuterbaseBaseCredential } from "@/outerbase-cloud/api-workspace";
import DataCatalogOuterbaseDriver from "@/outerbase-cloud/data-catalog-driver";
import { OuterbaseMySQLDriver } from "@/outerbase-cloud/database/mysql";
import { OuterbasePostgresDriver } from "@/outerbase-cloud/database/postgresql";
import { OuterbaseSqliteDriver } from "@/outerbase-cloud/database/sqlite";
import { OuterbaseQueryable } from "@/outerbase-cloud/database/query";
import OuterbaseQueryDriver from "@/outerbase-cloud/query-driver";
import { useParams } from "next/navigation";
import { useEffect, useMemo, useState } from "react";
Expand Down Expand Up @@ -74,15 +75,18 @@ export default function OuterbaseSourcePage() {

if (dialect === "postgres") {
return [
new OuterbasePostgresDriver(outerbaseConfig),
new PostgresLikeDriver(new OuterbaseQueryable(outerbaseConfig)),
new StudioExtensionManager([
...createPostgreSQLExtensions(),
...outerbaseSpecifiedDrivers,
]),
];
} else if (dialect === "mysql") {
return [
new OuterbaseMySQLDriver(outerbaseConfig, credential.database),
new MySQLLikeDriver(
new OuterbaseQueryable(outerbaseConfig),
credential.database
),
new StudioExtensionManager([
...createMySQLExtensions(),
...outerbaseSpecifiedDrivers,
Expand All @@ -91,7 +95,7 @@ export default function OuterbaseSourcePage() {
}

return [
new OuterbaseSqliteDriver(outerbaseConfig),
new SqliteLikeBaseDriver(new OuterbaseQueryable(outerbaseConfig)),
new StudioExtensionManager([
...createSQLiteExtensions(),
...outerbaseSpecifiedDrivers,
Expand Down
Loading