From be66cf6e84580122a57ee2628482bfcd1c14f73d Mon Sep 17 00:00:00 2001 From: 1ilit Date: Tue, 19 Sep 2023 15:49:57 +0300 Subject: [PATCH] Clean up --- src/components/area.jsx | 4 +- src/components/area_overview.jsx | 26 +-- src/components/canvas.jsx | 137 ++++-------- src/components/control_panel.jsx | 281 +++++------------------- src/components/notes_overview.jsx | 25 +-- src/components/reference_overview.jsx | 25 +-- src/components/table.jsx | 14 +- src/components/table_overview.jsx | 67 +----- src/pages/editor.jsx | 298 +++++++++++++++++++++++++- 9 files changed, 414 insertions(+), 463 deletions(-) diff --git a/src/components/area.jsx b/src/components/area.jsx index 3356c3a..e96abd0 100644 --- a/src/components/area.jsx +++ b/src/components/area.jsx @@ -16,8 +16,8 @@ export default function Area(props) { y: props.areaData.y, width: props.areaData.width, height: props.areaData.height, - mouseX: e.clientX/props.zoom, - mouseY: e.clientY/props.zoom, + mouseX: e.clientX / props.zoom, + mouseY: e.clientY / props.zoom, }); }; diff --git a/src/components/area_overview.jsx b/src/components/area_overview.jsx index 566606a..1c10b96 100644 --- a/src/components/area_overview.jsx +++ b/src/components/area_overview.jsx @@ -23,7 +23,7 @@ import { defaultTableTheme, tableThemes } from "../data/data"; import { AreaContext } from "../pages/editor"; export default function AreaOverview(props) { - const { areas, setAreas } = useContext(AreaContext); + const { areas, setAreas, addArea, deleteArea } = useContext(AreaContext); const [value, setValue] = useState(""); const [filteredResult, setFilteredResult] = useState( @@ -79,22 +79,7 @@ export default function AreaOverview(props) { /> - @@ -208,13 +193,8 @@ export default function AreaOverview(props) { onClick={(e) => { e.stopPropagation(); Toast.success(`Area deleted!`); - setAreas((prev) => - prev - .filter((e) => e.id !== i) - .map((e, idx) => ({ ...e, id: idx })) - ); + deleteArea(i, true); }} - // className="delete-button" > diff --git a/src/components/canvas.jsx b/src/components/canvas.jsx index d1964e0..e9f482b 100644 --- a/src/components/canvas.jsx +++ b/src/components/canvas.jsx @@ -13,10 +13,10 @@ import { import Note from "./note"; export default function Canvas(props) { - const { tables, setTables, relationships, setRelationships } = + const { tables, moveTable, relationships, addRelationship } = useContext(TableContext); - const { areas, setAreas } = useContext(AreaContext); - const { notes, setNotes } = useContext(NoteContext); + const { areas, setAreas, moveArea } = useContext(AreaContext); + const { notes, moveNote } = useContext(NoteContext); const { settings, setSettings } = useContext(SettingsContext); const { setUndoStack, setRedoStack } = useContext(UndoRedoContext); const [dragging, setDragging] = useState({ @@ -126,66 +126,21 @@ export default function Canvas(props) { })); setPanOffset({ x: e.clientX, y: e.clientY }); } else if (dragging.element === ObjectType.TABLE && dragging.id >= 0) { - const updatedTables = tables.map((t) => { - if (t.id === dragging.id) { - return { - ...t, - x: e.clientX / settings.zoom - offset.x, - y: e.clientY / settings.zoom - offset.y, - }; - } - return t; - }); - setTables(updatedTables); - setRelationships((prev) => - prev.map((r) => { - if (r.startTableId === dragging.id) { - return { - ...r, - startX: tables[r.startTableId].x + 15, - startY: tables[r.startTableId].y + r.startFieldId * 36 + 50 + 19, - }; - } else if (r.endTableId === dragging.id) { - return { - ...r, - endX: tables[r.endTableId].x + 15, - endY: tables[r.endTableId].y + r.endFieldId * 36 + 50 + 19, - }; - } - return r; - }) - ); + const dx = e.clientX / settings.zoom - offset.x; + const dy = e.clientY / settings.zoom - offset.y; + moveTable(dragging.id, dx, dy); } else if ( dragging.element === ObjectType.AREA && dragging.id >= 0 && areaResize.id === -1 ) { - setAreas((prev) => - prev.map((t) => { - if (t.id === dragging.id) { - const updatedArea = { - ...t, - x: e.clientX / settings.zoom - offset.x, - y: e.clientY / settings.zoom - offset.y, - }; - return updatedArea; - } - return t; - }) - ); + const dx = e.clientX / settings.zoom - offset.x; + const dy = e.clientY / settings.zoom - offset.y; + moveArea(dragging.id, dx, dy); } else if (dragging.element === ObjectType.NOTE && dragging.id >= 0) { - setNotes((prev) => - prev.map((t) => { - if (t.id === dragging.id) { - return { - ...t, - x: e.clientX / settings.zoom - offset.x, - y: e.clientY / settings.zoom - offset.y, - }; - } - return t; - }) - ); + const dx = e.clientX / settings.zoom - offset.x; + const dy = e.clientY / settings.zoom - offset.y; + moveNote(dragging.id, dx, dy); } else if (areaResize.id !== -1) { if (areaResize.dir === "none") return; @@ -237,15 +192,30 @@ export default function Canvas(props) { setCursor("grabbing"); }; - const coordsDidUpdate = () => { - return !( - dragging.prevX === tables[dragging.id].x && - dragging.prevY === tables[dragging.id].y - ); + const coordsDidUpdate = (element) => { + switch (element) { + case ObjectType.TABLE: + return !( + dragging.prevX === tables[dragging.id].x && + dragging.prevY === tables[dragging.id].y + ); + case ObjectType.AREA: + return !( + dragging.prevX === areas[dragging.id].x && + dragging.prevY === areas[dragging.id].y + ); + case ObjectType.NOTE: + return !( + dragging.prevX === notes[dragging.id].x && + dragging.prevY === notes[dragging.id].y + ); + default: + return false; + } }; const handleMouseUp = (e) => { - if (dragging.element !== ObjectType.NONE && coordsDidUpdate()) { + if (coordsDidUpdate(dragging.element)) { setUndoStack((prev) => [ ...prev, { @@ -289,38 +259,25 @@ export default function Canvas(props) { ) return; - setRelationships((prev) => { - const newRelationship = { - ...line, - endTableId: onRect.tableId, - endFieldId: onRect.field, - endX: tables[onRect.tableId].x + 15, - endY: tables[onRect.tableId].y + onRect.field * 36 + 50 + 19, - name: `${tables[line.startTableId].name}_to_${ - tables[onRect.tableId].name - }`, - id: prev.length, - }; - setUndoStack((prevUndo) => [ - ...prevUndo, - { - action: Action.ADD, - element: ObjectType.RELATIONSHIP, - data: newRelationship, - }, - ]); - setRedoStack([]); - return [...prev, newRelationship]; + addRelationship(true, { + ...line, + endTableId: onRect.tableId, + endFieldId: onRect.field, + endX: tables[onRect.tableId].x + 15, + endY: tables[onRect.tableId].y + onRect.field * 36 + 69, + name: `${tables[line.startTableId].name}_to_${ + tables[onRect.tableId].name + }`, + id: relationships.length, }); }; const handleMouseWheel = (e) => { e.preventDefault(); - if (e.deltaY <= 0) { - setSettings((prev) => ({ ...prev, zoom: prev.zoom * 1.05 })); - } else { - setSettings((prev) => ({ ...prev, zoom: prev.zoom / 1.05 })); - } + setSettings((prev) => ({ + ...prev, + zoom: e.deltaY <= 0 ? prev.zoom * 1.05 : prev.zoom / 1.05, + })); }; useEffect(() => { diff --git a/src/components/control_panel.jsx b/src/components/control_panel.jsx index e550a24..56d96c6 100644 --- a/src/components/control_panel.jsx +++ b/src/components/control_panel.jsx @@ -45,12 +45,7 @@ import { UndoRedoContext, } from "../pages/editor"; import { IconAddTable, IconAddArea, IconAddNote } from "./custom_icons"; -import { - defaultTableTheme, - defaultNoteTheme, - ObjectType, - Action, -} from "../data/data"; +import { ObjectType, Action } from "../data/data"; import CodeMirror from "@uiw/react-codemirror"; import { json } from "@codemirror/lang-json"; import jsPDF from "jspdf"; @@ -62,7 +57,7 @@ export default function ControlPanel(props) { CODE: 2, IMPORT: 3, }; - const ERROR = { + const STATUS = { NONE: 0, WARNING: 1, ERROR: 2, @@ -75,16 +70,27 @@ export default function ControlPanel(props) { extension: "", }); const [error, setError] = useState({ - type: ERROR.NONE, + type: STATUS.NONE, message: "", }); const [data, setData] = useState(null); const { layout, setLayout } = useContext(LayoutContext); const { settings, setSettings } = useContext(SettingsContext); - const { relationships, tables, setTables, setRelationships } = - useContext(TableContext); - const { notes, setNotes } = useContext(NoteContext); - const { areas, setAreas } = useContext(AreaContext); + const { + relationships, + tables, + setTables, + addTable, + moveTable, + deleteTable, + setRelationships, + addRelationship, + deleteRelationship, + } = useContext(TableContext); + const { notes, setNotes, moveNote, addNote, deleteNote } = + useContext(NoteContext); + const { areas, setAreas, moveArea, addArea, deleteArea } = + useContext(AreaContext); const { undoStack, redoStack, setUndoStack, setRedoStack } = useContext(UndoRedoContext); @@ -107,155 +113,18 @@ export default function ControlPanel(props) { setNotes(data.notes); }; - const addTable = () => { - setTables((prev) => [ - ...prev, - { - id: prev.length, - name: `table_${prev.length}`, - x: -settings.pan.x, - y: -settings.pan.y, - fields: [ - { - name: "id", - type: "UUID", - default: "", - check: "", - primary: true, - unique: true, - notNull: true, - increment: true, - comment: "", - }, - ], - comment: "", - indices: [], - color: defaultTableTheme, - }, - ]); - }; - - const addArea = () => { - setAreas((prev) => [ - ...prev, - { - id: prev.length, - name: `area_${prev.length}`, - x: -settings.pan.x, - y: -settings.pan.y, - width: 200, - height: 200, - color: defaultTableTheme, - }, - ]); - }; - - const addNote = () => { - setNotes((prev) => [ - ...prev, - { - id: prev.length, - x: -settings.pan.x, - y: -settings.pan.y, - title: `note_${prev.length}`, - content: "", - color: defaultNoteTheme, - height: 88, - }, - ]); - }; - - const moveTable = (id, x, y) => { - setTables((prev) => - prev.map((t) => { - if (t.id === id) { - setRelationships((prev) => - prev.map((r) => { - if (r.startTableId === id) { - return { - ...r, - startX: x + 15, - startY: y + r.startFieldId * 36 + 69, - }; - } else if (r.endTableId === id) { - return { - ...r, - endX: x + 15, - endY: y + r.endFieldId * 36 + 69, - }; - } - return r; - }) - ); - return { - ...t, - x: x, - y: y, - }; - } - return t; - }) - ); - }; - - const moveArea = (id, x, y) => { - setAreas((prev) => - prev.map((t) => { - if (t.id === id) { - return { - ...t, - x: x, - y: y, - }; - } - return t; - }) - ); - }; - - const moveNote = (id, x, y) => { - setNotes((prev) => - prev.map((t) => { - if (t.id === id) { - return { - ...t, - x: x, - y: y, - }; - } - return t; - }) - ); - }; - const undo = () => { if (undoStack.length === 0) return; const a = undoStack.pop(); if (a.action === Action.ADD) { if (a.element === ObjectType.TABLE) { - setTables((prev) => - prev - .filter((e) => e.id !== prev.length - 1) - .map((e, i) => ({ ...e, id: i })) - ); + deleteTable(tables[tables.length - 1].id, false); } else if (a.element === ObjectType.AREA) { - setAreas((prev) => - prev - .filter((e) => e.id !== prev.length - 1) - .map((e, i) => ({ ...e, id: i })) - ); + deleteArea(areas[areas.length - 1].id, false); } else if (a.element === ObjectType.NOTE) { - setNotes((prev) => - prev - .filter((e) => e.id !== prev.length - 1) - .map((e, i) => ({ ...e, id: i })) - ); + deleteNote(notes[notes.length - 1].id, false); } else if (a.element === ObjectType.RELATIONSHIP) { - setRelationships((prev) => - prev - .filter((e) => e.id !== a.data.id) - .map((e, idx) => ({ ...e, id: idx })) - ); + deleteRelationship(a.data.id, false); } setRedoStack((prev) => [...prev, a]); } else if (a.action === Action.MOVE) { @@ -280,17 +149,13 @@ export default function ControlPanel(props) { } } else if (a.action === Action.DELETE) { if (a.element === ObjectType.TABLE) { - setTables((prev) => { - const temp = prev.slice(); - temp.splice(a.data.id, 0, a.data); - return temp.map((t, i) => ({ ...t, id: i })); - }); + addTable(false, a.data); } else if (a.element === ObjectType.RELATIONSHIP) { - setRelationships((prev) => { - const temp = prev.slice(); - temp.splice(a.data.id, 0, a.data); - return temp.map((t, i) => ({ ...t, id: i })); - }); + addRelationship(false, a.data); + } else if (a.element === ObjectType.NOTE) { + addNote(false, a.data); + } else if (a.element === ObjectType.AREA) { + addArea(false, a.data); } setRedoStack((prev) => [...prev, a]); } @@ -301,17 +166,13 @@ export default function ControlPanel(props) { const a = redoStack.pop(); if (a.action === Action.ADD) { if (a.element === ObjectType.TABLE) { - addTable(); + addTable(false); } else if (a.element === ObjectType.AREA) { - addArea(); + addArea(false); } else if (a.element === ObjectType.NOTE) { - addNote(); + addNote(false); } else if (a.element === ObjectType.RELATIONSHIP) { - setRelationships((prev) => { - const temp = prev.slice(); - temp.splice(a.data.id, 0, a.data); - return temp.map((t, i) => ({ ...t, id: i })); - }); + addRelationship(false, a.data); } setUndoStack((prev) => [...prev, a]); } else if (a.action === Action.MOVE) { @@ -336,17 +197,13 @@ export default function ControlPanel(props) { } } else if (a.action === Action.DELETE) { if (a.element === ObjectType.TABLE) { - setTables((prev) => - prev - .filter((t) => t.id !== a.data.id) - .map((t, i) => ({ ...t, id: i })) - ); + deleteTable(a.data.id, false); } else if (a.element === ObjectType.RELATIONSHIP) { - setRelationships((prev) => - prev - .filter((t) => t.id !== a.data.id) - .map((t, i) => ({ ...t, id: i })) - ); + deleteRelationship(a.data.id, false); + } else if (a.element === ObjectType.NOTE) { + deleteNote(a.data.id, false); + } else if (a.element === ObjectType.AREA) { + deleteArea(a.data.id, false); } setUndoStack((prev) => [...prev, a]); } @@ -772,51 +629,21 @@ export default function ControlPanel(props) { @@ -856,7 +683,7 @@ export default function ControlPanel(props) { }); saveAs(blob, `${exportData.filename}.${exportData.extension}`); } else if (visible === MODAL.IMPORT) { - if (error.type !== ERROR.ERROR) { + if (error.type !== STATUS.ERROR) { setSettings((prev) => ({ ...prev, pan: { x: 0, y: 0 } })); overwriteDiagram(); setData(null); @@ -873,7 +700,7 @@ export default function ControlPanel(props) { filename: `diagram_${new Date().toISOString()}`, })); setError({ - type: ERROR.NONE, + type: STATUS.NONE, message: "", }); setData(null); @@ -885,7 +712,7 @@ export default function ControlPanel(props) { okButtonProps={{ disabled: (visible === MODAL.IMPORT && - (error.type === ERROR.ERROR || !data)) || + (error.type === STATUS.ERROR || !data)) || ((visible === MODAL.IMG || visible === MODAL.CODE) && !exportData.data), }} @@ -909,7 +736,7 @@ export default function ControlPanel(props) { jsonObject = JSON.parse(event.target.result); } catch (error) { setError({ - type: ERROR.ERROR, + type: STATUS.ERROR, message: "The file contains an error.", }); return; @@ -917,7 +744,7 @@ export default function ControlPanel(props) { if (f.type === "application/json") { if (!jsonDiagramIsValid(jsonObject)) { setError({ - type: ERROR.ERROR, + type: STATUS.ERROR, message: "The file is missing necessary properties for a diagram.", }); @@ -926,7 +753,7 @@ export default function ControlPanel(props) { } else if (f.name.split(".").pop() === "ddb") { if (!ddbDiagramIsValid(jsonObject)) { setError({ - type: ERROR.ERROR, + type: STATUS.ERROR, message: "The file is missing necessary properties for a diagram.", }); @@ -936,12 +763,12 @@ export default function ControlPanel(props) { setData(jsonObject); if (diagramIsEmpty()) { setError({ - type: ERROR.OK, + type: STATUS.OK, message: "Everything looks good. You can now import.", }); } else { setError({ - type: ERROR.WARNING, + type: STATUS.WARNING, message: "The current diagram is not empty. Importing a new diagram will overwrite the current changes.", }); @@ -962,19 +789,19 @@ export default function ControlPanel(props) { accept="application/json,.ddb" onRemove={() => setError({ - type: ERROR.NONE, + type: STATUS.NONE, message: "", }) } onFileChange={() => setError({ - type: ERROR.NONE, + type: STATUS.NONE, message: "", }) } limit={1} > - {error.type === ERROR.ERROR ? ( + {error.type === STATUS.ERROR ? ( {error.message} } /> - ) : error.type === ERROR.OK ? ( + ) : error.type === STATUS.OK ? ( {error.message}} /> ) : ( - error.type === ERROR.WARNING && ( + error.type === STATUS.WARNING && ( - @@ -189,11 +174,7 @@ export default function NotesOverview(props) { type="danger" onClick={() => { Toast.success(`Note deleted!`); - setNotes((prev) => - prev - .filter((e) => e.id !== i) - .map((e, idx) => ({ ...e, id: idx })) - ); + deleteNote(i, true); }} > diff --git a/src/components/reference_overview.jsx b/src/components/reference_overview.jsx index 3123f94..c918a47 100644 --- a/src/components/reference_overview.jsx +++ b/src/components/reference_overview.jsx @@ -22,8 +22,8 @@ import { IllustrationNoContent, IllustrationNoContentDark, } from "@douyinfe/semi-illustrations"; -import { Action, Cardinality, Constraint, ObjectType } from "../data/data"; -import { TableContext, UndoRedoContext } from "../pages/editor"; +import { Cardinality, Constraint } from "../data/data"; +import { TableContext } from "../pages/editor"; export default function ReferenceOverview(props) { const columns = [ @@ -36,8 +36,8 @@ export default function ReferenceOverview(props) { dataIndex: "foreign", }, ]; - const { tables, relationships, setRelationships } = useContext(TableContext); - const { setUndoStack, setRedoStack } = useContext(UndoRedoContext); + const { tables, relationships, setRelationships, deleteRelationship } = + useContext(TableContext); const [refActiveIndex, setRefActiveIndex] = useState(""); const [value, setValue] = useState(""); const [filteredResult, setFilteredResult] = useState( @@ -233,22 +233,7 @@ export default function ReferenceOverview(props) { icon={} block type="danger" - onClick={() => { - setUndoStack((prev) => [ - ...prev, - { - action: Action.DELETE, - element: ObjectType.RELATIONSHIP, - data: relationships[i], - }, - ]); - setRelationships((prev) => - prev - .filter((e) => e.id !== i) - .map((e, idx) => ({ ...e, id: idx })) - ); - setRedoStack([]); - }} + onClick={() => deleteRelationship(r.id, true)} > Delete diff --git a/src/components/table.jsx b/src/components/table.jsx index 1c0e8c8..148db62 100644 --- a/src/components/table.jsx +++ b/src/components/table.jsx @@ -40,7 +40,7 @@ export default function Table(props) { const [hoveredField, setHoveredField] = useState(-1); const [visible, setVisible] = useState(false); const { layout } = useContext(LayoutContext); - const { setTables } = useContext(TableContext); + const { setTables, deleteTable } = useContext(TableContext); const { tab, setTab } = useContext(TabContext); const { settings } = useContext(SettingsContext); @@ -180,11 +180,7 @@ export default function Table(props) { style={{ marginTop: "8px" }} onClick={() => { Toast.success(`Table deleted!`); - setTables((prev) => - prev - .filter((e) => e.id !== props.tableData.id) - .map((e, idx) => ({ ...e, id: idx })) - ); + deleteTable(props.tableData.id); props.setSelectedTable(""); }} > @@ -683,11 +679,7 @@ export default function Table(props) { type="danger" onClick={() => { Toast.success(`Table deleted!`); - setTables((prev) => - prev - .filter((e) => e.id !== props.tableData.id) - .map((e, idx) => ({ ...e, id: idx })) - ); + deleteTable(props.tableData.id); props.setSelectedTable(""); setVisible(false); }} diff --git a/src/components/table_overview.jsx b/src/components/table_overview.jsx index b878d20..67b8350 100644 --- a/src/components/table_overview.jsx +++ b/src/components/table_overview.jsx @@ -1,11 +1,5 @@ import { React, useContext, useState } from "react"; -import { - defaultTableTheme, - sqlDataTypes, - tableThemes, - Action, - ObjectType, -} from "../data/data"; +import { defaultTableTheme, sqlDataTypes, tableThemes } from "../data/data"; import { Collapse, Row, @@ -32,18 +26,12 @@ import { IllustrationNoContent, IllustrationNoContentDark, } from "@douyinfe/semi-illustrations"; -import { - SettingsContext, - TableContext, - UndoRedoContext, -} from "../pages/editor"; +import { TableContext } from "../pages/editor"; export default function TableOverview(props) { const [indexActiveKey, setIndexActiveKey] = useState(""); const [value, setValue] = useState(""); - const { tables, setTables } = useContext(TableContext); - const { settings } = useContext(SettingsContext); - const { setUndoStack, setRedoStack } = useContext(UndoRedoContext); + const { tables, setTables, addTable, deleteTable } = useContext(TableContext); const [filteredResult, setFilteredResult] = useState( tables.map((t) => { return t.name; @@ -118,39 +106,7 @@ export default function TableOverview(props) { icon={} block onClick={() => { - setTables((prev) => [ - ...prev, - { - id: prev.length, - name: `table_${prev.length}`, - x: -settings.pan.x, - y: -settings.pan.y, - fields: [ - { - name: "id", - type: "UUID", - default: "", - check: "", - primary: true, - unique: true, - notNull: true, - increment: true, - comment: "", - }, - ], - comment: "", - indices: [], - color: defaultTableTheme, - }, - ]); - setUndoStack((prev) => [ - ...prev, - { - action: Action.ADD, - element: ObjectType.TABLE, - }, - ]); - setRedoStack([]); + addTable(true); }} > Add table @@ -570,20 +526,7 @@ export default function TableOverview(props) { type="danger" onClick={() => { Toast.success(`Table deleted!`); - setUndoStack((prev) => [ - ...prev, - { - action: Action.DELETE, - element: ObjectType.TABLE, - data: tables[i], - }, - ]); - setRedoStack([]); - setTables((prev) => - prev - .filter((e) => e.id !== i) - .map((e, idx) => ({ ...e, id: idx })) - ); + deleteTable(i); props.setSelectedTable(""); }} > diff --git a/src/pages/editor.jsx b/src/pages/editor.jsx index a4180a2..9bd063e 100644 --- a/src/pages/editor.jsx +++ b/src/pages/editor.jsx @@ -5,7 +5,13 @@ import { DndProvider } from "react-dnd"; import { HTML5Backend } from "react-dnd-html5-backend"; import Canvas from "../components/canvas"; import EditorPanel from "../components/editor_panel"; -import { Tab } from "../data/data"; +import { + Tab, + defaultTableTheme, + defaultNoteTheme, + Action, + ObjectType, +} from "../data/data"; export const LayoutContext = createContext(); export const TableContext = createContext(); @@ -41,7 +47,7 @@ export default function Editor(props) { strictMode: false, showFieldSummary: true, zoom: 1, - pan: {x: 0, y: 0}, + pan: { x: 0, y: 0 }, showGrid: true, }); const [undoStack, setUndoStack] = useState([]); @@ -53,17 +59,297 @@ export default function Editor(props) { if (w > 340) setWidth(w); }; + const addTable = (addToHistory = true, data) => { + if (data) { + setTables((prev) => { + const temp = prev.slice(); + temp.splice(data.id, 0, data); + return temp.map((t, i) => ({ ...t, id: i })); + }); + } else { + setTables((prev) => [ + ...prev, + { + id: prev.length, + name: `table_${prev.length}`, + x: -settings.pan.x, + y: -settings.pan.y, + fields: [ + { + name: "id", + type: "UUID", + default: "", + check: "", + primary: true, + unique: true, + notNull: true, + increment: true, + comment: "", + }, + ], + comment: "", + indices: [], + color: defaultTableTheme, + }, + ]); + } + if (addToHistory) { + setUndoStack((prev) => [ + ...prev, + { + action: Action.ADD, + element: ObjectType.TABLE, + }, + ]); + setRedoStack([]); + } + }; + + const addArea = (addToHistory = true, data) => { + if (data) { + setAreas((prev) => { + const temp = prev.slice(); + temp.splice(data.id, 0, data); + return temp.map((t, i) => ({ ...t, id: i })); + }); + } else { + setAreas((prev) => [ + ...prev, + { + id: prev.length, + name: `area_${prev.length}`, + x: -settings.pan.x, + y: -settings.pan.y, + width: 200, + height: 200, + color: defaultTableTheme, + }, + ]); + } + if (addToHistory) { + setUndoStack((prev) => [ + ...prev, + { + action: Action.ADD, + element: ObjectType.AREA, + }, + ]); + setRedoStack([]); + } + }; + + const addNote = (addToHistory = true, data) => { + if (data) { + setNotes((prev) => { + const temp = prev.slice(); + temp.splice(data.id, 0, data); + return temp.map((t, i) => ({ ...t, id: i })); + }); + } else { + setNotes((prev) => [ + ...prev, + { + id: prev.length, + x: -settings.pan.x, + y: -settings.pan.y, + title: `note_${prev.length}`, + content: "", + color: defaultNoteTheme, + height: 88, + }, + ]); + } + if (addToHistory) { + setUndoStack((prev) => [ + ...prev, + { + action: Action.ADD, + element: ObjectType.NOTE, + }, + ]); + setRedoStack([]); + } + }; + + const addRelationship = (addToHistory = true, data) => { + if (addToHistory) { + setRelationships((prev) => { + setUndoStack((prevUndo) => [ + ...prevUndo, + { + action: Action.ADD, + element: ObjectType.RELATIONSHIP, + data: data, + }, + ]); + setRedoStack([]); + return [...prev, data]; + }); + } else { + setRelationships((prev) => { + const temp = prev.slice(); + temp.splice(data.id, 0, data); + return temp.map((t, i) => ({ ...t, id: i })); + }); + } + }; + + const moveTable = (id, x, y) => { + setTables((prev) => + prev.map((t) => { + if (t.id === id) { + setRelationships((prev) => + prev.map((r) => { + if (r.startTableId === id) { + return { + ...r, + startX: x + 15, + startY: y + r.startFieldId * 36 + 69, + }; + } else if (r.endTableId === id) { + return { + ...r, + endX: x + 15, + endY: y + r.endFieldId * 36 + 69, + }; + } + return r; + }) + ); + return { + ...t, + x: x, + y: y, + }; + } + return t; + }) + ); + }; + + const moveArea = (id, x, y) => { + setAreas((prev) => + prev.map((t) => { + if (t.id === id) { + return { + ...t, + x: x, + y: y, + }; + } + return t; + }) + ); + }; + + const moveNote = (id, x, y) => { + setNotes((prev) => + prev.map((t) => { + if (t.id === id) { + return { + ...t, + x: x, + y: y, + }; + } + return t; + }) + ); + }; + + const deleteTable = (id, addToHistory = true) => { + if (addToHistory) { + setUndoStack((prev) => [ + ...prev, + { + action: Action.DELETE, + element: ObjectType.TABLE, + data: tables[id], + }, + ]); + setRedoStack([]); + } + setTables((prev) => + prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i })) + ); + }; + + const deleteArea = (id, addToHistory = true) => { + if (addToHistory) { + setUndoStack((prev) => [ + ...prev, + { + action: Action.DELETE, + element: ObjectType.AREA, + data: areas[id], + }, + ]); + setRedoStack([]); + } + setAreas((prev) => + prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i })) + ); + }; + + const deleteNote = (id, addToHistory = true) => { + if (addToHistory) { + setUndoStack((prev) => [ + ...prev, + { + action: Action.DELETE, + element: ObjectType.NOTE, + data: notes[id], + }, + ]); + setRedoStack([]); + } + setNotes((prev) => + prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i })) + ); + }; + + const deleteRelationship = (id, addToHistory = true) => { + if (addToHistory) { + setUndoStack((prev) => [ + ...prev, + { + action: Action.DELETE, + element: ObjectType.RELATIONSHIP, + data: relationships[id], + }, + ]); + setRedoStack([]); + } + setRelationships((prev) => + prev.filter((e) => e.id !== id).map((e, i) => ({ ...e, id: i })) + ); + }; + useEffect(() => { - document.title = "Editor"; + document.title = "Editor - drawDB"; }, []); return ( - - + +