Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@
import org.gridsuite.study.server.dto.*;
import org.gridsuite.study.server.dto.computation.LoadFlowComputationInfos;
import org.gridsuite.study.server.dto.diagramgridlayout.DiagramGridLayout;
import org.gridsuite.study.server.dto.diagramgridlayout.nad.NadConfigInfos;
import org.gridsuite.study.server.dto.dynamicmapping.MappingInfos;
import org.gridsuite.study.server.dto.dynamicmapping.ModelInfos;
import org.gridsuite.study.server.dto.dynamicsecurityanalysis.DynamicSecurityAnalysisStatus;
Expand Down Expand Up @@ -2537,32 +2536,4 @@ public ResponseEntity<Void> setPccMinParameters(
studyService.setPccMinParameters(studyUuid, pccMinParametersInfos, userId);
return ResponseEntity.ok().build();
}

@PostMapping(value = "/studies/{studyUuid}/nad-configs", consumes = MediaType.APPLICATION_JSON_VALUE)
@Operation(summary = "Save NAD config")
@ApiResponses(value = {
@ApiResponse(responseCode = "200", description = "NAD config is saved"),
@ApiResponse(responseCode = "404", description = "Study does not exist")
})
public ResponseEntity<UUID> saveNadConfig(
@PathVariable("studyUuid") UUID studyUuid,
@RequestBody NadConfigInfos nadConfigData) {
studyService.assertIsStudyExist(studyUuid);
UUID savedUuid = studyService.saveNadConfig(studyUuid, nadConfigData);
return ResponseEntity.ok().body(savedUuid);
}

