- ) : issues.length > 0 ? (
+ ) : issues.dbml.length > 0 || issues.diagram.length > 0 ? (
<>
- {issues.map((e, i) => (
-
- {e}
+ {!layout.dbmlEditor &&
+ issues.dbml.map((e, i) => (
+
+ ))}
+ {issues.diagram.map((e, i) => (
+
))}
>
diff --git a/src/components/EditorSidePanel/SidePanel.jsx b/src/components/EditorSidePanel/SidePanel.jsx
index 168c1f6b..99a623af 100644
--- a/src/components/EditorSidePanel/SidePanel.jsx
+++ b/src/components/EditorSidePanel/SidePanel.jsx
@@ -1,5 +1,6 @@
-import { Tabs, TabPane } from "@douyinfe/semi-ui";
+import { Tabs, TabPane, Button, Divider, Tooltip } from "@douyinfe/semi-ui";
import { Tab } from "../../data/constants";
+import { IconCode } from "@douyinfe/semi-icons";
import {
useLayout,
useSelect,
@@ -16,14 +17,15 @@ import AreasTab from "./AreasTab/AreasTab";
import NotesTab from "./NotesTab/NotesTab";
import TablesTab from "./TablesTab/TablesTab";
import { useTranslation } from "react-i18next";
-import { useMemo } from "react";
+import { useMemo, useState } from "react";
import { databases } from "../../data/databases";
import EnumsTab from "./EnumsTab/EnumsTab";
import { isRtl } from "../../i18n/utils/rtl";
import i18n from "../../i18n/i18n";
+import DBMLEditor from "./DBMLEditor/DBMLEditor";
export default function SidePanel({ width, resize, setResize }) {
- const { layout } = useLayout();
+ const { layout, setLayout } = useLayout();
const { selectedElement, setSelectedElement } = useSelect();
const { database, tablesCount, relationshipsCount } = useDiagram();
const { areasCount } = useAreas();
@@ -31,6 +33,7 @@ export default function SidePanel({ width, resize, setResize }) {
const { typesCount } = useTypes();
const { enumsCount } = useEnums();
const { t } = useTranslation();
+ const [issues, setIssues] = useState({ diagram: [], dbml: [] });
const tabList = useMemo(() => {
const tabs = [
@@ -84,6 +87,10 @@ export default function SidePanel({ width, resize, setResize }) {
notesCount,
]);
+ const toggleDBMLEditor = () => {
+ setLayout((prev) => ({ ...prev, dbmlEditor: !prev.dbmlEditor }));
+ };
+
return (
-
- setSelectedElement((prev) => ({ ...prev, currentTab: key }))
- }
- collapsible
- tabBarStyle={{ direction: "ltr" }}
- >
- {tabList.length &&
- tabList.map((tab) => (
-
- {tab.component}
-
- ))}
-
+ {layout.dbmlEditor ? (
+
+ ) : (
+
+ setSelectedElement((prev) => ({ ...prev, currentTab: key }))
+ }
+ collapsible
+ tabBarStyle={{ direction: "ltr" }}
+ tabBarExtraContent={
+ <>
+
+
+ }
+ theme="borderless"
+ />
+
+ >
+ }
+ >
+ {tabList.length &&
+ tabList.map((tab) => (
+
+ {tab.component}
+
+ ))}
+
+ )}
{layout.issues && (
-
+
)}
diff --git a/src/context/LayoutContext.jsx b/src/context/LayoutContext.jsx
index cfb48360..5349b044 100644
--- a/src/context/LayoutContext.jsx
+++ b/src/context/LayoutContext.jsx
@@ -8,6 +8,7 @@ export default function LayoutContextProvider({ children }) {
sidebar: true,
issues: true,
toolbar: true,
+ dbmlEditor: false,
});
return (
diff --git a/src/data/constants.js b/src/data/constants.js
index 6020db45..39738ee3 100644
--- a/src/data/constants.js
+++ b/src/data/constants.js
@@ -106,6 +106,11 @@ export const DB = {
GENERIC: "generic",
};
+export const ErrorType = {
+ DIAGRAM: "diagram",
+ DBML: "dbml",
+};
+
export const IMPORT_FROM = {
JSON: 0,
DBML: 1,
diff --git a/src/i18n/locales/en.js b/src/i18n/locales/en.js
index 5dc8ed4c..96ecf99a 100644
--- a/src/i18n/locales/en.js
+++ b/src/i18n/locales/en.js
@@ -251,6 +251,8 @@ const en = {
bulk_update: "Bulk update",
multiselect: "Multiselect",
export_saved_data: "Export saved data",
+ dbml_view: "DBML view",
+ tab_view: "Tab view",
},
};
diff --git a/src/index.css b/src/index.css
index 976ecf3e..330fe1a2 100644
--- a/src/index.css
+++ b/src/index.css
@@ -67,7 +67,7 @@
background-color: rgba(var(--semi-blue-6), 1);
}
-.semi-spin-wrapper{
+.semi-spin-wrapper {
color: inherit;
}
@@ -119,7 +119,7 @@
}
.toolbar-theme {
- background-color: rgba(var(--semi-grey-1), 1);
+ background-color: rgba(var(--semi-grey-1), 0.7);
}
.hover-1:hover {
diff --git a/src/utils/exportAs/dbml.js b/src/utils/exportAs/dbml.js
index 736df391..2e150a8f 100644
--- a/src/utils/exportAs/dbml.js
+++ b/src/utils/exportAs/dbml.js
@@ -3,7 +3,10 @@ import i18n from "../../i18n/i18n";
import { escapeQuotes, parseDefault } from "../exportSQL/shared";
function columnDefault(field, database) {
- if (!field.default || field.default.trim() === "") {
+ if (
+ !field.default ||
+ (typeof field.default === "string" && field.default.trim() === "")
+ ) {
return "";
}
diff --git a/src/utils/importFrom/dbml.js b/src/utils/importFrom/dbml.js
index 3157f104..51459b60 100644
--- a/src/utils/importFrom/dbml.js
+++ b/src/utils/importFrom/dbml.js
@@ -28,7 +28,7 @@ export function fromDBML(src) {
field.id = nanoid();
field.name = column.name;
field.type = column.type.type_name.toUpperCase();
- field.default = column.dbdefault ?? "";
+ field.default = column.dbdefault?.value ?? "";
field.check = "";
field.primary = !!column.pk;
field.unique = !!column.pk;
diff --git a/src/utils/issues.js b/src/utils/issues.js
index ceb25c72..d5f54c0f 100644
--- a/src/utils/issues.js
+++ b/src/utils/issues.js
@@ -7,7 +7,12 @@ function checkDefault(field, database) {
if (isFunction(field.default)) return true;
- if (!field.notNull && field.default.toLowerCase() === "null") return true;
+ if (
+ !field.notNull &&
+ typeof field.default === "string" &&
+ field.default.toLowerCase() === "null"
+ )
+ return true;
if (!dbToTypes[database][field.type].checkDefault) return true;
diff --git a/src/utils/utils.js b/src/utils/utils.js
index 553c3401..1d93e7a1 100644
--- a/src/utils/utils.js
+++ b/src/utils/utils.js
@@ -30,7 +30,8 @@ export function strHasQuotes(str) {
const keywords = ["CURRENT_TIMESTAMP", "NULL"];
export function isKeyword(str) {
- return keywords.includes(str.toUpperCase());
+ if (typeof str === "string") return keywords.includes(str.toUpperCase());
+ return false;
}
export function isFunction(str) {