Handle thumbnails for templates

This commit is contained in:
1ilit 2023-12-11 23:11:30 +02:00
parent c3f2809313
commit 705251a275
4 changed files with 238 additions and 120 deletions

View File

@ -1,88 +1,8 @@
import { React, useState } from "react"; import { React, useState } from "react";
import { calcPath } from "../utils";
export default function Relationship(props) { export default function Relationship(props) {
const [hovered, setHovered] = useState(false); const [hovered, setHovered] = useState(false);
const calcPath = (x1, x2, y1, y2) => {
let r = 16;
const offsetX = 8;
const tableWidth = 200;
const midX = (x2 + x1 + tableWidth) / 2;
const endX = x2 + tableWidth < x1 ? x2 + tableWidth - offsetX * 2 : x2;
if (Math.abs(y1 - y2) <= 36) {
r = Math.abs(y2 - y1) / 3;
if (r <= 2) {
if (x1 + tableWidth <= x2)
return `M ${x1 + tableWidth - 2 * offsetX} ${y1} L ${x2 + 0.1} ${
y2 + 0.1
}`;
else if (x2 + tableWidth < x1)
return `M ${x2 + tableWidth - 2 * offsetX} ${y2} L ${x1 + 0.1} ${
y1 + 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} ${y1} A ${r} ${r} 0 0 1 ${
x1 - r - r
} ${y1 - r} L ${x1 - r - r} ${y2 + r} A ${r} ${r} 0 0 1 ${
x1 - 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}`;
}
}
};
return ( return (
<g> <g>

View File

@ -2,9 +2,9 @@ const t1 = {
tables: [ tables: [
{ {
id: 0, id: 0,
name: "template_1", name: "table_0",
x: 57, x: 73,
y: 63, y: 69,
fields: [ fields: [
{ {
name: "id", name: "id",
@ -21,12 +21,72 @@ const t1 = {
], ],
comment: "", comment: "",
indices: [], indices: [],
color: "#f03c3c", color: "#175e7a",
},
{
id: 1,
name: "table_1",
x: 366,
y: 117,
fields: [
{
name: "id",
type: "INT",
default: "",
check: "",
primary: true,
unique: true,
notNull: true,
increment: true,
comment: "",
id: 0,
},
],
comment: "",
indices: [],
color: "#175e7a",
},
],
relationships: [
{
startTableId: 0,
startFieldId: 0,
endTableId: 1,
endFieldId: 0,
startX: 88,
startY: 138,
endX: 381,
endY: 186,
name: "table_0_id_fk",
cardinality: "One to one",
updateConstraint: "No action",
deleteConstraint: "No action",
mandatory: false,
id: 0,
},
],
notes: [
{
id: 0,
x: 526,
y: 240,
title: "note_0",
content: "hi",
color: "#fcf7ac",
height: 65,
},
],
subjectAreas: [
{
id: 0,
name: "area_0",
x: 43,
y: 28,
width: 558,
height: 206,
color: "#175e7a",
}, },
], ],
relationships: [],
notes: [],
subjectAreas: [],
types: [], types: [],
title: "Template 1", title: "Template 1",
description: "Lorem ipsum", description: "Lorem ipsum",

View File

@ -4,10 +4,12 @@ import { Link } from "react-router-dom";
import { Tabs, TabPane } from "@douyinfe/semi-ui"; import { Tabs, TabPane } from "@douyinfe/semi-ui";
import { useLiveQuery } from "dexie-react-hooks"; import { useLiveQuery } from "dexie-react-hooks";
import { db } from "../data/db"; import { db } from "../data/db";
import { calcPath } from "../utils";
function cardCanvas(diagram) { function Thumbnail({ diagram }) {
const zoom = 0.3;
return ( return (
<div className="w-full"> <div className="w-full select-none">
<svg className="bg-white w-full"> <svg className="bg-white w-full">
<defs> <defs>
<pattern <pattern
@ -36,25 +38,35 @@ function cardCanvas(diagram) {
fill="url(#pattern-circles)" fill="url(#pattern-circles)"
></rect> ></rect>
<g id="diagram"> <g id="diagram">
{/* {diagram.areas.map((a) => ( {diagram.subjectAreas?.map((a) => (
<Area <foreignObject
key={a.id} key={a.id}
areaData={a} x={a.x * zoom}
onMouseDown={(e) => {}} y={a.y * zoom}
setResize={null} width={a.width > 0 ? a.width * zoom : 0}
initCoords={null} height={a.height > 0 ? a.height * zoom : 0}
setInitCoords={null} >
zoom={null} <div
></Area> className={`border border-slate-400 w-full h-full rounded-sm relative`}
))} */} >
{diagram.tables.map((table, i) => { <div
className="opacity-40 w-fill h-full"
style={{ backgroundColor: a.color }}
/>
</div>
<div className="text-color absolute top-[4px] left-[6px] select-none text-[4px]">
{a.name}
</div>
</foreignObject>
))}
{diagram.tables?.map((table, i) => {
const height = table.fields.length * 36 + 50 + 7; const height = table.fields.length * 36 + 50 + 7;
return ( return (
<foreignObject <foreignObject
x={table.x * 0.3} x={table.x * zoom}
y={table.y * 0.3} y={table.y * zoom}
width={200 * 0.3} width={200 * zoom}
height={height * 0.3} height={height * zoom}
key={i} key={i}
> >
<div className="border-[1px] rounded-[3px] border-zinc-300 text-[4px] bg-zinc-100"> <div className="border-[1px] rounded-[3px] border-zinc-300 text-[4px] bg-zinc-100">
@ -85,19 +97,58 @@ function cardCanvas(diagram) {
</foreignObject> </foreignObject>
); );
})} })}
{/* {diagram.relationships?.map((e, i) => (
{diagram.relationships.map((e, i) => ( <path
<Relationship key={i} data={e} /> d={calcPath(e.startX, e.endX, e.startY, e.endY, zoom)}
fill="none"
strokeWidth={1}
stroke="gray"
/>
))} ))}
{diagram.notes.map((n) => ( {diagram.notes?.map((n) => {
<Note const x = n.x * zoom;
key={n.id} const y = n.y * zoom;
data={n} const w = 180 * zoom;
onMouseDown={(e) => const r = 3 * zoom;
{} const fold = 24 * zoom;
} const h = n.height * zoom;
></Note> return (
))} */} <g>
<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}`}
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`}
fill={n.color}
stroke={"rgb(168 162 158)"}
strokeLinejoin="round"
strokeWidth="0.5"
/>
<foreignObject x={x} y={y} width={w} height={h}>
<div className="text-gray-900 w-full h-full px-[4px] py-[2px] text-[4px]">
<label htmlFor={`note_${n.id}`} className="ms-[6px]">
{n.title}
</label>
<div className="text-[4px] mt-[2px]">{n.content}</div>
</div>
</foreignObject>
</g>
);
})}
</g> </g>
</svg> </svg>
</div> </div>
@ -149,7 +200,7 @@ export default function Templates() {
key={i} key={i}
className="p-4 bg-gray-200 hover:translate-y-[-6px] transition-all duration-300" className="p-4 bg-gray-200 hover:translate-y-[-6px] transition-all duration-300"
> >
{cardCanvas(t)} <Thumbnail diagram={t} />
<div>{t.title}</div> <div>{t.title}</div>
<div>{t.description}</div> <div>{t.description}</div>
</div> </div>

View File

@ -605,6 +605,92 @@ function validateDiagram(diagram) {
return issues; return issues;
} }
const calcPath = (x1, x2, y1, y2, zoom = 1) => {
x1 *= zoom;
x2 *= zoom;
y1 *= zoom;
y2 *= zoom;
let r = 16 * zoom;
const offsetX = 8 * zoom;
const tableWidth = 200 * zoom;
const midX = (x2 + x1 + tableWidth) / 2;
const endX = x2 + tableWidth < x1 ? x2 + tableWidth - offsetX * 2 : 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 + 0.1} ${
y2 + 0.1
}`;
else if (x2 + tableWidth < x1)
return `M ${x2 + tableWidth - 2 * offsetX} ${y2} L ${x1 + 0.1} ${
y1 + 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} ${y1} A ${r} ${r} 0 0 1 ${x1 - r - r} ${
y1 - r
} L ${x1 - r - r} ${y2 + r} A ${r} ${r} 0 0 1 ${
x1 - 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 { export {
enterFullscreen, enterFullscreen,
exitFullscreen, exitFullscreen,
@ -620,4 +706,5 @@ export {
hasPrecision, hasPrecision,
validateDateStr, validateDateStr,
hasCheck, hasCheck,
calcPath,
}; };