Skip to content

Commit

Permalink
Merge pull request #202 from FEBFES/feature/198/add_task_comments
Browse files Browse the repository at this point in the history
198 - Task Comments
  • Loading branch information
IvanShish authored Jun 10, 2024
2 parents ded3646 + aaf088d commit 2eddcc0
Show file tree
Hide file tree
Showing 10 changed files with 329 additions and 4 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package com.febfes.fftmback.controller;

import com.febfes.fftmback.annotation.ApiCreate;
import com.febfes.fftmback.annotation.ApiGet;
import com.febfes.fftmback.annotation.ProtectedApi;
import com.febfes.fftmback.dto.TaskCommentDto;
import com.febfes.fftmback.mapper.TaskCommentMapper;
import com.febfes.fftmback.service.TaskCommentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.List;

@RestController
@RequestMapping("v1/projects/task")
@RequiredArgsConstructor
@ProtectedApi
@Tag(name = "TaskComment")
public class TaskCommentController {

private final TaskCommentService taskCommentService;
private final TaskCommentMapper taskCommentMapper;

@Operation(summary = "Create new task comment")
@ApiCreate(path = "comment")
public TaskCommentDto createTask(
@RequestBody TaskCommentDto taskCommentDto
) {
return taskCommentMapper.taskCommentEntityToTaskCommentDto(
taskCommentService.saveTaskComment(taskCommentMapper.taskCommentToTaskCommentEntity(taskCommentDto))
);
}

@Operation(summary = "Get task comments")
@ApiGet(path = "{taskId}/comments")
public List<TaskCommentDto> getTaskComments(
@PathVariable Long taskId
) {
return taskCommentMapper.taskCommentEntityToTaskCommentDto(taskCommentService.getCommentsByTaskId(taskId));
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package com.febfes.fftmback.domain.dao;


import com.febfes.fftmback.domain.dao.abstracts.BaseEntity;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.experimental.SuperBuilder;

@Entity
@Table(name = "task_comment")
@SuperBuilder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class TaskCommentEntity extends BaseEntity {

@ManyToOne
@JoinColumn(name = "creator_id", referencedColumnName = "id")
private UserEntity creator;

@Column(name = "task_id")
private Long taskId;

@Column(name = "text")
private String text;
}
13 changes: 13 additions & 0 deletions src/main/java/com/febfes/fftmback/dto/TaskCommentDto.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.febfes.fftmback.dto;

import lombok.Builder;

@Builder
public record TaskCommentDto(
Long id,
Long creatorId,
String creatorName,
Long taskId,
String text
) {
}
32 changes: 32 additions & 0 deletions src/main/java/com/febfes/fftmback/mapper/TaskCommentMapper.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.febfes.fftmback.mapper;

import com.febfes.fftmback.domain.dao.TaskCommentEntity;
import com.febfes.fftmback.dto.TaskCommentDto;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Named;

import java.util.List;

@Mapper(componentModel = "spring")
public interface TaskCommentMapper {

@Mapping(target = "creator.id", source = "creatorId")
TaskCommentEntity taskCommentToTaskCommentEntity(TaskCommentDto taskCommentDto);

@Mapping(target ="creatorId", source = "creator.id")
@Mapping(target = "creatorName", source = ".", qualifiedByName = "getCreatorName")
TaskCommentDto taskCommentEntityToTaskCommentDto(TaskCommentEntity taskCommentEntity);

@Mapping(target ="creatorId", source = "creator.id")
@Mapping(target = "creatorName", source = ".", qualifiedByName = "getCreatorName")
List<TaskCommentDto> taskCommentEntityToTaskCommentDto(List<TaskCommentEntity> taskCommentEntityList);

@Named("getCreatorName")
default String getCreatorName(TaskCommentEntity taskCommentEntity) {
return "%s %s".formatted(
taskCommentEntity.getCreator().getFirstName(),
taskCommentEntity.getCreator().getLastName()
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.febfes.fftmback.repository;

import com.febfes.fftmback.domain.dao.TaskCommentEntity;
import org.springframework.data.jpa.repository.JpaRepository;

public interface TaskCommentRepository extends JpaRepository<TaskCommentEntity, Long> {
}
12 changes: 12 additions & 0 deletions src/main/java/com/febfes/fftmback/service/TaskCommentService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.febfes.fftmback.service;

import com.febfes.fftmback.domain.dao.TaskCommentEntity;

import java.util.List;

public interface TaskCommentService {

TaskCommentEntity saveTaskComment(TaskCommentEntity taskComment);

List<TaskCommentEntity> getCommentsByTaskId(Long taskId);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package com.febfes.fftmback.service.impl;

import com.febfes.fftmback.domain.dao.TaskCommentEntity;
import com.febfes.fftmback.repository.TaskCommentRepository;
import com.febfes.fftmback.service.TaskCommentService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
@RequiredArgsConstructor
public class TaskCommentServiceImpl implements TaskCommentService {

private final TaskCommentRepository taskCommentRepository;

@Override
public TaskCommentEntity saveTaskComment(TaskCommentEntity taskComment) {
return taskCommentRepository.save(taskComment);
}

@Override
public List<TaskCommentEntity> getCommentsByTaskId(Long taskId) {
return taskCommentRepository.findAll(
Example.of(TaskCommentEntity.builder().taskId(taskId).build()),
Sort.by(Sort.Direction.ASC, "createDate")
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
databaseChangeLog:
- changeSet:
id: 0
author: VladisStep
comment: add task comment table
changes:
- createTable:
tableName: task_comment
columns:
- column:
name: id
type: bigint
autoIncrement: true
constraints:
primaryKey: true
nullable: false
- column:
name: create_date
type: timestamp
constraints:
nullable: false
- column:
name: creator_id
type: bigint
- column:
name: task_id
type: bigint
constraints:
nullable: false
- column:
name: text
type: varchar(1000)
- changeSet:
id: 1
author: VladisStep
comment: add foreign keys
changes:
- addForeignKeyConstraint:
constraintName: fk_creator_id
baseTableName: task_comment
baseColumnNames: creator_id
referencedTableName: user_entity
referencedColumnNames: id
onDelete: set null
- addForeignKeyConstraint:
constraintName: fk_task_id
baseTableName: task_comment
baseColumnNames: task_id
referencedTableName: task
referencedColumnNames: id
onDelete: cascade
- changeSet:
id: 2
author: VladisStep
comment: change text column type
changes:
- modifyDataType:
tableName: task_comment
columnName: text
newDataType: text
22 changes: 18 additions & 4 deletions src/test/java/com/febfes/fftmback/integration/BasicTestClass.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,10 @@


import com.febfes.fftmback.domain.common.RoleName;
import com.febfes.fftmback.domain.dao.TaskEntity;
import com.febfes.fftmback.domain.dao.UserEntity;
import com.febfes.fftmback.service.AuthenticationService;
import com.febfes.fftmback.service.ColumnService;
import com.febfes.fftmback.service.TaskTypeService;
import com.febfes.fftmback.service.UserService;
import com.febfes.fftmback.domain.dao.abstracts.BaseEntity;
import com.febfes.fftmback.service.*;
import com.febfes.fftmback.service.project.ProjectManagementService;
import com.febfes.fftmback.service.project.ProjectMemberService;
import com.febfes.fftmback.util.DatabaseCleanup;
Expand Down Expand Up @@ -59,6 +58,9 @@ public class BasicTestClass {
@Qualifier("projectManagementService")
protected ProjectManagementService projectManagementService;

@Autowired
protected TaskService taskService;

@LocalServerPort
private Integer port;

Expand Down Expand Up @@ -109,5 +111,17 @@ protected Long createNewProject() {
projectMemberService.addUserToProjectAndChangeRole(projectId, createdUserId, RoleName.OWNER);
return projectId;
}

protected Long createNewTask(Long projectId, Long userId) {
Long columnId = columnService.getOrderedColumns(projectId)
.stream()
.findAny()
.map(BaseEntity::getId)
.orElseThrow(() -> new IllegalArgumentException("Project with id=%d doesn't have task columns"));
return taskService.createTask(
TaskEntity.builder().projectId(projectId).columnId(columnId).name("SomeTask").build(),
userId
);
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package com.febfes.fftmback.integration;

import com.febfes.fftmback.domain.dao.TaskCommentEntity;
import com.febfes.fftmback.domain.dao.UserEntity;
import com.febfes.fftmback.dto.TaskCommentDto;
import com.febfes.fftmback.service.TaskCommentService;
import com.github.dockerjava.zerodep.shaded.org.apache.hc.core5.http.HttpStatus;
import io.restassured.http.ContentType;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.Optional;

import static com.febfes.fftmback.integration.ProjectControllerTest.PATH_TO_PROJECTS_API;
import static org.assertj.core.api.Assertions.assertThat;

class TaskCommentControllerTest extends BasicTestClass {

@Autowired
private TaskCommentService taskCommentService;

@Test
void createTaskCommentTest() {
Long userId = createNewUser();
Long projectId = createNewProject();
Long taskId = createNewTask(projectId, userId);

TaskCommentDto comment = TaskCommentDto.builder()
.creatorId(userId)
.taskId(taskId)
.text("Some comment text")
.build();

requestWithBearerToken()
.contentType(ContentType.JSON)
.body(comment)
.when()
.post("%s/task/comment".formatted(PATH_TO_PROJECTS_API))
.then()
.statusCode(HttpStatus.SC_OK);
}

@Test
void getTaskCommentTest() {
Long userId = createNewUser();
Long projectId = createNewProject();
Long taskId = createNewTask(projectId, userId);

TaskCommentEntity comment = taskCommentService.saveTaskComment(
TaskCommentEntity.builder()
.creator(UserEntity.builder().id(userId).build())
.taskId(taskId)
.text("Some comment text")
.build()
);

Optional<TaskCommentDto> receivedCommentOpt = requestWithBearerToken()
.contentType(ContentType.JSON)
.when()
.get("%s/task/%s/comments".formatted(PATH_TO_PROJECTS_API, taskId.toString()))
.then()
.statusCode(HttpStatus.SC_OK)
.extract()
.response()
.jsonPath()
.getList(".", TaskCommentDto.class)
.stream()
.findFirst();

assertThat(receivedCommentOpt).isPresent();
receivedCommentOpt.ifPresent(receivedComment -> {
assertThat(receivedComment.id()).isEqualTo(comment.getTaskId());
assertThat(receivedComment.taskId()).isEqualTo(comment.getTaskId());
assertThat(receivedComment.creatorId()).isEqualTo(comment.getCreator().getId());
assertThat(receivedComment.text()).isEqualTo(comment.getText());
});
}
}

0 comments on commit 2eddcc0

Please sign in to comment.