Skip to content

Commit

Permalink
Merge branch 'develop' of https://github.com/keppere/outerbase-studio
Browse files Browse the repository at this point in the history
…into query_placeholder
  • Loading branch information
keppere committed Jan 16, 2025
2 parents 4bec09e + aca864e commit 00edd5b
Show file tree
Hide file tree
Showing 23 changed files with 699 additions and 82 deletions.
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@libsqlstudio/studio",
"version": "0.9.0",
"version": "0.9.1",
"private": false,
"scripts": {
"dev": "next dev -p 3008",
Expand Down
22 changes: 22 additions & 0 deletions src/app/globals.css
Original file line number Diff line number Diff line change
Expand Up @@ -575,3 +575,25 @@ For Markdown Side
U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

.window-tab-scrollbar {
overflow: hidden;
overflow: block;
}

.window-tab-scrollbar:hover {
overflow: auto;
overflow-y: hidden;
}

.window-tab-scrollbar::-webkit-scrollbar {
height: 3px;
}

.window-tab-scrollbar:hover::-webkit-scrollbar-thumb {
background-color: #555; /* Color of the scrollbar thumb on hover */
}

.window-tab-scrollbar:hover::-webkit-scrollbar-thumb:hover {
background-color: #888; /* Color of the scrollbar thumb on hover */
}
103 changes: 65 additions & 38 deletions src/components/gui/schema-sidebar-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { useDatabaseDriver } from "@/context/driver-provider";
import { Table } from "@phosphor-icons/react";
import SchemaCreateDialog from "./schema-editor/schema-create";
import { scc } from "@/core/command";
import { useConfig } from "@/context/config-provider";

interface SchemaListProps {
search: string;
Expand Down Expand Up @@ -123,6 +124,7 @@ function flattenSchemaGroup(

export default function SchemaList({ search }: Readonly<SchemaListProps>) {
const { databaseDriver } = useDatabaseDriver();
const { extensions } = useConfig();
const [selected, setSelected] = useState("");
const { refresh, schema, currentSchemaName } = useSchema();
const [editSchema, setEditSchema] = useState<string | null>(null);
Expand All @@ -141,7 +143,63 @@ export default function SchemaList({ search }: Readonly<SchemaListProps>) {
const isTable = item?.type === "table";
const isTrigger = item?.type === "trigger";

const createMenuSection = {
title: "Create",
sub: [
databaseDriver.getFlags().supportCreateUpdateTable && {
title: "Create Table",
onClick: () => {
scc.tabs.openBuiltinSchema({
schemaName: item?.schemaName ?? currentSchemaName,
});
},
},
databaseDriver.getFlags().supportCreateUpdateTrigger
? {
title: "Create Trigger",
onClick: () => {
scc.tabs.openBuiltinTrigger({
schemaName: item?.schemaName ?? currentSchemaName,
tableName: item?.tableSchema?.tableName,
});
},
}
: undefined,
...extensions.getResourceCreateMenu(),
],
};

const modificationSection = item
? [
isTable && databaseDriver.getFlags().supportCreateUpdateTable
? {
title: "Edit Table",
onClick: () => {
scc.tabs.openBuiltinSchema({
schemaName: item?.schemaName ?? currentSchemaName,
tableName: item?.name,
});
},
}
: undefined,
databaseDriver.getFlags().supportCreateUpdateTrigger && isTrigger
? {
title: "Edit Trigger",
onClick: () => {
scc.tabs.openBuiltinTrigger({
schemaName: item?.schemaName ?? currentSchemaName,
name: item.name,
tableName: item?.tableSchema?.tableName,
});
},
}
: undefined,
...extensions.getResourceContextMenu(item, "modification"),
]
: [];

return [
createMenuSection,
{
title: "Copy Name",
disabled: !selectedName,
Expand All @@ -150,47 +208,16 @@ export default function SchemaList({ search }: Readonly<SchemaListProps>) {
},
},
{ separator: true },
databaseDriver.getFlags().supportCreateUpdateTable && {
title: "Create New Table",
onClick: () => {
scc.tabs.openBuiltinSchema({
schemaName: item?.schemaName ?? currentSchemaName,
});
},
},
isTable && databaseDriver.getFlags().supportCreateUpdateTable
? {
title: "Edit Table",
onClick: () => {
scc.tabs.openBuiltinTable({
schemaName: item?.schemaName ?? currentSchemaName,
tableName: item?.name,
});
},
}
: undefined,
databaseDriver.getFlags().supportCreateUpdateTrigger
? { separator: true }
: undefined,
databaseDriver.getFlags().supportCreateUpdateTrigger
? {
title: isTrigger ? "Edit Trigger" : "Create New Trigger",
onClick: () => {
scc.tabs.openBuiltinTrigger({
schemaName: item?.schemaName ?? currentSchemaName,
name: isTrigger ? item.name : "",
tableName: item?.tableSchema?.tableName,
});
},
}
: undefined,
databaseDriver.getFlags().supportCreateUpdateTable
? { separator: true }
: undefined,

// Modification Section
...modificationSection,
modificationSection.length > 0 ? { separator: true } : undefined,


{ title: "Refresh", onClick: () => refresh() },
].filter(Boolean) as OpenContextMenuList;
},
[refresh, databaseDriver, currentSchemaName]
[refresh, databaseDriver, currentSchemaName, extensions]
);

const listViewItems = useMemo(() => {
Expand Down
25 changes: 14 additions & 11 deletions src/components/gui/schema-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,24 +14,25 @@ import {
DropdownMenuTrigger,
} from "../ui/dropdown-menu";
import { scc } from "@/core/command";
import { StudioExtensionMenuItem } from "@/core/extension-manager";
import { useConfig } from "@/context/config-provider";

export default function SchemaView() {
const [search, setSearch] = useState("");
const { databaseDriver } = useDatabaseDriver();
const { currentSchemaName } = useSchema();
const [isCreateSchema, setIsCreateSchema] = useState(false);
const { extensions } = useConfig();

const contentMenu = useMemo(() => {
const items: {
name: string;
onClick: () => void;
}[] = [];
const items: StudioExtensionMenuItem[] = [];

const flags = databaseDriver.getFlags();

if (flags.supportCreateUpdateTable) {
items.push({
name: "Create Table",
title: "Create Table",
key: "create-table",
onClick: () => {
scc.tabs.openBuiltinSchema({ schemaName: currentSchemaName });
},
Expand All @@ -40,7 +41,8 @@ export default function SchemaView() {

if (flags.supportCreateUpdateDatabase) {
items.push({
name: "Create Database/Schema",
title: "Create Database/Schema",
key: "create-schema",
onClick: () => {
setIsCreateSchema(true);
},
Expand All @@ -49,15 +51,16 @@ export default function SchemaView() {

if (flags.supportCreateUpdateTrigger) {
items.push({
name: "Create Trigger",
title: "Create Trigger",
key: "create-trigger",
onClick: () => {
scc.tabs.openBuiltinTrigger({ schemaName: currentSchemaName });
},
});
}

return items;
}, [databaseDriver, currentSchemaName]);
return [...items, ...extensions.getResourceCreateMenu()];
}, [databaseDriver, currentSchemaName, extensions]);

const activatorButton = useMemo(() => {
if (contentMenu.length === 0) return null;
Expand Down Expand Up @@ -95,8 +98,8 @@ export default function SchemaView() {
<DropdownMenuContent side="bottom" align="start">
{contentMenu.map((menu) => {
return (
<DropdownMenuItem key={menu.name} onClick={menu.onClick}>
{menu.name}
<DropdownMenuItem key={menu.title} onClick={menu.onClick}>
{menu.title}
</DropdownMenuItem>
);
})}
Expand Down
4 changes: 2 additions & 2 deletions src/components/gui/sortable-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export const WindowTabItemButton = forwardRef<
return (
<button
className={cn(
"relative h-[40px] border-x text-neutral-500 flex items-center text-left text-xs px-2 min-w-[170px] max-w-[300px] hover:dark:text-white hover:text-black",
"bg-neutral-100 dark:bg-neutral-900 relative h-[40px] border-x text-neutral-500 flex items-center text-left text-xs px-2 min-w-[170px] max-w-[300px] hover:dark:text-white hover:text-black",
isDragging && "z-20",
selected
? "bg-neutral-50 dark:bg-neutral-950 text-primary"
Expand Down Expand Up @@ -69,7 +69,7 @@ export const WindowTabItemButton = forwardRef<
)}

{!selected && (
<div className="absolute right-[-1px] top-2 w-[1px] h-6 bg-neutral-800" />
<div className="absolute right-[-1px] top-2 w-[1px] h-6 bg-border dark:bg-neutral-800" />
)}
</button>
);
Expand Down
2 changes: 1 addition & 1 deletion src/components/gui/studio.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ export function Studio({
useEffect(() => {
finalExtensionManager.init();
return () => finalExtensionManager.cleanup();
});
}, [finalExtensionManager]);

const config = useMemo(() => {
return {
Expand Down
60 changes: 57 additions & 3 deletions src/components/gui/windows-tab.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
import { type LucideIcon, LucidePlus } from "lucide-react";
import { createContext, useCallback, useContext, useMemo } from "react";
import {
createContext,
useCallback,
useContext,
useEffect,
useMemo,
useRef,
} from "react";
import {
DndContext,
closestCenter,
Expand Down Expand Up @@ -79,6 +86,46 @@ export default function WindowTabs({
distance: 8,
},
});
const tabContainerRef = useRef<HTMLDivElement>(null);
const tabMenuRef = useRef<HTMLDivElement>(null);

useEffect(() => {
const container = tabContainerRef.current;
if (!container) return;

const selectedTab = container.children[selected];
if (!selectedTab) return;

const containerRect = container.getBoundingClientRect();
const selectedTabRect = selectedTab.getBoundingClientRect();

let menuWidth = 0;
if (tabMenuRef.current) {
menuWidth = tabMenuRef.current.getBoundingClientRect().width;
}

if (selectedTabRect.left < containerRect.left) {
container.scrollLeft += selectedTabRect.left - containerRect.left;
} else if (selectedTabRect.right > containerRect.right) {
container.scrollLeft +=
selectedTabRect.right - containerRect.right + menuWidth + 1;
}
}, [selected, tabs]);

useEffect(() => {
const container = tabContainerRef.current;
if (!container) return;

const handleWheel = (event: WheelEvent) => {
if (event.deltaY !== 0) {
container.scrollLeft += event.deltaY;
event.preventDefault();
}
};

container.addEventListener("wheel", handleWheel);
return () => container.removeEventListener("wheel", handleWheel);
}, []);

const keyboardSensor = useSensor(KeyboardSensor, {
coordinateGetter: sortableKeyboardCoordinates,
Expand Down Expand Up @@ -149,7 +196,10 @@ export default function WindowTabs({
>
<div className="flex flex-col w-full h-full">
<div className="grow-0 shrink-0 bg-neutral-100 dark:bg-neutral-900 overflow-x-auto no-scrollbar">
<div className="flex h-[40px]">
<div
className="flex h-[40px] window-tab-scrollbar"
ref={tabContainerRef}
>
<SortableContext
items={tabs.map((tab) => tab.key)}
strategy={horizontalListSortingStrategy}
Expand Down Expand Up @@ -186,7 +236,11 @@ export default function WindowTabs({
</SortableContext>

{menu && (
<div className="flex h-[40px] items-center border-b">
<div
ref={tabMenuRef}
style={{ zIndex: 50, position: "sticky" }}
className={`flex h-[40px] items-center border-b right-0 bg-neutral-100 dark:bg-neutral-900`}
>
<DropdownMenu modal={false}>
<DropdownMenuTrigger>
<div className="ml-1.5 text-xs flex h-7 items-center justify-center gap-1 rounded-lg p-1.5 py-2 text-neutral-600 transition hover:bg-neutral-200 hover:text-black dark:text-neutral-400 dark:hover:bg-neutral-800 dark:hover:text-white">
Expand Down
4 changes: 2 additions & 2 deletions src/core/extension-base.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { StudioExtensionManager } from "./extension-manager";
import { StudioExtensionContext } from "./extension-manager";

export abstract class IStudioExtension {
abstract extensionName: string;
abstract init(studio: StudioExtensionManager): void;
abstract init(studio: StudioExtensionContext): void;
abstract cleanup(): void;
}

Expand Down
Loading

0 comments on commit 00edd5b

Please sign in to comment.