diff --git a/src/components/control_panel.jsx b/src/components/control_panel.jsx index b31bbac..4c34334 100644 --- a/src/components/control_panel.jsx +++ b/src/components/control_panel.jsx @@ -48,6 +48,7 @@ import { SettingsContext, TabContext, TableContext, + TypeContext, UndoRedoContext, } from "../pages/editor"; import { IconAddTable, IconAddArea, IconAddNote } from "./custom_icons"; @@ -96,6 +97,8 @@ export default function ControlPanel(props) { addRelationship, deleteRelationship, } = useContext(TableContext); + const { types, addType, deleteType, updateType, setTypes } = + useContext(TypeContext); const { notes, setNotes, updateNote, addNote, deleteNote } = useContext(NoteContext); const { areas, setAreas, updateArea, addArea, deleteArea } = @@ -136,6 +139,8 @@ export default function ControlPanel(props) { deleteNote(notes[notes.length - 1].id, false); } else if (a.element === ObjectType.RELATIONSHIP) { deleteRelationship(a.data.id, false); + } else if (a.element === ObjectType.TYPE) { + deleteType(types.length - 1, false); } setRedoStack((prev) => [...prev, a]); } else if (a.action === Action.MOVE) { @@ -167,6 +172,8 @@ export default function ControlPanel(props) { addNote(false, a.data); } else if (a.element === ObjectType.AREA) { addArea(false, a.data); + } else if (a.element === ObjectType.TYPE) { + addType(false, { id: a.id, ...a.data }); } setRedoStack((prev) => [...prev, a]); } else if (a.action === Action.EDIT) { @@ -232,6 +239,34 @@ export default function ControlPanel(props) { setRelationships((prev) => prev.map((e, idx) => (idx === a.rid ? { ...e, ...a.undo } : e)) ); + } else if (a.element === ObjectType.TYPE) { + if (a.component === "field_add") { + updateType(a.tid, { + fields: types[a.tid].fields.filter( + (e, i) => i !== types[a.tid].fields.length - 1 + ), + }); + } + if (a.component === "field") { + updateType(a.tid, { + fields: types[a.tid].fields.map((e, i) => + i === a.fid ? { ...e, ...a.undo } : e + ), + }); + } else if (a.component === "field_delete") { + setTypes((prev) => + prev.map((t, i) => { + if (i === a.tid) { + const temp = t.fields.slice(); + temp.splice(a.fid, 0, a.data); + return { ...t, fields: temp }; + } + return t; + }) + ); + } else if (a.component === "self") { + updateType(a.tid, a.undo); + } } setRedoStack((prev) => [...prev, a]); } else if (a.action === Action.PAN) { @@ -255,6 +290,8 @@ export default function ControlPanel(props) { addNote(false); } else if (a.element === ObjectType.RELATIONSHIP) { addRelationship(false, a.data); + } else if (a.element === ObjectType.TYPE) { + addType(false); } setUndoStack((prev) => [...prev, a]); } else if (a.action === Action.MOVE) { @@ -286,6 +323,8 @@ export default function ControlPanel(props) { deleteNote(a.data.id, false); } else if (a.element === ObjectType.AREA) { deleteArea(a.data.id, false); + } else if (a.element === ObjectType.TYPE) { + deleteType(a.id, false); } setUndoStack((prev) => [...prev, a]); } else if (a.action === Action.EDIT) { @@ -363,6 +402,30 @@ export default function ControlPanel(props) { setRelationships((prev) => prev.map((e, idx) => (idx === a.rid ? { ...e, ...a.redo } : e)) ); + } else if (a.element === ObjectType.TYPE) { + if (a.component === "field_add") { + updateType(a.tid, { + fields: [ + ...types[a.tid].fields, + { + name: "", + type: "", + }, + ], + }); + } else if (a.component === "field") { + updateType(a.tid, { + fields: types[a.tid].fields.map((e, i) => + i === a.fid ? { ...e, ...a.redo } : e + ), + }); + } else if (a.component === "field_delete") { + updateType(a.tid, { + fields: types[a.tid].fields.filter((field, i) => i !== a.fid), + }); + } else if (a.component === "self") { + updateType(a.tid, a.redo); + } } setUndoStack((prev) => [...prev, a]); } else if (a.action === Action.PAN) { diff --git a/src/components/editor_panel.jsx b/src/components/editor_panel.jsx index c553700..603ccff 100644 --- a/src/components/editor_panel.jsx +++ b/src/components/editor_panel.jsx @@ -7,6 +7,7 @@ import { Tab } from "../data/data"; import { LayoutContext, TabContext } from "../pages/editor"; import NotesOverview from "./notes_overview"; import Issues from "./issues"; +import TypesOverview from "./types_overview"; const EditorPanel = (props) => { const { tab, setTab } = useContext(TabContext); @@ -17,12 +18,14 @@ const EditorPanel = (props) => { { tab: "Relationships", itemKey: Tab.relationships }, { tab: "Subject Areas", itemKey: Tab.subject_areas }, { tab: "Notes", itemKey: Tab.notes }, + { tab: "Types", itemKey: Tab.types }, ]; const contentList = [ , , , , + , ]; return ( diff --git a/src/components/types_overview.jsx b/src/components/types_overview.jsx new file mode 100644 index 0000000..4acdc4d --- /dev/null +++ b/src/components/types_overview.jsx @@ -0,0 +1,329 @@ +import { React, useContext, useState } from "react"; +import { Action, ObjectType, sqlDataTypes } from "../data/data"; +import { + Collapse, + Row, + Col, + Input, + TextArea, + Button, + Card, + Select, + AutoComplete, + Toast, + Empty, + Popover, +} from "@douyinfe/semi-ui"; +import { + IconDeleteStroked, + IconPlus, + IconSearch, + IconInfoCircle, +} from "@douyinfe/semi-icons"; +import { + IllustrationNoContent, + IllustrationNoContentDark, +} from "@douyinfe/semi-illustrations"; +import { TypeContext, UndoRedoContext } from "../pages/editor"; + +export default function TableOverview(props) { + const [value, setValue] = useState(""); + const { types, addType, deleteType, updateType } = useContext(TypeContext); + const { setUndoStack, setRedoStack } = useContext(UndoRedoContext); + const [editField, setEditField] = useState({}); + const [filteredResult, setFilteredResult] = useState( + types.map((t) => { + return t.name; + }) + ); + + const handleStringSearch = (value) => { + setFilteredResult( + types + .map((t) => { + return t.name; + }) + .filter((i) => i.includes(value)) + ); + }; + + return ( + <> + + + } + placeholder="Search..." + onSearch={(v) => handleStringSearch(v)} + emptyContent={ +
No types found
+ } + onChange={(v) => setValue(v)} + onSelect={(v) => { + const i = types.findIndex((t) => t.name === v); + document + .getElementById(`scroll_type_${i}`) + .scrollIntoView({ behavior: "smooth" }); + }} + className="w-full" + /> + + + + + + + This feature is meant for object-relational DMSMs like + PostgreSQL. However, if used for relational DMSMs, a JSON type + will be generated with the custom type schema. + + } + showArrow + position="right" + > + + +
+ ))} + + + +