Declutter utils

This commit is contained in:
1ilit 2024-03-11 02:45:44 +02:00
parent 680d349380
commit 787b7b9817
15 changed files with 285 additions and 294 deletions

View File

@ -37,17 +37,12 @@ import todo from "../assets/calendar.png";
import { toPng, toJpeg, toSvg } from "html-to-image";
import { saveAs } from "file-saver";
import {
jsonDiagramIsValid,
enterFullscreen,
exitFullscreen,
ddbDiagramIsValid,
dataURItoBlob,
jsonToMySQL,
jsonToPostgreSQL,
jsonToSQLite,
jsonToMariaDB,
jsonToSQLServer,
} from "../utils";
} from "../utils/toSQL";
import {
AreaContext,
NoteContext,
@ -73,6 +68,9 @@ import useTransform from "../hooks/useTransform";
import useTables from "../hooks/useTables";
import useUndoRedo from "../hooks/useUndoRedo";
import useSelect from "../hooks/useSelect";
import { enterFullscreen, exitFullscreen } from "../utils/fullscreen";
import { ddbDiagramIsValid, jsonDiagramIsValid } from "../utils/validateSchema";
import { dataURItoBlob } from "../utils/utils";
export default function ControlPanel({
diagramId,

View File

@ -1,7 +1,7 @@
import { Divider, Tooltip } from "@douyinfe/semi-ui";
import { exitFullscreen } from "../utils";
import useTransform from "../hooks/useTransform";
import useLayout from "../hooks/useLayout";
import { exitFullscreen } from "../utils/fullscreen";
export default function Controls() {
const { transform, setTransform } = useTransform();

View File

@ -1,9 +1,10 @@
import { useContext, useState, useEffect } from "react";
import { Collapse, Badge } from "@douyinfe/semi-ui";
import { TypeContext } from "../pages/Editor";
import { validateDiagram, arrayIsEqual } from "../utils";
import { validateDiagram } from "../utils/toSQL";
import useSettings from "../hooks/useSettings";
import useTables from "../hooks/useTables";
import { arrayIsEqual } from "../utils/utils";
export default function Issues() {
const { settings } = useSettings();

View File

@ -1,7 +1,7 @@
import { useRef } from "react";
import { calcPath } from "../utils";
import { Cardinality } from "../data/data";
import useSettings from "../hooks/useSettings";
import { calcPath } from "../utils/calcPath";
export default function Relationship({ data }) {
const { settings } = useSettings();
@ -50,14 +50,7 @@ export default function Relationship({ data }) {
<g className="select-none group">
<path
ref={pathRef}
d={calcPath(
data.startX,
data.endX,
data.startY,
data.endY,
data.startFieldId,
data.endFieldId
)}
d={calcPath(data.startX, data.endX, data.startY, data.endY)}
stroke="gray"
className="group-hover:stroke-sky-700"
fill="none"

View File

@ -1,6 +1,6 @@
import { useEffect, useState, useRef } from "react";
import { Cardinality } from "../data/data";
import { calcPath } from "../utils";
import { calcPath } from "../utils/calcPath";
function Table({ table, grab }) {
const [isHovered, setIsHovered] = useState(false);
@ -19,8 +19,9 @@ function Table({ table, grab }) {
onMouseLeave={() => setIsHovered(false)}
>
<div
className={`border-2 ${isHovered ? "border-dashed border-blue-500" : "border-zinc-300"
} select-none rounded-lg w-full bg-zinc-100 text-zinc-800`}
className={`border-2 ${
isHovered ? "border-dashed border-blue-500" : "border-zinc-300"
} select-none rounded-lg w-full bg-zinc-100 text-zinc-800`}
>
<div
className={`h-[10px] w-full rounded-t-md`}
@ -32,8 +33,9 @@ function Table({ table, grab }) {
{table.fields.map((e, i) => (
<div
key={i}
className={`${i === table.fields.length - 1 ? "" : "border-b border-gray-400"
} h-[36px] px-2 py-1 flex justify-between`}
className={`${
i === table.fields.length - 1 ? "" : "border-b border-gray-400"
} h-[36px] px-2 py-1 flex justify-between`}
onMouseEnter={() => setHoveredField(i)}
onMouseLeave={() => setHoveredField(-1)}
>
@ -99,9 +101,7 @@ function Relationship({ relationship }) {
relationship.startX,
relationship.endX,
relationship.startY,
relationship.endY,
relationship.startFieldId,
relationship.endFieldId
relationship.endY
)}
stroke="gray"
fill="none"
@ -231,10 +231,12 @@ export default function SimpleCanvas({ diagram, zoom }) {
height="100%"
fill="url(#pattern-circles)"
></rect>
<g style={{
transform: `scale(${zoom})`,
transformOrigin: "top left",
}}>
<g
style={{
transform: `scale(${zoom})`,
transformOrigin: "top left",
}}
>
{relationships.map((r, i) => (
<Relationship key={i} relationship={r} />
))}

View File

@ -32,7 +32,7 @@ import {
Toast,
} from "@douyinfe/semi-ui";
import { TabContext, TypeContext } from "../pages/Editor";
import { getSize, hasCheck, hasPrecision, isSized } from "../utils";
import { getSize, hasCheck, hasPrecision, isSized } from "../utils/toSQL";
import useLayout from "../hooks/useLayout";
import useSettings from "../hooks/useSettings";
import useUndoRedo from "../hooks/useUndoRedo";

View File

@ -36,7 +36,7 @@ import {
IllustrationNoContentDark,
} from "@douyinfe/semi-illustrations";
import { TypeContext } from "../pages/Editor";
import { getSize, hasCheck, hasPrecision, isSized } from "../utils";
import { getSize, hasCheck, hasPrecision, isSized } from "../utils/toSQL";
import useTables from "../hooks/useTables";
import useUndoRedo from "../hooks/useUndoRedo";
import useSelect from "../hooks/useSelect";

View File

@ -1,4 +1,4 @@
import { calcPath } from "../utils";
import { calcPath } from "../utils/calcPath";
export function Thumbnail({ diagram, i, zoom }) {
const translateX = 32 * zoom;
@ -119,9 +119,7 @@ export function Thumbnail({ diagram, i, zoom }) {
e.startX,
e.endX,
e.startY - translateY / zoom,
e.endY - (translateY / zoom) * 0.5,
e.startFieldId,
e.endFieldId
e.endY - (translateY / zoom) * 0.5
)}
fill="none"
strokeWidth={1}

View File

@ -28,7 +28,7 @@ import {
IllustrationNoContentDark,
} from "@douyinfe/semi-illustrations";
import { TypeContext } from "../pages/Editor";
import { isSized, hasPrecision, getSize } from "../utils";
import { isSized, hasPrecision, getSize } from "../utils/toSQL";
import useUndoRedo from "../hooks/useUndoRedo";
export default function TableOverview() {

View File

@ -1,12 +1,12 @@
import { useEffect } from "react";
import logo_light from "../assets/logo_light_160.png";
import template_screenshot from "../assets/template_screenshot.png"
import template_screenshot from "../assets/template_screenshot.png";
import { Link } from "react-router-dom";
import { Tabs, TabPane, Banner, Steps } from "@douyinfe/semi-ui";
import { IconDeleteStroked } from "@douyinfe/semi-icons";
import { db } from "../data/db";
import { useLiveQuery } from "dexie-react-hooks";
import { calcPath } from "../utils";
import { calcPath } from "../utils/calcPath";
function Thumbnail({ diagram, i }) {
const zoom = 0.3;
@ -82,8 +82,9 @@ function Thumbnail({ diagram, i }) {
</div>
{table.fields.map((f, j) => (
<div
className={`flex justify-between items-center py-[2px] px-[3px] ${j < table.fields.length - 1 ? "border-b" : ""
}`}
className={`flex justify-between items-center py-[2px] px-[3px] ${
j < table.fields.length - 1 ? "border-b" : ""
}`}
key={j}
>
<div className="flex items-center justify-start">
@ -103,15 +104,7 @@ function Thumbnail({ diagram, i }) {
{diagram.relationships?.map((e, i) => (
<path
key={i}
d={calcPath(
e.startX,
e.endX,
e.startY,
e.endY,
e.startFieldId,
e.endFieldId,
zoom
)}
d={calcPath(e.startX, e.endX, e.startY, e.endY, zoom)}
fill="none"
strokeWidth={1}
stroke="gray"
@ -127,19 +120,24 @@ function Thumbnail({ diagram, i }) {
return (
<g key={n.id}>
<path
d={`M${x + fold} ${y} L${x + w - r} ${y} A${r} ${r} 0 0 1 ${x + w
} ${y + r} L${x + w} ${y + h - r} A${r} ${r} 0 0 1 ${x + w - r
} ${y + h} L${x + r} ${y + h} A${r} ${r} 0 0 1 ${x} ${y + h - r
} L${x} ${y + fold}`}
d={`M${x + fold} ${y} L${x + w - r} ${y} A${r} ${r} 0 0 1 ${
x + w
} ${y + r} L${x + w} ${y + h - r} A${r} ${r} 0 0 1 ${
x + w - r
} ${y + h} L${x + r} ${y + h} A${r} ${r} 0 0 1 ${x} ${
y + h - r
} L${x} ${y + fold}`}
fill={n.color}
stroke="rgb(168 162 158)"
strokeLinejoin="round"
strokeWidth="0.5"
/>
<path
d={`M${x} ${y + fold} L${x + fold - r} ${y + fold
} A${r} ${r} 0 0 0 ${x + fold} ${y + fold - r} L${x + fold
} ${y} L${x} ${y + fold} Z`}
d={`M${x} ${y + fold} L${x + fold - r} ${
y + fold
} A${r} ${r} 0 0 0 ${x + fold} ${y + fold - r} L${
x + fold
} ${y} L${x} ${y + fold} Z`}
fill={n.color}
stroke={"rgb(168 162 158)"}
strokeLinejoin="round"
@ -250,81 +248,86 @@ export default function Templates() {
tab={<span className="mx-2">Your templates</span>}
itemKey="2"
>
{
customTemplates?.length > 0 ?
<div className="grid xl:grid-cols-3 grid-cols-2 sm:grid-cols-1 gap-8 my-6">
{customTemplates?.map((c, i) => (
<div
key={i}
className="bg-gray-100 hover:translate-y-[-6px] transition-all duration-300 border rounded-md"
>
<Thumbnail diagram={c} i={"2" + i} />
<div className="px-4 py-3 w-full">
<div className="flex justify-between">
<div className="text-lg font-bold text-zinc-700">
{c.title}
</div>
<div>
<button
className="me-1 border rounded px-2 py-1 bg-white hover:bg-gray-200 transition-all duration-300"
onClick={() => forkTemplate(c.id)}
>
<i className="fa-solid fa-code-fork"></i>
</button>
</div>
{customTemplates?.length > 0 ? (
<div className="grid xl:grid-cols-3 grid-cols-2 sm:grid-cols-1 gap-8 my-6">
{customTemplates?.map((c, i) => (
<div
key={i}
className="bg-gray-100 hover:translate-y-[-6px] transition-all duration-300 border rounded-md"
>
<Thumbnail diagram={c} i={"2" + i} />
<div className="px-4 py-3 w-full">
<div className="flex justify-between">
<div className="text-lg font-bold text-zinc-700">
{c.title}
</div>
<div className="flex justify-around mt-2">
<div>
<button
className="w-full text-center flex justify-center items-center border rounded px-2 py-1 bg-white hover:bg-gray-200 transition-all duration-300 text-blue-500"
onClick={() => editTemplate(c.id)}
className="me-1 border rounded px-2 py-1 bg-white hover:bg-gray-200 transition-all duration-300"
onClick={() => forkTemplate(c.id)}
>
<i className="bi bi-pencil-fill"></i>
<div className="ms-1.5 font-semibold">Edit</div>
</button>
<div className="border-l border-gray-300 mx-2" />
<button
className="w-full text-center flex justify-center items-center border rounded px-2 py-1 bg-white hover:bg-gray-200 transition-all duration-300 text-red-500"
onClick={() => deleteTemplate(c.id)}
>
<IconDeleteStroked />
<div className="ms-1.5 font-semibold">Delete</div>
<i className="fa-solid fa-code-fork"></i>
</button>
</div>
</div>
</div>
))}
</div> :
<div className="py-5">
<Banner
fullMode={false}
type="info"
bordered
icon={null}
closeIcon={null}
description={<div>You have no custom templates saved.</div>}
/>
<div className="grid grid-cols-5 sm:grid-cols-1 gap-4 place-content-center my-4">
<img src={template_screenshot} className="border col-span-3 sm:cols-span-1 rounded" />
<div className="col-span-2 sm:cols-span-1">
<div className="text-xl font-bold my-4">How to save a template</div>
<Steps direction="vertical" style={{ margin: "12px" }}>
<Steps.Step
title="Build a diagram"
description="Build the template in the editor"
/>
<Steps.Step
title="Save as template"
description="Editor > File > Save as template"
/>
<Steps.Step
title="Load a template"
description="Fork a template to build on"
/>
</Steps>
<div className="flex justify-around mt-2">
<button
className="w-full text-center flex justify-center items-center border rounded px-2 py-1 bg-white hover:bg-gray-200 transition-all duration-300 text-blue-500"
onClick={() => editTemplate(c.id)}
>
<i className="bi bi-pencil-fill"></i>
<div className="ms-1.5 font-semibold">Edit</div>
</button>
<div className="border-l border-gray-300 mx-2" />
<button
className="w-full text-center flex justify-center items-center border rounded px-2 py-1 bg-white hover:bg-gray-200 transition-all duration-300 text-red-500"
onClick={() => deleteTemplate(c.id)}
>
<IconDeleteStroked />
<div className="ms-1.5 font-semibold">Delete</div>
</button>
</div>
</div>
</div>
))}
</div>
) : (
<div className="py-5">
<Banner
fullMode={false}
type="info"
bordered
icon={null}
closeIcon={null}
description={<div>You have no custom templates saved.</div>}
/>
<div className="grid grid-cols-5 sm:grid-cols-1 gap-4 place-content-center my-4">
<img
src={template_screenshot}
className="border col-span-3 sm:cols-span-1 rounded"
/>
<div className="col-span-2 sm:cols-span-1">
<div className="text-xl font-bold my-4">
How to save a template
</div>
<Steps direction="vertical" style={{ margin: "12px" }}>
<Steps.Step
title="Build a diagram"
description="Build the template in the editor"
/>
<Steps.Step
title="Save as template"
description="Editor > File > Save as template"
/>
<Steps.Step
title="Load a template"
description="Fork a template to build on"
/>
</Steps>
</div>
</div>
}
</div>
)}
</TabPane>
</Tabs>
</div>

112
src/utils/calcPath.js Normal file
View File

@ -0,0 +1,112 @@
const calcPath = (x1, x2, y1, y2, zoom = 1) => {
const tableWidth = 200 * zoom;
if (y1 <= y2) {
if (x1 + tableWidth <= x2) {
x2 -= 14;
} else if (x2 <= x1 + tableWidth && x1 <= x2) {
// x2-=14;
// x1-=14;
} else if (x2 + tableWidth >= x1 && x2 + tableWidth <= x1 + tableWidth) {
x1 -= 14;
x2 -= 14;
} else {
x2 -= 14;
x1 -= 14;
}
} else {
if (x1 + tableWidth <= x2) {
x2 -= 14;
} else if (x1 + tableWidth >= x2 && x1 + tableWidth <= x2 + tableWidth) {
//
x1 -= 14;
x2 -= 14;
} else if (x1 >= x2 && x1 <= x2 + tableWidth) {
// x1-=19;
// x2-=14;
} else {
x1 -= 14;
x2 -= 14;
}
}
x1 *= zoom;
x2 *= zoom;
y1 *= zoom;
y2 *= zoom;
let r = 10 * zoom;
const offsetX = 8 * zoom;
const midX = (x2 + x1 + tableWidth) / 2;
const endX = x2 + tableWidth < x1 ? x2 + tableWidth : x2;
if (Math.abs(y1 - y2) <= 36 * zoom) {
r = Math.abs(y2 - y1) / 3;
if (r <= 2) {
if (x1 + tableWidth <= x2)
return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${x2} ${y2 + 0.1}`;
else if (x2 + tableWidth < x1)
return `M ${x1} ${y1} L ${x2 + tableWidth} ${y2 + 0.1}`;
}
}
if (y1 <= y2) {
if (x1 + tableWidth <= x2) {
return `M ${x1 + tableWidth - offsetX * 2} ${y1} L ${
midX - r
} ${y1} A ${r} ${r} 0 0 1 ${midX} ${y1 + r} L ${midX} ${
y2 - r
} A ${r} ${r} 0 0 0 ${midX + r} ${y2} L ${endX} ${y2}`;
} else if (x2 <= x1 + tableWidth && x1 <= x2) {
return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${
x2 + tableWidth
} ${y1} A ${r} ${r} 0 0 1 ${x2 + tableWidth + r} ${y1 + r} L ${
x2 + tableWidth + r
} ${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) {
return `M ${x1} ${y1} L ${x2 - r} ${y1} A ${r} ${r} 0 0 0 ${x2 - r - r} ${
y1 + r
} L ${x2 - r - r} ${y2 - r} A ${r} ${r} 0 0 0 ${
x2 - r
} ${y2} L ${x2} ${y2}`;
} else {
return `M ${x1} ${y1} L ${midX + r} ${y1} A ${r} ${r} 0 0 0 ${midX} ${
y1 + r
} L ${midX} ${y2 - r} A ${r} ${r} 0 0 1 ${
midX - r
} ${y2} L ${endX} ${y2}`;
}
} else {
if (x1 + tableWidth <= x2) {
return `M ${x1 + tableWidth - offsetX * 2} ${y1} L ${
midX - r
} ${y1} A ${r} ${r} 0 0 0 ${midX} ${y1 - r} L ${midX} ${
y2 + r
} A ${r} ${r} 0 0 1 ${midX + r} ${y2} L ${endX} ${y2}`;
} else if (x1 + tableWidth >= x2 && x1 + tableWidth <= x2 + tableWidth) {
return `M ${x1} ${y1} L ${x1 - r - r} ${y1} A ${r} ${r} 0 0 1 ${
x1 - r - r - r
} ${y1 - r} L ${x1 - r - r - r} ${y2 + r} A ${r} ${r} 0 0 1 ${
x1 - r - r
} ${y2} L ${endX} ${y2}`;
} else if (x1 >= x2 && x1 <= x2 + tableWidth) {
return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${
x1 + tableWidth - 2 * offsetX + r
} ${y1} A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r + r} ${
y1 - r
} L ${x1 + tableWidth - 2 * offsetX + r + r} ${
y2 + r
} A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r} ${y2} L ${
x2 + tableWidth - 2 * offsetX
} ${y2}`;
} else {
return `M ${x1} ${y1} L ${midX + r} ${y1} A ${r} ${r} 0 0 1 ${midX} ${
y1 - r
} L ${midX} ${y2 + r} A ${r} ${r} 0 0 0 ${
midX - r
} ${y2} L ${endX} ${y2}`;
}
}
};
export { calcPath };

26
src/utils/fullscreen.js Normal file
View File

@ -0,0 +1,26 @@
function enterFullscreen() {
const element = document.documentElement;
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
}
}
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
export { enterFullscreen, exitFullscreen };

View File

@ -1,53 +1,5 @@
import { Validator } from "jsonschema";
import { ddbSchema, jsonSchema } from "../data/schemas";
import { sqlDataTypes } from "../data/data";
function enterFullscreen() {
const element = document.documentElement;
if (element.requestFullscreen) {
element.requestFullscreen();
} else if (element.mozRequestFullScreen) {
element.mozRequestFullScreen();
} else if (element.webkitRequestFullscreen) {
element.webkitRequestFullscreen();
} else if (element.msRequestFullscreen) {
element.msRequestFullscreen();
}
}
function exitFullscreen() {
if (document.exitFullscreen) {
document.exitFullscreen();
} else if (document.mozCancelFullScreen) {
document.mozCancelFullScreen();
} else if (document.webkitExitFullscreen) {
document.webkitExitFullscreen();
} else if (document.msExitFullscreen) {
document.msExitFullscreen();
}
}
function jsonDiagramIsValid(obj) {
return new Validator().validate(obj, jsonSchema).valid;
}
function ddbDiagramIsValid(obj) {
return new Validator().validate(obj, ddbSchema).valid;
}
function dataURItoBlob(dataUrl) {
const byteString = atob(dataUrl.split(",")[1]);
const mimeString = dataUrl.split(",")[0].split(":")[1].split(";")[0];
const arrayBuffer = new ArrayBuffer(byteString.length);
const intArray = new Uint8Array(arrayBuffer);
for (let i = 0; i < byteString.length; i++) {
intArray[i] = byteString.charCodeAt(i);
}
return new Blob([intArray], { type: mimeString });
}
function getJsonType(f) {
if (!sqlDataTypes.includes(f.type)) {
return '{ "type" : "object", additionalProperties : true }';
@ -597,10 +549,6 @@ function jsonToSQLServer(obj) {
.join("\n")}`;
}
function arrayIsEqual(arr1, arr2) {
return JSON.stringify(arr1) === JSON.stringify(arr2);
}
function isSized(type) {
return ["CHAR", "VARCHAR", "BINARY", "VARBINARY", "TEXT"].includes(type);
}
@ -882,135 +830,15 @@ function validateDiagram(diagram) {
return issues;
}
const calcPath = (x1, x2, y1, y2, startFieldId, endFieldId, zoom = 1) => {
const tableWidth = 200 * zoom;
if (y1 <= y2) {
if (x1 + tableWidth <= x2) {
x2 -= 14;
} else if (x2 <= x1 + tableWidth && x1 <= x2) {
// x2-=14;
// x1-=14;
} else if (x2 + tableWidth >= x1 && x2 + tableWidth <= x1 + tableWidth) {
x1 -= 14;
x2 -= 14;
} else {
x2 -= 14;
x1 -= 14;
}
} else {
if (x1 + tableWidth <= x2) {
x2 -= 14;
} else if (x1 + tableWidth >= x2 && x1 + tableWidth <= x2 + tableWidth) {
//
x1 -= 14;
x2 -= 14;
} else if (x1 >= x2 && x1 <= x2 + tableWidth) {
// x1-=19;
// x2-=14;
} else {
x1 -= 14;
x2 -= 14;
}
}
x1 *= zoom;
x2 *= zoom;
y1 *= zoom;
y2 *= zoom;
let r = 10 * zoom;
const offsetX = 8 * zoom;
const midX = (x2 + x1 + tableWidth) / 2;
const endX = x2 + tableWidth < x1 ? x2 + tableWidth : x2;
// const startTableY = y1 - startFieldId * 36 - 50 - 18;
// const endTableY = y2 - endFieldId * 36 - 50;
if (Math.abs(y1 - y2) <= 36 * zoom) {
r = Math.abs(y2 - y1) / 3;
if (r <= 2) {
if (x1 + tableWidth <= x2)
return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${x2} ${y2 + 0.1}`;
else if (x2 + tableWidth < x1)
return `M ${x1} ${y1} L ${x2 + tableWidth} ${y2 + 0.1}`;
}
}
if (y1 <= y2) {
if (x1 + tableWidth <= x2) {
return `M ${x1 + tableWidth - offsetX * 2} ${y1} L ${
midX - r
} ${y1} A ${r} ${r} 0 0 1 ${midX} ${y1 + r} L ${midX} ${
y2 - r
} A ${r} ${r} 0 0 0 ${midX + r} ${y2} L ${endX} ${y2}`;
} else if (x2 <= x1 + tableWidth && x1 <= x2) {
return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${
x2 + tableWidth
} ${y1} A ${r} ${r} 0 0 1 ${x2 + tableWidth + r} ${y1 + r} L ${
x2 + tableWidth + r
} ${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) {
return `M ${x1} ${y1} L ${x2 - r} ${y1} A ${r} ${r} 0 0 0 ${x2 - r - r} ${
y1 + r
} L ${x2 - r - r} ${y2 - r} A ${r} ${r} 0 0 0 ${
x2 - r
} ${y2} L ${x2} ${y2}`;
} else {
return `M ${x1} ${y1} L ${midX + r} ${y1} A ${r} ${r} 0 0 0 ${midX} ${
y1 + r
} L ${midX} ${y2 - r} A ${r} ${r} 0 0 1 ${
midX - r
} ${y2} L ${endX} ${y2}`;
}
} else {
if (x1 + tableWidth <= x2) {
return `M ${x1 + tableWidth - offsetX * 2} ${y1} L ${
midX - r
} ${y1} A ${r} ${r} 0 0 0 ${midX} ${y1 - r} L ${midX} ${
y2 + r
} A ${r} ${r} 0 0 1 ${midX + r} ${y2} L ${endX} ${y2}`;
} else if (x1 + tableWidth >= x2 && x1 + tableWidth <= x2 + tableWidth) {
return `M ${x1} ${y1} L ${x1 - r - r} ${y1} A ${r} ${r} 0 0 1 ${
x1 - r - r - r
} ${y1 - r} L ${x1 - r - r - r} ${y2 + r} A ${r} ${r} 0 0 1 ${
x1 - r - r
} ${y2} L ${endX} ${y2}`;
} else if (x1 >= x2 && x1 <= x2 + tableWidth) {
return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${
x1 + tableWidth - 2 * offsetX + r
} ${y1} A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r + r} ${
y1 - r
} L ${x1 + tableWidth - 2 * offsetX + r + r} ${
y2 + r
} A ${r} ${r} 0 0 0 ${x1 + tableWidth - 2 * offsetX + r} ${y2} L ${
x2 + tableWidth - 2 * offsetX
} ${y2}`;
} else {
return `M ${x1} ${y1} L ${midX + r} ${y1} A ${r} ${r} 0 0 1 ${midX} ${
y1 - r
} L ${midX} ${y2 + r} A ${r} ${r} 0 0 0 ${
midX - r
} ${y2} L ${endX} ${y2}`;
}
}
};
export {
enterFullscreen,
exitFullscreen,
jsonDiagramIsValid,
ddbDiagramIsValid,
dataURItoBlob,
jsonToMySQL,
jsonToPostgreSQL,
validateDiagram,
arrayIsEqual,
isSized,
getSize,
hasPrecision,
validateDateStr,
hasCheck,
calcPath,
jsonToSQLite,
jsonToMariaDB,
jsonToSQLServer,

18
src/utils/utils.js Normal file
View File

@ -0,0 +1,18 @@
function dataURItoBlob(dataUrl) {
const byteString = atob(dataUrl.split(",")[1]);
const mimeString = dataUrl.split(",")[0].split(":")[1].split(";")[0];
const arrayBuffer = new ArrayBuffer(byteString.length);
const intArray = new Uint8Array(arrayBuffer);
for (let i = 0; i < byteString.length; i++) {
intArray[i] = byteString.charCodeAt(i);
}
return new Blob([intArray], { type: mimeString });
}
function arrayIsEqual(arr1, arr2) {
return JSON.stringify(arr1) === JSON.stringify(arr2);
}
export { dataURItoBlob, arrayIsEqual };

View File

@ -0,0 +1,12 @@
import { Validator } from "jsonschema";
import { ddbSchema, jsonSchema } from "../data/schemas";
function jsonDiagramIsValid(obj) {
return new Validator().validate(obj, jsonSchema).valid;
}
function ddbDiagramIsValid(obj) {
return new Validator().validate(obj, ddbSchema).valid;
}
export { jsonDiagramIsValid, ddbDiagramIsValid };