#42 Add leader and authors
This commit is contained in:
parent
e74fcb316c
commit
8a7117d713
@ -13,6 +13,7 @@ import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.grant.model.Grant;
|
||||
import ru.ulstu.grant.model.GrantDto;
|
||||
import ru.ulstu.grant.service.GrantService;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
@ -57,9 +58,13 @@ public class GrantController {
|
||||
@PostMapping(value = "/grant", params = "save")
|
||||
public String save(@Valid GrantDto grantDto, Errors errors) throws IOException {
|
||||
filterEmptyDeadlines(grantDto);
|
||||
// фильтр авторов
|
||||
if (grantDto.getDeadlines().isEmpty()) {
|
||||
errors.rejectValue("deadlines", "errorCode", "Не может быть пустым");
|
||||
}
|
||||
// if (grantDto.getLeader().getId().equals(null)) {
|
||||
// errors.rejectValue("leader", "errorCode", "Укажите руководителя");
|
||||
// }
|
||||
hasErrors(errors, GRANT_PAGE);
|
||||
grantService.save(grantDto);
|
||||
return String.format(REDIRECT_TO, GRANTS_PAGE);
|
||||
@ -91,6 +96,11 @@ public class GrantController {
|
||||
return grantService.getGrantStatuses();
|
||||
}
|
||||
|
||||
@ModelAttribute("allAuthors")
|
||||
public List<User> getAllAuthors() {
|
||||
return grantService.getGrantAuthors();
|
||||
}
|
||||
|
||||
private void filterEmptyDeadlines(GrantDto grantDto) {
|
||||
grantDto.setDeadlines(grantDto.getDeadlines().stream()
|
||||
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
||||
|
@ -2,28 +2,35 @@ package ru.ulstu.grant.model;
|
||||
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
import ru.ulstu.core.model.BaseEntity;
|
||||
import ru.ulstu.core.model.UserContainer;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.file.model.FileData;
|
||||
import ru.ulstu.project.model.Project;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Table(name = "grants")
|
||||
public class Grant extends BaseEntity {
|
||||
public class Grant extends BaseEntity implements UserContainer {
|
||||
public enum GrantStatus {
|
||||
APPLICATION("Заявка"),
|
||||
ON_COMPETITION("Отправлен на конкурс"),
|
||||
@ -52,6 +59,7 @@ public class Grant extends BaseEntity {
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "grant_id")
|
||||
@OrderBy("date")
|
||||
private List<Deadline> deadlines = new ArrayList<>();
|
||||
|
||||
//Описание гранта
|
||||
@ -67,6 +75,14 @@ public class Grant extends BaseEntity {
|
||||
@JoinColumn(name = "project_id")
|
||||
private Project project;
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
private Set<User> authors = new HashSet<>();
|
||||
|
||||
@NotNull
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "leader_id")
|
||||
private User leader;
|
||||
|
||||
public GrantStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
@ -115,6 +131,27 @@ public class Grant extends BaseEntity {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public Set<User> getAuthors() {
|
||||
return authors;
|
||||
}
|
||||
|
||||
public void setAuthors(Set<User> authors) {
|
||||
this.authors = authors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<User> getUsers() {
|
||||
return getAuthors();
|
||||
}
|
||||
|
||||
public User getLeader() {
|
||||
return leader;
|
||||
}
|
||||
|
||||
public void setLeader(User leader) {
|
||||
this.leader = leader;
|
||||
}
|
||||
|
||||
public Optional<Deadline> getNextDeadline() {
|
||||
return deadlines
|
||||
.stream()
|
||||
|
@ -2,14 +2,22 @@ package ru.ulstu.grant.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hibernate.validator.constraints.NotEmpty;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.project.model.ProjectDto;
|
||||
import ru.ulstu.user.model.UserDto;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
||||
|
||||
public class GrantDto {
|
||||
private final static int MAX_AUTHORS_LENGTH = 60;
|
||||
|
||||
private Integer id;
|
||||
@NotEmpty
|
||||
private String title;
|
||||
@ -18,6 +26,9 @@ public class GrantDto {
|
||||
private String comment;
|
||||
private String applicationFileName;
|
||||
private ProjectDto project;
|
||||
private Set<Integer> authorIds;
|
||||
private Set<UserDto> authors;
|
||||
private Integer leaderId;
|
||||
|
||||
public GrantDto() {
|
||||
deadlines.add(new Deadline());
|
||||
@ -29,7 +40,10 @@ public class GrantDto {
|
||||
@JsonProperty("status") Grant.GrantStatus status,
|
||||
@JsonProperty("deadlines") List<Deadline> deadlines,
|
||||
@JsonProperty("comment") String comment,
|
||||
@JsonProperty("project") ProjectDto project) {
|
||||
@JsonProperty("project") ProjectDto project,
|
||||
@JsonProperty("authorIds") Set<Integer> authorIds,
|
||||
@JsonProperty("authors") Set<UserDto> authors,
|
||||
@JsonProperty("leader") Integer leaderId) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.status = status;
|
||||
@ -37,6 +51,8 @@ public class GrantDto {
|
||||
this.comment = comment;
|
||||
this.applicationFileName = null;
|
||||
this.project = project;
|
||||
this.authors = authors;
|
||||
this.leaderId = leaderId;
|
||||
}
|
||||
|
||||
public GrantDto(Grant grant) {
|
||||
@ -47,6 +63,9 @@ public class GrantDto {
|
||||
this.comment = grant.getComment();
|
||||
this.project = grant.getProject() == null ? null : new ProjectDto(grant.getProject());
|
||||
this.applicationFileName = grant.getApplication() == null ? null : grant.getApplication().getName();
|
||||
this.authorIds = convert(grant.getAuthors(), user -> user.getId());
|
||||
this.authors = convert(grant.getAuthors(), UserDto::new);
|
||||
this.leaderId = grant.getLeader().getId();
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
@ -104,4 +123,35 @@ public class GrantDto {
|
||||
public void setApplicationFileName(String applicationFileName) {
|
||||
this.applicationFileName = applicationFileName;
|
||||
}
|
||||
|
||||
public Set<Integer> getAuthorIds() {
|
||||
return authorIds;
|
||||
}
|
||||
|
||||
public void setAuthorIds(Set<Integer> authorIds) {
|
||||
this.authorIds = authorIds;
|
||||
}
|
||||
|
||||
public Set<UserDto> getAuthors() {
|
||||
return authors;
|
||||
}
|
||||
|
||||
public void setAuthors(Set<UserDto> authors) {
|
||||
this.authors = authors;
|
||||
}
|
||||
|
||||
public String getAuthorsString() {
|
||||
return StringUtils.abbreviate(authors
|
||||
.stream()
|
||||
.map(author -> author.getLastName())
|
||||
.collect(Collectors.joining(", ")), MAX_AUTHORS_LENGTH);
|
||||
}
|
||||
|
||||
public Integer getLeaderId() {
|
||||
return leaderId;
|
||||
}
|
||||
|
||||
public void setLeaderId(Integer leaderId) {
|
||||
this.leaderId = leaderId;
|
||||
}
|
||||
}
|
||||
|
@ -12,6 +12,8 @@ import ru.ulstu.grant.repository.GrantRepository;
|
||||
import ru.ulstu.project.model.Project;
|
||||
import ru.ulstu.project.model.ProjectDto;
|
||||
import ru.ulstu.project.service.ProjectService;
|
||||
import ru.ulstu.user.model.User;
|
||||
import ru.ulstu.user.service.UserService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@ -30,15 +32,18 @@ public class GrantService {
|
||||
private final ProjectService projectService;
|
||||
private final DeadlineService deadlineService;
|
||||
private final FileService fileService;
|
||||
private final UserService userService;
|
||||
|
||||
public GrantService(GrantRepository grantRepository,
|
||||
FileService fileService,
|
||||
DeadlineService deadlineService,
|
||||
ProjectService projectService) {
|
||||
ProjectService projectService,
|
||||
UserService userService) {
|
||||
this.grantRepository = grantRepository;
|
||||
this.projectService = projectService;
|
||||
this.fileService = fileService;
|
||||
this.deadlineService = deadlineService;
|
||||
this.projectService = projectService;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
public List<Grant> findAll() {
|
||||
@ -73,6 +78,13 @@ public class GrantService {
|
||||
if (grantDto.getApplicationFileName() != null) {
|
||||
grant.setApplication(fileService.createFileFromTmp(grantDto.getApplicationFileName()));
|
||||
}
|
||||
grant.getAuthors().clear();
|
||||
if (grantDto.getAuthorIds() != null && !grantDto.getAuthorIds().isEmpty()) {
|
||||
grantDto.getAuthorIds().forEach(authorIds -> grant.getAuthors().add(userService.findById(authorIds)));
|
||||
}
|
||||
if (grantDto.getLeaderId() != null) {
|
||||
grant.setLeader(userService.findById(grantDto.getLeaderId()));
|
||||
}
|
||||
return grant;
|
||||
}
|
||||
|
||||
@ -84,7 +96,6 @@ public class GrantService {
|
||||
@Transactional
|
||||
public Integer update(GrantDto grantDto) throws IOException {
|
||||
Grant grant = grantRepository.findOne(grantDto.getId());
|
||||
Grant.GrantStatus oldStatus = grant.getStatus();
|
||||
if (grantDto.getApplicationFileName() != null && grant.getApplication() != null) {
|
||||
fileService.deleteFile(grant.getApplication());
|
||||
}
|
||||
@ -98,7 +109,6 @@ public class GrantService {
|
||||
if (grant.getApplication() != null) {
|
||||
fileService.deleteFile(grant.getApplication());
|
||||
}
|
||||
//возможно при удалении гранта будет удаляться и проект, к нему привязанный
|
||||
grantRepository.delete(grant);
|
||||
}
|
||||
|
||||
@ -107,13 +117,15 @@ public class GrantService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Grant create(String title, Project projectId, Date deadlineDate) {
|
||||
public Grant create(String title, Project projectId, Date deadlineDate, User user) {
|
||||
Grant grant = new Grant();
|
||||
grant.setTitle(title);
|
||||
grant.setComment("Комментарий к гранту 1");
|
||||
grant.setProject(projectId);
|
||||
grant.setStatus(APPLICATION);
|
||||
grant.getDeadlines().add(new Deadline(deadlineDate, "первый дедлайн"));
|
||||
grant.getAuthors().add(user);
|
||||
grant.setLeader(user);
|
||||
grant = grantRepository.save(grant);
|
||||
return grant;
|
||||
}
|
||||
@ -125,4 +137,8 @@ public class GrantService {
|
||||
update(grantDto);
|
||||
}
|
||||
}
|
||||
|
||||
public List<User> getGrantAuthors() {
|
||||
return userService.findAll();
|
||||
}
|
||||
}
|
||||
|
26
src/main/resources/db/changelog-20190402_000000-schema.xml
Normal file
26
src/main/resources/db/changelog-20190402_000000-schema.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||
<changeSet author="tanya" id="20190402_000000-1">
|
||||
<addColumn tableName="grants">
|
||||
<column name="leader_id" type="integer"></column>
|
||||
</addColumn>
|
||||
<addForeignKeyConstraint baseTableName="grants" baseColumnNames="leader_id"
|
||||
constraintName="fk_grants_leader_id" referencedTableName="users"
|
||||
referencedColumnNames="id"/>
|
||||
</changeSet>
|
||||
|
||||
<changeSet author="tanya" id="20190402_000000-2">
|
||||
<createTable tableName="grants_authors">
|
||||
<column name="grant_id" type="integer"/>
|
||||
<column name="author_id" type="integer"/>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseTableName="grants_authors" baseColumnNames="grant_id"
|
||||
constraintName="fk_grants_grants_authors" referencedTableName="grant"
|
||||
referencedColumnNames="id"/>
|
||||
<addForeignKeyConstraint baseTableName="grants_authors" baseColumnNames="author_id"
|
||||
constraintName="fk_user_grants_authors" referencedTableName="users"
|
||||
referencedColumnNames="id"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
12
src/main/resources/public/css/grant.css
Normal file
12
src/main/resources/public/css/grant.css
Normal file
@ -0,0 +1,12 @@
|
||||
.div-deadline-date {
|
||||
padding-right: 0px;
|
||||
}
|
||||
|
||||
.form-deadline-date{
|
||||
padding-right: 3px;
|
||||
}
|
||||
|
||||
.div-deadline-description{
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
@ -9,7 +9,7 @@
|
||||
<span th:replace="grants/fragments/grantStatusFragment :: grantStatus(grantStatus=${grant.status})"/>
|
||||
<a th:href="@{'grant?id='+${grant.id}}">
|
||||
<span class="h6" th:text="${grant.title}"/>
|
||||
<span class="text-muted" th:text="${grant.comment}"/>
|
||||
<span class="text-muted" th:text="${grant.authorsString}"/>
|
||||
</a>
|
||||
<input class="id-class" type="hidden" th:value="${grant.id}"/>
|
||||
<a class="remove-paper pull-right d-none" th:href="@{'/grants/delete/'+${grant.id}}"
|
||||
|
@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8"/>
|
||||
</head>
|
||||
<body>
|
||||
<span th:fragment="paperStatus (paperStatus)" class="fa-stack fa-1x">
|
||||
<span th:fragment="grantStatus (grantStatus)" class="fa-stack fa-1x">
|
||||
<th:block th:switch="${grantStatus.name()}">
|
||||
<div th:case="'APPLICATION'">
|
||||
<i class="fa fa-circle fa-stack-2x text-draft"></i>
|
||||
|
@ -3,7 +3,7 @@
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorator="default" xmlns:th="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/html">
|
||||
<head>
|
||||
|
||||
<link rel="stylesheet" href="../css/grant.css"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
<div th:replace="grants/fragments/grantNavigationFragment"/>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<form id="grant-form" method="post" th:action="@{'/grants/grant?id='+ *{id == null ? '' : id} + ''}"
|
||||
@ -42,20 +43,22 @@
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="comment">Комментарий:</label>
|
||||
<textarea class="form-control" rows="3" id="comment"
|
||||
th:field="*{comment}"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>Дедлайны показателей:</label>
|
||||
<div class="row" th:each="deadline, rowStat : *{deadlines}">
|
||||
<input type="hidden" th:field="*{deadlines[__${rowStat.index}__].id}"/>
|
||||
<div class="col-6">
|
||||
<input type="date" class="form-control" name="deadline"
|
||||
<div class="col-6 div-deadline-date">
|
||||
<input type="date" class="form-control form-deadline-date" name="deadline"
|
||||
th:field="*{deadlines[__${rowStat.index}__].date}"/>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<div class="col-4 div-deadline-description">
|
||||
<input class="form-control" type="text" placeholder="Описание"
|
||||
th:field="*{deadlines[__${rowStat.index}__].description}"/>
|
||||
</div>
|
||||
@ -72,8 +75,8 @@
|
||||
class="alert alert-danger">Incorrect title</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="submit" id="addDeadline" name="addDeadline" class="btn btn-primary" value="Добавить
|
||||
дедлайн"/>
|
||||
<input type="submit" id="addDeadline" name="addDeadline" class="btn btn-primary"
|
||||
value="Добавить дедлайн"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@ -82,15 +85,77 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-6 col-sm-12">
|
||||
<label data-toggle="collapse" href="#collapse-filter"
|
||||
aria-expanded="false" aria-controls="collapse-filter">Фильтр рабочей
|
||||
группы</label>
|
||||
<div class="form-check collapse" id="collapse-filter">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<input class="form-check-input" type="checkbox" id="f1"/>
|
||||
<label class="form-check-label" for="f1">Был руководителем проекта</label>
|
||||
</div>
|
||||
<div class="col">
|
||||
<input class="form-check-input" type="checkbox" id="f2"/>
|
||||
<label class="form-check-label" for="f2">Младше 35 лет</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<input class="form-check-input" type="checkbox" id="f3"/>
|
||||
<label class="form-check-label" for="f3">Cтепень к.т.н.</label> <br/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<input class="form-check-input" type="checkbox" id="f4"/>
|
||||
<label class="form-check-label" for="f4">Более 3-х публикаций в
|
||||
scopus</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<input class="form-check-input" type="checkbox" id="f5"/>
|
||||
<label class="form-check-label" for="f5">Наличие ВАК статей</label> <br/>
|
||||
</div>
|
||||
<div class="col">
|
||||
<input class="form-check-input" type="checkbox" id="f6"/>
|
||||
<label class="form-check-label" for="f6">Наименьшая загруженность</label>
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Руководитель проекта:</label>
|
||||
<select class="form-control" th:field="*{leaderId}" id="leader">
|
||||
<option th:each="leader : ${allAuthors}" th:value="${leader.id}"
|
||||
th:text="${leader.lastName}"> Руководитель
|
||||
</option>
|
||||
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Участники гранта:</label>
|
||||
<select class="selectpicker form-control" multiple="true" data-live-search="true"
|
||||
title="-- Выберите участников --"
|
||||
th:field="*{authorIds}">
|
||||
<option th:each="author: ${allAuthors}" th:value="${author.id}"
|
||||
th:text="${author.lastName}"> Участник
|
||||
</option>
|
||||
</select>
|
||||
<p th:if="${#fields.hasErrors('authorIds')}" th:errors="*{authorIds}"
|
||||
class="alert alert-danger">Incorrect member</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Список статей:</label>
|
||||
<p><a href="./#" class="btn btn-primary" ><i class="fa fa-plus-circle" aria-hidden="true">
|
||||
<p><a href="./#" class="btn btn-primary"><i class="fa fa-plus-circle"
|
||||
aria-hidden="true">
|
||||
</i> Добавить статью</a></p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div th:if="*{project} == null">
|
||||
<input type="submit" name="createProject" class="btn btn-primary"
|
||||
<input type="submit" name="createProject" class="btn btn-primary"
|
||||
value="Добавить проект"/>
|
||||
</div>
|
||||
<input type = "hidden" th:field="*{project.id}"/>
|
||||
|
Loading…
Reference in New Issue
Block a user