Skip to content
Snippets Groups Projects
Commit 2382029a authored by Jan Tymel's avatar Jan Tymel
Browse files

Change the remaining REST API related to tasks according to the new design

Related to #10
parent 5b1c0b60
No related branches found
No related tags found
No related merge requests found
...@@ -147,21 +147,21 @@ public class AdaptiveTrainingDefinitionsRestController { ...@@ -147,21 +147,21 @@ public class AdaptiveTrainingDefinitionsRestController {
levelOperationsService.updatePhaseLevel(phaseLevelUpdateDto); levelOperationsService.updatePhaseLevel(phaseLevelUpdateDto);
} }
@ApiOperation(httpMethod = "PUT", // @ApiOperation(httpMethod = "PUT",
value = "Update task", // value = "Update task",
nickname = "updateTask", // nickname = "updateTask",
consumes = MediaType.APPLICATION_JSON_VALUE // consumes = MediaType.APPLICATION_JSON_VALUE
) // )
@ApiResponses(value = { // @ApiResponses(value = {
@ApiResponse(code = 200, message = "Task updated"), // @ApiResponse(code = 200, message = "Task updated"),
@ApiResponse(code = 500, message = "Unexpected application error") // @ApiResponse(code = 500, message = "Unexpected application error")
}) // })
@PutMapping(path = "/tasks") // @PutMapping(path = "/tasks")
public void updateTask( // public void updateTask(
@ApiParam(value = "Task to be updated") @RequestBody TaskUpdateDto taskUpdateDto) { // @ApiParam(value = "Task to be updated") @RequestBody TaskUpdateDto taskUpdateDto) {
//
levelOperationsService.updateTask(taskUpdateDto); // levelOperationsService.updateTask(taskUpdateDto);
} // }
// @ApiOperation(httpMethod = "POST", // @ApiOperation(httpMethod = "POST",
// value = "Create a new task", // value = "Create a new task",
......
package com.example.demo.controller; package com.example.demo.controller;
import com.example.demo.dto.TaskDto; import com.example.demo.dto.TaskDto;
import com.example.demo.dto.TaskUpdateDto;
import com.example.demo.service.TaskService; import com.example.demo.service.TaskService;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
...@@ -12,12 +13,17 @@ import org.springframework.beans.factory.annotation.Autowired; ...@@ -12,12 +13,17 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable; import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping; 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.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController; import org.springframework.web.bind.annotation.RestController;
import javax.validation.Valid;
@RestController @RestController
@RequestMapping(value = "/training-definitions/{definitionId}/phases/{phaseId}/tasks", produces = MediaType.APPLICATION_JSON_VALUE) @RequestMapping(value = "/training-definitions/{definitionId}/phases/{phaseId}/tasks", produces = MediaType.APPLICATION_JSON_VALUE)
@Api(value = "/training-definitions/{definitionId}/phases", @Api(value = "/training-definitions/{definitionId}/phases",
...@@ -102,4 +108,53 @@ public class TasksController { ...@@ -102,4 +108,53 @@ public class TasksController {
return new ResponseEntity<>(createdTask, HttpStatus.CREATED); return new ResponseEntity<>(createdTask, HttpStatus.CREATED);
} }
@ApiOperation(httpMethod = "PUT",
value = "Update task",
notes = "Update the specified task",
nickname = "updateTask",
consumes = MediaType.APPLICATION_JSON_VALUE
)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Task updated"),
@ApiResponse(code = 500, message = "Unexpected application error")
})
@PutMapping
public ResponseEntity<TaskDto> updateTask(
@ApiParam(value = "Training definition ID", required = true)
@PathVariable(name = "definitionId") Long definitionId,
@ApiParam(value = "Game phase ID", required = true)
@PathVariable(name = "phaseId") Long phaseId,
@ApiParam(value = "Task to be updated")
@RequestBody @Valid TaskUpdateDto taskUpdateDto) {
TaskDto updatedTask = taskService.updateTask(definitionId, phaseId, taskUpdateDto);
return new ResponseEntity<>(updatedTask, HttpStatus.OK);
}
@ApiOperation(httpMethod = "DELETE",
value = "Remove a task",
notes = "Remove the specified task",
response = TaskDto.class,
nickname = "removeTask",
produces = MediaType.APPLICATION_JSON_VALUE
)
@ApiResponses(value = {
@ApiResponse(code = 200, message = "Task removed"),
@ApiResponse(code = 500, message = "Unexpected application error")
})
@DeleteMapping(path = "/{taskId}")
public ResponseEntity<Void> removeTask(
@ApiParam(value = "Training definition ID", required = true)
@PathVariable(name = "definitionId") Long definitionId,
@ApiParam(value = "Game phase ID", required = true)
@PathVariable(name = "phaseId") Long phaseId,
@ApiParam(value = "Task ID", required = true)
@PathVariable(name = "taskId") Long taskId) {
taskService.removeTask(definitionId, phaseId, taskId);
return ResponseEntity.ok().build();
}
} }
package com.example.demo.dto; package com.example.demo.dto;
import io.swagger.annotations.ApiModelProperty;
import javax.validation.constraints.NotEmpty;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.PositiveOrZero;
import java.util.List; import java.util.List;
public class TaskUpdateDto { public class TaskUpdateDto {
@ApiModelProperty(value = "Task ID", required = true, example = "1")
@NotNull(message = "Task ID must be specified")
private Long id; private Long id;
@ApiModelProperty(value = "Short description of task", required = true, example = "Task title")
@NotEmpty(message = "Task title must not be blank")
private String title; private String title;
@ApiModelProperty(value = "The information that are displayed to a player", required = true, example = "Capture the flag")
@NotEmpty(message = "Task content must not be blank")
private String content; private String content;
@ApiModelProperty(value = "Keyword that must be found in the task. Necessary in order to get to the next level", required = true, example = "secretFlag")
@NotEmpty(message = "Flag of task cannot be null")
private String flag; private String flag;
@ApiModelProperty(value = "Description how to get the flag", required = true, example = "Open secret.txt")
@NotEmpty(message = "Solution of task cannot be null")
private String solution; private String solution;
private Long incorrectFlagLimit;
@ApiModelProperty(value = "It defines the allowed number of incorrect flags submitted by the player", required = true, example = "5")
@NotNull(message = "Limit of the number of provided incorrect flags must be specified")
@PositiveOrZero(message = "Limit of the number of provided incorrect flags must not be a negative number")
private Integer incorrectFlagLimit;
// private List<AttachmentDto> attachments; // private List<AttachmentDto> attachments;
...@@ -62,11 +85,11 @@ public class TaskUpdateDto { ...@@ -62,11 +85,11 @@ public class TaskUpdateDto {
// this.attachments = attachments; // this.attachments = attachments;
// } // }
public Long getIncorrectFlagLimit() { public Integer getIncorrectFlagLimit() {
return incorrectFlagLimit; return incorrectFlagLimit;
} }
public void setIncorrectFlagLimit(Long incorrectFlagLimit) { public void setIncorrectFlagLimit(Integer incorrectFlagLimit) {
this.incorrectFlagLimit = incorrectFlagLimit; this.incorrectFlagLimit = incorrectFlagLimit;
} }
......
...@@ -2,11 +2,21 @@ package com.example.demo.repository; ...@@ -2,11 +2,21 @@ package com.example.demo.repository;
import com.example.demo.domain.Task; import com.example.demo.domain.Task;
import org.springframework.data.jpa.repository.JpaRepository; import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query; import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param; import org.springframework.data.repository.query.Param;
import org.springframework.transaction.annotation.Transactional;
public interface TaskRepository extends JpaRepository<Task, Long> { public interface TaskRepository extends JpaRepository<Task, Long> {
@Query("SELECT COALESCE(MAX(g.order), -1) FROM Task g WHERE g.phaseLevel.id = :phaseId") @Query("SELECT COALESCE(MAX(g.order), -1) FROM Task g WHERE g.phaseLevel.id = :phaseId")
Integer getCurrentMaxOrder(@Param("phaseId") Long phaseId); Integer getCurrentMaxOrder(@Param("phaseId") Long phaseId);
@Transactional
@Modifying
@Query("UPDATE Task t SET t.order = t.order - 1 " +
"WHERE t.phaseLevel.id = :gamePhaseId " +
"AND t.order > :order ")
void decreaseOrderAfterTaskWasDeleted(@Param("gamePhaseId") Long gamePhaseId,
@Param("order") int order);
} }
...@@ -6,7 +6,6 @@ import com.example.demo.domain.PhaseLevel; ...@@ -6,7 +6,6 @@ import com.example.demo.domain.PhaseLevel;
import com.example.demo.domain.Question; import com.example.demo.domain.Question;
import com.example.demo.domain.QuestionChoice; import com.example.demo.domain.QuestionChoice;
import com.example.demo.domain.QuestionnaireLevel; import com.example.demo.domain.QuestionnaireLevel;
import com.example.demo.domain.Task;
import com.example.demo.dto.BaseLevelDto; import com.example.demo.dto.BaseLevelDto;
import com.example.demo.dto.InfoLevelUpdateDto; import com.example.demo.dto.InfoLevelUpdateDto;
import com.example.demo.dto.PhaseCreateDTO; import com.example.demo.dto.PhaseCreateDTO;
...@@ -16,7 +15,6 @@ import com.example.demo.dto.QuestionChoiceUpdateDto; ...@@ -16,7 +15,6 @@ import com.example.demo.dto.QuestionChoiceUpdateDto;
import com.example.demo.dto.QuestionDto; import com.example.demo.dto.QuestionDto;
import com.example.demo.dto.QuestionUpdateDto; import com.example.demo.dto.QuestionUpdateDto;
import com.example.demo.dto.QuestionnaireUpdateDto; import com.example.demo.dto.QuestionnaireUpdateDto;
import com.example.demo.dto.TaskUpdateDto;
import com.example.demo.enums.PhaseType; import com.example.demo.enums.PhaseType;
import com.example.demo.enums.QuestionType; import com.example.demo.enums.QuestionType;
import com.example.demo.mapper.BeanMapper; import com.example.demo.mapper.BeanMapper;
...@@ -156,11 +154,6 @@ public class LevelOperationsService { ...@@ -156,11 +154,6 @@ public class LevelOperationsService {
phaseLevelService.updatePhaseLevel(phaseLevel); phaseLevelService.updatePhaseLevel(phaseLevel);
} }
public void updateTask(TaskUpdateDto taskUpdateDto) {
Task task = BeanMapper.INSTANCE.toEntity(taskUpdateDto);
taskService.updateTask(task);
}
public QuestionDto createQuestion(Long questionnaireId, QuestionType questionType) { public QuestionDto createQuestion(Long questionnaireId, QuestionType questionType) {
QuestionDto createdQuestion = questionService.createDefaultQuestion(questionnaireId, questionType); QuestionDto createdQuestion = questionService.createDefaultQuestion(questionnaireId, questionType);
......
...@@ -4,6 +4,7 @@ import com.example.demo.domain.PhaseLevel; ...@@ -4,6 +4,7 @@ import com.example.demo.domain.PhaseLevel;
import com.example.demo.domain.Task; import com.example.demo.domain.Task;
import com.example.demo.dto.TaskCreateDto; import com.example.demo.dto.TaskCreateDto;
import com.example.demo.dto.TaskDto; import com.example.demo.dto.TaskDto;
import com.example.demo.dto.TaskUpdateDto;
import com.example.demo.mapper.BeanMapper; import com.example.demo.mapper.BeanMapper;
import com.example.demo.repository.PhaseLevelRepository; import com.example.demo.repository.PhaseLevelRepository;
import com.example.demo.repository.TaskRepository; import com.example.demo.repository.TaskRepository;
...@@ -16,7 +17,6 @@ import org.springframework.stereotype.Service; ...@@ -16,7 +17,6 @@ import org.springframework.stereotype.Service;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional;
@Service @Service
public class TaskService { public class TaskService {
...@@ -105,25 +105,33 @@ public class TaskService { ...@@ -105,25 +105,33 @@ public class TaskService {
return BeanMapper.INSTANCE.toDto(task); return BeanMapper.INSTANCE.toDto(task);
} }
public TaskDto updateTask(Task taskUpdate) { public TaskDto updateTask(Long trainingDefinitionId, Long phaseId, TaskUpdateDto taskUpdateDto) {
Optional<Task> persistedTask = taskRepository.findById(taskUpdate.getId()); Task taskUpdate = BeanMapper.INSTANCE.toEntity(taskUpdateDto);
if (persistedTask.isEmpty()) { Task persistedTask = taskRepository.findById(taskUpdate.getId())
// TODO return 404 .orElseThrow(() -> new RuntimeException("Task was not found"));
LOG.error("No task found with ID {}.", taskUpdate.getId()); // TODO throw proper exception once kypo2-training is migrated
return new TaskDto();
}
taskUpdate.setPhaseLevel(persistedTask.get().getPhaseLevel()); // TODO add check to trainingDefinitionId and phaseId (field structure will be probably changed)
taskUpdate.setTrainingDefinitionId(persistedTask.get().getTrainingDefinitionId());
taskUpdate.setOrder(persistedTask.get().getOrder()); taskUpdate.setPhaseLevel(persistedTask.getPhaseLevel());
taskUpdate.setTrainingDefinitionId(persistedTask.getTrainingDefinitionId());
taskUpdate.setOrder(persistedTask.getOrder());
Task savedEntity = taskRepository.save(taskUpdate); Task savedEntity = taskRepository.save(taskUpdate);
return BeanMapper.INSTANCE.toDto(savedEntity); return BeanMapper.INSTANCE.toDto(savedEntity);
} }
public void removeTaskLevel(Long id) { public void removeTask(Long trainingDefinitionId, Long phaseId, Long taskId) {
taskRepository.deleteById(id); Task task = taskRepository.findById(taskId)
.orElseThrow(() -> new RuntimeException("Task was not found"));
// TODO throw proper exception once kypo2-training is migrated
// TODO add check to trainingDefinitionId and phaseId (field structure will be probably changed)
taskRepository.decreaseOrderAfterTaskWasDeleted(phaseId, task.getOrder());
taskRepository.delete(task);
} }
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment