From 4659620072b0dbfa8e939288a392fa8ac6c26807 Mon Sep 17 00:00:00 2001 From: litoral05 Date: Wed, 27 May 2026 14:37:46 +0100 Subject: [PATCH] adds chart workspace --- .../backend/charts/ChartWorkspace.java | 97 +++++++++++++++++++ .../charts/ChartWorkspaceController.java | 38 ++++++++ .../charts/ChartWorkspaceRepository.java | 13 +++ .../backend/charts/ChartWorkspaceScope.java | 11 +++ .../backend/charts/ChartWorkspaceService.java | 78 +++++++++++++++ .../charts/dto/ChartWorkspaceRequest.java | 7 ++ .../charts/dto/ChartWorkspaceResponse.java | 15 +++ .../resources/config/sensor-definitions.json | 2 +- .../migration/V5__create_chart_workspace.sql | 12 +++ 9 files changed, 272 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/litoralregas/backend/charts/ChartWorkspace.java create mode 100644 src/main/java/com/litoralregas/backend/charts/ChartWorkspaceController.java create mode 100644 src/main/java/com/litoralregas/backend/charts/ChartWorkspaceRepository.java create mode 100644 src/main/java/com/litoralregas/backend/charts/ChartWorkspaceScope.java create mode 100644 src/main/java/com/litoralregas/backend/charts/ChartWorkspaceService.java create mode 100644 src/main/java/com/litoralregas/backend/charts/dto/ChartWorkspaceRequest.java create mode 100644 src/main/java/com/litoralregas/backend/charts/dto/ChartWorkspaceResponse.java create mode 100644 src/main/resources/db/migration/V5__create_chart_workspace.sql diff --git a/src/main/java/com/litoralregas/backend/charts/ChartWorkspace.java b/src/main/java/com/litoralregas/backend/charts/ChartWorkspace.java new file mode 100644 index 0000000..1b62e80 --- /dev/null +++ b/src/main/java/com/litoralregas/backend/charts/ChartWorkspace.java @@ -0,0 +1,97 @@ +package com.litoralregas.backend.charts; + +import jakarta.persistence.*; + +import java.time.Instant; + +@Entity +@Table(name = "chart_workspace") +public class ChartWorkspace { + + @Id + @GeneratedValue(strategy = GenerationType.IDENTITY) + private Integer id; + + @Enumerated(EnumType.STRING) + @Column(nullable = false, unique = true) + private ChartWorkspaceScope scope; + + @Column(name = "layout_mode", nullable = false) + private String layoutMode; + + @Column(name = "charts_json", nullable = false, columnDefinition = "TEXT") + private String chartsJson; + + @Column(name = "created_at", nullable = false, updatable = false) + private Instant createdAt; + + @Column(name = "updated_at", nullable = false) + private Instant updatedAt; + + protected ChartWorkspace() { + } + + public ChartWorkspace( + ChartWorkspaceScope scope, + String layoutMode, + String chartsJson + ) { + this.scope = scope; + this.layoutMode = layoutMode; + this.chartsJson = chartsJson; + } + + @PrePersist + public void onCreate() { + Instant now = Instant.now(); + + if (createdAt == null) { + createdAt = now; + } + + if (updatedAt == null) { + updatedAt = now; + } + } + + @PreUpdate + public void onUpdate() { + updatedAt = Instant.now(); + } + + public Integer getId() { + return id; + } + + public ChartWorkspaceScope getScope() { + return scope; + } + + public void setScope(ChartWorkspaceScope scope) { + this.scope = scope; + } + + public String getLayoutMode() { + return layoutMode; + } + + public void setLayoutMode(String layoutMode) { + this.layoutMode = layoutMode; + } + + public String getChartsJson() { + return chartsJson; + } + + public void setChartsJson(String chartsJson) { + this.chartsJson = chartsJson; + } + + public Instant getCreatedAt() { + return createdAt; + } + + public Instant getUpdatedAt() { + return updatedAt; + } +} \ No newline at end of file diff --git a/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceController.java b/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceController.java new file mode 100644 index 0000000..ea247eb --- /dev/null +++ b/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceController.java @@ -0,0 +1,38 @@ +package com.litoralregas.backend.charts; + +import com.litoralregas.backend.charts.dto.ChartWorkspaceRequest; +import com.litoralregas.backend.charts.dto.ChartWorkspaceResponse; +import org.springframework.web.bind.annotation.*; + +@RestController +@RequestMapping("/api/chart-workspaces") +public class ChartWorkspaceController { + + private final ChartWorkspaceService service; + + public ChartWorkspaceController( + ChartWorkspaceService service + ) { + this.service = service; + } + + @GetMapping("/{scope}") + public ChartWorkspaceResponse getWorkspace( + @PathVariable ChartWorkspaceScope scope + ) { + + return service.getWorkspace(scope); + } + + @PutMapping("/{scope}") + public ChartWorkspaceResponse saveWorkspace( + @PathVariable ChartWorkspaceScope scope, + @RequestBody ChartWorkspaceRequest request + ) { + + return service.saveWorkspace( + scope, + request + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceRepository.java b/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceRepository.java new file mode 100644 index 0000000..1ea458b --- /dev/null +++ b/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceRepository.java @@ -0,0 +1,13 @@ +package com.litoralregas.backend.charts; + +import org.springframework.data.jpa.repository.JpaRepository; + +import java.util.Optional; + +public interface ChartWorkspaceRepository + extends JpaRepository { + + Optional findByScope( + ChartWorkspaceScope scope + ); +} \ No newline at end of file diff --git a/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceScope.java b/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceScope.java new file mode 100644 index 0000000..a81a8e2 --- /dev/null +++ b/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceScope.java @@ -0,0 +1,11 @@ +package com.litoralregas.backend.charts; + +public enum ChartWorkspaceScope { + GLOBAL, + CLIMATE, + IRRIGATION, + METEO, + LIGHTING, + HYDRO, + AEROPONICS +} \ No newline at end of file diff --git a/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceService.java b/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceService.java new file mode 100644 index 0000000..6eafae8 --- /dev/null +++ b/src/main/java/com/litoralregas/backend/charts/ChartWorkspaceService.java @@ -0,0 +1,78 @@ +package com.litoralregas.backend.charts; + +import com.litoralregas.backend.charts.dto.ChartWorkspaceRequest; +import com.litoralregas.backend.charts.dto.ChartWorkspaceResponse; +import jakarta.transaction.Transactional; +import org.springframework.stereotype.Service; + +@Service +public class ChartWorkspaceService { + + private final ChartWorkspaceRepository repository; + + public ChartWorkspaceService( + ChartWorkspaceRepository repository + ) { + this.repository = repository; + } + + @Transactional + public ChartWorkspaceResponse saveWorkspace( + ChartWorkspaceScope scope, + ChartWorkspaceRequest request + ) { + + ChartWorkspace workspace = + repository.findByScope(scope) + .orElseGet(() -> + new ChartWorkspace( + scope, + request.layoutMode(), + request.chartsJson() + ) + ); + + workspace.setLayoutMode( + request.layoutMode() + ); + + workspace.setChartsJson( + request.chartsJson() + ); + + ChartWorkspace saved = + repository.save(workspace); + + return toResponse(saved); + } + + public ChartWorkspaceResponse getWorkspace( + ChartWorkspaceScope scope + ) { + + ChartWorkspace workspace = + repository.findByScope(scope) + .orElseThrow(() -> + new IllegalArgumentException( + "Workspace not found for scope: " + + scope + ) + ); + + return toResponse(workspace); + } + + private ChartWorkspaceResponse toResponse( + ChartWorkspace workspace + ) { + + return new ChartWorkspaceResponse( + workspace.getId(), + workspace.getScope(), + workspace.getLayoutMode(), + workspace.getChartsJson(), + workspace.getCreatedAt(), + workspace.getUpdatedAt() + ); + } +} \ No newline at end of file diff --git a/src/main/java/com/litoralregas/backend/charts/dto/ChartWorkspaceRequest.java b/src/main/java/com/litoralregas/backend/charts/dto/ChartWorkspaceRequest.java new file mode 100644 index 0000000..8ef7fb8 --- /dev/null +++ b/src/main/java/com/litoralregas/backend/charts/dto/ChartWorkspaceRequest.java @@ -0,0 +1,7 @@ +package com.litoralregas.backend.charts.dto; + +public record ChartWorkspaceRequest( + String layoutMode, + String chartsJson +) { +} \ No newline at end of file diff --git a/src/main/java/com/litoralregas/backend/charts/dto/ChartWorkspaceResponse.java b/src/main/java/com/litoralregas/backend/charts/dto/ChartWorkspaceResponse.java new file mode 100644 index 0000000..c52d64b --- /dev/null +++ b/src/main/java/com/litoralregas/backend/charts/dto/ChartWorkspaceResponse.java @@ -0,0 +1,15 @@ +package com.litoralregas.backend.charts.dto; + +import com.litoralregas.backend.charts.ChartWorkspaceScope; + +import java.time.Instant; + +public record ChartWorkspaceResponse( + Integer id, + ChartWorkspaceScope scope, + String layoutMode, + String chartsJson, + Instant createdAt, + Instant updatedAt +) { +} \ No newline at end of file diff --git a/src/main/resources/config/sensor-definitions.json b/src/main/resources/config/sensor-definitions.json index b38a0db..994a33b 100644 --- a/src/main/resources/config/sensor-definitions.json +++ b/src/main/resources/config/sensor-definitions.json @@ -32340,7 +32340,7 @@ "signed": false, "validMin": null, "validMax": null - } + }, ], "schema": "sensor-definitions.v2.decoding-metadata" } \ No newline at end of file diff --git a/src/main/resources/db/migration/V5__create_chart_workspace.sql b/src/main/resources/db/migration/V5__create_chart_workspace.sql new file mode 100644 index 0000000..e710aa5 --- /dev/null +++ b/src/main/resources/db/migration/V5__create_chart_workspace.sql @@ -0,0 +1,12 @@ +CREATE TABLE chart_workspace ( + id INTEGER PRIMARY KEY AUTOINCREMENT, + + scope VARCHAR(50) NOT NULL UNIQUE, + + layout_mode VARCHAR(50) NOT NULL, + + charts_json TEXT NOT NULL, + + created_at TIMESTAMP NOT NULL, + updated_at TIMESTAMP NOT NULL +); \ No newline at end of file