Skip to content

Commit 6cbdd1e

Browse files
authored
fix(diagram): class context menu actions (#114, RDFA-529)
* fix: Fixed class context menu move actions opening delete dialog * feat: Add support for initial class diagram positioning Signed-off-by: Jan-Hendrik Spahn <jan-hendrik.spahn@soptim.de>
1 parent d6d1c07 commit 6cbdd1e

12 files changed

Lines changed: 132 additions & 142 deletions

File tree

backend/src/main/java/org/rdfarchitect/api/controller/datasets/graphs/classes/AllClassesRESTController.java

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import lombok.RequiredArgsConstructor;
2828

2929
import org.rdfarchitect.api.dto.ClassUMLAdaptedDTO;
30+
import org.rdfarchitect.api.dto.dl.ClassLayoutPositionDTO;
3031
import org.rdfarchitect.api.dto.packages.PackageDTO;
3132
import org.rdfarchitect.database.GraphIdentifier;
3233
import org.rdfarchitect.services.ExpandURIUseCase;
@@ -65,9 +66,13 @@ public class AllClassesRESTController {
6566
* added
6667
* @param classURIPrefix URI Prefix of the new class
6768
* @param className Label of the new class
69+
* @param classLayoutPosition Initial position of the new class in the diagram
6870
*/
6971
public record AddNewClassRequest(
70-
PackageDTO packageDTO, String classURIPrefix, String className) {}
72+
PackageDTO packageDTO,
73+
String classURIPrefix,
74+
String className,
75+
ClassLayoutPositionDTO classLayoutPosition) {}
7176

7277
@Operation(
7378
summary = "create new class",
@@ -112,7 +117,8 @@ public String addClass(
112117
graphIdentifier,
113118
addNewClassRequest.packageDTO,
114119
extendedClassURIPrefix,
115-
addNewClassRequest.className);
120+
addNewClassRequest.className,
121+
addNewClassRequest.classLayoutPosition);
116122

117123
logger.info(
118124
"Sending response to POST request: \"/api/datasets/{{}}/graphs/{{}}/classes\" to \"{}\".",
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* Copyright (c) 2024-2026 SOPTIM AG
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*
16+
*/
17+
18+
package org.rdfarchitect.api.dto.dl;
19+
20+
import lombok.Data;
21+
import lombok.NoArgsConstructor;
22+
23+
@Data
24+
@NoArgsConstructor
25+
public class ClassLayoutPositionDTO {
26+
27+
private float xPosition;
28+
29+
private float yPosition;
30+
}

backend/src/main/java/org/rdfarchitect/services/dl/update/DiagramLayoutServiceUtils.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,19 @@ public MRID insertDiagramObject(
8484
* @param diagramObjectMRID the mRID of the diagram object the point belongs to
8585
*/
8686
public void insertDiagramObjectPoint(Model diagramLayoutModel, MRID diagramObjectMRID) {
87+
insertDiagramObjectPoint(diagramLayoutModel, diagramObjectMRID, 0, 0);
88+
}
89+
90+
/**
91+
* Helper method for creating and inserting a {@link DiagramObjectPoint} at a given position.
92+
*
93+
* @param diagramLayoutModel the model into which the diagram object point is inserted
94+
* @param diagramObjectMRID the mRID of the diagram object the point belongs to
95+
* @param xPosition the x position of the diagram object point
96+
* @param yPosition the y position of the diagram object point
97+
*/
98+
public void insertDiagramObjectPoint(
99+
Model diagramLayoutModel, MRID diagramObjectMRID, float xPosition, float yPosition) {
87100
var maxZPosition =
88101
diagramLayoutModel.listObjectsOfProperty(DL.zPosition).toSet().stream()
89102
.max(
@@ -97,7 +110,7 @@ public void insertDiagramObjectPoint(Model diagramLayoutModel, MRID diagramObjec
97110
var diagramObjectPoint =
98111
DiagramObjectPoint.builder()
99112
.mRID(new MRID(UUID.randomUUID()))
100-
.position(new XYZPosition(0, 0, maxZPosition + 1))
113+
.position(new XYZPosition(xPosition, yPosition, maxZPosition + 1))
101114
.belongsToDiagramObject(diagramObjectMRID)
102115
.build();
103116
DLUpdates.insertDiagramObjectPoint(diagramLayoutModel, diagramObjectPoint);

backend/src/main/java/org/rdfarchitect/services/dl/update/classlayout/CreateClassLayoutDataUseCase.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.rdfarchitect.services.dl.update.classlayout;
1919

20+
import org.rdfarchitect.api.dto.dl.ClassLayoutPositionDTO;
2021
import org.rdfarchitect.api.dto.packages.PackageDTO;
2122
import org.rdfarchitect.database.GraphIdentifier;
2223

@@ -25,16 +26,20 @@
2526
public interface CreateClassLayoutDataUseCase {
2627

2728
/**
28-
* Creates the diagram layout data for a newly created class
29+
* Creates the diagram layout data for a newly created class, optionally at a given initial
30+
* position.
2931
*
3032
* @param graphIdentifier the identifier of the graph
3133
* @param packageDTO the DTO used for creating the new class
3234
* @param className the name of the newly created class
3335
* @param classUUID the UUID of the newly created class
36+
* @param classLayoutPosition the initial diagram position of the newly created class, or {@code
37+
* null} to place the class at the origin
3438
*/
3539
void createClassLayoutData(
3640
GraphIdentifier graphIdentifier,
3741
PackageDTO packageDTO,
3842
String className,
39-
UUID classUUID);
43+
UUID classUUID,
44+
ClassLayoutPositionDTO classLayoutPosition);
4045
}

backend/src/main/java/org/rdfarchitect/services/dl/update/classlayout/UpdateClassLayoutService.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import lombok.RequiredArgsConstructor;
2121

22+
import org.rdfarchitect.api.dto.dl.ClassLayoutPositionDTO;
2223
import org.rdfarchitect.api.dto.dl.ClassPositionDTO;
2324
import org.rdfarchitect.api.dto.packages.PackageDTO;
2425
import org.rdfarchitect.api.dto.packages.PackageMapper;
@@ -50,7 +51,8 @@ public void createClassLayoutData(
5051
GraphIdentifier graphIdentifier,
5152
PackageDTO packageDTO,
5253
String className,
53-
UUID classUUID) {
54+
UUID classUUID,
55+
ClassLayoutPositionDTO classLayoutPosition) {
5456
var diagramLayout = databasePort.getGraphWithContext(graphIdentifier).getDiagramLayout();
5557
var diagramLayoutModel = diagramLayout.getDiagramLayoutModel();
5658
UUID packageUUID;
@@ -65,7 +67,10 @@ public void createClassLayoutData(
6567
MRID doMRID =
6668
DiagramLayoutServiceUtils.insertDiagramObject(
6769
diagramLayoutModel, packageUUID, className, classUUID);
68-
DiagramLayoutServiceUtils.insertDiagramObjectPoint(diagramLayoutModel, doMRID);
70+
float xPosition = classLayoutPosition != null ? classLayoutPosition.getXPosition() : 0;
71+
float yPosition = classLayoutPosition != null ? classLayoutPosition.getYPosition() : 0;
72+
DiagramLayoutServiceUtils.insertDiagramObjectPoint(
73+
diagramLayoutModel, doMRID, xPosition, yPosition);
6974
}
7075

7176
@Override

backend/src/main/java/org/rdfarchitect/services/update/classes/AddClassUseCase.java

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
package org.rdfarchitect.services.update.classes;
1919

20+
import org.rdfarchitect.api.dto.dl.ClassLayoutPositionDTO;
2021
import org.rdfarchitect.api.dto.packages.PackageDTO;
2122
import org.rdfarchitect.database.GraphIdentifier;
2223

@@ -25,19 +26,21 @@
2526
public interface AddClassUseCase {
2627

2728
/**
28-
* Constructs a new class and adds it to the specified graph. All optional parameters are set to
29-
* null. The label of the class is set to NewClass with an index number appended if a NewClass
30-
* already exists in the graph.
29+
* Constructs a new class and adds it to the specified graph, optionally at a given initial
30+
* diagram layout position.
3131
*
3232
* @param graphIdentifier The graph URI and database name of the graph to add the class to.
3333
* @param packageDTO The Package to which the class will be added.
3434
* @param classURIPrefix The prefix of the class to be added.
3535
* @param className The name of the class to be added.
36+
* @param classLayoutPosition The initial diagram position of the class, or {@code null} to
37+
* place the class at the origin.
3638
* @return The UUID of the newly created class.
3739
*/
3840
UUID addClass(
3941
GraphIdentifier graphIdentifier,
4042
PackageDTO packageDTO,
4143
String classURIPrefix,
42-
String className);
44+
String className,
45+
ClassLayoutPositionDTO classLayoutPosition);
4346
}

backend/src/main/java/org/rdfarchitect/services/update/classes/UpdateClassService.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import org.apache.jena.vocabulary.RDF;
2222
import org.rdfarchitect.api.dto.ClassUMLAdaptedDTO;
2323
import org.rdfarchitect.api.dto.ClassUMLAdaptedMapper;
24+
import org.rdfarchitect.api.dto.dl.ClassLayoutPositionDTO;
2425
import org.rdfarchitect.api.dto.packages.PackageDTO;
2526
import org.rdfarchitect.api.dto.packages.PackageMapper;
2627
import org.rdfarchitect.database.DatabasePort;
@@ -110,7 +111,8 @@ public UUID addClass(
110111
GraphIdentifier graphIdentifier,
111112
PackageDTO packageDTO,
112113
String classURIPrefix,
113-
String className) {
114+
String className,
115+
ClassLayoutPositionDTO classLayoutPosition) {
114116
var cimPackage = packageMapper.toCIMObject(packageDTO);
115117
GraphRewindableWithUUIDs graph = null;
116118
UUID newClassUUID;
@@ -133,7 +135,7 @@ public UUID addClass(
133135
}
134136

135137
createClassLayoutDataUseCase.createClassLayoutData(
136-
graphIdentifier, packageDTO, className, newClassUUID);
138+
graphIdentifier, packageDTO, className, newClassUUID, classLayoutPosition);
137139

138140
changeLogUseCase.recordChange(
139141
graphIdentifier,

backend/src/test/java/org/rdfarchitect/services/dl/update/UpdateClassLayoutServiceTest.java

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.apache.jena.rdf.model.ResourceFactory;
2121
import org.junit.jupiter.api.BeforeAll;
2222
import org.junit.jupiter.api.Test;
23+
import org.rdfarchitect.api.dto.dl.ClassLayoutPositionDTO;
2324
import org.rdfarchitect.api.dto.dl.ClassPositionDTO;
2425
import org.rdfarchitect.api.dto.packages.PackageDTO;
2526
import org.rdfarchitect.dl.data.DLUtils;
@@ -51,12 +52,36 @@ void createClassLayoutData_diagramExists_createsClassLayoutData() {
5152
.label(PACKAGE_A_LABEL)
5253
.prefix("ex")
5354
.build();
54-
service.createClassLayoutData(graphIdentifier, packageDTO, CLASS_A_LABEL, CLASS_A_UUID);
55+
service.createClassLayoutData(
56+
graphIdentifier, packageDTO, CLASS_A_LABEL, CLASS_A_UUID, null);
5557

5658
// Assert
5759
assertInitialClassLayoutData(CLASS_A_UUID, PACKAGE_A_UUID, CLASS_A_LABEL);
5860
}
5961

62+
@Test
63+
void createClassLayoutData_withInitialPosition_createsClassLayoutDataAtPosition() {
64+
// Arrange
65+
addGraphFromFile("package.ttl");
66+
var packageDTO =
67+
PackageDTO.builder()
68+
.uuid(PACKAGE_A_UUID)
69+
.label(PACKAGE_A_LABEL)
70+
.prefix("ex")
71+
.build();
72+
var classLayoutPosition = new ClassLayoutPositionDTO();
73+
classLayoutPosition.setXPosition(123.0F);
74+
classLayoutPosition.setYPosition(456.0F);
75+
76+
// Act
77+
service.createClassLayoutData(
78+
graphIdentifier, packageDTO, CLASS_A_LABEL, CLASS_A_UUID, classLayoutPosition);
79+
80+
// Assert
81+
assertDiagramObject(CLASS_A_UUID, PACKAGE_A_UUID, CLASS_A_LABEL);
82+
assertDiagramObjectCoordinates(CLASS_A_UUID, 123.0F, 456.0F);
83+
}
84+
6085
@Test
6186
void updateClassPositions_fullGraph_repositionsClasses() {
6287
// Arrange

backend/src/test/java/org/rdfarchitect/services/update/UpdateClassServiceTest.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ void addClass_createsNewClass() {
103103
.label("default")
104104
.build();
105105

106-
updateClassService.addClass(graphIdentifier, packageDTO, PREFIX, "newClass");
106+
updateClassService.addClass(graphIdentifier, packageDTO, PREFIX, "newClass", null);
107107

108108
var graph = databasePort.getGraphWithContext(graphIdentifier).getRdfGraph();
109109
try {
@@ -150,7 +150,11 @@ void addClass_packageWithSameIriExists_throwsConflict() {
150150
assertThatThrownBy(
151151
() ->
152152
updateClassService.addClass(
153-
graphIdentifier, packageDTO, PREFIX, "packageCollision"))
153+
graphIdentifier,
154+
packageDTO,
155+
PREFIX,
156+
"packageCollision",
157+
null))
154158
.isInstanceOf(ResourceConflictException.class)
155159
.hasMessageContaining("package with the same IRI");
156160

frontend/src/lib/rendering/svelteflow/components/SvelteFlowPaneContextMenu.svelte

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
let triggerRef = $state(null);
4040
let open = $state(false);
4141
let showNewClassDialog = $state(false);
42+
let classLayoutPosition = $state(null);
4243
4344
let triggerStyle = $derived(getContextMenuTriggerStyle(request));
4445
@@ -56,6 +57,12 @@
5657
}
5758
5859
function openNewClassDialog() {
60+
classLayoutPosition = request?.flowPosition
61+
? {
62+
xPosition: request.flowPosition.x,
63+
yPosition: request.flowPosition.y,
64+
}
65+
: null;
5966
showNewClassDialog = true;
6067
onClose();
6168
}
@@ -83,5 +90,6 @@
8390
bind:showDialog={showNewClassDialog}
8491
{lockedDatasetName}
8592
{lockedGraphUri}
93+
{classLayoutPosition}
8694
{onClassCreated}
8795
/>

0 commit comments

Comments
 (0)