-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #49 from commonground-project/feat/add-timeline-co…
…ntroller Add timeline endpoint
- Loading branch information
Showing
12 changed files
with
296 additions
and
0 deletions.
There are no files selected for viewing
55 changes: 55 additions & 0 deletions
55
src/main/java/tw/commonground/backend/service/timeline/TimelineController.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,55 @@ | ||
package tw.commonground.backend.service.timeline; | ||
|
||
import jakarta.validation.Valid; | ||
import org.springframework.http.ResponseEntity; | ||
import org.springframework.web.bind.annotation.*; | ||
import tw.commonground.backend.service.timeline.dto.*; | ||
import tw.commonground.backend.service.timeline.entity.NodeEntity; | ||
|
||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
@RestController | ||
@RequestMapping("/api") | ||
public class TimelineController { | ||
|
||
private final TimelineService timelineService; | ||
|
||
public TimelineController(TimelineService timelineService) { | ||
this.timelineService = timelineService; | ||
} | ||
|
||
@GetMapping("/issue/{id}/timeline") | ||
public ResponseEntity<TimelineResponse> getTimeline(@PathVariable UUID id) { | ||
List<NodeEntity> nodes = timelineService.getNodes(id); | ||
TimelineResponse response = TimelineMapper.toResponse(nodes); | ||
return ResponseEntity.ok(response); | ||
} | ||
|
||
@PostMapping("/issue/{id}/timeline") | ||
public ResponseEntity<NodeResponse> createNode(@PathVariable UUID id, @Valid @RequestBody NodeRequest request) { | ||
NodeEntity node = timelineService.createNode(id, request); | ||
NodeResponse response = NodeMapper.toResponse(node); | ||
return ResponseEntity.ok(response); | ||
} | ||
|
||
@GetMapping("/timeline/node/{nodeId}") | ||
public ResponseEntity<NodeResponse> getNode(@PathVariable UUID nodeId) { | ||
NodeEntity node = timelineService.getNode(nodeId); | ||
NodeResponse response = NodeMapper.toResponse(node); | ||
return ResponseEntity.ok(response); | ||
} | ||
|
||
@PutMapping("/timeline/node/{nodeId}") | ||
public ResponseEntity<NodeResponse> updateNode(@PathVariable UUID nodeId, @Valid @RequestBody NodeRequest request) { | ||
NodeEntity node = timelineService.updateNode(nodeId, request); | ||
NodeResponse response = NodeMapper.toResponse(node); | ||
return ResponseEntity.ok(response); | ||
} | ||
|
||
@DeleteMapping("/timeline/node/{nodeId}") | ||
public ResponseEntity<Void> deleteNode(@PathVariable UUID nodeId) { | ||
timelineService.deleteNode(nodeId); | ||
return ResponseEntity.noContent().build(); | ||
} | ||
} |
82 changes: 82 additions & 0 deletions
82
src/main/java/tw/commonground/backend/service/timeline/TimelineService.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,82 @@ | ||
package tw.commonground.backend.service.timeline; | ||
|
||
import jakarta.persistence.EntityManager; | ||
import jakarta.persistence.PersistenceContext; | ||
import org.springframework.stereotype.Service; | ||
import tw.commonground.backend.exception.EntityNotFoundException; | ||
import tw.commonground.backend.exception.ValidationException; | ||
import tw.commonground.backend.service.issue.IssueService; | ||
import tw.commonground.backend.service.issue.entity.IssueEntity; | ||
import tw.commonground.backend.service.timeline.dto.NodeRequest; | ||
import tw.commonground.backend.service.timeline.entity.NodeEntity; | ||
import tw.commonground.backend.service.timeline.entity.NodeRepository; | ||
|
||
import java.time.LocalDate; | ||
import java.time.format.DateTimeParseException; | ||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
@Service | ||
public class TimelineService { | ||
|
||
private final IssueService issueService; | ||
|
||
private final NodeRepository nodeRepository; | ||
|
||
@PersistenceContext | ||
private EntityManager entityManager; | ||
|
||
public TimelineService(IssueService issueService, NodeRepository nodeRepository) { | ||
this.issueService = issueService; | ||
this.nodeRepository = nodeRepository; | ||
} | ||
|
||
public List<NodeEntity> getNodes(UUID issueId) { | ||
issueService.throwIfIssueNotExist(issueId); | ||
return nodeRepository.findAllByIssueId(issueId); | ||
} | ||
|
||
public NodeEntity getNode(UUID nodeId) { | ||
return nodeRepository.findById(nodeId) | ||
.orElseThrow(() -> new EntityNotFoundException("Node", "id", nodeId.toString())); | ||
} | ||
|
||
public NodeEntity createNode(UUID issueId, NodeRequest request) { | ||
issueService.throwIfIssueNotExist(issueId); | ||
|
||
NodeEntity node = new NodeEntity(); | ||
node.setTitle(request.getTitle()); | ||
node.setDescription(request.getDescription()); | ||
|
||
try { | ||
node.setDate(LocalDate.parse(request.getDate())); | ||
} catch (DateTimeParseException e) { | ||
throw new ValidationException("date", "Invalid date format"); | ||
} | ||
|
||
IssueEntity issue = entityManager.getReference(IssueEntity.class, issueId); | ||
node.setIssue(issue); | ||
|
||
return nodeRepository.save(node); | ||
} | ||
|
||
public NodeEntity updateNode(UUID nodeId, NodeRequest request) { | ||
NodeEntity node = nodeRepository.findById(nodeId) | ||
.orElseThrow(() -> new EntityNotFoundException("Node", "id", nodeId.toString())); | ||
|
||
node.setTitle(request.getTitle()); | ||
node.setDescription(request.getDescription()); | ||
|
||
try { | ||
node.setDate(LocalDate.parse(request.getDate())); | ||
} catch (DateTimeParseException e) { | ||
throw new ValidationException("date", "Invalid date format"); | ||
} | ||
|
||
return nodeRepository.save(node); | ||
} | ||
|
||
public void deleteNode(UUID nodeId) { | ||
nodeRepository.deleteById(nodeId); | ||
} | ||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/tw/commonground/backend/service/timeline/dto/NodeMapper.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,25 @@ | ||
package tw.commonground.backend.service.timeline.dto; | ||
|
||
import tw.commonground.backend.service.timeline.entity.NodeEntity; | ||
|
||
import java.time.format.DateTimeFormatter; | ||
|
||
public final class NodeMapper { | ||
|
||
private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd"); | ||
|
||
private NodeMapper() { | ||
// hide the constructor | ||
} | ||
|
||
public static NodeResponse toResponse(NodeEntity entity) { | ||
return NodeResponse.builder() | ||
.id(entity.getId().toString()) | ||
.createdAt(entity.getCreatedAt()) | ||
.updatedAt(entity.getUpdatedAt()) | ||
.title(entity.getTitle()) | ||
.description(entity.getDescription()) | ||
.date(entity.getDate().format(FORMATTER)) | ||
.build(); | ||
} | ||
} |
22 changes: 22 additions & 0 deletions
22
src/main/java/tw/commonground/backend/service/timeline/dto/NodeRequest.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,22 @@ | ||
package tw.commonground.backend.service.timeline.dto; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.Pattern; | ||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
@Getter | ||
@Setter | ||
@Builder | ||
public class NodeRequest { | ||
|
||
@NotBlank(message = "Title is required") | ||
private String title; | ||
|
||
private String description; | ||
|
||
@NotBlank(message = "Date is required") | ||
@Pattern(regexp = "^\\d{4}-\\d{2}-\\d{2}$", message = "Date must be in the format yyyy-MM-dd") | ||
private String date; | ||
} |
25 changes: 25 additions & 0 deletions
25
src/main/java/tw/commonground/backend/service/timeline/dto/NodeResponse.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,25 @@ | ||
package tw.commonground.backend.service.timeline.dto; | ||
|
||
import lombok.Builder; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
import java.time.LocalDateTime; | ||
|
||
@Getter | ||
@Setter | ||
@Builder | ||
public class NodeResponse { | ||
|
||
private String id; | ||
|
||
private LocalDateTime createdAt; | ||
|
||
private LocalDateTime updatedAt; | ||
|
||
private String title; | ||
|
||
private String description; | ||
|
||
private String date; | ||
} |
19 changes: 19 additions & 0 deletions
19
src/main/java/tw/commonground/backend/service/timeline/dto/TimelineMapper.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,19 @@ | ||
package tw.commonground.backend.service.timeline.dto; | ||
|
||
import tw.commonground.backend.service.timeline.entity.NodeEntity; | ||
|
||
import java.util.List; | ||
import java.util.stream.Collectors; | ||
|
||
public final class TimelineMapper { | ||
private TimelineMapper() { | ||
// hide the constructor | ||
} | ||
|
||
public static TimelineResponse toResponse(List<NodeEntity> nodes) { | ||
List<NodeResponse> content = nodes.stream() | ||
.map(NodeMapper::toResponse) | ||
.collect(Collectors.toList()); | ||
return new TimelineResponse(content); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
src/main/java/tw/commonground/backend/service/timeline/dto/TimelineResponse.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,14 @@ | ||
package tw.commonground.backend.service.timeline.dto; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.Getter; | ||
import lombok.Setter; | ||
|
||
import java.util.List; | ||
|
||
@Getter | ||
@Setter | ||
@AllArgsConstructor | ||
public class TimelineResponse { | ||
private List<NodeResponse> content; | ||
} |
1 change: 1 addition & 0 deletions
1
src/main/java/tw/commonground/backend/service/timeline/dto/package-info.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 @@ | ||
package tw.commonground.backend.service.timeline.dto; |
41 changes: 41 additions & 0 deletions
41
src/main/java/tw/commonground/backend/service/timeline/entity/NodeEntity.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,41 @@ | ||
package tw.commonground.backend.service.timeline.entity; | ||
|
||
import jakarta.persistence.*; | ||
import lombok.*; | ||
import org.springframework.data.annotation.CreatedDate; | ||
import org.springframework.data.annotation.LastModifiedDate; | ||
import org.springframework.data.jpa.domain.support.AuditingEntityListener; | ||
import tw.commonground.backend.service.issue.entity.IssueEntity; | ||
|
||
import java.time.LocalDate; | ||
import java.time.LocalDateTime; | ||
import java.util.UUID; | ||
|
||
@Getter | ||
@Setter | ||
@Entity | ||
@Builder | ||
@NoArgsConstructor | ||
@AllArgsConstructor | ||
@EntityListeners(AuditingEntityListener.class) | ||
public class NodeEntity { | ||
@Id | ||
@GeneratedValue | ||
private UUID id; | ||
|
||
@CreatedDate | ||
private LocalDateTime createdAt; | ||
|
||
@LastModifiedDate | ||
private LocalDateTime updatedAt; | ||
|
||
private String title; | ||
|
||
private String description; | ||
|
||
private LocalDate date; | ||
|
||
@ManyToOne | ||
private IssueEntity issue; | ||
|
||
} |
10 changes: 10 additions & 0 deletions
10
src/main/java/tw/commonground/backend/service/timeline/entity/NodeRepository.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,10 @@ | ||
package tw.commonground.backend.service.timeline.entity; | ||
|
||
import org.springframework.data.jpa.repository.JpaRepository; | ||
|
||
import java.util.List; | ||
import java.util.UUID; | ||
|
||
public interface NodeRepository extends JpaRepository<NodeEntity, UUID> { | ||
List<NodeEntity> findAllByIssueId(UUID issueId); | ||
} |
1 change: 1 addition & 0 deletions
1
src/main/java/tw/commonground/backend/service/timeline/entity/package-info.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 @@ | ||
package tw.commonground.backend.service.timeline.entity; |
1 change: 1 addition & 0 deletions
1
src/main/java/tw/commonground/backend/service/timeline/package-info.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 @@ | ||
package tw.commonground.backend.service.timeline; |