Add thumbnails to create new modal

This commit is contained in:
1ilit 2024-02-16 16:27:09 +02:00
parent c578374857
commit 38943d80f2
2 changed files with 197 additions and 22 deletions

View File

@ -10,7 +10,6 @@ import {
IconRedo,
IconRowsStroked,
IconEdit,
IconPlus,
} from "@douyinfe/semi-icons";
import { Link } from "react-router-dom";
import icon from "../assets/icon_dark_64.png";
@ -71,6 +70,7 @@ import { db } from "../data/db";
import { useLiveQuery } from "dexie-react-hooks";
import { Parser } from "node-sql-parser";
import Todo from "./Todo";
import { Thumbnail } from "./Thumbnail";
export default function ControlPanel({
diagramId,
@ -81,6 +81,7 @@ export default function ControlPanel({
setState,
lastSaved,
}) {
const defaultTemplates = useLiveQuery(() => db.templates.toArray());
const MODAL = {
NONE: 0,
IMG: 1,
@ -1012,7 +1013,7 @@ export default function ControlPanel({
},
},
{
"MSSQL": () => {
MSSQL: () => {
setVisible(MODAL.CODE);
const src = jsonToSQLServer({
tables: tables,
@ -1256,7 +1257,7 @@ export default function ControlPanel({
case MODAL.SAVEAS:
return "Save as";
case MODAL.NEW:
return "New diagram";
return "Create new diagram";
default:
return "";
}
@ -1820,32 +1821,28 @@ export default function ControlPanel({
const newModalBody = () => (
<div className="h-[360px] grid grid-cols-3 gap-2 overflow-auto px-1">
<div>
<div onClick={() => setSelectedTemplateId(0)}>
<div
className={`h-[180px] w-full bg-blue-400 bg-opacity-30 flex justify-center items-center rounded hover:bg-opacity-40 hover:border-2 hover:border-dashed ${
settings.mode === "light"
? "hover:border-blue-500"
: "hover:border-white"
} ${selectedTemplateId === 0 && "border-2 border-blue-500"}`}
onClick={() => setSelectedTemplateId(0)}
className={`rounded-md h-[180px] border-2 hover:border-dashed ${
selectedTemplateId === 0 ? "border-blue-400" : "border-zinc-100"
}`}
>
<IconPlus style={{ color: "#fff" }} size="extra-large" />
<Thumbnail i={0} diagram={{}} zoom={0.24} />
</div>
<div className="text-center mt-1">Blank</div>
</div>
{[1, 2, 3, 4, 5, 6, 7, 8].map((i) => (
<div key={i}>
{defaultTemplates.map((temp, i) => (
<div key={i} onClick={() => setSelectedTemplateId(temp.id)}>
<div
className={`h-[180px] w-full bg-blue-400 bg-opacity-30 flex justify-center items-center rounded hover:bg-opacity-40 hover:border-2 hover:border-dashed ${
settings.mode === "light"
? "hover:border-blue-500"
: "hover:border-white"
} ${selectedTemplateId === i && "border-2 border-blue-500"}`}
onClick={() => setSelectedTemplateId(i)}
className={`rounded-md h-[180px] border-2 hover:border-dashed ${
selectedTemplateId === temp.id
? "border-blue-400"
: "border-zinc-100"
}`}
>
+
<Thumbnail i={temp.id} diagram={temp} zoom={0.24} />
</div>
<div className="text-center mt-1">Template {i}</div>
<div className="text-center mt-1">{temp.title}</div>
</div>
))}
</div>
@ -2021,7 +2018,7 @@ export default function ControlPanel({
(visible === MODAL.IMPORT_SRC && data.src === ""),
}}
cancelText="Cancel"
width={600}
width={visible === MODAL.NEW ? 740 : 600}
>
{getModalBody()}
</Modal>

View File

@ -0,0 +1,178 @@
import { calcPath } from "../utils";
export function Thumbnail({ diagram, i, zoom }) {
const translateX = 32 * zoom;
const translateY = 32 * zoom;
const theme = localStorage.getItem("theme");
return (
<svg
className={`${
theme === "dark" ? "bg-[#222229]" : "bg-white"
} w-full h-full rounded-md text-color`}
>
<defs>
<pattern
id={"pattern-circles-" + i}
x="0"
y="0"
width="10"
height="10"
patternUnits="userSpaceOnUse"
patternContentUnits="userSpaceOnUse"
>
<circle
id={"pattern-circle-" + i}
cx="2"
cy="2"
r="0.4"
fill="rgb(99, 152, 191)"
></circle>
</pattern>
</defs>
<rect
x="0"
y="0"
width="100%"
height="100%"
fill={"url(#pattern-circles-" + i + ")"}
></rect>
<g
style={{
transform: `translate(${translateX}px, ${translateY}px) scale(${zoom})`,
}}
>
{diagram.subjectAreas?.map((a) => (
<foreignObject
key={a.id}
x={a.x}
y={a.y}
width={a.width > 0 ? a.width : 0}
height={a.height > 0 ? a.height : 0}
>
<div
className={`border border-slate-400 w-full h-full rounded-sm relative`}
>
<div
className="opacity-40 w-fill h-full"
style={{ backgroundColor: a.color }}
/>
</div>
<div className="text-color absolute top-1 left-2 select-none">
{a.name}
</div>
</foreignObject>
))}
{diagram.tables?.map((table, i) => {
const height = table.fields.length * 36 + 50 + 7;
return (
<foreignObject
x={table.x}
y={table.y}
width={200}
height={height}
key={i}
>
<div
className={`border rounded-md ${
theme === "dark"
? "bg-zinc-800"
: "border-zinc-300 bg-zinc-100"
}`}
>
<div
className="h-2 w-full rounded-t-sm"
style={{ backgroundColor: table.color }}
></div>
<div className="rounded-b-[3px]">
<div
className={`font-bold py-1 px-2 border-b ${
theme === "dark" ? "bg-zinc-900" : "bg-zinc-200"
} border-gray-300`}
>
{table.name}
</div>
{table.fields.map((f, j) => (
<div
className={`flex justify-between items-center py-1 px-2 ${
j < table.fields.length - 1 ? "border-b" : ""
}`}
key={j}
>
<div className="flex items-center justify-start">
<div
className={`w-[6px] h-[6px] bg-[#2f68ad] opacity-80 z-50 rounded-full me-2`}
></div>
<div>{f.name}</div>
</div>
<div className="text-zinc-500">{f.type}</div>
</div>
))}
</div>
</div>
</foreignObject>
);
})}
{diagram.relationships?.map((e, i) => (
<path
key={i}
d={calcPath(
e.startX,
e.endX,
e.startY - translateY / zoom,
e.endY - (translateY / zoom) * 0.5,
e.startFieldId,
e.endFieldId
)}
fill="none"
strokeWidth={1}
stroke="gray"
/>
))}
{diagram.notes?.map((n) => {
const x = n.x;
const y = n.y;
const w = 180;
const r = 3;
const fold = 24;
const h = n.height;
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}`}
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-4 py-2">
<label htmlFor={`note_${n.id}`} className="ms-4">
{n.title}
</label>
<div className="mt-[2px]">{n.content}</div>
</div>
</foreignObject>
</g>
);
})}
</g>
</svg>
);
}