@DeleteMapping(value = "/studies/{studyUuid}/nad-configs/{nadConfigUuid}")
@Operation(summary = "Delete NAD config")
@ApiResponses(value = {
@ApiResponse(responseCode = "204", description = "NAD config is deleted"),
@ApiResponse(responseCode = "404", description = "Study does not exist")
})
public ResponseEntity<Void> deleteNadConfig(
@PathVariable("studyUuid") UUID studyUuid,
@PathVariable("nadConfigUuid") UUID nadConfigUuid) {
studyService.assertIsStudyExist(studyUuid);
studyService.deleteNadConfig(studyUuid, nadConfigUuid);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
/*
* Copyright (c) 2025, RTE (http://www.rte-france.com)
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
package org.gridsuite.study.server.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.gridsuite.study.server.StudyApi;
import org.gridsuite.study.server.service.WorkspaceService;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.Map;
import java.util.UUID;

@RestController
@RequestMapping(value = "/" + StudyApi.API_VERSION + "/studies/{studyUuid}/workspaces")
@Tag(name = "Study server - Workspaces")
public class WorkspaceController {
private final WorkspaceService workspaceService;

public WorkspaceController(WorkspaceService workspaceService) {
this.workspaceService = workspaceService;
}

@GetMapping("")
@Operation(summary = "Get workspaces metadata")
@ApiResponse(responseCode = "200", description = "Workspaces metadata retrieved")
@ApiResponse(responseCode = "404", description = "Study not found")
public ResponseEntity<String> getWorkspaces(
@PathVariable UUID studyUuid) {
return ResponseEntity.ok(workspaceService.getWorkspaces(studyUuid));
}

@GetMapping("/{workspaceId}")
@Operation(summary = "Get a specific workspace")
@ApiResponse(responseCode = "200", description = "Workspace retrieved")
@ApiResponse(responseCode = "404", description = "Study or workspace not found")
public ResponseEntity<String> getWorkspace(
@PathVariable UUID studyUuid,
@PathVariable UUID workspaceId) {
return ResponseEntity.ok(workspaceService.getWorkspace(studyUuid, workspaceId));
}

@PutMapping("/{workspaceId}/name")
@Operation(summary = "Rename a workspace")
@ApiResponse(responseCode = "204", description = "Workspace renamed")
@ApiResponse(responseCode = "404", description = "Study or workspace not found")
public ResponseEntity<Void> renameWorkspace(
@PathVariable UUID studyUuid,
@PathVariable UUID workspaceId,
@RequestBody String name,
@RequestHeader(value = "clientId", required = false) String clientId) {
workspaceService.renameWorkspace(studyUuid, workspaceId, name, clientId);
return ResponseEntity.noContent().build();
}

@GetMapping("/{workspaceId}/panels")
@Operation(summary = "Get panels from a workspace")
@ApiResponse(responseCode = "200", description = "Panels retrieved")
@ApiResponse(responseCode = "404", description = "Study or workspace not found")
public ResponseEntity<String> getPanels(
@PathVariable UUID studyUuid,
@PathVariable UUID workspaceId,
@RequestParam(required = false) List<String> panelIds) {
return ResponseEntity.ok(workspaceService.getWorkspacePanels(studyUuid, workspaceId, panelIds));
}

@PostMapping("/{workspaceId}/panels")
@Operation(summary = "Create or update panels in a workspace")
@ApiResponse(responseCode = "204", description = "Panels created or updated")
@ApiResponse(responseCode = "404", description = "Study or workspace not found")
public ResponseEntity<Void> createOrUpdatePanels(
@PathVariable UUID studyUuid,
@PathVariable UUID workspaceId,
@RequestBody String panelsDto,
@RequestHeader(value = "clientId", required = false) String clientId) {
workspaceService.createOrUpdateWorkspacePanels(studyUuid, workspaceId, panelsDto, clientId);
return ResponseEntity.noContent().build();
}

@DeleteMapping("/{workspaceId}/panels")
@Operation(summary = "Delete panels from a workspace")
@ApiResponse(responseCode = "204", description = "Panels deleted")
@ApiResponse(responseCode = "404", description = "Study or workspace not found")
public ResponseEntity<Void> deletePanels(
@PathVariable UUID studyUuid,
@PathVariable UUID workspaceId,
@RequestBody(required = false) String panelIds,
@RequestHeader(value = "clientId", required = false) String clientId) {
workspaceService.deleteWorkspacePanels(studyUuid, workspaceId, panelIds, clientId);
return ResponseEntity.noContent().build();
}

@PostMapping("/{workspaceId}/panels/{panelId}/current-nad-config")
@Operation(summary = "Save NAD config")
@ApiResponse(responseCode = "201", description = "NAD config saved")
@ApiResponse(responseCode = "404", description = "Study not found")
public ResponseEntity<UUID> saveNadConfig(
@PathVariable UUID studyUuid,
@PathVariable UUID workspaceId,
@PathVariable UUID panelId,
@RequestBody Map<String, Object> nadConfigData,
@RequestHeader(value = "clientId", required = false) String clientId) {
UUID configUuid = workspaceService.saveNadConfig(studyUuid, workspaceId, panelId, nadConfigData, clientId);
return ResponseEntity.status(HttpStatus.CREATED).body(configUuid);
}

@DeleteMapping("/{workspaceId}/panels/{panelId}/current-nad-config")
@Operation(summary = "Delete current NAD config")
@ApiResponse(responseCode = "204", description = "Current NAD config deleted")
@ApiResponse(responseCode = "404", description = "Study not found")
public ResponseEntity<Void> deleteNadConfig(
@PathVariable UUID studyUuid,
@PathVariable UUID workspaceId,
@PathVariable UUID panelId) {
workspaceService.deleteNadConfig(studyUuid, workspaceId, panelId);
return ResponseEntity.noContent().build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ public class NotificationService {
public static final String HEADER_ELEMENT_UUID = "elementUuid";
public static final String HEADER_EXPORT_UUID = "exportUuid";
public static final String HEADER_EXPORT_TO_GRID_EXPLORE = "exportToGridExplore";
public static final String HEADER_WORKSPACE_UUID = "workspaceUuid";
public static final String HEADER_PANEL_ID = "panelId";
public static final String HEADER_CLIENT_ID = "clientId";
public static final String NETWORK_EXPORT_FINISHED = "networkExportFinished";

public static final String UPDATE_TYPE_BUILD_CANCELLED = "buildCancelled";
Expand Down Expand Up @@ -97,6 +100,10 @@ public class NotificationService {
public static final String UPDATE_SPREADSHEET_TAB = "spreadsheetTabUpdated";
public static final String UPDATE_SPREADSHEET_COLLECTION = "spreadsheetCollectionUpdated";
public static final String UPDATE_SPREADSHEET_PARAMETERS = "spreadsheetParametersUpdated";
public static final String UPDATE_WORKSPACE_RENAMED = "workspaceRenamed";
public static final String UPDATE_WORKSPACE_PANELS = "workspacePanelsUpdated";
public static final String DELETE_WORKSPACE_PANELS = "workspacePanelsDeleted";
public static final String UPDATE_WORKSPACE_NAD_CONFIG = "workspaceNadConfigUpdated";

public static final String MODIFICATIONS_CREATING_IN_PROGRESS = "creatingInProgress";
public static final String MODIFICATIONS_STASHING_IN_PROGRESS = "stashingInProgress";
Expand Down Expand Up @@ -205,6 +212,46 @@ public void emitSpreadsheetCollectionChanged(UUID studyUuid, UUID collectionUuid
sendStudyUpdateMessage(studyUuid, UPDATE_SPREADSHEET_COLLECTION, MessageBuilder.withPayload(collectionUuid.toString()));
}

@PostCompletion
public void emitWorkspaceUpdated(UUID studyUuid, UUID workspaceId, String clientId) {
MessageBuilder<String> builder = MessageBuilder.withPayload(workspaceId.toString());
if (clientId != null) {
builder.setHeader(HEADER_CLIENT_ID, clientId);
}
sendStudyUpdateMessage(studyUuid, UPDATE_WORKSPACE_RENAMED, builder);
}

@PostCompletion
public void emitWorkspacePanelsUpdated(UUID studyUuid, UUID workspaceId, String panelIds, String clientId) {
MessageBuilder<String> builder = MessageBuilder.withPayload(panelIds)
.setHeader(HEADER_WORKSPACE_UUID, workspaceId.toString());
if (clientId != null) {
builder.setHeader(HEADER_CLIENT_ID, clientId);
}
sendStudyUpdateMessage(studyUuid, UPDATE_WORKSPACE_PANELS, builder);
}

@PostCompletion
public void emitWorkspacePanelsDeleted(UUID studyUuid, UUID workspaceId, String panelIds, String clientId) {
MessageBuilder<String> builder = MessageBuilder.withPayload(panelIds)
.setHeader(HEADER_WORKSPACE_UUID, workspaceId.toString());
if (clientId != null) {
builder.setHeader(HEADER_CLIENT_ID, clientId);
}
sendStudyUpdateMessage(studyUuid, DELETE_WORKSPACE_PANELS, builder);
}

@PostCompletion
public void emitWorkspaceNadConfigUpdated(UUID studyUuid, UUID workspaceId, UUID panelId, UUID workspaceNadConfigUuid, String clientId) {
MessageBuilder<String> builder = MessageBuilder.withPayload(workspaceNadConfigUuid.toString())
.setHeader(HEADER_WORKSPACE_UUID, workspaceId.toString())
.setHeader(HEADER_PANEL_ID, panelId.toString());
if (clientId != null) {
builder.setHeader(HEADER_CLIENT_ID, clientId);
}
sendStudyUpdateMessage(studyUuid, UPDATE_WORKSPACE_NAD_CONFIG, builder);
}

@PostCompletion
public void emitSpreadsheetParametersChange(UUID studyUuid) {
sendStudyUpdateMessage(studyUuid, UPDATE_SPREADSHEET_PARAMETERS, MessageBuilder.withPayload(""));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ public class StudyEntity extends AbstractManuallyAssignedIdentifierEntity<UUID>
@Column(name = "diagramGridLayoutUuid")
private UUID diagramGridLayoutUuid;

@Column(name = "workspacesConfigUuid")
private UUID workspacesConfigUuid;

@OneToOne(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "study_voltage_init_parameters_id",
foreignKey = @ForeignKey(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -300,11 +300,12 @@ private void insertStudy(UUID studyUuid, String userId, NetworkInfos networkInfo
UUID pccMinParametersUuid = createDefaultPccMinParameters();
UUID spreadsheetConfigCollectionUuid = createDefaultSpreadsheetConfigCollection(userId, userProfileInfos);
UUID diagramGridLayoutUuid = studyService.createGridLayoutFromNadDiagram(userId, userProfileInfos);
UUID workspacesConfigUuid = createDefaultWorkspacesConfig();

studyService.insertStudy(studyUuid, userId, networkInfos, caseInfos, loadFlowParametersUuid,
shortCircuitParametersUuid, DynamicSimulationService.toEntity(dynamicSimulationParameters, objectMapper),
voltageInitParametersUuid, securityAnalysisParametersUuid, sensitivityAnalysisParametersUuid,
networkVisualizationParametersUuid, dynamicSecurityAnalysisParametersUuid, stateEstimationParametersUuid, pccMinParametersUuid, spreadsheetConfigCollectionUuid, diagramGridLayoutUuid,
networkVisualizationParametersUuid, dynamicSecurityAnalysisParametersUuid, stateEstimationParametersUuid, pccMinParametersUuid, spreadsheetConfigCollectionUuid, diagramGridLayoutUuid, workspacesConfigUuid,
importParameters, importReportUuid);
}

Expand Down Expand Up @@ -486,6 +487,15 @@ private UUID createDefaultSpreadsheetConfigCollection(String userId, UserProfile
}
}

private UUID createDefaultWorkspacesConfig() {
try {
return studyConfigService.createDefaultWorkspacesConfig();
} catch (final Exception e) {
LOGGER.error("Error while creating default workspace collection", e);
return null;
}
}

@Bean
public Consumer<Message<String>> consumeCaseImportFailed() {
return message -> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,7 @@
*/
package org.gridsuite.study.server.service;

import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.gridsuite.study.server.dto.diagramgridlayout.nad.NadConfigInfos;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import java.util.List;
Expand All @@ -23,23 +19,8 @@
@RequiredArgsConstructor
public class NadConfigService {

private static final Logger LOGGER = LoggerFactory.getLogger(NadConfigService.class);

private final SingleLineDiagramService singleLineDiagramService;

public UUID saveNadConfig(@NonNull NadConfigInfos nadConfigInfos) {
UUID configUuid = nadConfigInfos.getId();

if (configUuid == null) {
nadConfigInfos.setId(UUID.randomUUID());
singleLineDiagramService.createDiagramConfigs(List.of(nadConfigInfos));
} else {
singleLineDiagramService.updateNadConfig(nadConfigInfos);
}

return nadConfigInfos.getId();
}

public void deleteNadConfigs(List<UUID> nadConfigUuids) {
if (nadConfigUuids == null || nadConfigUuids.isEmpty()) {
return;
Expand Down
Loading