import { React, useContext, useState } from "react"; import { Action, ObjectType, defaultTableTheme, sqlDataTypes, tableThemes, } from "../data/data"; import { Collapse, Row, Col, Input, TextArea, Button, Card, Popover, Checkbox, Select, AutoComplete, Toast, Empty, } from "@douyinfe/semi-ui"; import { IconMore, IconKeyStroked, IconDeleteStroked, IconCheckboxTick, IconPlus, IconSearch, } from "@douyinfe/semi-icons"; import { IllustrationNoContent, IllustrationNoContentDark, } from "@douyinfe/semi-illustrations"; import { TableContext, UndoRedoContext } from "../pages/editor"; export default function TableOverview(props) { const [indexActiveKey, setIndexActiveKey] = useState(""); const [value, setValue] = useState(""); const { tables, setTables, addTable, deleteTable, updateField } = useContext(TableContext); const { setUndoStack, setRedoStack } = useContext(UndoRedoContext); const [editField, setEditField] = useState({}); const [filteredResult, setFilteredResult] = useState( tables.map((t) => { return t.name; }) ); const handleStringSearch = (value) => { setFilteredResult( tables .map((t) => { return t.name; }) .filter((i) => i.includes(value)) ); }; const updateTable = (tid, updatedValues) => { setTables((prev) => prev.map((table, i) => { if (tid === i) { return { ...table, ...updatedValues, }; } return table; }) ); }; return ( <> } placeholder="Search..." emptyContent={No tables found} onSearch={(v) => handleStringSearch(v)} onChange={(v) => setValue(v)} onSelect={(v) => { const { id } = tables.find((t) => t.name === v); props.setSelectedTable(`${id}`); document .getElementById(`scroll_table_${id}`) .scrollIntoView({ behavior: "smooth" }); }} className="w-full" /> } block onClick={() => addTable(true)}> Add table props.setSelectedTable(k)} accordion > {tables.length <= 0 ? ( } darkModeImage={ } title="No tables" description="Start building your diagram!" /> ) : ( tables.map((t, i) => ( {t.name}} itemKey={`${t.id}`}> {t.fields.map((f, j) => ( updateField(i, j, { name: value })} onFocus={(e) => setEditField({ tid: i, fid: j, values: { name: e.target.value }, }) } onBlur={(e) => { if (e.target.value === editField.name) return; setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "field", data: { undo: editField, redo: { tid: i, fid: j, values: { name: e.target.value }, }, }, }, ]); setRedoStack([]); setEditField({}); }} /> { return { label: value, value: value, }; })} filter value={f.type} placeholder="Type" onChange={(value) => { if (value === f.type) return; setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "field", data: { undo: { tid: i, fid: j, values: { type: f.type }, }, redo: { tid: i, fid: j, values: { type: value }, }, }, }, ]); setRedoStack([]); setEditField({}); updateField(i, j, { type: value }); }} > { setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "field", data: { undo: { tid: i, fid: j, values: { notNull: f.notNull }, }, redo: { tid: i, fid: j, values: { notNull: !f.notNull }, }, }, }, ]); setRedoStack([]); setEditField({}); updateField(i, j, { notNull: !f.notNull }); }} > ? { setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "field", data: { undo: { tid: i, fid: j, values: { primary: f.primary }, }, redo: { tid: i, fid: j, values: { primary: !f.primary }, }, }, }, ]); setRedoStack([]); setEditField({}); updateField(i, j, { primary: !f.primary }); }} icon={} > Default value updateField(i, j, { default: value }) } onFocus={(e) => setEditField({ tid: i, fid: j, values: { default: e.target.value }, }) } onBlur={(e) => { if (e.target.value === editField.default) return; setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "field", data: { undo: editField, redo: { tid: i, fid: j, values: { default: e.target.value }, }, }, }, ]); setRedoStack([]); setEditField({}); }} /> Check Expression updateField(i, j, { check: value }) } onFocus={(e) => setEditField({ tid: i, fid: j, values: { check: e.target.value }, }) } onBlur={(e) => { if (e.target.value === editField.check) return; setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "field", data: { undo: editField, redo: { tid: i, fid: j, values: { check: e.target.value }, }, }, }, ]); setRedoStack([]); setEditField({}); }} /> Unique { setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "field", data: { undo: { tid: i, fid: j, values: { [checkedValues.target.value]: !checkedValues.target.checked, }, }, redo: { tid: i, fid: j, values: { [checkedValues.target.value]: checkedValues.target.checked, }, }, }, }, ]); setRedoStack([]); setEditField({}); updateField(i, j, { [checkedValues.target.value]: checkedValues.target.checked, }); }} > Autoincrement { setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "field", data: { undo: { tid: i, fid: j, values: { [checkedValues.target.value]: !checkedValues.target.checked, }, }, redo: { tid: i, fid: j, values: { [checkedValues.target.value]: checkedValues.target.checked, }, }, }, }, ]); setRedoStack([]); setEditField({}); updateField(i, j, { [checkedValues.target.value]: checkedValues.target.checked, }); }} > Comment updateField(i, j, { comment: value }) } onFocus={(e) => setEditField({ tid: i, fid: j, values: { comment: e.target.value }, }) } onBlur={(e) => { if (e.target.value === editField.comment) return; setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "field", data: { undo: editField, redo: { tid: i, fid: j, values: { comment: e.target.value }, }, }, }, ]); setRedoStack([]); setEditField({}); }} /> } type="danger" block onClick={() => { setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "field_delete", tid: t.id, data: f, }, ]); setRedoStack([]); setTables((prev) => prev.map((table) => { if (table.id === i) { return { ...table, fields: table.fields.filter( (field, k) => k !== j ), }; } return table; }) ); }} > Delete field } trigger="click" position="rightTop" showArrow > }> ))} {t.indices.length > 0 && ( setIndexActiveKey(itemKey)} accordion > {t.indices.map((idx, k) => ( ({ value: e.name, label: e.name, }))} className="w-full" value={idx.fields} onChange={(value) => { setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "index", tid: i, iid: k, undo: { values: { fields: [...idx.fields], name: `${idx.fields.join("_")}_index`, }, }, redo: { values: { fields: [...value], name: `${value.join("_")}_index`, }, }, }, ]); setRedoStack([]); setEditField({}); setTables((prev) => prev.map((table, i) => { if (table.id === i) { return { ...table, indices: table.indices.map((index) => index.id === k ? { ...index, fields: [...value], name: `${value.join( "_" )}_index`, } : index ), }; } return table; }) ); }} /> } type="danger" block onClick={() => { setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "index_delete", tid: t.id, data: idx, }, ]); setRedoStack([]); setTables((prev) => prev.map((table) => { if (table.id === i) { return { ...table, indices: table.indices .filter( (index) => index.id !== idx.id ) .map((e, j) => ({ ...e, id: j, })), }; } return table; }) ); }} > Delete } trigger="click" position="rightTop" showArrow > } type="tertiary" style={{ marginLeft: "12px" }} > ))} )} updateTable(i, { comment: "" })} value={t.comment} autosize placeholder="Add comment" rows={1} onChange={(value) => updateTable(i, { comment: value })} onFocus={(e) => setEditField({ tid: t.id, values: { comment: e.target.value }, }) } onBlur={(e) => { if (e.target.value === editField.comment) return; setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "comment", data: { undo: editField, redo: { tid: i, values: { comment: e.target.value }, }, }, }, ]); setRedoStack([]); setEditField({}); }} /> Theme updateTable(i, { color: defaultTableTheme }) } > Clear {tableThemes .slice(0, Math.ceil(tableThemes.length / 2)) .map((c) => ( updateTable(i, { color: c })} > {t.color === c ? ( ) : ( )} ))} {tableThemes .slice(Math.ceil(tableThemes.length / 2)) .map((c) => ( updateTable(i, { color: c })} > ))} } trigger="click" position="bottomLeft" showArrow > { setIndexActiveKey("1"); setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "index_add", tid: t.id, }, ]); setRedoStack([]); setTables((prev) => prev.map((table) => { if (table.id === i) { return { ...table, indices: [ ...table.indices, { id: table.indices.length, name: `index_${table.indices.length}`, fields: [], }, ], }; } return table; }) ); }} > Add index { setUndoStack((prev) => [ ...prev, { action: Action.EDIT, element: ObjectType.TABLE, component: "field_add", tid: t.id, }, ]); setRedoStack([]); setTables((prev) => prev.map((table) => { if (table.id === i) { return { ...table, fields: [ ...table.fields, { name: "", type: "", default: "", check: "", primary: false, unique: false, notNull: false, increment: false, comment: "", id: table.fields.length, }, ], }; } return table; }) ); }} block > Add field } type="danger" onClick={() => { Toast.success(`Table deleted!`); deleteTable(i); props.setSelectedTable(""); }} > )) )} > ); }