Fix precison for float bug

This commit is contained in:
1ilit 2024-01-18 12:45:58 +02:00
parent df9a3f8089
commit 6c65134c93
4 changed files with 235 additions and 184 deletions

20
package-lock.json generated
View File

@ -20,6 +20,7 @@
"jsonschema": "^1.4.1", "jsonschema": "^1.4.1",
"jspdf": "^2.5.1", "jspdf": "^2.5.1",
"lexical": "^0.12.5", "lexical": "^0.12.5",
"node-sql-parser": "^4.17.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-cookie": "^7.0.1", "react-cookie": "^7.0.1",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",
@ -1975,6 +1976,14 @@
"resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz", "resolved": "https://registry.npmjs.org/bezier-easing/-/bezier-easing-2.1.0.tgz",
"integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig==" "integrity": "sha512-gbIqZ/eslnUFC1tjEvtz0sgx+xTK20wDnYMIA27VA04R7w6xxXQPZDbibjA9DTWZRA2CXtwHykkVzlCaAJAZig=="
}, },
"node_modules/big-integer": {
"version": "1.6.52",
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz",
"integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==",
"engines": {
"node": ">=0.6"
}
},
"node_modules/binary-extensions": { "node_modules/binary-extensions": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
@ -4122,6 +4131,17 @@
"integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==", "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
"dev": true "dev": true
}, },
"node_modules/node-sql-parser": {
"version": "4.17.0",
"resolved": "https://registry.npmjs.org/node-sql-parser/-/node-sql-parser-4.17.0.tgz",
"integrity": "sha512-3IhovpmUBpcETnoKK/KBdkz2mz53kVG5E1dnqz1QuYvtzdxYZW5xaGGEvW9u6Yyy2ivwR3eUZrn9inmEVef02w==",
"dependencies": {
"big-integer": "^1.6.48"
},
"engines": {
"node": ">=8"
}
},
"node_modules/normalize-path": { "node_modules/normalize-path": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",

View File

@ -22,6 +22,7 @@
"jsonschema": "^1.4.1", "jsonschema": "^1.4.1",
"jspdf": "^2.5.1", "jspdf": "^2.5.1",
"lexical": "^0.12.5", "lexical": "^0.12.5",
"node-sql-parser": "^4.17.0",
"react": "^18.2.0", "react": "^18.2.0",
"react-cookie": "^7.0.1", "react-cookie": "^7.0.1",
"react-dom": "^18.2.0", "react-dom": "^18.2.0",

View File

@ -64,6 +64,7 @@ import { areaSchema, noteSchema, tableSchema } from "../data/schemas";
import { Editor } from "@monaco-editor/react"; import { Editor } from "@monaco-editor/react";
import { db } from "../data/db"; import { db } from "../data/db";
import { useLiveQuery } from "dexie-react-hooks"; import { useLiveQuery } from "dexie-react-hooks";
import { Parser } from "node-sql-parser";
import Todo from "./Todo"; import Todo from "./Todo";
export default function ControlPanel({ export default function ControlPanel({
@ -84,6 +85,7 @@ export default function ControlPanel({
OPEN: 5, OPEN: 5,
SAVEAS: 6, SAVEAS: 6,
NEW: 7, NEW: 7,
IMPORT_SRC: 8,
}; };
const STATUS = { const STATUS = {
NONE: 0, NONE: 0,
@ -823,10 +825,13 @@ export default function ControlPanel({
.catch(() => Toast.error("Oops! Something went wrong.")); .catch(() => Toast.error("Oops! Something went wrong."));
}, },
}, },
Import: { "Import diagram": {
function: fileImport, function: fileImport,
shortcut: "Ctrl+I", shortcut: "Ctrl+I",
}, },
"Import from source": {
function: () => setVisible(MODAL.IMPORT_SRC)
},
"Export as": { "Export as": {
children: [ children: [
{ {
@ -1172,6 +1177,7 @@ export default function ControlPanel({
const getModalTitle = () => { const getModalTitle = () => {
switch (visible) { switch (visible) {
case MODAL.IMPORT: case MODAL.IMPORT:
case MODAL.IMPORT_SRC:
return "Import diagram"; return "Import diagram";
case MODAL.CODE: case MODAL.CODE:
return "Export source"; return "Export source";
@ -1193,6 +1199,7 @@ export default function ControlPanel({
const getOkText = () => { const getOkText = () => {
switch (visible) { switch (visible) {
case MODAL.IMPORT: case MODAL.IMPORT:
case MODAL.IMPORT_SRC:
return "Import"; return "Import";
case MODAL.CODE: case MODAL.CODE:
case MODAL.IMG: case MODAL.IMG:
@ -1235,6 +1242,9 @@ export default function ControlPanel({
setRedoStack([]); setRedoStack([]);
} }
return; return;
case MODAL.IMPORT_SRC:
setVisible(MODAL.NONE)
return;
case MODAL.OPEN: case MODAL.OPEN:
if (selectedDiagramId === 0) return; if (selectedDiagramId === 0) return;
loadDiagram(selectedDiagramId); loadDiagram(selectedDiagramId);
@ -1373,6 +1383,76 @@ export default function ControlPanel({
); );
}; };
const importSrcModalBody = () => {
return (
<>
<Upload
action="#"
beforeUpload={({ file, fileList }) => {
const f = fileList[0].fileInstance;
if (!f) {
return;
}
const reader = new FileReader();
reader.onload = async (e) => {
console.log(e.target.result);
const parser = new Parser();
const ast = parser.astify(e.target.result);
console.log(ast);
};
reader.readAsText(f);
return {
autoRemove: false,
fileInstance: file.fileInstance,
status: "success",
shouldUpload: false,
};
}}
draggable={true}
dragMainText="Drag and drop the file here or click to upload."
dragSubText="Upload an sql file to autogenerate your tables and columns."
accept=".sql"
onRemove={() =>
setError({
type: STATUS.NONE,
message: "",
})
}
onFileChange={() =>
setError({
type: STATUS.NONE,
message: "",
})
}
limit={1}
></Upload>
{error.type === STATUS.ERROR ? (
<Banner
type="danger"
fullMode={false}
description={<div className="text-red-800">{error.message}</div>}
/>
) : error.type === STATUS.OK ? (
<Banner
type="info"
fullMode={false}
description={<div>{error.message}</div>}
/>
) : (
error.type === STATUS.WARNING && (
<Banner
type="warning"
fullMode={false}
description={<div>{error.message}</div>}
/>
)
)}
</>
);
};
const newModalBody = () => ( const newModalBody = () => (
<div className="h-[360px] grid grid-cols-3 gap-2 overflow-auto px-1"> <div className="h-[360px] grid grid-cols-3 gap-2 overflow-auto px-1">
<div> <div>
@ -1408,6 +1488,8 @@ export default function ControlPanel({
switch (visible) { switch (visible) {
case MODAL.IMPORT: case MODAL.IMPORT:
return importModalBody(); return importModalBody();
case MODAL.IMPORT_SRC:
return importSrcModalBody();
case MODAL.NEW: case MODAL.NEW:
return newModalBody(); return newModalBody();
case MODAL.RENAME: case MODAL.RENAME:

View File

@ -95,8 +95,8 @@ function getTypeString(field, dbms = "mysql") {
if (isSized(field.type)) { if (isSized(field.type)) {
return `${field.type}(${field.size})`; return `${field.type}(${field.size})`;
} }
if (hasPrecision(field.type) && field.size !== "") { if (hasPrecision(field.type)) {
return `${field.type}${field.size}`; return `${field.type}${field.size ? `(${field.size})` : ""}`;
} }
if (field.type === "SET" || field.type === "ENUM") { if (field.type === "SET" || field.type === "ENUM") {
return `${field.type}(${field.values.map((v) => `"${v}"`).join(", ")})`; return `${field.type}(${field.values.map((v) => `"${v}"`).join(", ")})`;
@ -132,8 +132,8 @@ function getTypeString(field, dbms = "mysql") {
field.type === "BINARY" field.type === "BINARY"
? "bit" ? "bit"
: field.type === "VARBINARY" : field.type === "VARBINARY"
? "bit varying" ? "bit varying"
: field.type.toLowerCase(); : field.type.toLowerCase();
return `${type}(${field.size})`; return `${type}(${field.size})`;
} }
if (hasPrecision(field.type) && field.size !== "") { if (hasPrecision(field.type) && field.size !== "") {
@ -161,68 +161,56 @@ function jsonToMySQL(obj) {
return `${obj.tables return `${obj.tables
.map( .map(
(table) => (table) =>
`${ `${table.comment === "" ? "" : `/* ${table.comment} */\n`
table.comment === "" ? "" : `/* ${table.comment} */\n`
}CREATE TABLE \`${table.name}\` (\n${table.fields }CREATE TABLE \`${table.name}\` (\n${table.fields
.map( .map(
(field) => (field) =>
`${field.comment === "" ? "" : `\t-- ${field.comment}\n`}\t\`${ `${field.comment === "" ? "" : `\t-- ${field.comment}\n`}\t\`${field.name
field.name }\` ${getTypeString(field)}${field.notNull ? " NOT NULL" : ""}${field.increment ? " AUTO_INCREMENT" : ""
}\` ${getTypeString(field)}${field.notNull ? " NOT NULL" : ""}${ }${field.unique ? " UNIQUE" : ""}${field.default !== ""
field.increment ? " AUTO_INCREMENT" : "" ? ` DEFAULT ${hasQuotes(field.type) &&
}${field.unique ? " UNIQUE" : ""}${ field.default.toLowerCase() !== "null"
field.default !== "" ? `"${field.default}"`
? ` DEFAULT ${ : `${field.default}`
hasQuotes(field.type) && }`
field.default.toLowerCase() !== "null" : ""
? `"${field.default}"` }${field.check === "" || !hasCheck(field.type)
: `${field.default}` ? !sqlDataTypes.includes(field.type)
}` ? ` CHECK(\n\t\tJSON_SCHEMA_VALID("${generateSchema(
obj.types.find(
(t) => t.name === field.type.toLowerCase()
)
)}", \`${field.name}\`))`
: "" : ""
}${ : ` CHECK(${field.check})`
field.check === "" || !hasCheck(field.type)
? !sqlDataTypes.includes(field.type)
? ` CHECK(\n\t\tJSON_SCHEMA_VALID("${generateSchema(
obj.types.find(
(t) => t.name === field.type.toLowerCase()
)
)}", \`${field.name}\`))`
: ""
: ` CHECK(${field.check})`
}` }`
) )
.join(",\n")}${ .join(",\n")}${table.fields.filter((f) => f.primary).length > 0
table.fields.filter((f) => f.primary).length > 0
? `,\n\tPRIMARY KEY(${table.fields ? `,\n\tPRIMARY KEY(${table.fields
.filter((f) => f.primary) .filter((f) => f.primary)
.map((f) => `\`${f.name}\``) .map((f) => `\`${f.name}\``)
.join(", ")})` .join(", ")})`
: ""
}\n);\n${
table.indices.length > 0
? `\n${table.indices.map(
(i) =>
`\nCREATE ${i.unique ? "UNIQUE " : ""}INDEX \`${
i.name
}\`\nON \`${table.name}\` (${i.fields
.map((f) => `\`${f}\``)
.join(", ")});`
)}`
: "" : ""
}\n);\n${table.indices.length > 0
? `\n${table.indices.map(
(i) =>
`\nCREATE ${i.unique ? "UNIQUE " : ""}INDEX \`${i.name
}\`\nON \`${table.name}\` (${i.fields
.map((f) => `\`${f}\``)
.join(", ")});`
)}`
: ""
}` }`
) )
.join("\n")}\n${obj.references .join("\n")}\n${obj.references
.map( .map(
(r) => (r) =>
`ALTER TABLE \`${ `ALTER TABLE \`${obj.tables[r.startTableId].name
obj.tables[r.startTableId].name }\`\nADD FOREIGN KEY(\`${obj.tables[r.startTableId].fields[r.startFieldId].name
}\`\nADD FOREIGN KEY(\`${ }\`) REFERENCES \`${obj.tables[r.endTableId].name}\`(\`${obj.tables[r.endTableId].fields[r.endFieldId].name
obj.tables[r.startTableId].fields[r.startFieldId].name }\`)\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`
}\`) REFERENCES \`${obj.tables[r.endTableId].name}\`(\`${ )
obj.tables[r.endTableId].fields[r.endFieldId].name .join("\n")}`;
}\`)\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`
)
.join("\n")}`;
} }
function jsonToPostgreSQL(obj) { function jsonToPostgreSQL(obj) {
@ -238,86 +226,73 @@ function jsonToPostgreSQL(obj) {
if (typeStatements.length > 0) { if (typeStatements.length > 0) {
return ( return (
typeStatements.join("") + typeStatements.join("") +
`${ `${type.comment === "" ? "" : `/**\n${type.comment}\n*/\n`
type.comment === "" ? "" : `/**\n${type.comment}\n*/\n`
}CREATE TYPE ${type.name} AS (\n${type.fields }CREATE TYPE ${type.name} AS (\n${type.fields
.map((f) => `\t${f.name} ${getTypeString(f, "postgres")}`) .map((f) => `\t${f.name} ${getTypeString(f, "postgres")}`)
.join("\n")}\n);` .join("\n")}\n);`
); );
} else { } else {
return `${ return `${type.comment === "" ? "" : `/**\n${type.comment}\n*/\n`
type.comment === "" ? "" : `/**\n${type.comment}\n*/\n` }CREATE TYPE ${type.name} AS (\n${type.fields
}CREATE TYPE ${type.name} AS (\n${type.fields .map((f) => `\t${f.name} ${getTypeString(f, "postgres")}`)
.map((f) => `\t${f.name} ${getTypeString(f, "postgres")}`) .join("\n")}\n);`;
.join("\n")}\n);`;
} }
})}\n${obj.tables })}\n${obj.tables
.map( .map(
(table) => (table) =>
`${table.comment === "" ? "" : `/**\n${table.comment}\n*/\n`}${ `${table.comment === "" ? "" : `/**\n${table.comment}\n*/\n`}${table.fields.filter((f) => f.type === "ENUM" || f.type === "SET")
table.fields.filter((f) => f.type === "ENUM" || f.type === "SET") .length > 0
.length > 0 ? `${table.fields
? `${table.fields .filter((f) => f.type === "ENUM" || f.type === "SET")
.filter((f) => f.type === "ENUM" || f.type === "SET") .map(
.map( (f) =>
(f) => `CREATE TYPE "${f.name}_t" AS ENUM (${f.values
`CREATE TYPE "${f.name}_t" AS ENUM (${f.values .map((v) => `'${v}'`)
.map((v) => `'${v}'`) .join(", ")});\n\n`
.join(", ")});\n\n` )}`
)}` : ""
: ""
}CREATE TABLE "${table.name}" (\n${table.fields }CREATE TABLE "${table.name}" (\n${table.fields
.map( .map(
(field) => (field) =>
`${field.comment === "" ? "" : `\t-- ${field.comment}\n`}\t"${ `${field.comment === "" ? "" : `\t-- ${field.comment}\n`}\t"${field.name
field.name }" ${getTypeString(field, "postgres")}${field.notNull ? " NOT NULL" : ""
}" ${getTypeString(field, "postgres")}${ }${field.default !== ""
field.notNull ? " NOT NULL" : "" ? ` DEFAULT ${hasQuotes(field.type) &&
}${ field.default.toLowerCase() !== "null"
field.default !== "" ? `'${field.default}'`
? ` DEFAULT ${ : `${field.default}`
hasQuotes(field.type) && }`
field.default.toLowerCase() !== "null" : ""
? `'${field.default}'` }${field.check === "" || !hasCheck(field.type)
: `${field.default}` ? ""
}` : ` CHECK(${field.check})`
: ""
}${
field.check === "" || !hasCheck(field.type)
? ""
: ` CHECK(${field.check})`
}` }`
) )
.join(",\n")}${ .join(",\n")}${table.fields.filter((f) => f.primary).length > 0
table.fields.filter((f) => f.primary).length > 0
? `,\n\tPRIMARY KEY(${table.fields ? `,\n\tPRIMARY KEY(${table.fields
.filter((f) => f.primary) .filter((f) => f.primary)
.map((f) => `"${f.name}"`) .map((f) => `"${f.name}"`)
.join(", ")})` .join(", ")})`
: ""
}\n);\n${
table.indices.length > 0
? `${table.indices.map(
(i) =>
`\nCREATE ${i.unique ? "UNIQUE " : ""}INDEX "${
i.name
}"\nON "${table.name}" (${i.fields
.map((f) => `"${f}"`)
.join(", ")});`
)}`
: "" : ""
}\n);\n${table.indices.length > 0
? `${table.indices.map(
(i) =>
`\nCREATE ${i.unique ? "UNIQUE " : ""}INDEX "${i.name
}"\nON "${table.name}" (${i.fields
.map((f) => `"${f}"`)
.join(", ")});`
)}`
: ""
}` }`
) )
.join("\n")}\n${obj.references .join("\n")}\n${obj.references
.map( .map(
(r) => (r) =>
`ALTER TABLE "${obj.tables[r.startTableId].name}"\nADD FOREIGN KEY("${ `ALTER TABLE "${obj.tables[r.startTableId].name}"\nADD FOREIGN KEY("${obj.tables[r.startTableId].fields[r.startFieldId].name
obj.tables[r.startTableId].fields[r.startFieldId].name }") REFERENCES "${obj.tables[r.endTableId].name}"("${obj.tables[r.endTableId].fields[r.endFieldId].name
}") REFERENCES "${obj.tables[r.endTableId].name}"("${ }")\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};`
obj.tables[r.endTableId].fields[r.endFieldId].name )
}")\nON UPDATE ${r.updateConstraint.toUpperCase()} ON DELETE ${r.deleteConstraint.toUpperCase()};` .join("\n")}`;
)
.join("\n")}`;
} }
function arrayIsEqual(arr1, arr2) { function arrayIsEqual(arr1, arr2) {
@ -325,13 +300,13 @@ function arrayIsEqual(arr1, arr2) {
} }
function isSized(type) { function isSized(type) {
return ["CHAR", "VARCHAR", "BINARY", "VARBINARY", "TEXT", "FLOAT"].includes( return ["CHAR", "VARCHAR", "BINARY", "VARBINARY", "TEXT"].includes(
type type
); );
} }
function hasPrecision(type) { function hasPrecision(type) {
return ["DOUBLE", "NUMERIC", "DECIMAL"].includes(type); return ["DOUBLE", "NUMERIC", "DECIMAL", "FLOAT"].includes(type);
} }
function hasCheck(type) { function hasCheck(type) {
@ -569,11 +544,9 @@ function validateDiagram(diagram) {
diagram.tables[r.startTableId].fields[r.startFieldId].type !== diagram.tables[r.startTableId].fields[r.startFieldId].type !==
diagram.tables[r.endTableId].fields[r.endFieldId].type diagram.tables[r.endTableId].fields[r.endFieldId].type
) { ) {
issues.push(`Referencing column "${ issues.push(`Referencing column "${diagram.tables[r.endTableId].fields[r.endFieldId].name
diagram.tables[r.endTableId].fields[r.endFieldId].name }" and referenced column "${diagram.tables[r.startTableId].fields[r.startFieldId].name
}" and referenced column "${ }" are incompatible.
diagram.tables[r.startTableId].fields[r.startFieldId].name
}" are incompatible.
`); `);
} }
}); });
@ -632,81 +605,56 @@ const calcPath = (x1, x2, y1, y2, startFieldId, endFieldId, zoom = 1) => {
if (y1 <= y2) { if (y1 <= y2) {
if (x1 + tableWidth <= x2) { if (x1 + tableWidth <= x2) {
return `M ${x1 + tableWidth - offsetX * 2} ${y1} L ${ return `M ${x1 + tableWidth - offsetX * 2} ${y1} L ${midX - r
midX - r } ${y1} A ${r} ${r} 0 0 1 ${midX} ${y1 + r} L ${midX} ${y2 - r
} ${y1} A ${r} ${r} 0 0 1 ${midX} ${y1 + r} L ${midX} ${ } A ${r} ${r} 0 0 0 ${midX + r} ${y2} L ${endX} ${y2}`;
y2 - r
} A ${r} ${r} 0 0 0 ${midX + r} ${y2} L ${endX} ${y2}`;
} else if (x2 <= x1 + tableWidth && x1 <= x2) { } else if (x2 <= x1 + tableWidth && x1 <= x2) {
return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${ return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${x2 + tableWidth
x2 + tableWidth } ${y1} A ${r} ${r} 0 0 1 ${x2 + tableWidth + r} ${y1 + r} L ${x2 + tableWidth + r
} ${y1} A ${r} ${r} 0 0 1 ${x2 + tableWidth + r} ${y1 + r} L ${ } ${y2 - r} A ${r} ${r} 0 0 1 ${x2 + tableWidth} ${y2} L ${x2 + tableWidth - 2 * offsetX
x2 + tableWidth + r } ${y2}`;
} ${y2 - r} A ${r} ${r} 0 0 1 ${x2 + tableWidth} ${y2} L ${
x2 + tableWidth - 2 * offsetX
} ${y2}`;
} else if (x2 + tableWidth >= x1 && x2 + tableWidth <= x1 + tableWidth) { } else if (x2 + tableWidth >= x1 && x2 + tableWidth <= x1 + tableWidth) {
return `M ${x1} ${y1} L ${x2 - r} ${y1} A ${r} ${r} 0 0 0 ${x2 - r - r} ${ return `M ${x1} ${y1} L ${x2 - r} ${y1} A ${r} ${r} 0 0 0 ${x2 - r - r} ${y1 + r
y1 + r } L ${x2 - r - r} ${y2 - r} A ${r} ${r} 0 0 0 ${x2 - r
} L ${x2 - r - r} ${y2 - r} A ${r} ${r} 0 0 0 ${ } ${y2} L ${x2} ${y2}`;
x2 - r
} ${y2} L ${x2} ${y2}`;
} else { } else {
return `M ${x1} ${y1} L ${midX + r} ${y1} A ${r} ${r} 0 0 0 ${midX} ${ return `M ${x1} ${y1} L ${midX + r} ${y1} A ${r} ${r} 0 0 0 ${midX} ${y1 + r
y1 + r } L ${midX} ${y2 - r} A ${r} ${r} 0 0 1 ${midX - r
} L ${midX} ${y2 - r} A ${r} ${r} 0 0 1 ${ } ${y2} L ${endX} ${y2}`;
midX - r
} ${y2} L ${endX} ${y2}`;
} }
} else { } else {
if (x1 + tableWidth <= x2) { if (x1 + tableWidth <= x2) {
return `M ${x1 + tableWidth - offsetX * 2} ${y1} L ${ return `M ${x1 + tableWidth - offsetX * 2} ${y1} L ${midX - r
midX - r } ${y1} A ${r} ${r} 0 0 0 ${midX} ${y1 - r} L ${midX} ${y2 + r
} ${y1} A ${r} ${r} 0 0 0 ${midX} ${y1 - r} L ${midX} ${ } A ${r} ${r} 0 0 1 ${midX + r} ${y2} L ${endX} ${y2}`;
y2 + r
} A ${r} ${r} 0 0 1 ${midX + r} ${y2} L ${endX} ${y2}`;
} else if (x1 + tableWidth >= x2 && x1 + tableWidth <= x2 + tableWidth) { } else if (x1 + tableWidth >= x2 && x1 + tableWidth <= x2 + tableWidth) {
// this for the overlap remember // this for the overlap remember
if (startTableY < y2) { if (startTableY < y2) {
return `M ${x1} ${y1} L ${x1 - r - r} ${y1} A ${r} ${r} 0 0 1 ${ return `M ${x1} ${y1} L ${x1 - r - r} ${y1} A ${r} ${r} 0 0 1 ${x1 - r - r - r
x1 - r - r - r } ${y1 - r} L ${x1 - r - r - r} ${y2 + r} A ${r} ${r} 0 0 1 ${x1 - r - r
} ${y1 - r} L ${x1 - r - r - r} ${y2 + r} A ${r} ${r} 0 0 1 ${ } ${y2} L ${x1 - r - 4} ${y2}`;
x1 - r - r
} ${y2} L ${x1 - r - 4} ${y2}`;
} }
return `M ${x1} ${y1} L ${x1 - r - r} ${y1} A ${r} ${r} 0 0 1 ${ return `M ${x1} ${y1} L ${x1 - r - r} ${y1} A ${r} ${r} 0 0 1 ${x1 - r - r - r
x1 - r - r - r } ${y1 - r} L ${x1 - r - r - r} ${y2 + r} A ${r} ${r} 0 0 1 ${x1 - r - r
} ${y1 - r} L ${x1 - r - r - r} ${y2 + r} A ${r} ${r} 0 0 1 ${ } ${y2} L ${endX} ${y2}`;
x1 - r - r
} ${y2} L ${endX} ${y2}`;
} else if (x1 >= x2 && x1 <= x2 + tableWidth) { } else if (x1 >= x2 && x1 <= x2 + tableWidth) {
// this for the overlap remember // this for the overlap remember
if (startTableY < y2) { if (startTableY < y2) {
return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${ return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${x1 + tableWidth - 2 * offsetX + r
x1 + tableWidth - 2 * offsetX + r } ${y1} A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r + r} ${y1 - r
} ${y1} A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r + r} ${ } L ${x1 + tableWidth - 2 * offsetX + r + r} ${y2 + r
y1 - r } A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r} ${y2} L ${x1 + tableWidth - 16
} L ${x1 + tableWidth - 2 * offsetX + r + r} ${ } ${y2}`;
y2 + r
} A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r} ${y2} L ${
x1 + tableWidth - 16
} ${y2}`;
} }
return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${ return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${x1 + tableWidth - 2 * offsetX + r
x1 + tableWidth - 2 * offsetX + r } ${y1} A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r + r} ${y1 - r
} ${y1} A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r + r} ${ } L ${x1 + tableWidth - 2 * offsetX + r + r} ${y2 + r
y1 - r } A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r} ${y2} L ${x2 + tableWidth - 2 * offsetX
} L ${x1 + tableWidth - 2 * offsetX + r + r} ${ } ${y2}`;
y2 + r
} A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r} ${y2} L ${
x2 + tableWidth - 2 * offsetX
} ${y2}`;
} else { } else {
return `M ${x1} ${y1} L ${midX + r} ${y1} A ${r} ${r} 0 0 1 ${midX} ${ return `M ${x1} ${y1} L ${midX + r} ${y1} A ${r} ${r} 0 0 1 ${midX} ${y1 - r
y1 - r } L ${midX} ${y2 + r} A ${r} ${r} 0 0 0 ${midX - r
} L ${midX} ${y2 + r} A ${r} ${r} 0 0 0 ${ } ${y2} L ${endX} ${y2}`;
midX - r
} ${y2} L ${endX} ${y2}`;
} }
} }
}; };