From 27719e7f08756613e65e13ea61b0488fafee34c8 Mon Sep 17 00:00:00 2001 From: Zaine Arch Date: Sat, 3 Jan 2026 12:42:51 +0000 Subject: [PATCH 1/5] working on competency api --- .../controller/CompetenciesController.java | 40 ++++++++++++ .../org/zaine/app/model/Competencies.java | 64 +++++++++++++++++++ .../repositories/CompetenciesRepository.java | 9 +++ .../app/service/CompetenciesService.java | 38 +++++++++++ .../app/service/CompetenciesServiceTest.java | 51 +++++++++++++++ 5 files changed, 202 insertions(+) create mode 100644 src/main/java/org/zaine/app/controller/CompetenciesController.java create mode 100644 src/main/java/org/zaine/app/model/Competencies.java create mode 100644 src/main/java/org/zaine/app/repositories/CompetenciesRepository.java create mode 100644 src/main/java/org/zaine/app/service/CompetenciesService.java create mode 100644 src/test/java/org/zaine/app/service/CompetenciesServiceTest.java diff --git a/src/main/java/org/zaine/app/controller/CompetenciesController.java b/src/main/java/org/zaine/app/controller/CompetenciesController.java new file mode 100644 index 0000000..6d5e549 --- /dev/null +++ b/src/main/java/org/zaine/app/controller/CompetenciesController.java @@ -0,0 +1,40 @@ +package org.zaine.app.controller; + +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.PathVariable; +import org.zaine.app.model.Competencies; +import org.zaine.app.service.CompetenciesService; + +@RestController +public class CompetenciesController { + + @Autowired + private CompetenciesService competenciesService; + + @GetMapping("/competencies/items") + public List getAllCompetencies() { + + return competenciesService.getAllCompetencies(); + } + + @GetMapping("/competencies/item/{id}") + public Competencies getCompetencyById(@PathVariable Long id) { + return competenciesService.getCompetencyById(id); + } + + + @PostMapping("/competencies/items/{id}/state") + public void updateCompetencyState(@RequestParam Long id, @RequestParam String newState) { + Long compId = id; + String state = newState; + + //competenciesService.updateCompetencyState(id, newState); + + } + +} diff --git a/src/main/java/org/zaine/app/model/Competencies.java b/src/main/java/org/zaine/app/model/Competencies.java new file mode 100644 index 0000000..f1240af --- /dev/null +++ b/src/main/java/org/zaine/app/model/Competencies.java @@ -0,0 +1,64 @@ +package org.zaine.app.model; + +import java.time.Instant; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.Id; +import jakarta.persistence.Table; +import jakarta.persistence.GeneratedValue; + +@Entity +@Table(name = "competencies") +public class Competencies { + + @Id + @GeneratedValue + @Column(name="id") + private Long id; + + @Column(name="title") + private String title; + + @Column(name="state") + private String state; + + @Column(name="created_at") + private Instant createdAt; + + @Column(name="group") + private String group; + + + public Long getId() { + return id; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public Instant getCreatedAt() { + return createdAt; + } + + public String getGroup() { + return group; + } + + public void setGroup(String group) { + this.group = group; + } + +} diff --git a/src/main/java/org/zaine/app/repositories/CompetenciesRepository.java b/src/main/java/org/zaine/app/repositories/CompetenciesRepository.java new file mode 100644 index 0000000..0d90ade --- /dev/null +++ b/src/main/java/org/zaine/app/repositories/CompetenciesRepository.java @@ -0,0 +1,9 @@ +package org.zaine.app.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.zaine.app.model.Competencies; + + +public interface CompetenciesRepository extends JpaRepository { + +} diff --git a/src/main/java/org/zaine/app/service/CompetenciesService.java b/src/main/java/org/zaine/app/service/CompetenciesService.java new file mode 100644 index 0000000..fd4f740 --- /dev/null +++ b/src/main/java/org/zaine/app/service/CompetenciesService.java @@ -0,0 +1,38 @@ +package org.zaine.app.service; + +import java.lang.System.Logger; +import java.util.List; +import java.util.Optional; + +import org.springframework.stereotype.Service; +import org.zaine.app.model.Competencies; +import org.zaine.app.repositories.CompetenciesRepository; + +@Service +public class CompetenciesService { + + private static final Logger logger = System.getLogger(CompetenciesService.class.getName()); + + private final CompetenciesRepository competenciesRepository; + + public CompetenciesService(CompetenciesRepository competenciesRepository) { + this.competenciesRepository = competenciesRepository; + } + + public List getAllCompetencies() { + return competenciesRepository.findAll(); + + } + + public Competencies getCompetencyById(Long id) { + // Log the method entry + + logger.log(System.Logger.Level.INFO, "Entering getCompetencyById with id: " + id); + + return competenciesRepository.findById(id).get(); + } + + + public void updateCompetencyState(Long id, String newState) { + } +} diff --git a/src/test/java/org/zaine/app/service/CompetenciesServiceTest.java b/src/test/java/org/zaine/app/service/CompetenciesServiceTest.java new file mode 100644 index 0000000..effb504 --- /dev/null +++ b/src/test/java/org/zaine/app/service/CompetenciesServiceTest.java @@ -0,0 +1,51 @@ +package org.zaine.app.service; + +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.zaine.app.repositories.CompetenciesRepository; + +import jakarta.validation.constraints.NotNull; + +import org.zaine.app.model.Competencies; +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; +import java.util.Arrays; +import java.util.Optional; + +@ExtendWith(org.mockito.junit.jupiter.MockitoExtension.class) +public class CompetenciesServiceTest { + + @InjectMocks + private CompetenciesService competenciesService; + + @Mock + private CompetenciesRepository competenciesRepository; + + @Test + public void testGetAllCompetencies() { + Competencies comp1 = new Competencies(); + comp1.setTitle("Competency 1"); + Competencies comp2 = new Competencies(); + comp2.setTitle("Competency 2"); + when(competenciesRepository.findAll()).thenReturn(Arrays.asList(comp1, comp2)); + + java.util.List result = competenciesService.getAllCompetencies(); + assertEquals(2, result.size()); + assertSame(comp1, result.get(0)); + assertSame(comp2, result.get(1)); + } + + @Test + public void testGetCompetencyByIdReturnsCompetency() { + Competencies comp = new Competencies(); + @NotNull Long id = comp.getId(); + when(competenciesRepository.findById(id)).thenReturn(Optional.of(comp)); + + + Competencies result = competenciesService.getCompetencyById(id); + assertSame(comp, result); + + } +} -- 2.49.1 From 2fc5ad92d257106e22746f9d3c69db458dc9738f Mon Sep 17 00:00:00 2001 From: Zaine Arch Date: Sat, 3 Jan 2026 16:03:27 +0000 Subject: [PATCH 2/5] added an update competency functionality --- .gitignore | 3 ++- .../app/controller/CompetenciesController.java | 12 +++++++----- .../java/org/zaine/app/model/Competencies.java | 2 +- .../repositories/CompetenciesRepository.java | 2 +- .../zaine/app/service/CompetenciesService.java | 18 +++++++++++++++++- 5 files changed, 28 insertions(+), 9 deletions(-) diff --git a/.gitignore b/.gitignore index c82eeba..9657bf9 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,5 @@ target/ application.properties .settings/ .project -.classpath \ No newline at end of file +.classpath +.vscode/ \ No newline at end of file diff --git a/src/main/java/org/zaine/app/controller/CompetenciesController.java b/src/main/java/org/zaine/app/controller/CompetenciesController.java index 6d5e549..332fa77 100644 --- a/src/main/java/org/zaine/app/controller/CompetenciesController.java +++ b/src/main/java/org/zaine/app/controller/CompetenciesController.java @@ -10,9 +10,12 @@ import org.springframework.web.bind.annotation.PathVariable; import org.zaine.app.model.Competencies; import org.zaine.app.service.CompetenciesService; +import java.lang.System.Logger; + @RestController public class CompetenciesController { + private static final Logger logger = System.getLogger(CompetenciesController.class.getName()); @Autowired private CompetenciesService competenciesService; @@ -29,11 +32,10 @@ public class CompetenciesController { @PostMapping("/competencies/items/{id}/state") - public void updateCompetencyState(@RequestParam Long id, @RequestParam String newState) { - Long compId = id; - String state = newState; - - //competenciesService.updateCompetencyState(id, newState); + public void updateCompetencyState(@PathVariable Long id, @RequestParam String newState) { + logger.log(System.Logger.Level.INFO, "Received request to update competency id " + id + " to new state: " + newState); + + competenciesService.updateCompetencyState(id, newState); } diff --git a/src/main/java/org/zaine/app/model/Competencies.java b/src/main/java/org/zaine/app/model/Competencies.java index f1240af..9fd263a 100644 --- a/src/main/java/org/zaine/app/model/Competencies.java +++ b/src/main/java/org/zaine/app/model/Competencies.java @@ -25,7 +25,7 @@ public class Competencies { @Column(name="created_at") private Instant createdAt; - @Column(name="group") + @Column(name="group_name") private String group; diff --git a/src/main/java/org/zaine/app/repositories/CompetenciesRepository.java b/src/main/java/org/zaine/app/repositories/CompetenciesRepository.java index 0d90ade..e983772 100644 --- a/src/main/java/org/zaine/app/repositories/CompetenciesRepository.java +++ b/src/main/java/org/zaine/app/repositories/CompetenciesRepository.java @@ -5,5 +5,5 @@ import org.zaine.app.model.Competencies; public interface CompetenciesRepository extends JpaRepository { - + } diff --git a/src/main/java/org/zaine/app/service/CompetenciesService.java b/src/main/java/org/zaine/app/service/CompetenciesService.java index fd4f740..6b24247 100644 --- a/src/main/java/org/zaine/app/service/CompetenciesService.java +++ b/src/main/java/org/zaine/app/service/CompetenciesService.java @@ -15,6 +15,14 @@ public class CompetenciesService { private final CompetenciesRepository competenciesRepository; + private static final List ALLOWED_STATES = List.of( + "completed", + "manager_review", + "in_progress", + "not_started", + "comments" + ); + public CompetenciesService(CompetenciesRepository competenciesRepository) { this.competenciesRepository = competenciesRepository; } @@ -25,7 +33,6 @@ public class CompetenciesService { } public Competencies getCompetencyById(Long id) { - // Log the method entry logger.log(System.Logger.Level.INFO, "Entering getCompetencyById with id: " + id); @@ -34,5 +41,14 @@ public class CompetenciesService { public void updateCompetencyState(Long id, String newState) { + Competencies competency = getCompetencyById(id); + if (competency != null) { + competency.setState(newState); + competenciesRepository.save(competency); + logger.log(System.Logger.Level.INFO, "Updated competency id " + id + " to new state: " + newState); + } else { + logger.log(System.Logger.Level.WARNING, "Competency with id " + id + " not found."); + } + } } -- 2.49.1 From 95286ae6dd2c8ff03a4c48b40a3691e04bb51af7 Mon Sep 17 00:00:00 2001 From: Zaine Arch Date: Sat, 3 Jan 2026 20:04:21 +0000 Subject: [PATCH 3/5] fixed a few issues with the competencies, started working on notes. still wip --- .../app/controller/CommentsController.java | 34 +++++++++ .../controller/CompetenciesController.java | 20 +++--- .../java/org/zaine/app/model/Comments.java | 72 +++++++++++++++++++ .../app/repositories/CommentsRepository.java | 8 +++ .../zaine/app/service/CommentsService.java | 36 ++++++++++ .../app/service/CompetenciesService.java | 20 +++--- 6 files changed, 170 insertions(+), 20 deletions(-) create mode 100644 src/main/java/org/zaine/app/controller/CommentsController.java create mode 100644 src/main/java/org/zaine/app/model/Comments.java create mode 100644 src/main/java/org/zaine/app/repositories/CommentsRepository.java create mode 100644 src/main/java/org/zaine/app/service/CommentsService.java diff --git a/src/main/java/org/zaine/app/controller/CommentsController.java b/src/main/java/org/zaine/app/controller/CommentsController.java new file mode 100644 index 0000000..6be9780 --- /dev/null +++ b/src/main/java/org/zaine/app/controller/CommentsController.java @@ -0,0 +1,34 @@ +package org.zaine.app.controller; + +import java.lang.System.Logger; +import java.util.List; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; +import org.zaine.app.model.Comments; +import org.zaine.app.service.CommentsService; + +@RestController +public class CommentsController { + private static final Logger logger = System.getLogger(CommentsController.class.getName()); + @Autowired + private CommentsService commentsService; + + @GetMapping("/{page_slug}") + public List getAllCommentsBySlug(@PathVariable String page_slug) { + + List allComments = commentsService; + + + } + + @GetMapping("/comments/item/{id}") + public Comments getCommentById(@PathVariable Long id) { + return commentsService.getCommentById(id); + } + +} diff --git a/src/main/java/org/zaine/app/controller/CompetenciesController.java b/src/main/java/org/zaine/app/controller/CompetenciesController.java index 332fa77..a513e32 100644 --- a/src/main/java/org/zaine/app/controller/CompetenciesController.java +++ b/src/main/java/org/zaine/app/controller/CompetenciesController.java @@ -1,17 +1,17 @@ package org.zaine.app.controller; +import java.lang.System.Logger; import java.util.List; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; -import org.springframework.web.bind.annotation.PathVariable; import org.zaine.app.model.Competencies; import org.zaine.app.service.CompetenciesService; -import java.lang.System.Logger; - @RestController public class CompetenciesController { @@ -20,15 +20,15 @@ public class CompetenciesController { private CompetenciesService competenciesService; @GetMapping("/competencies/items") - public List getAllCompetencies() { + public List getAllCompetencies() { - return competenciesService.getAllCompetencies(); + return competenciesService.getAllCompetencies(); } - @GetMapping("/competencies/item/{id}") - public Competencies getCompetencyById(@PathVariable Long id) { - return competenciesService.getCompetencyById(id); - } + @GetMapping("/competencies/item/{id}") + public Competencies getCompetencyById(@PathVariable Long id) { + return competenciesService.getCompetencyById(id); + } @PostMapping("/competencies/items/{id}/state") @@ -36,7 +36,7 @@ public class CompetenciesController { logger.log(System.Logger.Level.INFO, "Received request to update competency id " + id + " to new state: " + newState); competenciesService.updateCompetencyState(id, newState); - + } } diff --git a/src/main/java/org/zaine/app/model/Comments.java b/src/main/java/org/zaine/app/model/Comments.java new file mode 100644 index 0000000..ee9b506 --- /dev/null +++ b/src/main/java/org/zaine/app/model/Comments.java @@ -0,0 +1,72 @@ +package org.zaine.app.model; + +import java.time.Instant; +import jakarta.persistence.Column; +import jakarta.persistence.Entity; +import jakarta.persistence.GeneratedValue; +import jakarta.persistence.Id; +import jakarta.persistence.Table; + +@Entity +@Table(name = "comments") +public class Comments { + + @Id + @GeneratedValue + @Column(name = "id") + private Long id; + + @Column(name = "page_slug") + private String pageSlug; + + @Column(name="author") + private String author; + + @Column(name="content") + private String content; + + @Column(name="created_at") + private Instant createdAt; + + @Column(name="parent_id") + private Long parentId; + + + public Long getId() { + return id; + } + public void setId(Long id) { + this.id = id; + } + public String getPageSlug() { + return pageSlug; + } + public void setPageSlug(String pageSlug) { + this.pageSlug = pageSlug; + } + public String getAuthor() { + return author; + } + public void setAuthor(String author) { + this.author = author; + } + public String getContent() { + return content; + } + public void setContent(String content) { + this.content = content; + } + public Instant getCreatedAt() { + return createdAt; + } + public void setCreatedAt(Instant createdAt) { + this.createdAt = createdAt; + } + public Long getParentId() { + return parentId; + } + public void setParentId(Long parentId) { + this.parentId = parentId; + } + +} diff --git a/src/main/java/org/zaine/app/repositories/CommentsRepository.java b/src/main/java/org/zaine/app/repositories/CommentsRepository.java new file mode 100644 index 0000000..313c98b --- /dev/null +++ b/src/main/java/org/zaine/app/repositories/CommentsRepository.java @@ -0,0 +1,8 @@ +package org.zaine.app.repositories; + +import org.springframework.data.jpa.repository.JpaRepository; +import org.zaine.app.model.Comments; + +public interface CommentsRepository extends JpaRepository { + +} diff --git a/src/main/java/org/zaine/app/service/CommentsService.java b/src/main/java/org/zaine/app/service/CommentsService.java new file mode 100644 index 0000000..682ac6e --- /dev/null +++ b/src/main/java/org/zaine/app/service/CommentsService.java @@ -0,0 +1,36 @@ +package org.zaine.app.service; + +import java.lang.System.Logger; +import java.util.List; +import org.springframework.stereotype.Service; +import org.zaine.app.model.Comments; +import org.zaine.app.repositories.CommentsRepository; +import java.util.stream.*; + +@Service +public class CommentsService { + private static final Logger logger = System.getLogger(CommentsService.class.getName()); + + private final CommentsRepository commentsRepository; + + public CommentsService(CommentsRepository commentsRepository) { + this.commentsRepository = commentsRepository; + } + + public List getAllComments() { + return commentsRepository.findAll(); + } + + public List getAllCommentsBySlug(String page_slug) { + logger.log(System.Logger.Level.INFO, "Entering getAllCommentsBySlug with slug: " + page_slug); + return commentsRepository.findAll().stream() + .filter(comment -> page_slug.equals(comment.getPageSlug())) + .toList(); + } + + public Comments getCommentById(Long id) { + logger.log(System.Logger.Level.INFO, "Entering getCommentById with id: " + id); + return commentsRepository.findById(id).get(); + } + +} diff --git a/src/main/java/org/zaine/app/service/CompetenciesService.java b/src/main/java/org/zaine/app/service/CompetenciesService.java index 6b24247..5582075 100644 --- a/src/main/java/org/zaine/app/service/CompetenciesService.java +++ b/src/main/java/org/zaine/app/service/CompetenciesService.java @@ -2,8 +2,6 @@ package org.zaine.app.service; import java.lang.System.Logger; import java.util.List; -import java.util.Optional; - import org.springframework.stereotype.Service; import org.zaine.app.model.Competencies; import org.zaine.app.repositories.CompetenciesRepository; @@ -15,14 +13,10 @@ public class CompetenciesService { private final CompetenciesRepository competenciesRepository; - private static final List ALLOWED_STATES = List.of( - "completed", - "manager_review", - "in_progress", - "not_started", - "comments" - ); - + private static final List ALLOWED_STATES = + List.of("completed", "manager_review", "in_progress", "not_started", "comments"); + + public CompetenciesService(CompetenciesRepository competenciesRepository) { this.competenciesRepository = competenciesRepository; } @@ -42,6 +36,12 @@ public class CompetenciesService { public void updateCompetencyState(Long id, String newState) { Competencies competency = getCompetencyById(id); + + if (!ALLOWED_STATES.contains(newState)) { + logger.log(System.Logger.Level.WARNING, "Invalid state: " + newState); + throw new IllegalArgumentException("Invalid state: " + newState); + } + if (competency != null) { competency.setState(newState); competenciesRepository.save(competency); -- 2.49.1 From 1358b8981cfdfe9513ce511ae41c9a523b64b979 Mon Sep 17 00:00:00 2001 From: Zaine Arch Date: Sat, 3 Jan 2026 22:13:13 +0000 Subject: [PATCH 4/5] 3 endpoints complete for comments -> get all comments, get by id, get by slug --- .../app/controller/CommentsController.java | 22 ++++++----- .../zaine/app/service/CommentsService.java | 38 ++++++++++--------- 2 files changed, 33 insertions(+), 27 deletions(-) diff --git a/src/main/java/org/zaine/app/controller/CommentsController.java b/src/main/java/org/zaine/app/controller/CommentsController.java index 6be9780..9c6bfd6 100644 --- a/src/main/java/org/zaine/app/controller/CommentsController.java +++ b/src/main/java/org/zaine/app/controller/CommentsController.java @@ -18,17 +18,21 @@ public class CommentsController { @Autowired private CommentsService commentsService; - @GetMapping("/{page_slug}") - public List getAllCommentsBySlug(@PathVariable String page_slug) { - - List allComments = commentsService; - - + @GetMapping("/{page_slug}") + public List getAllCommentsBySlug(@PathVariable String page_slug) { + List allComments = commentsService.getAllCommentsBySlug(page_slug); + return allComments; + } - @GetMapping("/comments/item/{id}") - public Comments getCommentById(@PathVariable Long id) { + @GetMapping("/comments/item/{id}") + public Comments getCommentById(@PathVariable Long id) { return commentsService.getCommentById(id); - } + } + + @GetMapping("/comments/items") + public List getAllComments() { + return commentsService.getAllComments(); + } } diff --git a/src/main/java/org/zaine/app/service/CommentsService.java b/src/main/java/org/zaine/app/service/CommentsService.java index 682ac6e..62e7a6c 100644 --- a/src/main/java/org/zaine/app/service/CommentsService.java +++ b/src/main/java/org/zaine/app/service/CommentsService.java @@ -11,26 +11,28 @@ import java.util.stream.*; public class CommentsService { private static final Logger logger = System.getLogger(CommentsService.class.getName()); - private final CommentsRepository commentsRepository; - - public CommentsService(CommentsRepository commentsRepository) { - this.commentsRepository = commentsRepository; - } - - public List getAllComments() { - return commentsRepository.findAll(); - } - + private final CommentsRepository commentsRepository; + + public CommentsService(CommentsRepository commentsRepository) { + this.commentsRepository = commentsRepository; + } + + public List getAllComments() { + return commentsRepository.findAll(); + } + public List getAllCommentsBySlug(String page_slug) { logger.log(System.Logger.Level.INFO, "Entering getAllCommentsBySlug with slug: " + page_slug); - return commentsRepository.findAll().stream() + List allComments = commentsRepository.findAll(); + List filteredComments = allComments.stream() .filter(comment -> page_slug.equals(comment.getPageSlug())) - .toList(); - } - - public Comments getCommentById(Long id) { - logger.log(System.Logger.Level.INFO, "Entering getCommentById with id: " + id); - return commentsRepository.findById(id).get(); - } + .collect(Collectors.toList()); + return filteredComments; + } + + public Comments getCommentById(Long id) { + logger.log(System.Logger.Level.INFO, "Entering getCommentById with id: " + id); + return commentsRepository.findById(id).get(); + } } -- 2.49.1 From ee681ad1f380433e19bd729f6f9c36d0f4f68fe8 Mon Sep 17 00:00:00 2001 From: Zaine Arch Date: Sat, 3 Jan 2026 23:45:08 +0000 Subject: [PATCH 5/5] Completed the api through the use of DTO's --- .gitignore | 3 +- Dockerfile | 21 ++++++++ .../app/controller/CommentsController.java | 41 +++++++++++++-- .../controller/CompetenciesController.java | 29 +++++++---- .../app/controller/HealthController.java | 2 +- .../zaine/app/controller/NotesController.java | 15 +++++- .../org/zaine/app/dto/CompetenciesDTO.java | 18 +++++++ .../org/zaine/app/dto/CreateCommentDTO.java | 50 +++++++++++++++++++ .../java/org/zaine/app/dto/CreateNoteDTO.java | 29 +++++++++++ .../java/org/zaine/app/model/Comments.java | 20 +++++--- .../org/zaine/app/model/Competencies.java | 7 +-- src/main/java/org/zaine/app/model/Notes.java | 13 ++++- .../app/repositories/CommentsRepository.java | 23 ++++++++- .../repositories/CompetenciesRepository.java | 2 +- .../zaine/app/service/CommentsService.java | 20 +++++++- .../app/service/CompetenciesService.java | 28 +++++------ .../app/service/CompetenciesServiceTest.java | 2 +- 17 files changed, 272 insertions(+), 51 deletions(-) create mode 100644 Dockerfile create mode 100644 src/main/java/org/zaine/app/dto/CompetenciesDTO.java create mode 100644 src/main/java/org/zaine/app/dto/CreateCommentDTO.java create mode 100644 src/main/java/org/zaine/app/dto/CreateNoteDTO.java diff --git a/.gitignore b/.gitignore index 9657bf9..abbafae 100644 --- a/.gitignore +++ b/.gitignore @@ -4,4 +4,5 @@ application.properties .settings/ .project .classpath -.vscode/ \ No newline at end of file +.vscode/ +.env \ No newline at end of file diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..1efbdd7 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +# -------- Build stage -------- +FROM maven:3.9.6-eclipse-temurin-21 AS build + +WORKDIR /app + +COPY pom.xml . +RUN mvn -B dependency:go-offline + +COPY src ./src +RUN mvn -B clean package -DskipTests + +# -------- Runtime stage -------- +FROM eclipse-temurin:21-jre + +WORKDIR /app + +COPY --from=build /app/target/*.jar app.jar + +EXPOSE 9010 + +ENTRYPOINT ["java", "-jar", "app.jar"] diff --git a/src/main/java/org/zaine/app/controller/CommentsController.java b/src/main/java/org/zaine/app/controller/CommentsController.java index 9c6bfd6..83e6b7f 100644 --- a/src/main/java/org/zaine/app/controller/CommentsController.java +++ b/src/main/java/org/zaine/app/controller/CommentsController.java @@ -7,12 +7,15 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import org.zaine.app.dto.CreateCommentDTO; import org.zaine.app.model.Comments; import org.zaine.app.service.CommentsService; @RestController +@RequestMapping("/api/comments") public class CommentsController { private static final Logger logger = System.getLogger(CommentsController.class.getName()); @Autowired @@ -25,14 +28,44 @@ public class CommentsController { } - @GetMapping("/comments/item/{id}") - public Comments getCommentById(@PathVariable Long id) { + @GetMapping("/item/{id}") + public Comments getCommentById(@PathVariable Integer id) { return commentsService.getCommentById(id); } - @GetMapping("/comments/items") + @GetMapping("") public List getAllComments() { return commentsService.getAllComments(); } + + @PostMapping( + value = "", + consumes = "application/json" + ) + public void addComment(@RequestBody CreateCommentDTO dto) { + + if (dto.getContent() == null || dto.getContent().trim().isEmpty()) { + logger.log(System.Logger.Level.WARNING, + "Attempted to add empty comment. Operation aborted."); + return; + } + + Comments newComment = new Comments(); + newComment.setPageSlug(dto.getPageSlug()); + newComment.setAuthor(dto.getAuthor()); + newComment.setContent(dto.getContent()); + newComment.setParentId(dto.getParentId()); + newComment.setCreatedAt(java.time.Instant.now()); + + logger.log(System.Logger.Level.INFO, + "Adding comment to pageSlug: " + dto.getPageSlug()); + + commentsService.addComment(newComment); + } + + @GetMapping("/thread/{comment_id}") + public List getCommentThread(@PathVariable Integer comment_id) { + return commentsService.getCommentThread(comment_id); + } } diff --git a/src/main/java/org/zaine/app/controller/CompetenciesController.java b/src/main/java/org/zaine/app/controller/CompetenciesController.java index a513e32..6af277a 100644 --- a/src/main/java/org/zaine/app/controller/CompetenciesController.java +++ b/src/main/java/org/zaine/app/controller/CompetenciesController.java @@ -2,41 +2,48 @@ package org.zaine.app.controller; import java.lang.System.Logger; import java.util.List; +import java.util.Map; +import org.zaine.app.dto.CompetenciesDTO; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PostMapping; -import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; import org.zaine.app.model.Competencies; import org.zaine.app.service.CompetenciesService; + @RestController +@RequestMapping("/api/competencies") public class CompetenciesController { private static final Logger logger = System.getLogger(CompetenciesController.class.getName()); @Autowired private CompetenciesService competenciesService; - @GetMapping("/competencies/items") + @GetMapping("/items") public List getAllCompetencies() { return competenciesService.getAllCompetencies(); } - @GetMapping("/competencies/item/{id}") - public Competencies getCompetencyById(@PathVariable Long id) { + @GetMapping("/item/{id}") + public Competencies getCompetencyById(@PathVariable Integer id) { return competenciesService.getCompetencyById(id); } - - @PostMapping("/competencies/items/{id}/state") - public void updateCompetencyState(@PathVariable Long id, @RequestParam String newState) { - logger.log(System.Logger.Level.INFO, "Received request to update competency id " + id + " to new state: " + newState); - - competenciesService.updateCompetencyState(id, newState); - + @PostMapping( + value = "/items/{id}/state", + consumes = "application/json" + ) + public void updateCompetencyState( + @PathVariable Integer id, + @RequestBody CompetenciesDTO request + ) { + competenciesService.updateCompetencyState(id, request.getState()); } } diff --git a/src/main/java/org/zaine/app/controller/HealthController.java b/src/main/java/org/zaine/app/controller/HealthController.java index 02f9bb4..cc34ba8 100644 --- a/src/main/java/org/zaine/app/controller/HealthController.java +++ b/src/main/java/org/zaine/app/controller/HealthController.java @@ -1,4 +1,4 @@ -package org.zaine.app; +package org.zaine.app.controller; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; diff --git a/src/main/java/org/zaine/app/controller/NotesController.java b/src/main/java/org/zaine/app/controller/NotesController.java index ca8a862..d75e2e8 100644 --- a/src/main/java/org/zaine/app/controller/NotesController.java +++ b/src/main/java/org/zaine/app/controller/NotesController.java @@ -7,11 +7,13 @@ 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.RestController; +import org.zaine.app.dto.CreateNoteDTO; import org.zaine.app.model.Notes; import org.zaine.app.service.NotesService; import java.util.List; @RestController +@RequestMapping("/api") public class NotesController { @Autowired private NotesService notesService; @@ -22,10 +24,19 @@ public class NotesController { return notesService.getAllNotes(); } - @PostMapping("/notes") - public Notes createNote(@RequestBody Notes note) { + @PostMapping( + value = "/notes", + consumes = "application/json" + ) + public Notes createNote(@RequestBody CreateNoteDTO dto) { + + Notes note = new Notes(); + note.setAuthorName(dto.getAuthorName()); + note.setContent(dto.getContent()); + return notesService.createNote(note); } + diff --git a/src/main/java/org/zaine/app/dto/CompetenciesDTO.java b/src/main/java/org/zaine/app/dto/CompetenciesDTO.java new file mode 100644 index 0000000..3b68ebf --- /dev/null +++ b/src/main/java/org/zaine/app/dto/CompetenciesDTO.java @@ -0,0 +1,18 @@ +package org.zaine.app.dto; + +public class CompetenciesDTO { + + private String state; + + public CompetenciesDTO() { + // REQUIRED: default constructor + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } +} diff --git a/src/main/java/org/zaine/app/dto/CreateCommentDTO.java b/src/main/java/org/zaine/app/dto/CreateCommentDTO.java new file mode 100644 index 0000000..8766e95 --- /dev/null +++ b/src/main/java/org/zaine/app/dto/CreateCommentDTO.java @@ -0,0 +1,50 @@ +package org.zaine.app.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CreateCommentDTO { + + @JsonProperty("page_slug") + private String pageSlug; + + private String author; + + private String content; + + @JsonProperty("parent_id") + private Integer parentId; + + public CreateCommentDTO() {} + + public String getPageSlug() { + return pageSlug; + } + + public void setPageSlug(String pageSlug) { + this.pageSlug = pageSlug; + } + + public String getAuthor() { + return author; + } + + public void setAuthor(String author) { + this.author = author; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + + public Integer getParentId() { + return parentId; + } + + public void setParentId(Integer parentId) { + this.parentId = parentId; + } +} diff --git a/src/main/java/org/zaine/app/dto/CreateNoteDTO.java b/src/main/java/org/zaine/app/dto/CreateNoteDTO.java new file mode 100644 index 0000000..8e4896c --- /dev/null +++ b/src/main/java/org/zaine/app/dto/CreateNoteDTO.java @@ -0,0 +1,29 @@ +package org.zaine.app.dto; + +import com.fasterxml.jackson.annotation.JsonProperty; + +public class CreateNoteDTO { + + @JsonProperty("author_name") + private String authorName; + + private String content; + + public CreateNoteDTO() {} + + public String getAuthorName() { + return authorName; + } + + public void setAuthorName(String authorName) { + this.authorName = authorName; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } +} diff --git a/src/main/java/org/zaine/app/model/Comments.java b/src/main/java/org/zaine/app/model/Comments.java index ee9b506..920327f 100644 --- a/src/main/java/org/zaine/app/model/Comments.java +++ b/src/main/java/org/zaine/app/model/Comments.java @@ -1,9 +1,13 @@ package org.zaine.app.model; import java.time.Instant; + +import com.fasterxml.jackson.annotation.JsonProperty; + import jakarta.persistence.Column; import jakarta.persistence.Entity; import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; import jakarta.persistence.Id; import jakarta.persistence.Table; @@ -12,9 +16,9 @@ import jakarta.persistence.Table; public class Comments { @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name = "id") - private Long id; + private Integer id; @Column(name = "page_slug") private String pageSlug; @@ -25,17 +29,19 @@ public class Comments { @Column(name="content") private String content; + @JsonProperty("created_at") @Column(name="created_at") private Instant createdAt; + @JsonProperty("parent_id") @Column(name="parent_id") - private Long parentId; + private Integer parentId; - public Long getId() { + public Integer getId() { return id; } - public void setId(Long id) { + public void setId(Integer id) { this.id = id; } public String getPageSlug() { @@ -62,10 +68,10 @@ public class Comments { public void setCreatedAt(Instant createdAt) { this.createdAt = createdAt; } - public Long getParentId() { + public Integer getParentId() { return parentId; } - public void setParentId(Long parentId) { + public void setParentId(Integer parentId) { this.parentId = parentId; } diff --git a/src/main/java/org/zaine/app/model/Competencies.java b/src/main/java/org/zaine/app/model/Competencies.java index 9fd263a..72c59a2 100644 --- a/src/main/java/org/zaine/app/model/Competencies.java +++ b/src/main/java/org/zaine/app/model/Competencies.java @@ -6,15 +6,16 @@ import jakarta.persistence.Entity; import jakarta.persistence.Id; import jakarta.persistence.Table; import jakarta.persistence.GeneratedValue; +import jakarta.persistence.GenerationType; @Entity @Table(name = "competencies") public class Competencies { @Id - @GeneratedValue + @GeneratedValue(strategy = GenerationType.IDENTITY) @Column(name="id") - private Long id; + private Integer id; @Column(name="title") private String title; @@ -29,7 +30,7 @@ public class Competencies { private String group; - public Long getId() { + public Integer getId() { return id; } diff --git a/src/main/java/org/zaine/app/model/Notes.java b/src/main/java/org/zaine/app/model/Notes.java index 4c978b2..c72e277 100644 --- a/src/main/java/org/zaine/app/model/Notes.java +++ b/src/main/java/org/zaine/app/model/Notes.java @@ -9,6 +9,8 @@ import jakarta.persistence.GeneratedValue; import java.time.Instant; import java.util.UUID; +import com.fasterxml.jackson.annotation.JsonProperty; + @Entity @Table(name = "public_notes") public class Notes { @@ -21,11 +23,14 @@ public class Notes { @Column(name="content") private String content; + @JsonProperty("author_name") @Column(name="author_name") - private String authorName; + private String authorName; + @JsonProperty("created_at") @Column(name="created_at") - private Instant createdAt; + private Instant createdAt; + public UUID getId() { return id; @@ -51,5 +56,9 @@ public class Notes { return createdAt; } + public void setCreatedAt(Instant createdAt) { + this.createdAt = createdAt; + } + } diff --git a/src/main/java/org/zaine/app/repositories/CommentsRepository.java b/src/main/java/org/zaine/app/repositories/CommentsRepository.java index 313c98b..8984b27 100644 --- a/src/main/java/org/zaine/app/repositories/CommentsRepository.java +++ b/src/main/java/org/zaine/app/repositories/CommentsRepository.java @@ -1,8 +1,29 @@ package org.zaine.app.repositories; +import java.util.List; + import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.query.Param; import org.zaine.app.model.Comments; -public interface CommentsRepository extends JpaRepository { +public interface CommentsRepository extends JpaRepository { + @Query(value = """ + WITH RECURSIVE comment_tree AS ( + SELECT id, parent_id, author, content, created_at, page_slug + FROM comments + WHERE id = :commentId + AND is_deleted = false + UNION ALL + + SELECT c.id, c.parent_id, c.author, c.content, c.created_at, c.page_slug + FROM comments c + JOIN comment_tree ct ON c.parent_id = ct.id + WHERE c.is_deleted = false + ) + SELECT * FROM comment_tree + ORDER BY created_at ASC + """, nativeQuery = true) + List findCommentThread(@Param("commentId") Integer commentId); } diff --git a/src/main/java/org/zaine/app/repositories/CompetenciesRepository.java b/src/main/java/org/zaine/app/repositories/CompetenciesRepository.java index e983772..66afcd7 100644 --- a/src/main/java/org/zaine/app/repositories/CompetenciesRepository.java +++ b/src/main/java/org/zaine/app/repositories/CompetenciesRepository.java @@ -4,6 +4,6 @@ import org.springframework.data.jpa.repository.JpaRepository; import org.zaine.app.model.Competencies; -public interface CompetenciesRepository extends JpaRepository { +public interface CompetenciesRepository extends JpaRepository { } diff --git a/src/main/java/org/zaine/app/service/CommentsService.java b/src/main/java/org/zaine/app/service/CommentsService.java index 62e7a6c..9b7c022 100644 --- a/src/main/java/org/zaine/app/service/CommentsService.java +++ b/src/main/java/org/zaine/app/service/CommentsService.java @@ -30,9 +30,25 @@ public class CommentsService { return filteredComments; } - public Comments getCommentById(Long id) { + public Comments getCommentById(Integer id) { logger.log(System.Logger.Level.INFO, "Entering getCommentById with id: " + id); return commentsRepository.findById(id).get(); } -} + public void addComment(Comments comment) { + if (comment == null) { + logger.log(System.Logger.Level.WARNING, "Comment is null. Operation aborted."); + return; + } else { + logger.log(System.Logger.Level.INFO, "Adding comment with id: " + comment.getId()); + commentsRepository.save(comment); + logger.log(System.Logger.Level.INFO, "Added new comment with id: " + comment.getId()); + + } + } + + public List getCommentThread(Integer comment_id) { + logger.log(System.Logger.Level.INFO, "Entering getCommentThread with id: " + comment_id); + return commentsRepository.findCommentThread(comment_id); + } +} diff --git a/src/main/java/org/zaine/app/service/CompetenciesService.java b/src/main/java/org/zaine/app/service/CompetenciesService.java index 5582075..5e9ade9 100644 --- a/src/main/java/org/zaine/app/service/CompetenciesService.java +++ b/src/main/java/org/zaine/app/service/CompetenciesService.java @@ -26,7 +26,7 @@ public class CompetenciesService { } - public Competencies getCompetencyById(Long id) { + public Competencies getCompetencyById(Integer id) { logger.log(System.Logger.Level.INFO, "Entering getCompetencyById with id: " + id); @@ -34,21 +34,19 @@ public class CompetenciesService { } - public void updateCompetencyState(Long id, String newState) { - Competencies competency = getCompetencyById(id); - - if (!ALLOWED_STATES.contains(newState)) { - logger.log(System.Logger.Level.WARNING, "Invalid state: " + newState); - throw new IllegalArgumentException("Invalid state: " + newState); - } + public void updateCompetencyState(Integer id, String newState) { - if (competency != null) { - competency.setState(newState); + if (newState == null) { + throw new IllegalArgumentException("State must not be null"); + } + + if (!ALLOWED_STATES.contains(newState)) { + throw new IllegalArgumentException("Invalid state: " + newState); + } + + Competencies competency = getCompetencyById(id); + competency.setState(newState); competenciesRepository.save(competency); - logger.log(System.Logger.Level.INFO, "Updated competency id " + id + " to new state: " + newState); - } else { - logger.log(System.Logger.Level.WARNING, "Competency with id " + id + " not found."); - } - } + } diff --git a/src/test/java/org/zaine/app/service/CompetenciesServiceTest.java b/src/test/java/org/zaine/app/service/CompetenciesServiceTest.java index effb504..0ca2a31 100644 --- a/src/test/java/org/zaine/app/service/CompetenciesServiceTest.java +++ b/src/test/java/org/zaine/app/service/CompetenciesServiceTest.java @@ -40,7 +40,7 @@ public class CompetenciesServiceTest { @Test public void testGetCompetencyByIdReturnsCompetency() { Competencies comp = new Competencies(); - @NotNull Long id = comp.getId(); + @NotNull Integer id = comp.getId(); when(competenciesRepository.findById(id)).thenReturn(Optional.of(comp)); -- 2.49.1