Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add mysql driver #147

Merged
merged 21 commits into from
Sep 5, 2024
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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.6.4",
"private": false,
"scripts": {
"dev": "next dev",
"dev": "next dev -p 3008",
"dev-https": "next dev --experimental-https",
"build": "next build",
"build-with-migrate": "npm run db:migrate && next build",
Expand Down
22 changes: 22 additions & 0 deletions src/app/(theme)/embed/mysql/page-client.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
"use client";
import { Studio } from "@/components/gui/studio";
import { IframeMySQLDriver } from "@/drivers/iframe-driver";
import { useSearchParams } from "next/navigation";
import { useEffect, useMemo } from "react";

export default function EmbedPageClient() {
const searchParams = useSearchParams();
const driver = useMemo(() => new IframeMySQLDriver(), []);

useEffect(() => {
return driver.listen();
}, [driver]);

return (
<Studio
driver={driver}
name={searchParams.get("name") || "Unnamed Connection"}
color={searchParams.get("color") || "gray"}
/>
);
}
37 changes: 37 additions & 0 deletions src/app/(theme)/embed/mysql/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import ThemeLayout from "../../theme_layout";
import EmbedPageClient from "./page-client";

export default async function EmbedPage(props: {
searchParams: {
theme?: string;
disableThemeToggle?: string;
[key: string]: any;
};
}) {
let overrideTheme: "dark" | "light" | undefined = undefined;
const disableToggle = props.searchParams.disableThemeToggle === "1";

if (props.searchParams.theme) {
overrideTheme = props.searchParams.theme === "dark" ? "dark" : "light";
}

const overrideThemeVariables: Record<string, string> = {};

for (const key in props.searchParams) {
if (!key.startsWith("themeVariables[")) {
continue;
}

overrideThemeVariables[key.slice(15, -1)] = props.searchParams[key];
}

return (
<ThemeLayout
overrideTheme={overrideTheme}
disableToggle={disableToggle}
overrideThemeVariables={overrideThemeVariables}
>
<EmbedPageClient />
</ThemeLayout>
);
}
4 changes: 2 additions & 2 deletions src/app/(theme)/embed/sqlite/page-client.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
"use client";
import { Studio } from "@/components/gui/studio";
import IframeDriver from "@/drivers/iframe-driver";
import { IframeSQLiteDriver } from "@/drivers/iframe-driver";
import { useSearchParams } from "next/navigation";
import { useEffect, useMemo } from "react";

export default function EmbedPageClient() {
const searchParams = useSearchParams();
const driver = useMemo(() => new IframeDriver(), []);
const driver = useMemo(() => new IframeSQLiteDriver(), []);

useEffect(() => {
return driver.listen();
Expand Down
23 changes: 14 additions & 9 deletions src/components/gui/database-gui.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import SettingSidebar from "./sidebar/setting-sidebar";

import { useDatabaseDriver } from "@/context/driver-provider";
import SavedDocTab from "./sidebar/saved-doc-tab";
import { useSchema } from "@/context/schema-provider";

export default function DatabaseGui() {
const DEFAULT_WIDTH = 300;
Expand All @@ -33,8 +34,10 @@ export default function DatabaseGui() {
setDefaultWidthPercentage((DEFAULT_WIDTH / window.innerWidth) * 100);
}, []);

const { collaborationDriver, docDriver } = useDatabaseDriver();
const { databaseDriver, collaborationDriver, docDriver } =
useDatabaseDriver();
const [selectedTabIndex, setSelectedTabIndex] = useState(0);
const { currentSchemaName } = useSchema();
const [tabs, setTabs] = useState<WindowTabItemProps[]>(() => [
{
title: "Query",
Expand Down Expand Up @@ -119,14 +122,16 @@ export default function DatabaseGui() {
openTab({ type: "query" });
},
},
{
text: "New Table",
onClick: () => {
openTab({ type: "schema" });
},
},
];
}, []);
databaseDriver.getFlags().supportCreateUpdateTable
? {
text: "New Table",
onClick: () => {
openTab({ type: "schema", schemaName: currentSchemaName });
},
}
: undefined,
].filter(Boolean) as { text: string; onClick: () => void }[];
}, [currentSchemaName, databaseDriver]);

