diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml new file mode 100644 index 0000000..a17ed84 --- /dev/null +++ b/.github/FUNDING.yml @@ -0,0 +1 @@ +open_collective: drawdb \ No newline at end of file diff --git a/src/components/EditorHeader/SideSheet/Todo.jsx b/src/components/EditorHeader/SideSheet/Todo.jsx index fd53196..6f000dd 100644 --- a/src/components/EditorHeader/SideSheet/Todo.jsx +++ b/src/components/EditorHeader/SideSheet/Todo.jsx @@ -247,7 +247,7 @@ export default function Todo() { diff --git a/src/components/EditorSidePanel/AreasTab/AreasTab.jsx b/src/components/EditorSidePanel/AreasTab/AreasTab.jsx index 0801a9e..db28c7b 100644 --- a/src/components/EditorSidePanel/AreasTab/AreasTab.jsx +++ b/src/components/EditorSidePanel/AreasTab/AreasTab.jsx @@ -15,7 +15,7 @@ export default function AreasTab() {
-
diff --git a/src/components/EditorSidePanel/NotesTab/NoteInfo.jsx b/src/components/EditorSidePanel/NotesTab/NoteInfo.jsx index 8ceee8e..ccf1859 100644 --- a/src/components/EditorSidePanel/NotesTab/NoteInfo.jsx +++ b/src/components/EditorSidePanel/NotesTab/NoteInfo.jsx @@ -98,7 +98,7 @@ export default function NoteInfo({ data, nid }) {
} diff --git a/src/components/EditorSidePanel/TablesTab/SearchBar.jsx b/src/components/EditorSidePanel/TablesTab/SearchBar.jsx index ab0f35d..bcaec05 100644 --- a/src/components/EditorSidePanel/TablesTab/SearchBar.jsx +++ b/src/components/EditorSidePanel/TablesTab/SearchBar.jsx @@ -1,40 +1,64 @@ -import { useMemo, useState } from "react"; +import { useMemo } from "react"; import { useSelect } from "../../../hooks"; -import { AutoComplete } from "@douyinfe/semi-ui"; +import { TreeSelect } from "@douyinfe/semi-ui"; import { IconSearch } from "@douyinfe/semi-icons"; import { ObjectType } from "../../../data/constants"; import { useTranslation } from "react-i18next"; export default function SearchBar({ tables }) { const { setSelectedElement } = useSelect(); - const [searchText, setSearchText] = useState(""); const { t } = useTranslation(); - const filteredTable = useMemo( - () => tables.map((t) => t.name).filter((i) => i.includes(searchText)), - [tables, searchText], - ); + + const treeData = useMemo(() => { + return tables.map(({ id, name: parentName, fields }, i) => { + const children = fields.map(({ name }, j) => ({ + tableId: id, + id: `${j}`, + label: name, + value: name, + key: `${i}-${j}`, + })); + + return { + tableId: id, + id: `${i}`, + label: parentName, + value: parentName, + key: `${i}`, + children, + }; + }); + }, [tables]); return ( - } - placeholder={t("search")} emptyContent={
{t("not_found")}
} - onChange={(v) => setSearchText(v)} - onSelect={(v) => { - const { id } = tables.find((t) => t.name === v); + filterTreeNode + placeholder={t("search")} + onChange={(node) => { + const { tableId, id, children } = node; + setSelectedElement((prev) => ({ ...prev, - id: id, + id: tableId, open: true, element: ObjectType.TABLE, })); document - .getElementById(`scroll_table_${id}`) + .getElementById(`scroll_table_${tableId}`) .scrollIntoView({ behavior: "smooth" }); + + if (!children) { + document + .getElementById(`scroll_table_${tableId}_input_${id}`) + .focus(); + } }} + onChangeWithObject className="w-full" /> ); diff --git a/src/components/EditorSidePanel/TablesTab/TableField.jsx b/src/components/EditorSidePanel/TablesTab/TableField.jsx index d8c9d9f..9c68759 100644 --- a/src/components/EditorSidePanel/TablesTab/TableField.jsx +++ b/src/components/EditorSidePanel/TablesTab/TableField.jsx @@ -20,8 +20,9 @@ export default function TableField({ data, tid, index }) { updateField(tid, index, { name: value })} onFocus={(e) => setEditField({ name: e.target.value })} diff --git a/src/components/EditorSidePanel/TablesTab/TableInfo.jsx b/src/components/EditorSidePanel/TablesTab/TableInfo.jsx index 5e5b42e..05a61b5 100644 --- a/src/components/EditorSidePanel/TablesTab/TableInfo.jsx +++ b/src/components/EditorSidePanel/TablesTab/TableInfo.jsx @@ -33,7 +33,7 @@ export default function TableInfo({ data }) {
{t("name")}:
updateTable(data.id, { name: value })} @@ -290,7 +290,7 @@ export default function TableInfo({ data }) { ...data.indices, { id: data.indices.length, - name: `index_${data.indices.length}`, + name: `${data.name}_index_${data.indices.length}`, unique: false, fields: [], }, diff --git a/src/components/EditorSidePanel/TablesTab/TablesTab.jsx b/src/components/EditorSidePanel/TablesTab/TablesTab.jsx index 1361aa8..2f1ea91 100644 --- a/src/components/EditorSidePanel/TablesTab/TablesTab.jsx +++ b/src/components/EditorSidePanel/TablesTab/TablesTab.jsx @@ -46,10 +46,17 @@ export default function TablesTab() { {tables.map((t) => (
- {t.name} -
+ <> +
+ {t.name} +
+
+ } itemKey={`${t.id}`} > diff --git a/src/i18n/locales/en.js b/src/i18n/locales/en.js index 2a438a4..11acde0 100644 --- a/src/i18n/locales/en.js +++ b/src/i18n/locales/en.js @@ -226,6 +226,7 @@ const en = { no_enums: "No enums", no_enums_text: "Define enums here", declare_array: "Declare array", + empty_index_name: "Declared an index with no name in table '{{tableName}}'", }, }; diff --git a/src/utils/exportSQL/generic.js b/src/utils/exportSQL/generic.js index 8663140..16427bc 100644 --- a/src/utils/exportSQL/generic.js +++ b/src/utils/exportSQL/generic.js @@ -176,14 +176,14 @@ export function jsonToMySQL(obj) { : "" }\n)${table.comment ? ` COMMENT='${table.comment}'` : ""};\n${ table.indices.length > 0 - ? `\n${table.indices.map( - (i) => - `\nCREATE ${i.unique ? "UNIQUE " : ""}INDEX \`${ - i.name - }\`\nON \`${table.name}\` (${i.fields - .map((f) => `\`${f}\``) - .join(", ")});`, - )}` + ? `\n${table.indices + .map( + (i) => + `CREATE ${i.unique ? "UNIQUE " : ""}INDEX \`${i.name}\`\nON \`${table.name}\` (${i.fields + .map((f) => `\`${f}\``) + .join(", ")});`, + ) + .join("\n")}` : "" }`, ) @@ -251,10 +251,8 @@ export function jsonToPostgreSQL(obj) { field.name }" ${getTypeString(field, obj.database, "postgres")}${ field.notNull ? " NOT NULL" : "" - }${ - field.default !== "" - ? ` DEFAULT ${parseDefault(field, obj.database)}` - : "" + }${field.unique ? " UNIQUE" : ""}${ + field.default !== "" ? ` DEFAULT ${parseDefault(field)}` : "" }${ field.check === "" || !dbToTypes[obj.database][field.type].hasCheck @@ -271,14 +269,16 @@ export function jsonToPostgreSQL(obj) { : "" }\n);\n${ table.indices.length > 0 - ? `${table.indices.map( - (i) => - `\nCREATE ${i.unique ? "UNIQUE " : ""}INDEX "${ - i.name - }"\nON "${table.name}" (${i.fields - .map((f) => `"${f}"`) - .join(", ")});`, - )}` + ? `${table.indices + .map( + (i) => + `CREATE ${i.unique ? "UNIQUE " : ""}INDEX "${ + i.name + }"\nON "${table.name}" (${i.fields + .map((f) => `"${f}"`) + .join(", ")});`, + ) + .join("\n")}` : "" }`, ) @@ -426,14 +426,16 @@ export function jsonToMariaDB(obj) { : "" }\n);${ table.indices.length > 0 - ? `\n${table.indices.map( - (i) => - `\nCREATE ${i.unique ? "UNIQUE " : ""}INDEX \`${ - i.name - }\`\nON \`${table.name}\` (${i.fields - .map((f) => `\`${f}\``) - .join(", ")});`, - )}` + ? `\n${table.indices + .map( + (i) => + `CREATE ${i.unique ? "UNIQUE " : ""}INDEX \`${ + i.name + }\`\nON \`${table.name}\` (${i.fields + .map((f) => `\`${f}\``) + .join(", ")});`, + ) + .join("\n")}` : "" }`, ) diff --git a/src/utils/issues.js b/src/utils/issues.js index ffffbf1..6b3db61 100644 --- a/src/utils/issues.js +++ b/src/utils/issues.js @@ -99,6 +99,13 @@ export function getIssues(diagram) { }); table.indices.forEach((index) => { + if (index.name.trim() === "") { + issues.push( + i18n.t("empty_index_name", { + tableName: table.name, + }), + ); + } if (index.fields.length === 0) { issues.push( i18n.t("empty_index", { diff --git a/src/utils/modalTitles.js b/src/utils/modalTitles.js index 6501aa0..2887aae 100644 --- a/src/utils/modalTitles.js +++ b/src/utils/modalTitles.js @@ -7,7 +7,7 @@ export const getModalTitle = (modal) => { case MODAL.IMPORT_SRC: return i18n.t("import_diagram"); case MODAL.CODE: - return i18n.t("export_source"); + return i18n.t("export"); case MODAL.IMG: return i18n.t("export_image"); case MODAL.RENAME: