Undo redo parsing for references

This commit is contained in:
1ilit 2023-09-19 15:50:46 +03:00
parent ab0dc2c44e
commit 2b2e4840c9
4 changed files with 197 additions and 135 deletions

View File

@ -195,19 +195,11 @@ export default function ControlPanel(props) {
} else if (a.component === "comment") { } else if (a.component === "comment") {
updateTable(a.tid, a.undo, false); updateTable(a.tid, a.undo, false);
} else if (a.component === "index_add") { } else if (a.component === "index_add") {
setTables((prev) => updateTable(a.tid, {
prev.map((table, i) => { indices: tables[a.tid].indices
if (table.id === a.tid) { .filter((e) => e.id !== tables[a.tid].indices.length - 1)
return { .map((t, i) => ({ ...t, id: i })),
...table, });
indices: table.indices
.filter((e) => e.id !== tables[a.tid].indices.length - 1)
.map((t, i) => ({ ...t, id: i })),
};
}
return table;
})
);
} else if (a.component === "index") { } else if (a.component === "index") {
updateTable(a.tid, { updateTable(a.tid, {
indices: tables[a.tid].indices.map((index) => indices: tables[a.tid].indices.map((index) =>
@ -236,6 +228,10 @@ export default function ControlPanel(props) {
} else if (a.component === "self") { } else if (a.component === "self") {
updateTable(a.tid, a.undo); updateTable(a.tid, a.undo);
} }
} else if (a.element === ObjectType.RELATIONSHIP) {
setRelationships((prev) =>
prev.map((e, idx) => (idx === a.rid ? { ...e, ...a.undo } : e))
);
} }
setRedoStack((prev) => [...prev, a]); setRedoStack((prev) => [...prev, a]);
} else if (a.action === Action.PAN) { } else if (a.action === Action.PAN) {
@ -365,6 +361,10 @@ export default function ControlPanel(props) {
} else if (a.component === "self") { } else if (a.component === "self") {
updateTable(a.tid, a.redo); updateTable(a.tid, a.redo);
} }
} else if (a.element === ObjectType.RELATIONSHIP) {
setRelationships((prev) =>
prev.map((e, idx) => (idx === a.rid ? { ...e, ...a.redo } : e))
);
} }
setUndoStack((prev) => [...prev, a]); setUndoStack((prev) => [...prev, a]);
} else if (a.action === Action.PAN) { } else if (a.action === Action.PAN) {
@ -1105,7 +1105,7 @@ export default function ControlPanel(props) {
!exportData.data), !exportData.data),
}} }}
cancelText="Cancel" cancelText="Cancel"
width={540} width={600}
> >
{visible === MODAL.IMPORT ? ( {visible === MODAL.IMPORT ? (
<div> <div>

View File

@ -3,9 +3,9 @@ import {
AutoComplete, AutoComplete,
Collapse, Collapse,
Empty, Empty,
Form,
Row, Row,
Col, Col,
Select,
Button, Button,
Checkbox, Checkbox,
Popover, Popover,
@ -22,8 +22,8 @@ import {
IllustrationNoContent, IllustrationNoContent,
IllustrationNoContentDark, IllustrationNoContentDark,
} from "@douyinfe/semi-illustrations"; } from "@douyinfe/semi-illustrations";
import { Cardinality, Constraint } from "../data/data"; import { Cardinality, Constraint, Action, ObjectType } from "../data/data";
import { TableContext } from "../pages/editor"; import { TableContext, UndoRedoContext } from "../pages/editor";
export default function ReferenceOverview(props) { export default function ReferenceOverview(props) {
const columns = [ const columns = [
@ -38,6 +38,7 @@ export default function ReferenceOverview(props) {
]; ];
const { tables, relationships, setRelationships, deleteRelationship } = const { tables, relationships, setRelationships, deleteRelationship } =
useContext(TableContext); useContext(TableContext);
const { setUndoStack, setRedoStack } = useContext(UndoRedoContext);
const [refActiveIndex, setRefActiveIndex] = useState(""); const [refActiveIndex, setRefActiveIndex] = useState("");
const [value, setValue] = useState(""); const [value, setValue] = useState("");
const [filteredResult, setFilteredResult] = useState( const [filteredResult, setFilteredResult] = useState(
@ -99,126 +100,177 @@ export default function ReferenceOverview(props) {
relationships.map((r, i) => ( relationships.map((r, i) => (
<div id={`scroll_ref_${r.id}`} key={i}> <div id={`scroll_ref_${r.id}`} key={i}>
<Collapse.Panel header={<div>{r.name}</div>} itemKey={`${i}`}> <Collapse.Panel header={<div>{r.name}</div>} itemKey={`${i}`}>
<Form <div className="flex justify-between items-center mb-3">
onChange={(value) => <div className="me-3">
<span className="font-semibold">Primary: </span>
{tables[r.endTableId].name}
</div>
<div className="mx-1">
<span className="font-semibold">Foreign: </span>
{tables[r.startTableId].name}
</div>
<div className="ms-1">
<Popover
content={
<div className="p-2">
<Table
columns={columns}
dataSource={[
{
key: "1",
foreign: `${tables[r.startTableId].name}(${
tables[r.startTableId].fields[r.startFieldId]
.name
})`,
primary: `${tables[r.endTableId].name}(${
tables[r.endTableId].fields[r.endFieldId].name
})`,
},
]}
pagination={false}
size="small"
bordered
/>
<div className="mt-2">
<Button icon={<IconLoopTextStroked />} block>
Swap
</Button>
</div>
</div>
}
trigger="click"
position="rightTop"
showArrow
>
<Button icon={<IconMore />} type="tertiary"></Button>
</Popover>
</div>
</div>
<div className="font-semibold my-1">Cardinality</div>
<Select
optionList={Object.values(Cardinality).map((v) => ({
label: v,
value: v,
}))}
value={r.cardinality}
className="w-full"
onChange={(value) => {
setUndoStack((prev) => [
...prev,
{
action: Action.EDIT,
element: ObjectType.RELATIONSHIP,
rid: i,
undo: { cardinality: r.cardinality },
redo: { cardinality: value },
},
]);
setRedoStack([]);
setRelationships((prev) => setRelationships((prev) =>
prev.map((e, idx) => prev.map((e, idx) =>
idx === i ? { ...e, ...value.values } : e idx === i ? { ...e, cardinality: value } : e
) )
) );
} }}
> ></Select>
<div className="flex justify-between items-center my-1"> <Row gutter={6} className="my-3">
<div className="me-3"> <Col span={12}>
<strong>Primary: </strong> <div className="font-semibold">On update: </div>
{tables[r.endTableId].name} <Select
</div> optionList={Object.values(Constraint).map((v) => ({
<div className="mx-1"> label: v,
<strong>Foreign: </strong> value: v,
{tables[r.startTableId].name} }))}
</div> value={r.updateConstraint}
<div className="ms-1"> className="w-full"
<Popover onChange={(value) => {
content={ setUndoStack((prev) => [
<div className="p-2 w-[260px]"> ...prev,
<Table {
columns={columns} action: Action.EDIT,
dataSource={[ element: ObjectType.RELATIONSHIP,
{ rid: i,
key: "1", undo: { updateConstraint: r.updateConstraint },
foreign: tables[r.startTableId].name, redo: { updateConstraint: value },
primary: tables[r.endTableId].name, },
}, ]);
{ setRedoStack([]);
key: "2",
foreign:
tables[r.startTableId].fields[
r.startFieldId
].name,
primary:
tables[r.endTableId].fields[r.endFieldId]
.name,
},
]}
pagination={false}
bordered
/>
<div className="mt-2">
<Button icon={<IconLoopTextStroked />} block>
Swap
</Button>
</div>
</div>
}
trigger="click"
position="rightTop"
showArrow
>
<Button icon={<IconMore />} type="tertiary"></Button>
</Popover>
</div>
</div>
<Form.Input initValue={r.name} field="name" label="Name" />
<Form.Select
optionList={Object.values(Cardinality).map((v) => ({
label: v,
value: v,
}))}
field="cardinality"
label="Cardinality"
initValue={r.cardinality}
className="w-full"
></Form.Select>
<Row gutter={6}>
<Col span={12}>
<Form.Select
optionList={Object.values(Constraint).map((v) => ({
label: v,
value: v,
}))}
field="updateConstraint"
label="On update"
initValue={r.updateConstraint}
className="w-full"
></Form.Select>
</Col>
<Col span={12}>
<Form.Select
optionList={Object.values(Constraint).map((v) => ({
label: v,
value: v,
}))}
field="deleteConstraint"
label="On delete"
initValue={r.deleteConstraint}
className="w-full"
></Form.Select>
</Col>
</Row>
<div className="flex justify-between items-center my-3">
<label htmlFor="unique" className="font-medium text-black">
Mandetory
</label>
<Checkbox
value="mandetory"
checked={r.mandetory}
onChange={(checkedValues) =>
setRelationships((prev) => setRelationships((prev) =>
prev.map((e, idx) => prev.map((e, idx) =>
idx === i idx === i ? { ...e, updateConstraint: value } : e
? {
...e,
[checkedValues.target.value]:
checkedValues.target.checked,
}
: e
) )
);
}}
></Select>
</Col>
<Col span={12}>
<div className="font-semibold">On delete: </div>
<Select
optionList={Object.values(Constraint).map((v) => ({
label: v,
value: v,
}))}
value={r.deleteConstraint}
className="w-full"
onChange={(value) => {
setUndoStack((prev) => [
...prev,
{
action: Action.EDIT,
element: ObjectType.RELATIONSHIP,
rid: i,
undo: { deleteConstraint: r.deleteConstraint },
redo: { deleteConstraint: value },
},
]);
setRedoStack([]);
setRelationships((prev) =>
prev.map((e, idx) =>
idx === i ? { ...e, deleteConstraint: value } : e
)
);
}}
></Select>
</Col>
</Row>
<div className="flex justify-between items-center my-3">
<div className="font-semibold">Mandetory</div>
<Checkbox
value="mandetory"
checked={r.mandetory}
onChange={(checkedValues) => {
setUndoStack((prev) => [
...prev,
{
action: Action.EDIT,
element: ObjectType.RELATIONSHIP,
rid: i,
undo: {
[checkedValues.target.value]:
!checkedValues.target.checked,
},
redo: {
[checkedValues.target.value]:
checkedValues.target.checked,
},
},
]);
setRedoStack([]);
setRelationships((prev) =>
prev.map((e, idx) =>
idx === i
? {
...e,
[checkedValues.target.value]:
checkedValues.target.checked,
}
: e
) )
} );
></Checkbox> }}
</div> ></Checkbox>
</Form> </div>
<Row gutter={6} className="mt-1"> <Row gutter={6} className="mt-3">
<Col span={12}> <Col span={12}>
<Button <Button
icon={<IconRowsStroked />} icon={<IconRowsStroked />}

View File

@ -48,11 +48,10 @@ const Cardinality = {
ONE_TO_ONE: "One to one", ONE_TO_ONE: "One to one",
ONE_TO_MANY: "One to many", ONE_TO_MANY: "One to many",
MANY_TO_ONE: "Many to one", MANY_TO_ONE: "Many to one",
MANY_TO_MANY: "Many to many",
}; };
const Constraint = { const Constraint = {
none: "None", none: "No action",
restrict: "Restrict", restrict: "Restrict",
cascade: "Cascade", cascade: "Cascade",
setNull: "Set null", setNull: "Set null",

View File

@ -48,7 +48,7 @@ function dataURItoBlob(dataUrl) {
} }
function jsonToSQL(obj) { function jsonToSQL(obj) {
return obj.tables return `${obj.tables
.map( .map(
(table) => (table) =>
`${ `${
@ -86,7 +86,7 @@ function jsonToSQL(obj) {
: "" : ""
}\n);\n${ }\n);\n${
table.indices.length > 0 table.indices.length > 0
? `${table.indices.map( ? `\n${table.indices.map(
(i) => (i) =>
`\nCREATE ${i.unique ? "UNIQUE " : ""}INDEX \`${ `\nCREATE ${i.unique ? "UNIQUE " : ""}INDEX \`${
i.name i.name
@ -97,7 +97,18 @@ function jsonToSQL(obj) {
: "" : ""
}` }`
) )
.join("\n\n"); .join("\n")}\n${obj.references
.map(
(r) =>
`ALTER TABLE \`${
obj.tables[r.startTableId].name
}\`\nADD FOREIGN KEY(\`${
obj.tables[r.startTableId].fields[r.startFieldId].name
}\`) REFERENCES \`${obj.tables[r.endTableId].name}\`(\`${
obj.tables[r.endTableId].fields[r.endFieldId].name
}\`)\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`
)
.join("\n")}`;
} }
export { export {