Use nanoid instead of numberic ids for fields and tables

This commit is contained in:
1ilit 2025-05-11 20:48:03 +04:00
parent 9c40ae31f0
commit a1c60af3cd
20 changed files with 171 additions and 241 deletions

31
package-lock.json generated
View File

@ -30,6 +30,7 @@
"jspdf": "^3.0.1",
"jszip": "^3.10.1",
"lexical": "^0.12.5",
"nanoid": "^5.1.5",
"node-sql-parser": "^5.3.8",
"oracle-sql-parser": "^0.1.0",
"react": "^18.2.0",
@ -6235,10 +6236,9 @@
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"dev": true,
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz",
"integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==",
"funding": [
{
"type": "github",
@ -6247,10 +6247,10 @@
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
"node": "^18 || >=20"
}
},
"node_modules/natural-compare": {
@ -6592,6 +6592,25 @@
"node": "^10 || ^12 || >=14"
}
},
"node_modules/postcss/node_modules/nanoid": {
"version": "3.3.11",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
"integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"license": "MIT",
"bin": {
"nanoid": "bin/nanoid.cjs"
},
"engines": {
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",

View File

@ -32,6 +32,7 @@
"jspdf": "^3.0.1",
"jszip": "^3.10.1",
"lexical": "^0.12.5",
"nanoid": "^5.1.5",
"node-sql-parser": "^5.3.8",
"oracle-sql-parser": "^0.1.0",
"react": "^18.2.0",

View File

@ -55,7 +55,7 @@ export default function Canvas() {
} = useSelect();
const [dragging, setDragging] = useState({
element: ObjectType.NONE,
id: -1,
id: null,
prevX: 0,
prevY: 0,
initialPositions: [],
@ -73,8 +73,8 @@ export default function Canvas() {
});
const [grabOffset, setGrabOffset] = useState({ x: 0, y: 0 });
const [hoveredTable, setHoveredTable] = useState({
tableId: -1,
field: -2,
tableId: null,
fieldId: null,
});
const [panning, setPanning] = useState({
isPanning: false,
@ -264,7 +264,7 @@ export default function Canvas() {
});
} else if (
dragging.element !== ObjectType.NONE &&
dragging.id >= 0 &&
dragging.id !== null &&
bulkSelectedElements.length
) {
const currentX = pointer.spaces.diagram.x + grabOffset.x;
@ -318,21 +318,21 @@ export default function Canvas() {
(panning.cursorStart.y - pointer.spaces.screen.y) / transform.zoom,
},
}));
} else if (dragging.element === ObjectType.TABLE && dragging.id >= 0) {
} else if (dragging.element === ObjectType.TABLE && dragging.id !== null) {
updateTable(dragging.id, {
x: pointer.spaces.diagram.x + grabOffset.x,
y: pointer.spaces.diagram.y + grabOffset.y,
});
} else if (
dragging.element === ObjectType.AREA &&
dragging.id >= 0 &&
dragging.id !== null &&
areaResize.id === -1
) {
updateArea(dragging.id, {
x: pointer.spaces.diagram.x + grabOffset.x,
y: pointer.spaces.diagram.y + grabOffset.y,
});
} else if (dragging.element === ObjectType.NOTE && dragging.id >= 0) {
} else if (dragging.element === ObjectType.NOTE && dragging.id !== null) {
updateNote(dragging.id, {
x: pointer.spaces.diagram.x + grabOffset.x,
y: pointer.spaces.diagram.y + grabOffset.y,
@ -598,8 +598,8 @@ export default function Canvas() {
};
const handleLinking = () => {
if (hoveredTable.tableId < 0) return;
if (hoveredTable.field < 0) return;
if (hoveredTable.tableId === null) return;
if (hoveredTable.fieldId === null) return;
const { fields: startTableFields, name: startTableName } = tables.find(
(t) => t.id === linkingLine.startTableId,
@ -611,7 +611,7 @@ export default function Canvas() {
(t) => t.id === hoveredTable.tableId,
);
const { type: endType } = endTableFields.find(
(f) => f.id === hoveredTable.field,
(f) => f.id === hoveredTable.fieldId,
);
if (!areFieldsCompatible(database, startType, endType)) {
@ -620,14 +620,14 @@ export default function Canvas() {
}
if (
linkingLine.startTableId === hoveredTable.tableId &&
linkingLine.startFieldId === hoveredTable.field
linkingLine.startFieldId === hoveredTable.fieldId
)
return;
const newRelationship = {
...linkingLine,
endTableId: hoveredTable.tableId,
endFieldId: hoveredTable.field,
endFieldId: hoveredTable.fieldId,
cardinality: Cardinality.ONE_TO_ONE,
updateConstraint: Constraint.NONE,
deleteConstraint: Constraint.NONE,

View File

@ -22,7 +22,7 @@ import { isRtl } from "../../i18n/utils/rtl";
import i18n from "../../i18n/i18n";
export default function Table(props) {
const [hoveredField, setHoveredField] = useState(-1);
const [hoveredField, setHoveredField] = useState(null);
const { database } = useDiagram();
const {
tableData,
@ -45,9 +45,10 @@ export default function Table(props) {
const height =
tableData.fields.length * tableFieldHeight + tableHeaderHeight + 7;
const isSelected = useMemo(() => {
return (
(selectedElement.id === tableData.id &&
(selectedElement.id == tableData.id &&
selectedElement.element === ObjectType.TABLE) ||
bulkSelectedElements.some(
(e) => e.type === ObjectType.TABLE && e.id === tableData.id,
@ -124,7 +125,7 @@ export default function Table(props) {
onClick={openEditor}
/>
<Popover
key={tableData.key}
key={tableData.id}
content={
<div className="popover-theme">
<div className="mb-2">
@ -304,13 +305,17 @@ export default function Table(props) {
setHoveredField(index);
setHoveredTable({
tableId: tableData.id,
field: fieldData.id,
fieldId: fieldData.id,
});
}}
onPointerLeave={(e) => {
if (!e.isPrimary) return;
setHoveredField(-1);
setHoveredField(null);
setHoveredTable({
tableId: null,
fieldId: null,
});
}}
onPointerDown={(e) => {
// Required for onPointerLeave to trigger when a touch pointer leaves

View File

@ -78,6 +78,7 @@ import { IdContext } from "../Workspace";
import { socials } from "../../data/socials";
import { toDBML } from "../../utils/exportAs/dbml";
import { exportSavedData } from "../../utils/exportSavedData";
import { nanoid } from "nanoid";
export default function ControlPanel({
diagramId,
@ -150,7 +151,7 @@ export default function ControlPanel({
if (a.action === Action.ADD) {
if (a.element === ObjectType.TABLE) {
deleteTable(tables[tables.length - 1].id, false);
deleteTable(a.id, false);
} else if (a.element === ObjectType.AREA) {
deleteArea(areas[areas.length - 1].id, false);
} else if (a.element === ObjectType.NOTE) {
@ -165,10 +166,8 @@ export default function ControlPanel({
setRedoStack((prev) => [...prev, a]);
} else if (a.action === Action.MOVE) {
if (a.element === ObjectType.TABLE) {
setRedoStack((prev) => [
...prev,
{ ...a, x: tables[a.id].x, y: tables[a.id].y },
]);
const { x, y } = tables.find((t) => t.id === a.id);
setRedoStack((prev) => [...prev, { ...a, x, y }]);
updateTable(a.id, { x: a.x, y: a.y });
} else if (a.element === ObjectType.AREA) {
setRedoStack((prev) => [
@ -205,6 +204,7 @@ export default function ControlPanel({
} else if (a.element === ObjectType.NOTE) {
updateNote(a.nid, a.undo);
} else if (a.element === ObjectType.TABLE) {
const table = tables.find((t) => t.id === a.tid);
if (a.component === "field") {
updateField(a.tid, a.fid, a.undo);
} else if (a.component === "field_delete") {
@ -213,65 +213,24 @@ export default function ControlPanel({
a.data.relationship.forEach((r) => {
temp.splice(r.id, 0, r);
});
temp = temp.map((e, i) => {
const recoveredRel = a.data.relationship.find(
(x) =>
(x.startTableId === e.startTableId &&
x.startFieldId === e.startFieldId) ||
(x.endTableId === e.endTableId &&
x.endFieldId === a.endFieldId),
);
if (
e.startTableId === a.tid &&
e.startFieldId >= a.data.field.id &&
!recoveredRel
) {
return {
...e,
id: i,
startFieldId: e.startFieldId + 1,
};
}
if (
e.endTableId === a.tid &&
e.endFieldId >= a.data.field.id &&
!recoveredRel
) {
return {
...e,
id: i,
endFieldId: e.endFieldId + 1,
};
}
return { ...e, id: i };
});
return temp;
});
setTables((prev) =>
prev.map((t) => {
if (t.id === a.tid) {
const temp = t.fields.slice();
temp.splice(a.data.field.id, 0, a.data.field);
return { ...t, fields: temp.map((t, i) => ({ ...t, id: i })) };
}
return t;
}),
);
const updatedFields = table.fields.slice();
updatedFields.splice(a.data.index, 0, a.data.field);
updateTable(a.tid, { fields: updatedFields });
} else if (a.component === "field_add") {
updateTable(a.tid, {
fields: tables[a.tid].fields
.filter((e) => e.id !== tables[a.tid].fields.length - 1)
.map((t, i) => ({ ...t, id: i })),
fields: table.fields.filter((e) => e.id !== a.fid),
});
} else if (a.component === "index_add") {
updateTable(a.tid, {
indices: tables[a.tid].indices
.filter((e) => e.id !== tables[a.tid].indices.length - 1)
indices: table.indices
.filter((e) => e.id !== table.indices.length - 1)
.map((t, i) => ({ ...t, id: i })),
});
} else if (a.component === "index") {
updateTable(a.tid, {
indices: tables[a.tid].indices.map((index) =>
indices: table.indices.map((index) =>
index.id === a.iid
? {
...index,
@ -281,19 +240,11 @@ export default function ControlPanel({
),
});
} else if (a.component === "index_delete") {
setTables((prev) =>
prev.map((table) => {
if (table.id === a.tid) {
const temp = table.indices.slice();
temp.splice(a.data.id, 0, a.data);
return {
...table,
indices: temp.map((t, i) => ({ ...t, id: i })),
};
}
return table;
}),
);
const updatedIndices = table.indices.slice();
updatedIndices.splice(a.data.id, 0, a.data);
updateTable(a.tid, {
indices: updatedIndices.map((t, i) => ({ ...t, id: i })),
});
} else if (a.component === "self") {
updateTable(a.tid, a.undo);
}
@ -390,10 +341,8 @@ export default function ControlPanel({
setUndoStack((prev) => [...prev, a]);
} else if (a.action === Action.MOVE) {
if (a.element === ObjectType.TABLE) {
setUndoStack((prev) => [
...prev,
{ ...a, x: tables[a.id].x, y: tables[a.id].y },
]);
const { x, y } = tables.find((t) => t.id == a.id);
setUndoStack((prev) => [...prev, { ...a, x, y }]);
updateTable(a.id, { x: a.x, y: a.y });
} else if (a.element === ObjectType.AREA) {
setUndoStack((prev) => [
@ -429,6 +378,7 @@ export default function ControlPanel({
} else if (a.element === ObjectType.NOTE) {
updateNote(a.nid, a.redo);
} else if (a.element === ObjectType.TABLE) {
const table = tables.find((t) => t.id === a.tid);
if (a.component === "field") {
updateField(a.tid, a.fid, a.redo);
} else if (a.component === "field_delete") {
@ -436,7 +386,7 @@ export default function ControlPanel({
} else if (a.component === "field_add") {
updateTable(a.tid, {
fields: [
...tables[a.tid].fields,
...table.fields,
{
name: "",
type: "",
@ -447,32 +397,24 @@ export default function ControlPanel({
notNull: false,
increment: false,
comment: "",
id: tables[a.tid].fields.length,
id: nanoid(),
},
],
});
} else if (a.component === "index_add") {
setTables((prev) =>
prev.map((table) => {
if (table.id === a.tid) {
return {
...table,
indices: [
...table.indices,
{
id: table.indices.length,
name: `index_${table.indices.length}`,
fields: [],
},
],
};
}
return table;
}),
);
updateTable(a.tid, {
indices: [
...table.indices,
{
id: table.indices.length,
name: `index_${table.indices.length}`,
fields: [],
},
],
});
} else if (a.component === "index") {
updateTable(a.tid, {
indices: tables[a.tid].indices.map((index) =>
indices: table.indices.map((index) =>
index.id === a.iid
? {
...index,
@ -483,7 +425,7 @@ export default function ControlPanel({
});
} else if (a.component === "index_delete") {
updateTable(a.tid, {
indices: tables[a.tid].indices
indices: table.indices
.filter((e) => e.id !== a.data.id)
.map((t, i) => ({ ...t, id: i })),
});

View File

@ -83,10 +83,12 @@ export default function ImportDiagram({
let ok = true;
jsonObject.relationships.forEach((rel) => {
if (
!jsonObject.tables.find(rel.startTableId) ||
!jsonObject.tables.find(rel.endTableId)
) {
const startTable = jsonObject.tables.find(
(t) => t.id === rel.startTableId,
);
const endTable = jsonObject.tables.find((t) => t.id === rel.endTableId);
if (!startTable || !endTable) {
setError({
type: STATUS.ERROR,
message: `Relationship ${rel.name} references a table that does not exist.`,
@ -96,10 +98,8 @@ export default function ImportDiagram({
}
if (
!jsonObject.tables
.find(rel.startTableId)
.fields.find(rel.startFieldId) ||
!jsonObject.tables.find(rel.endTableId).fields.find(rel.endFieldId)
!startTable.fields.find((f) => f.id === rel.startFieldId) ||
!endTable.fields.find((f) => f.id === rel.endFieldId)
) {
setError({
type: STATUS.ERROR,

View File

@ -59,8 +59,7 @@ export default function Modal({
importFrom,
}) {
const { t, i18n } = useTranslation();
const { tables, setTables, setRelationships, database, setDatabase } =
useDiagram();
const { setTables, setRelationships, database, setDatabase } = useDiagram();
const { setNotes } = useNotes();
const { setAreas } = useAreas();
const { setTypes } = useTypes();
@ -182,15 +181,10 @@ export default function Modal({
setUndoStack([]);
setRedoStack([]);
} else {
const initialTablesLength = tables.length;
setTables((prev) =>
[...prev, ...diagramData.tables].map((t, i) => ({ ...t, id: i })),
);
setTables((prev) => [...prev, ...diagramData.tables]);
setRelationships((prev) =>
[...prev, ...diagramData.relationships].map((r, i) => ({
...r,
startTableId: initialTablesLength + r.startTableId,
endTableId: initialTablesLength + r.endTableId,
id: i,
})),
);

View File

@ -31,6 +31,7 @@ export default function Share({ title, setModal }) {
const diagramToString = useCallback(() => {
return JSON.stringify({
title,
tables: tables,
relationships: relationships,
notes: notes,
@ -38,7 +39,6 @@ export default function Share({ title, setModal }) {
database: database,
...(databases[database].hasTypes && { types: types }),
...(databases[database].hasEnums && { enums: enums }),
title: title,
transform: transform,
});
}, [

View File

@ -14,7 +14,7 @@ import { useTranslation } from "react-i18next";
import { dbToTypes } from "../../../data/datatypes";
import { databases } from "../../../data/databases";
export default function FieldDetails({ data, tid, index }) {
export default function FieldDetails({ data, tid }) {
const { t } = useTranslation();
const { tables, database } = useDiagram();
const { setUndoStack, setRedoStack } = useUndoRedo();
@ -41,7 +41,7 @@ export default function FieldDetails({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: editField,
redo: { default: e.target.value },
message: t("edit_table", {
@ -81,7 +81,7 @@ export default function FieldDetails({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: editField,
redo: { values: data.values },
message: t("edit_table", {
@ -113,7 +113,7 @@ export default function FieldDetails({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: editField,
redo: { size: e.target.value },
message: t("edit_table", {
@ -150,7 +150,7 @@ export default function FieldDetails({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: editField,
redo: { size: e.target.value },
message: t("edit_table", {
@ -183,7 +183,7 @@ export default function FieldDetails({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: editField,
redo: { check: e.target.value },
message: t("edit_table", {
@ -211,7 +211,7 @@ export default function FieldDetails({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: {
[checkedValues.target.value]: !checkedValues.target.checked,
},
@ -243,7 +243,7 @@ export default function FieldDetails({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: {
[checkedValues.target.value]: !checkedValues.target.checked,
},
@ -278,7 +278,7 @@ export default function FieldDetails({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: {
[checkedValues.target.value]: !checkedValues.target.checked,
},
@ -315,7 +315,7 @@ export default function FieldDetails({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: {
[checkedValues.target.value]:
!checkedValues.target.checked,
@ -356,7 +356,7 @@ export default function FieldDetails({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: editField,
redo: { comment: e.target.value },
message: t("edit_table", {

View File

@ -38,7 +38,7 @@ export default function TableField({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: editField,
redo: { name: e.target.value },
message: t("edit_table", {
@ -81,7 +81,7 @@ export default function TableField({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: { type: data.type },
redo: { type: value },
message: t("edit_table", {
@ -148,7 +148,7 @@ export default function TableField({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: { notNull: data.notNull },
redo: { notNull: !data.notNull },
message: t("edit_table", {
@ -177,7 +177,7 @@ export default function TableField({ data, tid, index }) {
element: ObjectType.TABLE,
component: "field",
tid: tid,
fid: index,
fid: data.id,
undo: { primary: data.primary },
redo: { primary: !data.primary },
message: t("edit_table", {
@ -196,7 +196,7 @@ export default function TableField({ data, tid, index }) {
<Popover
content={
<div className="px-1 w-[240px] popover-theme">
<FieldDetails data={data} index={index} tid={tid} />
<FieldDetails data={data} tid={tid} />
</div>
}
trigger="click"

View File

@ -14,6 +14,7 @@ import TableField from "./TableField";
import IndexDetails from "./IndexDetails";
import { useTranslation } from "react-i18next";
import { SortableList } from "../../SortableList/SortableList";
import { nanoid } from "nanoid";
export default function TableInfo({ data }) {
const { t } = useTranslation();
@ -200,6 +201,7 @@ export default function TableInfo({ data }) {
</Button>
<Button
onClick={() => {
const id = nanoid();
setUndoStack((prev) => [
...prev,
{
@ -207,6 +209,7 @@ export default function TableInfo({ data }) {
element: ObjectType.TABLE,
component: "field_add",
tid: data.id,
fid: id,
message: t("edit_table", {
tableName: data.name,
extra: "[add field]",
@ -218,6 +221,7 @@ export default function TableInfo({ data }) {
fields: [
...data.fields,
{
id,
name: "",
type: "",
default: "",
@ -227,7 +231,6 @@ export default function TableInfo({ data }) {
notNull: false,
increment: false,
comment: "",
id: data.fields.length,
},
],
});

View File

@ -40,7 +40,7 @@ export default function TablesTab() {
setSelectedElement((prev) => ({
...prev,
open: true,
id: parseInt(k),
id: k[0],
element: ObjectType.TABLE,
}))
}

View File

@ -3,6 +3,7 @@ import { Action, DB, ObjectType, defaultBlue } from "../data/constants";
import { useTransform, useUndoRedo, useSelect } from "../hooks";
import { Toast } from "@douyinfe/semi-ui";
import { useTranslation } from "react-i18next";
import { nanoid } from "nanoid";
export const DiagramContext = createContext(null);
@ -16,17 +17,18 @@ export default function DiagramContextProvider({ children }) {
const { selectedElement, setSelectedElement } = useSelect();
const addTable = (data, addToHistory = true) => {
const id = nanoid();
if (data) {
setTables((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);
return temp;
});
} else {
setTables((prev) => [
...prev,
{
id: prev.length,
id,
name: `table_${prev.length}`,
x: transform.pan.x,
y: transform.pan.y,
@ -41,13 +43,12 @@ export default function DiagramContextProvider({ children }) {
notNull: true,
increment: true,
comment: "",
id: 0,
id: nanoid(),
},
],
comment: "",
indices: [],
color: defaultBlue,
key: Date.now(),
},
]);
}
@ -55,6 +56,7 @@ export default function DiagramContextProvider({ children }) {
setUndoStack((prev) => [
...prev,
{
id: data ? data.id : id,
action: Action.ADD,
element: ObjectType.TABLE,
message: t("add_table"),
@ -66,7 +68,6 @@ export default function DiagramContextProvider({ children }) {
const deleteTable = (id, addToHistory = true) => {
if (addToHistory) {
Toast.success(t("table_deleted"));
const rels = relationships.reduce((acc, r) => {
if (r.startTableId === id || r.endTableId === id) {
acc.push(r);
@ -74,41 +75,32 @@ export default function DiagramContextProvider({ children }) {
return acc;
}, []);
const deletedTable = tables.find((t) => t.id === id);
const deletedTableIndex = tables.findIndex((t) => t.id === id);
setUndoStack((prev) => [
...prev,
{
action: Action.DELETE,
element: ObjectType.TABLE,
data: { table: deletedTable, relationship: rels },
data: {
table: deletedTable,
relationship: rels,
index: deletedTableIndex,
},
message: t("delete_table", { tableName: deletedTable.name }),
},
]);
setRedoStack([]);
Toast.success(t("table_deleted"));
}
setRelationships((prevR) => {
return prevR
.filter((e) => !(e.startTableId === id || e.endTableId === id))
.map((e, i) => {
const newR = { ...e };
if (e.startTableId > id) {
newR.startTableId = e.startTableId - 1;
}
if (e.endTableId > id) {
newR.endTableId = e.endTableId - 1;
}
return { ...newR, id: i };
});
});
setTables((prev) => {
return prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i }));
});
setRelationships((prevR) =>
prevR.filter((e) => !(e.startTableId === id || e.endTableId === id)),
);
setTables((prev) => prev.filter((e) => e.id !== id));
if (id === selectedElement.id) {
setSelectedElement((prev) => ({
...prev,
element: ObjectType.NONE,
id: -1,
id: null,
open: false,
}));
}
@ -157,6 +149,7 @@ export default function DiagramContextProvider({ children }) {
tid: tid,
data: {
field: field,
index: fields.findIndex((f) => f.id === field.id),
relationship: rels,
},
message: t("edit_table", {
@ -167,40 +160,17 @@ export default function DiagramContextProvider({ children }) {
]);
setRedoStack([]);
}
setRelationships((prev) => {
const temp = prev
.filter(
(e) =>
!(
(e.startTableId === tid && e.startFieldId === field.id) ||
(e.endTableId === tid && e.endFieldId === field.id)
),
)
.map((e, i) => {
if (e.startTableId === tid && e.startFieldId > field.id) {
return {
...e,
startFieldId: e.startFieldId - 1,
id: i,
};
}
if (e.endTableId === tid && e.endFieldId > field.id) {
return {
...e,
endFieldId: e.endFieldId - 1,
id: i,
};
}
return { ...e, id: i };
});
return temp;
});
setRelationships((prev) =>
prev.filter(
(e) =>
!(
(e.startTableId === tid && e.startFieldId === field.id) ||
(e.endTableId === tid && e.endFieldId === field.id)
),
),
);
updateTable(tid, {
fields: fields
.filter((e) => e.id !== field.id)
.map((t, i) => {
return { ...t, id: i };
}),
fields: fields.filter((e) => e.id !== field.id),
});
};

View File

@ -1,3 +1,4 @@
import { nanoid } from "nanoid";
import { Cardinality, DB } from "../../data/constants";
import { dbToTypes } from "../../data/datatypes";
import { buildSQLFromAST } from "./shared";
@ -32,10 +33,11 @@ export function fromMariaDB(ast, diagramDb = DB.GENERIC) {
table.color = "#175e7a";
table.fields = [];
table.indices = [];
table.id = tables.length;
table.id = nanoid();
e.create_definitions.forEach((d) => {
if (d.resource === "column") {
const field = {};
field.id = nanoid();
field.name = d.column.column;
let type = d.definition.dataType;
@ -126,13 +128,7 @@ export function fromMariaDB(ast, diagramDb = DB.GENERIC) {
);
if (!startField) return;
relationship.name =
"fk_" +
startTableName +
"_" +
startFieldName +
"_" +
endTableName;
relationship.name = `fk_${startTableName}_${startFieldName}_${endTableName}`;
relationship.startTableId = startTableId;
relationship.endTableId = endTable.id;
relationship.endFieldId = endField.id;
@ -173,9 +169,6 @@ export function fromMariaDB(ast, diagramDb = DB.GENERIC) {
}
});
table.fields.forEach((f, j) => {
f.id = j;
});
tables.push(table);
} else if (e.keyword === "index") {
const index = {

View File

@ -1,3 +1,4 @@
import { nanoid } from "nanoid";
import { Cardinality, DB } from "../../data/constants";
import { dbToTypes } from "../../data/datatypes";
import { buildSQLFromAST } from "./shared";
@ -44,10 +45,11 @@ export function fromMSSQL(ast, diagramDb = DB.GENERIC) {
table.color = "#175e7a";
table.fields = [];
table.indices = [];
table.id = tables.length;
table.id = nanoid();
e.create_definitions.forEach((d) => {
if (d.resource === "column") {
const field = {};
field.id = nanoid();
field.name = d.column.column;
let type = d.definition.dataType;
@ -138,13 +140,7 @@ export function fromMSSQL(ast, diagramDb = DB.GENERIC) {
);
if (!startField) return;
relationship.name =
"fk_" +
startTableName +
"_" +
startFieldName +
"_" +
endTableName;
relationship.name = `fk_${startTableName}_${startFieldName}_${endTableName}`;
relationship.startTableId = startTableId;
relationship.endTableId = endTable.id;
relationship.endFieldId = endField.id;
@ -178,9 +174,6 @@ export function fromMSSQL(ast, diagramDb = DB.GENERIC) {
}
}
});
table.fields.forEach((f, j) => {
f.id = j;
});
tables.push(table);
} else if (e.keyword === "index") {
const index = {

View File

@ -1,3 +1,4 @@
import { nanoid } from "nanoid";
import { Cardinality, DB } from "../../data/constants";
import { dbToTypes } from "../../data/datatypes";
import { buildSQLFromAST } from "./shared";
@ -32,10 +33,11 @@ export function fromMySQL(ast, diagramDb = DB.GENERIC) {
table.color = "#175e7a";
table.fields = [];
table.indices = [];
table.id = tables.length;
table.id = nanoid();
e.create_definitions.forEach((d) => {
if (d.resource === "column") {
const field = {};
field.id = nanoid();
field.name = d.column.column;
let type = d.definition.dataType;

View File

@ -1,3 +1,4 @@
import { nanoid } from "nanoid";
import { Cardinality, Constraint, DB } from "../../data/constants";
import { dbToTypes } from "../../data/datatypes";
@ -33,10 +34,11 @@ export function fromOracleSQL(ast, diagramDb = DB.GENERIC) {
table.color = "#175e7a";
table.fields = [];
table.indices = [];
table.id = tables.length;
table.id = nanoid();
e.table.relational_properties.forEach((d) => {
if (d.resource === "column") {
const field = {};
field.id = nanoid();
field.name = d.name;
let type = d.type.type.toUpperCase();
@ -104,7 +106,12 @@ export function fromOracleSQL(ast, diagramDb = DB.GENERIC) {
relationship.name =
d.name && Boolean(d.name.trim())
? d.name
: "fk_" + table.name + "_" + startFieldName + "_" + endTableName;
: "fk_" +
table.name +
"_" +
startFieldName +
"_" +
endTableName;
relationship.deleteConstraint =
d.constraint.reference.on_delete &&
Boolean(d.constraint.reference.on_delete.trim())

View File

@ -1,3 +1,4 @@
import { nanoid } from "nanoid";
import { Cardinality, DB } from "../../data/constants";
import { dbToTypes } from "../../data/datatypes";
import { buildSQLFromAST } from "./shared";
@ -32,10 +33,11 @@ export function fromPostgres(ast, diagramDb = DB.GENERIC) {
table.color = "#175e7a";
table.fields = [];
table.indices = [];
table.id = tables.length;
table.id = nanoid();
e.create_definitions.forEach((d) => {
const field = {};
if (d.resource === "column") {
field.id = nanoid();
field.name = d.column.column.expr.value;
let type = types.find((t) =>

View File

@ -1,3 +1,4 @@
import { nanoid } from "nanoid";
import { Cardinality, DB } from "../../data/constants";
import { dbToTypes } from "../../data/datatypes";
import { buildSQLFromAST } from "./shared";
@ -98,10 +99,11 @@ export function fromSQLite(ast, diagramDb = DB.GENERIC) {
table.color = "#175e7a";
table.fields = [];
table.indices = [];
table.id = tables.length;
table.id = nanoid();
e.create_definitions.forEach((d) => {
if (d.resource === "column") {
const field = {};
field.id = nanoid();
field.name = d.column.column;
let type = d.definition.dataType;
@ -187,9 +189,6 @@ export function fromSQLite(ast, diagramDb = DB.GENERIC) {
}
}
});
table.fields.forEach((f, j) => {
f.id = j;
});
tables.push(table);
} else if (e.keyword === "index") {
const index = {

View File

@ -213,7 +213,7 @@ export function getIssues(diagram) {
if (visited.includes(tableId)) {
issues.push(
i18n.t("circular_dependency", {
refName: diagram.tables.find(tableId)?.name,
refName: diagram.tables.find((t) => t.id === tableId)?.name,
}),
);
return;