Merge branch '42--2' into 'dev'
Resolve "Форма добавления и фильтра участников гранта" Closes #42 See merge request romanov73/ng-tracker!44
This commit is contained in:
commit
5a55e3cfc8
@ -1,46 +1,46 @@
|
|||||||
## Краткое описание задачи
|
## Краткое описание задачи
|
||||||
|
|
||||||
Что требуется сделать
|
Что требуется сделать
|
||||||
|
|
||||||
|
|
||||||
## `Опционально` Список верстаемых страниц
|
## `Опционально` Список верстаемых страниц
|
||||||
|
|
||||||
Будут затронуты страницы:
|
Будут затронуты страницы:
|
||||||
* page1.html
|
* page1.html
|
||||||
* page2.html
|
* page2.html
|
||||||
* page3.html
|
* page3.html
|
||||||
|
|
||||||
## `Опционально` Список затрагиваемых модулей
|
## `Опционально` Список затрагиваемых модулей
|
||||||
|
|
||||||
При реализации задачи потребуется также реализовать методы контроллера
|
При реализации задачи потребуется также реализовать методы контроллера
|
||||||
|
|
||||||
|
|
||||||
## `Опционально` Список реализуемых функций
|
## `Опционально` Список реализуемых функций
|
||||||
|
|
||||||
После выполнения задачи станет доступным:
|
После выполнения задачи станет доступным:
|
||||||
* просмотр `entity_name`
|
* просмотр `entity_name`
|
||||||
* редактирование `entity_name`
|
* редактирование `entity_name`
|
||||||
* валидация `entity_name`
|
* валидация `entity_name`
|
||||||
|
|
||||||
## `Опционально` Сценарии работы
|
## `Опционально` Сценарии работы
|
||||||
|
|
||||||
Сценарий просмотра:
|
Сценарий просмотра:
|
||||||
1. Зайти на главную страницу приложения
|
1. Зайти на главную страницу приложения
|
||||||
2. Перейти в раздел `section_name`
|
2. Перейти в раздел `section_name`
|
||||||
3. Перейти к списку `entity_name`
|
3. Перейти к списку `entity_name`
|
||||||
4. Выбрать нужную `entity_name` и нажать на нее
|
4. Выбрать нужную `entity_name` и нажать на нее
|
||||||
|
|
||||||
Сценарий редактирования:
|
Сценарий редактирования:
|
||||||
1. Зайти на главную страницу приложения
|
1. Зайти на главную страницу приложения
|
||||||
2. Перейти в раздел `section_name`
|
2. Перейти в раздел `section_name`
|
||||||
3. Перейти к списку `entity_name`
|
3. Перейти к списку `entity_name`
|
||||||
4. Выбрать нужную `entity_name` и нажать на нее
|
4. Выбрать нужную `entity_name` и нажать на нее
|
||||||
5. Внести нужные правки в поля и сохранить
|
5. Внести нужные правки в поля и сохранить
|
||||||
|
|
||||||
## Описание конечного результата, дающего возможность проверки выполнения задачи: компоненты проекта, сценарии работы
|
## Описание конечного результата, дающего возможность проверки выполнения задачи: компоненты проекта, сценарии работы
|
||||||
|
|
||||||
* Сверстаны страницы page1.hml, page2.hml, page3.hml
|
* Сверстаны страницы page1.hml, page2.hml, page3.hml
|
||||||
* Реализован контроллер для обслуживания страниц
|
* Реализован контроллер для обслуживания страниц
|
||||||
* Сохранение в БД еще не реализовано
|
* Сохранение в БД еще не реализовано
|
||||||
* Валидация происходит по полям `field1, field2`
|
* Валидация происходит по полям `field1, field2`
|
||||||
* Сценарий просмотра проверяется при ручном внечении записей в БД
|
* Сценарий просмотра проверяется при ручном внечении записей в БД
|
||||||
|
@ -13,6 +13,7 @@ import ru.ulstu.deadline.model.Deadline;
|
|||||||
import ru.ulstu.grant.model.Grant;
|
import ru.ulstu.grant.model.Grant;
|
||||||
import ru.ulstu.grant.model.GrantDto;
|
import ru.ulstu.grant.model.GrantDto;
|
||||||
import ru.ulstu.grant.service.GrantService;
|
import ru.ulstu.grant.service.GrantService;
|
||||||
|
import ru.ulstu.user.model.User;
|
||||||
import springfox.documentation.annotations.ApiIgnore;
|
import springfox.documentation.annotations.ApiIgnore;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
@ -24,7 +25,6 @@ import static org.springframework.util.StringUtils.isEmpty;
|
|||||||
import static ru.ulstu.core.controller.Navigation.GRANTS_PAGE;
|
import static ru.ulstu.core.controller.Navigation.GRANTS_PAGE;
|
||||||
import static ru.ulstu.core.controller.Navigation.GRANT_PAGE;
|
import static ru.ulstu.core.controller.Navigation.GRANT_PAGE;
|
||||||
import static ru.ulstu.core.controller.Navigation.REDIRECT_TO;
|
import static ru.ulstu.core.controller.Navigation.REDIRECT_TO;
|
||||||
import static ru.ulstu.core.controller.Navigation.hasErrors;
|
|
||||||
|
|
||||||
|
|
||||||
@Controller()
|
@Controller()
|
||||||
@ -57,27 +57,42 @@ public class GrantController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/grant", params = "save")
|
@PostMapping(value = "/grant", params = "save")
|
||||||
public String save(@Valid GrantDto grantDto, Errors errors) throws IOException {
|
public String save(@Valid GrantDto grantDto, Errors errors)
|
||||||
|
throws IOException {
|
||||||
filterEmptyDeadlines(grantDto);
|
filterEmptyDeadlines(grantDto);
|
||||||
if (grantDto.getDeadlines().isEmpty()) {
|
if (grantDto.getDeadlines().isEmpty()) {
|
||||||
errors.rejectValue("deadlines", "errorCode", "Не может быть пустым");
|
errors.rejectValue("deadlines", "errorCode", "Не может быть пусто");
|
||||||
|
}
|
||||||
|
if (grantDto.getLeaderId().equals(-1)) {
|
||||||
|
errors.rejectValue("leaderId", "errorCode", "Укажите руководителя");
|
||||||
|
}
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
return GRANT_PAGE;
|
||||||
}
|
}
|
||||||
hasErrors(errors, GRANT_PAGE);
|
|
||||||
grantService.save(grantDto);
|
grantService.save(grantDto);
|
||||||
return String.format(REDIRECT_TO, GRANTS_PAGE);
|
return String.format(REDIRECT_TO, GRANTS_PAGE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/grant", params = "filterUsers")
|
||||||
|
public String filterUsers() {
|
||||||
|
return GRANT_PAGE;
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/grant", params = "addDeadline")
|
@PostMapping(value = "/grant", params = "addDeadline")
|
||||||
public String addDeadline(@Valid GrantDto grantDto, Errors errors) {
|
public String addDeadline(@Valid GrantDto grantDto, Errors errors) {
|
||||||
filterEmptyDeadlines(grantDto);
|
filterEmptyDeadlines(grantDto);
|
||||||
hasErrors(errors, GRANT_PAGE);
|
if (errors.hasErrors()) {
|
||||||
|
return GRANT_PAGE;
|
||||||
|
}
|
||||||
grantDto.getDeadlines().add(new Deadline());
|
grantDto.getDeadlines().add(new Deadline());
|
||||||
return GRANT_PAGE;
|
return GRANT_PAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/grant", params = "createProject")
|
@PostMapping(value = "/grant", params = "createProject")
|
||||||
public String createProject(@Valid GrantDto grantDto, Errors errors) {
|
public String createProject(@Valid GrantDto grantDto, Errors errors) {
|
||||||
hasErrors(errors, GRANT_PAGE);
|
if (errors.hasErrors()) {
|
||||||
|
return GRANT_PAGE;
|
||||||
|
}
|
||||||
grantService.createProject(grantDto);
|
grantService.createProject(grantDto);
|
||||||
return GRANT_PAGE;
|
return GRANT_PAGE;
|
||||||
}
|
}
|
||||||
@ -93,6 +108,11 @@ public class GrantController {
|
|||||||
return grantService.getGrantStatuses();
|
return grantService.getGrantStatuses();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("allAuthors")
|
||||||
|
public List<User> getAllAuthors(GrantDto grantDto) {
|
||||||
|
return grantService.getGrantAuthors(grantDto);
|
||||||
|
}
|
||||||
|
|
||||||
private void filterEmptyDeadlines(GrantDto grantDto) {
|
private void filterEmptyDeadlines(GrantDto grantDto) {
|
||||||
grantDto.setDeadlines(grantDto.getDeadlines().stream()
|
grantDto.setDeadlines(grantDto.getDeadlines().stream()
|
||||||
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
||||||
|
@ -2,28 +2,35 @@ package ru.ulstu.grant.model;
|
|||||||
|
|
||||||
import org.hibernate.validator.constraints.NotBlank;
|
import org.hibernate.validator.constraints.NotBlank;
|
||||||
import ru.ulstu.core.model.BaseEntity;
|
import ru.ulstu.core.model.BaseEntity;
|
||||||
|
import ru.ulstu.core.model.UserContainer;
|
||||||
import ru.ulstu.deadline.model.Deadline;
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
import ru.ulstu.file.model.FileData;
|
import ru.ulstu.file.model.FileData;
|
||||||
import ru.ulstu.project.model.Project;
|
import ru.ulstu.project.model.Project;
|
||||||
|
import ru.ulstu.user.model.User;
|
||||||
|
|
||||||
import javax.persistence.CascadeType;
|
import javax.persistence.CascadeType;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
import javax.persistence.EnumType;
|
import javax.persistence.EnumType;
|
||||||
import javax.persistence.Enumerated;
|
import javax.persistence.Enumerated;
|
||||||
|
import javax.persistence.FetchType;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
|
import javax.persistence.ManyToMany;
|
||||||
import javax.persistence.ManyToOne;
|
import javax.persistence.ManyToOne;
|
||||||
import javax.persistence.OneToMany;
|
import javax.persistence.OneToMany;
|
||||||
|
import javax.persistence.OrderBy;
|
||||||
import javax.persistence.Table;
|
import javax.persistence.Table;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "grants")
|
@Table(name = "grants")
|
||||||
public class Grant extends BaseEntity {
|
public class Grant extends BaseEntity implements UserContainer {
|
||||||
public enum GrantStatus {
|
public enum GrantStatus {
|
||||||
APPLICATION("Заявка"),
|
APPLICATION("Заявка"),
|
||||||
ON_COMPETITION("Отправлен на конкурс"),
|
ON_COMPETITION("Отправлен на конкурс"),
|
||||||
@ -52,6 +59,7 @@ public class Grant extends BaseEntity {
|
|||||||
|
|
||||||
@OneToMany(cascade = CascadeType.ALL)
|
@OneToMany(cascade = CascadeType.ALL)
|
||||||
@JoinColumn(name = "grant_id")
|
@JoinColumn(name = "grant_id")
|
||||||
|
@OrderBy("date")
|
||||||
private List<Deadline> deadlines = new ArrayList<>();
|
private List<Deadline> deadlines = new ArrayList<>();
|
||||||
|
|
||||||
//Описание гранта
|
//Описание гранта
|
||||||
@ -67,6 +75,14 @@ public class Grant extends BaseEntity {
|
|||||||
@JoinColumn(name = "project_id")
|
@JoinColumn(name = "project_id")
|
||||||
private Project project;
|
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() {
|
public GrantStatus getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -115,6 +131,27 @@ public class Grant extends BaseEntity {
|
|||||||
this.project = project;
|
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() {
|
public Optional<Deadline> getNextDeadline() {
|
||||||
return deadlines
|
return deadlines
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -2,14 +2,22 @@ package ru.ulstu.grant.model;
|
|||||||
|
|
||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hibernate.validator.constraints.NotEmpty;
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
import ru.ulstu.deadline.model.Deadline;
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
import ru.ulstu.project.model.ProjectDto;
|
import ru.ulstu.project.model.ProjectDto;
|
||||||
|
import ru.ulstu.user.model.UserDto;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
||||||
|
|
||||||
public class GrantDto {
|
public class GrantDto {
|
||||||
|
private final static int MAX_AUTHORS_LENGTH = 60;
|
||||||
|
|
||||||
private Integer id;
|
private Integer id;
|
||||||
@NotEmpty
|
@NotEmpty
|
||||||
private String title;
|
private String title;
|
||||||
@ -18,6 +26,12 @@ public class GrantDto {
|
|||||||
private String comment;
|
private String comment;
|
||||||
private String applicationFileName;
|
private String applicationFileName;
|
||||||
private ProjectDto project;
|
private ProjectDto project;
|
||||||
|
private Set<Integer> authorIds;
|
||||||
|
private Set<UserDto> authors;
|
||||||
|
private Integer leaderId;
|
||||||
|
private boolean wasLeader;
|
||||||
|
private boolean hasAge;
|
||||||
|
private boolean hasDegree;
|
||||||
|
|
||||||
public GrantDto() {
|
public GrantDto() {
|
||||||
deadlines.add(new Deadline());
|
deadlines.add(new Deadline());
|
||||||
@ -29,7 +43,13 @@ public class GrantDto {
|
|||||||
@JsonProperty("status") Grant.GrantStatus status,
|
@JsonProperty("status") Grant.GrantStatus status,
|
||||||
@JsonProperty("deadlines") List<Deadline> deadlines,
|
@JsonProperty("deadlines") List<Deadline> deadlines,
|
||||||
@JsonProperty("comment") String comment,
|
@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,
|
||||||
|
@JsonProperty("wasLeader") boolean wasLeader,
|
||||||
|
@JsonProperty("hasAge") boolean hasAge,
|
||||||
|
@JsonProperty("hasDegree") boolean hasDegree) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.status = status;
|
this.status = status;
|
||||||
@ -37,6 +57,11 @@ public class GrantDto {
|
|||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
this.applicationFileName = null;
|
this.applicationFileName = null;
|
||||||
this.project = project;
|
this.project = project;
|
||||||
|
this.authors = authors;
|
||||||
|
this.leaderId = leaderId;
|
||||||
|
this.wasLeader = wasLeader;
|
||||||
|
this.hasAge = hasAge;
|
||||||
|
this.hasDegree = hasDegree;
|
||||||
}
|
}
|
||||||
|
|
||||||
public GrantDto(Grant grant) {
|
public GrantDto(Grant grant) {
|
||||||
@ -47,6 +72,12 @@ public class GrantDto {
|
|||||||
this.comment = grant.getComment();
|
this.comment = grant.getComment();
|
||||||
this.project = grant.getProject() == null ? null : new ProjectDto(grant.getProject());
|
this.project = grant.getProject() == null ? null : new ProjectDto(grant.getProject());
|
||||||
this.applicationFileName = grant.getApplication() == null ? null : grant.getApplication().getName();
|
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();
|
||||||
|
this.wasLeader = false;
|
||||||
|
this.hasAge = false;
|
||||||
|
this.hasDegree = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
@ -104,4 +135,59 @@ public class GrantDto {
|
|||||||
public void setApplicationFileName(String applicationFileName) {
|
public void setApplicationFileName(String applicationFileName) {
|
||||||
this.applicationFileName = 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isWasLeader() {
|
||||||
|
return wasLeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setWasLeader(boolean wasLeader) {
|
||||||
|
this.wasLeader = wasLeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHasAge() {
|
||||||
|
return hasAge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasAge(boolean hasAge) {
|
||||||
|
this.hasAge = hasAge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHasDegree() {
|
||||||
|
return hasDegree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasDegree(boolean hasDegree) {
|
||||||
|
this.hasDegree = hasDegree;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,19 +0,0 @@
|
|||||||
package ru.ulstu.grant.model;
|
|
||||||
|
|
||||||
public class GrantStatusDto {
|
|
||||||
private final String id;
|
|
||||||
private final String name;
|
|
||||||
|
|
||||||
public GrantStatusDto(Grant.GrantStatus status) {
|
|
||||||
this.id = status.name();
|
|
||||||
this.name = status.getStatusName();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getId() {
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
@ -3,6 +3,9 @@ package ru.ulstu.grant.repository;
|
|||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import ru.ulstu.grant.model.Grant;
|
import ru.ulstu.grant.model.Grant;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
public interface GrantRepository extends JpaRepository<Grant, Integer> {
|
public interface GrantRepository extends JpaRepository<Grant, Integer> {
|
||||||
|
|
||||||
|
List<Grant> findByStatus(Grant.GrantStatus status);
|
||||||
}
|
}
|
||||||
|
@ -12,11 +12,14 @@ import ru.ulstu.grant.repository.GrantRepository;
|
|||||||
import ru.ulstu.project.model.Project;
|
import ru.ulstu.project.model.Project;
|
||||||
import ru.ulstu.project.model.ProjectDto;
|
import ru.ulstu.project.model.ProjectDto;
|
||||||
import ru.ulstu.project.service.ProjectService;
|
import ru.ulstu.project.service.ProjectService;
|
||||||
|
import ru.ulstu.user.model.User;
|
||||||
|
import ru.ulstu.user.service.UserService;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.springframework.util.ObjectUtils.isEmpty;
|
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||||
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
||||||
@ -30,15 +33,18 @@ public class GrantService {
|
|||||||
private final ProjectService projectService;
|
private final ProjectService projectService;
|
||||||
private final DeadlineService deadlineService;
|
private final DeadlineService deadlineService;
|
||||||
private final FileService fileService;
|
private final FileService fileService;
|
||||||
|
private final UserService userService;
|
||||||
|
|
||||||
public GrantService(GrantRepository grantRepository,
|
public GrantService(GrantRepository grantRepository,
|
||||||
FileService fileService,
|
FileService fileService,
|
||||||
DeadlineService deadlineService,
|
DeadlineService deadlineService,
|
||||||
ProjectService projectService) {
|
ProjectService projectService,
|
||||||
|
UserService userService) {
|
||||||
this.grantRepository = grantRepository;
|
this.grantRepository = grantRepository;
|
||||||
this.projectService = projectService;
|
|
||||||
this.fileService = fileService;
|
this.fileService = fileService;
|
||||||
this.deadlineService = deadlineService;
|
this.deadlineService = deadlineService;
|
||||||
|
this.projectService = projectService;
|
||||||
|
this.userService = userService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Grant> findAll() {
|
public List<Grant> findAll() {
|
||||||
@ -73,6 +79,13 @@ public class GrantService {
|
|||||||
if (grantDto.getApplicationFileName() != null) {
|
if (grantDto.getApplicationFileName() != null) {
|
||||||
grant.setApplication(fileService.createFileFromTmp(grantDto.getApplicationFileName()));
|
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;
|
return grant;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -84,7 +97,6 @@ public class GrantService {
|
|||||||
@Transactional
|
@Transactional
|
||||||
public Integer update(GrantDto grantDto) throws IOException {
|
public Integer update(GrantDto grantDto) throws IOException {
|
||||||
Grant grant = grantRepository.findOne(grantDto.getId());
|
Grant grant = grantRepository.findOne(grantDto.getId());
|
||||||
Grant.GrantStatus oldStatus = grant.getStatus();
|
|
||||||
if (grantDto.getApplicationFileName() != null && grant.getApplication() != null) {
|
if (grantDto.getApplicationFileName() != null && grant.getApplication() != null) {
|
||||||
fileService.deleteFile(grant.getApplication());
|
fileService.deleteFile(grant.getApplication());
|
||||||
}
|
}
|
||||||
@ -98,7 +110,6 @@ public class GrantService {
|
|||||||
if (grant.getApplication() != null) {
|
if (grant.getApplication() != null) {
|
||||||
fileService.deleteFile(grant.getApplication());
|
fileService.deleteFile(grant.getApplication());
|
||||||
}
|
}
|
||||||
//возможно при удалении гранта будет удаляться и проект, к нему привязанный
|
|
||||||
grantRepository.delete(grant);
|
grantRepository.delete(grant);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,13 +118,15 @@ public class GrantService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@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 grant = new Grant();
|
||||||
grant.setTitle(title);
|
grant.setTitle(title);
|
||||||
grant.setComment("Комментарий к гранту 1");
|
grant.setComment("Комментарий к гранту 1");
|
||||||
grant.setProject(projectId);
|
grant.setProject(projectId);
|
||||||
grant.setStatus(APPLICATION);
|
grant.setStatus(APPLICATION);
|
||||||
grant.getDeadlines().add(new Deadline(deadlineDate, "первый дедлайн"));
|
grant.getDeadlines().add(new Deadline(deadlineDate, "первый дедлайн"));
|
||||||
|
grant.getAuthors().add(user);
|
||||||
|
grant.setLeader(user);
|
||||||
grant = grantRepository.save(grant);
|
grant = grantRepository.save(grant);
|
||||||
return grant;
|
return grant;
|
||||||
}
|
}
|
||||||
@ -125,4 +138,22 @@ public class GrantService {
|
|||||||
update(grantDto);
|
update(grantDto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<User> getGrantAuthors(GrantDto grantDto) {
|
||||||
|
List<User> filteredUsers = userService.filterByAgeAndDegree(grantDto.isHasAge(), grantDto.isHasDegree());
|
||||||
|
if (grantDto.isWasLeader()) {
|
||||||
|
filteredUsers = filteredUsers
|
||||||
|
.stream()
|
||||||
|
.filter(getCompletedGrantLeaders()::contains)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
return filteredUsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<User> getCompletedGrantLeaders() {
|
||||||
|
return grantRepository.findByStatus(Grant.GrantStatus.COMPLETED)
|
||||||
|
.stream()
|
||||||
|
.map(Grant::getLeader)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import ru.ulstu.core.model.BaseEntity;
|
|||||||
|
|
||||||
import javax.persistence.Column;
|
import javax.persistence.Column;
|
||||||
import javax.persistence.Entity;
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.EnumType;
|
||||||
|
import javax.persistence.Enumerated;
|
||||||
import javax.persistence.JoinColumn;
|
import javax.persistence.JoinColumn;
|
||||||
import javax.persistence.JoinTable;
|
import javax.persistence.JoinTable;
|
||||||
import javax.persistence.ManyToMany;
|
import javax.persistence.ManyToMany;
|
||||||
@ -85,6 +87,28 @@ public class User extends BaseEntity {
|
|||||||
@BatchSize(size = 20)
|
@BatchSize(size = 20)
|
||||||
private Set<UserRole> roles;
|
private Set<UserRole> roles;
|
||||||
|
|
||||||
|
@Column(name = "birth_date")
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
private Date birthDate;
|
||||||
|
|
||||||
|
public enum UserDegree {
|
||||||
|
CANDIDATE("Кандидат технических наук"),
|
||||||
|
DOCTOR("Доктор технических наук");
|
||||||
|
|
||||||
|
private String degreeName;
|
||||||
|
|
||||||
|
UserDegree(String degreeName) {
|
||||||
|
this.degreeName = degreeName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDegreeName() {
|
||||||
|
return degreeName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Enumerated(value = EnumType.STRING)
|
||||||
|
private UserDegree degree;
|
||||||
|
|
||||||
public User() {
|
public User() {
|
||||||
roles = new HashSet<>();
|
roles = new HashSet<>();
|
||||||
activated = false;
|
activated = false;
|
||||||
@ -189,6 +213,22 @@ public class User extends BaseEntity {
|
|||||||
this.patronymic = patronymic;
|
this.patronymic = patronymic;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Date getBirthDate() {
|
||||||
|
return birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBirthDate(Date birthDate) {
|
||||||
|
this.birthDate = birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public UserDegree getDegree() {
|
||||||
|
return degree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDegree(UserDegree degree) {
|
||||||
|
this.degree = degree;
|
||||||
|
}
|
||||||
|
|
||||||
public String getUserAbbreviate() {
|
public String getUserAbbreviate() {
|
||||||
return String.format(USER_ABBREVIATE_TEMPLATE,
|
return String.format(USER_ABBREVIATE_TEMPLATE,
|
||||||
lastName == null ? "" : lastName,
|
lastName == null ? "" : lastName,
|
||||||
|
@ -15,6 +15,7 @@ import ru.ulstu.user.controller.UserController;
|
|||||||
import javax.validation.constraints.Pattern;
|
import javax.validation.constraints.Pattern;
|
||||||
import javax.validation.constraints.Size;
|
import javax.validation.constraints.Size;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
|
import java.util.Date;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@ -70,6 +71,10 @@ public class UserDto implements OdinDto {
|
|||||||
@Size(min = Constants.MIN_PASSWORD_LENGTH, max = 50)
|
@Size(min = Constants.MIN_PASSWORD_LENGTH, max = 50)
|
||||||
private String passwordConfirm;
|
private String passwordConfirm;
|
||||||
|
|
||||||
|
private Date birthDate;
|
||||||
|
|
||||||
|
private User.UserDegree degree;
|
||||||
|
|
||||||
public UserDto() {
|
public UserDto() {
|
||||||
activated = false;
|
activated = false;
|
||||||
roles = new LinkedHashSet<>();
|
roles = new LinkedHashSet<>();
|
||||||
@ -86,6 +91,8 @@ public class UserDto implements OdinDto {
|
|||||||
this.roles.addAll(user.getRoles().stream()
|
this.roles.addAll(user.getRoles().stream()
|
||||||
.map(UserRoleDto::new)
|
.map(UserRoleDto::new)
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
|
this.birthDate = user.getBirthDate();
|
||||||
|
this.degree = user.getDegree();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
@ -163,6 +170,22 @@ public class UserDto implements OdinDto {
|
|||||||
return passwordConfirm;
|
return passwordConfirm;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Date getBirthDate() {
|
||||||
|
return birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBirthDate(Date birthDate) {
|
||||||
|
this.birthDate = birthDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public User.UserDegree getDegree() {
|
||||||
|
return degree;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDegree(User.UserDegree degree) {
|
||||||
|
this.degree = degree;
|
||||||
|
}
|
||||||
|
|
||||||
@JsonIgnore
|
@JsonIgnore
|
||||||
public boolean isPasswordsValid() {
|
public boolean isPasswordsValid() {
|
||||||
if (StringUtils.isEmpty(password) || StringUtils.isEmpty(passwordConfirm)) {
|
if (StringUtils.isEmpty(password) || StringUtils.isEmpty(passwordConfirm)) {
|
||||||
@ -188,6 +211,8 @@ public class UserDto implements OdinDto {
|
|||||||
", roles=" + roles +
|
", roles=" + roles +
|
||||||
", password='" + password + '\'' +
|
", password='" + password + '\'' +
|
||||||
", passwordConfirm='" + passwordConfirm + '\'' +
|
", passwordConfirm='" + passwordConfirm + '\'' +
|
||||||
|
", birthDate='" + birthDate + '\'' +
|
||||||
|
", degree='" + degree + '\'' +
|
||||||
'}';
|
'}';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package ru.ulstu.user.repository;
|
|||||||
|
|
||||||
import org.springframework.data.jpa.repository.EntityGraph;
|
import org.springframework.data.jpa.repository.EntityGraph;
|
||||||
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.user.model.User;
|
import ru.ulstu.user.model.User;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
@ -25,4 +27,11 @@ public interface UserRepository extends JpaRepository<User, Integer> {
|
|||||||
|
|
||||||
@EntityGraph(attributePaths = "roles")
|
@EntityGraph(attributePaths = "roles")
|
||||||
User findOneWithRolesByLogin(String login);
|
User findOneWithRolesByLogin(String login);
|
||||||
|
|
||||||
|
@Query("SELECT u FROM User u " +
|
||||||
|
"WHERE (YEAR(CURRENT_DATE) - YEAR(u.birthDate) < 35 OR :hasAge = FALSE) " +
|
||||||
|
"AND (u.degree = 'CANDIDATE' OR :hasDegree = FALSE)" +
|
||||||
|
"ORDER BY u.lastName")
|
||||||
|
List<User> filterByAgeAndDegree(@Param("hasAge") boolean hasAge,
|
||||||
|
@Param("hasDegree") boolean hasDegree);
|
||||||
}
|
}
|
||||||
|
@ -324,4 +324,8 @@ public class UserService implements UserDetailsService {
|
|||||||
}
|
}
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<User> filterByAgeAndDegree(boolean hasDegree, boolean hasAge) {
|
||||||
|
return userRepository.filterByAgeAndDegree(hasDegree, hasAge);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
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="authors_id" type="integer"/>
|
||||||
|
</createTable>
|
||||||
|
<addForeignKeyConstraint baseTableName="grants_authors" baseColumnNames="grant_id"
|
||||||
|
constraintName="fk_grants_grants_authors" referencedTableName="grants"
|
||||||
|
referencedColumnNames="id"/>
|
||||||
|
<addForeignKeyConstraint baseTableName="grants_authors" baseColumnNames="authors_id"
|
||||||
|
constraintName="fk_user_grants_authors" referencedTableName="users"
|
||||||
|
referencedColumnNames="id"/>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
13
src/main/resources/db/changelog-20190404_000000-schema.xml
Normal file
13
src/main/resources/db/changelog-20190404_000000-schema.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?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="20190404_000000-1">
|
||||||
|
<addColumn tableName="users">
|
||||||
|
<column name="birth_date" type="timestamp"></column>
|
||||||
|
</addColumn>
|
||||||
|
<addColumn tableName="users">
|
||||||
|
<column name="degree" type="varchar(255)"></column>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
@ -27,4 +27,6 @@
|
|||||||
<include file="db/changelog-20190418_000000-schema.xml"/>
|
<include file="db/changelog-20190418_000000-schema.xml"/>
|
||||||
<include file="db/changelog-20190323_000001-schema.xml"/>
|
<include file="db/changelog-20190323_000001-schema.xml"/>
|
||||||
<include file="db/common/changelog-20190312_130000-schema.xml"/>
|
<include file="db/common/changelog-20190312_130000-schema.xml"/>
|
||||||
|
<include file="db/changelog-20190402_000000-schema.xml"/>
|
||||||
|
<include file="db/changelog-20190404_000000-schema.xml"/>
|
||||||
</databaseChangeLog>
|
</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})"/>
|
<span th:replace="grants/fragments/grantStatusFragment :: grantStatus(grantStatus=${grant.status})"/>
|
||||||
<a th:href="@{'grant?id='+${grant.id}}">
|
<a th:href="@{'grant?id='+${grant.id}}">
|
||||||
<span class="h6" th:text="${grant.title}"/>
|
<span class="h6" th:text="${grant.title}"/>
|
||||||
<span class="text-muted" th:text="${grant.comment}"/>
|
<span class="text-muted" th:text="${grant.authorsString}"/>
|
||||||
</a>
|
</a>
|
||||||
<input class="id-class" type="hidden" th:value="${grant.id}"/>
|
<input class="id-class" type="hidden" th:value="${grant.id}"/>
|
||||||
<a class="remove-paper pull-right d-none" th:href="@{'/grants/delete/'+${grant.id}}"
|
<a class="remove-paper pull-right d-none" th:href="@{'/grants/delete/'+${grant.id}}"
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<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()}">
|
<th:block th:switch="${grantStatus.name()}">
|
||||||
<div th:case="'APPLICATION'">
|
<div th:case="'APPLICATION'">
|
||||||
<i class="fa fa-circle fa-stack-2x text-draft"></i>
|
<i class="fa fa-circle fa-stack-2x text-draft"></i>
|
||||||
|
@ -3,13 +3,12 @@
|
|||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
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">
|
layout:decorator="default" xmlns:th="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/html">
|
||||||
<head>
|
<head>
|
||||||
|
<link rel="stylesheet" href="../css/grant.css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<div class="container" layout:fragment="content">
|
<div class="container" layout:fragment="content">
|
||||||
|
<section id="grant">
|
||||||
<section id="paper">
|
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12 text-center">
|
<div class="col-lg-12 text-center">
|
||||||
@ -17,6 +16,7 @@
|
|||||||
<div th:replace="grants/fragments/grantNavigationFragment"/>
|
<div th:replace="grants/fragments/grantNavigationFragment"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<hr/>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<form id="grant-form" method="post" th:action="@{'/grants/grant?id='+ *{id == null ? '' : id} + ''}"
|
<form id="grant-form" method="post" th:action="@{'/grants/grant?id='+ *{id == null ? '' : id} + ''}"
|
||||||
@ -33,7 +33,6 @@
|
|||||||
class="alert alert-danger">Incorrect title</p>
|
class="alert alert-danger">Incorrect title</p>
|
||||||
<p class="help-block text-danger"></p>
|
<p class="help-block text-danger"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="status">Статус:</label>
|
<label for="status">Статус:</label>
|
||||||
<select class="form-control" th:field="*{status}" id="status">
|
<select class="form-control" th:field="*{status}" id="status">
|
||||||
@ -51,11 +50,11 @@
|
|||||||
<label>Дедлайны показателей:</label>
|
<label>Дедлайны показателей:</label>
|
||||||
<div class="row" th:each="deadline, rowStat : *{deadlines}">
|
<div class="row" th:each="deadline, rowStat : *{deadlines}">
|
||||||
<input type="hidden" th:field="*{deadlines[__${rowStat.index}__].id}"/>
|
<input type="hidden" th:field="*{deadlines[__${rowStat.index}__].id}"/>
|
||||||
<div class="col-6">
|
<div class="col-6 div-deadline-date">
|
||||||
<input type="date" class="form-control" name="deadline"
|
<input type="date" class="form-control form-deadline-date" name="deadline"
|
||||||
th:field="*{deadlines[__${rowStat.index}__].date}"/>
|
th:field="*{deadlines[__${rowStat.index}__].date}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-4">
|
<div class="col-4 div-deadline-description">
|
||||||
<input class="form-control" type="text" placeholder="Описание"
|
<input class="form-control" type="text" placeholder="Описание"
|
||||||
th:field="*{deadlines[__${rowStat.index}__].description}"/>
|
th:field="*{deadlines[__${rowStat.index}__].description}"/>
|
||||||
</div>
|
</div>
|
||||||
@ -72,31 +71,101 @@
|
|||||||
class="alert alert-danger">Incorrect title</p>
|
class="alert alert-danger">Incorrect title</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<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>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="loader">Загрузить заявку:</label>
|
<label for="loader">Загрузить заявку:</label>
|
||||||
<div id="loader">
|
<div id="loader">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</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 th:class="${grantDto.wasLeader || grantDto.hasAge || grantDto.hasDegree} ?
|
||||||
|
'form-check' : 'form-check collapse'" id="collapse-filter">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<input class="form-check-input" type="checkbox" id="f1"
|
||||||
|
th:field="*{wasLeader}" th:onclick="|$('#filter').click();|"/>
|
||||||
|
<label class="form-check-label" for="f1">Был руководителем проекта</label>
|
||||||
|
</div>
|
||||||
|
<div class="col">
|
||||||
|
<input class="form-check-input" type="checkbox" id="f2"
|
||||||
|
th:field="*{hasAge}" th:onclick="|$('#filter').click();|"/>
|
||||||
|
<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"
|
||||||
|
th:field="*{hasDegree}" th:onclick="|$('#filter').click();|"/>
|
||||||
|
<label class="form-check-label" for="f3">Cтепень к.т.н.</label>
|
||||||
|
</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>
|
||||||
|
<input type="submit" hidden="hidden" id="filter" name="filterUsers"
|
||||||
|
value="Применить фильтр"/>
|
||||||
|
<hr/>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Руководитель проекта:</label>
|
||||||
|
<select class="form-control" th:field="*{leaderId}" id="leaderId"
|
||||||
|
onchange="updateAuthors();">
|
||||||
|
<option selected="selected" hidden="hidden" th:value="-1">-- Выберите
|
||||||
|
руководителя --
|
||||||
|
</option>
|
||||||
|
<option th:each="leader : ${allAuthors}" th:value="${leader.id}"
|
||||||
|
th:text="${leader.lastName}"> Руководитель
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
<p th:if="${#fields.hasErrors('leaderId')}" th:errors="*{leaderId}"
|
||||||
|
class="alert alert-danger">Choose leader</p>
|
||||||
|
<p class="help-block text-danger"></p>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label>Участники гранта:</label>
|
||||||
|
<select class="selectpicker form-control" multiple="true"
|
||||||
|
title="-- Выберите участников --" id="authors"
|
||||||
|
th:field="*{authorIds}">
|
||||||
|
<option th:each="author : ${allAuthors}" th:value="${author.id}"
|
||||||
|
th:text="${author.lastName}"> Участник
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Список статей:</label>
|
<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>
|
</i> Добавить статью</a></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div th:if="*{project} == null">
|
<div th:if="*{project} == null">
|
||||||
<input type="submit" name="createProject" class="btn btn-primary"
|
<input type="submit" name="createProject" class="btn btn-primary"
|
||||||
value="Добавить проект"/>
|
value="Добавить проект"/>
|
||||||
</div>
|
</div>
|
||||||
<input type = "hidden" th:field="*{project.id}"/>
|
<input type = "hidden" th:field="*{project.id}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="clearfix"></div>
|
<div class="clearfix"></div>
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -132,6 +201,16 @@
|
|||||||
$('.selectpicker').selectpicker();
|
$('.selectpicker').selectpicker();
|
||||||
});
|
});
|
||||||
/*]]>*/
|
/*]]>*/
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
function updateAuthors() {
|
||||||
|
$("#authors").val('default');
|
||||||
|
$("#authors").selectpicker("refresh");
|
||||||
|
$("#authors").children('option:disabled').prop('disabled', false);
|
||||||
|
var lid = $("#leaderId option:selected").val();
|
||||||
|
$("#authors [value='" + lid + "']").attr("disabled", "disabled");
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -82,7 +82,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 col-sm-6 portfolio-item">
|
<div class="col-md-4 col-sm-6 portfolio-item">
|
||||||
<a class="portfolio-link" href="./students/tasks">
|
<a class="portfolio-link" href="./students/tasks">
|
||||||
<div class="portfolio-hover">
|
<div class="portfolio-hover">
|
||||||
<div class="portfolio-hover-content">
|
<div class="portfolio-hover-content">
|
||||||
<i class="fa fa-arrow-right fa-3x"></i>
|
<i class="fa fa-arrow-right fa-3x"></i>
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en"
|
<html lang="en"
|
||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
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">
|
layout:decorator="default" xmlns:th="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/html">
|
||||||
<head>
|
<head>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
@ -19,7 +19,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<form id="project-form" method="post" th:action="@{'/projects/project?id='+ *{id == null ? '' : id} + ''}"
|
<form id="project-form" method="post"
|
||||||
|
th:action="@{'/projects/project?id='+ *{id == null ? '' : id} + ''}"
|
||||||
th:object="${projectDto}">
|
th:object="${projectDto}">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-6 col-sm-12">
|
<div class="col-md-6 col-sm-12">
|
||||||
@ -55,7 +56,7 @@
|
|||||||
<input type="submit" id="createGrant" name="createGrant" class="btn btn-primary"
|
<input type="submit" id="createGrant" name="createGrant" class="btn btn-primary"
|
||||||
value="Добавить грант"/>
|
value="Добавить грант"/>
|
||||||
</div>
|
</div>
|
||||||
<input type = "hidden" th:field="*{grant.id}"/>
|
<input type="hidden" th:field="*{grant.id}"/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
@ -88,7 +89,8 @@
|
|||||||
class="alert alert-danger">Incorrect title</p>
|
class="alert alert-danger">Incorrect title</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<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>
|
||||||
|
|
||||||
@ -107,7 +109,8 @@
|
|||||||
type="submit">
|
type="submit">
|
||||||
Сохранить
|
Сохранить
|
||||||
</button>
|
</button>
|
||||||
<button id="cancelButton" class="btn btn-default text-uppercase" href="/projects/projects">
|
<button id="cancelButton" class="btn btn-default text-uppercase"
|
||||||
|
href="/projects/projects">
|
||||||
Отмена
|
Отмена
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
@ -135,6 +138,7 @@
|
|||||||
$('.selectpicker').selectpicker();
|
$('.selectpicker').selectpicker();
|
||||||
});
|
});
|
||||||
/*]]>*/
|
/*]]>*/
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
<div class="row justify-content-center" id="dashboard">
|
<div class="row justify-content-center" id="dashboard">
|
||||||
<div th:replace="students/fragments/taskDashboardFragment"/>
|
<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>
|
||||||
|
Loading…
Reference in New Issue
Block a user