-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Added chart annotation endpoints (#4604)
Co-authored-by: jryu01 <[email protected]>
- Loading branch information
Showing
5 changed files
with
295 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
171 changes: 171 additions & 0 deletions
171
...ftware/uncharted/terarium/hmiserver/controller/dataservice/ChartAnnotationController.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
package software.uncharted.terarium.hmiserver.controller.dataservice; | ||
|
||
import io.swagger.v3.oas.annotations.Operation; | ||
import io.swagger.v3.oas.annotations.media.Content; | ||
import io.swagger.v3.oas.annotations.responses.ApiResponse; | ||
import io.swagger.v3.oas.annotations.responses.ApiResponses; | ||
import jakarta.transaction.Transactional; | ||
import java.io.IOException; | ||
import java.util.List; | ||
import java.util.UUID; | ||
import lombok.RequiredArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
import org.springframework.http.HttpStatus; | ||
import org.springframework.http.MediaType; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.security.access.annotation.Secured; | ||
import org.springframework.web.bind.annotation.DeleteMapping; | ||
import org.springframework.web.bind.annotation.PathVariable; | ||
import org.springframework.web.bind.annotation.PostMapping; | ||
import org.springframework.web.bind.annotation.RequestBody; | ||
import org.springframework.web.bind.annotation.RequestMapping; | ||
import org.springframework.web.bind.annotation.RequestParam; | ||
import org.springframework.web.bind.annotation.RestController; | ||
import org.springframework.web.server.ResponseStatusException; | ||
import software.uncharted.terarium.hmiserver.models.dataservice.ChartAnnotation; | ||
import software.uncharted.terarium.hmiserver.models.dataservice.ResponseDeleted; | ||
import software.uncharted.terarium.hmiserver.security.Roles; | ||
import software.uncharted.terarium.hmiserver.service.CurrentUserService; | ||
import software.uncharted.terarium.hmiserver.service.data.ChartAnnotationService; | ||
import software.uncharted.terarium.hmiserver.service.data.ProjectAssetService; | ||
import software.uncharted.terarium.hmiserver.service.data.ProjectService; | ||
import software.uncharted.terarium.hmiserver.utils.rebac.Schema; | ||
|
||
@RequestMapping("/chart-annotations") | ||
@RestController | ||
@Slf4j | ||
@RequiredArgsConstructor | ||
@Transactional | ||
public class ChartAnnotationController { | ||
|
||
final ChartAnnotationService chartAnnotationService; | ||
|
||
final ProjectAssetService projectAssetService; | ||
|
||
final ProjectService projectService; | ||
|
||
final CurrentUserService currentUserService; | ||
|
||
private static class SearchRequestBody { | ||
|
||
public UUID nodeId; | ||
} | ||
|
||
@PostMapping("/search") | ||
@Secured(Roles.USER) | ||
@Operation(summary = "Gets a list of chart annotations by provided node ID") | ||
@ApiResponses( | ||
value = { | ||
@ApiResponse( | ||
responseCode = "200", | ||
description = "chart annotations found.", | ||
content = @Content( | ||
mediaType = MediaType.APPLICATION_JSON_VALUE, | ||
schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = ChartAnnotation.class) | ||
) | ||
), | ||
@ApiResponse(responseCode = "204", description = "There was no chart annotation found", content = @Content), | ||
@ApiResponse( | ||
responseCode = "500", | ||
description = "There was an issue retrieving the chart annotations from the data store", | ||
content = @Content | ||
) | ||
} | ||
) | ||
public ResponseEntity<List<ChartAnnotation>> getChartAnnotationsByNodeId( | ||
@RequestParam(name = "project-id", required = false) final UUID projectId, | ||
@RequestBody final SearchRequestBody body | ||
) { | ||
final Schema.Permission permission = projectService.checkPermissionCanRead( | ||
currentUserService.get().getId(), | ||
projectId | ||
); | ||
|
||
final List<ChartAnnotation> chartAnnotations = chartAnnotationService.getAnnotationsByNodeId( | ||
body.nodeId, | ||
permission | ||
); | ||
|
||
return ResponseEntity.ok(chartAnnotations); | ||
} | ||
|
||
@PostMapping | ||
@Secured(Roles.USER) | ||
@Operation(summary = "Create a new annotation") | ||
@ApiResponses( | ||
value = { | ||
@ApiResponse( | ||
responseCode = "201", | ||
description = "Annotation created.", | ||
content = @Content( | ||
mediaType = MediaType.APPLICATION_JSON_VALUE, | ||
schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = ChartAnnotation.class) | ||
) | ||
), | ||
@ApiResponse( | ||
responseCode = "500", | ||
description = "There was an issue creating the chart annotation", | ||
content = @Content | ||
) | ||
} | ||
) | ||
public ResponseEntity<ChartAnnotation> createChartAnnotation( | ||
@RequestBody final ChartAnnotation item, | ||
@RequestParam(name = "project-id", required = false) final UUID projectId | ||
) { | ||
final Schema.Permission permission = projectService.checkPermissionCanWrite( | ||
currentUserService.get().getId(), | ||
projectId | ||
); | ||
try { | ||
return ResponseEntity.status(HttpStatus.CREATED).body( | ||
chartAnnotationService.createAsset(item, projectId, permission) | ||
); | ||
} catch (final IOException e) { | ||
final String error = "Unable to create chart annotation"; | ||
log.error(error, e); | ||
throw new ResponseStatusException(org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR, error); | ||
} | ||
} | ||
|
||
@DeleteMapping("/{id}") | ||
@Secured(Roles.USER) | ||
@Operation(summary = "Delete a chart annotation by ID") | ||
@ApiResponses( | ||
value = { | ||
@ApiResponse( | ||
responseCode = "200", | ||
description = "Delete chart annotation", | ||
content = { | ||
@Content( | ||
mediaType = "application/json", | ||
schema = @io.swagger.v3.oas.annotations.media.Schema(implementation = ResponseDeleted.class) | ||
) | ||
} | ||
), | ||
@ApiResponse( | ||
responseCode = "500", | ||
description = "There was an issue deleting the chart annotation", | ||
content = @Content | ||
) | ||
} | ||
) | ||
public ResponseEntity<ResponseDeleted> deleteChartAnnotation( | ||
@PathVariable("id") final UUID id, | ||
@RequestParam(name = "project-id", required = false) final UUID projectId | ||
) { | ||
final Schema.Permission permission = projectService.checkPermissionCanWrite( | ||
currentUserService.get().getId(), | ||
projectId | ||
); | ||
|
||
try { | ||
chartAnnotationService.deleteAsset(id, projectId, permission); | ||
return ResponseEntity.ok(new ResponseDeleted("ChartAnnotation", id)); | ||
} catch (final Exception e) { | ||
final String error = String.format("Failed to delete chart annotation %s", id); | ||
log.error(error, e); | ||
throw new ResponseStatusException(org.springframework.http.HttpStatus.INTERNAL_SERVER_ERROR, error); | ||
} | ||
} | ||
} |
57 changes: 57 additions & 0 deletions
57
...c/main/java/software/uncharted/terarium/hmiserver/models/dataservice/ChartAnnotation.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
package software.uncharted.terarium.hmiserver.models.dataservice; | ||
|
||
import com.fasterxml.jackson.annotation.JsonAlias; | ||
import com.fasterxml.jackson.databind.JsonNode; | ||
import io.hypersistence.utils.hibernate.type.json.JsonType; | ||
import jakarta.persistence.Column; | ||
import jakarta.persistence.Entity; | ||
import jakarta.persistence.EnumType; | ||
import jakarta.persistence.Enumerated; | ||
import java.util.UUID; | ||
import lombok.Data; | ||
import lombok.EqualsAndHashCode; | ||
import lombok.experimental.Accessors; | ||
import org.hibernate.annotations.Type; | ||
import software.uncharted.terarium.hmiserver.annotations.TSModel; | ||
import software.uncharted.terarium.hmiserver.models.TerariumAsset; | ||
|
||
@Data | ||
@Accessors(chain = true) | ||
@EqualsAndHashCode(callSuper = true) | ||
@TSModel | ||
@Entity | ||
public class ChartAnnotation extends TerariumAsset { | ||
|
||
// TODO: Add chart type enums once we have the full list of the charts we support | ||
|
||
// @TSModel | ||
// public enum ChartType { | ||
// @JsonAlias("variable") | ||
// VARIABLE, | ||
// @JsonAlias("parameter") | ||
// PARAMETER, | ||
// @JsonAlias("loss") | ||
// LOSS, | ||
// @JsonAlias("error") | ||
// ERROR | ||
// } | ||
|
||
private UUID nodeId; | ||
private UUID outputId; | ||
|
||
private UUID chartId; | ||
|
||
// TODO: add chart type to specify which type of chart this annotation is applied to | ||
// @Enumerated(EnumType.STRING) | ||
// private ChartType chartType; | ||
|
||
@Type(JsonType.class) | ||
@Column(columnDefinition = "json") | ||
private JsonNode layerSpec; | ||
|
||
private boolean llmGenerated; | ||
|
||
@Type(JsonType.class) | ||
@Column(columnDefinition = "json") | ||
private JsonNode metadata; | ||
} |
12 changes: 12 additions & 0 deletions
12
...java/software/uncharted/terarium/hmiserver/repository/data/ChartAnnotationRepository.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package software.uncharted.terarium.hmiserver.repository.data; | ||
|
||
import java.util.List; | ||
import java.util.UUID; | ||
import org.springframework.stereotype.Repository; | ||
import software.uncharted.terarium.hmiserver.models.dataservice.ChartAnnotation; | ||
import software.uncharted.terarium.hmiserver.repository.PSCrudSoftDeleteRepository; | ||
|
||
@Repository | ||
public interface ChartAnnotationRepository extends PSCrudSoftDeleteRepository<ChartAnnotation, UUID> { | ||
List<ChartAnnotation> findByNodeIdAndDeletedOnIsNull(UUID nodeId); | ||
} |
46 changes: 46 additions & 0 deletions
46
.../main/java/software/uncharted/terarium/hmiserver/service/data/ChartAnnotationService.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package software.uncharted.terarium.hmiserver.service.data; | ||
|
||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import io.micrometer.observation.annotation.Observed; | ||
import java.util.List; | ||
import java.util.UUID; | ||
import org.springframework.stereotype.Service; | ||
import software.uncharted.terarium.hmiserver.configuration.Config; | ||
import software.uncharted.terarium.hmiserver.models.dataservice.ChartAnnotation; | ||
import software.uncharted.terarium.hmiserver.repository.data.ChartAnnotationRepository; | ||
import software.uncharted.terarium.hmiserver.service.s3.S3ClientService; | ||
import software.uncharted.terarium.hmiserver.utils.rebac.Schema; | ||
|
||
@Service | ||
public class ChartAnnotationService | ||
extends TerariumAssetServiceWithoutSearch<ChartAnnotation, ChartAnnotationRepository> { | ||
|
||
public ChartAnnotationService( | ||
final ObjectMapper objectMapper, | ||
final Config config, | ||
final ProjectService projectService, | ||
final ProjectAssetService projectAssetService, | ||
final ChartAnnotationRepository repository, | ||
final S3ClientService s3ClientService | ||
) { | ||
super( | ||
objectMapper, | ||
config, | ||
projectService, | ||
projectAssetService, | ||
repository, | ||
s3ClientService, | ||
ChartAnnotation.class | ||
); | ||
} | ||
|
||
public List<ChartAnnotation> getAnnotationsByNodeId(UUID nodeId, final Schema.Permission hasReadPermission) { | ||
return repository.findByNodeIdAndDeletedOnIsNull(nodeId); | ||
} | ||
|
||
@Override | ||
@Observed(name = "function_profile") | ||
protected String getAssetPath() { | ||
throw new UnsupportedOperationException("Chart annotations are not stored in S3"); | ||
} | ||
} |