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) => (
+
+ }
+ 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 };
}