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
7 changes: 0 additions & 7 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -232,13 +232,6 @@
<artifactId>spring-boot-starter-logging</artifactId>
</dependency>

<!-- https://mvnrepository.com/artifact/jakarta.mail/jakarta.mail-api -->
<dependency>
<groupId>jakarta.mail</groupId>
<artifactId>jakarta.mail-api</artifactId>
<version>2.1.3</version>
</dependency>

<!-- Tablesaw for DataFrame operations -->
<dependency>
<groupId>tech.tablesaw</groupId>
Expand Down
118 changes: 118 additions & 0 deletions src/main/java/com/open/spring/mvc/comment/CommentApiController.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package com.open.spring.mvc.comment;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
Expand All @@ -11,12 +15,27 @@
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.CrossOrigin;

import com.open.spring.mvc.slack.CalendarIssueService;
import com.open.spring.mvc.slack.EmailNotificationService;

@RestController
@RequestMapping("/api/Comment")
@CrossOrigin(origins = { "http://127.0.0.1:4500", "https://pages.opencodingsociety.com" }, allowCredentials = "true")
public class CommentApiController {

@Autowired
private final CommentJPA CommentJPA;

@Autowired
private CalendarIssueService calendarIssueService;

@Autowired
private EmailNotificationService emailNotificationService;

// Constructor injection for CommentJPA
public CommentApiController(CommentJPA CommentJPA) {
this.CommentJPA = CommentJPA;
Expand Down Expand Up @@ -86,4 +105,103 @@ public ResponseEntity<List<Comment>> getCommentsByAuthor(@RequestParam String au

return new ResponseEntity<>(comments, HttpStatus.OK); // Return 200 with the list of comments
}

@GetMapping("/issue/{issueId}")
public ResponseEntity<List<Comment>> getCommentsByIssue(@PathVariable Long issueId,
@AuthenticationPrincipal UserDetails userDetails) {
if (userDetails == null) {
return new ResponseEntity<>(HttpStatus.UNAUTHORIZED);
}

List<Comment> comments = CommentJPA.findByAssignmentOrderByTimestampDesc(issueAssignmentKey(issueId));
return new ResponseEntity<>(comments, HttpStatus.OK);
}

@PostMapping("/issue/{issueId}")
public ResponseEntity<?> createIssueComment(@PathVariable Long issueId,
@RequestBody Map<String, Object> payload,
@AuthenticationPrincipal UserDetails userDetails) {
if (userDetails == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(Map.of("message", "Authentication required"));
}

String text = payload.get("text") == null ? "" : String.valueOf(payload.get("text")).trim();
if (text.isEmpty()) {
return ResponseEntity.badRequest().body(Map.of("message", "Comment text is required"));
}

return calendarIssueService.getIssueById(issueId, userDetails.getUsername(), hasPrivilegedRole(userDetails))
.<ResponseEntity<?>>map(issue -> {
String authorUid = userDetails.getUsername();
Comment savedComment = CommentJPA.save(new Comment(issueAssignmentKey(issueId), text, authorUid));
emailNotificationService.notifyOnIssueComment(issue, savedComment);
emailNotificationService.notifyAllStarredIssueFollowers(issue, savedComment);

Map<String, Object> response = new HashMap<>();
response.put("comment", savedComment);
response.put("commentCount", CommentJPA.countByAssignment(issueAssignmentKey(issueId)));
return ResponseEntity.status(HttpStatus.CREATED).body(response);
})
.orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(Map.of("message", "Issue not found")));
}

@PostMapping("/issue/{issueId}/star")
public ResponseEntity<?> toggleIssueStar(@PathVariable Long issueId,
@AuthenticationPrincipal UserDetails userDetails) {
if (userDetails == null) {
return ResponseEntity.status(HttpStatus.UNAUTHORIZED)
.body(Map.of("message", "Authentication required"));
}

return calendarIssueService.getIssueById(issueId, userDetails.getUsername(), hasPrivilegedRole(userDetails))
.<ResponseEntity<?>>map(issue -> {
String starKey = issueStarAssignmentKey(issueId);
String authorUid = userDetails.getUsername();
boolean starred = false;

// Find existing star comments for this assignment with text "star"
List<Comment> existingStars = CommentJPA.findByAssignmentAndText(starKey, "star");
Comment toRemove = null;
if (existingStars != null) {
for (Comment c : existingStars) {
if (authorUid.equals(c.getAuthor())) {
toRemove = c;
break;
}
}
}

if (toRemove != null) {
CommentJPA.delete(toRemove);
starred = false;
} else {
CommentJPA.save(new Comment(starKey, "star", authorUid));
starred = true;
}

Map<String, Object> response = new HashMap<>();
response.put("starred", starred);
response.put("starCount", CommentJPA.countByAssignment(starKey));
response.put("issueId", issueId);
return ResponseEntity.ok(response);
})
.orElseGet(() -> ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(Map.of("message", "Issue not found")));
}

private String issueAssignmentKey(Long issueId) {
return "issue-" + issueId;
}

private String issueStarAssignmentKey(Long issueId) {
return issueAssignmentKey(issueId) + "::star";
}

private boolean hasPrivilegedRole(UserDetails userDetails) {
return userDetails.getAuthorities().stream()
.map(authority -> authority.getAuthority())
.anyMatch(role -> "ROLE_ADMIN".equals(role) || "ROLE_TEACHER".equals(role));
}
}
10 changes: 10 additions & 0 deletions src/main/java/com/open/spring/mvc/comment/CommentJPA.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,15 @@ public interface CommentJPA extends JpaRepository<Comment, Long> {

List<Comment> findByAssignment(String assignment);

List<Comment> findByAssignmentOrderByTimestampDesc(String assignment);

List<Comment> findAllByOrderByTimestampDesc();

long countByAssignment(String assignment);

boolean existsByAssignmentAndAuthor(String assignment, String author);

void deleteByAssignmentAndAuthor(String assignment, String author);

List<Comment> findByAssignmentAndText(String assignment, String text);
}
Loading