Merge remote-tracking branch 'remotes/origin/dev' into 76-students-tags-filter
# Conflicts: # src/main/resources/templates/students/dashboard.html
This commit is contained in:
commit
8400c5d40d
@ -1,46 +1,46 @@
|
||||
## Краткое описание задачи
|
||||
|
||||
Что требуется сделать
|
||||
|
||||
|
||||
## `Опционально` Список верстаемых страниц
|
||||
|
||||
Будут затронуты страницы:
|
||||
* page1.html
|
||||
* page2.html
|
||||
* page3.html
|
||||
|
||||
## `Опционально` Список затрагиваемых модулей
|
||||
|
||||
При реализации задачи потребуется также реализовать методы контроллера
|
||||
|
||||
|
||||
## `Опционально` Список реализуемых функций
|
||||
|
||||
После выполнения задачи станет доступным:
|
||||
* просмотр `entity_name`
|
||||
* редактирование `entity_name`
|
||||
* валидация `entity_name`
|
||||
|
||||
## `Опционально` Сценарии работы
|
||||
|
||||
Сценарий просмотра:
|
||||
1. Зайти на главную страницу приложения
|
||||
2. Перейти в раздел `section_name`
|
||||
3. Перейти к списку `entity_name`
|
||||
4. Выбрать нужную `entity_name` и нажать на нее
|
||||
|
||||
Сценарий редактирования:
|
||||
1. Зайти на главную страницу приложения
|
||||
2. Перейти в раздел `section_name`
|
||||
3. Перейти к списку `entity_name`
|
||||
4. Выбрать нужную `entity_name` и нажать на нее
|
||||
5. Внести нужные правки в поля и сохранить
|
||||
|
||||
## Описание конечного результата, дающего возможность проверки выполнения задачи: компоненты проекта, сценарии работы
|
||||
|
||||
* Сверстаны страницы page1.hml, page2.hml, page3.hml
|
||||
* Реализован контроллер для обслуживания страниц
|
||||
* Сохранение в БД еще не реализовано
|
||||
* Валидация происходит по полям `field1, field2`
|
||||
* Сценарий просмотра проверяется при ручном внечении записей в БД
|
||||
## Краткое описание задачи
|
||||
|
||||
Что требуется сделать
|
||||
|
||||
|
||||
## `Опционально` Список верстаемых страниц
|
||||
|
||||
Будут затронуты страницы:
|
||||
* page1.html
|
||||
* page2.html
|
||||
* page3.html
|
||||
|
||||
## `Опционально` Список затрагиваемых модулей
|
||||
|
||||
При реализации задачи потребуется также реализовать методы контроллера
|
||||
|
||||
|
||||
## `Опционально` Список реализуемых функций
|
||||
|
||||
После выполнения задачи станет доступным:
|
||||
* просмотр `entity_name`
|
||||
* редактирование `entity_name`
|
||||
* валидация `entity_name`
|
||||
|
||||
## `Опционально` Сценарии работы
|
||||
|
||||
Сценарий просмотра:
|
||||
1. Зайти на главную страницу приложения
|
||||
2. Перейти в раздел `section_name`
|
||||
3. Перейти к списку `entity_name`
|
||||
4. Выбрать нужную `entity_name` и нажать на нее
|
||||
|
||||
Сценарий редактирования:
|
||||
1. Зайти на главную страницу приложения
|
||||
2. Перейти в раздел `section_name`
|
||||
3. Перейти к списку `entity_name`
|
||||
4. Выбрать нужную `entity_name` и нажать на нее
|
||||
5. Внести нужные правки в поля и сохранить
|
||||
|
||||
## Описание конечного результата, дающего возможность проверки выполнения задачи: компоненты проекта, сценарии работы
|
||||
|
||||
* Сверстаны страницы page1.hml, page2.hml, page3.hml
|
||||
* Реализован контроллер для обслуживания страниц
|
||||
* Сохранение в БД еще не реализовано
|
||||
* Валидация происходит по полям `field1, field2`
|
||||
* Сценарий просмотра проверяется при ручном внечении записей в БД
|
||||
|
@ -100,7 +100,7 @@
|
||||
|
||||
<!-- Checks for imports -->
|
||||
<!-- See http://checkstyle.sf.net/config_import.html -->
|
||||
<!--<module name="AvoidStarImport"/>-->
|
||||
<module name="AvoidStarImport"/>
|
||||
<module name="IllegalImport"/> <!-- defaults to sun.* packages -->
|
||||
<module name="RedundantImport"/>
|
||||
<!--module name="UnusedImports">
|
||||
@ -136,7 +136,7 @@
|
||||
<module name="AvoidNestedBlocks"/>
|
||||
<module name="EmptyBlock"/>
|
||||
<module name="LeftCurly"/>
|
||||
<!--<module name="NeedBraces"/>-->
|
||||
<module name="NeedBraces"/>
|
||||
<module name="RightCurly"/>
|
||||
|
||||
<!-- Checks for common coding problems -->
|
||||
|
@ -4,28 +4,24 @@ package ru.ulstu.conference.controller;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.ulstu.conference.model.ConferenceDto;
|
||||
import ru.ulstu.conference.model.ConferenceFilterDto;
|
||||
import ru.ulstu.conference.model.ConferenceUser;
|
||||
import ru.ulstu.conference.service.ConferenceService;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.user.model.User;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.util.StringUtils.isEmpty;
|
||||
import static ru.ulstu.core.controller.Navigation.CONFERENCES_PAGE;
|
||||
import static ru.ulstu.core.controller.Navigation.CONFERENCE_PAGE;
|
||||
import static ru.ulstu.core.controller.Navigation.REDIRECT_TO;
|
||||
import static ru.ulstu.core.controller.Navigation.*;
|
||||
|
||||
|
||||
@Controller()
|
||||
@ -44,16 +40,19 @@ public class ConferenceController {
|
||||
modelMap.put("filteredConferences", new ConferenceFilterDto(conferenceService.findAllDto()));
|
||||
}
|
||||
|
||||
@PostMapping("/conferences")
|
||||
public void filterConferences(@Valid ConferenceFilterDto conferenceFilterDto, ModelMap modelMap) {
|
||||
modelMap.put("filteredConferences", new ConferenceFilterDto(conferenceService.filter(conferenceFilterDto),
|
||||
conferenceFilterDto.getFilterUserId(),
|
||||
conferenceFilterDto.getYear()));
|
||||
}
|
||||
|
||||
@GetMapping("/conference")
|
||||
public void getConference(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
|
||||
if (id != null && id > 0) {
|
||||
ConferenceDto conferenceDto = conferenceService.findOneDto(id);
|
||||
conferenceDto.setNotSelectedPapers(getNotSelectPapers(conferenceDto.getPaperIds()));
|
||||
modelMap.put("conferenceDto", conferenceDto);
|
||||
modelMap.put("conferenceDto", conferenceService.getExistConferenceById(id));
|
||||
} else {
|
||||
ConferenceDto conferenceDto = new ConferenceDto();
|
||||
conferenceDto.setNotSelectedPapers(getNotSelectPapers(new ArrayList<Integer>()));
|
||||
modelMap.put("conferenceDto", conferenceDto);
|
||||
modelMap.put("conferenceDto", conferenceService.getNewConference());
|
||||
}
|
||||
}
|
||||
|
||||
@ -104,8 +103,37 @@ public class ConferenceController {
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
|
||||
public List<Paper> getNotSelectPapers(List<Integer> paperIds) {
|
||||
return conferenceService.getConferencePapers(paperIds);
|
||||
@PostMapping(value = "/conference", params = "takePart")
|
||||
public String takePart(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
||||
if (errors.hasErrors()) {
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
conferenceService.takePart(conferenceDto);
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
|
||||
@ModelAttribute("allParticipation")
|
||||
public List<ConferenceUser.Participation> getAllParticipation() {
|
||||
return conferenceService.getAllParticipations();
|
||||
}
|
||||
|
||||
@ModelAttribute("allDeposit")
|
||||
public List<ConferenceUser.Deposit> getAllDeposit() {
|
||||
return conferenceService.getAllDeposit();
|
||||
}
|
||||
|
||||
@ModelAttribute("allUsers")
|
||||
public List<User> getAllUsers() {
|
||||
return conferenceService.getAllUsers();
|
||||
}
|
||||
|
||||
@ModelAttribute("allYears")
|
||||
public List<Integer> getAllYears() {
|
||||
List<Integer> years = new ArrayList<>();
|
||||
for (int i = Calendar.getInstance().get(Calendar.YEAR); i > 2010; i--) {
|
||||
years.add(i);
|
||||
}
|
||||
return years;
|
||||
}
|
||||
|
||||
private void filterEmptyDeadlines(ConferenceDto conferenceDto) {
|
||||
|
@ -7,25 +7,11 @@ import org.springframework.format.annotation.DateTimeFormat;
|
||||
import ru.ulstu.core.model.BaseEntity;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@Entity
|
||||
@Table(name = "conference")
|
||||
@ -62,11 +48,10 @@ public class Conference extends BaseEntity {
|
||||
inverseJoinColumns = {@JoinColumn(name = "paper_id")})
|
||||
private List<Paper> papers = new ArrayList<>();
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "users_conference",
|
||||
joinColumns = {@JoinColumn(name = "conference_id")},
|
||||
inverseJoinColumns = {@JoinColumn(name = "users_id")})
|
||||
private Set<User> users = new HashSet<>();
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "conference_id", unique = true)
|
||||
@Fetch(FetchMode.SUBSELECT)
|
||||
private List<ConferenceUser> users = new ArrayList<>();
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
@ -132,11 +117,11 @@ public class Conference extends BaseEntity {
|
||||
this.papers = papers;
|
||||
}
|
||||
|
||||
public Set<User> getUsers() {
|
||||
public List<ConferenceUser> getUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
public void setUsers(Set<User> users) {
|
||||
public void setUsers(List<ConferenceUser> users) {
|
||||
this.users = users;
|
||||
}
|
||||
}
|
||||
|
@ -6,21 +6,21 @@ import org.hibernate.validator.constraints.NotEmpty;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.user.model.UserDto;
|
||||
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
||||
|
||||
public class ConferenceDto {
|
||||
|
||||
private final static String BEGIN_DATE = "Начало: ";
|
||||
private final static String END_DATE = "Конец: ";
|
||||
|
||||
private Integer id;
|
||||
@NotEmpty
|
||||
@Size(min = 2, max = 400)
|
||||
@ -38,14 +38,12 @@ public class ConferenceDto {
|
||||
private Date endDate = new Date();
|
||||
private List<Deadline> deadlines = new ArrayList<>();
|
||||
private List<Integer> removedDeadlineIds = new ArrayList<>();
|
||||
private Set<Integer> userIds = new HashSet<>();
|
||||
private List<Integer> userIds = new ArrayList<>();
|
||||
private List<Integer> paperIds = new ArrayList<>();
|
||||
private List<Paper> papers = new ArrayList<>();
|
||||
|
||||
|
||||
private List<Paper> notSelectedPapers = new ArrayList<>();
|
||||
private Set<UserDto> users = new HashSet<>();
|
||||
private Integer filterUserId;
|
||||
private List<ConferenceUser> users = new ArrayList<>();
|
||||
private boolean disabledTakePart = false;
|
||||
|
||||
public ConferenceDto() {
|
||||
}
|
||||
@ -59,11 +57,12 @@ public class ConferenceDto {
|
||||
@JsonProperty("beginDate") Date beginDate,
|
||||
@JsonProperty("endDate") Date endDate,
|
||||
@JsonProperty("deadlines") List<Deadline> deadlines,
|
||||
@JsonProperty("userIds") Set<Integer> userIds,
|
||||
@JsonProperty("userIds") List<Integer> userIds,
|
||||
@JsonProperty("paperIds") List<Integer> paperIds,
|
||||
@JsonProperty("users") Set<UserDto> users,
|
||||
@JsonProperty("users") List<ConferenceUser> users,
|
||||
@JsonProperty("papers") List<Paper> papers,
|
||||
@JsonProperty("notSelectedPapers") List<Paper> notSelectedPapers) {
|
||||
@JsonProperty("notSelectedPapers") List<Paper> notSelectedPapers,
|
||||
@JsonProperty("notSelectedPapers") Boolean disabledTakePart) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.description = description;
|
||||
@ -77,6 +76,7 @@ public class ConferenceDto {
|
||||
this.users = users;
|
||||
this.papers = papers;
|
||||
this.notSelectedPapers = notSelectedPapers;
|
||||
this.disabledTakePart = disabledTakePart;
|
||||
}
|
||||
|
||||
public ConferenceDto(Conference conference) {
|
||||
@ -90,9 +90,8 @@ public class ConferenceDto {
|
||||
this.deadlines = conference.getDeadlines();
|
||||
this.userIds = convert(conference.getUsers(), user -> user.getId());
|
||||
this.paperIds = convert(conference.getPapers(), paper -> paper.getId());
|
||||
this.users = convert(conference.getUsers(), UserDto::new);
|
||||
this.users = conference.getUsers();
|
||||
this.papers = conference.getPapers();
|
||||
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
@ -159,11 +158,11 @@ public class ConferenceDto {
|
||||
this.deadlines = deadlines;
|
||||
}
|
||||
|
||||
public Set<Integer> getUserIds() {
|
||||
public List<Integer> getUserIds() {
|
||||
return userIds;
|
||||
}
|
||||
|
||||
public void setUserIds(Set<Integer> userIds) {
|
||||
public void setUserIds(List<Integer> userIds) {
|
||||
this.userIds = userIds;
|
||||
}
|
||||
|
||||
@ -183,20 +182,20 @@ public class ConferenceDto {
|
||||
this.papers = papers;
|
||||
}
|
||||
|
||||
public Set<UserDto> getUsers() {
|
||||
public List<ConferenceUser> getUsers() {
|
||||
return users;
|
||||
}
|
||||
|
||||
public void setUsers(Set<UserDto> users) {
|
||||
public void setUsers(List<ConferenceUser> users) {
|
||||
this.users = users;
|
||||
}
|
||||
|
||||
public Integer getFilterUserId() {
|
||||
return filterUserId;
|
||||
public boolean isDisabledTakePart() {
|
||||
return disabledTakePart;
|
||||
}
|
||||
|
||||
public void setFilterUserId(Integer filterUserId) {
|
||||
this.filterUserId = filterUserId;
|
||||
public void setDisabledTakePart(boolean disabledTakePart) {
|
||||
this.disabledTakePart = disabledTakePart;
|
||||
}
|
||||
|
||||
public List<Integer> getRemovedDeadlineIds() {
|
||||
@ -215,4 +214,8 @@ public class ConferenceDto {
|
||||
this.notSelectedPapers = notSelectedPapers;
|
||||
}
|
||||
|
||||
public String getDatesString() {
|
||||
return BEGIN_DATE + beginDate.toString().split(" ")[0] + " " + END_DATE + endDate.toString().split(" ")[0];
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -5,15 +5,15 @@ import java.util.List;
|
||||
public class ConferenceFilterDto {
|
||||
|
||||
private List<ConferenceDto> conferences;
|
||||
private Integer filterAuthorId;
|
||||
private Integer filterUserId;
|
||||
private Integer year;
|
||||
|
||||
public ConferenceFilterDto() {
|
||||
}
|
||||
|
||||
public ConferenceFilterDto(List<ConferenceDto> conferenceDtos, Integer filterAuthorId, Integer year) {
|
||||
public ConferenceFilterDto(List<ConferenceDto> conferenceDtos, Integer filterUserId, Integer year) {
|
||||
this.conferences = conferenceDtos;
|
||||
this.filterAuthorId = filterAuthorId;
|
||||
this.filterUserId = filterUserId;
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
@ -29,12 +29,12 @@ public class ConferenceFilterDto {
|
||||
this.conferences = conferences;
|
||||
}
|
||||
|
||||
public Integer getFilterAuthorId() {
|
||||
return filterAuthorId;
|
||||
public Integer getFilterUserId() {
|
||||
return filterUserId;
|
||||
}
|
||||
|
||||
public void setFilterAuthorId(Integer filterAuthorId) {
|
||||
this.filterAuthorId = filterAuthorId;
|
||||
public void setFilterUserId(Integer filterUserId) {
|
||||
this.filterUserId = filterUserId;
|
||||
}
|
||||
|
||||
public Integer getYear() {
|
||||
|
104
src/main/java/ru/ulstu/conference/model/ConferenceUser.java
Normal file
104
src/main/java/ru/ulstu/conference/model/ConferenceUser.java
Normal file
@ -0,0 +1,104 @@
|
||||
package ru.ulstu.conference.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import ru.ulstu.core.model.BaseEntity;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
@Entity
|
||||
@Table(name = "users_conference")
|
||||
public class ConferenceUser extends BaseEntity {
|
||||
|
||||
public enum Participation {
|
||||
INTRAMURAL("Очная"),
|
||||
EXTRAMURAL("Заочная");
|
||||
|
||||
private String participationName;
|
||||
|
||||
Participation(String name) {
|
||||
this.participationName = name;
|
||||
}
|
||||
|
||||
public String getParticipation() {
|
||||
return participationName;
|
||||
}
|
||||
}
|
||||
|
||||
public enum Deposit {
|
||||
ARTICLE("Статья"),
|
||||
REPORT("Доклад"),
|
||||
PRESENTATION("Презентация");
|
||||
|
||||
private String depositName;
|
||||
|
||||
Deposit(String name) {
|
||||
this.depositName = name;
|
||||
}
|
||||
|
||||
public String getDeposit() {
|
||||
return depositName;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@NotNull
|
||||
@Column(name = "participation", nullable = false)
|
||||
@Enumerated(value = EnumType.STRING)
|
||||
private Participation participation = Participation.INTRAMURAL;
|
||||
|
||||
@NotNull
|
||||
@Column(name = "deposit", nullable = false)
|
||||
@Enumerated(value = EnumType.STRING)
|
||||
private Deposit deposit = Deposit.ARTICLE;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "users_id")
|
||||
private User user;
|
||||
|
||||
public ConferenceUser() {
|
||||
}
|
||||
|
||||
public ConferenceUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
@JsonCreator
|
||||
public ConferenceUser(@JsonProperty("id") Integer id,
|
||||
@JsonProperty("deposit") Participation participation,
|
||||
@JsonProperty("deposit") Deposit deposit,
|
||||
@JsonProperty("user") User user) {
|
||||
this.setId(id);
|
||||
this.participation = participation;
|
||||
this.deposit = deposit;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
|
||||
public Participation getParticipation() {
|
||||
return participation;
|
||||
}
|
||||
|
||||
public void setParticipation(Participation participation) {
|
||||
this.participation = participation;
|
||||
}
|
||||
|
||||
public Deposit getDeposit() {
|
||||
return deposit;
|
||||
}
|
||||
|
||||
public void setDeposit(Deposit deposit) {
|
||||
this.deposit = deposit;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
}
|
@ -1,7 +1,14 @@
|
||||
package ru.ulstu.conference.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import ru.ulstu.conference.model.Conference;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface ConferenceRepository extends JpaRepository<Conference, Integer> {
|
||||
@Query("SELECT c FROM Conference c LEFT JOIN c.users u WHERE (:user IS NULL OR u.user = :user) AND (YEAR(c.beginDate) = :year OR :year IS NULL)")
|
||||
List<Conference> filter(@Param("user") User user, @Param("year") Integer year);
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package ru.ulstu.conference.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import ru.ulstu.conference.model.ConferenceUser;
|
||||
|
||||
public interface ConferenceUserRepository extends JpaRepository<ConferenceUser, Integer> {
|
||||
}
|
@ -5,12 +5,18 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.ulstu.conference.model.Conference;
|
||||
import ru.ulstu.conference.model.ConferenceDto;
|
||||
import ru.ulstu.conference.model.ConferenceFilterDto;
|
||||
import ru.ulstu.conference.model.ConferenceUser;
|
||||
import ru.ulstu.conference.repository.ConferenceRepository;
|
||||
import ru.ulstu.deadline.service.DeadlineService;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.paper.service.PaperService;
|
||||
import ru.ulstu.user.model.User;
|
||||
import ru.ulstu.user.service.UserService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||
@ -21,17 +27,37 @@ public class ConferenceService {
|
||||
private final static int MAX_DISPLAY_SIZE = 40;
|
||||
|
||||
private final ConferenceRepository conferenceRepository;
|
||||
private final ConferenceUserService conferenceUserService;
|
||||
private final DeadlineService deadlineService;
|
||||
private final PaperService paperService;
|
||||
private final UserService userService;
|
||||
|
||||
public ConferenceService(ConferenceRepository conferenceRepository,
|
||||
ConferenceUserService conferenceUserService,
|
||||
DeadlineService deadlineService,
|
||||
PaperService paperService) {
|
||||
PaperService paperService,
|
||||
UserService userService) {
|
||||
this.conferenceRepository = conferenceRepository;
|
||||
this.conferenceUserService = conferenceUserService;
|
||||
this.deadlineService = deadlineService;
|
||||
this.paperService = paperService;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
public ConferenceDto getExistConferenceById(Integer id) {
|
||||
ConferenceDto conferenceDto = findOneDto(id);
|
||||
conferenceDto.setNotSelectedPapers(getNotSelectPapers(conferenceDto.getPaperIds()));
|
||||
conferenceDto.setDisabledTakePart(isCurrentUserParticipant(conferenceDto.getUsers()));
|
||||
return conferenceDto;
|
||||
}
|
||||
|
||||
public ConferenceDto getNewConference() {
|
||||
ConferenceDto conferenceDto = new ConferenceDto();
|
||||
conferenceDto.setNotSelectedPapers(getNotSelectPapers(new ArrayList<Integer>()));
|
||||
return conferenceDto;
|
||||
}
|
||||
|
||||
|
||||
public List<Conference> findAll() {
|
||||
return conferenceRepository.findAll();
|
||||
}
|
||||
@ -88,10 +114,27 @@ public class ConferenceService {
|
||||
conferenceDto.getNotSelectedPapers().add(removedPaper);
|
||||
}
|
||||
|
||||
public List<Paper> getConferencePapers(List<Integer> paperIds) {
|
||||
public void takePart(ConferenceDto conferenceDto) throws IOException {
|
||||
conferenceDto.getUsers().add(new ConferenceUser(userService.getCurrentUser()));
|
||||
conferenceDto.setDisabledTakePart(true);
|
||||
}
|
||||
|
||||
public List<Paper> getNotSelectPapers(List<Integer> paperIds) {
|
||||
return paperService.findAllNotSelect(paperIds);
|
||||
}
|
||||
|
||||
public List<User> getAllUsers() {
|
||||
return userService.findAll();
|
||||
}
|
||||
|
||||
public List<ConferenceUser.Participation> getAllParticipations() {
|
||||
return Arrays.asList(ConferenceUser.Participation.values());
|
||||
}
|
||||
|
||||
public List<ConferenceUser.Deposit> getAllDeposit() {
|
||||
return Arrays.asList(ConferenceUser.Deposit.values());
|
||||
}
|
||||
|
||||
private Conference copyFromDto(Conference conference, ConferenceDto conferenceDto) throws IOException {
|
||||
conference.setTitle(conferenceDto.getTitle());
|
||||
conference.setDescription(conferenceDto.getDescription());
|
||||
@ -101,6 +144,7 @@ public class ConferenceService {
|
||||
conference.setEndDate(conferenceDto.getEndDate());
|
||||
conference.setPapers(conferenceDto.getPapers());
|
||||
conference.setDeadlines(deadlineService.saveOrCreate(conferenceDto.getDeadlines()));
|
||||
conference.setUsers(conferenceUserService.saveOrCreate(conferenceDto.getUsers()));
|
||||
if (conferenceDto.getPaperIds() != null && !conferenceDto.getPaperIds().isEmpty()) {
|
||||
conferenceDto.getPaperIds().forEach(paperId ->
|
||||
conference.getPapers().add(paperService.findEntityById(paperId)));
|
||||
@ -109,4 +153,14 @@ public class ConferenceService {
|
||||
}
|
||||
|
||||
|
||||
public boolean isCurrentUserParticipant(List<ConferenceUser> conferenceUsers) {
|
||||
return conferenceUsers.stream().anyMatch(participant -> participant.getUser().equals(userService.getCurrentUser()));
|
||||
}
|
||||
|
||||
public List<ConferenceDto> filter(ConferenceFilterDto conferenceFilterDto) {
|
||||
return convert(conferenceRepository.filter(
|
||||
conferenceFilterDto.getFilterUserId() == null ? null : userService.findById(conferenceFilterDto.getFilterUserId()),
|
||||
conferenceFilterDto.getYear()), ConferenceDto::new);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,48 @@
|
||||
package ru.ulstu.conference.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.ulstu.conference.model.ConferenceUser;
|
||||
import ru.ulstu.conference.repository.ConferenceUserRepository;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class ConferenceUserService {
|
||||
|
||||
private final ConferenceUserRepository conferenceUserRepository;
|
||||
|
||||
public ConferenceUserService(ConferenceUserRepository conferenceUserRepository) {
|
||||
this.conferenceUserRepository = conferenceUserRepository;
|
||||
}
|
||||
|
||||
public List<ConferenceUser> saveOrCreate(List<ConferenceUser> users) {
|
||||
return users
|
||||
.stream()
|
||||
.map(user -> {
|
||||
return user.getId() != null ? update(user) : create(user);
|
||||
}).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public ConferenceUser update(ConferenceUser user) {
|
||||
ConferenceUser updateUser = conferenceUserRepository.findOne(user.getId());
|
||||
updateUser.setDeposit(user.getDeposit());
|
||||
updateUser.setParticipation(user.getParticipation());
|
||||
conferenceUserRepository.save(updateUser);
|
||||
return updateUser;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public ConferenceUser create(ConferenceUser user) {
|
||||
ConferenceUser newUser = new ConferenceUser();
|
||||
newUser.setDeposit(user.getDeposit());
|
||||
newUser.setParticipation(user.getParticipation());
|
||||
newUser.setUser(user.getUser());
|
||||
newUser = conferenceUserRepository.save(newUser);
|
||||
return newUser;
|
||||
}
|
||||
|
||||
|
||||
}
|
@ -24,7 +24,7 @@ public class DateUtils {
|
||||
return cal;
|
||||
}
|
||||
|
||||
public static List<Month> getMonths () {
|
||||
public static List<Month> getMonths() {
|
||||
return Arrays.asList(Month.values());
|
||||
}
|
||||
|
||||
|
@ -19,6 +19,9 @@ public class FileData extends BaseEntity {
|
||||
|
||||
private byte[] data;
|
||||
|
||||
@Column(name = "is_latex_attach")
|
||||
private Boolean isLatexAttach;
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
@ -50,4 +53,12 @@ public class FileData extends BaseEntity {
|
||||
public void setData(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Boolean isLatexAttach() {
|
||||
return isLatexAttach;
|
||||
}
|
||||
|
||||
public void setLatexAttach(Boolean latexAttach) {
|
||||
isLatexAttach = latexAttach;
|
||||
}
|
||||
}
|
||||
|
@ -9,6 +9,7 @@ public class FileDataDto {
|
||||
private String fileName;
|
||||
private String tmpFileName;
|
||||
private boolean deleted;
|
||||
private Boolean isLatexAttach;
|
||||
|
||||
public FileDataDto() {
|
||||
}
|
||||
@ -16,17 +17,20 @@ public class FileDataDto {
|
||||
@JsonCreator
|
||||
public FileDataDto(@JsonProperty("id") Integer id,
|
||||
@JsonProperty("name") String name,
|
||||
@JsonProperty("isLatexAttach") Boolean isLatexAttach,
|
||||
@JsonProperty("fileName") String fileName,
|
||||
@JsonProperty("tmpFileName") String tmpFileName) {
|
||||
this.id = id;
|
||||
this.name = name;
|
||||
this.fileName = fileName;
|
||||
this.tmpFileName = tmpFileName;
|
||||
this.isLatexAttach = isLatexAttach;
|
||||
}
|
||||
|
||||
public FileDataDto(FileData fileData) {
|
||||
this.id = fileData.getId();
|
||||
this.name = fileData.getName();
|
||||
this.isLatexAttach = fileData.isLatexAttach();
|
||||
}
|
||||
|
||||
public FileDataDto(String fileName, String tmpFileName) {
|
||||
@ -73,4 +77,19 @@ public class FileDataDto {
|
||||
this.deleted = deleted;
|
||||
}
|
||||
|
||||
public Boolean isLatexAttach() {
|
||||
return isLatexAttach;
|
||||
}
|
||||
|
||||
public Boolean getIsLatexAttach() {
|
||||
return isLatexAttach;
|
||||
}
|
||||
|
||||
public void setLatexAttach(Boolean latexAttach) {
|
||||
isLatexAttach = latexAttach;
|
||||
}
|
||||
|
||||
public void setIsLatexAttach(Boolean latexAttach) {
|
||||
isLatexAttach = latexAttach;
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,10 @@ import org.springframework.web.multipart.MultipartFile;
|
||||
import ru.ulstu.file.model.FileData;
|
||||
import ru.ulstu.file.model.FileDataDto;
|
||||
import ru.ulstu.file.repostory.FileRepository;
|
||||
import ru.ulstu.paper.model.PaperDto;
|
||||
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@ -15,6 +18,7 @@ import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
|
||||
@ -107,6 +111,7 @@ public class FileService {
|
||||
|
||||
private FileData copyFromDto(FileData fileData, FileDataDto fileDataDto) {
|
||||
fileData.setName(fileDataDto.getName());
|
||||
fileData.setLatexAttach(fileDataDto.isLatexAttach());
|
||||
return fileData;
|
||||
}
|
||||
|
||||
@ -118,4 +123,27 @@ public class FileService {
|
||||
public FileDataDto createFromMultipartFile(MultipartFile multipartFile) throws IOException {
|
||||
return new FileDataDto(multipartFile.getOriginalFilename(), uploadToTmpDir(multipartFile));
|
||||
}
|
||||
|
||||
public void createLatexAttachs(PaperDto paper) throws IOException {
|
||||
for (FileDataDto fileDataDto : paper.getFiles()
|
||||
.stream()
|
||||
.filter(f -> (f.isLatexAttach() != null && f.isLatexAttach()) && !f.isDeleted())
|
||||
.collect(Collectors.toList())) {
|
||||
if (fileDataDto.getId() == null) {
|
||||
File oldFile = getTmpFilePath(fileDataDto.getTmpFileName()).toFile();
|
||||
File renamed = getTmpFilePath(fileDataDto.getName()).toFile();
|
||||
oldFile.renameTo(renamed);
|
||||
} else {
|
||||
Files.write(getTmpFilePath(fileDataDto.getName()), fileRepository.findOne(fileDataDto.getId()).getData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public File createLatexFile(PaperDto paper) throws IOException {
|
||||
BufferedWriter writer = Files.newBufferedWriter(getTmpFilePath(paper.getTitle() + ".tex"));
|
||||
writer.write(paper.getLatexText());
|
||||
writer.close();
|
||||
|
||||
return getTmpFilePath(paper.getTitle() + ".tex").toFile();
|
||||
}
|
||||
}
|
||||
|
@ -3,16 +3,12 @@ package ru.ulstu.grant.controller;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
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.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
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 springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
import javax.validation.Valid;
|
||||
@ -21,10 +17,7 @@ import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.util.StringUtils.isEmpty;
|
||||
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.REDIRECT_TO;
|
||||
import static ru.ulstu.core.controller.Navigation.hasErrors;
|
||||
import static ru.ulstu.core.controller.Navigation.*;
|
||||
|
||||
|
||||
@Controller()
|
||||
@ -57,27 +50,42 @@ public class GrantController {
|
||||
}
|
||||
|
||||
@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);
|
||||
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);
|
||||
return String.format(REDIRECT_TO, GRANTS_PAGE);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/grant", params = "filterUsers")
|
||||
public String filterUsers() {
|
||||
return GRANT_PAGE;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/grant", params = "addDeadline")
|
||||
public String addDeadline(@Valid GrantDto grantDto, Errors errors) {
|
||||
filterEmptyDeadlines(grantDto);
|
||||
hasErrors(errors, GRANT_PAGE);
|
||||
if (errors.hasErrors()) {
|
||||
return GRANT_PAGE;
|
||||
}
|
||||
grantDto.getDeadlines().add(new Deadline());
|
||||
return GRANT_PAGE;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/grant", params = "createProject")
|
||||
public String createProject(@Valid GrantDto grantDto, Errors errors) {
|
||||
hasErrors(errors, GRANT_PAGE);
|
||||
if (errors.hasErrors()) {
|
||||
return GRANT_PAGE;
|
||||
}
|
||||
grantService.createProject(grantDto);
|
||||
return GRANT_PAGE;
|
||||
}
|
||||
@ -93,6 +101,11 @@ public class GrantController {
|
||||
return grantService.getGrantStatuses();
|
||||
}
|
||||
|
||||
@ModelAttribute("allAuthors")
|
||||
public List<User> getAllAuthors(GrantDto grantDto) {
|
||||
return grantService.getGrantAuthors(grantDto);
|
||||
}
|
||||
|
||||
private void filterEmptyDeadlines(GrantDto grantDto) {
|
||||
grantDto.setDeadlines(grantDto.getDeadlines().stream()
|
||||
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
||||
|
@ -2,28 +2,19 @@ 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.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.*;
|
||||
|
||||
@Entity
|
||||
@Table(name = "grants")
|
||||
public class Grant extends BaseEntity {
|
||||
public class Grant extends BaseEntity implements UserContainer {
|
||||
public enum GrantStatus {
|
||||
APPLICATION("Заявка"),
|
||||
ON_COMPETITION("Отправлен на конкурс"),
|
||||
@ -52,6 +43,7 @@ public class Grant extends BaseEntity {
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "grant_id")
|
||||
@OrderBy("date")
|
||||
private List<Deadline> deadlines = new ArrayList<>();
|
||||
|
||||
//Описание гранта
|
||||
@ -67,6 +59,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 +115,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,12 @@ public class GrantDto {
|
||||
private String comment;
|
||||
private String applicationFileName;
|
||||
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() {
|
||||
deadlines.add(new Deadline());
|
||||
@ -29,7 +43,13 @@ 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,
|
||||
@JsonProperty("wasLeader") boolean wasLeader,
|
||||
@JsonProperty("hasAge") boolean hasAge,
|
||||
@JsonProperty("hasDegree") boolean hasDegree) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.status = status;
|
||||
@ -37,6 +57,11 @@ public class GrantDto {
|
||||
this.comment = comment;
|
||||
this.applicationFileName = null;
|
||||
this.project = project;
|
||||
this.authors = authors;
|
||||
this.leaderId = leaderId;
|
||||
this.wasLeader = wasLeader;
|
||||
this.hasAge = hasAge;
|
||||
this.hasDegree = hasDegree;
|
||||
}
|
||||
|
||||
public GrantDto(Grant grant) {
|
||||
@ -47,6 +72,12 @@ 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();
|
||||
this.wasLeader = false;
|
||||
this.hasAge = false;
|
||||
this.hasDegree = false;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
@ -104,4 +135,59 @@ 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;
|
||||
}
|
||||
|
||||
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 ru.ulstu.grant.model.Grant;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
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.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;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
||||
@ -30,15 +33,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 +79,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 +97,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 +110,6 @@ public class GrantService {
|
||||
if (grant.getApplication() != null) {
|
||||
fileService.deleteFile(grant.getApplication());
|
||||
}
|
||||
//возможно при удалении гранта будет удаляться и проект, к нему привязанный
|
||||
grantRepository.delete(grant);
|
||||
}
|
||||
|
||||
@ -107,13 +118,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 +138,22 @@ public class GrantService {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
@ -31,14 +31,13 @@ public abstract class OdinField implements Comparable {
|
||||
return this.name().toLowerCase();
|
||||
}
|
||||
}
|
||||
|
||||
private Field field;
|
||||
protected final OdinFieldType fieldType;
|
||||
protected final String fieldName;
|
||||
protected final String caption;
|
||||
protected final OdinVisible.OdinVisibleType visible;
|
||||
protected final boolean readOnly;
|
||||
protected final boolean notEmpty;
|
||||
private Field field;
|
||||
|
||||
public OdinField(Field field, OdinFieldType fieldType) {
|
||||
this.field = field;
|
||||
@ -126,8 +125,12 @@ public abstract class OdinField implements Comparable {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
OdinField odinField = (OdinField) o;
|
||||
return Objects.equals(fieldName, odinField.fieldName);
|
||||
}
|
||||
|
@ -1,29 +1,30 @@
|
||||
package ru.ulstu.paper.controller;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
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.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.paper.model.PaperDto;
|
||||
import ru.ulstu.paper.model.PaperFilterDto;
|
||||
import ru.ulstu.paper.service.LatexService;
|
||||
import ru.ulstu.paper.service.PaperService;
|
||||
import ru.ulstu.user.model.User;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.io.IOException;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.nio.charset.StandardCharsets.UTF_8;
|
||||
import static org.springframework.util.StringUtils.isEmpty;
|
||||
|
||||
|
||||
@ -32,9 +33,11 @@ import static org.springframework.util.StringUtils.isEmpty;
|
||||
@ApiIgnore
|
||||
public class PaperController {
|
||||
private final PaperService paperService;
|
||||
private final LatexService latexService;
|
||||
|
||||
public PaperController(PaperService paperService) {
|
||||
public PaperController(PaperService paperService, LatexService latexService) {
|
||||
this.paperService = paperService;
|
||||
this.latexService = latexService;
|
||||
}
|
||||
|
||||
@GetMapping("/papers")
|
||||
@ -111,6 +114,14 @@ public class PaperController {
|
||||
return years;
|
||||
}
|
||||
|
||||
@PostMapping("/generatePdf")
|
||||
public ResponseEntity<byte[]> getPdfFile(PaperDto paper) throws IOException, InterruptedException {
|
||||
HttpHeaders headers = new HttpHeaders();
|
||||
headers.add("Content-Disposition", "attachment; filename='" +
|
||||
URLEncoder.encode(paper.getTitle() + ".pdf", UTF_8.toString()) + "'");
|
||||
return new ResponseEntity<>(latexService.generatePdfFromLatexFile(paper), headers, HttpStatus.OK);
|
||||
}
|
||||
|
||||
private void filterEmptyDeadlines(PaperDto paperDto) {
|
||||
paperDto.setDeadlines(paperDto.getDeadlines().stream()
|
||||
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
||||
|
@ -10,25 +10,8 @@ import ru.ulstu.file.model.FileData;
|
||||
import ru.ulstu.timeline.model.Event;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
import javax.persistence.Column;
|
||||
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.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
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;
|
||||
import javax.persistence.*;
|
||||
import java.util.*;
|
||||
|
||||
@Entity
|
||||
public class Paper extends BaseEntity implements UserContainer {
|
||||
@ -91,6 +74,9 @@ public class Paper extends BaseEntity implements UserContainer {
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
private Set<User> authors = new HashSet<>();
|
||||
|
||||
@Column(name = "latex_text")
|
||||
private String latexText;
|
||||
|
||||
public PaperStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
@ -179,6 +165,14 @@ public class Paper extends BaseEntity implements UserContainer {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getLatexText() {
|
||||
return latexText;
|
||||
}
|
||||
|
||||
public void setLatexText(String latexText) {
|
||||
this.latexText = latexText;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<User> getUsers() {
|
||||
return getAuthors();
|
||||
|
@ -4,8 +4,8 @@ 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.file.model.FileDataDto;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.file.model.FileDataDto;
|
||||
import ru.ulstu.user.model.UserDto;
|
||||
|
||||
import javax.validation.constraints.Size;
|
||||
@ -36,6 +36,7 @@ public class PaperDto {
|
||||
private Set<Integer> authorIds;
|
||||
private Set<UserDto> authors;
|
||||
private Integer filterAuthorId;
|
||||
private String latexText;
|
||||
|
||||
public PaperDto() {
|
||||
deadlines.add(new Deadline());
|
||||
@ -49,6 +50,7 @@ public class PaperDto {
|
||||
@JsonProperty("updateDate") Date updateDate,
|
||||
@JsonProperty("deadlines") List<Deadline> deadlines,
|
||||
@JsonProperty("comment") String comment,
|
||||
@JsonProperty("latex_text") String latexText,
|
||||
@JsonProperty("url") String url,
|
||||
@JsonProperty("locked") Boolean locked,
|
||||
@JsonProperty("files") List<FileDataDto> files,
|
||||
@ -62,6 +64,7 @@ public class PaperDto {
|
||||
this.deadlines = deadlines;
|
||||
this.comment = comment;
|
||||
this.url = url;
|
||||
this.latexText = latexText;
|
||||
this.locked = locked;
|
||||
this.files = files;
|
||||
this.authors = authors;
|
||||
@ -76,6 +79,7 @@ public class PaperDto {
|
||||
this.deadlines = paper.getDeadlines();
|
||||
this.comment = paper.getComment();
|
||||
this.url = paper.getUrl();
|
||||
this.latexText = paper.getLatexText();
|
||||
this.locked = paper.getLocked();
|
||||
this.files = convert(paper.getFiles(), FileDataDto::new);
|
||||
this.authorIds = convert(paper.getAuthors(), user -> user.getId());
|
||||
@ -178,6 +182,14 @@ public class PaperDto {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getLatexText() {
|
||||
return latexText;
|
||||
}
|
||||
|
||||
public void setLatexText(String latexText) {
|
||||
this.latexText = latexText;
|
||||
}
|
||||
|
||||
public String getAuthorsString() {
|
||||
return StringUtils.abbreviate(authors
|
||||
.stream()
|
||||
|
76
src/main/java/ru/ulstu/paper/service/LatexService.java
Normal file
76
src/main/java/ru/ulstu/paper/service/LatexService.java
Normal file
@ -0,0 +1,76 @@
|
||||
package ru.ulstu.paper.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.ulstu.file.service.FileService;
|
||||
import ru.ulstu.paper.model.PaperDto;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
|
||||
@Service
|
||||
public class LatexService {
|
||||
private final String pdfLatexError = "Errors occurred while executing pdfLaTeX.";
|
||||
private final String bibtexError = "Errors occurred while executing bibtex.";
|
||||
private String errorMessage;
|
||||
private File pdfFile;
|
||||
private FileService fileService;
|
||||
|
||||
public LatexService(FileService fileService) {
|
||||
this.fileService = fileService;
|
||||
}
|
||||
|
||||
public byte[] generatePdfFromLatexFile(PaperDto paper) throws IOException, InterruptedException {
|
||||
fileService.createLatexAttachs(paper);
|
||||
File tex = fileService.createLatexFile(paper);
|
||||
|
||||
if (!generate(paper.getTitle(), tex.getParentFile())) {
|
||||
throw new IOException(errorMessage);
|
||||
}
|
||||
|
||||
return Files.readAllBytes(pdfFile.toPath());
|
||||
}
|
||||
|
||||
private int startProcess(String[] args, File dir, String message) throws IOException, InterruptedException {
|
||||
ProcessBuilder processBuilder = new ProcessBuilder(args);
|
||||
processBuilder.redirectErrorStream(true);
|
||||
processBuilder.directory(dir);
|
||||
|
||||
Process process = processBuilder.start();
|
||||
InputStreamReader inputStreamReader = new InputStreamReader(process.getInputStream());
|
||||
|
||||
try (BufferedReader bufferedReader = new BufferedReader(inputStreamReader)) {
|
||||
while ((bufferedReader.readLine()) != null) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
int exitCode = process.waitFor();
|
||||
if (exitCode != 0) {
|
||||
errorMessage = message + " Exit value of the process: " + exitCode;
|
||||
}
|
||||
return exitCode;
|
||||
}
|
||||
|
||||
private boolean generate(String filename, File dir) throws IOException, InterruptedException {
|
||||
startProcess(new String[]{"pdflatex", filename, "--interaction=nonstopmode"}, dir, pdfLatexError);
|
||||
startProcess(new String[]{"bibtex", filename}, dir, bibtexError);
|
||||
if (startProcess(new String[]{"pdflatex", filename, "--interaction=nonstopmode"}, dir, pdfLatexError) != 0) {
|
||||
return false;
|
||||
}
|
||||
return checkPdf(filename, dir);
|
||||
}
|
||||
|
||||
private boolean checkPdf(String filename, File dir) {
|
||||
pdfFile = new File(dir.getAbsolutePath() + File.separator + filename + ".pdf");
|
||||
|
||||
if (pdfFile.isFile()) {
|
||||
return true;
|
||||
} else {
|
||||
errorMessage = "The pdf file could not be created.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
@ -16,21 +16,13 @@ import ru.ulstu.user.model.User;
|
||||
import ru.ulstu.user.service.UserService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.stream.Collectors.toList;
|
||||
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
||||
import static ru.ulstu.paper.model.Paper.PaperStatus.ATTENTION;
|
||||
import static ru.ulstu.paper.model.Paper.PaperStatus.COMPLETED;
|
||||
import static ru.ulstu.paper.model.Paper.PaperStatus.DRAFT;
|
||||
import static ru.ulstu.paper.model.Paper.PaperStatus.FAILED;
|
||||
import static ru.ulstu.paper.model.Paper.PaperStatus.ON_PREPARATION;
|
||||
import static ru.ulstu.paper.model.Paper.PaperStatus.*;
|
||||
|
||||
@Service
|
||||
public class PaperService {
|
||||
@ -95,6 +87,7 @@ public class PaperService {
|
||||
private Paper copyFromDto(Paper paper, PaperDto paperDto) throws IOException {
|
||||
paper.setComment(paperDto.getComment());
|
||||
paper.setUrl(paperDto.getUrl());
|
||||
paper.setLatexText(paperDto.getLatexText());
|
||||
paper.setCreateDate(paper.getCreateDate() == null ? new Date() : paper.getCreateDate());
|
||||
paper.setLocked(paperDto.getLocked());
|
||||
paper.setStatus(paperDto.getStatus() == null ? DRAFT : paperDto.getStatus());
|
||||
|
@ -5,14 +5,7 @@ import org.hibernate.validator.constraints.Email;
|
||||
import ru.ulstu.configuration.Constants;
|
||||
import ru.ulstu.core.model.BaseEntity;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.*;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
@ -85,6 +78,28 @@ public class User extends BaseEntity {
|
||||
@BatchSize(size = 20)
|
||||
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() {
|
||||
roles = new HashSet<>();
|
||||
activated = false;
|
||||
@ -189,6 +204,22 @@ public class User extends BaseEntity {
|
||||
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() {
|
||||
return String.format(USER_ABBREVIATE_TEMPLATE,
|
||||
lastName == null ? "" : lastName,
|
||||
|
@ -14,10 +14,7 @@ import ru.ulstu.user.controller.UserController;
|
||||
|
||||
import javax.validation.constraints.Pattern;
|
||||
import javax.validation.constraints.Size;
|
||||
import java.util.Collection;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ru.ulstu.odin.model.annotation.OdinString.OdinStringType.PASSWORD;
|
||||
@ -70,6 +67,10 @@ public class UserDto implements OdinDto {
|
||||
@Size(min = Constants.MIN_PASSWORD_LENGTH, max = 50)
|
||||
private String passwordConfirm;
|
||||
|
||||
private Date birthDate;
|
||||
|
||||
private User.UserDegree degree;
|
||||
|
||||
public UserDto() {
|
||||
activated = false;
|
||||
roles = new LinkedHashSet<>();
|
||||
@ -86,6 +87,8 @@ public class UserDto implements OdinDto {
|
||||
this.roles.addAll(user.getRoles().stream()
|
||||
.map(UserRoleDto::new)
|
||||
.collect(Collectors.toList()));
|
||||
this.birthDate = user.getBirthDate();
|
||||
this.degree = user.getDegree();
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
@ -163,6 +166,22 @@ public class UserDto implements OdinDto {
|
||||
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
|
||||
public boolean isPasswordsValid() {
|
||||
if (StringUtils.isEmpty(password) || StringUtils.isEmpty(passwordConfirm)) {
|
||||
@ -188,6 +207,8 @@ public class UserDto implements OdinDto {
|
||||
", roles=" + roles +
|
||||
", password='" + password + '\'' +
|
||||
", 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.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
import java.util.Date;
|
||||
@ -25,4 +27,11 @@ public interface UserRepository extends JpaRepository<User, Integer> {
|
||||
|
||||
@EntityGraph(attributePaths = "roles")
|
||||
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);
|
||||
}
|
||||
|
@ -16,33 +16,13 @@ import ru.ulstu.core.error.EntityIdIsNullException;
|
||||
import ru.ulstu.core.jpa.OffsetablePageRequest;
|
||||
import ru.ulstu.core.model.BaseEntity;
|
||||
import ru.ulstu.core.model.response.PageableItems;
|
||||
import ru.ulstu.user.error.UserActivationError;
|
||||
import ru.ulstu.user.error.UserEmailExistsException;
|
||||
import ru.ulstu.user.error.UserIdExistsException;
|
||||
import ru.ulstu.user.error.UserIsUndeadException;
|
||||
import ru.ulstu.user.error.UserLoginExistsException;
|
||||
import ru.ulstu.user.error.UserNotActivatedException;
|
||||
import ru.ulstu.user.error.UserNotFoundException;
|
||||
import ru.ulstu.user.error.UserPasswordsNotValidOrNotMatchException;
|
||||
import ru.ulstu.user.error.UserResetKeyError;
|
||||
import ru.ulstu.user.model.User;
|
||||
import ru.ulstu.user.model.UserDto;
|
||||
import ru.ulstu.user.model.UserListDto;
|
||||
import ru.ulstu.user.model.UserResetPasswordDto;
|
||||
import ru.ulstu.user.model.UserRole;
|
||||
import ru.ulstu.user.model.UserRoleConstants;
|
||||
import ru.ulstu.user.model.UserRoleDto;
|
||||
import ru.ulstu.user.error.*;
|
||||
import ru.ulstu.user.model.*;
|
||||
import ru.ulstu.user.repository.UserRepository;
|
||||
import ru.ulstu.user.repository.UserRoleRepository;
|
||||
import ru.ulstu.user.util.UserUtils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
@ -324,4 +304,8 @@ public class UserService implements UserDetailsService {
|
||||
}
|
||||
return user;
|
||||
}
|
||||
|
||||
public List<User> filterByAgeAndDegree(boolean hasDegree, boolean hasAge) {
|
||||
return userRepository.filterByAgeAndDegree(hasDegree, hasAge);
|
||||
}
|
||||
}
|
||||
|
14
src/main/resources/db/changelog-20190323_000001-schema.xml
Normal file
14
src/main/resources/db/changelog-20190323_000001-schema.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?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="masha" id="20190323_000000-1">
|
||||
<addColumn tableName="paper">
|
||||
<column name="latex_text" type="varchar"/>
|
||||
</addColumn>
|
||||
<addColumn tableName="file">
|
||||
<column name="is_latex_attach" type="boolean"/>
|
||||
</addColumn>
|
||||
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
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>
|
14
src/main/resources/db/changelog-20190417_000000-schema.xml
Normal file
14
src/main/resources/db/changelog-20190417_000000-schema.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?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="vova" id="20190417_000000-1">
|
||||
<addColumn tableName="users_conference">
|
||||
<column name="id" type="integer"></column>
|
||||
<column name="version" type="integer"></column>
|
||||
</addColumn>
|
||||
<addPrimaryKey columnNames="id" constraintName="pk_users_conference" tableName="users_conference"/>
|
||||
<modifyDataType tableName="users_conference" columnName="participation" newDataType="varchar(255)"/>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
@ -24,6 +24,10 @@
|
||||
<include file="db/changelog-20190331_000000-schema.xml"/>
|
||||
<include file="db/changelog-20190331_000010-schema.xml"/>
|
||||
<include file="db/changelog-20190410_000000-schema.xml"/>
|
||||
<include file="db/changelog-20190417_000000-schema.xml"/>
|
||||
<include file="db/changelog-20190418_000000-schema.xml"/>
|
||||
<include file="db/changelog-20190323_000001-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>
|
@ -3,7 +3,7 @@ body {
|
||||
}
|
||||
|
||||
.conference-row .col:hover {
|
||||
background-color: #eaeaea;
|
||||
background-color: #f3f3f3;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
|
||||
@ -11,7 +11,13 @@ body {
|
||||
color: white;
|
||||
}
|
||||
|
||||
.filter .dropdown {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.conference-row .col .text-decoration {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
|
||||
.form-group textarea {
|
||||
@ -43,7 +49,44 @@ body {
|
||||
|
||||
.member {
|
||||
margin: 0;
|
||||
height: 40px;
|
||||
max-height: 40px;
|
||||
}
|
||||
.member select {
|
||||
appearance: none;
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
border: none;
|
||||
outline: none;
|
||||
padding: 0.5rem 1.75em 0.5rem 0.5em;
|
||||
display: inline-block;
|
||||
background: transparent url("https://cdn3.iconfinder.com/data/icons/faticons/32/arrow-down-01-16.png") no-repeat right 7px center;
|
||||
|
||||
}
|
||||
|
||||
.member select:nth-child(4) {
|
||||
border-right: 1px solid #ced4da;
|
||||
}
|
||||
|
||||
|
||||
.member-name {
|
||||
padding: .75rem 1.25rem;
|
||||
cursor: default;
|
||||
outline: none;
|
||||
border: none;
|
||||
border-right: 1px solid #ced4da;
|
||||
}
|
||||
|
||||
#take-part[disabled=disabled] {
|
||||
background-color: #ced4da;
|
||||
border-color: #c2c5c7;
|
||||
}
|
||||
|
||||
#take-part[disabled=disabled]:hover {
|
||||
background-color: #737475 !important;
|
||||
border-color: #5d5e5f !important;
|
||||
}
|
||||
|
||||
|
||||
.paper-list {
|
||||
height: 200px;
|
||||
|
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;
|
||||
}
|
@ -1,5 +1,9 @@
|
||||
#files-list .row > div:nth-child(6) {
|
||||
#files-list .row > div:nth-child(7) {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.nav-tabs {
|
||||
margin-bottom: 20px;
|
||||
}
|
@ -1,17 +1,5 @@
|
||||
$(document).ready(function () {
|
||||
|
||||
$(".conference-row").mouseenter(function (event) {
|
||||
var conferenceRow = $(event.target).closest(".conference-row");
|
||||
$(conferenceRow).css("background-color", "#f8f9fa");
|
||||
$(conferenceRow).find(".remove-conference").removeClass("d-none");
|
||||
|
||||
});
|
||||
$(".conference-row").mouseleave(function (event) {
|
||||
var conferenceRow = $(event.target).closest(".conference-row");
|
||||
$(conferenceRow).css("background-color", "white");
|
||||
$(conferenceRow).closest(".conference-row").find(".remove-conference").addClass("d-none");
|
||||
});
|
||||
|
||||
$('a[data-confirm]').click(function(ev) {
|
||||
var href = $(this).attr('href');
|
||||
if (!$('#dataConfirmModal').length) {
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
var urlFileUpload = "/api/1.0/files/uploadTmpFile";
|
||||
var urlFileDownload = "/api/1.0/files/download/";
|
||||
var urlPdfGenerating = "/papers/generatePdf";
|
||||
var urlFileDownloadTmp = "/api/1.0/files/download-tmp/";
|
||||
|
||||
/* exported MessageTypesEnum */
|
||||
|
@ -97,38 +97,35 @@
|
||||
<div class="form-group">
|
||||
<label for="members">Участники:</label>
|
||||
<div class="member-list form-control list-group" id="members">
|
||||
<div class="member d-flex list-group-item justify-content-between p-1">
|
||||
<div class="member-name">
|
||||
Пользователь 1
|
||||
</div>
|
||||
<div class="member-participation">
|
||||
очная
|
||||
</div>
|
||||
<div class="member-deposit">
|
||||
статья
|
||||
</div>
|
||||
</div>
|
||||
<div class="member d-flex list-group-item p-0"
|
||||
th:each="user, rowStat : *{users}">
|
||||
<input type="hidden" th:field="*{users[__${rowStat.index}__].id}"/>
|
||||
<input type="hidden" th:field="*{users[__${rowStat.index}__].user}"/>
|
||||
<input class="member-name w-100" readonly="true"
|
||||
th:field="*{users[__${rowStat.index}__].user.lastName}"/>
|
||||
<select class="member-participation w-auto"
|
||||
th:field="*{users[__${rowStat.index}__].participation}">
|
||||
<option th:each="participation : ${allParticipation}"
|
||||
th:value="${participation}"
|
||||
th:text="${participation.participation}">Participation
|
||||
</option>
|
||||
|
||||
<div class="member d-flex list-group-item justify-content-between p-1">
|
||||
<div class="member-name">
|
||||
Пользователь 1
|
||||
</div>
|
||||
<div class="member-participation">
|
||||
очная
|
||||
</div>
|
||||
<div class="member-deposit">
|
||||
доклад
|
||||
</div>
|
||||
</select>
|
||||
<select class="member-deposit w-auto"
|
||||
th:field="*{users[__${rowStat.index}__].deposit}">
|
||||
<option th:each="deposit : ${allDeposit}" th:value="${deposit}"
|
||||
th:text="${deposit.deposit}">Deposit
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group d-flex justify-content-end">
|
||||
<button id="take-part" class="btn btn-primary"
|
||||
type="button">
|
||||
Принять участие
|
||||
</button>
|
||||
<input type="hidden" th:value="*{disabledTakePart}" th:name="disabledTakePart"/>
|
||||
<input id="take-part" class="btn btn-primary"
|
||||
type="submit" name="takePart" value="Принять участие"
|
||||
th:disabled="*{disabledTakePart}"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
|
@ -27,16 +27,19 @@
|
||||
<div class="col-md-3 col-sm-12">
|
||||
<div class="filter">
|
||||
<h5>Фильтр:</h5>
|
||||
<select class="form-control" id="author"
|
||||
onchange="this.form.submit();">
|
||||
<option value="">Все авторы</option>
|
||||
<option>lastName
|
||||
<select class="selectpicker form-control" id="user"
|
||||
th:field="${filteredConferences.filterUserId}"
|
||||
onchange="this.form.submit();" data-style="btn-primary" data-size="5">
|
||||
<option value="">Все участники</option>
|
||||
<option th:each="user: ${allUsers}" th:value="${user.id}"
|
||||
th:text="${user.lastName}">lastName
|
||||
</option>
|
||||
</select>
|
||||
<select class="form-control" id="year"
|
||||
onchange="this.form.submit();">
|
||||
<select class="selectpicker form-control" id="year" th:field="${filteredConferences.year}"
|
||||
onchange="this.form.submit();" data-style="btn-primary" data-size="5">
|
||||
<option value="">Все годы</option>
|
||||
<option>year
|
||||
<option th:each="year: ${allYears}" th:value="${year}"
|
||||
th:text="${year}">year
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
@ -5,13 +5,14 @@
|
||||
</head>
|
||||
<body>
|
||||
<div th:fragment="confLine (conference)" class="row text-left conference-row h3" style="background-color: white;">
|
||||
<div class="col">
|
||||
<a th:href="@{'conference?id='+${conference.id}}">
|
||||
<div class="col d-flex justify-content-between">
|
||||
<a th:href="@{'conference?id='+${conference.id}}" class="w-100 text-decoration">
|
||||
<span class="h5" th:text="${conference.title}"/>
|
||||
<span class="text-muted h6 float-right m-2" th:text="${conference.datesString}"/>
|
||||
</a>
|
||||
<input class="id-class" type="hidden" th:value="${conference.id}"/>
|
||||
<a class="remove-paper pull-right" th:href="@{'/conferences/delete/'+${conference.id}}"
|
||||
data-confirm="Удалить статью?">
|
||||
<a class="remove-paper pull-right m-auto" th:href="@{'/conferences/delete/'+${conference.id}}"
|
||||
data-confirm="Удалить конференцию?">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -10,7 +10,9 @@
|
||||
<span th:replace="grants/fragments/grantStatusFragment :: grantStatus(grantStatus=${grant.status})"/>
|
||||
</div>
|
||||
<div class="col col-10 text-right">
|
||||
<h7 class="service-heading" th:text="${grant.title}"> title</h7>
|
||||
<a th:href="'grant?id='+${grant.id}">
|
||||
<h7 class="service-heading" th:text="${grant.title}"> title</h7>
|
||||
</a>
|
||||
<p class="text-muted" th:text="${grant.status.statusName}"> status</p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -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,13 +3,12 @@
|
||||
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>
|
||||
|
||||
<div class="container" layout:fragment="content">
|
||||
|
||||
<section id="paper">
|
||||
<section id="grant">
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-lg-12 text-center">
|
||||
@ -17,6 +16,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} + ''}"
|
||||
@ -33,7 +33,6 @@
|
||||
class="alert alert-danger">Incorrect title</p>
|
||||
<p class="help-block text-danger"></p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="status">Статус:</label>
|
||||
<select class="form-control" th:field="*{status}" id="status">
|
||||
@ -51,11 +50,11 @@
|
||||
<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,31 +71,101 @@
|
||||
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">
|
||||
<label for="loader">Загрузить заявку:</label>
|
||||
<div id="loader">
|
||||
|
||||
</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">
|
||||
<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}"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
<div class="col-lg-12">
|
||||
<div class="form-group">
|
||||
@ -132,6 +201,19 @@
|
||||
$('.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>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -82,7 +82,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<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-content">
|
||||
<i class="fa fa-arrow-right fa-3x"></i>
|
||||
|
@ -0,0 +1,46 @@
|
||||
<!DOCTYPE HTML>
|
||||
<html xmlns:th="http://www.thymeleaf.org">
|
||||
<head>
|
||||
<meta charset="UTF-8"/>
|
||||
</head>
|
||||
<body>
|
||||
<body>
|
||||
<div th:fragment="filesList (isLatexAttach)" th:remove="tag">
|
||||
<th:block th:each="file, rowStat : *{files}">
|
||||
|
||||
<span th:if="${(!isLatexAttach and file.isLatexAttach == null) or file.isLatexAttach == isLatexAttach}"
|
||||
th:remove="tag">
|
||||
|
||||
<div class="row" th:id="|files${rowStat.index}|"
|
||||
th:style="${file.deleted} ? 'display: none;' :''">
|
||||
<input type="hidden" th:field="*{files[__${rowStat.index}__].id}"/>
|
||||
<input type="hidden"
|
||||
th:field="*{files[__${rowStat.index}__].deleted}"/>
|
||||
<input type="hidden"
|
||||
th:field="*{files[__${rowStat.index}__].name}"/>
|
||||
<input type="hidden"
|
||||
th:field="*{files[__${rowStat.index}__].tmpFileName}"/>
|
||||
<input type="hidden"
|
||||
th:field="*{files[__${rowStat.index}__].isLatexAttach}"/>
|
||||
<div class="col-2">
|
||||
<a class="btn btn-danger float-right"
|
||||
th:onclick="|$('#files${rowStat.index}\\.deleted').val('true'); $('#files${rowStat.index}').hide(); |">
|
||||
<span aria-hidden="true"><i class="fa fa-times"/></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-10">
|
||||
<a th:onclick="${file.id==null} ? 'downloadFile('+${file.tmpFileName}+',null,\''+${file.name}+'\')':
|
||||
'downloadFile(null,'+${file.id}+',\''+${file.name}+'\')' "
|
||||
href="javascript:void(0)"
|
||||
th:text="*{files[__${rowStat.index}__].name}">
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</span>
|
||||
</th:block>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
@ -20,35 +20,47 @@
|
||||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-lg-12">
|
||||
<form id="paper-form" method="post" th:action="@{'/papers/paper?id='+ *{id == null ? '' : id} + ''}"
|
||||
<form name="paperform" id="paper-form" method="post"
|
||||
th:action="@{'/papers/paper?id='+ *{id == null ? '' : id} + ''}"
|
||||
th:object="${paperDto}">
|
||||
<div class="row">
|
||||
<div class="col-md-7 col-sm-12">
|
||||
<input type="hidden" name="id" th:field="*{id}"/>
|
||||
<div class="form-group">
|
||||
<label for="title">Название:</label>
|
||||
<input class="form-control" id="title" type="text"
|
||||
placeholder="Название статьи"
|
||||
th:field="*{title}"/>
|
||||
<p th:if="${#fields.hasErrors('title')}" th:errors="*{title}"
|
||||
class="alert alert-danger">Incorrect title</p>
|
||||
<p class="help-block text-danger"></p>
|
||||
</div>
|
||||
<nav>
|
||||
<div class="nav nav-tabs" id="nav-tab" role="tablist">
|
||||
<a class="nav-item nav-link active" id="nav-main-tab" data-toggle="tab"
|
||||
href="#nav-main" role="tab" aria-controls="nav-main" aria-selected="true">Статья</a>
|
||||
<a class="nav-item nav-link" id="nav-latex-tab" data-toggle="tab"
|
||||
href="#nav-latex" role="tab" aria-controls="nav-latex" aria-selected="false">Latex</a>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="tab-content" id="nav-tabContent">
|
||||
<div class="tab-pane fade show active" id="nav-main" role="tabpanel"
|
||||
aria-labelledby="nav-main-tab">
|
||||
<input type="hidden" name="id" th:field="*{id}"/>
|
||||
<div class="form-group">
|
||||
<label for="title">Название:</label>
|
||||
<input class="form-control" id="title" type="text"
|
||||
placeholder="Название статьи"
|
||||
th:field="*{title}"/>
|
||||
<p th:if="${#fields.hasErrors('title')}" th:errors="*{title}"
|
||||
class="alert alert-danger">Incorrect title</p>
|
||||
<p class="help-block text-danger"></p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="status">Статус:</label>
|
||||
<select class="form-control" th:field="*{status}" id="status">
|
||||
<option th:each="status : ${allStatuses}" th:value="${status}"
|
||||
th:text="${status.statusName}">Status
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="status">Статус:</label>
|
||||
<select class="form-control" th:field="*{status}" id="status">
|
||||
<option th:each="status : ${allStatuses}" th:value="${status}"
|
||||
th:text="${status.statusName}">Status
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="comment">Комментарий:</label>
|
||||
<textarea class="form-control" rows="5" id="comment"
|
||||
th:field="*{comment}"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="comment">Комментарий:</label>
|
||||
<textarea class="form-control" rows="5" id="comment"
|
||||
th:field="*{comment}"></textarea>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="title">Ссылка на сайт конференции:</label>
|
||||
@ -99,42 +111,52 @@
|
||||
class="alert alert-danger">Incorrect title</p>
|
||||
</div>
|
||||
|
||||
<div class="form-group" id="files-list">
|
||||
<label>Файлы:</label>
|
||||
<th:block th:each="file, rowStat : *{files}">
|
||||
<div class="row" th:id="|files${rowStat.index}|"
|
||||
th:style="${file.deleted} ? 'display: none;' :''">
|
||||
<input type="hidden" th:field="*{files[__${rowStat.index}__].id}"/>
|
||||
<input type="hidden" th:field="*{files[__${rowStat.index}__].deleted}"/>
|
||||
<input type="hidden" th:field="*{files[__${rowStat.index}__].name}"/>
|
||||
<input type="hidden" th:field="*{files[__${rowStat.index}__].tmpFileName}"/>
|
||||
<div class="col-2">
|
||||
<a class="btn btn-danger float-right"
|
||||
th:onclick="|$('#files${rowStat.index}\\.deleted').val('true'); $('#files${rowStat.index}').hide(); |">
|
||||
<span aria-hidden="true"><i class="fa fa-times"/></span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col-10">
|
||||
<a th:onclick="${file.id==null} ? 'downloadFile('+${file.tmpFileName}+',null,\''+${file.name}+'\')':
|
||||
'downloadFile(null,'+${file.id}+',\''+${file.name}+'\')' "
|
||||
href="javascript:void(0)"
|
||||
th:text="*{files[__${rowStat.index}__].name}">
|
||||
</a>
|
||||
<div class="form-group files-list" id="files-list">
|
||||
<label>Файлы:</label>
|
||||
|
||||
<div th:replace="papers/fragments/paperFilesListFragment :: filesList(isLatexAttach = ${false})"/>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="locked"
|
||||
th:field="*{locked}"/>
|
||||
<label class="form-check-label" for="locked">Заблокирована</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="loader">Загрузить статью:</label>
|
||||
<div id="loader">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</th:block>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="form-check">
|
||||
<input type="checkbox" class="form-check-input" id="locked"
|
||||
th:field="*{locked}"/>
|
||||
<label class="form-check-label" for="locked">Заблокирована</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="loader">Загрузить статью:</label>
|
||||
<div id="loader">
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-latex" role="tabpanel"
|
||||
aria-labelledby="nav-profile-tab">
|
||||
<div class="form-group">
|
||||
<label for="latex-text">Latex текст:</label>
|
||||
<textarea class="form-control" id="latex-text" type="text" rows="10"
|
||||
placeholder="Latex.."
|
||||
th:field="*{latexText}"/>
|
||||
</div>
|
||||
<div class="form-group files-list" id="latex-files-list">
|
||||
<label>Файлы:</label>
|
||||
<div th:replace="papers/fragments/paperFilesListFragment :: filesList(isLatexAttach = ${true})"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="latex-loader">Загрузить файлы:</label>
|
||||
<div id="latex-loader">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button id="pdfBtn" class="btn btn-primary text-uppercase"
|
||||
onclick="generatePDF()"
|
||||
type="button">
|
||||
<i id="pdfLoadingIcon" class='fa fa-circle-o-notch fa-spin'
|
||||
style="display: none;"></i>
|
||||
pdf
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -207,14 +229,26 @@
|
||||
showFeedbackMessage("Файл успешно загружен");
|
||||
console.debug(response);
|
||||
|
||||
addNewFile(response);
|
||||
addNewFile(response, $("#files-list"), false);
|
||||
}
|
||||
});
|
||||
new FileLoader({
|
||||
div: "latex-loader",
|
||||
url: urlFileUpload,
|
||||
maxSize: -1,
|
||||
extensions: [],
|
||||
callback: function (response) {
|
||||
showFeedbackMessage("Файл успешно загружен");
|
||||
console.debug(response);
|
||||
|
||||
addNewFile(response, $("#latex-files-list"), true);
|
||||
}
|
||||
});
|
||||
$('.selectpicker').selectpicker();
|
||||
});
|
||||
/*]]>*/
|
||||
function addNewFile(fileDto) {
|
||||
var fileNumber = $("#files-list div.row").length;
|
||||
function addNewFile(fileDto, listElement, isLatexAttach) {
|
||||
var fileNumber = $('.files-list div.row').length;
|
||||
|
||||
var newFileRow = $("<div/>")
|
||||
.attr("id", 'files' + fileNumber)
|
||||
@ -248,6 +282,13 @@
|
||||
.attr("name", "files[" + fileNumber + "].tmpFileName");
|
||||
newFileRow.append(tmpFileNameInput);
|
||||
|
||||
var isLatexInput = $("<input/>")
|
||||
.attr("type", "hidden")
|
||||
.attr("id", "files" + fileNumber + ".isLatexAttach")
|
||||
.attr("value", isLatexAttach)
|
||||
.attr("name", "files[" + fileNumber + "].isLatexAttach");
|
||||
newFileRow.append(isLatexInput);
|
||||
|
||||
var nextDiv = $("<div/>")
|
||||
.addClass("col-2");
|
||||
|
||||
@ -266,7 +307,7 @@
|
||||
.attr("onclick", "downloadFile('" + fileDto.tmpFileName + "',null,'" + fileDto.fileName + "')"));
|
||||
newFileRow.append(nameDiv);
|
||||
|
||||
$("#files-list").append(newFileRow);
|
||||
listElement.append(newFileRow);
|
||||
|
||||
}
|
||||
|
||||
@ -298,6 +339,37 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function generatePDF() {
|
||||
$('#pdfLoadingIcon').show();
|
||||
$('#pdfBtn').prop('disabled', true);
|
||||
|
||||
var formData = new FormData(document.forms.paperform);
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open("POST", urlPdfGenerating);
|
||||
xhr.send(formData);
|
||||
xhr.responseType = 'blob';
|
||||
|
||||
xhr.onload = function () {
|
||||
if (this.status == 200) {
|
||||
console.debug(this.response);
|
||||
var blob = new Blob([this.response], {type: 'application/pdf'});
|
||||
let a = document.createElement("a");
|
||||
a.style = "display: none";
|
||||
document.body.appendChild(a);
|
||||
let url = window.URL.createObjectURL(blob);
|
||||
a.href = url;
|
||||
a.download = $('#title').val() + '.pdf';
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
} else {
|
||||
showFeedbackMessage("Ошибка при создании PDF", MessageTypesEnum.DANGER);
|
||||
}
|
||||
$('#pdfLoadingIcon').hide();
|
||||
$('#pdfBtn').prop('disabled', false);
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
</div>
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
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>
|
||||
@ -19,7 +19,8 @@
|
||||
</div>
|
||||
<div class="row">
|
||||
<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}">
|
||||
<div class="row">
|
||||
<div class="col-md-6 col-sm-12">
|
||||
@ -55,7 +56,7 @@
|
||||
<input type="submit" id="createGrant" name="createGrant" class="btn btn-primary"
|
||||
value="Добавить грант"/>
|
||||
</div>
|
||||
<input type = "hidden" th:field="*{grant.id}"/>
|
||||
<input type="hidden" th:field="*{grant.id}"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
@ -88,7 +89,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>
|
||||
|
||||
@ -107,7 +109,8 @@
|
||||
type="submit">
|
||||
Сохранить
|
||||
</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>
|
||||
</div>
|
||||
@ -135,6 +138,8 @@
|
||||
$('.selectpicker').selectpicker();
|
||||
});
|
||||
/*]]>*/
|
||||
|
||||
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -17,6 +17,7 @@
|
||||
<th:block th:each="task : ${tasks}">
|
||||
<div th:replace="students/fragments/taskDashboardFragment :: taskDashboard(task=${task})"/>
|
||||
</th:block>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
Loading…
Reference in New Issue
Block a user