diff --git a/.gitlab/issue_templates/feature.md b/.gitlab/issue_templates/feature.md index bb1e9f3..c9e1757 100644 --- a/.gitlab/issue_templates/feature.md +++ b/.gitlab/issue_templates/feature.md @@ -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` +* Сценарий просмотра проверяется при ручном внечении записей в БД diff --git a/checkstyle.xml b/checkstyle.xml index 5877ec9..828cdaa 100644 --- a/checkstyle.xml +++ b/checkstyle.xml @@ -100,7 +100,7 @@ - + + diff --git a/src/main/java/ru/ulstu/conference/controller/ConferenceController.java b/src/main/java/ru/ulstu/conference/controller/ConferenceController.java index 823f853..0da1c12 100644 --- a/src/main/java/ru/ulstu/conference/controller/ConferenceController.java +++ b/src/main/java/ru/ulstu/conference/controller/ConferenceController.java @@ -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())); - modelMap.put("conferenceDto", conferenceDto); + modelMap.put("conferenceDto", conferenceService.getNewConference()); } } @@ -104,8 +103,37 @@ public class ConferenceController { return CONFERENCE_PAGE; } - public List getNotSelectPapers(List 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 getAllParticipation() { + return conferenceService.getAllParticipations(); + } + + @ModelAttribute("allDeposit") + public List getAllDeposit() { + return conferenceService.getAllDeposit(); + } + + @ModelAttribute("allUsers") + public List getAllUsers() { + return conferenceService.getAllUsers(); + } + + @ModelAttribute("allYears") + public List getAllYears() { + List years = new ArrayList<>(); + for (int i = Calendar.getInstance().get(Calendar.YEAR); i > 2010; i--) { + years.add(i); + } + return years; } private void filterEmptyDeadlines(ConferenceDto conferenceDto) { diff --git a/src/main/java/ru/ulstu/conference/model/Conference.java b/src/main/java/ru/ulstu/conference/model/Conference.java index b6affcd..d602438 100644 --- a/src/main/java/ru/ulstu/conference/model/Conference.java +++ b/src/main/java/ru/ulstu/conference/model/Conference.java @@ -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 papers = new ArrayList<>(); - @ManyToMany(fetch = FetchType.EAGER) - @JoinTable(name = "users_conference", - joinColumns = {@JoinColumn(name = "conference_id")}, - inverseJoinColumns = {@JoinColumn(name = "users_id")}) - private Set users = new HashSet<>(); + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "conference_id", unique = true) + @Fetch(FetchMode.SUBSELECT) + private List users = new ArrayList<>(); public String getTitle() { return title; @@ -132,11 +117,11 @@ public class Conference extends BaseEntity { this.papers = papers; } - public Set getUsers() { + public List getUsers() { return users; } - public void setUsers(Set users) { + public void setUsers(List users) { this.users = users; } } diff --git a/src/main/java/ru/ulstu/conference/model/ConferenceDto.java b/src/main/java/ru/ulstu/conference/model/ConferenceDto.java index ec9ec92..2e2f13b 100644 --- a/src/main/java/ru/ulstu/conference/model/ConferenceDto.java +++ b/src/main/java/ru/ulstu/conference/model/ConferenceDto.java @@ -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 deadlines = new ArrayList<>(); private List removedDeadlineIds = new ArrayList<>(); - private Set userIds = new HashSet<>(); + private List userIds = new ArrayList<>(); private List paperIds = new ArrayList<>(); private List papers = new ArrayList<>(); - - private List notSelectedPapers = new ArrayList<>(); - private Set users = new HashSet<>(); - private Integer filterUserId; + private List 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 deadlines, - @JsonProperty("userIds") Set userIds, + @JsonProperty("userIds") List userIds, @JsonProperty("paperIds") List paperIds, - @JsonProperty("users") Set users, + @JsonProperty("users") List users, @JsonProperty("papers") List papers, - @JsonProperty("notSelectedPapers") List notSelectedPapers) { + @JsonProperty("notSelectedPapers") List 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 getUserIds() { + public List getUserIds() { return userIds; } - public void setUserIds(Set userIds) { + public void setUserIds(List userIds) { this.userIds = userIds; } @@ -183,20 +182,20 @@ public class ConferenceDto { this.papers = papers; } - public Set getUsers() { + public List getUsers() { return users; } - public void setUsers(Set users) { + public void setUsers(List 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 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]; + } + } diff --git a/src/main/java/ru/ulstu/conference/model/ConferenceFilterDto.java b/src/main/java/ru/ulstu/conference/model/ConferenceFilterDto.java index 37878b2..8503b40 100644 --- a/src/main/java/ru/ulstu/conference/model/ConferenceFilterDto.java +++ b/src/main/java/ru/ulstu/conference/model/ConferenceFilterDto.java @@ -5,15 +5,15 @@ import java.util.List; public class ConferenceFilterDto { private List conferences; - private Integer filterAuthorId; + private Integer filterUserId; private Integer year; public ConferenceFilterDto() { } - public ConferenceFilterDto(List conferenceDtos, Integer filterAuthorId, Integer year) { + public ConferenceFilterDto(List 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() { diff --git a/src/main/java/ru/ulstu/conference/model/ConferenceUser.java b/src/main/java/ru/ulstu/conference/model/ConferenceUser.java new file mode 100644 index 0000000..b2d2d36 --- /dev/null +++ b/src/main/java/ru/ulstu/conference/model/ConferenceUser.java @@ -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; + } + +} diff --git a/src/main/java/ru/ulstu/conference/repository/ConferenceRepository.java b/src/main/java/ru/ulstu/conference/repository/ConferenceRepository.java index 4325633..99f311e 100644 --- a/src/main/java/ru/ulstu/conference/repository/ConferenceRepository.java +++ b/src/main/java/ru/ulstu/conference/repository/ConferenceRepository.java @@ -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 { + @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 filter(@Param("user") User user, @Param("year") Integer year); } diff --git a/src/main/java/ru/ulstu/conference/repository/ConferenceUserRepository.java b/src/main/java/ru/ulstu/conference/repository/ConferenceUserRepository.java new file mode 100644 index 0000000..5e654d5 --- /dev/null +++ b/src/main/java/ru/ulstu/conference/repository/ConferenceUserRepository.java @@ -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 { +} diff --git a/src/main/java/ru/ulstu/conference/service/ConferenceService.java b/src/main/java/ru/ulstu/conference/service/ConferenceService.java index 4d267d1..b03e9d3 100644 --- a/src/main/java/ru/ulstu/conference/service/ConferenceService.java +++ b/src/main/java/ru/ulstu/conference/service/ConferenceService.java @@ -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())); + return conferenceDto; + } + + public List findAll() { return conferenceRepository.findAll(); } @@ -88,10 +114,27 @@ public class ConferenceService { conferenceDto.getNotSelectedPapers().add(removedPaper); } - public List getConferencePapers(List paperIds) { + public void takePart(ConferenceDto conferenceDto) throws IOException { + conferenceDto.getUsers().add(new ConferenceUser(userService.getCurrentUser())); + conferenceDto.setDisabledTakePart(true); + } + + public List getNotSelectPapers(List paperIds) { return paperService.findAllNotSelect(paperIds); } + public List getAllUsers() { + return userService.findAll(); + } + + public List getAllParticipations() { + return Arrays.asList(ConferenceUser.Participation.values()); + } + + public List 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 conferenceUsers) { + return conferenceUsers.stream().anyMatch(participant -> participant.getUser().equals(userService.getCurrentUser())); + } + + public List filter(ConferenceFilterDto conferenceFilterDto) { + return convert(conferenceRepository.filter( + conferenceFilterDto.getFilterUserId() == null ? null : userService.findById(conferenceFilterDto.getFilterUserId()), + conferenceFilterDto.getYear()), ConferenceDto::new); + + } } diff --git a/src/main/java/ru/ulstu/conference/service/ConferenceUserService.java b/src/main/java/ru/ulstu/conference/service/ConferenceUserService.java new file mode 100644 index 0000000..f771b2a --- /dev/null +++ b/src/main/java/ru/ulstu/conference/service/ConferenceUserService.java @@ -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 saveOrCreate(List 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; + } + + +} diff --git a/src/main/java/ru/ulstu/core/util/DateUtils.java b/src/main/java/ru/ulstu/core/util/DateUtils.java index b24b09c..42a4182 100644 --- a/src/main/java/ru/ulstu/core/util/DateUtils.java +++ b/src/main/java/ru/ulstu/core/util/DateUtils.java @@ -24,7 +24,7 @@ public class DateUtils { return cal; } - public static List getMonths () { + public static List getMonths() { return Arrays.asList(Month.values()); } diff --git a/src/main/java/ru/ulstu/file/model/FileData.java b/src/main/java/ru/ulstu/file/model/FileData.java index e5b3277..3f97130 100644 --- a/src/main/java/ru/ulstu/file/model/FileData.java +++ b/src/main/java/ru/ulstu/file/model/FileData.java @@ -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; + } } diff --git a/src/main/java/ru/ulstu/file/model/FileDataDto.java b/src/main/java/ru/ulstu/file/model/FileDataDto.java index 919cd80..e83bf12 100644 --- a/src/main/java/ru/ulstu/file/model/FileDataDto.java +++ b/src/main/java/ru/ulstu/file/model/FileDataDto.java @@ -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; + } } diff --git a/src/main/java/ru/ulstu/file/service/FileService.java b/src/main/java/ru/ulstu/file/service/FileService.java index ad9f946..4bb1658 100644 --- a/src/main/java/ru/ulstu/file/service/FileService.java +++ b/src/main/java/ru/ulstu/file/service/FileService.java @@ -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(); + } } diff --git a/src/main/java/ru/ulstu/grant/controller/GrantController.java b/src/main/java/ru/ulstu/grant/controller/GrantController.java index a7dc948..b633261 100644 --- a/src/main/java/ru/ulstu/grant/controller/GrantController.java +++ b/src/main/java/ru/ulstu/grant/controller/GrantController.java @@ -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 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())) diff --git a/src/main/java/ru/ulstu/grant/model/Grant.java b/src/main/java/ru/ulstu/grant/model/Grant.java index 685a1d5..7853166 100644 --- a/src/main/java/ru/ulstu/grant/model/Grant.java +++ b/src/main/java/ru/ulstu/grant/model/Grant.java @@ -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 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 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 getAuthors() { + return authors; + } + + public void setAuthors(Set authors) { + this.authors = authors; + } + + @Override + public Set getUsers() { + return getAuthors(); + } + + public User getLeader() { + return leader; + } + + public void setLeader(User leader) { + this.leader = leader; + } + public Optional getNextDeadline() { return deadlines .stream() diff --git a/src/main/java/ru/ulstu/grant/model/GrantDto.java b/src/main/java/ru/ulstu/grant/model/GrantDto.java index fb29164..aa8634b 100644 --- a/src/main/java/ru/ulstu/grant/model/GrantDto.java +++ b/src/main/java/ru/ulstu/grant/model/GrantDto.java @@ -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 authorIds; + private Set 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 deadlines, @JsonProperty("comment") String comment, - @JsonProperty("project") ProjectDto project) { + @JsonProperty("project") ProjectDto project, + @JsonProperty("authorIds") Set authorIds, + @JsonProperty("authors") Set 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 getAuthorIds() { + return authorIds; + } + + public void setAuthorIds(Set authorIds) { + this.authorIds = authorIds; + } + + public Set getAuthors() { + return authors; + } + + public void setAuthors(Set 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; + } } diff --git a/src/main/java/ru/ulstu/grant/model/GrantStatusDto.java b/src/main/java/ru/ulstu/grant/model/GrantStatusDto.java deleted file mode 100644 index 34676d6..0000000 --- a/src/main/java/ru/ulstu/grant/model/GrantStatusDto.java +++ /dev/null @@ -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; - } -} diff --git a/src/main/java/ru/ulstu/grant/repository/GrantRepository.java b/src/main/java/ru/ulstu/grant/repository/GrantRepository.java index 92dec43..44c2cc0 100644 --- a/src/main/java/ru/ulstu/grant/repository/GrantRepository.java +++ b/src/main/java/ru/ulstu/grant/repository/GrantRepository.java @@ -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 { + List findByStatus(Grant.GrantStatus status); } diff --git a/src/main/java/ru/ulstu/grant/service/GrantService.java b/src/main/java/ru/ulstu/grant/service/GrantService.java index d5beec3..8427da3 100644 --- a/src/main/java/ru/ulstu/grant/service/GrantService.java +++ b/src/main/java/ru/ulstu/grant/service/GrantService.java @@ -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 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 getGrantAuthors(GrantDto grantDto) { + List filteredUsers = userService.filterByAgeAndDegree(grantDto.isHasAge(), grantDto.isHasDegree()); + if (grantDto.isWasLeader()) { + filteredUsers = filteredUsers + .stream() + .filter(getCompletedGrantLeaders()::contains) + .collect(Collectors.toList()); + } + return filteredUsers; + } + + private List getCompletedGrantLeaders() { + return grantRepository.findByStatus(Grant.GrantStatus.COMPLETED) + .stream() + .map(Grant::getLeader) + .collect(Collectors.toList()); + } } diff --git a/src/main/java/ru/ulstu/odin/model/OdinField.java b/src/main/java/ru/ulstu/odin/model/OdinField.java index 5917a44..c60c945 100644 --- a/src/main/java/ru/ulstu/odin/model/OdinField.java +++ b/src/main/java/ru/ulstu/odin/model/OdinField.java @@ -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); } diff --git a/src/main/java/ru/ulstu/paper/controller/PaperController.java b/src/main/java/ru/ulstu/paper/controller/PaperController.java index 27fec4e..5a5f915 100644 --- a/src/main/java/ru/ulstu/paper/controller/PaperController.java +++ b/src/main/java/ru/ulstu/paper/controller/PaperController.java @@ -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 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())) diff --git a/src/main/java/ru/ulstu/paper/model/Paper.java b/src/main/java/ru/ulstu/paper/model/Paper.java index 1d7e468..cb4a31d 100644 --- a/src/main/java/ru/ulstu/paper/model/Paper.java +++ b/src/main/java/ru/ulstu/paper/model/Paper.java @@ -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 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 getUsers() { return getAuthors(); diff --git a/src/main/java/ru/ulstu/paper/model/PaperDto.java b/src/main/java/ru/ulstu/paper/model/PaperDto.java index 182b12c..7ddc0e0 100644 --- a/src/main/java/ru/ulstu/paper/model/PaperDto.java +++ b/src/main/java/ru/ulstu/paper/model/PaperDto.java @@ -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 authorIds; private Set 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 deadlines, @JsonProperty("comment") String comment, + @JsonProperty("latex_text") String latexText, @JsonProperty("url") String url, @JsonProperty("locked") Boolean locked, @JsonProperty("files") List 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() diff --git a/src/main/java/ru/ulstu/paper/service/LatexService.java b/src/main/java/ru/ulstu/paper/service/LatexService.java new file mode 100644 index 0000000..82dd1ba --- /dev/null +++ b/src/main/java/ru/ulstu/paper/service/LatexService.java @@ -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; + } + } +} diff --git a/src/main/java/ru/ulstu/paper/service/PaperService.java b/src/main/java/ru/ulstu/paper/service/PaperService.java index 6c27c6e..5a6eb23 100644 --- a/src/main/java/ru/ulstu/paper/service/PaperService.java +++ b/src/main/java/ru/ulstu/paper/service/PaperService.java @@ -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()); diff --git a/src/main/java/ru/ulstu/user/model/User.java b/src/main/java/ru/ulstu/user/model/User.java index 06f407b..e18414d 100644 --- a/src/main/java/ru/ulstu/user/model/User.java +++ b/src/main/java/ru/ulstu/user/model/User.java @@ -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 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, diff --git a/src/main/java/ru/ulstu/user/model/UserDto.java b/src/main/java/ru/ulstu/user/model/UserDto.java index c98e0bb..2a0f7af 100644 --- a/src/main/java/ru/ulstu/user/model/UserDto.java +++ b/src/main/java/ru/ulstu/user/model/UserDto.java @@ -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 + '\'' + '}'; } } diff --git a/src/main/java/ru/ulstu/user/repository/UserRepository.java b/src/main/java/ru/ulstu/user/repository/UserRepository.java index 2edc8aa..afcdd69 100644 --- a/src/main/java/ru/ulstu/user/repository/UserRepository.java +++ b/src/main/java/ru/ulstu/user/repository/UserRepository.java @@ -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 { @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 filterByAgeAndDegree(@Param("hasAge") boolean hasAge, + @Param("hasDegree") boolean hasDegree); } diff --git a/src/main/java/ru/ulstu/user/service/UserService.java b/src/main/java/ru/ulstu/user/service/UserService.java index 25d8e95..7e97b83 100644 --- a/src/main/java/ru/ulstu/user/service/UserService.java +++ b/src/main/java/ru/ulstu/user/service/UserService.java @@ -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 filterByAgeAndDegree(boolean hasDegree, boolean hasAge) { + return userRepository.filterByAgeAndDegree(hasDegree, hasAge); + } } diff --git a/src/main/resources/db/changelog-20190323_000001-schema.xml b/src/main/resources/db/changelog-20190323_000001-schema.xml new file mode 100644 index 0000000..1ab3efb --- /dev/null +++ b/src/main/resources/db/changelog-20190323_000001-schema.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog-20190402_000000-schema.xml b/src/main/resources/db/changelog-20190402_000000-schema.xml new file mode 100644 index 0000000..1bbb256 --- /dev/null +++ b/src/main/resources/db/changelog-20190402_000000-schema.xml @@ -0,0 +1,26 @@ + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/db/changelog-20190404_000000-schema.xml b/src/main/resources/db/changelog-20190404_000000-schema.xml new file mode 100644 index 0000000..0f45e31 --- /dev/null +++ b/src/main/resources/db/changelog-20190404_000000-schema.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + diff --git a/src/main/resources/db/changelog-20190417_000000-schema.xml b/src/main/resources/db/changelog-20190417_000000-schema.xml new file mode 100644 index 0000000..f0a0d64 --- /dev/null +++ b/src/main/resources/db/changelog-20190417_000000-schema.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/db/changelog-master.xml b/src/main/resources/db/changelog-master.xml index 22d3cbd..32651bc 100644 --- a/src/main/resources/db/changelog-master.xml +++ b/src/main/resources/db/changelog-master.xml @@ -24,6 +24,10 @@ + + + + \ No newline at end of file diff --git a/src/main/resources/public/css/conference.css b/src/main/resources/public/css/conference.css index fa3666e..ad06b3c 100644 --- a/src/main/resources/public/css/conference.css +++ b/src/main/resources/public/css/conference.css @@ -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,8 +49,45 @@ 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; padding: 0px; diff --git a/src/main/resources/public/css/grant.css b/src/main/resources/public/css/grant.css new file mode 100644 index 0000000..2c95628 --- /dev/null +++ b/src/main/resources/public/css/grant.css @@ -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; +} \ No newline at end of file diff --git a/src/main/resources/public/css/paper.css b/src/main/resources/public/css/paper.css index 6e61d0c..824209f 100644 --- a/src/main/resources/public/css/paper.css +++ b/src/main/resources/public/css/paper.css @@ -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; } \ No newline at end of file diff --git a/src/main/resources/public/js/conference.js b/src/main/resources/public/js/conference.js index dd843ca..d415ca2 100644 --- a/src/main/resources/public/js/conference.js +++ b/src/main/resources/public/js/conference.js @@ -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) { diff --git a/src/main/resources/public/js/core.js b/src/main/resources/public/js/core.js index bf6fb77..58e68f4 100644 --- a/src/main/resources/public/js/core.js +++ b/src/main/resources/public/js/core.js @@ -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 */ diff --git a/src/main/resources/templates/conferences/conference.html b/src/main/resources/templates/conferences/conference.html index 27c602a..478ebcb 100644 --- a/src/main/resources/templates/conferences/conference.html +++ b/src/main/resources/templates/conferences/conference.html @@ -97,38 +97,35 @@
-
-
- Пользователь 1 -
-
- очная -
-
- статья -
-
+
+ + + + +
-
- + +
diff --git a/src/main/resources/templates/conferences/conferences.html b/src/main/resources/templates/conferences/conferences.html index 46b2e73..7b0ac8d 100644 --- a/src/main/resources/templates/conferences/conferences.html +++ b/src/main/resources/templates/conferences/conferences.html @@ -27,16 +27,19 @@
Фильтр:
- + + - -
diff --git a/src/main/resources/templates/conferences/fragments/confLineFragment.html b/src/main/resources/templates/conferences/fragments/confLineFragment.html index d104952..7d948d4 100644 --- a/src/main/resources/templates/conferences/fragments/confLineFragment.html +++ b/src/main/resources/templates/conferences/fragments/confLineFragment.html @@ -5,13 +5,14 @@
-
- + diff --git a/src/main/resources/templates/grants/fragments/grantDashboardFragment.html b/src/main/resources/templates/grants/fragments/grantDashboardFragment.html index df3e3d0..51d0925 100644 --- a/src/main/resources/templates/grants/fragments/grantDashboardFragment.html +++ b/src/main/resources/templates/grants/fragments/grantDashboardFragment.html @@ -10,7 +10,9 @@
- title + + title +

status

diff --git a/src/main/resources/templates/grants/fragments/grantLineFragment.html b/src/main/resources/templates/grants/fragments/grantLineFragment.html index 1048897..dda0e8d 100644 --- a/src/main/resources/templates/grants/fragments/grantLineFragment.html +++ b/src/main/resources/templates/grants/fragments/grantLineFragment.html @@ -9,7 +9,7 @@ - + - +
diff --git a/src/main/resources/templates/grants/grant.html b/src/main/resources/templates/grants/grant.html index fc2878d..fdce1ff 100644 --- a/src/main/resources/templates/grants/grant.html +++ b/src/main/resources/templates/grants/grant.html @@ -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"> - +
- -
+
@@ -17,6 +16,7 @@
+