diff --git a/src/main/java/org/gridsuite/study/server/StudyController.java b/src/main/java/org/gridsuite/study/server/StudyController.java index a57823e37..d888cab06 100644 --- a/src/main/java/org/gridsuite/study/server/StudyController.java +++ b/src/main/java/org/gridsuite/study/server/StudyController.java @@ -1296,6 +1296,19 @@ public ResponseEntity updateNode(@RequestBody NetworkModificationNode node return ResponseEntity.ok().build(); } + @PutMapping(value = "/studies/{studyUuid}/tree/nodes/{parentUuid}/children-column-positions") + @Operation(summary = "update children column positions") + @ApiResponses(value = { + @ApiResponse(responseCode = "200", description = "the node column positions have been updated"), + @ApiResponse(responseCode = "404", description = "The study or a node was not found")}) + public ResponseEntity updateNodesColumnPositions(@RequestBody List children, + @Parameter(description = "study uuid") @PathVariable("studyUuid") UUID studyUuid, + @Parameter(description = "parent node uuid") @PathVariable("parentUuid") UUID parentUuid, + @RequestHeader(HEADER_USER_ID) String userId) { + networkModificationTreeService.updateNodesColumnPositions(studyUuid, parentUuid, children, userId); + return ResponseEntity.ok().build(); + } + @GetMapping(value = "/studies/{studyUuid}/tree/nodes/{id}") @Operation(summary = "get simplified node") @ApiResponses(value = { diff --git a/src/main/java/org/gridsuite/study/server/networkmodificationtree/AbstractNodeRepositoryProxy.java b/src/main/java/org/gridsuite/study/server/networkmodificationtree/AbstractNodeRepositoryProxy.java index 51a8c7a1e..6dec21ee9 100644 --- a/src/main/java/org/gridsuite/study/server/networkmodificationtree/AbstractNodeRepositoryProxy.java +++ b/src/main/java/org/gridsuite/study/server/networkmodificationtree/AbstractNodeRepositoryProxy.java @@ -39,6 +39,7 @@ protected U completeNodeInfo(AbstractNodeInfoEntity nodeInfoEntity, U node) { node.setId(nodeInfoEntity.getId()); node.setName(nodeInfoEntity.getName()); node.setDescription(nodeInfoEntity.getDescription()); + node.setColumnPosition(nodeInfoEntity.getColumnPosition()); node.setReadOnly(nodeInfoEntity.getReadOnly()); return node; } diff --git a/src/main/java/org/gridsuite/study/server/networkmodificationtree/dto/AbstractNode.java b/src/main/java/org/gridsuite/study/server/networkmodificationtree/dto/AbstractNode.java index aec11d121..1c56baecf 100644 --- a/src/main/java/org/gridsuite/study/server/networkmodificationtree/dto/AbstractNode.java +++ b/src/main/java/org/gridsuite/study/server/networkmodificationtree/dto/AbstractNode.java @@ -48,6 +48,8 @@ public abstract class AbstractNode { String description; + Integer columnPosition; + Boolean readOnly; NodeType type; diff --git a/src/main/java/org/gridsuite/study/server/networkmodificationtree/entities/AbstractNodeInfoEntity.java b/src/main/java/org/gridsuite/study/server/networkmodificationtree/entities/AbstractNodeInfoEntity.java index 388be9482..3cb34673b 100644 --- a/src/main/java/org/gridsuite/study/server/networkmodificationtree/entities/AbstractNodeInfoEntity.java +++ b/src/main/java/org/gridsuite/study/server/networkmodificationtree/entities/AbstractNodeInfoEntity.java @@ -44,6 +44,9 @@ public UUID getId() { @Column String description; + @Column + Integer columnPosition; + @Column Boolean readOnly; } diff --git a/src/main/java/org/gridsuite/study/server/notification/NotificationService.java b/src/main/java/org/gridsuite/study/server/notification/NotificationService.java index 792dacd06..6ae7dc329 100644 --- a/src/main/java/org/gridsuite/study/server/notification/NotificationService.java +++ b/src/main/java/org/gridsuite/study/server/notification/NotificationService.java @@ -23,6 +23,7 @@ import java.time.Instant; import java.util.Collection; +import java.util.List; import java.util.Set; import java.util.UUID; @@ -113,6 +114,7 @@ public class NotificationService { public static final String NODE_RENAMED = "nodeRenamed"; public static final String NODE_BUILD_STATUS_UPDATED = "nodeBuildStatusUpdated"; public static final String SUBTREE_MOVED = "subtreeMoved"; + public static final String NODES_COLUMN_POSITIONS_CHANGED = "nodesColumnPositionsChanged"; public static final String SUBTREE_CREATED = "subtreeCreated"; public static final String MESSAGE_LOG = "Sending message : {}"; public static final String DEFAULT_ERROR_MESSAGE = "Unknown error"; @@ -309,6 +311,20 @@ public void emitSubtreeMoved(UUID studyUuid, UUID parentNodeSubtreeMoved, UUID r ); } + @PostCompletion + public void emitColumnsChanged(UUID studyUuid, UUID parentNodeUuid, List orderedUuids) { + try { + sendUpdateMessage(MessageBuilder.withPayload(objectMapper.writeValueAsString(orderedUuids)) + .setHeader(HEADER_STUDY_UUID, studyUuid) + .setHeader(HEADER_UPDATE_TYPE, NODES_COLUMN_POSITIONS_CHANGED) + .setHeader(HEADER_PARENT_NODE, parentNodeUuid) + .build() + ); + } catch (JsonProcessingException e) { + LOGGER.error("Unable to notify on column positions update", e); + } + } + @PostCompletion public void emitSubtreeInserted(UUID studyUuid, UUID parentNodeSubtreeInserted, UUID referenceNodeUuid) { sendUpdateMessage(MessageBuilder.withPayload("") diff --git a/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java b/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java index bbcc8ea4f..90ba2c9d8 100644 --- a/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java +++ b/src/main/java/org/gridsuite/study/server/service/NetworkModificationTreeService.java @@ -445,6 +445,27 @@ public void updateNode(UUID studyUuid, NetworkModificationNode node, String user notificationService.emitElementUpdated(studyUuid, userId); } + @Transactional + public void updateNodesColumnPositions(UUID studyUuid, UUID parentUuid, List childrenNodes, String userId) { + // Convert to a map for quick lookup + Map nodeIdToColumnPosition = childrenNodes.stream() + .collect(Collectors.toMap(NetworkModificationNode::getId, NetworkModificationNode::getColumnPosition)); + + List childrenIds = childrenNodes.stream().map(NetworkModificationNode::getId).toList(); + networkModificationNodeInfoRepository.findAllById(childrenIds).forEach(entity -> { + Integer newColumnPosition = nodeIdToColumnPosition.get(entity.getId()); + entity.setColumnPosition(Objects.requireNonNull(newColumnPosition)); + }); + + List orderedUuids = childrenNodes.stream() + .sorted(Comparator.comparingInt(AbstractNode::getColumnPosition)) + .map(NetworkModificationNode::getId) + .toList(); + + notificationService.emitColumnsChanged(studyUuid, parentUuid, orderedUuids); + notificationService.emitElementUpdated(studyUuid, userId); + } + private boolean isRenameNode(AbstractNode node) { NetworkModificationNode renameNode = NetworkModificationNode.builder() .id(node.getId()) diff --git a/src/main/resources/db/changelog/changesets/changelog_20241213T125757Z.xml b/src/main/resources/db/changelog/changesets/changelog_20241213T125757Z.xml new file mode 100644 index 000000000..dd8a32f7e --- /dev/null +++ b/src/main/resources/db/changelog/changesets/changelog_20241213T125757Z.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog/db.changelog-master.yaml b/src/main/resources/db/changelog/db.changelog-master.yaml index d4baeb7f0..ecf55dd25 100644 --- a/src/main/resources/db/changelog/db.changelog-master.yaml +++ b/src/main/resources/db/changelog/db.changelog-master.yaml @@ -269,5 +269,8 @@ databaseChangeLog: file: changesets/changelog_20241211T123019Z.xml relativeToChangelogFile: true - include: - file: changesets/changelog_20241211T181846Z.xml + file: changesets/changelog_20241213T125757Z.xml relativeToChangelogFile: true + - include: + file: changesets/changelog_20241211T181846Z.xml + relativeToChangelogFile: true \ No newline at end of file diff --git a/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java b/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java index fe3877748..74796485b 100644 --- a/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java +++ b/src/test/java/org/gridsuite/study/server/NetworkModificationTreeTest.java @@ -874,6 +874,34 @@ void testNodeUpdate() throws Exception { .andExpect(status().isNotFound()); } + @Test + void testUpdateNodesColumnPositions() throws Exception { + String userId = "userId"; + RootNode root = createRoot(); + final NetworkModificationNode node1 = buildNetworkModificationNode("nod", "silently", UUID.randomUUID(), VARIANT_ID, UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), BuildStatus.NOT_BUILT); + final NetworkModificationNode node2 = buildNetworkModificationNode("nodding", "politely", UUID.randomUUID(), VARIANT_ID, UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), UUID.randomUUID(), BuildStatus.NOT_BUILT); + createNode(root.getStudyId(), root, node1, userId); + createNode(root.getStudyId(), root, node2, userId); + assertNull(node1.getColumnPosition()); + node1.setColumnPosition(1); + node2.setColumnPosition(0); + List nodes = List.of(node1, node2); + + mockMvc.perform(put("/v1/studies/{studyUuid}/tree/nodes/{parentUuid}/children-column-positions", root.getStudyId(), root.getId()) + .contentType(MediaType.APPLICATION_JSON) + .content(objectWriter.writeValueAsString(nodes)) + .header(USER_ID_HEADER, "userId")) + .andExpect(status().isOk()); + + List nodesUuids = List.of(node2.getId(), node1.getId()); + for (NetworkModificationNodeInfoEntity entity : networkModificationNodeInfoRepository.findAllById(nodesUuids)) { + assertEquals(entity.getId().equals(node2.getId()) ? 0 : 1, entity.getColumnPosition()); + } + + checkColumnsChangedMessageSent(root.getStudyId(), root.getId(), nodesUuids); + checkElementUpdatedMessageSent(root.getStudyId(), userId); + } + // This test is for a part of the code that is not used yet // We update a node description (this is not used in the front) and we assume that it will emit a nodeUpdated notif // If it's not the case or if this test causes problems feel free to update it / remove it as needed @@ -1336,6 +1364,14 @@ private void checkElementUpdatedMessageSent(UUID elementUuid, String userId) { assertEquals(userId, message.getHeaders().get(NotificationService.HEADER_MODIFIED_BY)); } + private void checkColumnsChangedMessageSent(UUID studyUuid, UUID parentNodeUuid, List orderedUuids) throws Exception { + Message message = output.receive(TIMEOUT, STUDY_UPDATE_DESTINATION); + assertEquals(NotificationService.NODES_COLUMN_POSITIONS_CHANGED, message.getHeaders().get(NotificationService.HEADER_UPDATE_TYPE)); + assertEquals(studyUuid, message.getHeaders().get(NotificationService.HEADER_STUDY_UUID)); + assertEquals(parentNodeUuid, message.getHeaders().get(NotificationService.HEADER_PARENT_NODE)); + assertEquals(objectMapper.writeValueAsString(orderedUuids), new String(message.getPayload())); + } + private void checkUpdateNodesMessageReceived(UUID studyUuid, List nodesUuids) { Message messageStatus = output.receive(TIMEOUT, STUDY_UPDATE_DESTINATION); assertEquals("", new String(messageStatus.getPayload()));