mirror of
https://github.com/drawdb-io/drawdb.git
synced 2025-05-24 02:09:17 +00:00
Use nanoid instead of numberic ids for fields and tables
This commit is contained in:
parent
9c40ae31f0
commit
a1c60af3cd
31
package-lock.json
generated
31
package-lock.json
generated
@ -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",
|
||||
|
@ -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",
|
||||
|
@ -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,
|
||||
|
@ -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
|
||||
|
@ -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,16 +397,12 @@ 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,
|
||||
updateTable(a.tid, {
|
||||
indices: [
|
||||
...table.indices,
|
||||
{
|
||||
@ -465,14 +411,10 @@ export default function ControlPanel({
|
||||
fields: [],
|
||||
},
|
||||
],
|
||||
};
|
||||
}
|
||||
return table;
|
||||
}),
|
||||
);
|
||||
});
|
||||
} 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 })),
|
||||
});
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
})),
|
||||
);
|
||||
|
@ -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,
|
||||
});
|
||||
}, [
|
||||
|
@ -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", {
|
||||
|
@ -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"
|
||||
|
@ -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,
|
||||
},
|
||||
],
|
||||
});
|
||||
|
@ -40,7 +40,7 @@ export default function TablesTab() {
|
||||
setSelectedElement((prev) => ({
|
||||
...prev,
|
||||
open: true,
|
||||
id: parseInt(k),
|
||||
id: k[0],
|
||||
element: ObjectType.TABLE,
|
||||
}))
|
||||
}
|
||||
|
@ -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(
|
||||
setRelationships((prev) =>
|
||||
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;
|
||||
});
|
||||
),
|
||||
);
|
||||
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),
|
||||
});
|
||||
};
|
||||
|
||||
|
@ -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 = {
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
|
@ -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())
|
||||
|
@ -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) =>
|
||||
|
@ -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 = {
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user