diff --git a/library/lib/App.tsx b/library/lib/App.tsx
index dda25cb..25e2005 100644
--- a/library/lib/App.tsx
+++ b/library/lib/App.tsx
@@ -12,7 +12,11 @@ import {
useEdgesState,
} from "@xyflow/react"
import "@xyflow/react/dist/style.css"
-import { MAX_SCALE_TO_ZOOM_IN, MIN_SCALE_TO_ZOOM_OUT } from "./constants"
+import {
+ HALF_OF_BACKGROUND_BOX_LENGHT_IN_PX,
+ MAX_SCALE_TO_ZOOM_IN,
+ MIN_SCALE_TO_ZOOM_OUT,
+} from "./constants"
import { initialEdges, initialNodes } from "./initialElements"
import { Sidebar, SvgMarkers } from "@/components"
import { diagramNodeTypes } from "./nodes"
@@ -66,6 +70,10 @@ function App({ onReactFlowInit }: AppProps) {
minZoom={MIN_SCALE_TO_ZOOM_OUT}
maxZoom={MAX_SCALE_TO_ZOOM_IN}
snapToGrid
+ snapGrid={[
+ HALF_OF_BACKGROUND_BOX_LENGHT_IN_PX,
+ HALF_OF_BACKGROUND_BOX_LENGHT_IN_PX,
+ ]}
>
diff --git a/library/lib/constants/canvasConstants.ts b/library/lib/constants/canvasConstants.ts
index da01e1c..9ef3c8b 100644
--- a/library/lib/constants/canvasConstants.ts
+++ b/library/lib/constants/canvasConstants.ts
@@ -1,3 +1,4 @@
export const MIN_SCALE_TO_ZOOM_OUT = 0.4
export const MAX_SCALE_TO_ZOOM_IN = 2.5
export const MOUSE_UP_OFFSET_IN_PIXELS = 5
+export const HALF_OF_BACKGROUND_BOX_LENGHT_IN_PX = 10
diff --git a/library/lib/hooks/useDrop.ts b/library/lib/hooks/useDrop.ts
index 50952a1..c9cbf51 100644
--- a/library/lib/hooks/useDrop.ts
+++ b/library/lib/hooks/useDrop.ts
@@ -25,10 +25,13 @@ export const useDrop = () => {
return
}
// Convert the drop position to the flow position
- const dropPosition = screenToFlowPosition({
- x: event.clientX,
- y: event.clientY,
- })
+ const dropPosition = screenToFlowPosition(
+ {
+ x: event.clientX,
+ y: event.clientY,
+ },
+ { snapToGrid: true }
+ )
// Adjust position by subtracting the offset
const position = {
diff --git a/standalone/webapp/assets/diagramTemplates/Adapter.json b/standalone/webapp/assets/diagramTemplates/Adapter.json
new file mode 100644
index 0000000..6da8823
--- /dev/null
+++ b/standalone/webapp/assets/diagramTemplates/Adapter.json
@@ -0,0 +1,110 @@
+{
+ "version": "apollon2",
+ "title": "Adapter",
+ "nodes": [
+ {
+ "width": 190,
+ "height": 82,
+ "id": "2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "type": "class",
+ "position": { "x": 270, "y": 120 },
+ "data": {
+ "name": "Adapter",
+ "methods": [
+ { "id": "96d06d69-c8d2-4ea3-8d6b-d05c22a03286", "name": "+ method()" }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 190, "height": 82 },
+ "dragging": true,
+ "resizing": false
+ },
+ {
+ "width": 160,
+ "height": 82,
+ "id": "7052e703-263f-4df5-95e0-3558793849af",
+ "type": "class",
+ "position": { "x": 120, "y": 330 },
+ "data": {
+ "name": "Adaptee1",
+ "methods": [
+ { "id": "964c1c16-441b-4d1e-99c3-406f3a37f50b", "name": "+ method()" }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 160, "height": 82 },
+ "dragging": true,
+ "resizing": false
+ },
+ {
+ "width": 167.20445251464844,
+ "height": 112,
+ "id": "286257b1-ebd3-424f-b3e4-c1c2a722531b",
+ "type": "class",
+ "position": { "x": -90, "y": 105 },
+ "data": {
+ "name": "Client",
+ "methods": [
+ { "id": "964c1c16-441b-4d1e-99c3-406f3a37f50b", "name": "+ doWork()" }
+ ],
+ "attributes": [
+ {
+ "id": "fe5106d4-60eb-4c80-97b0-b5b8b8f1f80d",
+ "name": "+ adapter: Adapter"
+ }
+ ]
+ },
+ "selected": false,
+ "measured": { "width": 167, "height": 112 },
+ "dragging": true
+ },
+ {
+ "width": 160,
+ "height": 82,
+ "id": "2fecb039-1b0d-4de9-8820-fa120c51f4f6",
+ "type": "class",
+ "position": { "x": 435, "y": 330 },
+ "data": {
+ "name": "Adaptee2",
+ "methods": [
+ { "id": "964c1c16-441b-4d1e-99c3-406f3a37f50b", "name": "+ method()" }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 160, "height": 82 },
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "286257b1-ebd3-424f-b3e4-c1c2a722531b",
+ "sourceHandle": "right",
+ "target": "2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "targetHandle": "left",
+ "type": "uniassociation",
+ "selected": false,
+ "id": "xy-edge__286257b1-ebd3-424f-b3e4-c1c2a722531bright-2eb1ceb2-266e-4669-89f1-c61e246cb10cleft"
+ },
+ {
+ "source": "7052e703-263f-4df5-95e0-3558793849af",
+ "sourceHandle": "top",
+ "target": "2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "targetHandle": "bottom",
+ "id": "1737993042486-7052e703-263f-4df5-95e0-3558793849af-2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "type": "inheritance",
+ "selected": false
+ },
+ {
+ "source": "2fecb039-1b0d-4de9-8820-fa120c51f4f6",
+ "sourceHandle": "top",
+ "target": "2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "targetHandle": "bottom",
+ "id": "1737993045593-2fecb039-1b0d-4de9-8820-fa120c51f4f6-2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "type": "inheritance",
+ "selected": false
+ }
+ ]
+}
diff --git a/standalone/webapp/assets/diagramTemplates/Bridge.json b/standalone/webapp/assets/diagramTemplates/Bridge.json
new file mode 100644
index 0000000..058d29c
--- /dev/null
+++ b/standalone/webapp/assets/diagramTemplates/Bridge.json
@@ -0,0 +1,190 @@
+{
+ "version": "apollon2",
+ "title": "Bridge",
+ "nodes": [
+ {
+ "width": 190,
+ "height": 82,
+ "id": "2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "type": "class",
+ "position": { "x": 270, "y": 120 },
+ "data": {
+ "name": "Abstraction",
+ "methods": [
+ {
+ "id": "96d06d69-c8d2-4ea3-8d6b-d05c22a03286",
+ "name": "+ operation()"
+ }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 190, "height": 82 },
+ "dragging": true,
+ "resizing": false
+ },
+ {
+ "width": 160,
+ "height": 82,
+ "id": "7052e703-263f-4df5-95e0-3558793849af",
+ "type": "class",
+ "position": { "x": 120, "y": 330 },
+ "data": {
+ "name": "Adaptee1",
+ "methods": [
+ { "id": "964c1c16-441b-4d1e-99c3-406f3a37f50b", "name": "+ method()" }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 160, "height": 82 },
+ "dragging": true,
+ "resizing": false
+ },
+ {
+ "width": 167.20445251464844,
+ "height": 52,
+ "id": "286257b1-ebd3-424f-b3e4-c1c2a722531b",
+ "type": "class",
+ "position": { "x": -90, "y": 135 },
+ "data": { "name": "Client", "methods": [], "attributes": [] },
+ "selected": false,
+ "measured": { "width": 167, "height": 52 },
+ "dragging": true
+ },
+ {
+ "width": 160,
+ "height": 82,
+ "id": "2fecb039-1b0d-4de9-8820-fa120c51f4f6",
+ "type": "class",
+ "position": { "x": 435, "y": 330 },
+ "data": {
+ "name": "Adaptee2",
+ "methods": [
+ { "id": "964c1c16-441b-4d1e-99c3-406f3a37f50b", "name": "+ method()" }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 160, "height": 82 },
+ "dragging": true
+ },
+ {
+ "width": 160,
+ "height": 82,
+ "id": "889cb1f6-175a-45c0-ae06-d1acab5dcbdc",
+ "type": "class",
+ "position": { "x": 765, "y": 120 },
+ "data": {
+ "name": "Implementor",
+ "methods": [
+ {
+ "id": "964c1c16-441b-4d1e-99c3-406f3a37f50b",
+ "name": "+ operationImpl()"
+ }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 160, "height": 82 },
+ "dragging": true
+ },
+ {
+ "width": 198.02259826660156,
+ "height": 82,
+ "id": "2e018906-a3db-4308-977b-175ace3c3185",
+ "type": "class",
+ "position": { "x": 630, "y": 330 },
+ "data": {
+ "name": "ConcreteImplementor1",
+ "methods": [
+ {
+ "id": "964c1c16-441b-4d1e-99c3-406f3a37f50b",
+ "name": "+ operationImpl()"
+ }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 198, "height": 82 },
+ "dragging": true
+ },
+ {
+ "width": 198.02259826660156,
+ "height": 82,
+ "id": "1bb3eed4-bcc2-45af-9b6e-62020b9c439d",
+ "type": "class",
+ "position": { "x": 900, "y": 330 },
+ "data": {
+ "name": "ConcreteImplementor2",
+ "methods": [
+ {
+ "id": "964c1c16-441b-4d1e-99c3-406f3a37f50b",
+ "name": "+ operationImpl()"
+ }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 197.97740173339844, "height": 82 },
+ "dragging": true,
+ "resizing": false
+ }
+ ],
+ "edges": [
+ {
+ "source": "286257b1-ebd3-424f-b3e4-c1c2a722531b",
+ "sourceHandle": "right",
+ "target": "2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "targetHandle": "left",
+ "type": "biassociation",
+ "selected": false,
+ "id": "xy-edge__286257b1-ebd3-424f-b3e4-c1c2a722531bright-2eb1ceb2-266e-4669-89f1-c61e246cb10cleft"
+ },
+ {
+ "source": "7052e703-263f-4df5-95e0-3558793849af",
+ "sourceHandle": "top",
+ "target": "2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "targetHandle": "bottom",
+ "id": "1737993042486-7052e703-263f-4df5-95e0-3558793849af-2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "type": "inheritance",
+ "selected": false
+ },
+ {
+ "source": "2fecb039-1b0d-4de9-8820-fa120c51f4f6",
+ "sourceHandle": "top",
+ "target": "2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "targetHandle": "bottom",
+ "id": "1737993045593-2fecb039-1b0d-4de9-8820-fa120c51f4f6-2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "type": "inheritance",
+ "selected": false
+ },
+ {
+ "source": "2e018906-a3db-4308-977b-175ace3c3185",
+ "sourceHandle": "top",
+ "target": "889cb1f6-175a-45c0-ae06-d1acab5dcbdc",
+ "targetHandle": "bottom",
+ "id": "1737993203512-2e018906-a3db-4308-977b-175ace3c3185-889cb1f6-175a-45c0-ae06-d1acab5dcbdc",
+ "type": "inheritance",
+ "selected": false
+ },
+ {
+ "source": "1bb3eed4-bcc2-45af-9b6e-62020b9c439d",
+ "sourceHandle": "top",
+ "target": "889cb1f6-175a-45c0-ae06-d1acab5dcbdc",
+ "targetHandle": "bottom",
+ "id": "1737993210921-1bb3eed4-bcc2-45af-9b6e-62020b9c439d-889cb1f6-175a-45c0-ae06-d1acab5dcbdc",
+ "type": "inheritance",
+ "selected": false
+ },
+ {
+ "source": "2eb1ceb2-266e-4669-89f1-c61e246cb10c",
+ "sourceHandle": "right",
+ "target": "889cb1f6-175a-45c0-ae06-d1acab5dcbdc",
+ "targetHandle": "left",
+ "id": "1737993220311-2eb1ceb2-266e-4669-89f1-c61e246cb10c-889cb1f6-175a-45c0-ae06-d1acab5dcbdc",
+ "type": "biassociation",
+ "selected": false
+ }
+ ]
+}
diff --git a/standalone/webapp/assets/diagramTemplates/Command.json b/standalone/webapp/assets/diagramTemplates/Command.json
new file mode 100644
index 0000000..e08992e
--- /dev/null
+++ b/standalone/webapp/assets/diagramTemplates/Command.json
@@ -0,0 +1,165 @@
+{
+ "version": "apollon2",
+ "title": "Command",
+ "nodes": [
+ {
+ "width": 160,
+ "height": 52,
+ "id": "8acfa3c3-de5b-424a-a555-cb68855538d0",
+ "type": "class",
+ "position": { "x": -280, "y": 340 },
+ "data": { "name": "Client", "methods": [], "attributes": [] },
+ "selected": false,
+ "measured": { "width": 160, "height": 52 },
+ "dragging": true,
+ "resizing": false
+ },
+ {
+ "width": 246.431640625,
+ "height": 82,
+ "id": "7351d563-b929-460e-a09d-e2b463bfceea",
+ "type": "class",
+ "position": { "x": -20, "y": 30 },
+ "data": {
+ "name": "Invoker",
+ "methods": [
+ {
+ "id": "d5ea460f-22f9-4494-a28f-2fc7a1ea64dc",
+ "name": "+ setCommand(c: Command)"
+ }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 246, "height": 82 },
+ "dragging": true
+ },
+ {
+ "width": 160,
+ "height": 82,
+ "id": "41a9495d-9993-449e-a3b5-a7a704130380",
+ "type": "class",
+ "position": { "x": 10, "y": 200 },
+ "data": {
+ "name": "Receiver",
+ "methods": [
+ { "id": "d5ea460f-22f9-4494-a28f-2fc7a1ea64dc", "name": "+ action()" }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 160, "height": 82 },
+ "dragging": true
+ },
+ {
+ "width": 170,
+ "height": 82,
+ "id": "52e53f8b-cac0-4816-a70a-c2f154f3fb67",
+ "type": "class",
+ "position": { "x": 390, "y": 30 },
+ "data": {
+ "name": "Command",
+ "methods": [
+ {
+ "id": "d5ea460f-22f9-4494-a28f-2fc7a1ea64dc",
+ "name": "+ execute()"
+ }
+ ],
+ "attributes": [],
+ "stereotype": "Interface"
+ },
+ "selected": false,
+ "measured": { "width": 170, "height": 82 },
+ "dragging": true,
+ "resizing": false
+ },
+ {
+ "width": 270,
+ "height": 112,
+ "id": "f235a28a-6d9b-482c-9e67-546dfd92e0d5",
+ "type": "class",
+ "position": { "x": 340, "y": 190 },
+ "data": {
+ "name": "ConcreteCommand",
+ "methods": [
+ {
+ "id": "d5ea460f-22f9-4494-a28f-2fc7a1ea64dc",
+ "name": "+ execute()"
+ }
+ ],
+ "attributes": [
+ { "id": "c418186e-4631-4b07-b5f3-25d414d248da", "name": "- state" }
+ ]
+ },
+ "selected": false,
+ "measured": { "width": 270, "height": 112 },
+ "dragging": true,
+ "resizing": false
+ }
+ ],
+ "edges": [
+ {
+ "source": "8acfa3c3-de5b-424a-a555-cb68855538d0",
+ "sourceHandle": "top",
+ "target": "7351d563-b929-460e-a09d-e2b463bfceea",
+ "targetHandle": "left",
+ "id": "1737994716146-8acfa3c3-de5b-424a-a555-cb68855538d0-7351d563-b929-460e-a09d-e2b463bfceea",
+ "type": "uniassociation",
+ "selected": false
+ },
+ {
+ "source": "8acfa3c3-de5b-424a-a555-cb68855538d0",
+ "sourceHandle": "top",
+ "target": "41a9495d-9993-449e-a3b5-a7a704130380",
+ "targetHandle": "left",
+ "id": "1737994722983-8acfa3c3-de5b-424a-a555-cb68855538d0-41a9495d-9993-449e-a3b5-a7a704130380",
+ "type": "uniassociation",
+ "selected": false
+ },
+ {
+ "source": "f235a28a-6d9b-482c-9e67-546dfd92e0d5",
+ "sourceHandle": "top",
+ "target": "52e53f8b-cac0-4816-a70a-c2f154f3fb67",
+ "targetHandle": "bottom",
+ "id": "1737994915434-52e53f8b-cac0-4816-a70a-c2f154f3fb67-f235a28a-6d9b-482c-9e67-546dfd92e0d5",
+ "type": "inheritance",
+ "selected": false
+ },
+ {
+ "source": "f235a28a-6d9b-482c-9e67-546dfd92e0d5",
+ "sourceHandle": "left",
+ "target": "41a9495d-9993-449e-a3b5-a7a704130380",
+ "targetHandle": "right",
+ "id": "1737994981686-f235a28a-6d9b-482c-9e67-546dfd92e0d5-41a9495d-9993-449e-a3b5-a7a704130380",
+ "type": "uniassociation",
+ "selected": false
+ },
+ {
+ "source": "726a23e8-c86e-469d-927a-d0f4c199b474",
+ "sourceHandle": "top",
+ "target": "52e53f8b-cac0-4816-a70a-c2f154f3fb67",
+ "targetHandle": "bottom-right",
+ "id": "1737994991158-726a23e8-c86e-469d-927a-d0f4c199b474-52e53f8b-cac0-4816-a70a-c2f154f3fb67",
+ "type": "biassociation",
+ "selected": false
+ },
+ {
+ "source": "7351d563-b929-460e-a09d-e2b463bfceea",
+ "sourceHandle": "right",
+ "target": "52e53f8b-cac0-4816-a70a-c2f154f3fb67",
+ "targetHandle": "left",
+ "id": "1737995015106-7351d563-b929-460e-a09d-e2b463bfceea-52e53f8b-cac0-4816-a70a-c2f154f3fb67",
+ "type": "uniassociation",
+ "selected": false
+ },
+ {
+ "source": "8acfa3c3-de5b-424a-a555-cb68855538d0",
+ "sourceHandle": "right",
+ "target": "f235a28a-6d9b-482c-9e67-546dfd92e0d5",
+ "targetHandle": "bottom",
+ "id": "1737995032625-8acfa3c3-de5b-424a-a555-cb68855538d0-f235a28a-6d9b-482c-9e67-546dfd92e0d5",
+ "type": "dependency",
+ "selected": false
+ }
+ ]
+}
diff --git a/standalone/webapp/assets/diagramTemplates/Factory.json b/standalone/webapp/assets/diagramTemplates/Factory.json
new file mode 100644
index 0000000..f42df28
--- /dev/null
+++ b/standalone/webapp/assets/diagramTemplates/Factory.json
@@ -0,0 +1,155 @@
+{
+ "version": "apollon2",
+ "title": "Factory",
+ "nodes": [
+ {
+ "width": 210,
+ "height": 82,
+ "id": "cfc9b781-debe-4ca3-903c-9a9e555f6812",
+ "type": "class",
+ "position": { "x": -470, "y": 100 },
+ "data": {
+ "name": "Factory",
+ "methods": [
+ {
+ "id": "fc2d26e3-a3ad-4871-ac3c-0c792b06b8e1",
+ "name": "+ createProduct()"
+ }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 210, "height": 82 },
+ "dragging": true,
+ "resizing": false
+ },
+ {
+ "width": 250,
+ "height": 112,
+ "id": "1c0330be-83dd-4d92-9bd1-d62a36e90c7b",
+ "type": "class",
+ "position": { "x": 80, "y": 90 },
+ "data": {
+ "name": "Product",
+ "methods": [
+ {
+ "id": "e191f8a6-e51b-4564-b4cb-26ab79681799",
+ "name": "+ doSomething()"
+ }
+ ],
+ "attributes": [
+ {
+ "id": "a2015b4c-5872-4117-a34c-adb8d0898883",
+ "name": "+ attribute: Type"
+ }
+ ],
+ "stereotype": "Abstract"
+ },
+ "selected": false,
+ "measured": { "width": 250, "height": 112 },
+ "dragging": true,
+ "resizing": false
+ },
+ {
+ "width": 210,
+ "height": 82,
+ "id": "8a30926e-581b-49c9-b0cc-7a9119ae1579",
+ "type": "class",
+ "position": { "x": -210, "y": 310 },
+ "data": {
+ "name": "ConcreteProduct",
+ "methods": [
+ {
+ "id": "e191f8a6-e51b-4564-b4cb-26ab79681799",
+ "name": "+ doSomething()"
+ }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 210, "height": 82 },
+ "resizing": false,
+ "dragging": true
+ },
+ {
+ "width": 230,
+ "height": 82,
+ "id": "fc1e3b34-6e01-4fb6-8c26-a70535fa1ff2",
+ "type": "class",
+ "position": { "x": 90, "y": 310 },
+ "data": {
+ "name": "ConcreteProduct",
+ "methods": [
+ {
+ "id": "e191f8a6-e51b-4564-b4cb-26ab79681799",
+ "name": "+ doSomething()"
+ }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 230, "height": 82 },
+ "dragging": true,
+ "resizing": false
+ },
+ {
+ "width": 240,
+ "height": 82,
+ "id": "552eb7f3-62a7-45d9-8133-da6f5379b5a4",
+ "type": "class",
+ "position": { "x": 390, "y": 310 },
+ "data": {
+ "name": "ConcreteProduct",
+ "methods": [
+ {
+ "id": "e191f8a6-e51b-4564-b4cb-26ab79681799",
+ "name": "+ doSomething()"
+ }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 240, "height": 82 },
+ "resizing": false,
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "cfc9b781-debe-4ca3-903c-9a9e555f6812",
+ "sourceHandle": "right",
+ "target": "1c0330be-83dd-4d92-9bd1-d62a36e90c7b",
+ "targetHandle": "left",
+ "type": "uniassociation",
+ "selected": false,
+ "id": "xy-edge__cfc9b781-debe-4ca3-903c-9a9e555f6812right-1c0330be-83dd-4d92-9bd1-d62a36e90c7bleft"
+ },
+ {
+ "source": "8a30926e-581b-49c9-b0cc-7a9119ae1579",
+ "sourceHandle": "top",
+ "target": "1c0330be-83dd-4d92-9bd1-d62a36e90c7b",
+ "targetHandle": "bottom",
+ "id": "1737998332817-8a30926e-581b-49c9-b0cc-7a9119ae1579-1c0330be-83dd-4d92-9bd1-d62a36e90c7b",
+ "type": "inheritance",
+ "selected": false
+ },
+ {
+ "source": "fc1e3b34-6e01-4fb6-8c26-a70535fa1ff2",
+ "sourceHandle": "top",
+ "target": "1c0330be-83dd-4d92-9bd1-d62a36e90c7b",
+ "targetHandle": "bottom",
+ "id": "1737998342518-fc1e3b34-6e01-4fb6-8c26-a70535fa1ff2-1c0330be-83dd-4d92-9bd1-d62a36e90c7b",
+ "type": "inheritance",
+ "selected": false
+ },
+ {
+ "source": "552eb7f3-62a7-45d9-8133-da6f5379b5a4",
+ "sourceHandle": "top",
+ "target": "1c0330be-83dd-4d92-9bd1-d62a36e90c7b",
+ "targetHandle": "bottom",
+ "id": "1737998344813-552eb7f3-62a7-45d9-8133-da6f5379b5a4-1c0330be-83dd-4d92-9bd1-d62a36e90c7b",
+ "type": "inheritance",
+ "selected": false
+ }
+ ]
+}
diff --git a/standalone/webapp/assets/diagramTemplates/Observer.json b/standalone/webapp/assets/diagramTemplates/Observer.json
new file mode 100644
index 0000000..4958d88
--- /dev/null
+++ b/standalone/webapp/assets/diagramTemplates/Observer.json
@@ -0,0 +1,121 @@
+{
+ "version": "apollon2",
+ "title": "Observer",
+ "nodes": [
+ {
+ "width": 223.02252197265625,
+ "height": 142,
+ "id": "ea2576c6-d132-47d0-8caa-8f4a6df78256",
+ "type": "class",
+ "position": { "x": -60, "y": 30 },
+ "data": {
+ "name": "Publisher",
+ "methods": [
+ {
+ "id": "e191f8a6-e51b-4564-b4cb-26ab79681799",
+ "name": "+ subscribe(subscriber)"
+ },
+ {
+ "id": "f0231957-8d8f-4706-b83b-17ef92a6feec",
+ "name": "+ unsubscribe(subscriber)"
+ },
+ { "id": "e73f83c0-e4fd-468c-8974-d8f9cbae6dbf", "name": "+ notify()" }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 223, "height": 142 },
+ "dragging": true
+ },
+ {
+ "width": 223.02252197265625,
+ "height": 142,
+ "id": "db6efc15-44dc-427e-9352-1a4bed4d239b",
+ "type": "class",
+ "position": { "x": -60, "y": 290 },
+ "data": {
+ "name": "ConcretePublisher",
+ "methods": [
+ {
+ "id": "e191f8a6-e51b-4564-b4cb-26ab79681799",
+ "name": "+ subscribe(subscriber)"
+ },
+ {
+ "id": "bf9d9d7c-d4be-4585-afdf-6ee32f1efccf",
+ "name": "+ unsubscribe(subscriber)"
+ },
+ { "id": "43be27fb-dbe5-45ea-8ea3-fad50f07dcbb", "name": "+ notify()" }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 223, "height": 142 },
+ "dragging": true
+ },
+ {
+ "width": 194.7955780029297,
+ "height": 82,
+ "id": "659c7ab7-a771-400c-bd7c-ef061f1668f3",
+ "type": "class",
+ "position": { "x": 450, "y": 310 },
+ "data": {
+ "name": "ConcreteSubscriber",
+ "methods": [
+ { "id": "e191f8a6-e51b-4564-b4cb-26ab79681799", "name": "+ update()" }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 195, "height": 82 },
+ "dragging": true,
+ "resizing": false
+ },
+ {
+ "width": 230,
+ "height": 82,
+ "id": "b399bebd-10a6-444d-9c09-cf14f41aec7d",
+ "type": "class",
+ "position": { "x": 430, "y": 40 },
+ "data": {
+ "name": "Subscriber",
+ "methods": [
+ { "id": "e191f8a6-e51b-4564-b4cb-26ab79681799", "name": "+ update()" }
+ ],
+ "attributes": []
+ },
+ "selected": false,
+ "measured": { "width": 230, "height": 82 },
+ "resizing": false,
+ "dragging": true
+ }
+ ],
+ "edges": [
+ {
+ "source": "db6efc15-44dc-427e-9352-1a4bed4d239b",
+ "sourceHandle": "top",
+ "target": "ea2576c6-d132-47d0-8caa-8f4a6df78256",
+ "targetHandle": "bottom",
+ "id": "1737998028042-db6efc15-44dc-427e-9352-1a4bed4d239b-ea2576c6-d132-47d0-8caa-8f4a6df78256",
+ "type": "inheritance",
+ "selected": false
+ },
+ {
+ "source": "ea2576c6-d132-47d0-8caa-8f4a6df78256",
+ "sourceHandle": "right-top",
+ "target": "b399bebd-10a6-444d-9c09-cf14f41aec7d",
+ "targetHandle": "left-top",
+ "id": "1737998083879-ea2576c6-d132-47d0-8caa-8f4a6df78256-b399bebd-10a6-444d-9c09-cf14f41aec7d",
+ "type": "biassociation",
+ "selected": false
+ },
+ {
+ "source": "659c7ab7-a771-400c-bd7c-ef061f1668f3",
+ "sourceHandle": "top",
+ "target": "b399bebd-10a6-444d-9c09-cf14f41aec7d",
+ "targetHandle": "bottom",
+ "id": "1737998095406-659c7ab7-a771-400c-bd7c-ef061f1668f3-b399bebd-10a6-444d-9c09-cf14f41aec7d",
+ "type": "inheritance",
+ "selected": false
+ }
+ ]
+}
diff --git a/standalone/webapp/images/logo.png b/standalone/webapp/assets/images/logo.png
similarity index 100%
rename from standalone/webapp/images/logo.png
rename to standalone/webapp/assets/images/logo.png
diff --git a/standalone/webapp/index.html b/standalone/webapp/index.html
index 93cb6a1..7b61ca9 100644
--- a/standalone/webapp/index.html
+++ b/standalone/webapp/index.html
@@ -2,9 +2,9 @@
-
+
- Apollon TUM
+ Apollon2
diff --git a/standalone/webapp/src/components/modals/NewDiagramFromTemplateModal.tsx b/standalone/webapp/src/components/modals/NewDiagramFromTemplateModal.tsx
new file mode 100644
index 0000000..320ed61
--- /dev/null
+++ b/standalone/webapp/src/components/modals/NewDiagramFromTemplateModal.tsx
@@ -0,0 +1,199 @@
+import Box from "@mui/material/Box"
+import Modal from "@mui/material/Modal"
+import { useApollon2Context } from "@/contexts"
+import Button from "@mui/material/Button/Button"
+import { useModalContext } from "@/contexts/ModalContext"
+import ListItemText from "@mui/material/ListItemText"
+import MenuItem from "@mui/material/MenuItem"
+import MenuList from "@mui/material/MenuList"
+import Divider from "@mui/material/Divider"
+import { Paper, Typography } from "@mui/material"
+import CloseOutlinedIcon from "@mui/icons-material/CloseOutlined"
+import { useState } from "react"
+
+const style = {
+ position: "absolute",
+ top: "50%",
+ left: "50%",
+ transform: "translate(-50%, -50%)",
+ bgcolor: "background.paper",
+ display: "flex",
+ flex: 1,
+ flexDirection: "column",
+ minWidth: 350,
+ gap: 1,
+}
+
+enum TemplateType {
+ Adapter = "Adapter",
+ Bridge = "Bridge",
+ Command = "Command",
+ Observer = "Observer",
+ Factory = "Factory",
+}
+
+export const NewDiagramFromTemplateModal = () => {
+ const { apollon2, setDiagramName } = useApollon2Context()
+ const { closeModal } = useModalContext()
+ const [selectedTemplate, setSelectedTemplate] = useState(
+ TemplateType.Adapter
+ )
+ const [error, setError] = useState(null)
+
+ const handleCreate = async () => {
+ console.log("Create diagram from template")
+ setError(null)
+
+ try {
+ const jsonModule = await import(
+ `assets/diagramTemplates/${selectedTemplate}.json`
+ )
+ const jsonData = jsonModule.default
+
+ if (!jsonData) {
+ throw new Error("Selected template data not found")
+ }
+
+ const JsonDataINStringFormat = JSON.stringify(jsonData)
+ const diagramName = jsonData.title as string
+
+ setDiagramName(diagramName)
+ apollon2?.importJson(JsonDataINStringFormat)
+ closeModal()
+ } catch (err: unknown) {
+ console.error("Error creating diagram from template:", err)
+
+ if (err instanceof Error) {
+ setError(err.message)
+ } else {
+ setError("An unexpected error occurred")
+ }
+ }
+ }
+
+ return (
+
+
+ {/* Header */}
+
+
+ Start Diagram from template
+
+
+
+
+
+
+ {error && (
+
+ {error}
+
+ )}
+
+ {/* Selected Template */}
+
+ Selected Template
+
+ {selectedTemplate}
+
+
+
+
+ Structural
+
+
+
+
+ Behavioral
+
+
+
+
+ Creational
+
+
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/standalone/webapp/src/components/modals/index.ts b/standalone/webapp/src/components/modals/index.ts
index e69de29..896b99e 100644
--- a/standalone/webapp/src/components/modals/index.ts
+++ b/standalone/webapp/src/components/modals/index.ts
@@ -0,0 +1,2 @@
+export * from "./NewDiagramFromTemplateModal"
+export * from "./NewDiagramModal"
diff --git a/standalone/webapp/src/components/navbar/DesktopNavbar.tsx b/standalone/webapp/src/components/navbar/DesktopNavbar.tsx
index e118a62..27003e6 100644
--- a/standalone/webapp/src/components/navbar/DesktopNavbar.tsx
+++ b/standalone/webapp/src/components/navbar/DesktopNavbar.tsx
@@ -22,7 +22,7 @@ export const DesktopNavbar = () => {
{/* Logo */}
-
+
= ({ color }) => {
)
const handleNewFile = useCallback(() => {
- openModal("NEWDIAGRAM")
+ openModal("NEW_DIAGRAM")
closeMainMenu()
}, [openModal, closeMainMenu])
const handleStartFromTemplate = useCallback(() => {
- // Implement the functionality for starting from a template
+ openModal("NEW_DIAGRAM_FROM_TEMPLATE")
closeMainMenu()
}, [closeMainMenu])
diff --git a/standalone/webapp/src/types/ModalTypes.ts b/standalone/webapp/src/types/ModalTypes.ts
index c54ebf7..c1ea51c 100644
--- a/standalone/webapp/src/types/ModalTypes.ts
+++ b/standalone/webapp/src/types/ModalTypes.ts
@@ -1,6 +1,5 @@
-export type ModalName = "NEWDIAGRAM" // Extend as needed
+export type ModalName = "NEW_DIAGRAM" | "NEW_DIAGRAM_FROM_TEMPLATE" // Extend as needed
export interface ModalProps {
- // Define any props your modals might need
[key: string]: unknown
}
diff --git a/standalone/webapp/src/wrappers/ModalWrapper.tsx b/standalone/webapp/src/wrappers/ModalWrapper.tsx
index 1c716a2..5611e67 100644
--- a/standalone/webapp/src/wrappers/ModalWrapper.tsx
+++ b/standalone/webapp/src/wrappers/ModalWrapper.tsx
@@ -1,10 +1,10 @@
-// ModalWrapper.tsx
-import { NewDiagramModal } from "@/components/modals/NewDiagramModal"
+import {
+ NewDiagramModal,
+ NewDiagramFromTemplateModal,
+} from "@/components/modals"
import { ModalName, ModalProps } from "@/types"
import React from "react"
-// Import other modals as needed
-
interface ModalWrapperProps {
name: ModalName
props?: ModalProps
@@ -13,7 +13,8 @@ interface ModalWrapperProps {
// Define a mapping from modal names to modal components
const MODAL_COMPONENTS: Record> = {
- NEWDIAGRAM: NewDiagramModal,
+ NEW_DIAGRAM: NewDiagramModal,
+ NEW_DIAGRAM_FROM_TEMPLATE: NewDiagramFromTemplateModal,
// Add other modals here
}
diff --git a/standalone/webapp/vite.config.ts b/standalone/webapp/vite.config.ts
index 9055213..ccc1e21 100644
--- a/standalone/webapp/vite.config.ts
+++ b/standalone/webapp/vite.config.ts
@@ -8,6 +8,7 @@ export default defineConfig({
resolve: {
alias: {
"@": resolve(__dirname, "src"),
+ assets: resolve(__dirname, "assets"),
},
},
})