return (
<div className="h-screen w-screen flex flex-col">
Expand Down
4 changes: 4 additions & 0 deletions src/components/gui/schema-editor/column-fk-popup.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ import { Separator } from "../../ui/separator";
export default function ColumnForeignKeyPopup({
constraint,
disabled,
schemaName,
onChange,
}: Readonly<{
constraint: DatabaseForeignKeyClause;
schemaName: string;
disabled: boolean;
onChange: ColumnChangeEvent;
}>) {
Expand All @@ -33,6 +35,7 @@ export default function ColumnForeignKeyPopup({
<div className="flex flex-col gap-2 mt-2">
<Label className="text-xs font-normal">Foreign Table Name</Label>
<TableCombobox
schemaName={schemaName}
value={constraint.foreignTableName}
disabled={disabled}
onChange={(newTable) => {
Expand Down Expand Up @@ -64,6 +67,7 @@ export default function ColumnForeignKeyPopup({
},
});
}}
schemaName={schemaName}
tableName={constraint.foreignTableName}
/>
</div>
Expand Down
2 changes: 1 addition & 1 deletion src/components/gui/schema-editor/column-provider.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { DatabaseTableColumnChange } from "@/drivers/base-driver";
import { PropsWithChildren, createContext, useContext } from "react";
import { DatabaseTableColumnChange } from ".";

const ColumnContext = createContext<{ columns: DatabaseTableColumnChange[] }>({
columns: [],
Expand Down
85 changes: 38 additions & 47 deletions src/components/gui/schema-editor/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,39 +4,15 @@ import { Dispatch, SetStateAction, useCallback, useMemo } from "react";
import { Button, buttonVariants } from "../../ui/button";
import SchemaEditorColumnList from "./schema-editor-column-list";
import { Input } from "../../ui/input";
import generateSqlSchemaChange, {
checkSchemaChange,
} from "@/components/lib/sql-generate.schema";
import {
DatabaseTableColumn,
DatabaseTableColumnConstraint,
} from "@/drivers/base-driver";
import { checkSchemaChange } from "@/components/lib/sql-generate.schema";
import SchemaEditorConstraintList from "./schema-editor-constraint-list";
import { ColumnsProvider } from "./column-provider";
import { Popover, PopoverContent, PopoverTrigger } from "../../ui/popover";
import CodePreview from "../code-preview";
import { toast } from "sonner";

export interface DatabaseTableColumnChange {
old: DatabaseTableColumn | null;
new: DatabaseTableColumn | null;
}

export interface DatabaseTableConstraintChange {
id: string;
old: DatabaseTableColumnConstraint | null;
new: DatabaseTableColumnConstraint | null;
}

export interface DatabaseTableSchemaChange {
name: {
old?: string;
new?: string;
};
columns: DatabaseTableColumnChange[];
constraints: DatabaseTableConstraintChange[];
createScript?: string;
}
import { DatabaseTableSchemaChange } from "@/drivers/base-driver";
import { useDatabaseDriver } from "@/context/driver-provider";
import SchemaNameSelect from "./schema-name-select";

interface Props {
onSave: () => void;
Expand All @@ -51,6 +27,7 @@ export default function SchemaEditor({
onSave,
onDiscard,
}: Readonly<Props>) {
const { databaseDriver } = useDatabaseDriver();
const isCreateScript = value.name.old === "";

const onAddColumn = useCallback(() => {
Expand Down Expand Up @@ -84,8 +61,8 @@ export default function SchemaEditor({
const hasChange = checkSchemaChange(value);

const previewScript = useMemo(() => {
return generateSqlSchemaChange(value).join("\n");
}, [value]);
return databaseDriver.createUpdateTableSchema(value).join("\n");
}, [value, databaseDriver]);

return (
<div className="w-full h-full flex flex-col">
Expand All @@ -94,7 +71,7 @@ export default function SchemaEditor({
<Button
variant="ghost"
onClick={onSave}
disabled={!hasChange || !value.name?.new}
disabled={!hasChange || !value.name?.new || !value.schemaName}
size={"sm"}
>
<LucideSave className="w-4 h-4 mr-2" />
Expand Down Expand Up @@ -173,22 +150,34 @@ export default function SchemaEditor({
)}
</div>

<div className="flex items-center mx-3 mt-1 mb-2 ml-5 gap-2">
<div className="text-xs flex items-center justify-center">Name</div>
<Input
placeholder="Table Name"
value={value.name.new ?? value.name.old ?? ""}
onChange={(e) => {
onChange({
...value,
name: {
...value.name,
new: e.currentTarget.value,
},
});
}}
className="w-[200px]"
/>
<div className="flex items-center mx-3 mt-3 mb-4 ml-5 gap-2">
<div>
<div className="text-xs font-medium mb-1">Table Name</div>
<Input
placeholder="Table Name"
value={value.name.new ?? value.name.old ?? ""}
onChange={(e) => {
onChange({
...value,
name: {
...value.name,
new: e.currentTarget.value,
},
});
}}
className="w-[200px]"
/>
</div>
<div>
<div className="text-xs font-medium mb-1">Schema</div>
<SchemaNameSelect
readonly={!isCreateScript}
value={value.schemaName}
onChange={(selectedSchema) => {
onChange({ ...value, schemaName: selectedSchema });
}}
/>
</div>
</div>
<Separator />
</div>
Expand All @@ -197,9 +186,11 @@ export default function SchemaEditor({
columns={value.columns}
onChange={onChange}
onAddColumn={onAddColumn}
schemaName={value.schemaName}
/>
<ColumnsProvider value={value.columns}>
<SchemaEditorConstraintList
schemaName={value.schemaName}
constraints={value.constraints}
onChange={onChange}
disabled={!isCreateScript}
Expand Down
18 changes: 15 additions & 3 deletions src/components/gui/schema-editor/schema-editor-column-list.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import { DatabaseTableColumnChange, DatabaseTableSchemaChange } from ".";
import { Dispatch, SetStateAction, useCallback } from "react";
import {
DropdownMenu,
Expand All @@ -22,7 +21,9 @@ import ColumnDefaultValueInput from "./column-default-value-input";
import { checkSchemaColumnChange } from "@/components/lib/sql-generate.schema";
import {
DatabaseTableColumn,
DatabaseTableColumnChange,
DatabaseTableColumnConstraint,
DatabaseTableSchemaChange,
TableColumnDataType,
} from "@/drivers/base-driver";
import { cn } from "@/lib/utils";
Expand Down Expand Up @@ -83,10 +84,12 @@ function changeColumnOnIndex(
function ColumnItem({
value,
idx,
schemaName,
onChange,
}: {
value: DatabaseTableColumnChange;
idx: number;
schemaName?: string;
onChange: Dispatch<SetStateAction<DatabaseTableSchemaChange>>;
}) {
const disabled = !!value.old;
Expand Down Expand Up @@ -197,11 +200,12 @@ function ColumnItem({
/>
)}

{column.constraint?.foreignKey && (
{column.constraint?.foreignKey && schemaName && (
<ColumnForeignKeyPopup
constraint={column.constraint.foreignKey}
disabled={disabled}
onChange={change}
schemaName={schemaName}
/>
)}

Expand Down Expand Up @@ -293,10 +297,12 @@ function ColumnItem({
export default function SchemaEditorColumnList({
columns,
onChange,
schemaName,
onAddColumn,
}: Readonly<{
columns: DatabaseTableColumnChange[];
onChange: Dispatch<SetStateAction<DatabaseTableSchemaChange>>;
schemaName?: string;
onAddColumn: () => void;
}>) {
const headerStyle = "text-xs p-2 text-left bg-secondary border";
Expand All @@ -317,7 +323,13 @@ export default function SchemaEditorColumnList({
</thead>
<tbody>
{columns.map((col, idx) => (
<ColumnItem idx={idx} value={col} key={idx} onChange={onChange} />
<ColumnItem
idx={idx}
value={col}
key={idx}
onChange={onChange}
schemaName={schemaName}
/>
))}
</tbody>
<tfoot>
Expand Down
Loading
Loading