Undo and redo for moving and adding objects
This commit is contained in:
parent
59609b1cd8
commit
c79999d773
@ -1,6 +1,6 @@
|
|||||||
import React, { useContext, useRef, useState, useEffect } from "react";
|
import React, { useContext, useRef, useState, useEffect } from "react";
|
||||||
import Table from "./table";
|
import Table from "./table";
|
||||||
import { Cardinality, Constraint, ObjectType } from "../data/data";
|
import { Action, Cardinality, Constraint, ObjectType } from "../data/data";
|
||||||
import Area from "./area";
|
import Area from "./area";
|
||||||
import Relationship from "./relationship";
|
import Relationship from "./relationship";
|
||||||
import {
|
import {
|
||||||
@ -8,6 +8,7 @@ import {
|
|||||||
NoteContext,
|
NoteContext,
|
||||||
SettingsContext,
|
SettingsContext,
|
||||||
TableContext,
|
TableContext,
|
||||||
|
UndoRedoContext,
|
||||||
} from "../pages/editor";
|
} from "../pages/editor";
|
||||||
import Note from "./note";
|
import Note from "./note";
|
||||||
|
|
||||||
@ -17,7 +18,13 @@ export default function Canvas(props) {
|
|||||||
const { areas, setAreas } = useContext(AreaContext);
|
const { areas, setAreas } = useContext(AreaContext);
|
||||||
const { notes, setNotes } = useContext(NoteContext);
|
const { notes, setNotes } = useContext(NoteContext);
|
||||||
const { settings, setSettings } = useContext(SettingsContext);
|
const { settings, setSettings } = useContext(SettingsContext);
|
||||||
const [dragging, setDragging] = useState([ObjectType.NONE, -1]);
|
const { redoStack, setUndoStack, setRedoStack } = useContext(UndoRedoContext);
|
||||||
|
const [dragging, setDragging] = useState({
|
||||||
|
element: ObjectType.NONE,
|
||||||
|
id: -1,
|
||||||
|
prevX: 0,
|
||||||
|
prevY: 0,
|
||||||
|
});
|
||||||
const [linking, setLinking] = useState(false);
|
const [linking, setLinking] = useState(false);
|
||||||
const [line, setLine] = useState({
|
const [line, setLine] = useState({
|
||||||
startTableId: -1,
|
startTableId: -1,
|
||||||
@ -62,21 +69,36 @@ export default function Canvas(props) {
|
|||||||
x: clientX / settings.zoom - table.x,
|
x: clientX / settings.zoom - table.x,
|
||||||
y: clientY / settings.zoom - table.y,
|
y: clientY / settings.zoom - table.y,
|
||||||
});
|
});
|
||||||
setDragging([ObjectType.TABLE, id]);
|
setDragging({
|
||||||
|
element: ObjectType.TABLE,
|
||||||
|
id: id,
|
||||||
|
prevX: table.x,
|
||||||
|
prevY: table.y,
|
||||||
|
});
|
||||||
} else if (type === ObjectType.AREA) {
|
} else if (type === ObjectType.AREA) {
|
||||||
const area = areas.find((t) => t.id === id);
|
const area = areas.find((t) => t.id === id);
|
||||||
setOffset({
|
setOffset({
|
||||||
x: clientX / settings.zoom - area.x,
|
x: clientX / settings.zoom - area.x,
|
||||||
y: clientY / settings.zoom - area.y,
|
y: clientY / settings.zoom - area.y,
|
||||||
});
|
});
|
||||||
setDragging([ObjectType.AREA, id]);
|
setDragging({
|
||||||
|
element: ObjectType.AREA,
|
||||||
|
id: id,
|
||||||
|
prevX: area.x,
|
||||||
|
prevY: area.y,
|
||||||
|
});
|
||||||
} else if (type === ObjectType.NOTE) {
|
} else if (type === ObjectType.NOTE) {
|
||||||
const note = notes.find((t) => t.id === id);
|
const note = notes.find((t) => t.id === id);
|
||||||
setOffset({
|
setOffset({
|
||||||
x: clientX / settings.zoom - note.x,
|
x: clientX / settings.zoom - note.x,
|
||||||
y: clientY / settings.zoom - note.y,
|
y: clientY / settings.zoom - note.y,
|
||||||
});
|
});
|
||||||
setDragging([ObjectType.NOTE, id]);
|
setDragging({
|
||||||
|
element: ObjectType.NOTE,
|
||||||
|
id: id,
|
||||||
|
prevX: note.x,
|
||||||
|
prevY: note.y,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -93,7 +115,7 @@ export default function Canvas(props) {
|
|||||||
});
|
});
|
||||||
} else if (
|
} else if (
|
||||||
panning &&
|
panning &&
|
||||||
dragging[0] === ObjectType.NONE &&
|
dragging.element === ObjectType.NONE &&
|
||||||
areaResize.id === -1
|
areaResize.id === -1
|
||||||
) {
|
) {
|
||||||
const dx = (e.clientX - panOffset.x) / settings.zoom;
|
const dx = (e.clientX - panOffset.x) / settings.zoom;
|
||||||
@ -121,9 +143,9 @@ export default function Canvas(props) {
|
|||||||
setAreas((prev) => prev.map((t) => ({ ...t, x: t.x + dx, y: t.y + dy })));
|
setAreas((prev) => prev.map((t) => ({ ...t, x: t.x + dx, y: t.y + dy })));
|
||||||
|
|
||||||
setNotes((prev) => prev.map((n) => ({ ...n, x: n.x + dx, y: n.y + dy })));
|
setNotes((prev) => prev.map((n) => ({ ...n, x: n.x + dx, y: n.y + dy })));
|
||||||
} else if (dragging[0] === ObjectType.TABLE && dragging[1] >= 0) {
|
} else if (dragging.element === ObjectType.TABLE && dragging.id >= 0) {
|
||||||
const updatedTables = tables.map((t) => {
|
const updatedTables = tables.map((t) => {
|
||||||
if (t.id === dragging[1]) {
|
if (t.id === dragging.id) {
|
||||||
return {
|
return {
|
||||||
...t,
|
...t,
|
||||||
x: e.clientX / settings.zoom - offset.x,
|
x: e.clientX / settings.zoom - offset.x,
|
||||||
@ -135,13 +157,13 @@ export default function Canvas(props) {
|
|||||||
setTables(updatedTables);
|
setTables(updatedTables);
|
||||||
setRelationships((prev) =>
|
setRelationships((prev) =>
|
||||||
prev.map((r) => {
|
prev.map((r) => {
|
||||||
if (r.startTableId === dragging[1]) {
|
if (r.startTableId === dragging.id) {
|
||||||
return {
|
return {
|
||||||
...r,
|
...r,
|
||||||
startX: tables[r.startTableId].x + 15,
|
startX: tables[r.startTableId].x + 15,
|
||||||
startY: tables[r.startTableId].y + r.startFieldId * 36 + 50 + 19,
|
startY: tables[r.startTableId].y + r.startFieldId * 36 + 50 + 19,
|
||||||
};
|
};
|
||||||
} else if (r.endTableId === dragging[1]) {
|
} else if (r.endTableId === dragging.id) {
|
||||||
return {
|
return {
|
||||||
...r,
|
...r,
|
||||||
endX: tables[r.endTableId].x + 15,
|
endX: tables[r.endTableId].x + 15,
|
||||||
@ -152,13 +174,13 @@ export default function Canvas(props) {
|
|||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else if (
|
} else if (
|
||||||
dragging[0] === ObjectType.AREA &&
|
dragging.element === ObjectType.AREA &&
|
||||||
dragging[1] >= 0 &&
|
dragging.id >= 0 &&
|
||||||
areaResize.id === -1
|
areaResize.id === -1
|
||||||
) {
|
) {
|
||||||
setAreas((prev) =>
|
setAreas((prev) =>
|
||||||
prev.map((t) => {
|
prev.map((t) => {
|
||||||
if (t.id === dragging[1]) {
|
if (t.id === dragging.id) {
|
||||||
const updatedArea = {
|
const updatedArea = {
|
||||||
...t,
|
...t,
|
||||||
x: e.clientX / settings.zoom - offset.x,
|
x: e.clientX / settings.zoom - offset.x,
|
||||||
@ -169,10 +191,10 @@ export default function Canvas(props) {
|
|||||||
return t;
|
return t;
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
} else if (dragging[0] === ObjectType.NOTE && dragging[1] >= 0) {
|
} else if (dragging.element === ObjectType.NOTE && dragging.id >= 0) {
|
||||||
setNotes((prev) =>
|
setNotes((prev) =>
|
||||||
prev.map((t) => {
|
prev.map((t) => {
|
||||||
if (t.id === dragging[1]) {
|
if (t.id === dragging.id) {
|
||||||
return {
|
return {
|
||||||
...t,
|
...t,
|
||||||
x: e.clientX / settings.zoom - offset.x,
|
x: e.clientX / settings.zoom - offset.x,
|
||||||
@ -233,8 +255,28 @@ export default function Canvas(props) {
|
|||||||
setCursor("grabbing");
|
setCursor("grabbing");
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleMouseUp = () => {
|
const coordsDidUpdate = () => {
|
||||||
setDragging([ObjectType.NONE, -1]);
|
return !(
|
||||||
|
dragging.prevX === tables[dragging.id].x &&
|
||||||
|
dragging.prevY === tables[dragging.id].y
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleMouseUp = (e) => {
|
||||||
|
if (dragging.element !== ObjectType.NONE && coordsDidUpdate()) {
|
||||||
|
setUndoStack((prev) => [
|
||||||
|
...prev,
|
||||||
|
{
|
||||||
|
action: Action.MOVE,
|
||||||
|
element: dragging.element,
|
||||||
|
x: dragging.prevX,
|
||||||
|
y: dragging.prevY,
|
||||||
|
id: dragging.id,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
if (redoStack.length > 0) setRedoStack([]);
|
||||||
|
}
|
||||||
|
setDragging({ element: ObjectType.NONE, id: -1, prevX: 0, prevY: 0 });
|
||||||
setPanning(false);
|
setPanning(false);
|
||||||
setCursor("default");
|
setCursor("default");
|
||||||
if (linking) handleLinking();
|
if (linking) handleLinking();
|
||||||
@ -252,7 +294,7 @@ export default function Canvas(props) {
|
|||||||
|
|
||||||
const handleGripField = (id) => {
|
const handleGripField = (id) => {
|
||||||
setPanning(false);
|
setPanning(false);
|
||||||
setDragging([ObjectType.NONE, -1]);
|
setDragging({ element: ObjectType.NONE, id: -1, prevX: 0, prevY: 0 });
|
||||||
setLinking(true);
|
setLinking(true);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,8 +44,13 @@ import {
|
|||||||
TableContext,
|
TableContext,
|
||||||
UndoRedoContext,
|
UndoRedoContext,
|
||||||
} from "../pages/editor";
|
} from "../pages/editor";
|
||||||
import { AddTable, AddArea, AddNote } from "./custom_icons";
|
import { IconAddTable, IconAddArea, IconAddNote } from "./custom_icons";
|
||||||
import { defaultTableTheme, defaultNoteTheme } from "../data/data";
|
import {
|
||||||
|
defaultTableTheme,
|
||||||
|
defaultNoteTheme,
|
||||||
|
ObjectType,
|
||||||
|
Action,
|
||||||
|
} from "../data/data";
|
||||||
import CodeMirror from "@uiw/react-codemirror";
|
import CodeMirror from "@uiw/react-codemirror";
|
||||||
import { json } from "@codemirror/lang-json";
|
import { json } from "@codemirror/lang-json";
|
||||||
import jsPDF from "jspdf";
|
import jsPDF from "jspdf";
|
||||||
@ -445,30 +450,161 @@ export default function ControlPanel(props) {
|
|||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const addArea = () => {
|
||||||
|
setAreas((prev) => [
|
||||||
|
...prev,
|
||||||
|
{
|
||||||
|
id: prev.length,
|
||||||
|
name: `area_${prev.length}`,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
color: defaultTableTheme,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const addNote = () => {
|
||||||
|
setNotes((prev) => [
|
||||||
|
...prev,
|
||||||
|
{
|
||||||
|
id: prev.length,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
title: `note_${prev.length}`,
|
||||||
|
content: "",
|
||||||
|
color: defaultNoteTheme,
|
||||||
|
height: 88,
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
|
||||||
|
const moveTable = (id, x, y) => {
|
||||||
|
setTables((prev) =>
|
||||||
|
prev.map((t) => {
|
||||||
|
if (t.id === id) {
|
||||||
|
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 = () => {
|
const undo = () => {
|
||||||
if (undoStack.length === 0) return;
|
if (undoStack.length === 0) return;
|
||||||
const a = undoStack.pop();
|
const a = undoStack.pop();
|
||||||
if (a.action === "add") {
|
if (a.action === Action.ADD) {
|
||||||
if (a.element === "table") {
|
if (a.element === ObjectType.TABLE) {
|
||||||
setTables((prev) =>
|
setTables((prev) =>
|
||||||
prev
|
prev
|
||||||
.filter((e) => e.id !== prev.length - 1)
|
.filter((e) => e.id !== prev.length - 1)
|
||||||
.map((e, i) => ({ ...e, id: i }))
|
.map((e, i) => ({ ...e, id: i }))
|
||||||
);
|
);
|
||||||
|
} else if (a.element === ObjectType.AREA) {
|
||||||
|
setAreas((prev) =>
|
||||||
|
prev
|
||||||
|
.filter((e) => e.id !== prev.length - 1)
|
||||||
|
.map((e, i) => ({ ...e, id: i }))
|
||||||
|
);
|
||||||
|
} else if (a.element === ObjectType.NOTE) {
|
||||||
|
setNotes((prev) =>
|
||||||
|
prev
|
||||||
|
.filter((e) => e.id !== prev.length - 1)
|
||||||
|
.map((e, i) => ({ ...e, id: i }))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
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 },
|
||||||
|
]);
|
||||||
|
moveTable(a.id, a.x, a.y);
|
||||||
|
} else if (a.element === ObjectType.AREA) {
|
||||||
|
setRedoStack((prev) => [
|
||||||
|
...prev,
|
||||||
|
{ ...a, x: areas[a.id].x, y: areas[a.id].y },
|
||||||
|
]);
|
||||||
|
moveArea(a.id, a.x, a.y);
|
||||||
|
} else if (a.element === ObjectType.NOTE) {
|
||||||
|
setRedoStack((prev) => [
|
||||||
|
...prev,
|
||||||
|
{ ...a, x: notes[a.id].x, y: notes[a.id].y },
|
||||||
|
]);
|
||||||
|
moveNote(a.id, a.x, a.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setRedoStack((prev) => [...prev, a]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const redo = () => {
|
const redo = () => {
|
||||||
if (redoStack.length === 0) return;
|
if (redoStack.length === 0) return;
|
||||||
const a = redoStack.pop();
|
const a = redoStack.pop();
|
||||||
if (a.action === "add") {
|
if (a.action === Action.ADD) {
|
||||||
if (a.element === "table") {
|
if (a.element === ObjectType.TABLE) {
|
||||||
addTable();
|
addTable();
|
||||||
|
} else if (a.element === ObjectType.AREA) {
|
||||||
|
addArea();
|
||||||
|
} else if (a.element === ObjectType.NOTE) {
|
||||||
|
addNote();
|
||||||
|
}
|
||||||
|
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 },
|
||||||
|
]);
|
||||||
|
moveTable(a.id, a.x, a.y);
|
||||||
|
}else if (a.element === ObjectType.AREA) {
|
||||||
|
setUndoStack((prev) => [
|
||||||
|
...prev,
|
||||||
|
{ ...a, x: areas[a.id].x, y: areas[a.id].y },
|
||||||
|
]);
|
||||||
|
moveArea(a.id, a.x, a.y);
|
||||||
|
} else if (a.element === ObjectType.NOTE) {
|
||||||
|
setUndoStack((prev) => [
|
||||||
|
...prev,
|
||||||
|
{ ...a, x: notes[a.id].x, y: notes[a.id].y },
|
||||||
|
]);
|
||||||
|
moveNote(a.id, a.x, a.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
setUndoStack((prev) => [...prev, a]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -545,14 +681,20 @@ export default function ControlPanel(props) {
|
|||||||
title="Undo"
|
title="Undo"
|
||||||
onClick={undo}
|
onClick={undo}
|
||||||
>
|
>
|
||||||
<IconUndo size="large" />
|
<IconUndo
|
||||||
|
size="large"
|
||||||
|
style={{ color: undoStack.length === 0 ? "#9598a6" : "" }}
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="py-1 px-2 hover:bg-slate-200 rounded flex items-center"
|
className="py-1 px-2 hover:bg-slate-200 rounded flex items-center"
|
||||||
title="Redo"
|
title="Redo"
|
||||||
onClick={redo}
|
onClick={redo}
|
||||||
>
|
>
|
||||||
<IconRedo size="large" />
|
<IconRedo
|
||||||
|
size="large"
|
||||||
|
style={{ color: redoStack.length === 0 ? "#9598a6" : "" }}
|
||||||
|
/>
|
||||||
</button>
|
</button>
|
||||||
<Divider layout="vertical" margin="8px" />
|
<Divider layout="vertical" margin="8px" />
|
||||||
<button
|
<button
|
||||||
@ -563,54 +705,48 @@ export default function ControlPanel(props) {
|
|||||||
setUndoStack((prev) => [
|
setUndoStack((prev) => [
|
||||||
...prev,
|
...prev,
|
||||||
{
|
{
|
||||||
action: "add",
|
action: Action.ADD,
|
||||||
element: "table",
|
element: ObjectType.TABLE,
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
if (redoStack.length > 0) setRedoStack([]);
|
setRedoStack([]);
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<AddTable />
|
<IconAddTable />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="py-1 px-2 hover:bg-slate-200 rounded flex items-center"
|
className="py-1 px-2 hover:bg-slate-200 rounded flex items-center"
|
||||||
title="Add subject area"
|
title="Add subject area"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
setAreas((prev) => [
|
addArea();
|
||||||
|
setUndoStack((prev) => [
|
||||||
...prev,
|
...prev,
|
||||||
{
|
{
|
||||||
id: prev.length,
|
action: Action.ADD,
|
||||||
name: `area_${prev.length}`,
|
element: ObjectType.AREA,
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
width: 200,
|
|
||||||
height: 200,
|
|
||||||
color: defaultTableTheme,
|
|
||||||
},
|
},
|
||||||
])
|
]);
|
||||||
}
|
setRedoStack([]);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<AddArea />
|
<IconAddArea />
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
className="py-1 px-2 hover:bg-slate-200 rounded flex items-center"
|
className="py-1 px-2 hover:bg-slate-200 rounded flex items-center"
|
||||||
title="Add new note"
|
title="Add new note"
|
||||||
onClick={() =>
|
onClick={() => {
|
||||||
setNotes((prev) => [
|
addNote();
|
||||||
|
setUndoStack((prev) => [
|
||||||
...prev,
|
...prev,
|
||||||
{
|
{
|
||||||
id: prev.length,
|
action: Action.ADD,
|
||||||
x: 0,
|
element: ObjectType.NOTE,
|
||||||
y: 0,
|
|
||||||
title: `note_${prev.length}`,
|
|
||||||
content: "",
|
|
||||||
color: defaultNoteTheme,
|
|
||||||
height: 88,
|
|
||||||
},
|
},
|
||||||
])
|
]);
|
||||||
}
|
setRedoStack([]);
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<AddNote />
|
<IconAddNote />
|
||||||
</button>
|
</button>
|
||||||
<Divider layout="vertical" margin="8px" />
|
<Divider layout="vertical" margin="8px" />
|
||||||
<button
|
<button
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
export function AddTable() {
|
export function IconAddTable() {
|
||||||
return (
|
return (
|
||||||
<svg height="26" width="26">
|
<svg height="26" width="26">
|
||||||
<path
|
<path
|
||||||
@ -13,7 +13,7 @@ export function AddTable() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AddArea() {
|
export function IconAddArea() {
|
||||||
return (
|
return (
|
||||||
<svg height="26" width="26">
|
<svg height="26" width="26">
|
||||||
<path
|
<path
|
||||||
@ -26,7 +26,7 @@ export function AddArea() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function AddNote() {
|
export function IconAddNote() {
|
||||||
return (
|
return (
|
||||||
<svg height="26" width="26">
|
<svg height="26" width="26">
|
||||||
<path
|
<path
|
||||||
|
@ -75,6 +75,11 @@ const ObjectType = {
|
|||||||
NOTE: 3,
|
NOTE: 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const Action = {
|
||||||
|
ADD: 0,
|
||||||
|
MOVE: 1,
|
||||||
|
}
|
||||||
|
|
||||||
export {
|
export {
|
||||||
bgBlue,
|
bgBlue,
|
||||||
sqlDataTypes,
|
sqlDataTypes,
|
||||||
@ -86,4 +91,5 @@ export {
|
|||||||
Constraint,
|
Constraint,
|
||||||
Tab,
|
Tab,
|
||||||
ObjectType,
|
ObjectType,
|
||||||
|
Action
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user