Merge branch 'dev' into 79-students-tags-generation
# Conflicts: # src/main/resources/db/changelog-20190505_000000-schema.xml # src/main/resources/db/changelog-master.xml
This commit is contained in:
commit
7798508d4f
@ -13,7 +13,6 @@ import ru.ulstu.conference.model.ConferenceDto;
|
|||||||
import ru.ulstu.conference.model.ConferenceFilterDto;
|
import ru.ulstu.conference.model.ConferenceFilterDto;
|
||||||
import ru.ulstu.conference.model.ConferenceUser;
|
import ru.ulstu.conference.model.ConferenceUser;
|
||||||
import ru.ulstu.conference.service.ConferenceService;
|
import ru.ulstu.conference.service.ConferenceService;
|
||||||
import ru.ulstu.deadline.model.Deadline;
|
|
||||||
import ru.ulstu.user.model.User;
|
import ru.ulstu.user.model.User;
|
||||||
import springfox.documentation.annotations.ApiIgnore;
|
import springfox.documentation.annotations.ApiIgnore;
|
||||||
|
|
||||||
@ -22,9 +21,7 @@ import java.io.IOException;
|
|||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.List;
|
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.CONFERENCES_PAGE;
|
||||||
import static ru.ulstu.core.controller.Navigation.CONFERENCE_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.REDIRECT_TO;
|
||||||
@ -77,7 +74,8 @@ public class ConferenceController {
|
|||||||
|
|
||||||
@PostMapping(value = "/conference", params = "save")
|
@PostMapping(value = "/conference", params = "save")
|
||||||
public String save(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
public String save(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
||||||
filterEmptyDeadlines(conferenceDto);
|
conferenceService.filterEmptyDeadlines(conferenceDto);
|
||||||
|
conferenceService.checkEmptyFieldsOfDeadline(conferenceDto, errors);
|
||||||
if (errors.hasErrors()) {
|
if (errors.hasErrors()) {
|
||||||
return CONFERENCE_PAGE;
|
return CONFERENCE_PAGE;
|
||||||
}
|
}
|
||||||
@ -87,11 +85,11 @@ public class ConferenceController {
|
|||||||
|
|
||||||
@PostMapping(value = "/conference", params = "addDeadline")
|
@PostMapping(value = "/conference", params = "addDeadline")
|
||||||
public String addDeadline(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
public String addDeadline(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
||||||
filterEmptyDeadlines(conferenceDto);
|
conferenceService.filterEmptyDeadlines(conferenceDto);
|
||||||
if (errors.hasErrors()) {
|
if (errors.hasErrors()) {
|
||||||
return CONFERENCE_PAGE;
|
return CONFERENCE_PAGE;
|
||||||
}
|
}
|
||||||
conferenceDto.getDeadlines().add(new Deadline());
|
conferenceService.addDeadline(conferenceDto);
|
||||||
return CONFERENCE_PAGE;
|
return CONFERENCE_PAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -167,9 +165,4 @@ public class ConferenceController {
|
|||||||
return years;
|
return years;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filterEmptyDeadlines(ConferenceDto conferenceDto) {
|
|
||||||
conferenceDto.setDeadlines(conferenceDto.getDeadlines().stream()
|
|
||||||
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
|
||||||
.collect(Collectors.toList()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,10 @@ import javax.persistence.Table;
|
|||||||
import javax.persistence.Temporal;
|
import javax.persistence.Temporal;
|
||||||
import javax.persistence.TemporalType;
|
import javax.persistence.TemporalType;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
@Table(name = "conference")
|
@Table(name = "conference")
|
||||||
@ -57,6 +59,7 @@ public class Conference extends BaseEntity {
|
|||||||
@JoinTable(name = "paper_conference",
|
@JoinTable(name = "paper_conference",
|
||||||
joinColumns = {@JoinColumn(name = "conference_id")},
|
joinColumns = {@JoinColumn(name = "conference_id")},
|
||||||
inverseJoinColumns = {@JoinColumn(name = "paper_id")})
|
inverseJoinColumns = {@JoinColumn(name = "paper_id")})
|
||||||
|
@Fetch(FetchMode.SUBSELECT)
|
||||||
private List<Paper> papers = new ArrayList<>();
|
private List<Paper> papers = new ArrayList<>();
|
||||||
|
|
||||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
@ -135,4 +138,13 @@ public class Conference extends BaseEntity {
|
|||||||
public void setUsers(List<ConferenceUser> users) {
|
public void setUsers(List<ConferenceUser> users) {
|
||||||
this.users = users;
|
this.users = users;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Optional<Deadline> getNextDeadline() {
|
||||||
|
return deadlines
|
||||||
|
.stream()
|
||||||
|
.filter(deadline -> deadline.getDate() != null)
|
||||||
|
.sorted(Comparator.comparing(Deadline::getDate))
|
||||||
|
.filter(d -> d.getDate().after(new Date()))
|
||||||
|
.findFirst();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,113 @@
|
|||||||
package ru.ulstu.conference.service;
|
package ru.ulstu.conference.service;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.ulstu.conference.model.Conference;
|
||||||
|
import ru.ulstu.core.util.DateUtils;
|
||||||
|
import ru.ulstu.ping.service.PingService;
|
||||||
|
import ru.ulstu.user.service.MailService;
|
||||||
|
import ru.ulstu.user.service.UserService;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ConferenceNotificationService {
|
public class ConferenceNotificationService {
|
||||||
|
|
||||||
|
private final static int YESTERDAY = -1;
|
||||||
|
private final static int DAYS_TO_DEADLINE_NOTIFICATION = 7;
|
||||||
|
private final static String TEMPLATE_PING = "conferencePingNotification";
|
||||||
|
private final static String TEMPLATE_DEADLINE = "conferenceDeadlineNotification";
|
||||||
|
private final static String TEMPLATE_CREATE = "conferenceCreateNotification";
|
||||||
|
private final static String TEMPLATE_UPDATE_DEADLINES = "conferenceUpdateDeadlinesNotification";
|
||||||
|
private final static String TEMPLATE_UPDATE_DATES = "conferenceUpdateDatesNotification";
|
||||||
|
|
||||||
|
private final static String TITLE_PING = "Обратите внимание на конференцию: %s";
|
||||||
|
private final static String TITLE_DEADLINE = "Приближается дедлайн конференции: %s";
|
||||||
|
private final static String TITLE_CREATE = "Создана новая конференция: %s";
|
||||||
|
private final static String TITLE_UPDATE_DEADLINES = "Изменения дедлайнов в конференции: %s";
|
||||||
|
private final static String TITLE_UPDATE_DATES = "Изменение дат проведения конференции: %s";
|
||||||
|
|
||||||
|
private final MailService mailService;
|
||||||
|
private final UserService userService;
|
||||||
|
private final PingService pingService;
|
||||||
|
|
||||||
|
public ConferenceNotificationService(MailService mailService,
|
||||||
|
UserService userService,
|
||||||
|
PingService pingService) {
|
||||||
|
this.mailService = mailService;
|
||||||
|
this.userService = userService;
|
||||||
|
this.pingService = pingService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendDeadlineNotifications(List<Conference> conferences) {
|
||||||
|
Date now = DateUtils.addDays(new Date(), DAYS_TO_DEADLINE_NOTIFICATION);
|
||||||
|
conferences
|
||||||
|
.stream()
|
||||||
|
.filter(conference -> needToSendDeadlineNotification(conference, now))
|
||||||
|
.forEach(this::sendMessageDeadline);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean needToSendDeadlineNotification(Conference conference, Date compareDate) {
|
||||||
|
return (conference.getNextDeadline().isPresent())
|
||||||
|
&& conference.getNextDeadline().get().getDate().after(new Date())
|
||||||
|
&& conference.getNextDeadline().get().getDate().before(compareDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendMessageDeadline(Conference conference) {
|
||||||
|
Map<String, Object> variables = ImmutableMap.of("conference", conference);
|
||||||
|
sendForAllParticipants(variables, conference, TEMPLATE_DEADLINE, String.format(TITLE_DEADLINE, conference.getTitle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendCreateNotification(Conference conference) {
|
||||||
|
Map<String, Object> variables = ImmutableMap.of("conference", conference);
|
||||||
|
sendForAllUsers(variables, TEMPLATE_CREATE, String.format(TITLE_CREATE, conference.getTitle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateDeadlineNotification(Conference conference) {
|
||||||
|
Map<String, Object> variables = ImmutableMap.of("conference", conference);
|
||||||
|
sendForAllParticipants(variables, conference, TEMPLATE_UPDATE_DEADLINES, String.format(TITLE_UPDATE_DEADLINES, conference.getTitle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateConferencesDatesNotification(Conference conference, Date oldBeginDate, Date oldEndDate) {
|
||||||
|
Map<String, Object> variables = ImmutableMap.of("conference", conference, "oldBeginDate", oldBeginDate, "oldEndDate", oldEndDate);
|
||||||
|
sendForAllParticipants(variables, conference, TEMPLATE_UPDATE_DATES, String.format(TITLE_UPDATE_DATES, conference.getTitle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendForAllUsers(Map<String, Object> variables, String template, String title) {
|
||||||
|
userService.findAll().forEach(user -> mailService.sendEmailFromTemplate(variables, user, template, title));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendForAllParticipants(Map<String, Object> variables, Conference conference, String template, String title) {
|
||||||
|
conference.getUsers().forEach(conferenceUser -> mailService.sendEmailFromTemplate(variables, conferenceUser.getUser(), template, title));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void sendPingNotifications(List<Conference> conferences) {
|
||||||
|
Calendar calendar = Calendar.getInstance();
|
||||||
|
calendar.setTime(new Date());
|
||||||
|
calendar.add(Calendar.DAY_OF_MONTH, YESTERDAY);
|
||||||
|
conferences
|
||||||
|
.stream()
|
||||||
|
.filter(conference -> {
|
||||||
|
Integer pingCount = pingService.countPingYesterday(conference, calendar);
|
||||||
|
return needToSendPingNotification(conference, pingCount);
|
||||||
|
})
|
||||||
|
.forEach(this::sendMessagePing);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean needToSendPingNotification(Conference conference, Integer pingCount) {
|
||||||
|
if (pingCount > 0) {
|
||||||
|
conference.setPing((Integer) pingCount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendMessagePing(Conference conference) {
|
||||||
|
Map<String, Object> variables = ImmutableMap.of("conference", conference);
|
||||||
|
sendForAllParticipants(variables, conference, TEMPLATE_PING, String.format(TITLE_PING, conference.getTitle()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
package ru.ulstu.conference.service;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class ConferenceScheduler {
|
||||||
|
private final static boolean IS_DEADLINE_NOTIFICATION_BEFORE_WEEK = true;
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(ConferenceScheduler.class);
|
||||||
|
|
||||||
|
private final ConferenceNotificationService conferenceNotificationService;
|
||||||
|
private final ConferenceService conferenceService;
|
||||||
|
|
||||||
|
public ConferenceScheduler(ConferenceNotificationService conferenceNotificationService,
|
||||||
|
ConferenceService conferenceService) {
|
||||||
|
this.conferenceNotificationService = conferenceNotificationService;
|
||||||
|
this.conferenceService = conferenceService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Scheduled(cron = "0 0 8 * * MON", zone = "Europe/Samara")
|
||||||
|
public void checkDeadlineBeforeWeek() {
|
||||||
|
log.debug("ConferenceScheduler.checkDeadlineBeforeWeek started");
|
||||||
|
conferenceNotificationService.sendDeadlineNotifications(conferenceService.findAll());
|
||||||
|
log.debug("ConferenceScheduler.checkDeadlineBeforeWeek finished");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Scheduled(cron = "0 0 8 * * *", zone = "Europe/Samara")
|
||||||
|
public void checkNewPing() {
|
||||||
|
log.debug("ConferenceScheduler.checkPing started");
|
||||||
|
conferenceNotificationService.sendPingNotifications(conferenceService.findAll());
|
||||||
|
log.debug("ConferenceScheduler.checkPing finished");
|
||||||
|
}
|
||||||
|
}
|
@ -5,15 +5,18 @@ import org.springframework.data.domain.Sort;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
import ru.ulstu.conference.model.Conference;
|
import ru.ulstu.conference.model.Conference;
|
||||||
import ru.ulstu.conference.model.ConferenceDto;
|
import ru.ulstu.conference.model.ConferenceDto;
|
||||||
import ru.ulstu.conference.model.ConferenceFilterDto;
|
import ru.ulstu.conference.model.ConferenceFilterDto;
|
||||||
import ru.ulstu.conference.model.ConferenceUser;
|
import ru.ulstu.conference.model.ConferenceUser;
|
||||||
import ru.ulstu.conference.repository.ConferenceRepository;
|
import ru.ulstu.conference.repository.ConferenceRepository;
|
||||||
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
import ru.ulstu.deadline.service.DeadlineService;
|
import ru.ulstu.deadline.service.DeadlineService;
|
||||||
import ru.ulstu.paper.model.Paper;
|
import ru.ulstu.paper.model.Paper;
|
||||||
import ru.ulstu.paper.service.PaperService;
|
import ru.ulstu.paper.service.PaperService;
|
||||||
import ru.ulstu.ping.service.PingService;
|
import ru.ulstu.ping.service.PingService;
|
||||||
|
import ru.ulstu.timeline.service.EventService;
|
||||||
import ru.ulstu.user.model.User;
|
import ru.ulstu.user.model.User;
|
||||||
import ru.ulstu.user.service.UserService;
|
import ru.ulstu.user.service.UserService;
|
||||||
|
|
||||||
@ -22,6 +25,7 @@ import java.util.ArrayList;
|
|||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.springframework.util.ObjectUtils.isEmpty;
|
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||||
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
||||||
@ -36,19 +40,25 @@ public class ConferenceService {
|
|||||||
private final PaperService paperService;
|
private final PaperService paperService;
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
private final PingService pingService;
|
private final PingService pingService;
|
||||||
|
private final ConferenceNotificationService conferenceNotificationService;
|
||||||
|
private final EventService eventService;
|
||||||
|
|
||||||
public ConferenceService(ConferenceRepository conferenceRepository,
|
public ConferenceService(ConferenceRepository conferenceRepository,
|
||||||
ConferenceUserService conferenceUserService,
|
ConferenceUserService conferenceUserService,
|
||||||
DeadlineService deadlineService,
|
DeadlineService deadlineService,
|
||||||
PaperService paperService,
|
PaperService paperService,
|
||||||
UserService userService,
|
UserService userService,
|
||||||
PingService pingService) {
|
PingService pingService,
|
||||||
|
ConferenceNotificationService conferenceNotificationService,
|
||||||
|
EventService eventService) {
|
||||||
this.conferenceRepository = conferenceRepository;
|
this.conferenceRepository = conferenceRepository;
|
||||||
this.conferenceUserService = conferenceUserService;
|
this.conferenceUserService = conferenceUserService;
|
||||||
this.deadlineService = deadlineService;
|
this.deadlineService = deadlineService;
|
||||||
this.paperService = paperService;
|
this.paperService = paperService;
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
this.pingService = pingService;
|
this.pingService = pingService;
|
||||||
|
this.conferenceNotificationService = conferenceNotificationService;
|
||||||
|
this.eventService = eventService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConferenceDto getExistConferenceById(Integer id) {
|
public ConferenceDto getExistConferenceById(Integer id) {
|
||||||
@ -91,13 +101,25 @@ public class ConferenceService {
|
|||||||
public Integer create(ConferenceDto conferenceDto) throws IOException {
|
public Integer create(ConferenceDto conferenceDto) throws IOException {
|
||||||
Conference newConference = copyFromDto(new Conference(), conferenceDto);
|
Conference newConference = copyFromDto(new Conference(), conferenceDto);
|
||||||
newConference = conferenceRepository.save(newConference);
|
newConference = conferenceRepository.save(newConference);
|
||||||
|
conferenceNotificationService.sendCreateNotification(newConference);
|
||||||
|
eventService.createFromConference(newConference);
|
||||||
return newConference.getId();
|
return newConference.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public Integer update(ConferenceDto conferenceDto) throws IOException {
|
public Integer update(ConferenceDto conferenceDto) throws IOException {
|
||||||
Conference conference = conferenceRepository.findOne(conferenceDto.getId());
|
Conference conference = conferenceRepository.findOne(conferenceDto.getId());
|
||||||
|
List<Deadline> oldDeadlines = conference.getDeadlines().stream()
|
||||||
|
.map(this::copyDeadline)
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
Date oldBeginDate = conference.getBeginDate();
|
||||||
|
Date oldEndDate = conference.getEndDate();
|
||||||
conferenceRepository.save(copyFromDto(conference, conferenceDto));
|
conferenceRepository.save(copyFromDto(conference, conferenceDto));
|
||||||
|
eventService.updateConferenceDeadlines(conference);
|
||||||
|
sendNotificationAfterUpdateDeadlines(conference, oldDeadlines);
|
||||||
|
if (!conference.getBeginDate().equals(oldBeginDate) || !conference.getEndDate().equals(oldEndDate)) {
|
||||||
|
conferenceNotificationService.updateConferencesDatesNotification(conference, oldBeginDate, oldEndDate);
|
||||||
|
}
|
||||||
conferenceDto.getRemovedDeadlineIds().forEach(deadlineService::remove);
|
conferenceDto.getRemovedDeadlineIds().forEach(deadlineService::remove);
|
||||||
return conference.getId();
|
return conference.getId();
|
||||||
}
|
}
|
||||||
@ -109,6 +131,11 @@ public class ConferenceService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void addDeadline(ConferenceDto conferenceDto) {
|
||||||
|
conferenceDto.getDeadlines().add(new Deadline());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void removeDeadline(ConferenceDto conferenceDto, Integer deadlineIndex) throws IOException {
|
public void removeDeadline(ConferenceDto conferenceDto, Integer deadlineIndex) throws IOException {
|
||||||
if (conferenceDto.getDeadlines().get(deadlineIndex).getId() != null) {
|
if (conferenceDto.getDeadlines().get(deadlineIndex).getId() != null) {
|
||||||
conferenceDto.getRemovedDeadlineIds().add(conferenceDto.getDeadlines().get(deadlineIndex).getId());
|
conferenceDto.getRemovedDeadlineIds().add(conferenceDto.getDeadlines().get(deadlineIndex).getId());
|
||||||
@ -224,4 +251,39 @@ public class ConferenceService {
|
|||||||
modelMap.addAttribute("nearshoreSales", nearshoreSales);
|
modelMap.addAttribute("nearshoreSales", nearshoreSales);
|
||||||
modelMap.addAttribute("offshoreSales", offshoreSales);
|
modelMap.addAttribute("offshoreSales", offshoreSales);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void sendNotificationAfterUpdateDeadlines(Conference conference, List<Deadline> oldDeadlines) {
|
||||||
|
if (oldDeadlines.size() != conference.getDeadlines().size()) {
|
||||||
|
conferenceNotificationService.updateDeadlineNotification(conference);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (conference.getDeadlines()
|
||||||
|
.stream()
|
||||||
|
.filter(deadline -> !oldDeadlines.contains(deadline))
|
||||||
|
.count() > 0) {
|
||||||
|
conferenceNotificationService.updateDeadlineNotification(conference);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Deadline copyDeadline(Deadline oldDeadline) {
|
||||||
|
Deadline newDeadline = new Deadline(oldDeadline.getDate(), oldDeadline.getDescription());
|
||||||
|
newDeadline.setId(oldDeadline.getId());
|
||||||
|
return newDeadline;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void checkEmptyFieldsOfDeadline(ConferenceDto conferenceDto, Errors errors) {
|
||||||
|
for (Deadline deadline : conferenceDto.getDeadlines()) {
|
||||||
|
if (deadline.getDate() == null || deadline.getDescription().isEmpty()) {
|
||||||
|
errors.rejectValue("deadlines", "errorCode", "Все поля дедлайна должны быть заполнены");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void filterEmptyDeadlines(ConferenceDto conferenceDto) {
|
||||||
|
conferenceDto.setDeadlines(conferenceDto.getDeadlines().stream()
|
||||||
|
.filter(dto -> dto.getDate() != null || !org.springframework.util.StringUtils.isEmpty(dto.getDescription()))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import javax.persistence.Entity;
|
|||||||
import javax.persistence.Temporal;
|
import javax.persistence.Temporal;
|
||||||
import javax.persistence.TemporalType;
|
import javax.persistence.TemporalType;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
@Entity
|
@Entity
|
||||||
public class Deadline extends BaseEntity {
|
public class Deadline extends BaseEntity {
|
||||||
@ -51,4 +52,26 @@ public class Deadline extends BaseEntity {
|
|||||||
public void setDate(Date date) {
|
public void setDate(Date date) {
|
||||||
this.date = date;
|
this.date = date;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (o == null || getClass() != o.getClass()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!super.equals(o)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Deadline deadline = (Deadline) o;
|
||||||
|
return getId().equals(deadline.getId()) &&
|
||||||
|
description.equals(deadline.description) &&
|
||||||
|
date.equals(deadline.date);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hash(super.hashCode(), description, date);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,7 +132,7 @@ public class GrantController {
|
|||||||
|
|
||||||
@ModelAttribute("allPapers")
|
@ModelAttribute("allPapers")
|
||||||
public List<Paper> getAllPapers() {
|
public List<Paper> getAllPapers() {
|
||||||
return grantService.getAllPapers();
|
return grantService.getAllUncompletedPapers();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void filterEmptyDeadlines(GrantDto grantDto) {
|
private void filterEmptyDeadlines(GrantDto grantDto) {
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
package ru.ulstu.grant.model;
|
package ru.ulstu.grant.model;
|
||||||
|
|
||||||
|
import org.hibernate.annotations.Fetch;
|
||||||
|
import org.hibernate.annotations.FetchMode;
|
||||||
import org.hibernate.validator.constraints.NotBlank;
|
import org.hibernate.validator.constraints.NotBlank;
|
||||||
import ru.ulstu.core.model.BaseEntity;
|
import ru.ulstu.core.model.BaseEntity;
|
||||||
import ru.ulstu.core.model.UserContainer;
|
import ru.ulstu.core.model.UserContainer;
|
||||||
@ -7,6 +9,7 @@ import ru.ulstu.deadline.model.Deadline;
|
|||||||
import ru.ulstu.file.model.FileData;
|
import ru.ulstu.file.model.FileData;
|
||||||
import ru.ulstu.paper.model.Paper;
|
import ru.ulstu.paper.model.Paper;
|
||||||
import ru.ulstu.project.model.Project;
|
import ru.ulstu.project.model.Project;
|
||||||
|
import ru.ulstu.timeline.model.Event;
|
||||||
import ru.ulstu.user.model.User;
|
import ru.ulstu.user.model.User;
|
||||||
|
|
||||||
import javax.persistence.CascadeType;
|
import javax.persistence.CascadeType;
|
||||||
@ -66,10 +69,11 @@ public class Grant extends BaseEntity implements UserContainer {
|
|||||||
|
|
||||||
private String comment;
|
private String comment;
|
||||||
|
|
||||||
//Заявка на грант
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
@ManyToOne
|
@JoinColumn(name = "grant_id", unique = true)
|
||||||
@JoinColumn(name = "file_id")
|
@Fetch(FetchMode.SUBSELECT)
|
||||||
private FileData application;
|
private List<FileData> files = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
@ManyToOne(cascade = CascadeType.ALL)
|
@ManyToOne(cascade = CascadeType.ALL)
|
||||||
@JoinColumn(name = "project_id")
|
@JoinColumn(name = "project_id")
|
||||||
@ -87,8 +91,13 @@ public class Grant extends BaseEntity implements UserContainer {
|
|||||||
@JoinTable(name = "grants_papers",
|
@JoinTable(name = "grants_papers",
|
||||||
joinColumns = {@JoinColumn(name = "grant_id")},
|
joinColumns = {@JoinColumn(name = "grant_id")},
|
||||||
inverseJoinColumns = {@JoinColumn(name = "paper_id")})
|
inverseJoinColumns = {@JoinColumn(name = "paper_id")})
|
||||||
|
@Fetch(FetchMode.SUBSELECT)
|
||||||
private List<Paper> papers = new ArrayList<>();
|
private List<Paper> papers = new ArrayList<>();
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
|
||||||
|
@JoinColumn(name = "grant_id")
|
||||||
|
private List<Event> events = new ArrayList<>();
|
||||||
|
|
||||||
public GrantStatus getStatus() {
|
public GrantStatus getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -113,12 +122,12 @@ public class Grant extends BaseEntity implements UserContainer {
|
|||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public FileData getApplication() {
|
public List<FileData> getFiles() {
|
||||||
return application;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setApplication(FileData application) {
|
public void setFiles(List<FileData> files) {
|
||||||
this.application = application;
|
this.files = files;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
@ -166,6 +175,14 @@ public class Grant extends BaseEntity implements UserContainer {
|
|||||||
this.papers = papers;
|
this.papers = papers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Event> getEvents() {
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEvents(List<Event> events) {
|
||||||
|
this.events = events;
|
||||||
|
}
|
||||||
|
|
||||||
public Optional<Deadline> getNextDeadline() {
|
public Optional<Deadline> getNextDeadline() {
|
||||||
return deadlines
|
return deadlines
|
||||||
.stream()
|
.stream()
|
||||||
|
@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
import org.apache.commons.lang3.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.hibernate.validator.constraints.NotEmpty;
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
import ru.ulstu.deadline.model.Deadline;
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
|
import ru.ulstu.file.model.FileDataDto;
|
||||||
import ru.ulstu.paper.model.Paper;
|
import ru.ulstu.paper.model.Paper;
|
||||||
import ru.ulstu.project.model.ProjectDto;
|
import ru.ulstu.project.model.ProjectDto;
|
||||||
import ru.ulstu.user.model.UserDto;
|
import ru.ulstu.user.model.UserDto;
|
||||||
@ -25,7 +26,7 @@ public class GrantDto {
|
|||||||
private Grant.GrantStatus status;
|
private Grant.GrantStatus status;
|
||||||
private List<Deadline> deadlines = new ArrayList<>();
|
private List<Deadline> deadlines = new ArrayList<>();
|
||||||
private String comment;
|
private String comment;
|
||||||
private String applicationFileName;
|
private List<FileDataDto> files = new ArrayList<>();
|
||||||
private ProjectDto project;
|
private ProjectDto project;
|
||||||
private Set<Integer> authorIds;
|
private Set<Integer> authorIds;
|
||||||
private Set<UserDto> authors;
|
private Set<UserDto> authors;
|
||||||
@ -33,6 +34,8 @@ public class GrantDto {
|
|||||||
private boolean wasLeader;
|
private boolean wasLeader;
|
||||||
private boolean hasAge;
|
private boolean hasAge;
|
||||||
private boolean hasDegree;
|
private boolean hasDegree;
|
||||||
|
private boolean hasBAKPapers;
|
||||||
|
private boolean hasScopusPapers;
|
||||||
private List<Integer> paperIds = new ArrayList<>();
|
private List<Integer> paperIds = new ArrayList<>();
|
||||||
private List<Paper> papers = new ArrayList<>();
|
private List<Paper> papers = new ArrayList<>();
|
||||||
private List<Integer> removedDeadlineIds = new ArrayList<>();
|
private List<Integer> removedDeadlineIds = new ArrayList<>();
|
||||||
@ -47,6 +50,7 @@ public class GrantDto {
|
|||||||
@JsonProperty("status") Grant.GrantStatus status,
|
@JsonProperty("status") Grant.GrantStatus status,
|
||||||
@JsonProperty("deadlines") List<Deadline> deadlines,
|
@JsonProperty("deadlines") List<Deadline> deadlines,
|
||||||
@JsonProperty("comment") String comment,
|
@JsonProperty("comment") String comment,
|
||||||
|
@JsonProperty("files") List<FileDataDto> files,
|
||||||
@JsonProperty("project") ProjectDto project,
|
@JsonProperty("project") ProjectDto project,
|
||||||
@JsonProperty("authorIds") Set<Integer> authorIds,
|
@JsonProperty("authorIds") Set<Integer> authorIds,
|
||||||
@JsonProperty("authors") Set<UserDto> authors,
|
@JsonProperty("authors") Set<UserDto> authors,
|
||||||
@ -61,8 +65,9 @@ public class GrantDto {
|
|||||||
this.status = status;
|
this.status = status;
|
||||||
this.deadlines = deadlines;
|
this.deadlines = deadlines;
|
||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
this.applicationFileName = null;
|
this.files = files;
|
||||||
this.project = project;
|
this.project = project;
|
||||||
|
this.authorIds = authorIds;
|
||||||
this.authors = authors;
|
this.authors = authors;
|
||||||
this.leaderId = leaderId;
|
this.leaderId = leaderId;
|
||||||
this.wasLeader = wasLeader;
|
this.wasLeader = wasLeader;
|
||||||
@ -78,8 +83,8 @@ public class GrantDto {
|
|||||||
this.status = grant.getStatus();
|
this.status = grant.getStatus();
|
||||||
this.deadlines = grant.getDeadlines();
|
this.deadlines = grant.getDeadlines();
|
||||||
this.comment = grant.getComment();
|
this.comment = grant.getComment();
|
||||||
|
this.files = convert(grant.getFiles(), FileDataDto::new);
|
||||||
this.project = grant.getProject() == null ? null : new ProjectDto(grant.getProject());
|
this.project = grant.getProject() == null ? null : new ProjectDto(grant.getProject());
|
||||||
this.applicationFileName = grant.getApplication() == null ? null : grant.getApplication().getName();
|
|
||||||
this.authorIds = convert(grant.getAuthors(), user -> user.getId());
|
this.authorIds = convert(grant.getAuthors(), user -> user.getId());
|
||||||
this.authors = convert(grant.getAuthors(), UserDto::new);
|
this.authors = convert(grant.getAuthors(), UserDto::new);
|
||||||
this.leaderId = grant.getLeader().getId();
|
this.leaderId = grant.getLeader().getId();
|
||||||
@ -130,6 +135,14 @@ public class GrantDto {
|
|||||||
this.comment = comment;
|
this.comment = comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<FileDataDto> getFiles() {
|
||||||
|
return files;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFiles(List<FileDataDto> files) {
|
||||||
|
this.files = files;
|
||||||
|
}
|
||||||
|
|
||||||
public ProjectDto getProject() {
|
public ProjectDto getProject() {
|
||||||
return project;
|
return project;
|
||||||
}
|
}
|
||||||
@ -138,14 +151,6 @@ public class GrantDto {
|
|||||||
this.project = project;
|
this.project = project;
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getApplicationFileName() {
|
|
||||||
return applicationFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setApplicationFileName(String applicationFileName) {
|
|
||||||
this.applicationFileName = applicationFileName;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Set<Integer> getAuthorIds() {
|
public Set<Integer> getAuthorIds() {
|
||||||
return authorIds;
|
return authorIds;
|
||||||
}
|
}
|
||||||
@ -224,4 +229,20 @@ public class GrantDto {
|
|||||||
public void setRemovedDeadlineIds(List<Integer> removedDeadlineIds) {
|
public void setRemovedDeadlineIds(List<Integer> removedDeadlineIds) {
|
||||||
this.removedDeadlineIds = removedDeadlineIds;
|
this.removedDeadlineIds = removedDeadlineIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isHasBAKPapers() {
|
||||||
|
return hasBAKPapers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasBAKPapers(boolean hasBAKPapers) {
|
||||||
|
this.hasBAKPapers = hasBAKPapers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isHasScopusPapers() {
|
||||||
|
return hasScopusPapers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHasScopusPapers(boolean hasScopusPapers) {
|
||||||
|
this.hasScopusPapers = hasScopusPapers;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,73 @@
|
|||||||
|
package ru.ulstu.grant.service;
|
||||||
|
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.ulstu.core.util.DateUtils;
|
||||||
|
import ru.ulstu.grant.model.Grant;
|
||||||
|
import ru.ulstu.user.model.User;
|
||||||
|
import ru.ulstu.user.service.MailService;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class GrantNotificationService {
|
||||||
|
private final static int DAYS_TO_DEADLINE_NOTIFICATION = 7;
|
||||||
|
private final static String TEMPLATE_DEADLINE = "grantDeadlineNotification";
|
||||||
|
private final static String TEMPLATE_CREATE = "grantCreateNotification";
|
||||||
|
private final static String TEMPLATE_AUTHORS_CHANGED = "grantAuthorsChangeNotification";
|
||||||
|
private final static String TEMPLATE_LEADER_CHANGED = "grantLeaderChangeNotification";
|
||||||
|
|
||||||
|
private final static String TITLE_DEADLINE = "Приближается дедлайн гранта: %s";
|
||||||
|
private final static String TITLE_CREATE = "Создан грант: %s";
|
||||||
|
private final static String TITLE_AUTHORS_CHANGED = "Изменился состав рабочей группы гранта: %s";
|
||||||
|
private final static String TITLE_LEADER_CHANGED = "Изменился руководитель гранта: %s";
|
||||||
|
|
||||||
|
private final MailService mailService;
|
||||||
|
|
||||||
|
public GrantNotificationService(MailService mailService) {
|
||||||
|
this.mailService = mailService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendDeadlineNotifications(List<Grant> grants, boolean isDeadlineBeforeWeek) {
|
||||||
|
Date now = DateUtils.addDays(new Date(), DAYS_TO_DEADLINE_NOTIFICATION);
|
||||||
|
grants.stream()
|
||||||
|
.filter(grant -> needToSendDeadlineNotification(grant, now, isDeadlineBeforeWeek))
|
||||||
|
.forEach(grant -> sendMessageDeadline(grant));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean needToSendDeadlineNotification(Grant grant, Date compareDate, boolean isDeadlineBeforeWeek) {
|
||||||
|
return (grant.getNextDeadline().isPresent())
|
||||||
|
&& (compareDate.before(grant.getNextDeadline().get().getDate()) && isDeadlineBeforeWeek
|
||||||
|
|| compareDate.after(grant.getNextDeadline().get().getDate()) && !isDeadlineBeforeWeek)
|
||||||
|
&& grant.getNextDeadline().get().getDate().after(new Date());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendMessageDeadline(Grant grant) {
|
||||||
|
Map<String, Object> variables = ImmutableMap.of("grant", grant);
|
||||||
|
sendForAllAuthors(variables, grant, TEMPLATE_DEADLINE, String.format(TITLE_DEADLINE, grant.getTitle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendCreateNotification(Grant grant) {
|
||||||
|
Map<String, Object> variables = ImmutableMap.of("grant", grant);
|
||||||
|
sendForAllAuthors(variables, grant, TEMPLATE_CREATE, String.format(TITLE_CREATE, grant.getTitle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendAuthorsChangeNotification(Grant grant, Set<User> oldAuthors) {
|
||||||
|
Map<String, Object> variables = ImmutableMap.of("grant", grant, "oldAuthors", oldAuthors);
|
||||||
|
sendForAllAuthors(variables, grant, TEMPLATE_AUTHORS_CHANGED, String.format(TITLE_AUTHORS_CHANGED, grant.getTitle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void sendLeaderChangeNotification(Grant grant, User oldLeader) {
|
||||||
|
Map<String, Object> variables = ImmutableMap.of("grant", grant, "oldLeader", oldLeader);
|
||||||
|
sendForAllAuthors(variables, grant, TEMPLATE_LEADER_CHANGED, String.format(TITLE_LEADER_CHANGED, grant.getTitle()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void sendForAllAuthors(Map<String, Object> variables, Grant grant, String template, String title) {
|
||||||
|
Set<User> allAuthors = grant.getAuthors();
|
||||||
|
allAuthors.forEach(author -> mailService.sendEmailFromTemplate(variables, author, template, title));
|
||||||
|
mailService.sendEmailFromTemplate(variables, grant.getLeader(), template, title);
|
||||||
|
}
|
||||||
|
}
|
30
src/main/java/ru/ulstu/grant/service/GrantScheduler.java
Normal file
30
src/main/java/ru/ulstu/grant/service/GrantScheduler.java
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
package ru.ulstu.grant.service;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class GrantScheduler {
|
||||||
|
private final static boolean IS_DEADLINE_NOTIFICATION_BEFORE_WEEK = true;
|
||||||
|
|
||||||
|
private final Logger log = LoggerFactory.getLogger(GrantScheduler.class);
|
||||||
|
|
||||||
|
private final GrantNotificationService grantNotificationService;
|
||||||
|
private final GrantService grantService;
|
||||||
|
|
||||||
|
public GrantScheduler(GrantNotificationService grantNotificationService,
|
||||||
|
GrantService grantService) {
|
||||||
|
this.grantNotificationService = grantNotificationService;
|
||||||
|
this.grantService = grantService;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Scheduled(cron = "0 0 8 * * MON", zone = "Europe/Samara")
|
||||||
|
public void checkDeadlineBeforeWeek() {
|
||||||
|
log.debug("GrantScheduler.checkDeadlineBeforeWeek started");
|
||||||
|
grantNotificationService.sendDeadlineNotifications(grantService.findAll(), IS_DEADLINE_NOTIFICATION_BEFORE_WEEK);
|
||||||
|
log.debug("GrantScheduler.checkDeadlineBeforeWeek finished");
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import org.springframework.stereotype.Service;
|
|||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
import ru.ulstu.deadline.model.Deadline;
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
import ru.ulstu.deadline.service.DeadlineService;
|
import ru.ulstu.deadline.service.DeadlineService;
|
||||||
|
import ru.ulstu.file.model.FileDataDto;
|
||||||
import ru.ulstu.file.service.FileService;
|
import ru.ulstu.file.service.FileService;
|
||||||
import ru.ulstu.grant.model.Grant;
|
import ru.ulstu.grant.model.Grant;
|
||||||
import ru.ulstu.grant.model.GrantDto;
|
import ru.ulstu.grant.model.GrantDto;
|
||||||
@ -14,15 +15,19 @@ import ru.ulstu.paper.service.PaperService;
|
|||||||
import ru.ulstu.project.model.Project;
|
import ru.ulstu.project.model.Project;
|
||||||
import ru.ulstu.project.model.ProjectDto;
|
import ru.ulstu.project.model.ProjectDto;
|
||||||
import ru.ulstu.project.service.ProjectService;
|
import ru.ulstu.project.service.ProjectService;
|
||||||
|
import ru.ulstu.timeline.service.EventService;
|
||||||
import ru.ulstu.user.model.User;
|
import ru.ulstu.user.model.User;
|
||||||
import ru.ulstu.user.service.UserService;
|
import ru.ulstu.user.service.UserService;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import static java.util.stream.Collectors.toList;
|
||||||
import static org.springframework.util.ObjectUtils.isEmpty;
|
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||||
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
||||||
import static ru.ulstu.grant.model.Grant.GrantStatus.APPLICATION;
|
import static ru.ulstu.grant.model.Grant.GrantStatus.APPLICATION;
|
||||||
@ -37,19 +42,25 @@ public class GrantService {
|
|||||||
private final FileService fileService;
|
private final FileService fileService;
|
||||||
private final UserService userService;
|
private final UserService userService;
|
||||||
private final PaperService paperService;
|
private final PaperService paperService;
|
||||||
|
private final EventService eventService;
|
||||||
|
private final GrantNotificationService grantNotificationService;
|
||||||
|
|
||||||
public GrantService(GrantRepository grantRepository,
|
public GrantService(GrantRepository grantRepository,
|
||||||
FileService fileService,
|
FileService fileService,
|
||||||
DeadlineService deadlineService,
|
DeadlineService deadlineService,
|
||||||
ProjectService projectService,
|
ProjectService projectService,
|
||||||
UserService userService,
|
UserService userService,
|
||||||
PaperService paperService) {
|
PaperService paperService,
|
||||||
|
EventService eventService,
|
||||||
|
GrantNotificationService grantNotificationService) {
|
||||||
this.grantRepository = grantRepository;
|
this.grantRepository = grantRepository;
|
||||||
this.fileService = fileService;
|
this.fileService = fileService;
|
||||||
this.deadlineService = deadlineService;
|
this.deadlineService = deadlineService;
|
||||||
this.projectService = projectService;
|
this.projectService = projectService;
|
||||||
this.userService = userService;
|
this.userService = userService;
|
||||||
this.paperService = paperService;
|
this.paperService = paperService;
|
||||||
|
this.eventService = eventService;
|
||||||
|
this.grantNotificationService = grantNotificationService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Grant> findAll() {
|
public List<Grant> findAll() {
|
||||||
@ -70,6 +81,8 @@ public class GrantService {
|
|||||||
public Integer create(GrantDto grantDto) throws IOException {
|
public Integer create(GrantDto grantDto) throws IOException {
|
||||||
Grant newGrant = copyFromDto(new Grant(), grantDto);
|
Grant newGrant = copyFromDto(new Grant(), grantDto);
|
||||||
newGrant = grantRepository.save(newGrant);
|
newGrant = grantRepository.save(newGrant);
|
||||||
|
eventService.createFromGrant(newGrant);
|
||||||
|
grantNotificationService.sendCreateNotification(newGrant);
|
||||||
return newGrant.getId();
|
return newGrant.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,9 +94,9 @@ public class GrantService {
|
|||||||
grant.setProject(projectService.findById(grantDto.getProject().getId()));
|
grant.setProject(projectService.findById(grantDto.getProject().getId()));
|
||||||
}
|
}
|
||||||
grant.setDeadlines(deadlineService.saveOrCreate(grantDto.getDeadlines()));
|
grant.setDeadlines(deadlineService.saveOrCreate(grantDto.getDeadlines()));
|
||||||
if (grantDto.getApplicationFileName() != null) {
|
grant.setFiles(fileService.saveOrCreate(grantDto.getFiles().stream()
|
||||||
grant.setApplication(fileService.createFileFromTmp(grantDto.getApplicationFileName()));
|
.filter(f -> !f.isDeleted())
|
||||||
}
|
.collect(toList())));
|
||||||
grant.getAuthors().clear();
|
grant.getAuthors().clear();
|
||||||
if (grantDto.getAuthorIds() != null && !grantDto.getAuthorIds().isEmpty()) {
|
if (grantDto.getAuthorIds() != null && !grantDto.getAuthorIds().isEmpty()) {
|
||||||
grantDto.getAuthorIds().forEach(authorIds -> grant.getAuthors().add(userService.findById(authorIds)));
|
grantDto.getAuthorIds().forEach(authorIds -> grant.getAuthors().add(userService.findById(authorIds)));
|
||||||
@ -106,20 +119,36 @@ public class GrantService {
|
|||||||
@Transactional
|
@Transactional
|
||||||
public Integer update(GrantDto grantDto) throws IOException {
|
public Integer update(GrantDto grantDto) throws IOException {
|
||||||
Grant grant = grantRepository.findOne(grantDto.getId());
|
Grant grant = grantRepository.findOne(grantDto.getId());
|
||||||
if (grantDto.getApplicationFileName() != null && grant.getApplication() != null) {
|
Set<User> oldAuthors = new HashSet<>(grant.getAuthors());
|
||||||
fileService.deleteFile(grant.getApplication());
|
User oldLeader = grant.getLeader();
|
||||||
|
for (FileDataDto file : grantDto.getFiles().stream()
|
||||||
|
.filter(f -> f.isDeleted() && f.getId() != null)
|
||||||
|
.collect(toList())) {
|
||||||
|
fileService.delete(file.getId());
|
||||||
}
|
}
|
||||||
grantDto.getRemovedDeadlineIds().forEach(deadlineService::remove);
|
grantDto.getRemovedDeadlineIds().forEach(deadlineService::remove);
|
||||||
grantRepository.save(copyFromDto(grant, grantDto));
|
grantRepository.save(copyFromDto(grant, grantDto));
|
||||||
|
|
||||||
|
grant.getAuthors().forEach(author -> {
|
||||||
|
if (!oldAuthors.contains(author)) {
|
||||||
|
grantNotificationService.sendAuthorsChangeNotification(grant, oldAuthors);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
oldAuthors.forEach(oldAuthor -> {
|
||||||
|
if (!grant.getAuthors().contains(oldAuthor)) {
|
||||||
|
grantNotificationService.sendAuthorsChangeNotification(grant, oldAuthors);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if (grant.getLeader() != oldLeader) {
|
||||||
|
grantNotificationService.sendLeaderChangeNotification(grant, oldLeader);
|
||||||
|
}
|
||||||
|
eventService.updateGrantDeadlines(grant);
|
||||||
return grant.getId();
|
return grant.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public void delete(Integer grantId) throws IOException {
|
public void delete(Integer grantId) throws IOException {
|
||||||
Grant grant = grantRepository.findOne(grantId);
|
Grant grant = grantRepository.findOne(grantId);
|
||||||
if (grant.getApplication() != null) {
|
|
||||||
fileService.deleteFile(grant.getApplication());
|
|
||||||
}
|
|
||||||
grantRepository.delete(grant);
|
grantRepository.delete(grant);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,6 +168,10 @@ public class GrantService {
|
|||||||
grant.setLeader(user);
|
grant.setLeader(user);
|
||||||
grant.getPapers().add(paper);
|
grant.getPapers().add(paper);
|
||||||
grant = grantRepository.save(grant);
|
grant = grantRepository.save(grant);
|
||||||
|
|
||||||
|
eventService.createFromGrant(grant);
|
||||||
|
grantNotificationService.sendCreateNotification(grant);
|
||||||
|
|
||||||
return grant;
|
return grant;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,19 +186,28 @@ public class GrantService {
|
|||||||
public List<User> getGrantAuthors(GrantDto grantDto) {
|
public List<User> getGrantAuthors(GrantDto grantDto) {
|
||||||
List<User> filteredUsers = userService.filterByAgeAndDegree(grantDto.isHasAge(), grantDto.isHasDegree());
|
List<User> filteredUsers = userService.filterByAgeAndDegree(grantDto.isHasAge(), grantDto.isHasDegree());
|
||||||
if (grantDto.isWasLeader()) {
|
if (grantDto.isWasLeader()) {
|
||||||
filteredUsers = filteredUsers
|
filteredUsers = checkContains(filteredUsers, getCompletedGrantLeaders());
|
||||||
.stream()
|
}
|
||||||
.filter(getCompletedGrantLeaders()::contains)
|
if (grantDto.isHasBAKPapers()) {
|
||||||
.collect(Collectors.toList());
|
filteredUsers = checkContains(filteredUsers, getBAKAuthors());
|
||||||
|
}
|
||||||
|
if (grantDto.isHasScopusPapers()) {
|
||||||
|
filteredUsers = checkContains(filteredUsers, getScopusAuthors());
|
||||||
}
|
}
|
||||||
return filteredUsers;
|
return filteredUsers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<User> checkContains(List<User> filteredUsers, List<User> checkUsers) {
|
||||||
|
return filteredUsers.stream()
|
||||||
|
.filter(checkUsers::contains)
|
||||||
|
.collect(toList());
|
||||||
|
}
|
||||||
|
|
||||||
private List<User> getCompletedGrantLeaders() {
|
private List<User> getCompletedGrantLeaders() {
|
||||||
return grantRepository.findByStatus(Grant.GrantStatus.COMPLETED)
|
return grantRepository.findByStatus(Grant.GrantStatus.COMPLETED)
|
||||||
.stream()
|
.stream()
|
||||||
.map(Grant::getLeader)
|
.map(Grant::getLeader)
|
||||||
.collect(Collectors.toList());
|
.collect(toList());
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Paper> getGrantPapers(List<Integer> paperIds) {
|
public List<Paper> getGrantPapers(List<Integer> paperIds) {
|
||||||
@ -177,6 +219,10 @@ public class GrantService {
|
|||||||
return paperService.findAll();
|
return paperService.findAll();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Paper> getAllUncompletedPapers() {
|
||||||
|
return paperService.findAllNotCompleted();
|
||||||
|
}
|
||||||
|
|
||||||
public void attachPaper(GrantDto grantDto) {
|
public void attachPaper(GrantDto grantDto) {
|
||||||
if (!grantDto.getPaperIds().isEmpty()) {
|
if (!grantDto.getPaperIds().isEmpty()) {
|
||||||
grantDto.getPapers().clear();
|
grantDto.getPapers().clear();
|
||||||
@ -193,4 +239,26 @@ public class GrantService {
|
|||||||
grantDto.getDeadlines().remove((int) deadlineId);
|
grantDto.getDeadlines().remove((int) deadlineId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<User> getCompletedPapersAuthors(Paper.PaperType type) {
|
||||||
|
List<Paper> papers = paperService.findAllCompletedByType(type);
|
||||||
|
return papers.stream()
|
||||||
|
.filter(paper -> paper.getAuthors() != null)
|
||||||
|
.flatMap(paper -> paper.getAuthors().stream())
|
||||||
|
.collect(toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<User> getBAKAuthors() {
|
||||||
|
return getCompletedPapersAuthors(Paper.PaperType.VAK)
|
||||||
|
.stream()
|
||||||
|
.distinct()
|
||||||
|
.collect(toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<User> getScopusAuthors() {
|
||||||
|
List<User> authors = getCompletedPapersAuthors(Paper.PaperType.SCOPUS);
|
||||||
|
return authors
|
||||||
|
.stream()
|
||||||
|
.filter(author -> Collections.frequency(authors, author) > 3)
|
||||||
|
.collect(toList());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,10 +3,12 @@ package ru.ulstu.paper.model;
|
|||||||
import org.hibernate.annotations.Fetch;
|
import org.hibernate.annotations.Fetch;
|
||||||
import org.hibernate.annotations.FetchMode;
|
import org.hibernate.annotations.FetchMode;
|
||||||
import org.hibernate.validator.constraints.NotBlank;
|
import org.hibernate.validator.constraints.NotBlank;
|
||||||
|
import ru.ulstu.conference.model.Conference;
|
||||||
import ru.ulstu.core.model.BaseEntity;
|
import ru.ulstu.core.model.BaseEntity;
|
||||||
import ru.ulstu.core.model.UserContainer;
|
import ru.ulstu.core.model.UserContainer;
|
||||||
import ru.ulstu.deadline.model.Deadline;
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
import ru.ulstu.file.model.FileData;
|
import ru.ulstu.file.model.FileData;
|
||||||
|
import ru.ulstu.grant.model.Grant;
|
||||||
import ru.ulstu.timeline.model.Event;
|
import ru.ulstu.timeline.model.Event;
|
||||||
import ru.ulstu.user.model.User;
|
import ru.ulstu.user.model.User;
|
||||||
|
|
||||||
@ -114,6 +116,12 @@ public class Paper extends BaseEntity implements UserContainer {
|
|||||||
@Column(name = "latex_text")
|
@Column(name = "latex_text")
|
||||||
private String latexText;
|
private String latexText;
|
||||||
|
|
||||||
|
@ManyToMany(mappedBy = "papers")
|
||||||
|
private List<Conference> conferences;
|
||||||
|
|
||||||
|
@ManyToMany(mappedBy = "papers")
|
||||||
|
private List<Grant> grants;
|
||||||
|
|
||||||
public PaperStatus getStatus() {
|
public PaperStatus getStatus() {
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
@ -218,6 +226,22 @@ public class Paper extends BaseEntity implements UserContainer {
|
|||||||
this.latexText = latexText;
|
this.latexText = latexText;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Conference> getConferences() {
|
||||||
|
return conferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConferences(List<Conference> conferences) {
|
||||||
|
this.conferences = conferences;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Grant> getGrants() {
|
||||||
|
return grants;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrants(List<Grant> grants) {
|
||||||
|
this.grants = grants;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<User> getUsers() {
|
public Set<User> getUsers() {
|
||||||
return getAuthors();
|
return getAuthors();
|
||||||
|
@ -16,4 +16,12 @@ public interface PaperRepository extends JpaRepository<Paper, Integer> {
|
|||||||
List<Paper> findByIdNotIn(List<Integer> paperIds);
|
List<Paper> findByIdNotIn(List<Integer> paperIds);
|
||||||
|
|
||||||
List<Paper> findAllByIdIn(List<Integer> paperIds);
|
List<Paper> findAllByIdIn(List<Integer> paperIds);
|
||||||
|
|
||||||
|
List<Paper> findByTypeAndStatus(Paper.PaperType type, Paper.PaperStatus status);
|
||||||
|
|
||||||
|
List<Paper> findByStatusNot(Paper.PaperStatus status);
|
||||||
|
|
||||||
|
List<Paper> findByConferencesIsNullAndStatusNot(Paper.PaperStatus status);
|
||||||
|
|
||||||
|
List<Paper> findByIdNotInAndConferencesIsNullAndStatusNot(List<Integer> paperIds, Paper.PaperStatus status);
|
||||||
}
|
}
|
||||||
|
@ -242,11 +242,14 @@ public class PaperService {
|
|||||||
|
|
||||||
public List<Paper> findAllNotSelect(List<Integer> paperIds) {
|
public List<Paper> findAllNotSelect(List<Integer> paperIds) {
|
||||||
if (!paperIds.isEmpty()) {
|
if (!paperIds.isEmpty()) {
|
||||||
return sortPapers(paperRepository.findByIdNotIn(paperIds));
|
return sortPapers(paperRepository.findByIdNotInAndConferencesIsNullAndStatusNot(paperIds, COMPLETED));
|
||||||
} else {
|
} else {
|
||||||
return sortPapers(paperRepository.findAll());
|
return sortPapers(paperRepository.findByConferencesIsNullAndStatusNot(COMPLETED));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Paper> findAllNotCompleted() {
|
||||||
|
return paperRepository.findByStatusNot(COMPLETED);
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Paper> findAllSelect(List<Integer> paperIds) {
|
public List<Paper> findAllSelect(List<Integer> paperIds) {
|
||||||
@ -303,4 +306,8 @@ public class PaperService {
|
|||||||
StringUtils.isEmpty(referenceDto.getPublisher()) ? "" : referenceDto.getPublisher() + ", ",
|
StringUtils.isEmpty(referenceDto.getPublisher()) ? "" : referenceDto.getPublisher() + ", ",
|
||||||
referenceDto.getPages());
|
referenceDto.getPages());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Paper> findAllCompletedByType(Paper.PaperType type) {
|
||||||
|
return paperRepository.findByTypeAndStatus(type, Paper.PaperStatus.COMPLETED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,13 @@
|
|||||||
package ru.ulstu.ping.repository;
|
package ru.ulstu.ping.repository;
|
||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import org.springframework.data.repository.query.Param;
|
||||||
|
import ru.ulstu.conference.model.Conference;
|
||||||
import ru.ulstu.ping.model.Ping;
|
import ru.ulstu.ping.model.Ping;
|
||||||
|
|
||||||
public interface PingRepository extends JpaRepository<Ping, Integer> {
|
public interface PingRepository extends JpaRepository<Ping, Integer> {
|
||||||
|
|
||||||
|
@Query("SELECT count(*) FROM Ping p WHERE (DAY(p.date) = :day) AND (MONTH(p.date) = :month) AND (YEAR(p.date) = :year) AND (p.conference = :conference)")
|
||||||
|
long countByConferenceAndDate(@Param("conference") Conference conference, @Param("day") Integer day, @Param("month") Integer month, @Param("year") Integer year);
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@ import ru.ulstu.ping.repository.PingRepository;
|
|||||||
import ru.ulstu.user.service.UserService;
|
import ru.ulstu.user.service.UserService;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
@ -27,4 +28,9 @@ public class PingService {
|
|||||||
newPing.setConference(conference);
|
newPing.setConference(conference);
|
||||||
pingRepository.save(newPing);
|
pingRepository.save(newPing);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Integer countPingYesterday(Conference conference, Calendar calendar) {
|
||||||
|
return Math.toIntExact(pingRepository.countByConferenceAndDate(conference, calendar.get(Calendar.DAY_OF_MONTH),
|
||||||
|
calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.YEAR)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
package ru.ulstu.timeline.model;
|
package ru.ulstu.timeline.model;
|
||||||
|
|
||||||
import org.hibernate.validator.constraints.NotBlank;
|
import org.hibernate.validator.constraints.NotBlank;
|
||||||
|
import ru.ulstu.conference.model.Conference;
|
||||||
import ru.ulstu.core.model.BaseEntity;
|
import ru.ulstu.core.model.BaseEntity;
|
||||||
|
import ru.ulstu.grant.model.Grant;
|
||||||
import ru.ulstu.paper.model.Paper;
|
import ru.ulstu.paper.model.Paper;
|
||||||
import ru.ulstu.user.model.User;
|
import ru.ulstu.user.model.User;
|
||||||
|
|
||||||
@ -18,6 +20,7 @@ import javax.persistence.OneToMany;
|
|||||||
import javax.persistence.Temporal;
|
import javax.persistence.Temporal;
|
||||||
import javax.persistence.TemporalType;
|
import javax.persistence.TemporalType;
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@ -62,7 +65,7 @@ public class Event extends BaseEntity {
|
|||||||
private String description;
|
private String description;
|
||||||
|
|
||||||
@ManyToMany(fetch = FetchType.EAGER)
|
@ManyToMany(fetch = FetchType.EAGER)
|
||||||
private List<User> recipients;
|
private List<User> recipients = new ArrayList<User>();
|
||||||
|
|
||||||
@ManyToOne
|
@ManyToOne
|
||||||
@JoinColumn(name = "child_id")
|
@JoinColumn(name = "child_id")
|
||||||
@ -76,6 +79,14 @@ public class Event extends BaseEntity {
|
|||||||
@JoinColumn(name = "paper_id")
|
@JoinColumn(name = "paper_id")
|
||||||
private Paper paper;
|
private Paper paper;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "conference_id")
|
||||||
|
private Conference conference;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
@JoinColumn(name = "grant_id")
|
||||||
|
private Grant grant;
|
||||||
|
|
||||||
public String getTitle() {
|
public String getTitle() {
|
||||||
return title;
|
return title;
|
||||||
}
|
}
|
||||||
@ -163,4 +174,20 @@ public class Event extends BaseEntity {
|
|||||||
public void setPaper(Paper paper) {
|
public void setPaper(Paper paper) {
|
||||||
this.paper = paper;
|
this.paper = paper;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Conference getConference() {
|
||||||
|
return conference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConference(Conference conference) {
|
||||||
|
this.conference = conference;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Grant getGrant() {
|
||||||
|
return grant;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrant(Grant grant) {
|
||||||
|
this.grant = grant;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@ package ru.ulstu.timeline.model;
|
|||||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
import org.hibernate.validator.constraints.NotBlank;
|
import org.hibernate.validator.constraints.NotBlank;
|
||||||
|
import ru.ulstu.conference.model.ConferenceDto;
|
||||||
|
import ru.ulstu.grant.model.GrantDto;
|
||||||
import ru.ulstu.paper.model.PaperDto;
|
import ru.ulstu.paper.model.PaperDto;
|
||||||
import ru.ulstu.user.model.UserDto;
|
import ru.ulstu.user.model.UserDto;
|
||||||
|
|
||||||
@ -25,6 +27,8 @@ public class EventDto {
|
|||||||
private final String description;
|
private final String description;
|
||||||
private final List<UserDto> recipients;
|
private final List<UserDto> recipients;
|
||||||
private PaperDto paperDto;
|
private PaperDto paperDto;
|
||||||
|
private ConferenceDto conferenceDto;
|
||||||
|
private GrantDto grantDto;
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
public EventDto(@JsonProperty("id") Integer id,
|
public EventDto(@JsonProperty("id") Integer id,
|
||||||
@ -36,7 +40,9 @@ public class EventDto {
|
|||||||
@JsonProperty("updateDate") Date updateDate,
|
@JsonProperty("updateDate") Date updateDate,
|
||||||
@JsonProperty("description") String description,
|
@JsonProperty("description") String description,
|
||||||
@JsonProperty("paperDto") PaperDto paperDto,
|
@JsonProperty("paperDto") PaperDto paperDto,
|
||||||
@JsonProperty("recipients") List<UserDto> recipients) {
|
@JsonProperty("recipients") List<UserDto> recipients,
|
||||||
|
@JsonProperty("conferenceDto") ConferenceDto conferenceDto,
|
||||||
|
@JsonProperty("grantDto") GrantDto grantDto) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.period = period;
|
this.period = period;
|
||||||
@ -47,6 +53,8 @@ public class EventDto {
|
|||||||
this.description = description;
|
this.description = description;
|
||||||
this.recipients = recipients;
|
this.recipients = recipients;
|
||||||
this.paperDto = paperDto;
|
this.paperDto = paperDto;
|
||||||
|
this.conferenceDto = conferenceDto;
|
||||||
|
this.grantDto = grantDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
public EventDto(Event event) {
|
public EventDto(Event event) {
|
||||||
@ -58,8 +66,16 @@ public class EventDto {
|
|||||||
this.createDate = event.getCreateDate();
|
this.createDate = event.getCreateDate();
|
||||||
this.updateDate = event.getUpdateDate();
|
this.updateDate = event.getUpdateDate();
|
||||||
this.description = event.getDescription();
|
this.description = event.getDescription();
|
||||||
this.paperDto = new PaperDto(event.getPaper());
|
|
||||||
this.recipients = convert(event.getRecipients(), UserDto::new);
|
this.recipients = convert(event.getRecipients(), UserDto::new);
|
||||||
|
if (paperDto != null) {
|
||||||
|
this.paperDto = new PaperDto(event.getPaper());
|
||||||
|
}
|
||||||
|
if (conferenceDto != null) {
|
||||||
|
this.conferenceDto = new ConferenceDto(event.getConference());
|
||||||
|
}
|
||||||
|
if (grantDto != null) {
|
||||||
|
this.grantDto = new GrantDto(event.getGrant());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Integer getId() {
|
public Integer getId() {
|
||||||
@ -105,4 +121,20 @@ public class EventDto {
|
|||||||
public void setPaperDto(PaperDto paperDto) {
|
public void setPaperDto(PaperDto paperDto) {
|
||||||
this.paperDto = paperDto;
|
this.paperDto = paperDto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ConferenceDto getConferenceDto() {
|
||||||
|
return conferenceDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setConferenceDto(ConferenceDto conferenceDto) {
|
||||||
|
this.conferenceDto = conferenceDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public GrantDto getGrantDto() {
|
||||||
|
return grantDto;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrantDto(GrantDto grantDto) {
|
||||||
|
this.grantDto = grantDto;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@ package ru.ulstu.timeline.repository;
|
|||||||
|
|
||||||
import org.springframework.data.jpa.repository.JpaRepository;
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
import org.springframework.data.jpa.repository.Query;
|
import org.springframework.data.jpa.repository.Query;
|
||||||
|
import ru.ulstu.conference.model.Conference;
|
||||||
|
import ru.ulstu.grant.model.Grant;
|
||||||
import ru.ulstu.paper.model.Paper;
|
import ru.ulstu.paper.model.Paper;
|
||||||
import ru.ulstu.timeline.model.Event;
|
import ru.ulstu.timeline.model.Event;
|
||||||
|
|
||||||
@ -15,4 +17,8 @@ public interface EventRepository extends JpaRepository<Event, Integer> {
|
|||||||
List<Event> findAllFuture();
|
List<Event> findAllFuture();
|
||||||
|
|
||||||
List<Event> findAllByPaper(Paper paper);
|
List<Event> findAllByPaper(Paper paper);
|
||||||
|
|
||||||
|
List<Event> findAllByConference(Conference conference);
|
||||||
|
|
||||||
|
List<Event> findAllByGrant(Grant grant);
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,9 @@ import org.apache.commons.lang3.time.DateUtils;
|
|||||||
import org.springframework.context.annotation.Lazy;
|
import org.springframework.context.annotation.Lazy;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
import ru.ulstu.conference.model.Conference;
|
||||||
import ru.ulstu.deadline.model.Deadline;
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
|
import ru.ulstu.grant.model.Grant;
|
||||||
import ru.ulstu.paper.model.Paper;
|
import ru.ulstu.paper.model.Paper;
|
||||||
import ru.ulstu.timeline.model.Event;
|
import ru.ulstu.timeline.model.Event;
|
||||||
import ru.ulstu.timeline.model.EventDto;
|
import ru.ulstu.timeline.model.EventDto;
|
||||||
@ -140,4 +142,65 @@ public class EventService {
|
|||||||
public List<EventDto> findAllFutureDto() {
|
public List<EventDto> findAllFutureDto() {
|
||||||
return convert(findAllFuture(), EventDto::new);
|
return convert(findAllFuture(), EventDto::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void createFromConference(Conference newConference) {
|
||||||
|
List<Timeline> timelines = timelineService.findAll();
|
||||||
|
Timeline timeline = timelines.isEmpty() ? new Timeline() : timelines.get(0);
|
||||||
|
|
||||||
|
for (Deadline deadline : newConference.getDeadlines()
|
||||||
|
.stream()
|
||||||
|
.filter(d -> d.getDate().after(new Date()) || DateUtils.isSameDay(d.getDate(), new Date()))
|
||||||
|
.collect(Collectors.toList())) {
|
||||||
|
Event newEvent = new Event();
|
||||||
|
newEvent.setTitle("Дедлайн конференции");
|
||||||
|
newEvent.setStatus(Event.EventStatus.NEW);
|
||||||
|
newEvent.setExecuteDate(deadline.getDate());
|
||||||
|
newEvent.setCreateDate(new Date());
|
||||||
|
newEvent.setUpdateDate(new Date());
|
||||||
|
newEvent.setDescription("Дедлайн '" + deadline.getDescription() + "' конференции '" + newConference.getTitle() + "'");
|
||||||
|
newConference.getUsers().forEach(conferenceUser -> newEvent.getRecipients().add(conferenceUser.getUser()));
|
||||||
|
newEvent.setConference(newConference);
|
||||||
|
save(newEvent);
|
||||||
|
|
||||||
|
timeline.getEvents().add(newEvent);
|
||||||
|
timelineService.save(timeline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateConferenceDeadlines(Conference conference) {
|
||||||
|
eventRepository.delete(eventRepository.findAllByConference(conference));
|
||||||
|
createFromConference(conference);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void createFromGrant(Grant newGrant) {
|
||||||
|
List<Timeline> timelines = timelineService.findAll();
|
||||||
|
Timeline timeline = timelines.isEmpty() ? new Timeline() : timelines.get(0);
|
||||||
|
|
||||||
|
for (Deadline deadline : newGrant.getDeadlines()
|
||||||
|
.stream()
|
||||||
|
.filter(d -> d.getDate().after(new Date()) || DateUtils.isSameDay(d.getDate(), new Date()))
|
||||||
|
.collect(Collectors.toList())) {
|
||||||
|
Event newEvent = new Event();
|
||||||
|
newEvent.setTitle("Дедлайн гранта");
|
||||||
|
newEvent.setStatus(Event.EventStatus.NEW);
|
||||||
|
newEvent.setExecuteDate(deadline.getDate());
|
||||||
|
newEvent.setCreateDate(new Date());
|
||||||
|
newEvent.setUpdateDate(new Date());
|
||||||
|
newEvent.setDescription("Дедлайн '" + deadline.getDescription() + "' гранта '" + newGrant.getTitle() + "'");
|
||||||
|
if (newGrant.getAuthors() != null) {
|
||||||
|
newEvent.setRecipients(new ArrayList(newGrant.getAuthors()));
|
||||||
|
}
|
||||||
|
newEvent.getRecipients().add(newGrant.getLeader());
|
||||||
|
newEvent.setGrant(newGrant);
|
||||||
|
eventRepository.save(newEvent);
|
||||||
|
|
||||||
|
timeline.getEvents().add(newEvent);
|
||||||
|
timelineService.save(timeline);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void updateGrantDeadlines(Grant grant) {
|
||||||
|
eventRepository.delete(eventRepository.findAllByGrant(grant));
|
||||||
|
createFromGrant(grant);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
13
src/main/resources/db/changelog-20190426_000000-schema.xml
Normal file
13
src/main/resources/db/changelog-20190426_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="vova" id="20190426_000000-1">
|
||||||
|
<addColumn tableName="event">
|
||||||
|
<column name="conference_id" type="integer"></column>
|
||||||
|
</addColumn>
|
||||||
|
<addForeignKeyConstraint baseTableName="event" baseColumnNames="conference_id"
|
||||||
|
constraintName="fk_event_conference_id" referencedTableName="conference"
|
||||||
|
referencedColumnNames="id"/>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
10
src/main/resources/db/changelog-20190428_000000-schema.xml
Normal file
10
src/main/resources/db/changelog-20190428_000000-schema.xml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
<?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="anton" id="20190428_000000-1">
|
||||||
|
<update tableName="project">
|
||||||
|
<column name="status" value="APPLICATION"/>
|
||||||
|
</update>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
11
src/main/resources/db/changelog-20190430_000000-schema.xml
Normal file
11
src/main/resources/db/changelog-20190430_000000-schema.xml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
<?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="20190430_000000-1">
|
||||||
|
<dropColumn columnName="file_id" tableName="grants"/>
|
||||||
|
<addColumn tableName="file">
|
||||||
|
<column name="grant_id" type="integer"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
@ -2,23 +2,14 @@
|
|||||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
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">
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||||
<changeSet author="nastya" id="20190505_000000-1">
|
|
||||||
<createTable tableName="scheduler">
|
|
||||||
<column name="id" type="integer">
|
|
||||||
<constraints nullable="false"/>
|
|
||||||
</column>
|
|
||||||
<column name="task_id" type="integer">
|
|
||||||
<constraints nullable="false"/>
|
|
||||||
</column>
|
|
||||||
<column name="date" type="timestamp">
|
|
||||||
<constraints nullable="false"/>
|
|
||||||
</column>
|
|
||||||
<column name="version" type="integer"/>
|
|
||||||
</createTable>
|
|
||||||
<addPrimaryKey columnNames="id" constraintName="pk_scheduler" tableName="scheduler"/>
|
|
||||||
<addForeignKeyConstraint baseTableName="scheduler" baseColumnNames="task_id"
|
|
||||||
constraintName="fk_scheduler_task_id" referencedTableName="task"
|
|
||||||
referencedColumnNames="id"/>
|
|
||||||
</changeSet>
|
|
||||||
|
|
||||||
|
<changeSet author="tanya" id="20190505_000000-1">
|
||||||
|
<addColumn tableName="event">
|
||||||
|
<column name="grant_id" type="integer"/>
|
||||||
|
</addColumn>
|
||||||
|
<addForeignKeyConstraint baseTableName="event" baseColumnNames="grant_id"
|
||||||
|
constraintName="fk_event_grant_id" referencedTableName="grants"
|
||||||
|
referencedColumnNames="id"/>
|
||||||
|
|
||||||
|
</changeSet>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
||||||
|
25
src/main/resources/db/changelog-20190505_000001-schema.xml
Normal file
25
src/main/resources/db/changelog-20190505_000001-schema.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?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="nastya" id="20190505_000001-1">
|
||||||
|
<createTable tableName="scheduler">
|
||||||
|
<column name="id" type="integer">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="task_id" type="integer">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="date" type="timestamp">
|
||||||
|
<constraints nullable="false"/>
|
||||||
|
</column>
|
||||||
|
<column name="version" type="integer"/>
|
||||||
|
</createTable>
|
||||||
|
<addPrimaryKey columnNames="id" constraintName="pk_scheduler" tableName="scheduler"/>
|
||||||
|
<addForeignKeyConstraint baseTableName="scheduler" baseColumnNames="task_id"
|
||||||
|
constraintName="fk_scheduler_task_id" referencedTableName="task"
|
||||||
|
referencedColumnNames="id"/>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
</databaseChangeLog>
|
@ -0,0 +1,8 @@
|
|||||||
|
<?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="20190507_000000-1">
|
||||||
|
<dropColumn columnName="deadline_date" tableName="grants"/>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
14
src/main/resources/db/changelog-20190507_000001-schema.xml
Normal file
14
src/main/resources/db/changelog-20190507_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="tanya" id="20190507_000001-1">
|
||||||
|
<sql>
|
||||||
|
update grants
|
||||||
|
set leader_id =
|
||||||
|
(select u.id
|
||||||
|
from users u
|
||||||
|
where u.last_name = 'Романов' AND u.first_name = 'Антон');
|
||||||
|
</sql>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
@ -34,5 +34,11 @@
|
|||||||
<include file="db/changelog-20190421_000000-schema.xml"/>
|
<include file="db/changelog-20190421_000000-schema.xml"/>
|
||||||
<include file="db/changelog-20190422_000000-schema.xml"/>
|
<include file="db/changelog-20190422_000000-schema.xml"/>
|
||||||
<include file="db/changelog-20190424_000000-schema.xml"/>
|
<include file="db/changelog-20190424_000000-schema.xml"/>
|
||||||
|
<include file="db/changelog-20190426_000000-schema.xml"/>
|
||||||
|
<include file="db/changelog-20190428_000000-schema.xml"/>
|
||||||
|
<include file="db/changelog-20190430_000000-schema.xml"/>
|
||||||
<include file="db/changelog-20190505_000000-schema.xml"/>
|
<include file="db/changelog-20190505_000000-schema.xml"/>
|
||||||
|
<include file="db/changelog-20190505_000001-schema.xml"/>
|
||||||
|
<include file="db/changelog-20190507_000000-schema.xml"/>
|
||||||
|
<include file="db/changelog-20190507_000001-schema.xml"/>
|
||||||
</databaseChangeLog>
|
</databaseChangeLog>
|
@ -0,0 +1,30 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title>Уведомление о создании конференции</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Уважаемый(ая) <span th:text="${user.firstName + ' ' + user.lastName}">Ivan Ivanov</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Была создана новая конференция: "<a th:href="@{|${baseUrl}/conferences/conference?id=${conference.id}|}">
|
||||||
|
<span th:text="${conference.title}">Title</span></a>".
|
||||||
|
<br/>
|
||||||
|
Спешите принять участие!
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Даты проведения:
|
||||||
|
<span th:text="${#dates.format(conference.beginDate, 'dd.MM.yyyy')}"></span>
|
||||||
|
-
|
||||||
|
<span th:text="${#dates.format(conference.endDate, 'dd.MM.yyyy')}"></span>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Regards,
|
||||||
|
<br/>
|
||||||
|
<em>NG-tracker.</em>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,29 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title>Уведомление о дедлайне конференции</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Уважаемый(ая) <span th:text="${user.firstName + ' ' + user.lastName}">Ivan Ivanov</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Приближается дедлайн конференции "<a th:href="@{|${baseUrl}/conferences/conference?id=${conference.id}|}">
|
||||||
|
<span th:text="${conference.title}">Title</span></a>".
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Срок исполнения: <b><span th:text="${#dates.format(conference.nextDeadline.get().date, 'dd.MM.yyyy')}"></span></b>.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
Примечание: <b><span th:text="${conference.nextDeadline.get().description}"></span></b>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Regards,
|
||||||
|
<br/>
|
||||||
|
<em>NG-tracker.</em>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,25 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title>Обратите внимание на конференциию</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Уважаемый(ая) <span th:text="${user.firstName + ' ' + user.lastName}">Ivan Ivanov</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Конференция "<a th:href="@{|${baseUrl}/conferences/conference?id=${conference.id}|}">
|
||||||
|
<span th:text="${conference.title}">Title</span></a>" была пропингована
|
||||||
|
<b><span th:text="${conference.ping}"></span></b> раз.
|
||||||
|
<br/>
|
||||||
|
Обратите внимание.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Regards,
|
||||||
|
<br/>
|
||||||
|
<em>NG-tracker.</em>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,31 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title>Уведомление об изменении дат проведения конференции</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Уважаемый(ая) <span th:text="${user.firstName + ' ' + user.lastName}">Ivan Ivanov</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Даты проведения конференции "<a th:href="@{|${baseUrl}/conferences/conference?id=${conference.id}|}">
|
||||||
|
<span th:text="${conference.title}">Title</span></a>" изменились с <br/>
|
||||||
|
"<span th:text="${#dates.format(oldBeginDate, 'dd.MM.yyyy')}">oldBeginDate</span>"
|
||||||
|
-
|
||||||
|
"<span th:text="${#dates.format(oldEndDate, 'dd.MM.yyyy')}">oldEndDate</span>"
|
||||||
|
<br/>
|
||||||
|
|
||||||
|
на <br/>
|
||||||
|
"<span th:text="${#dates.format(conference.beginDate, 'dd.MM.yyyy')}"></span>"
|
||||||
|
-
|
||||||
|
"<span th:text="${#dates.format(conference.endDate, 'dd.MM.yyyy')}"></span>".
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Regards,
|
||||||
|
<br/>
|
||||||
|
<em>NG-tracker.</em>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title>Уведомление об изменении дедлайнов конференции</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Уважаемый(ая) <span th:text="${user.firstName + ' ' + user.lastName}">Ivan Ivanov</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Дедлайны конференции "<a th:href="@{|${baseUrl}/conferences/conference?id=${conference.id}|}">
|
||||||
|
<span th:text="${conference.title}">Title</span></a>" притерпели изменения.
|
||||||
|
<br/>
|
||||||
|
Ознакомтесь с изменениями.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Regards,
|
||||||
|
<br/>
|
||||||
|
<em>NG-tracker.</em>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title>Уведомление об изменении состава рабочей группы</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Уважаемый(ая) <span th:text="${user.firstName + ' ' + user.lastName}">Ivan Ivanov</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Состав рабочей группы гранта "<a th:href="@{|${baseUrl}/grants/grant?id=${grant.id}|}"><span
|
||||||
|
th:text="${grant.title}">Title</span></a>" сменился с
|
||||||
|
" <span th:each="author : ${oldAuthors}" th:text="${author.lastName + ' '}">oldAuthors</span>"
|
||||||
|
на " <span th:each="author : ${grant.authors}" th:text="${author.lastName + ' '}">newAuthors</span>".
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Regards,
|
||||||
|
<br/>
|
||||||
|
<em>NG-tracker.</em>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title>Уведомление о создании гранта</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Уважаемый(ая) <span th:text="${user.firstName + ' ' + user.lastName}">Ivan Ivanov</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Был добавлен новый грант: "<a th:href="@{|${baseUrl}/grants/grant?id=${grant.id}|}">
|
||||||
|
<span th:text="${grant.title}">Title</span></a>".
|
||||||
|
<br/>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Руководитель гранта:
|
||||||
|
<span th:text="${grant.leader.firstName}"></span>
|
||||||
|
<span th:text="${grant.leader.lastName}">Leader</span>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Regards,
|
||||||
|
<br/>
|
||||||
|
<em>NG-tracker.</em>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,28 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title>Уведомление о дедлайне гранта</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Уважаемый(ая) <span th:text="${user.firstName + ' ' + user.lastName}">Ivan Ivanov</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Приближается дедлайн гранта "<a th:href="@{|${baseUrl}/grants/grant?id=${grant.id}|}"><span
|
||||||
|
th:text="${grant.title}">Title</span></a>".
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Срок исполнения: <b><span th:text="${#dates.format(grant.nextDeadline.get().date, 'dd.MM.yyyy')}">Date</span></b>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Примечание: <b><span th:text="${grant.nextDeadline.get().description}">Description</span></b>.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Regards,
|
||||||
|
<br/>
|
||||||
|
<em>NG-tracker.</em>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -0,0 +1,24 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<title>Уведомление об изменении руководителя гранта</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
|
||||||
|
<link rel="shortcut icon" th:href="@{|${baseUrl}/favicon.ico|}"/>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>
|
||||||
|
Уважаемый(ая) <span th:text="${user.firstName + ' ' + user.lastName}">Ivan Ivanov</span>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Руководитель гранта "<a th:href="@{|${baseUrl}/grants/grant?id=${grant.id}|}"><span
|
||||||
|
th:text="${grant.title}">Title</span></a>" сменился с
|
||||||
|
"<span th:text="${oldLeader.lastName} ">oldLeader</span>"
|
||||||
|
на "<span th:text="${grant.leader.lastName}">newLeader</span>".
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Regards,
|
||||||
|
<br/>
|
||||||
|
<em>NG-tracker.</em>
|
||||||
|
</p>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -7,6 +7,10 @@ body {
|
|||||||
border-radius: .25rem;
|
border-radius: .25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.conference-row .d-flex:hover .icon-delete {
|
||||||
|
visibility: visible;
|
||||||
|
}
|
||||||
|
|
||||||
.filter-option-inner-inner {
|
.filter-option-inner-inner {
|
||||||
color: white;
|
color: white;
|
||||||
}
|
}
|
||||||
@ -17,10 +21,20 @@ body {
|
|||||||
|
|
||||||
.conference-row .d-flex .text-decoration {
|
.conference-row .d-flex .text-decoration {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.conference-row .d-flex .text-decoration:nth-child(1) {
|
.conference-row .d-flex .text-decoration:nth-child(1) {
|
||||||
margin-left: 10px;
|
margin-left: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.conference-row .d-flex .icon-delete {
|
||||||
|
width: 29px;
|
||||||
|
height: 29px;
|
||||||
|
margin: auto;
|
||||||
|
border: none;
|
||||||
|
visibility: hidden;
|
||||||
|
background-color: transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -159,7 +173,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.icon-delete:hover {
|
.icon-delete:hover {
|
||||||
background-color: #ff0000;
|
background-color: #ff0000 !important;
|
||||||
transition: background-color .15s ease-in-out;
|
transition: background-color .15s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,4 +28,16 @@
|
|||||||
|
|
||||||
.btn-delete-deadline {
|
.btn-delete-deadline {
|
||||||
color: black;
|
color: black;
|
||||||
|
}
|
||||||
|
|
||||||
|
.div-file-name{
|
||||||
|
padding-top: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.div-loader {
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.div-row-file {
|
||||||
|
margin-bottom: 2px;
|
||||||
}
|
}
|
@ -1,7 +1,7 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en"
|
<html lang="en"
|
||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
layout:decorator="default" xmlns:th="">
|
layout:decorator="default" xmlns:th="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/html">
|
||||||
<head>
|
<head>
|
||||||
<link rel="stylesheet" type="text/css" href="../css/conference.css"/>
|
<link rel="stylesheet" type="text/css" href="../css/conference.css"/>
|
||||||
</head>
|
</head>
|
||||||
@ -135,7 +135,6 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="papers">Статьи:</label>
|
<label for="papers">Статьи:</label>
|
||||||
<div class="paper-list form-control list-group" id="papers">
|
<div class="paper-list form-control list-group" id="papers">
|
||||||
<!--<input th:type="hidden" th:field="*{papers}"/>-->
|
|
||||||
<div class="paper d-flex list-group-item p-0"
|
<div class="paper d-flex list-group-item p-0"
|
||||||
th:each="paper, rowStat : *{papers}">
|
th:each="paper, rowStat : *{papers}">
|
||||||
<input type="hidden" th:field="*{papers[__${rowStat.index}__].id}"/>
|
<input type="hidden" th:field="*{papers[__${rowStat.index}__].id}"/>
|
||||||
@ -148,15 +147,13 @@
|
|||||||
<span th:text="*{papers[__${rowStat.index}__].title}">
|
<span th:text="*{papers[__${rowStat.index}__].title}">
|
||||||
Имя статьи
|
Имя статьи
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<!--<img class="icon-paper" src="/img/conference/paper.png"/>-->
|
|
||||||
</a>
|
</a>
|
||||||
<a class="paper-name"
|
<a class="paper-name"
|
||||||
th:unless="*{papers[__${rowStat.index}__].id !=null}">
|
th:unless="*{papers[__${rowStat.index}__].id !=null}">
|
||||||
|
<span th:replace="papers/fragments/paperStatusFragment :: paperStatus(paperStatus=*{papers[__${rowStat.index}__].status})"/>
|
||||||
<span th:text="*{papers[__${rowStat.index}__].title}">
|
<span th:text="*{papers[__${rowStat.index}__].title}">
|
||||||
Имя статьи
|
Имя статьи
|
||||||
</span>
|
</span>
|
||||||
<img class="icon-paper" src="/img/conference/paper.png"/>
|
|
||||||
</a>
|
</a>
|
||||||
<input type="submit" class="icon icon-delete grey-border"
|
<input type="submit" class="icon icon-delete grey-border"
|
||||||
alt="Удалить" name="removePaper" th:value="${rowStat.index}"/>
|
alt="Удалить" name="removePaper" th:value="${rowStat.index}"/>
|
||||||
|
@ -7,17 +7,13 @@
|
|||||||
<div th:fragment="confLine (conference)" class="row text-left conference-row h3" style="background-color: white;">
|
<div th:fragment="confLine (conference)" class="row text-left conference-row h3" style="background-color: white;">
|
||||||
<div class="d-flex justify-content-between w-100">
|
<div class="d-flex justify-content-between w-100">
|
||||||
<a th:href="@{'conference?id='+${conference.id}}" class="w-100 text-decoration">
|
<a th:href="@{'conference?id='+${conference.id}}" class="w-100 text-decoration">
|
||||||
<span class="h5" th:text="${conference.title}"/>
|
<span class="h6 float-left m-2" th:text="${conference.title}"/>
|
||||||
<span class="text-muted h6 float-right m-2" th:text="${conference.datesString}"/>
|
<span class="text-muted h6 float-right m-2" th:text="${conference.datesString}"/>
|
||||||
</a>
|
</a>
|
||||||
<input class="id-class" type="hidden" th:value="${conference.id}"/>
|
<input class="id-class" type="hidden" th:value="${conference.id}"/>
|
||||||
<input type="submit" class="icon icon-delete grey-border"
|
<input type="submit" class="icon icon-delete grey-border"
|
||||||
alt="Удалить" th:value="${conference.id}"
|
alt="Удалить" th:value="${conference.id}"
|
||||||
data-confirm="Удалить конференцию?"/>
|
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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -0,0 +1,37 @@
|
|||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html xmlns:th="http://www.thymeleaf.org">
|
||||||
|
<head>
|
||||||
|
<meta charset="UTF-8"/>
|
||||||
|
</head>
|
||||||
|
<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 div-row-file" 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-10 div-file-name">
|
||||||
|
<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 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>
|
||||||
|
</span>
|
||||||
|
</th:block>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
@ -61,7 +61,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<button type="submit"
|
<button type="submit"
|
||||||
class="btn btn-danger float-right btn-delete-deadline "
|
class="btn btn-danger float-right btn-delete-deadline"
|
||||||
id="removeDeadline" name="removeDeadline"
|
id="removeDeadline" name="removeDeadline"
|
||||||
th:value="${rowStat.index}">
|
th:value="${rowStat.index}">
|
||||||
<span aria-hidden="true">
|
<span aria-hidden="true">
|
||||||
@ -77,12 +77,14 @@
|
|||||||
<input type="submit" id="addDeadline" name="addDeadline" class="btn btn-primary"
|
<input type="submit" id="addDeadline" name="addDeadline" class="btn btn-primary"
|
||||||
value="Добавить дедлайн"/>
|
value="Добавить дедлайн"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group div-loader">
|
||||||
<label for="loader">Загрузить заявку:</label>
|
<label for="loader">Загрузить файлы:</label>
|
||||||
<div id="loader">
|
<div id="loader">
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group" id="files-list">
|
||||||
|
<div th:replace="grants/fragments/grantFilesListFragment :: filesList(isLatexAttach = ${false})"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6 col-sm-12">
|
<div class="col-md-6 col-sm-12">
|
||||||
<label data-toggle="collapse"
|
<label data-toggle="collapse"
|
||||||
@ -90,7 +92,8 @@
|
|||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
aria-controls="collapse-filter">Фильтр рабочей группы
|
aria-controls="collapse-filter">Фильтр рабочей группы
|
||||||
</label>
|
</label>
|
||||||
<div th:class="${grantDto.wasLeader || grantDto.hasAge || grantDto.hasDegree} ?
|
<div th:class="${grantDto.wasLeader || grantDto.hasAge || grantDto.hasDegree
|
||||||
|
|| grantDto.hasBAKPapers || grantDto.hasScopusPapers} ?
|
||||||
'form-check' : 'form-check collapse'" id="collapse-filter">
|
'form-check' : 'form-check collapse'" id="collapse-filter">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@ -111,14 +114,16 @@
|
|||||||
<label class="form-check-label" for="f3">Cтепень к.т.н.</label>
|
<label class="form-check-label" for="f3">Cтепень к.т.н.</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<input class="form-check-input" type="checkbox" id="f4"/>
|
<input class="form-check-input" type="checkbox" id="f4"
|
||||||
|
th:field="*{hasScopusPapers}" th:onclick="|$('#filter').click();|"/>
|
||||||
<label class="form-check-label" for="f4">Более 3-х публикаций в
|
<label class="form-check-label" for="f4">Более 3-х публикаций в
|
||||||
scopus</label>
|
scopus</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<input class="form-check-input" type="checkbox" id="f5"/>
|
<input class="form-check-input" type="checkbox" id="f5"
|
||||||
|
th:field="*{hasBAKPapers}" th:onclick="|$('#filter').click();|"/>
|
||||||
<label class="form-check-label" for="f5">Наличие ВАК статей</label> <br/>
|
<label class="form-check-label" for="f5">Наличие ВАК статей</label> <br/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
@ -196,6 +201,30 @@
|
|||||||
Статус статьи
|
Статус статьи
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="col" th:unless="${#lists.isEmpty(paper.grants)}">
|
||||||
|
<label>Гранты: </label>
|
||||||
|
<div th:each="grant, grantRowStat : *{papers[__${rowStat.index}__].grants}"
|
||||||
|
th:remove="tag">
|
||||||
|
<div th:unless="${grant.id}==*{id}" th:remove="tag">
|
||||||
|
<li>
|
||||||
|
<a th:href="@{'/grants/grant?id=' + ${grant.id} + ''}">
|
||||||
|
<span th:text="${grant.title} "></span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col" th:unless="${#lists.isEmpty(paper.conferences)}">
|
||||||
|
<label>Конференции: </label>
|
||||||
|
<div th:each="conference, conferenceRowStat : *{papers[__${rowStat.index}__].conferences}"
|
||||||
|
th:remove="tag">
|
||||||
|
<li>
|
||||||
|
<a th:href="@{'/conferences/conference?id=' + ${conference.id} + ''}">
|
||||||
|
<span th:text="${conference.title}"></span>
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -233,20 +262,100 @@
|
|||||||
new FileLoader({
|
new FileLoader({
|
||||||
div: "loader",
|
div: "loader",
|
||||||
url: urlFileUpload,
|
url: urlFileUpload,
|
||||||
maxSize: 1.5,
|
maxSize: -1,
|
||||||
extensions: ["doc", "docx", "xls", "jpg", "pdf", "txt", "png"],
|
extensions: [],
|
||||||
callback: function (response) {
|
callback: function (response) {
|
||||||
showFeedbackMessage("Файл успешно загружен");
|
showFeedbackMessage("Файл успешно загружен");
|
||||||
console.debug(response);
|
console.debug(response);
|
||||||
|
addNewFile(response);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$('.selectpicker').selectpicker();
|
$('.selectpicker').selectpicker();
|
||||||
});
|
});
|
||||||
/*]]>*/
|
/*]]>*/
|
||||||
|
function addNewFile(fileDto) {
|
||||||
|
var fileNumber = $("#files-list div.row").length;
|
||||||
|
|
||||||
|
var newFileRow = $("<div/>")
|
||||||
|
.attr("id", 'files' + fileNumber)
|
||||||
|
.addClass("row div-row-file");
|
||||||
|
|
||||||
|
var idInput = $("<input/>")
|
||||||
|
.attr("type", "hidden")
|
||||||
|
.attr("id", "files" + fileNumber + ".id")
|
||||||
|
.attr("value", '')
|
||||||
|
.attr("name", "files[" + fileNumber + "].id");
|
||||||
|
newFileRow.append(idInput);
|
||||||
|
|
||||||
|
var flagInput = $("<input/>")
|
||||||
|
.attr("type", "hidden")
|
||||||
|
.attr("id", "files" + fileNumber + ".deleted")
|
||||||
|
.attr("value", "false")
|
||||||
|
.attr("name", "files[" + fileNumber + "].deleted");
|
||||||
|
newFileRow.append(flagInput);
|
||||||
|
|
||||||
|
var nameInput = $("<input/>")
|
||||||
|
.attr("type", "hidden")
|
||||||
|
.attr("id", "files" + fileNumber + ".name")
|
||||||
|
.attr("value", fileDto.fileName)
|
||||||
|
.attr("name", "files[" + fileNumber + "].name");
|
||||||
|
newFileRow.append(nameInput);
|
||||||
|
|
||||||
|
var tmpFileNameInput = $("<input/>")
|
||||||
|
.attr("type", "hidden")
|
||||||
|
.attr("id", "files" + fileNumber + ".tmpFileName")
|
||||||
|
.attr("value", fileDto.tmpFileName)
|
||||||
|
.attr("name", "files[" + fileNumber + "].tmpFileName");
|
||||||
|
newFileRow.append(tmpFileNameInput);
|
||||||
|
|
||||||
|
var nameDiv = $("<div/>")
|
||||||
|
.addClass("col-10 div-file-name")
|
||||||
|
.append($("<a/>").text(fileDto.fileName)
|
||||||
|
.attr("href", 'javascript:void(0)')
|
||||||
|
.attr("onclick", "downloadFile('" + fileDto.tmpFileName + "',null,'" + fileDto.fileName + "')"));
|
||||||
|
newFileRow.append(nameDiv);
|
||||||
|
|
||||||
|
var nextDiv = $("<div/>")
|
||||||
|
.addClass("col-2");
|
||||||
|
|
||||||
|
var nextA = $("<a/>")
|
||||||
|
.addClass("btn btn-danger float-right")
|
||||||
|
.attr("onclick", "$('#files" + fileNumber + "\\\\.deleted').val('true'); $('#files" + fileNumber + "').hide();")
|
||||||
|
.append(($("<span/>").attr("aria-hidden", "true")).append($("<i/>").addClass("fa fa-times")))
|
||||||
|
;
|
||||||
|
nextDiv.append(nextA)
|
||||||
|
newFileRow.append(nextDiv);
|
||||||
|
$("#files-list").append(newFileRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
function downloadFile(tmpName, fileId, downloadName) {
|
||||||
|
let xhr = new XMLHttpRequest();
|
||||||
|
if (fileId != null) xhr.open('GET', urlFileDownload + fileId);
|
||||||
|
if (tmpName != null) xhr.open('GET', urlFileDownloadTmp + tmpName);
|
||||||
|
xhr.responseType = 'blob';
|
||||||
|
|
||||||
|
var formData = new FormData();
|
||||||
|
if (fileId != null) formData.append("file-id", fileId);
|
||||||
|
if (tmpName != null) formData.append("tmp-file-name", tmpName);
|
||||||
|
|
||||||
|
xhr.send(formData);
|
||||||
|
|
||||||
|
xhr.onload = function () {
|
||||||
|
if (this.status == 200) {
|
||||||
|
console.debug(this.response);
|
||||||
|
var blob = new Blob([this.response], {type: '*'});
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.style = "display: none";
|
||||||
|
document.body.appendChild(a);
|
||||||
|
let url = window.URL.createObjectURL(blob);
|
||||||
|
a.href = url;
|
||||||
|
a.download = downloadName;
|
||||||
|
a.click();
|
||||||
|
window.URL.revokeObjectURL(url);
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
function updateAuthors() {
|
function updateAuthors() {
|
||||||
@ -256,23 +365,6 @@
|
|||||||
var lid = $("#leaderId option:selected").val();
|
var lid = $("#leaderId option:selected").val();
|
||||||
$("#authors [value='" + lid + "']").attr("disabled", "disabled");
|
$("#authors [value='" + lid + "']").attr("disabled", "disabled");
|
||||||
}
|
}
|
||||||
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
function viewdiv(id) {
|
|
||||||
var el = document.getElementById(id);
|
|
||||||
var link = document.getElementById('toggleLink');
|
|
||||||
if (el.style.display == "block") {
|
|
||||||
el.style.display = "none";
|
|
||||||
link.innerText = link.getAttribute('data-text-hide');
|
|
||||||
} else {
|
|
||||||
el.style.display = "block";
|
|
||||||
link.innerText = link.getAttribute('data-text-show');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
Loading…
Reference in New Issue
Block a user