diff --git a/src/components/EditorCanvas/Canvas.jsx b/src/components/EditorCanvas/Canvas.jsx index d96433dee..d4ceecbfc 100644 --- a/src/components/EditorCanvas/Canvas.jsx +++ b/src/components/EditorCanvas/Canvas.jsx @@ -31,6 +31,7 @@ import { useEventListener } from "usehooks-ts"; import { areFieldsCompatible, getTableHeight } from "../../utils/utils"; import { getRectFromEndpoints, isInsideRect } from "../../utils/rect"; import { State, noteWidth } from "../../data/constants"; +import { nanoid } from "nanoid"; export default function Canvas() { const { t } = useTranslation(); @@ -622,7 +623,7 @@ export default function Canvas() { updateConstraint: Constraint.NONE, deleteConstraint: Constraint.NONE, name: `fk_${startTableName}_${startField.name}_${endTableName}`, - id: relationships.length, + id: nanoid(), }; delete newRelationship.startX; delete newRelationship.startY; diff --git a/src/components/EditorHeader/ControlPanel.jsx b/src/components/EditorHeader/ControlPanel.jsx index 5cea90ed0..99635aed6 100644 --- a/src/components/EditorHeader/ControlPanel.jsx +++ b/src/components/EditorHeader/ControlPanel.jsx @@ -163,7 +163,7 @@ export default function ControlPanel({ } else if (a.element === ObjectType.NOTE) { deleteNote(notes[notes.length - 1].id, false); } else if (a.element === ObjectType.RELATIONSHIP) { - deleteRelationship(a.data.id, false); + deleteRelationship(a.data.relationship.id, false); } else if (a.element === ObjectType.TYPE) { deleteType(types.length - 1, false); } else if (a.element === ObjectType.ENUM) { @@ -361,7 +361,7 @@ export default function ControlPanel({ if (a.element === ObjectType.TABLE) { deleteTable(a.data.table.id, false); } else if (a.element === ObjectType.RELATIONSHIP) { - deleteRelationship(a.data.id, false); + deleteRelationship(a.data.relationship.id, false); } else if (a.element === ObjectType.NOTE) { deleteNote(a.data.id, false); } else if (a.element === ObjectType.AREA) { diff --git a/src/components/EditorSidePanel/RelationshipsTab/RelationshipsTab.jsx b/src/components/EditorSidePanel/RelationshipsTab/RelationshipsTab.jsx index ac2a058dc..537db7cda 100644 --- a/src/components/EditorSidePanel/RelationshipsTab/RelationshipsTab.jsx +++ b/src/components/EditorSidePanel/RelationshipsTab/RelationshipsTab.jsx @@ -1,14 +1,18 @@ import { Collapse } from "@douyinfe/semi-ui"; -import { useSelect, useDiagram } from "../../../hooks"; +import { useSelect, useDiagram, useSaveState, useLayout } from "../../../hooks"; import Empty from "../Empty"; import SearchBar from "./SearchBar"; import RelationshipInfo from "./RelationshipInfo"; -import { ObjectType } from "../../../data/constants"; +import { ObjectType, State } from "../../../data/constants"; import { useTranslation } from "react-i18next"; +import { SortableList } from "../../SortableList/SortableList"; +import { DragHandle } from "../../SortableList/DragHandle"; export default function RelationshipsTab() { - const { relationships } = useDiagram(); + const { relationships, setRelationships } = useDiagram(); const { selectedElement, setSelectedElement } = useSelect(); + const { setSaveState } = useSaveState(); + const { layout } = useLayout(); const { t } = useTranslation(); return ( @@ -29,30 +33,40 @@ export default function RelationshipsTab() { } keepDOM={false} lazyRender - onChange={(k) => + onChange={(k) => { setSelectedElement((prev) => ({ ...prev, open: true, - id: parseInt(k), + id: k[0], element: ObjectType.RELATIONSHIP, - })) - } + })); + }} accordion > - {relationships.map((r) => ( -
- - {r.name} -
- } - itemKey={`${r.id}`} - > - - - - ))} + setRelationships(newRelationships)} + afterChange={() => setSaveState(State.SAVING)} + renderItem={(item) => ( +
+ + +
+ {item.name} +
+
+ } + itemKey={`${item.id}`} + > + + + + )} + /> )} diff --git a/src/context/DiagramContext.jsx b/src/context/DiagramContext.jsx index eb43016c4..b554cb2be 100644 --- a/src/context/DiagramContext.jsx +++ b/src/context/DiagramContext.jsx @@ -183,7 +183,10 @@ export default function DiagramContextProvider({ children }) { { action: Action.ADD, element: ObjectType.RELATIONSHIP, - data: data, + data: { + relationship: data, + index: prevUndo.length + }, message: t("add_relationship"), }, ]); @@ -193,30 +196,32 @@ export default function DiagramContextProvider({ children }) { } else { setRelationships((prev) => { const temp = prev.slice(); - temp.splice(data.id, 0, data); - return temp.map((t, i) => ({ ...t, id: i })); + temp.splice(data.index, 0, data.relationship || data); + return temp; }); } }; const deleteRelationship = (id, addToHistory = true) => { if (addToHistory) { + const relationshipIndex = relationships.findIndex((r) => r.id === id); setUndoStack((prev) => [ ...prev, { action: Action.DELETE, element: ObjectType.RELATIONSHIP, - data: relationships[id], + data: { + relationship: relationships[relationshipIndex], + index: relationshipIndex, + }, message: t("delete_relationship", { - refName: relationships[id].name, + refName: relationships[relationshipIndex].name, }), }, ]); setRedoStack([]); } - setRelationships((prev) => - prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i })), - ); + setRelationships((prev) => prev.filter((e) => e.id !== id)); }; const updateRelationship = (id, updatedValues) => { diff --git a/src/utils/importFrom/dbml.js b/src/utils/importFrom/dbml.js index 2bb448cbc..08cb6b4c8 100644 --- a/src/utils/importFrom/dbml.js +++ b/src/utils/importFrom/dbml.js @@ -82,7 +82,7 @@ export function fromDBML(src) { relationship.endTableId = endTable.id; relationship.endFieldId = endField.id; relationship.startFieldId = startField.id; - relationship.id = relationships.length; + relationship.id = nanoid(); relationship.updateConstraint = ref.onDelete ? ref.onDelete[0].toUpperCase() + ref.onDelete.substring(1) diff --git a/src/utils/importSQL/mariadb.js b/src/utils/importSQL/mariadb.js index 4f06f3769..b3a2a85e2 100644 --- a/src/utils/importSQL/mariadb.js +++ b/src/utils/importSQL/mariadb.js @@ -133,6 +133,7 @@ export function fromMariaDB(ast, diagramDb = DB.GENERIC) { relationship.endTableId = endTable.id; relationship.endFieldId = endField.id; relationship.startFieldId = startField.id; + relationship.id = nanoid() let updateConstraint = "No action"; let deleteConstraint = "No action"; d.reference_definition.on_action.forEach((c) => { @@ -240,6 +241,7 @@ export function fromMariaDB(ast, diagramDb = DB.GENERIC) { relationship.endFieldId = endField.id; relationship.updateConstraint = updateConstraint; relationship.deleteConstraint = deleteConstraint; + relationship.id = nanoid(); if (startField.unique) { relationship.cardinality = Cardinality.ONE_TO_ONE; @@ -248,8 +250,6 @@ export function fromMariaDB(ast, diagramDb = DB.GENERIC) { } relationships.push(relationship); - - relationships.forEach((r, i) => (r.id = i)); } }); } @@ -261,7 +261,5 @@ export function fromMariaDB(ast, diagramDb = DB.GENERIC) { parseSingleStatement(ast); } - relationships.forEach((r, i) => (r.id = i)); - return { tables, relationships }; } diff --git a/src/utils/importSQL/mssql.js b/src/utils/importSQL/mssql.js index eff847a39..0decdaa58 100644 --- a/src/utils/importSQL/mssql.js +++ b/src/utils/importSQL/mssql.js @@ -145,6 +145,8 @@ export function fromMSSQL(ast, diagramDb = DB.GENERIC) { relationship.endTableId = endTable.id; relationship.endFieldId = endField.id; relationship.startFieldId = startField.id; + relationship.id = nanoid(); + let updateConstraint = "No action"; let deleteConstraint = "No action"; d.reference_definition.on_action.forEach((c) => { @@ -244,6 +246,7 @@ export function fromMSSQL(ast, diagramDb = DB.GENERIC) { relationship.endFieldId = endField.id; relationship.updateConstraint = updateConstraint; relationship.deleteConstraint = deleteConstraint; + relationship.id = nanoid(); if (startField.unique) { relationship.cardinality = Cardinality.ONE_TO_ONE; @@ -252,8 +255,6 @@ export function fromMSSQL(ast, diagramDb = DB.GENERIC) { } relationships.push(relationship); - - relationships.forEach((r, i) => (r.id = i)); } }); } diff --git a/src/utils/importSQL/mysql.js b/src/utils/importSQL/mysql.js index c1d70a3ae..dfc878cc9 100644 --- a/src/utils/importSQL/mysql.js +++ b/src/utils/importSQL/mysql.js @@ -132,6 +132,8 @@ export function fromMySQL(ast, diagramDb = DB.GENERIC) { relationship.endTableId = endTable.id; relationship.endFieldId = endField.id; relationship.startFieldId = startField.id; + relationship.id = nanoid(); + let updateConstraint = "No action"; let deleteConstraint = "No action"; d.reference_definition.on_action.forEach((c) => { @@ -238,6 +240,7 @@ export function fromMySQL(ast, diagramDb = DB.GENERIC) { relationship.endFieldId = endField.id; relationship.updateConstraint = updateConstraint; relationship.deleteConstraint = deleteConstraint; + relationship.id = nanoid(); if (startField.unique) { relationship.cardinality = Cardinality.ONE_TO_ONE; @@ -246,8 +249,6 @@ export function fromMySQL(ast, diagramDb = DB.GENERIC) { } relationships.push(relationship); - - relationships.forEach((r, i) => (r.id = i)); } }); } @@ -259,7 +260,5 @@ export function fromMySQL(ast, diagramDb = DB.GENERIC) { parseSingleStatement(ast); } - relationships.forEach((r, i) => (r.id = i)); - return { tables, relationships }; } diff --git a/src/utils/importSQL/oraclesql.js b/src/utils/importSQL/oraclesql.js index de76814e5..40da5a58b 100644 --- a/src/utils/importSQL/oraclesql.js +++ b/src/utils/importSQL/oraclesql.js @@ -98,6 +98,7 @@ export function fromOracleSQL(ast, diagramDb = DB.GENERIC) { ); if (!startField) return; + relationship.id = nanoid(); relationship.startTableId = table.id; relationship.startFieldId = startField.id; relationship.endTableId = endTable.id; @@ -130,7 +131,5 @@ export function fromOracleSQL(ast, diagramDb = DB.GENERIC) { ast.forEach((e) => parseSingleStatement(e)); - relationships.forEach((r, i) => (r.id = i)); - return { tables, relationships, enums }; } diff --git a/src/utils/importSQL/postgres.js b/src/utils/importSQL/postgres.js index 2e741145e..2be4d5c90 100644 --- a/src/utils/importSQL/postgres.js +++ b/src/utils/importSQL/postgres.js @@ -152,6 +152,8 @@ export function fromPostgres(ast, diagramDb = DB.GENERIC) { relationship.endTableId = endTable.id; relationship.endFieldId = endField.id; relationship.startFieldId = startField.id; + relationship.id = nanoid(); + let updateConstraint = Constraint.NONE; let deleteConstraint = Constraint.NONE; d.reference_definition.on_action.forEach((c) => { @@ -224,6 +226,7 @@ export function fromPostgres(ast, diagramDb = DB.GENERIC) { relationship.endFieldId = endField.id; relationship.updateConstraint = updateConstraint; relationship.deleteConstraint = deleteConstraint; + relationship.id = nanoid(); if (startField.unique) { relationship.cardinality = Cardinality.ONE_TO_ONE; @@ -232,8 +235,6 @@ export function fromPostgres(ast, diagramDb = DB.GENERIC) { } relationships.push(relationship); - - relationships.forEach((r, i) => (r.id = i)); } }); tables.push(table); @@ -347,6 +348,7 @@ export function fromPostgres(ast, diagramDb = DB.GENERIC) { relationship.updateConstraint = updateConstraint; relationship.deleteConstraint = deleteConstraint; relationship.cardinality = Cardinality.ONE_TO_ONE; + relationship.id = nanoid(); if (startField.unique) { relationship.cardinality = Cardinality.ONE_TO_ONE; @@ -355,8 +357,6 @@ export function fromPostgres(ast, diagramDb = DB.GENERIC) { } relationships.push(relationship); - - relationships.forEach((r, i) => (r.id = i)); } }); } @@ -369,7 +369,5 @@ export function fromPostgres(ast, diagramDb = DB.GENERIC) { parseSingleStatement(ast); } - relationships.forEach((r, i) => (r.id = i)); - return { tables, relationships, types, enums }; } diff --git a/src/utils/importSQL/sqlite.js b/src/utils/importSQL/sqlite.js index ecb07d9de..5ef6303e7 100644 --- a/src/utils/importSQL/sqlite.js +++ b/src/utils/importSQL/sqlite.js @@ -65,6 +65,8 @@ export function fromSQLite(ast, diagramDb = DB.GENERIC) { relationship.endTableId = endTable.id; relationship.endFieldId = endField.id; relationship.startFieldId = startField.id; + relationship.id = nanoid(); + let updateConstraint = "No action"; let deleteConstraint = "No action"; referenceDefinition.on_action.forEach((c) => { @@ -215,7 +217,5 @@ export function fromSQLite(ast, diagramDb = DB.GENERIC) { parseSingleStatement(ast); } - relationships.forEach((r, i) => (r.id = i)); - return { tables, relationships }; }