TSK-1280: Sort options for task comments in REST-API
This commit is contained in:
parent
d07459fe26
commit
38c9adea5c
|
@ -62,7 +62,7 @@ public class UpdateTaskCommentAccTest extends AbstractAccTest {
|
|||
List<TaskComment> taskComments =
|
||||
taskService.getTaskComments("TKI:000000000000000000000000000000000000");
|
||||
assertThat(taskComments).hasSize(3);
|
||||
assertThat(taskComments.get(1).getTextField()).isEqualTo("some other text in textfield");
|
||||
assertThat(taskComments.get(0).getTextField()).isEqualTo("some other text in textfield");
|
||||
|
||||
TaskComment taskComment =
|
||||
taskService.getTaskComment("TCI:000000000000000000000000000000000001");
|
||||
|
@ -74,7 +74,7 @@ public class UpdateTaskCommentAccTest extends AbstractAccTest {
|
|||
// make sure the task comment wasn't updated
|
||||
List<TaskComment> taskCommentsAfterUpdateAttempt =
|
||||
taskService.getTaskComments("TKI:000000000000000000000000000000000000");
|
||||
assertThat(taskCommentsAfterUpdateAttempt.get(1).getTextField())
|
||||
assertThat(taskCommentsAfterUpdateAttempt.get(0).getTextField())
|
||||
.isEqualTo("some other text in textfield");
|
||||
}
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
-- TASK_COMMENT TABLE ID , TASK_ID ,TEXTFIELD ,CREATOR ,COMPLETED ,MODIFIED
|
||||
-- TASK_COMMENT TABLE ID , TASK_ID ,TEXTFIELD ,CREATOR ,CREATED ,MODIFIED
|
||||
|
||||
-- TaskComments for GetTaskCommentAccTest + UpdateTaskCommentAccTest
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000000', 'TKI:000000000000000000000000000000000000', 'some text in textfield', 'user_1_1', '2018-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000001', 'TKI:000000000000000000000000000000000000', 'some other text in textfield', 'user_1_1', '2018-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000002', 'TKI:000000000000000000000000000000000000', 'some other text in textfield', 'user_1_1', '2018-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000000', 'TKI:000000000000000000000000000000000000', 'some text in textfield', 'user_1_1', '2017-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000001', 'TKI:000000000000000000000000000000000000', 'some other text in textfield', 'user_1_1', '2015-01-29 15:55:00', '2022-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000002', 'TKI:000000000000000000000000000000000000', 'some other text in textfield', 'user_1_1', '2020-01-29 15:55:00', '2021-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000003', 'TKI:000000000000000000000000000000000025', 'some text in textfield', 'user_1_1', '2018-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
-- TaskComments for DeleteTaskCommentAccTest
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000004', 'TKI:000000000000000000000000000000000001', 'some text in textfield', 'user_1_1', '2018-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
-- TASK_COMMENT TABLE ID , TASK_ID ,TEXTFIELD ,CREATOR ,COMPLETED ,MODIFIED
|
||||
-- TASK_COMMENT TABLE ID , TASK_ID ,TEXTFIELD ,CREATOR ,CREATED ,MODIFIED
|
||||
|
||||
-- TaskComments for GetTaskCommentAccTest + UpdateTaskCommentAccTest
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000000', 'TKI:000000000000000000000000000000000000', 'some text in textfield', 'user_1_1', '2018-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000001', 'TKI:000000000000000000000000000000000000', 'some other text in textfield', 'user_1_1', '2018-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000002', 'TKI:000000000000000000000000000000000000', 'some other text in textfield', 'user_1_1', '2018-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000000', 'TKI:000000000000000000000000000000000000', 'some text in textfield', 'user_1_1', '2017-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000001', 'TKI:000000000000000000000000000000000000', 'some other text in textfield', 'user_1_1', '2015-01-29 15:55:00', '2022-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000002', 'TKI:000000000000000000000000000000000000', 'some other text in textfield', 'user_1_1', '2020-01-29 15:55:00', '2021-01-30 15:55:00');
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000003', 'TKI:000000000000000000000000000000000025', 'some text in textfield', 'user_1_1', '2018-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
-- TaskComments for DeleteTaskCommentAccTest
|
||||
INSERT INTO TASK_COMMENT VALUES('TCI:000000000000000000000000000000000004', 'TKI:000000000000000000000000000000000001', 'some text in textfield', 'user_1_1', '2018-01-29 15:55:00', '2018-01-30 15:55:00');
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package pro.taskana.task.rest;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
@ -9,12 +10,14 @@ import org.springframework.hateoas.config.EnableHypermediaSupport.HypermediaType
|
|||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.MultiValueMap;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
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.PutMapping;
|
||||
import org.springframework.web.bind.annotation.RequestBody;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import pro.taskana.common.api.exceptions.ConcurrencyException;
|
||||
|
@ -29,13 +32,21 @@ import pro.taskana.task.api.models.TaskComment;
|
|||
import pro.taskana.task.rest.assembler.TaskCommentRepresentationModelAssembler;
|
||||
import pro.taskana.task.rest.models.TaskCommentRepresentationModel;
|
||||
|
||||
/** Controller for all {@link TaskComment} related endpoints. */
|
||||
/**
|
||||
* Controller for all {@link TaskComment} related endpoints.
|
||||
*/
|
||||
@RestController
|
||||
@EnableHypermediaSupport(type = HypermediaType.HAL)
|
||||
public class TaskCommentController {
|
||||
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger(TaskCommentController.class);
|
||||
|
||||
private static final String SORT_BY = "sort-by";
|
||||
private static final String SORT_DIRECTION = "order";
|
||||
private static final String CREATED = "created";
|
||||
private static final String MODIFIED = "modified";
|
||||
|
||||
|
||||
private final TaskService taskService;
|
||||
private final TaskCommentRepresentationModelAssembler taskCommentRepresentationModelAssembler;
|
||||
|
||||
|
@ -52,7 +63,7 @@ public class TaskCommentController {
|
|||
public ResponseEntity<TaskCommentRepresentationModel> getTaskComment(
|
||||
@PathVariable String taskCommentId)
|
||||
throws NotAuthorizedException, TaskNotFoundException, TaskCommentNotFoundException,
|
||||
InvalidArgumentException {
|
||||
InvalidArgumentException {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Entry to getTaskComment(taskCommentId= {})", taskCommentId);
|
||||
}
|
||||
|
@ -75,13 +86,19 @@ public class TaskCommentController {
|
|||
@GetMapping(path = Mapping.URL_TASK_GET_POST_COMMENTS)
|
||||
@Transactional(readOnly = true, rollbackFor = Exception.class)
|
||||
public ResponseEntity<TaskanaPagedModel<TaskCommentRepresentationModel>> getTaskComments(
|
||||
@PathVariable String taskId) throws NotAuthorizedException, TaskNotFoundException {
|
||||
@PathVariable String taskId,
|
||||
@RequestParam(required = false) MultiValueMap<String, String> params)
|
||||
throws NotAuthorizedException, TaskNotFoundException, InvalidArgumentException {
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Entry to getTaskComments(taskId= {})", taskId);
|
||||
}
|
||||
|
||||
List<TaskComment> taskComments = taskService.getTaskComments(taskId);
|
||||
|
||||
//TODO Maybe introduce a query for task comments
|
||||
applySortingParams(taskComments, params);
|
||||
|
||||
TaskanaPagedModel<TaskCommentRepresentationModel> taskCommentListResource =
|
||||
taskCommentRepresentationModelAssembler.toPageModel(taskComments, null);
|
||||
|
||||
|
@ -100,7 +117,7 @@ public class TaskCommentController {
|
|||
public ResponseEntity<TaskCommentRepresentationModel> deleteTaskComment(
|
||||
@PathVariable String taskCommentId)
|
||||
throws NotAuthorizedException, TaskNotFoundException, TaskCommentNotFoundException,
|
||||
InvalidArgumentException {
|
||||
InvalidArgumentException {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Entry to deleteTaskComment(taskCommentId= {})", taskCommentId);
|
||||
}
|
||||
|
@ -122,7 +139,7 @@ public class TaskCommentController {
|
|||
@PathVariable String taskCommentId,
|
||||
@RequestBody TaskCommentRepresentationModel taskCommentRepresentationModel)
|
||||
throws NotAuthorizedException, TaskNotFoundException, TaskCommentNotFoundException,
|
||||
InvalidArgumentException, ConcurrencyException {
|
||||
InvalidArgumentException, ConcurrencyException {
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug(
|
||||
"Entry to updateTaskComment(taskCommentId= {}, taskCommentResource= {})",
|
||||
|
@ -186,4 +203,47 @@ public class TaskCommentController {
|
|||
|
||||
return result;
|
||||
}
|
||||
|
||||
private List<TaskComment> applySortingParams(List<TaskComment> taskComments,
|
||||
MultiValueMap<String, String> params) throws InvalidArgumentException {
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER
|
||||
.debug("Entry to applySortingParams(taskComments= {}, params= {})", taskComments, params);
|
||||
}
|
||||
|
||||
String sortBy = params.getFirst(SORT_BY);
|
||||
|
||||
if (sortBy != null) {
|
||||
|
||||
switch (sortBy) {
|
||||
case (CREATED):
|
||||
if (params.getFirst(SORT_DIRECTION) != null
|
||||
&& "desc".equals(params.getFirst(SORT_DIRECTION))) {
|
||||
taskComments.sort(Comparator.comparing(TaskComment::getCreated).reversed());
|
||||
} else {
|
||||
taskComments.sort(Comparator.comparing(TaskComment::getCreated));
|
||||
|
||||
}
|
||||
break;
|
||||
case (MODIFIED):
|
||||
if (params.getFirst(SORT_DIRECTION) != null
|
||||
&& "desc".equals(params.getFirst(SORT_DIRECTION))) {
|
||||
taskComments.sort(Comparator.comparing(TaskComment::getModified).reversed());
|
||||
} else {
|
||||
taskComments.sort(Comparator.comparing(TaskComment::getModified));
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new InvalidArgumentException("Unknown sort attribute: " + sortBy);
|
||||
}
|
||||
}
|
||||
|
||||
if (LOGGER.isDebugEnabled()) {
|
||||
LOGGER.debug("Exit from applySortingParams(), returning {}", taskComments);
|
||||
}
|
||||
|
||||
return taskComments;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
|||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||
|
||||
import java.time.Instant;
|
||||
import java.util.Comparator;
|
||||
import org.assertj.core.api.ThrowableAssert.ThrowingCallable;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Disabled;
|
||||
|
@ -25,19 +26,23 @@ import pro.taskana.common.rest.TaskanaSpringBootTest;
|
|||
import pro.taskana.common.rest.models.TaskanaPagedModel;
|
||||
import pro.taskana.task.rest.models.TaskCommentRepresentationModel;
|
||||
|
||||
/** Test TaskCommentController. */
|
||||
/**
|
||||
* Test TaskCommentController.
|
||||
*/
|
||||
@TaskanaSpringBootTest
|
||||
class TaskCommentControllerIntTest {
|
||||
|
||||
private static final ParameterizedTypeReference<TaskanaPagedModel<TaskCommentRepresentationModel>>
|
||||
TASK_COMMENT_PAGE_MODEL_TYPE =
|
||||
new ParameterizedTypeReference<TaskanaPagedModel<TaskCommentRepresentationModel>>() {};
|
||||
new ParameterizedTypeReference<TaskanaPagedModel<TaskCommentRepresentationModel>>() {
|
||||
};
|
||||
private static RestTemplate template;
|
||||
|
||||
@Value("${taskana.schemaName:TASKANA}")
|
||||
public String schemaName;
|
||||
|
||||
@Autowired RestHelper restHelper;
|
||||
@Autowired
|
||||
RestHelper restHelper;
|
||||
|
||||
@BeforeAll
|
||||
static void init() {
|
||||
|
@ -83,6 +88,85 @@ class TaskCommentControllerIntTest {
|
|||
.isEqualTo(HttpStatus.FORBIDDEN);
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_ReturnSortedAndOrederedTaskCommentsSortedByModified_When_UsingSortAndOrderParams() {
|
||||
|
||||
String url =
|
||||
restHelper.toUrl(Mapping.URL_TASK_GET_POST_COMMENTS,
|
||||
"TKI:000000000000000000000000000000000000");
|
||||
|
||||
ResponseEntity<TaskanaPagedModel<TaskCommentRepresentationModel>>
|
||||
getTaskCommentsSortedByModifiedOrderedByDescendingResponse = template.exchange(
|
||||
url + "?sort-by=modified&order=desc",
|
||||
HttpMethod.GET,
|
||||
new HttpEntity<String>(restHelper.getHeadersAdmin()),
|
||||
TASK_COMMENT_PAGE_MODEL_TYPE);
|
||||
|
||||
assertThat(getTaskCommentsSortedByModifiedOrderedByDescendingResponse.getBody().getContent())
|
||||
.hasSize(3)
|
||||
.extracting(TaskCommentRepresentationModel::getModified)
|
||||
.isSortedAccordingTo(Comparator.reverseOrder());
|
||||
|
||||
ResponseEntity<TaskanaPagedModel<TaskCommentRepresentationModel>>
|
||||
getTaskCommentsSortedByModifiedOrderedByAscendingResponse = template.exchange(
|
||||
url + "?sort-by=modified",
|
||||
HttpMethod.GET,
|
||||
new HttpEntity<String>(restHelper.getHeadersAdmin()),
|
||||
TASK_COMMENT_PAGE_MODEL_TYPE);
|
||||
|
||||
assertThat(getTaskCommentsSortedByModifiedOrderedByAscendingResponse.getBody().getContent())
|
||||
.hasSize(3)
|
||||
.extracting(TaskCommentRepresentationModel::getModified)
|
||||
.isSortedAccordingTo(Comparator.naturalOrder());
|
||||
|
||||
ResponseEntity<TaskanaPagedModel<TaskCommentRepresentationModel>>
|
||||
getTaskCommentsSortedByCreatedOrderedByDescendingResponse = template.exchange(
|
||||
url + "?sort-by=created&order=desc",
|
||||
HttpMethod.GET,
|
||||
new HttpEntity<String>(restHelper.getHeadersAdmin()),
|
||||
TASK_COMMENT_PAGE_MODEL_TYPE);
|
||||
|
||||
assertThat(getTaskCommentsSortedByCreatedOrderedByDescendingResponse.getBody().getContent())
|
||||
.hasSize(3)
|
||||
.extracting(TaskCommentRepresentationModel::getCreated)
|
||||
.isSortedAccordingTo(Comparator.reverseOrder());
|
||||
|
||||
ResponseEntity<TaskanaPagedModel<TaskCommentRepresentationModel>>
|
||||
getTaskCommentsSortedByCreatedOrderedByAscendingResponse = template.exchange(
|
||||
url + "?sort-by=created",
|
||||
HttpMethod.GET,
|
||||
new HttpEntity<String>(restHelper.getHeadersAdmin()),
|
||||
TASK_COMMENT_PAGE_MODEL_TYPE);
|
||||
|
||||
assertThat(getTaskCommentsSortedByCreatedOrderedByAscendingResponse.getBody().getContent())
|
||||
.hasSize(3)
|
||||
.extracting(TaskCommentRepresentationModel::getCreated)
|
||||
.isSortedAccordingTo(Comparator.naturalOrder());
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
void should_ThrowException_When_UsingInvalidSortParam() {
|
||||
|
||||
String url =
|
||||
restHelper.toUrl(Mapping.URL_TASK_GET_POST_COMMENTS,
|
||||
"TKI:000000000000000000000000000000000000");
|
||||
|
||||
ThrowingCallable httpCall =
|
||||
() -> {
|
||||
template.exchange(
|
||||
url + "?sort-by=invalidSortParam",
|
||||
HttpMethod.GET,
|
||||
new HttpEntity<String>(restHelper.getHeadersUser_1_1()),
|
||||
TASK_COMMENT_PAGE_MODEL_TYPE);
|
||||
};
|
||||
assertThatThrownBy(httpCall)
|
||||
.extracting(ex -> ((HttpClientErrorException) ex).getStatusCode())
|
||||
.isEqualTo(HttpStatus.BAD_REQUEST);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Disabled("Disabled until Authorization check is up!")
|
||||
@Test
|
||||
void should_FailToReturnTaskComment_When_TaskIstNotVisible() {
|
||||
|
@ -219,7 +303,6 @@ class TaskCommentControllerIntTest {
|
|||
@Test
|
||||
void should_FailToUpdateTaskComment_When_TaskCommentIdInResourceDoesNotMatchPathVariable() {
|
||||
|
||||
|
||||
String url =
|
||||
restHelper.toUrl(Mapping.URL_TASK_COMMENT, "TCI:000000000000000000000000000000000000");
|
||||
|
||||
|
@ -259,12 +342,12 @@ class TaskCommentControllerIntTest {
|
|||
|
||||
ResponseEntity<TaskanaPagedModel<TaskCommentRepresentationModel>>
|
||||
getTaskCommentsBeforeDeleteionResponse =
|
||||
template.exchange(
|
||||
restHelper.toUrl(
|
||||
Mapping.URL_TASK_COMMENTS, "TKI:000000000000000000000000000000000001"),
|
||||
HttpMethod.GET,
|
||||
new HttpEntity<String>(restHelper.getHeadersAdmin()),
|
||||
TASK_COMMENT_PAGE_MODEL_TYPE);
|
||||
template.exchange(
|
||||
restHelper.toUrl(
|
||||
Mapping.URL_TASK_COMMENTS, "TKI:000000000000000000000000000000000001"),
|
||||
HttpMethod.GET,
|
||||
new HttpEntity<String>(restHelper.getHeadersAdmin()),
|
||||
TASK_COMMENT_PAGE_MODEL_TYPE);
|
||||
assertThat(getTaskCommentsBeforeDeleteionResponse.getBody().getContent()).hasSize(2);
|
||||
|
||||
String url =
|
||||
|
|
|
@ -321,6 +321,10 @@ include::{snippets}/GetAllTaskCommentsForSpecificTaskDocTest/http-response.adoc[
|
|||
|
||||
include::{snippets}/GetAllTaskCommentsForSpecificTaskDocTest/response-fields.adoc[]
|
||||
|
||||
=== Sort options
|
||||
|
||||
sort-by={ created | modified } | order={ desc | asc }
|
||||
|
||||
|
||||
=== Get a specific task comment
|
||||
|
||||
|
|
Loading…
Reference in New Issue