Import tables from dbml

This commit is contained in:
1ilit 2025-01-28 18:45:51 +04:00
parent 5bd6f936a1
commit d76a9e9ff8
9 changed files with 131 additions and 59 deletions

View File

@ -1444,7 +1444,7 @@ export default function ControlPanel({
function toolbar() {
return (
<div
className="py-1.5 px-5 flex justify-between items-center rounded-xl my-1 sm:mx-1 xl:mx-6 select-none overflow-hidden toolbar-theme"
className="py-1.5 px-5 flex justify-between items-center rounded-lg my-1 sm:mx-1 xl:mx-6 select-none overflow-hidden toolbar-theme"
style={isRtl(i18n.language) ? { direction: "rtl" } : {}}
>
<div className="flex justify-start items-center">

View File

@ -2,28 +2,28 @@ import { useEffect, useState } from "react";
import CodeMirror from "@uiw/react-codemirror";
import { vscodeDark, vscodeLight } from "@uiw/codemirror-theme-vscode";
import { languageExtension } from "../../../data/editorExtensions";
import { useSettings } from "../../../hooks";
import { useDiagram, useSettings } from "../../../hooks";
import { useDebounceValue } from "usehooks-ts";
import { Parser } from "@dbml/core";
import "./styles.css";
const parser = new Parser();
import { fromDBML } from "../../../utils/dbml/fromDBML";
export default function DBMLEditor() {
const { settings } = useSettings();
const { setTables } = useDiagram();
const [value, setValue] = useState("");
const [debouncedValue] = useDebounceValue(value, 1000);
useEffect(() => {
if (debouncedValue) {
try {
const database = parser.parse(debouncedValue, "dbml");
console.log(database);
const { tables } = fromDBML(debouncedValue);
console.log(tables);
setTables(tables);
} catch (e) {
console.log(e);
console.log("error: ", e);
}
}
}, [debouncedValue]);
}, [debouncedValue, setTables]);
return (
<div>

View File

@ -9,3 +9,15 @@
.ͼ1o .cm-gutters {
background-color: var(--semi-color-bg-0);
}
.ͼ1.cm-focused {
outline: none;
}
.ͼ16 {
background-color: #1e1e1e00;
}
.ͼ16 .cm-gutters {
background-color: rgba(var(--semi-grey-1), 0.3);
}

View File

@ -92,31 +92,12 @@ export default function SidePanel({ width, resize, setResize }) {
style={{ width: `${width}px` }}
>
<div className="h-full flex-1 overflow-y-auto">
<<<<<<< HEAD
<Tabs
type="card"
activeKey={selectedElement.currentTab}
lazyRender
keepDOM={false}
onChange={(key) =>
setSelectedElement((prev) => ({ ...prev, currentTab: key }))
}
collapsible
tabBarStyle={{ direction: "ltr" }}
>
{tabList.length &&
tabList.map((tab) => (
<TabPane tab={tab.tab} itemKey={tab.itemKey} key={tab.itemKey}>
<div className="p-2">{tab.component}</div>
</TabPane>
))}
</Tabs>
=======
{layout.dbmlEditor ? (
<Tabs
type="card"
activeKey={selectedElement.currentTab}
lazyRender
keepDOM={false}
onChange={(key) =>
setSelectedElement((prev) => ({ ...prev, currentTab: key }))
}
@ -137,7 +118,6 @@ export default function SidePanel({ width, resize, setResize }) {
) : (
<DBMLEditor />
)}
>>>>>>> feb41e8 (Add dbml editor to sidepanel)
</div>
{layout.issues && (
<div className="mt-auto border-t-2 border-color shadow-inner">

View File

@ -243,11 +243,8 @@ const en = {
failed_to_load: "Failed to load. Make sure the link is correct.",
share_info:
"* Sharing this link will not create a live real-time collaboration session.",
<<<<<<< HEAD
show_relationship_labels: "Show relationship labels",
=======
dbml_editor: "DBML editor",
>>>>>>> feb41e8 (Add dbml editor to sidepanel)
},
};

View File

@ -105,7 +105,7 @@
}
.toolbar-theme {
background-color: rgba(var(--semi-grey-1), 1);
background-color: rgba(var(--semi-grey-1), 0.7);
}
.hover-1:hover {

View File

@ -0,0 +1,27 @@
import {
tableColorStripHeight,
tableFieldHeight,
tableHeaderHeight,
} from "../data/constants";
export function arrangeTables(diagram) {
let maxHeight = -1;
const tableWidth = 200;
const gapX = 54;
const gapY = 40;
diagram.tables.forEach((table, i) => {
if (i < diagram.tables.length / 2) {
table.x = i * tableWidth + (i + 1) * gapX;
table.y = gapY;
const height =
table.fields.length * tableFieldHeight +
tableHeaderHeight +
tableColorStripHeight;
maxHeight = Math.max(height, maxHeight);
} else {
const index = diagram.tables.length - i - 1;
table.x = index * tableWidth + (index + 1) * gapX;
table.y = maxHeight + 2 * gapY;
}
});
}

View File

@ -0,0 +1,78 @@
import { Parser } from "@dbml/core";
import { arrangeTables } from "../arrangeTables";
const parser = new Parser();
/**
{
"id": 0,
"name": "some_table",
"x": 812.9083754222163,
"y": 400.3451698134321,
"fields": [
{
"name": "id",
"type": "INT",
"default": "",
"check": "",
"primary": true,
"unique": true,
"notNull": true,
"increment": true,
"comment": "",
"id": 0
}
],
"comment": "",
"indices": [],
"color": "#175e7a",
"key": 1737222753837
}
*/
export function fromDBML(src) {
const ast = parser.parse(src, "dbml");
const tables = [];
for (const schema of ast.schemas) {
for (const table of schema.tables) {
let parsedTable = {};
parsedTable.id = tables.length;
parsedTable.name = table.name;
parsedTable.comment = "";
parsedTable.color = "#175e7a";
parsedTable.fields = [];
parsedTable.indices = [];
for (const column of table.fields) {
const field = {};
field.id = parsedTable.fields.length;
field.name = column.name;
field.type = column.type.type_name.toUpperCase();
field.default = column.dbdefault ?? "";
field.check = "";
field.primary = !!column.pk;
field.unique = true;
field.notNull = !!column.not_null;
field.increment = !!column.increment;
field.comment = column.note ?? "";
parsedTable.fields.push(field);
}
console.log(table);
tables.push(parsedTable);
}
}
console.log(ast);
const diagram = { tables };
arrangeTables(diagram);
return diagram;
}

View File

@ -1,9 +1,5 @@
import {
DB,
tableColorStripHeight,
tableFieldHeight,
tableHeaderHeight,
} from "../../data/constants";
import { DB } from "../../data/constants";
import { arrangeTables } from "../arrangeTables";
import { fromMariaDB } from "./mariadb";
import { fromMSSQL } from "./mssql";
import { fromMySQL } from "./mysql";
@ -33,25 +29,7 @@ export function importSQL(ast, toDb = DB.MYSQL, diagramDb = DB.GENERIC) {
break;
}
let maxHeight = -1;
const tableWidth = 200;
const gapX = 54;
const gapY = 40;
diagram.tables.forEach((table, i) => {
if (i < diagram.tables.length / 2) {
table.x = i * tableWidth + (i + 1) * gapX;
table.y = gapY;
const height =
table.fields.length * tableFieldHeight +
tableHeaderHeight +
tableColorStripHeight;
maxHeight = Math.max(height, maxHeight);
} else {
const index = diagram.tables.length - i - 1;
table.x = index * tableWidth + (index + 1) * gapX;
table.y = maxHeight + 2 * gapY;
}
});
arrangeTables(diagram);
return diagram;
}