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 + setSelectedTemplate(TemplateType.Adapter)} + onDoubleClick={handleCreate} + > + Adapter + + setSelectedTemplate(TemplateType.Bridge)} + onDoubleClick={handleCreate} + > + Bridge + + + + Behavioral + setSelectedTemplate(TemplateType.Command)} + onDoubleClick={handleCreate} + > + Command + + setSelectedTemplate(TemplateType.Observer)} + onDoubleClick={handleCreate} + > + Observer + + + + Creational + setSelectedTemplate(TemplateType.Factory)} + onDoubleClick={handleCreate} + > + Factory + + + + + + + + + + + ) +} 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 {/* Logo */} - Logo + 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"), }, }, })