layout context

This commit is contained in:
1ilit 2023-09-19 15:48:48 +03:00
parent 23e58a0110
commit 1eea618faa
6 changed files with 140 additions and 139 deletions

View File

@ -1,11 +1,13 @@
import React, { useRef, useState } from "react";
import React, { useContext, useRef, useState } from "react";
import { useDrop } from "react-dnd";
import Table from "./table";
import { defaultTableTheme, Cardinality, Constraint } from "../data/data";
import Area from "./area";
import Relationship from "./relationship";
import { TableContext } from "../pages/editor";
export default function Canvas(props) {
const { tables, setTables } = useContext(TableContext);
const ObjectType = {
NONE: 0,
TABLE: 1,
@ -51,7 +53,7 @@ export default function Canvas(props) {
const handleMouseDownRect = (e, id, type) => {
const { clientX, clientY } = e;
if (type === ObjectType.TABLE) {
const table = props.tables.find((t) => t.id === id);
const table = tables.find((t) => t.id === id);
setOffset({
x: clientX - table.x,
y: clientY - table.y,
@ -87,8 +89,8 @@ export default function Canvas(props) {
const dy = e.clientY - panOffset.y;
setPanOffset({ x: e.clientX, y: e.clientY });
props.setTables(
props.tables.map((t) => ({
setTables(
tables.map((t) => ({
...t,
x: t.x + dx,
y: t.y + dy,
@ -113,7 +115,7 @@ export default function Canvas(props) {
}))
);
} else if (dragging[0] === ObjectType.TABLE && dragging[1] >= 0) {
const updatedTables = props.tables.map((t) => {
const updatedTables = tables.map((t) => {
if (t.id === dragging[1]) {
const updatedTable = {
...t,
@ -124,20 +126,19 @@ export default function Canvas(props) {
}
return t;
});
props.setTables(updatedTables);
setTables(updatedTables);
const updatedRelationShips = props.relationships.map((r) => {
if (r.startTableId === dragging[1]) {
return {
...r,
startX: props.tables[r.startTableId].x + 15,
startY:
props.tables[r.startTableId].y + r.startFieldId * 36 + 50 + 19,
startX: tables[r.startTableId].x + 15,
startY: tables[r.startTableId].y + r.startFieldId * 36 + 50 + 19,
};
} else if (r.endTableId === dragging[1]) {
return {
...r,
endX: props.tables[r.endTableId].x + 15,
endY: props.tables[r.endTableId].y + r.endFieldId * 36 + 50 + 19,
endX: tables[r.endTableId].x + 15,
endY: tables[r.endTableId].y + r.endFieldId * 36 + 50 + 19,
};
}
return r;
@ -246,10 +247,10 @@ export default function Canvas(props) {
...line,
endTableId: onRect.tableId,
endFieldId: onRect.field,
endX: props.tables[onRect.tableId].x + 15,
endY: props.tables[onRect.tableId].y + onRect.field * 36 + 50 + 19,
name: `${props.tables[line.startTableId].name}_to_${
props.tables[onRect.tableId].name
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,
},
@ -265,8 +266,8 @@ export default function Canvas(props) {
const x = offset.x - canvasRect.left - 100 * 0.5;
const y = offset.y - canvasRect.top - 100 * 0.5;
const newTable = {
id: props.tables.length,
name: `table_${props.tables.length}`,
id: tables.length,
name: `table_${tables.length}`,
x: x,
y: y,
fields: [
@ -286,7 +287,7 @@ export default function Canvas(props) {
indices: [],
color: defaultTableTheme,
};
props.setTables((prev) => [...prev, newTable]);
setTables((prev) => [...prev, newTable]);
props.setCode((prev) =>
prev === ""
? `CREATE TABLE \`${newTable.name}\`;`
@ -297,7 +298,7 @@ export default function Canvas(props) {
isOver: !!monitor.isOver(),
}),
}),
[props.tables]
[tables]
);
return (
@ -352,13 +353,10 @@ export default function Canvas(props) {
setAreas={props.setAreas}
></Area>
))}
{props.tables.map((table, i) => (
{tables.map((table, i) => (
<Table
key={table.id}
id={table.id}
tableData={table}
tables={props.tables}
setTables={props.setTables}
setOnRect={setOnRect}
handleGripField={handleGripField}
setLine={setLine}

View File

@ -1,14 +1,15 @@
import { React, useState, useRef } from "react";
import { React, useState } from "react";
import CodeMirror from "@uiw/react-codemirror";
import { createTheme } from "@uiw/codemirror-themes";
import { sql } from "@codemirror/lang-sql";
import { tags as t } from "@lezer/highlight";
import Shape from "./shape";
import { Parser } from "node-sql-parser";
// import { Parser } from "node-sql-parser";
import { Tabs } from "@douyinfe/semi-ui";
import TableOverview from "./table_overview";
import ReferenceOverview from "./reference_overview";
import { defaultTableTheme } from "../data/data";
// import { TableContext } from "../pages/editor";
const myTheme = createTheme({
dark: "light",
@ -26,7 +27,8 @@ const myTheme = createTheme({
const EditorPanel = (props) => {
const [tab, setTab] = useState("1");
const map = useRef(new Map());
// const map = useRef(new Map());
// const {tables, setTables} = useContext(TableContext);
const tabList = [
{ tab: "Tables", itemKey: "1" },
@ -35,11 +37,10 @@ const EditorPanel = (props) => {
{ tab: "Editor", itemKey: "4" },
];
const contentList = [
<TableOverview tables={props.tables} setTables={props.setTables} />,
<TableOverview />,
<ReferenceOverview
relationships={props.relationships}
setRelationships={props.setRelationships}
tables={props.tables}
/>,
<Shape />,
<CodeMirror
@ -99,44 +100,44 @@ const EditorPanel = (props) => {
<br />
<button
onClick={() => {
try {
const parser = new Parser();
const ast = parser.astify(props.code);
console.log(ast);
ast.forEach((e) => {
e.table.forEach((t) => {
if (map.current.has(t.table)) {
return;
}
map.current.set(t.table, t);
const newTable = {
id: props.tables.length,
name: `table_${props.tables.length}`,
x: 0,
y: 0,
fields: [
{
name: "id",
type: "UUID",
default: "",
check: "",
primary: true,
unique: true,
notNull: true,
increment: true,
comment: "",
},
],
comment: "",
indices: [],
color: defaultTableTheme,
};
props.setTables((prev) => [...prev, newTable]);
});
});
} catch (e) {
alert("parsing error");
}
// try {
// const parser = new Parser();
// const ast = parser.astify(props.code);
// console.log(ast);
// ast.forEach((e) => {
// e.table.forEach((t) => {
// if (map.current.has(t.table)) {
// return;
// }
// map.current.set(t.table, t);
// const newTable = {
// id: props.tables.length,
// name: `table_${props.tables.length}`,
// x: 0,
// y: 0,
// fields: [
// {
// name: "id",
// type: "UUID",
// default: "",
// check: "",
// primary: true,
// unique: true,
// notNull: true,
// increment: true,
// comment: "",
// },
// ],
// comment: "",
// indices: [],
// color: defaultTableTheme,
// };
// props.setTables((prev) => [...prev, newTable]);
// });
// });
// } catch (e) {
// alert("parsing error");
// }
}}
>
parse

View File

@ -1,4 +1,4 @@
import React, { useState } from "react";
import React, { useContext, useState } from "react";
import {
AutoComplete,
Collapse,
@ -23,6 +23,7 @@ import {
IllustrationNoContentDark,
} from "@douyinfe/semi-illustrations";
import { Cardinality, Constraint } from "../data/data";
import { TableContext } from "../pages/editor";
export default function ReferenceOverview(props) {
const columns = [
@ -35,6 +36,7 @@ export default function ReferenceOverview(props) {
dataIndex: "foreign",
},
];
const { tables } = useContext(TableContext);
const [refActiveIndex, setRefActiveIndex] = useState("");
const [value, setValue] = useState("");
const [filteredResult, setFilteredResult] = useState(
@ -108,11 +110,11 @@ export default function ReferenceOverview(props) {
<div className="flex justify-between items-center my-1">
<div className="me-3">
<strong>Primary: </strong>
{props.tables[r.endTableId].name}
{tables[r.endTableId].name}
</div>
<div className="mx-1">
<strong>Foreign: </strong>
{props.tables[r.startTableId].name}
{tables[r.startTableId].name}
</div>
<div className="ms-1">
<Popover
@ -123,19 +125,18 @@ export default function ReferenceOverview(props) {
dataSource={[
{
key: "1",
foreign: props.tables[r.startTableId].name,
primary: props.tables[r.endTableId].name,
foreign: tables[r.startTableId].name,
primary: tables[r.endTableId].name,
},
{
key: "2",
foreign:
props.tables[r.startTableId].fields[
tables[r.startTableId].fields[
r.startFieldId
].name,
primary:
props.tables[r.endTableId].fields[
r.endFieldId
].name,
tables[r.endTableId].fields[r.endFieldId]
.name,
},
]}
pagination={false}

View File

@ -12,13 +12,14 @@ import {
Button,
SideSheet,
} from "@douyinfe/semi-ui";
import { LayoutContext } from "../pages/editor";
import { LayoutContext, TableContext } from "../pages/editor";
export default function Table(props) {
const [isHovered, setIsHovered] = useState(false);
const [hoveredField, setHoveredField] = useState(-1);
const [visible, setVisible] = useState(false);
const {layout} = useContext(LayoutContext);
const {setTables} = useContext(TableContext);
// const [editFieldVisible, setEditFieldVisible] = useState(-1);
// const [field, setField] = useState({
// name: "",
@ -36,7 +37,7 @@ export default function Table(props) {
return (
<g>
<foreignObject
key={props.id}
key={props.tableData.id}
x={props.tableData.x}
y={props.tableData.y}
width={200}
@ -199,7 +200,7 @@ export default function Table(props) {
onMouseEnter={() => {
setHoveredField(i);
props.setOnRect({
tableId: props.id,
tableId: props.tableData.id,
field: i,
});
}}
@ -217,7 +218,7 @@ export default function Table(props) {
props.setLine((prev) => ({
...prev,
startFieldId: i,
startTableId: props.id,
startTableId: props.tableData.id,
startX: props.tableData.x + 15,
startY: props.tableData.y + i * 36 + 50 + 19,
endX: props.tableData.x + 15,
@ -237,13 +238,13 @@ export default function Table(props) {
backgroundColor: "#d42020",
}}
onClick={(ev) => {
props.setTables((prev) => {
setTables((prev) => {
const updatedTables = [...prev];
const updatedFields = [
...updatedTables[props.id].fields,
...updatedTables[props.tableData.id].fields,
];
updatedFields.splice(i, 1);
updatedTables[props.id].fields = [...updatedFields];
updatedTables[props.tableData.id].fields = [...updatedFields];
return updatedTables;
});
}}

View File

@ -1,4 +1,4 @@
import { React, useState } from "react";
import { React, useContext, useState } from "react";
import { defaultTableTheme, sqlDataTypes, tableThemes } from "../data/data";
import {
Collapse,
@ -27,20 +27,22 @@ import {
IllustrationNoContent,
IllustrationNoContentDark,
} from "@douyinfe/semi-illustrations";
import { TableContext } from "../pages/editor";
export default function TableOverview(props) {
const [indexActiveKey, setIndexActiveKey] = useState("");
const [tableActiveKey, setTableActiveKey] = useState("");
const [value, setValue] = useState("");
const { tables, setTables } = useContext(TableContext);
const [filteredResult, setFilteredResult] = useState(
props.tables.map((t) => {
tables.map((t) => {
return t.name;
})
);
const handleStringSearch = (value) => {
setFilteredResult(
props.tables
tables
.map((t) => {
return t.name;
})
@ -49,7 +51,7 @@ export default function TableOverview(props) {
};
const updatedField = (tid, fid, updatedValues) => {
props.setTables((prev) =>
setTables((prev) =>
prev.map((table, i) => {
if (tid === i) {
return {
@ -65,7 +67,7 @@ export default function TableOverview(props) {
};
const updateTable = (tid, updatedValues) => {
props.setTables((prev) =>
setTables((prev) =>
prev.map((table, i) => {
if (tid === i) {
return {
@ -92,7 +94,7 @@ export default function TableOverview(props) {
onSearch={(v) => handleStringSearch(v)}
onChange={(v) => setValue(v)}
onSelect={(v) => {
const { id } = props.tables.find((t) => t.name === v);
const { id } = tables.find((t) => t.name === v);
setTableActiveKey(`${id}`);
document
.getElementById(`scroll_table_${id}`)
@ -107,9 +109,7 @@ export default function TableOverview(props) {
block
onClick={() => {
const id =
props.tables.length === 0
? 0
: props.tables[props.tables.length - 1].id + 1;
tables.length === 0 ? 0 : tables[tables.length - 1].id + 1;
const newTable = {
id: id,
name: `table_${id}`,
@ -132,7 +132,7 @@ export default function TableOverview(props) {
indices: [],
color: defaultTableTheme,
};
props.setTables((prev) => [...prev, newTable]);
setTables((prev) => [...prev, newTable]);
}}
>
Add table
@ -144,7 +144,7 @@ export default function TableOverview(props) {
onChange={(k) => setTableActiveKey(k)}
accordion
>
{props.tables.length <= 0 ? (
{tables.length <= 0 ? (
<div className="select-none">
<Empty
image={
@ -160,7 +160,7 @@ export default function TableOverview(props) {
/>
</div>
) : (
props.tables.map((t, i) => (
tables.map((t, i) => (
<div id={`scroll_table_${t.id}`} key={t.id}>
<Collapse.Panel header={<div>{t.name}</div>} itemKey={`${t.id}`}>
{t.fields.map((f, j) => (
@ -296,7 +296,7 @@ export default function TableOverview(props) {
type="danger"
block
onClick={(ev) => {
props.setTables((prev) => {
setTables((prev) => {
const updatedTables = [...prev];
const updatedFields = [
...updatedTables[t.id].fields,
@ -349,7 +349,7 @@ export default function TableOverview(props) {
className="w-full"
defaultValue={idx.fields}
onChange={(value) => {
const updatedTables = [...props.tables];
const updatedTables = [...tables];
const updatedIndices = [...t.indices];
updatedIndices[k] = {
name: `${value.join("_")}_index`,
@ -359,7 +359,7 @@ export default function TableOverview(props) {
...t,
indices: [...updatedIndices],
};
props.setTables(updatedTables);
setTables(updatedTables);
}}
/>
<Popover
@ -379,14 +379,14 @@ export default function TableOverview(props) {
type="danger"
block
onClick={() => {
const updatedTables = [...props.tables];
const updatedTables = [...tables];
const updatedIndices = [...t.indices];
updatedIndices.splice(k, 1);
updatedTables[i] = {
...t,
indices: [...updatedIndices],
};
props.setTables(updatedTables);
setTables(updatedTables);
}}
>
Delete
@ -506,7 +506,7 @@ export default function TableOverview(props) {
block
onClick={() => {
setIndexActiveKey("1");
const updatedTables = [...props.tables];
const updatedTables = [...tables];
updatedTables[i] = {
...t,
indices: [
@ -514,7 +514,7 @@ export default function TableOverview(props) {
{ name: `index_${t.indices.length}`, fields: [] },
],
};
props.setTables(updatedTables);
setTables(updatedTables);
}}
>
Add index
@ -523,7 +523,7 @@ export default function TableOverview(props) {
<Col span={6}>
<Button
onClick={() => {
const updatedTables = [...props.tables];
const updatedTables = [...tables];
updatedTables[i].fields = [
...updatedTables[i].fields,
{
@ -537,7 +537,7 @@ export default function TableOverview(props) {
comment: "",
},
];
props.setTables(updatedTables);
setTables(updatedTables);
}}
block
>
@ -550,7 +550,7 @@ export default function TableOverview(props) {
type="danger"
onClick={() => {
Toast.success(`Table deleted!`);
props.setTables((prev) =>
setTables((prev) =>
prev
.filter((e) => e.id !== i)
.map((e, idx) => ({ ...e, id: idx }))

View File

@ -7,6 +7,7 @@ import Canvas from "../components/canvas";
import EditorPanel from "../components/editor_panel";
export const LayoutContext = createContext();
export const TableContext = createContext();
export default function Editor(props) {
const [code, setCode] = useState("");
@ -33,10 +34,12 @@ export default function Editor(props) {
if (w > 340) setWidth(w);
};
const value = {layout, setLayout};
const layoutValue = { layout, setLayout };
const tableValue = { tables, setTables };
return (
<LayoutContext.Provider value={value}>
<LayoutContext.Provider value={layoutValue}>
<TableContext.Provider value={tableValue}>
<div className="h-[100vh] overflow-hidden">
<ControlPanel />
<div
@ -51,8 +54,6 @@ export default function Editor(props) {
<DndProvider backend={HTML5Backend}>
{layout.sidebar && (
<EditorPanel
tables={tables}
setTables={setTables}
code={code}
setCode={setCode}
relationships={relationships}
@ -65,8 +66,6 @@ export default function Editor(props) {
/>
)}
<Canvas
tables={tables}
setTables={setTables}
code={code}
setCode={setCode}
relationships={relationships}
@ -78,6 +77,7 @@ export default function Editor(props) {
{layout.services && <Sidebar />}
</div>
</div>
</TableContext.Provider>
</LayoutContext.Provider>
);
}