Skip to content

Commit

Permalink
Merge pull request #623 from bounswe/develop
Browse files Browse the repository at this point in the history
  • Loading branch information
mmtftr authored Dec 6, 2024
2 parents 61fdbbf + 06bf7b1 commit c08a16e
Show file tree
Hide file tree
Showing 39 changed files with 2,675 additions and 236 deletions.
3 changes: 3 additions & 0 deletions .github/workflows/frontend_test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,3 +42,6 @@ jobs:

- name: Run tests
run: yarn test

- name: Run type-check
run: yarn tsc
26 changes: 26 additions & 0 deletions backend/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,32 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- JaCoCo Plugin for Coverage -->
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<version>0.8.10</version>
<executions>
<execution>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>report</id>
<phase>verify</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Surefire Plugin for Test Execution -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>3.1.2</version>
</plugin>
</plugins>
</build>

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,13 @@ protected void configure() {
skip(destination.getFollowing());
}
});
modelMapper.addMappings(new PropertyMap<User, SelfProfileResponseDto>() {
@Override
protected void configure() {
skip(destination.getQuestions());
skip(destination.getAnswers());
}
});
modelMapper.addMappings(new PropertyMap <UserProfileResponseDto,User>() {
@Override
protected void configure() {
Expand All @@ -39,12 +46,19 @@ protected void configure() {

}
});
modelMapper.addMappings(new PropertyMap<Question, GetQuestionWithTagDto>() {
@Override
protected void configure() {
map(source.getQuestionBody(), destination.getContent());
}
});
modelMapper.addMappings(new PropertyMap< GetQuestionWithTagDto,Question>() {
@Override
protected void configure() {
skip(destination.getTags());
skip(destination.getVotes());
skip(destination.getAskedBy());
map(source.getContent(), destination.getQuestionBody());
}
});
modelMapper.addMappings(new PropertyMap<ProgrammingLanguagesTag, GetProgrammingLanguageTagResponseDto>() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,12 @@

import com.group1.programminglanguagesforum.Constants.EndpointConstants;
import com.group1.programminglanguagesforum.DTOs.Requests.UserProfileUpdateRequestDto;
import com.group1.programminglanguagesforum.DTOs.Responses.ErrorResponse;
import com.group1.programminglanguagesforum.DTOs.Responses.GenericApiResponse;
import com.group1.programminglanguagesforum.DTOs.Responses.SelfProfileResponseDto;
import com.group1.programminglanguagesforum.DTOs.Responses.UserProfileResponseDto;
import com.group1.programminglanguagesforum.DTOs.Responses.UserSummaryDto;
import com.group1.programminglanguagesforum.DTOs.Responses.*;
import com.group1.programminglanguagesforum.Entities.User;
import com.group1.programminglanguagesforum.Exceptions.UnauthorizedAccessException;
import com.group1.programminglanguagesforum.Exceptions.UserNotFoundException;
import com.group1.programminglanguagesforum.Services.AnswerService;
import com.group1.programminglanguagesforum.Services.QuestionService;
import com.group1.programminglanguagesforum.Services.UserContextService;
import com.group1.programminglanguagesforum.Services.UserService;
import com.group1.programminglanguagesforum.Util.ApiResponseBuilder;
Expand All @@ -33,6 +31,8 @@ public class UserController extends BaseController {
private final UserContextService userContextService;
private final UserService userService;
private final ModelMapper modelMapper;
private final QuestionService questionService;
private final AnswerService answerService;

@GetMapping(value = EndpointConstants.UserEndpoints.USER_ME)
public ResponseEntity<GenericApiResponse<SelfProfileResponseDto>> getUser() {
Expand All @@ -41,6 +41,16 @@ public ResponseEntity<GenericApiResponse<SelfProfileResponseDto>> getUser() {
User user = userContextService.getCurrentUser();
SelfProfileResponseDto selfProfileResponseDto = modelMapper.map(user,
SelfProfileResponseDto.class);
List<QuestionSummaryDto> questions = questionService.findByAuthorId(user.getId());
List<GetAnswerDtoForProfile> answers = answerService.findByAnsweredBy(user.getId());
selfProfileResponseDto.setQuestionCount((long) questions.size());
selfProfileResponseDto.setQuestions(
questions);
selfProfileResponseDto.setAnswerCount((long) answers.size());
selfProfileResponseDto.setAnswers(
answers);


GenericApiResponse<SelfProfileResponseDto> response = ApiResponseBuilder.buildSuccessResponse(
selfProfileResponseDto.getClass(),
"User retrieved successfully",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package com.group1.programminglanguagesforum.DTOs.Responses;

import lombok.*;

@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class GetAnswerDtoForProfile {
private Long id;
private String content;
private AuthorDto author;
private String createdAt;
private String updatedAt;
private Long upvoteCount;
private Long downvoteCount;
private boolean selfAnswer;
private Integer selfVoted;
@Builder
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public static class QuesitonInfoForAnswer {
private Long id;
private String title;
}
private QuesitonInfoForAnswer question;

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
public class GetQuestionWithTagDto {
private Long id;
private String title;
private String questionBody;
private String content;
@Builder.Default
private Long likeCount = 0L;
@Builder.Default
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
import com.group1.programminglanguagesforum.Entities.ExperienceLevel;
import lombok.*;

import java.util.List;

@Builder
@NoArgsConstructor
@AllArgsConstructor
Expand All @@ -19,5 +21,8 @@ public class SelfProfileResponseDto {
private int followersCount;
private int followingCount;
private int reputationPoints;
private Long questionCount;
private ExperienceLevel experienceLevel;
private List<QuestionSummaryDto> questions;
private List<GetAnswerDtoForProfile> answers;
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
package com.group1.programminglanguagesforum.Repositories;

import com.group1.programminglanguagesforum.Entities.Answer;
import com.group1.programminglanguagesforum.Entities.User;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

import java.util.List;

@Repository
public interface AnswerRepository extends JpaRepository<Answer,Long> {

@Query("SELECT a FROM Answer a WHERE a.answeredBy.id = :userId")
List<Answer> findByAnsweredBy(Long userId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,6 @@ Page<Question> searchQuestions(
@Param("tagIds") List<Long> tagIds,
@Param("difficulty") DifficultyLevel difficulty,
Pageable pageable);
@Query("SELECT q FROM Question q WHERE q.askedBy.id = :author")
List<Question> findByAuthorId(@Param("author") Long authorId);
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.group1.programminglanguagesforum.DTOs.Requests.CreateAnswerRequestDto;
import com.group1.programminglanguagesforum.DTOs.Responses.AuthorDto;
import com.group1.programminglanguagesforum.DTOs.Responses.CreateAnswerResponseDto;
import com.group1.programminglanguagesforum.DTOs.Responses.GetAnswerDtoForProfile;
import com.group1.programminglanguagesforum.DTOs.Responses.GetAnswersResponseDto;
import com.group1.programminglanguagesforum.Entities.Answer;
import com.group1.programminglanguagesforum.Entities.Question;
Expand All @@ -23,6 +24,13 @@ public class AnswerService {
private final QuestionService questionService;
private final VoteRepository voteRepository;


public java.util.List<GetAnswerDtoForProfile> findByAnsweredBy(Long userId) {
return answerRepository.findByAnsweredBy(userId).stream()
.map(this::mapAnswerToProfileDto)
.toList();
}

public CreateAnswerResponseDto createAnswer(Long questionId, CreateAnswerRequestDto createAnswerRequestDto) throws UnauthorizedAccessException {
User currentUser = userContextService.getCurrentUser();
Question question = questionService.findById(questionId).orElseThrow();
Expand Down Expand Up @@ -101,6 +109,32 @@ public GetAnswersResponseDto getAnswersForQuestion(Long questionId) {
.build();
}

public GetAnswerDtoForProfile mapAnswerToProfileDto(Answer answer){
final User currentUser = getCurrentUserOrNull();
return GetAnswerDtoForProfile.builder()
.id(answer.getId())
.content(answer.getAnswerBody())
.author(
AuthorDto.builder()
.id(answer.getAnsweredBy().getId())
.username(answer.getAnsweredBy().getUsername())
.reputationPoints(answer.getAnsweredBy().getReputationPoints())
.name(answer.getAnsweredBy().getFirstName() + " " + answer.getAnsweredBy().getLastName())
.build()
)
.createdAt(answer.getCreatedAt())
.updatedAt(answer.getUpdatedAt())
.upvoteCount(answer.getUpvoteCount())
.downvoteCount(answer.getDownvoteCount())
.selfAnswer(currentUser != null && currentUser.getId().equals(answer.getAnsweredBy().getId()))
.selfVoted(currentUser != null && voteRepository.findByUserAndAnswer(currentUser, answer).isPresent() ? voteRepository.findByUserAndAnswer(currentUser, answer).get().isUpvote()? 1 : -1 : 0)
.question(GetAnswerDtoForProfile.QuesitonInfoForAnswer.builder()
.id(answer.getQuestion().getId())
.title(answer.getQuestion().getTitle())
.build())
.build();
}

private User getCurrentUserOrNull() {
try {
return userContextService.getCurrentUser();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,11 @@ public class QuestionService {
public Optional<Question> findById(Long id) {
return questionRepository.findById(id);
}
public List<QuestionSummaryDto> findByAuthorId(Long authorId) {
return questionRepository.findByAuthorId(authorId).stream()
.map(this::mapToQuestionSummary)
.collect(Collectors.toList());
}

public CreateQuestionResponseDto createQuestion(CreateQuestionRequestDto dto)
throws UnauthorizedAccessException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,20 +70,23 @@ public GetTagDetailsResponseDto getTagDetails(Long tagId) {
List<GetQuestionWithTagDto> relatedQuestions = questions.stream()
.map(question -> modelMapper.map(question, GetQuestionWithTagDto.class))
.toList();
Long questionCount = (long) questions.size();

if (tagType == TagType.PROGRAMMING_LANGUAGE) {
ProgrammingLanguagesTag languageTag = (ProgrammingLanguagesTag) tagEntity;
GetProgrammingLanguageTagResponseDto responseDto = modelMapper.map(languageTag,
GetProgrammingLanguageTagResponseDto.class);
responseDto.setTagType(tagType.toString());
responseDto.setRelatedQuestions(relatedQuestions);
responseDto.setQuestionCount(questionCount);
return responseDto;
} else if (tagType == TagType.PROGRAMMING_PARADIGM) {
ProgrammingParadigmTag paradigmTag = (ProgrammingParadigmTag) tagEntity;
GetProgrammingParadigmResponseDto responseDto = modelMapper.map(paradigmTag,
GetProgrammingParadigmResponseDto.class);
responseDto.setTagType(tagType.toString());
responseDto.setRelatedQuestions(relatedQuestions);
responseDto.setQuestionCount(questionCount);
return responseDto;
}

Expand All @@ -93,6 +96,7 @@ public GetTagDetailsResponseDto getTagDetails(Long tagId) {
.description(tagEntity.getTagDescription())
.tagType(getTagType(tagEntity).toString())
.relatedQuestions(relatedQuestions)
.questionCount(questionCount)

.build();

Expand All @@ -102,6 +106,7 @@ public Page<GetTagDetailsResponseDto> searchTags(String q, Pageable pageable) {
Page<Tag> tags = tagRepository.findTagsByTagNameContainingIgnoreCase(q, pageable);
return tags.map(tag -> GetTagDetailsResponseDto.builder()
.tagId(tag.getId())
.questionCount((long) questionRepository.findQuestionsByTagId(tag.getId()).size())
.name(tag.getTagName())
.description(tag.getTagDescription())
.tagType(getTagType(tag).toString())
Expand Down
Loading

0 comments on commit c08a16e

Please sign in to comment.