Merge branch '76-students-tags-filter' into 'dev'
Resolve "Фильтр задач по типу (тегам)" Closes #77, #75, and #76 See merge request romanov73/ng-tracker!61
This commit is contained in:
commit
bb2518e5f4
@ -5,13 +5,16 @@ import org.springframework.ui.ModelMap;
|
|||||||
import org.springframework.validation.Errors;
|
import org.springframework.validation.Errors;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||||
|
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.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
import ru.ulstu.deadline.model.Deadline;
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
import ru.ulstu.students.model.Task;
|
import ru.ulstu.students.model.Task;
|
||||||
import ru.ulstu.students.model.TaskDto;
|
import ru.ulstu.students.model.TaskDto;
|
||||||
|
import ru.ulstu.students.model.TaskFilterDto;
|
||||||
import ru.ulstu.students.service.TaskService;
|
import ru.ulstu.students.service.TaskService;
|
||||||
|
import ru.ulstu.tags.model.Tag;
|
||||||
import springfox.documentation.annotations.ApiIgnore;
|
import springfox.documentation.annotations.ApiIgnore;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
@ -35,16 +38,16 @@ public class TaskController {
|
|||||||
this.taskService = taskService;
|
this.taskService = taskService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@GetMapping("/tasks")
|
|
||||||
public void getTasks(ModelMap modelMap) {
|
|
||||||
modelMap.put("tasks", taskService.findAllDto());
|
|
||||||
}
|
|
||||||
|
|
||||||
@GetMapping("/dashboard")
|
@GetMapping("/dashboard")
|
||||||
public void getDashboard(ModelMap modelMap) {
|
public void getDashboard(ModelMap modelMap) {
|
||||||
modelMap.put("tasks", taskService.findAllDto());
|
modelMap.put("tasks", taskService.findAllDto());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/tasks")
|
||||||
|
public void getTask(ModelMap modelMap) {
|
||||||
|
modelMap.put("filteredTasks", new TaskFilterDto(taskService.findAllDto(), null, null, null));
|
||||||
|
}
|
||||||
|
|
||||||
@GetMapping("/task")
|
@GetMapping("/task")
|
||||||
public void getTask(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
|
public void getTask(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
|
||||||
if (id != null && id > 0) {
|
if (id != null && id > 0) {
|
||||||
@ -54,6 +57,14 @@ public class TaskController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping("/tasks")
|
||||||
|
public void filterTasks(@Valid TaskFilterDto taskFilterDto, ModelMap modelMap) {
|
||||||
|
modelMap.put("filteredTasks", new TaskFilterDto(taskService.filter(taskFilterDto),
|
||||||
|
taskFilterDto.getStatus(),
|
||||||
|
taskFilterDto.getTag(),
|
||||||
|
taskFilterDto.getOrder()));
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/task", params = "save")
|
@PostMapping(value = "/task", params = "save")
|
||||||
public String save(@Valid TaskDto taskDto, Errors errors) throws IOException {
|
public String save(@Valid TaskDto taskDto, Errors errors) throws IOException {
|
||||||
filterEmptyDeadlines(taskDto);
|
filterEmptyDeadlines(taskDto);
|
||||||
@ -77,11 +88,23 @@ public class TaskController {
|
|||||||
return TASK_PAGE;
|
return TASK_PAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/delete/{task-id}")
|
||||||
|
public String delete(@PathVariable("task-id") Integer taskId) throws IOException {
|
||||||
|
taskService.delete(taskId);
|
||||||
|
return String.format(REDIRECT_TO, TASKS_PAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@ModelAttribute("allStatuses")
|
@ModelAttribute("allStatuses")
|
||||||
public List<Task.TaskStatus> getTaskStatuses() {
|
public List<Task.TaskStatus> getTaskStatuses() {
|
||||||
return taskService.getTaskStatuses();
|
return taskService.getTaskStatuses();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("allTags")
|
||||||
|
public List<Tag> getTags() {
|
||||||
|
return taskService.getTags();
|
||||||
|
}
|
||||||
|
|
||||||
private void filterEmptyDeadlines(TaskDto taskDto) {
|
private void filterEmptyDeadlines(TaskDto taskDto) {
|
||||||
taskDto.setDeadlines(taskDto.getDeadlines().stream()
|
taskDto.setDeadlines(taskDto.getDeadlines().stream()
|
||||||
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
||||||
|
@ -50,7 +50,7 @@ public class Task extends BaseEntity {
|
|||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@Enumerated(value = EnumType.STRING)
|
@Enumerated(value = EnumType.STRING)
|
||||||
private ru.ulstu.students.model.Task.TaskStatus status = TaskStatus.IN_WORK;
|
private TaskStatus status = TaskStatus.IN_WORK;
|
||||||
|
|
||||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
@JoinColumn(name = "task_id", unique = true)
|
@JoinColumn(name = "task_id", unique = true)
|
||||||
|
@ -26,7 +26,7 @@ public class TaskDto {
|
|||||||
private Date createDate;
|
private Date createDate;
|
||||||
private Date updateDate;
|
private Date updateDate;
|
||||||
private Set<Integer> tagIds;
|
private Set<Integer> tagIds;
|
||||||
private List<Tag> tags;
|
private List<Tag> tags = new ArrayList<>();
|
||||||
|
|
||||||
public TaskDto() {
|
public TaskDto() {
|
||||||
deadlines.add(new Deadline());
|
deadlines.add(new Deadline());
|
||||||
|
54
src/main/java/ru/ulstu/students/model/TaskFilterDto.java
Normal file
54
src/main/java/ru/ulstu/students/model/TaskFilterDto.java
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
package ru.ulstu.students.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TaskFilterDto {
|
||||||
|
|
||||||
|
private List<TaskDto> tasks;
|
||||||
|
private Task.TaskStatus status;
|
||||||
|
private Integer tagId;
|
||||||
|
private String order;
|
||||||
|
|
||||||
|
public TaskFilterDto(List<TaskDto> tasks, Task.TaskStatus status, Integer tagId, String order) {
|
||||||
|
this.tasks = tasks;
|
||||||
|
this.status = status;
|
||||||
|
this.tagId = tagId;
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskFilterDto() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TaskDto> getTasks() {
|
||||||
|
return tasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTasks(List<TaskDto> tasks) {
|
||||||
|
this.tasks = tasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task.TaskStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Task.TaskStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getTag() {
|
||||||
|
return tagId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTag(Integer tagId) {
|
||||||
|
this.tagId = tagId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOrder() {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOrder(String order) {
|
||||||
|
this.order = order;
|
||||||
|
}
|
||||||
|
}
|
@ -1,7 +1,18 @@
|
|||||||
package ru.ulstu.students.repository;
|
package ru.ulstu.students.repository;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
import ru.ulstu.students.model.Task;
|
import ru.ulstu.students.model.Task;
|
||||||
|
import ru.ulstu.tags.model.Tag;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface TaskRepository extends JpaRepository<Task, Integer> {
|
public interface TaskRepository extends JpaRepository<Task, Integer> {
|
||||||
|
|
||||||
|
@Query("SELECT t FROM Task t WHERE (t.status = :status OR :status IS NULL) AND (:tag IS NULL OR :tag MEMBER OF t.tags) ORDER BY create_date DESC")
|
||||||
|
List<Task> filterNew(@Param("status") Task.TaskStatus status, @Param("tag") Tag tag);
|
||||||
|
|
||||||
|
@Query("SELECT t FROM Task t WHERE (t.status = :status OR :status IS NULL) AND (:tag IS NULL OR :tag MEMBER OF t.tags) ORDER BY create_date ASC")
|
||||||
|
List<Task> filterOld(@Param("status") Task.TaskStatus status, @Param("tag") Tag tag);
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,15 @@
|
|||||||
package ru.ulstu.students.service;
|
package ru.ulstu.students.service;
|
||||||
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.data.domain.Sort;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import ru.ulstu.deadline.service.DeadlineService;
|
import ru.ulstu.deadline.service.DeadlineService;
|
||||||
import ru.ulstu.students.model.Task;
|
import ru.ulstu.students.model.Task;
|
||||||
import ru.ulstu.students.model.TaskDto;
|
import ru.ulstu.students.model.TaskDto;
|
||||||
|
import ru.ulstu.students.model.TaskFilterDto;
|
||||||
import ru.ulstu.students.repository.TaskRepository;
|
import ru.ulstu.students.repository.TaskRepository;
|
||||||
|
import ru.ulstu.tags.model.Tag;
|
||||||
import ru.ulstu.tags.service.TagService;
|
import ru.ulstu.tags.service.TagService;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -27,15 +30,15 @@ public class TaskService {
|
|||||||
private final DeadlineService deadlineService;
|
private final DeadlineService deadlineService;
|
||||||
private final TagService tagService;
|
private final TagService tagService;
|
||||||
|
|
||||||
public TaskService(TaskRepository grantRepository,
|
public TaskService(TaskRepository taskRepository,
|
||||||
DeadlineService deadlineService, TagService tagService) {
|
DeadlineService deadlineService, TagService tagService) {
|
||||||
this.taskRepository = grantRepository;
|
this.taskRepository = taskRepository;
|
||||||
this.deadlineService = deadlineService;
|
this.deadlineService = deadlineService;
|
||||||
this.tagService = tagService;
|
this.tagService = tagService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Task> findAll() {
|
public List<Task> findAll() {
|
||||||
return taskRepository.findAll();
|
return taskRepository.findAll(new Sort(Sort.Direction.DESC, "createDate"));
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<TaskDto> findAllDto() {
|
public List<TaskDto> findAllDto() {
|
||||||
@ -48,6 +51,18 @@ public class TaskService {
|
|||||||
return new TaskDto(taskRepository.findOne(id));
|
return new TaskDto(taskRepository.findOne(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<TaskDto> filter(TaskFilterDto filterDto) {
|
||||||
|
if (filterDto.getOrder().compareTo("new") == 0) {
|
||||||
|
return convert(taskRepository.filterNew(
|
||||||
|
filterDto.getStatus(),
|
||||||
|
filterDto.getTag() == null ? null : tagService.findById(filterDto.getTag())), TaskDto::new);
|
||||||
|
} else {
|
||||||
|
return convert(taskRepository.filterOld(
|
||||||
|
filterDto.getStatus(),
|
||||||
|
filterDto.getTag() == null ? null : tagService.findById(filterDto.getTag())), TaskDto::new);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public Integer create(TaskDto taskDto) throws IOException {
|
public Integer create(TaskDto taskDto) throws IOException {
|
||||||
Task newTask = copyFromDto(new Task(), taskDto);
|
Task newTask = copyFromDto(new Task(), taskDto);
|
||||||
@ -76,8 +91,10 @@ public class TaskService {
|
|||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void delete(Integer taskId) throws IOException {
|
public void delete(Integer taskId) throws IOException {
|
||||||
Task task = taskRepository.findOne(taskId);
|
if (taskRepository.exists(taskId)) {
|
||||||
taskRepository.delete(task);
|
taskRepository.delete(taskId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void save(TaskDto taskDto) throws IOException {
|
public void save(TaskDto taskDto) throws IOException {
|
||||||
@ -92,4 +109,8 @@ public class TaskService {
|
|||||||
return Arrays.asList(Task.TaskStatus.values());
|
return Arrays.asList(Task.TaskStatus.values());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Tag> getTags() {
|
||||||
|
return tagService.getTags();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -50,4 +50,12 @@ public class TagService {
|
|||||||
return newTag;
|
return newTag;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Tag> getTags() {
|
||||||
|
return tagRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tag findById(Integer tagId) {
|
||||||
|
return tagRepository.findOne(tagId);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -13,6 +13,21 @@
|
|||||||
cursor: text;
|
cursor: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.filter .bootstrap-select{
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-option-inner-inner{
|
||||||
|
font-size: 12px;
|
||||||
|
text-transform: uppercase;
|
||||||
|
font-weight: normal;
|
||||||
|
line-height: 25px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.sorting .bootstrap-select{
|
||||||
|
margin-bottom: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
.input-tag-name {
|
.input-tag-name {
|
||||||
border: none;
|
border: none;
|
||||||
box-shadow: none;
|
box-shadow: none;
|
||||||
|
@ -90,7 +90,7 @@ $(document).ready(function () {
|
|||||||
' <div class="modal-dialog modal-sm">\n' +
|
' <div class="modal-dialog modal-sm">\n' +
|
||||||
' <div class="modal-content">\n' +
|
' <div class="modal-content">\n' +
|
||||||
' <div class="modal-header">\n' +
|
' <div class="modal-header">\n' +
|
||||||
' <h8 class="modal-title" id="myModalLabel">Удалить статью?</h8>\n' +
|
' <h8 class="modal-title" id="myModalLabel">Удалить задачу?</h8>\n' +
|
||||||
' <button type="button" class="close" data-dismiss="modal" aria-label="Закрыть"><span\n' +
|
' <button type="button" class="close" data-dismiss="modal" aria-label="Закрыть"><span\n' +
|
||||||
' aria-hidden="true">×</span></button>\n' +
|
' aria-hidden="true">×</span></button>\n' +
|
||||||
' </div>\n' +
|
' </div>\n' +
|
||||||
|
@ -242,6 +242,8 @@
|
|||||||
/*]]>*/
|
/*]]>*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function updateAuthors() {
|
function updateAuthors() {
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
</div>
|
</div>
|
||||||
<hr/>
|
<hr/>
|
||||||
<div class="row justify-content-center" id="dashboard">
|
<div class="row justify-content-center" id="dashboard">
|
||||||
<div th:replace="students/fragments/taskDashboardFragment"/>
|
<th:block th:each="task : ${tasks}">
|
||||||
<!--<th:block th:each="task : ${tasks}">-->
|
<div th:replace="students/fragments/taskDashboardFragment :: taskDashboard(task=${task})"/>
|
||||||
<!--<div th:replace="students/fragments/taskDashboardFragment :: taskDashboard(task=${task})"/>-->
|
</th:block>
|
||||||
<!--</th:block>-->
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
@ -6,9 +6,6 @@
|
|||||||
<body>
|
<body>
|
||||||
<span th:fragment="taskStatus (taskStatus)" class="fa-stack fa-1x">
|
<span th:fragment="taskStatus (taskStatus)" class="fa-stack fa-1x">
|
||||||
<th:block th:switch="${taskStatus.name()}">
|
<th:block th:switch="${taskStatus.name()}">
|
||||||
<!--<div th:case="'ATTENTION'">-->
|
|
||||||
<!--<i class="fa fa-circle fa-stack-2x text-warning"></i>-->
|
|
||||||
<!--</div>-->
|
|
||||||
<div th:case="'IN_WORK'">
|
<div th:case="'IN_WORK'">
|
||||||
<i class="fa fa-circle fa-stack-2x text-primary"></i>
|
<i class="fa fa-circle fa-stack-2x text-primary"></i>
|
||||||
</div>
|
</div>
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container" layout:fragment="content">
|
<div class="container" layout:fragment="content">
|
||||||
<form id="tasks-form" method="post" th:action="@{'/tasks/tasks'}">
|
<form id="tasks-form" method="post" th:action="@{'/students/tasks'}">
|
||||||
<input th:type="hidden" name="taskDeleteId" id="taskDeleteId"/>
|
<input th:type="hidden" name="taskDeleteId" id="taskDeleteId"/>
|
||||||
<section id="tasks">
|
<section id="tasks">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
@ -20,27 +20,43 @@
|
|||||||
<hr/>
|
<hr/>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-9 col-sm-12">
|
<div class="col-md-9 col-sm-12">
|
||||||
<th:block th:each="task : ${tasks}">
|
<th:block th:each="task : ${filteredTasks.tasks}">
|
||||||
<div th:replace="students/fragments/taskLineFragment :: taskLine(task=${task})"/>
|
<div th:replace="students/fragments/taskLineFragment :: taskLine(task=${task})"/>
|
||||||
</th:block>
|
</th:block>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 col-sm-12">
|
<div class="col-md-3 col-sm-12">
|
||||||
|
<div class="sorting">
|
||||||
|
<h5>Сортировать:</h5>
|
||||||
|
<select class="form-control selectpicker" size="auto" th:field="${filteredTasks.order}"
|
||||||
|
id="order"
|
||||||
|
onchange="this.form.submit();">
|
||||||
|
<option th:value="new">
|
||||||
|
Сначала новые
|
||||||
|
</option>
|
||||||
|
<option th:value="old">
|
||||||
|
Сначала старые
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="filter">
|
<div class="filter">
|
||||||
<h5>Фильтр:</h5>
|
<h5>Фильтр:</h5>
|
||||||
<select class="form-control" id="status"
|
<select class="form-control selectpicker" size="auto" th:field="${filteredTasks.status}"
|
||||||
|
id="status"
|
||||||
onchange="this.form.submit();">
|
onchange="this.form.submit();">
|
||||||
<option value="">Все статусы</option>
|
<option value="">Все статусы</option>
|
||||||
<!--<option th:each="author: ${allAuthors}" th:value="${author.id}"-->
|
<option th:each="status: ${allStatuses}" th:value="${status}"
|
||||||
<!--th:text="${author.lastName}">lastName-->
|
th:text="${status.statusName}">
|
||||||
<!--</option>-->
|
status
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<select class="form-control selectpicker" size="auto" data-live-search="true"
|
||||||
|
th:field="${filteredTasks.tag}" id="tags"
|
||||||
|
onchange="this.form.submit();">
|
||||||
|
<option value="">Все теги</option>
|
||||||
|
<option th:each="tag: ${allTags}" th:value="${tag.id}"
|
||||||
|
th:text="${tag.tagName}">tag
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
<select class="form-control" id="tags"
|
|
||||||
onchange="this.form.submit();">
|
|
||||||
<option value="">Все типы</option>
|
|
||||||
<!--<option th:each="year: ${allYears}" th:value="${year}"-->
|
|
||||||
<!--th:text="${year}">year-->
|
|
||||||
<!--</option>-->
|
|
||||||
</select>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user