merged with dev
This commit is contained in:
commit
a50aa383d9
@ -6,7 +6,6 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@ -14,7 +13,6 @@ import ru.ulstu.conference.model.ConferenceDto;
|
||||
import ru.ulstu.conference.model.ConferenceFilterDto;
|
||||
import ru.ulstu.conference.model.ConferenceUser;
|
||||
import ru.ulstu.conference.service.ConferenceService;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.user.model.User;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
@ -23,9 +21,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.util.StringUtils.isEmpty;
|
||||
import static ru.ulstu.core.controller.Navigation.CONFERENCES_PAGE;
|
||||
import static ru.ulstu.core.controller.Navigation.CONFERENCE_PAGE;
|
||||
import static ru.ulstu.core.controller.Navigation.REDIRECT_TO;
|
||||
@ -57,6 +53,8 @@ public class ConferenceController {
|
||||
@GetMapping("/dashboard")
|
||||
public void getDashboard(ModelMap modelMap) {
|
||||
modelMap.put("conferences", conferenceService.findAllActiveDto());
|
||||
|
||||
conferenceService.setChartData(modelMap); // example
|
||||
}
|
||||
|
||||
@GetMapping("/conference")
|
||||
@ -68,30 +66,27 @@ public class ConferenceController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping(value = "/conference", params = "save")
|
||||
public String save(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
||||
filterEmptyDeadlines(conferenceDto);
|
||||
if (errors.hasErrors()) {
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
conferenceService.save(conferenceDto);
|
||||
return String.format(REDIRECT_TO, CONFERENCES_PAGE);
|
||||
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{conference-id}")
|
||||
public String delete(@PathVariable("conference-id") Integer conferenceId) throws IOException {
|
||||
@PostMapping(value = "/conferences", params = "deleteConference")
|
||||
public String delete(@RequestParam("deleteConference") Integer conferenceId) throws IOException {
|
||||
conferenceService.delete(conferenceId);
|
||||
return String.format(REDIRECT_TO, CONFERENCES_PAGE);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/conference", params = "save")
|
||||
public String save(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
||||
if (!conferenceService.save(conferenceDto, errors)) {
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
return String.format(REDIRECT_TO, CONFERENCES_PAGE);
|
||||
}
|
||||
|
||||
@PostMapping(value = "/conference", params = "addDeadline")
|
||||
public String addDeadline(@Valid ConferenceDto conferenceDto, Errors errors) {
|
||||
filterEmptyDeadlines(conferenceDto);
|
||||
public String addDeadline(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
||||
conferenceService.filterEmptyDeadlines(conferenceDto);
|
||||
if (errors.hasErrors()) {
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
conferenceDto.getDeadlines().add(new Deadline());
|
||||
conferenceService.addDeadline(conferenceDto);
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
|
||||
@ -105,6 +100,16 @@ public class ConferenceController {
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/conference", params = "addPaper")
|
||||
public String addPaper(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
||||
if (errors.hasErrors()) {
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
conferenceService.addPaper(conferenceDto);
|
||||
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/conference", params = "removePaper")
|
||||
public String removePaper(@Valid ConferenceDto conferenceDto, Errors errors,
|
||||
@RequestParam(value = "removePaper") Integer paperIndex) throws IOException {
|
||||
@ -124,6 +129,15 @@ public class ConferenceController {
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/conference", params = "pingConference")
|
||||
public String ping(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
||||
if (errors.hasErrors()) {
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
conferenceService.ping(conferenceDto);
|
||||
return CONFERENCE_PAGE;
|
||||
}
|
||||
|
||||
@ModelAttribute("allParticipation")
|
||||
public List<ConferenceUser.Participation> getAllParticipation() {
|
||||
return conferenceService.getAllParticipations();
|
||||
@ -148,9 +162,4 @@ public class ConferenceController {
|
||||
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.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
@Entity
|
||||
@Table(name = "conference")
|
||||
@ -35,7 +37,7 @@ public class Conference extends BaseEntity {
|
||||
|
||||
private String url;
|
||||
|
||||
private int ping;
|
||||
private int ping = 0;
|
||||
|
||||
@Column(name = "begin_date")
|
||||
@Temporal(TemporalType.TIMESTAMP)
|
||||
@ -53,10 +55,11 @@ public class Conference extends BaseEntity {
|
||||
@OrderBy("date")
|
||||
private List<Deadline> deadlines = new ArrayList<>();
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@ManyToMany(cascade = CascadeType.MERGE, fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "paper_conference",
|
||||
joinColumns = {@JoinColumn(name = "conference_id")},
|
||||
inverseJoinColumns = {@JoinColumn(name = "paper_id")})
|
||||
@Fetch(FetchMode.SUBSELECT)
|
||||
private List<Paper> papers = new ArrayList<>();
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
@ -135,4 +138,13 @@ public class Conference extends BaseEntity {
|
||||
public void setUsers(List<ConferenceUser> 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();
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import ru.ulstu.core.model.BaseEntity;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.name.NameContainer;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
|
||||
import javax.persistence.Temporal;
|
||||
@ -17,7 +18,7 @@ import java.util.List;
|
||||
|
||||
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
||||
|
||||
public class ConferenceDto {
|
||||
public class ConferenceDto extends NameContainer {
|
||||
|
||||
private final static String BEGIN_DATE = "Начало: ";
|
||||
private final static String END_DATE = "Конец: ";
|
||||
|
@ -11,14 +11,14 @@ public class ConferenceFilterDto {
|
||||
public ConferenceFilterDto() {
|
||||
}
|
||||
|
||||
public ConferenceFilterDto(List<ConferenceDto> conferenceDtos, Integer filterUserId, Integer year) {
|
||||
this.conferences = conferenceDtos;
|
||||
public ConferenceFilterDto(List<ConferenceDto> conferences, Integer filterUserId, Integer year) {
|
||||
this.conferences = conferences;
|
||||
this.filterUserId = filterUserId;
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public ConferenceFilterDto(List<ConferenceDto> conferenceDtos) {
|
||||
this(conferenceDtos, null, null);
|
||||
public ConferenceFilterDto(List<ConferenceDto> conferences) {
|
||||
this(conferences, null, null);
|
||||
}
|
||||
|
||||
public List<ConferenceDto> getConferences() {
|
||||
|
@ -1,19 +1,32 @@
|
||||
package ru.ulstu.conference.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import ru.ulstu.conference.model.Conference;
|
||||
import ru.ulstu.name.BaseRepository;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
public interface ConferenceRepository extends JpaRepository<Conference, Integer> {
|
||||
public interface ConferenceRepository extends JpaRepository<Conference, Integer>, BaseRepository {
|
||||
@Query("SELECT c FROM Conference c LEFT JOIN c.users u WHERE (:user IS NULL OR u.user = :user) " +
|
||||
"AND (YEAR(c.beginDate) = :year OR :year IS NULL) ORDER BY begin_date DESC")
|
||||
List<Conference> findByUserAndYear(@Param("user") User user, @Param("year") Integer year);
|
||||
|
||||
@Query("SELECT c FROM Conference c WHERE c.beginDate > :date")
|
||||
List<Conference> findAllActive(@Param("date") Date date);
|
||||
|
||||
@Query("SELECT case when count(c) > 0 then true else false end FROM Conference c JOIN c.papers p WHERE p.id = :paperId")
|
||||
boolean isPaperAttached(@Param("paperId") Integer paperId);
|
||||
|
||||
@Modifying
|
||||
@Query("UPDATE Conference c SET c.ping = (c.ping + 1) WHERE c.id = :id")
|
||||
int updatePingConference(@Param("id") Integer id);
|
||||
|
||||
@Override
|
||||
@Query("SELECT title FROM Conference c WHERE (c.title = :name) AND (:id IS NULL OR c.id != :id) ")
|
||||
String findByNameAndNotId(@Param("name") String name, @Param("id") Integer id);
|
||||
}
|
||||
|
@ -1,7 +1,113 @@
|
||||
package ru.ulstu.conference.service;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
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
|
||||
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");
|
||||
}
|
||||
}
|
@ -4,14 +4,20 @@ import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.Errors;
|
||||
import ru.ulstu.conference.model.Conference;
|
||||
import ru.ulstu.conference.model.ConferenceDto;
|
||||
import ru.ulstu.conference.model.ConferenceFilterDto;
|
||||
import ru.ulstu.conference.model.ConferenceUser;
|
||||
import ru.ulstu.conference.repository.ConferenceRepository;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.deadline.service.DeadlineService;
|
||||
import ru.ulstu.name.BaseService;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.paper.service.PaperService;
|
||||
import ru.ulstu.ping.service.PingService;
|
||||
import ru.ulstu.timeline.service.EventService;
|
||||
import ru.ulstu.user.model.User;
|
||||
import ru.ulstu.user.service.UserService;
|
||||
|
||||
@ -20,12 +26,13 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
||||
|
||||
@Service
|
||||
public class ConferenceService {
|
||||
public class ConferenceService extends BaseService {
|
||||
private final static int MAX_DISPLAY_SIZE = 40;
|
||||
|
||||
private final ConferenceRepository conferenceRepository;
|
||||
@ -33,17 +40,27 @@ public class ConferenceService {
|
||||
private final DeadlineService deadlineService;
|
||||
private final PaperService paperService;
|
||||
private final UserService userService;
|
||||
private final PingService pingService;
|
||||
private final ConferenceNotificationService conferenceNotificationService;
|
||||
private final EventService eventService;
|
||||
|
||||
public ConferenceService(ConferenceRepository conferenceRepository,
|
||||
ConferenceUserService conferenceUserService,
|
||||
DeadlineService deadlineService,
|
||||
PaperService paperService,
|
||||
UserService userService) {
|
||||
UserService userService,
|
||||
PingService pingService,
|
||||
ConferenceNotificationService conferenceNotificationService,
|
||||
EventService eventService) {
|
||||
this.baseRepository = conferenceRepository;
|
||||
this.conferenceRepository = conferenceRepository;
|
||||
this.conferenceUserService = conferenceUserService;
|
||||
this.deadlineService = deadlineService;
|
||||
this.paperService = paperService;
|
||||
this.userService = userService;
|
||||
this.pingService = pingService;
|
||||
this.conferenceNotificationService = conferenceNotificationService;
|
||||
this.eventService = eventService;
|
||||
}
|
||||
|
||||
public ConferenceDto getExistConferenceById(Integer id) {
|
||||
@ -71,39 +88,71 @@ public class ConferenceService {
|
||||
}
|
||||
|
||||
public ConferenceDto findOneDto(Integer id) {
|
||||
return new ConferenceDto(conferenceRepository.getOne(id));
|
||||
return new ConferenceDto(conferenceRepository.findOne(id));
|
||||
}
|
||||
|
||||
public boolean save(ConferenceDto conferenceDto, Errors errors) throws IOException {
|
||||
conferenceDto.setName(conferenceDto.getTitle());
|
||||
filterEmptyDeadlines(conferenceDto);
|
||||
checkEmptyFieldsOfDeadline(conferenceDto, errors);
|
||||
checkUniqueName(conferenceDto,
|
||||
errors,
|
||||
conferenceDto.getId(),
|
||||
"title",
|
||||
"Конференция с таким именем уже существует");
|
||||
if (errors.hasErrors()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
public void save(ConferenceDto conferenceDto) throws IOException {
|
||||
if (isEmpty(conferenceDto.getId())) {
|
||||
create(conferenceDto);
|
||||
} else {
|
||||
update(conferenceDto);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Integer create(ConferenceDto conferenceDto) throws IOException {
|
||||
Conference newConference = copyFromDto(new Conference(), conferenceDto);
|
||||
newConference = conferenceRepository.save(newConference);
|
||||
conferenceNotificationService.sendCreateNotification(newConference);
|
||||
eventService.createFromConference(newConference);
|
||||
return newConference.getId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Integer update(ConferenceDto conferenceDto) throws IOException {
|
||||
Conference conference = conferenceRepository.getOne(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));
|
||||
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);
|
||||
return conference.getId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Integer conferenceId) {
|
||||
if (conferenceRepository.existsById(conferenceId)) {
|
||||
conferenceRepository.deleteById(conferenceId);
|
||||
if (conferenceRepository.exists(conferenceId)) {
|
||||
eventService.removeConferencesEvent(conferenceRepository.findOne(conferenceId));
|
||||
conferenceRepository.delete(conferenceId);
|
||||
}
|
||||
}
|
||||
|
||||
public void addDeadline(ConferenceDto conferenceDto) {
|
||||
conferenceDto.getDeadlines().add(new Deadline());
|
||||
}
|
||||
|
||||
|
||||
public void removeDeadline(ConferenceDto conferenceDto, Integer deadlineIndex) throws IOException {
|
||||
if (conferenceDto.getDeadlines().get(deadlineIndex).getId() != null) {
|
||||
conferenceDto.getRemovedDeadlineIds().add(conferenceDto.getDeadlines().get(deadlineIndex).getId());
|
||||
@ -111,10 +160,20 @@ public class ConferenceService {
|
||||
conferenceDto.getDeadlines().remove((int) deadlineIndex);
|
||||
}
|
||||
|
||||
public void addPaper(ConferenceDto conferenceDto) {
|
||||
Paper paper = new Paper();
|
||||
paper.setTitle(userService.getCurrentUser().getLastName() + "_" + conferenceDto.getTitle() + "_" + (new Date()).getTime());
|
||||
paper.setStatus(Paper.PaperStatus.DRAFT);
|
||||
|
||||
conferenceDto.getPapers().add(paper);
|
||||
}
|
||||
|
||||
public void removePaper(ConferenceDto conferenceDto, Integer paperIndex) throws IOException {
|
||||
Paper removedPaper = conferenceDto.getPapers().remove((int) paperIndex);
|
||||
if (removedPaper.getId() != null) {
|
||||
conferenceDto.getNotSelectedPapers().add(removedPaper);
|
||||
}
|
||||
}
|
||||
|
||||
public void takePart(ConferenceDto conferenceDto) throws IOException {
|
||||
conferenceDto.getUsers().add(new ConferenceUser(userService.getCurrentUser()));
|
||||
@ -141,15 +200,15 @@ public class ConferenceService {
|
||||
conference.setTitle(conferenceDto.getTitle());
|
||||
conference.setDescription(conferenceDto.getDescription());
|
||||
conference.setUrl(conferenceDto.getUrl());
|
||||
conference.setPing(0);
|
||||
conference.setBeginDate(conferenceDto.getBeginDate());
|
||||
conference.setEndDate(conferenceDto.getEndDate());
|
||||
conference.setPapers(conferenceDto.getPapers());
|
||||
conference.getPapers().clear();
|
||||
conferenceDto.getPapers().forEach(paper -> conference.getPapers().add(paper.getId() != null ? paperService.findPaperById(paper.getId()) : paperService.create(paper)));
|
||||
conference.setDeadlines(deadlineService.saveOrCreate(conferenceDto.getDeadlines()));
|
||||
conference.setUsers(conferenceUserService.saveOrCreate(conferenceDto.getUsers()));
|
||||
if (conferenceDto.getPaperIds() != null && !conferenceDto.getPaperIds().isEmpty()) {
|
||||
conferenceDto.getPaperIds().forEach(paperId ->
|
||||
conference.getPapers().add(paperService.findEntityById(paperId)));
|
||||
conference.getPapers().add(paperService.findPaperById(paperId)));
|
||||
}
|
||||
return conference;
|
||||
}
|
||||
@ -173,4 +232,74 @@ public class ConferenceService {
|
||||
public List<Conference> findAllActive() {
|
||||
return conferenceRepository.findAllActive(new Date());
|
||||
}
|
||||
|
||||
public boolean isAttachedToConference(Integer paperId) {
|
||||
return conferenceRepository.isPaperAttached(paperId);
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void ping(ConferenceDto conferenceDto) throws IOException {
|
||||
pingService.addPing(findOne(conferenceDto.getId()));
|
||||
conferenceRepository.updatePingConference(conferenceDto.getId());
|
||||
}
|
||||
|
||||
public Conference findOne(Integer conferenceId) {
|
||||
return conferenceRepository.findOne(conferenceId);
|
||||
}
|
||||
|
||||
public void setChartData(ModelMap modelMap) {
|
||||
//first, add the regional sales
|
||||
Integer northeastSales = 17089;
|
||||
Integer westSales = 10603;
|
||||
Integer midwestSales = 5223;
|
||||
Integer southSales = 10111;
|
||||
|
||||
modelMap.addAttribute("northeastSales", northeastSales);
|
||||
modelMap.addAttribute("southSales", southSales);
|
||||
modelMap.addAttribute("midwestSales", midwestSales);
|
||||
modelMap.addAttribute("westSales", westSales);
|
||||
|
||||
//now add sales by lure type
|
||||
List<Integer> inshoreSales = Arrays.asList(4074, 3455, 4112);
|
||||
List<Integer> nearshoreSales = Arrays.asList(3222, 3011, 3788);
|
||||
List<Integer> offshoreSales = Arrays.asList(7811, 7098, 6455);
|
||||
|
||||
modelMap.addAttribute("inshoreSales", inshoreSales);
|
||||
modelMap.addAttribute("nearshoreSales", nearshoreSales);
|
||||
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()));
|
||||
}
|
||||
}
|
||||
|
@ -39,6 +39,11 @@ public class AdviceController {
|
||||
return userService.getCurrentUser().getUserAbbreviate();
|
||||
}
|
||||
|
||||
@ModelAttribute("flashMessage")
|
||||
public String getFlashMessage() {
|
||||
return null;
|
||||
}
|
||||
|
||||
private Response<Void> handleException(ErrorConstants error) {
|
||||
log.warn(error.toString());
|
||||
return new Response<>(error);
|
||||
|
@ -9,6 +9,7 @@ import javax.persistence.Entity;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import java.util.Date;
|
||||
import java.util.Objects;
|
||||
|
||||
@Entity
|
||||
public class Deadline extends BaseEntity {
|
||||
@ -51,4 +52,26 @@ public class Deadline extends BaseEntity {
|
||||
public void setDate(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);
|
||||
}
|
||||
}
|
||||
|
@ -13,6 +13,7 @@ import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.grant.model.Grant;
|
||||
import ru.ulstu.grant.model.GrantDto;
|
||||
import ru.ulstu.grant.service.GrantService;
|
||||
import ru.ulstu.paper.model.PaperDto;
|
||||
import ru.ulstu.user.model.User;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
@ -50,7 +51,9 @@ public class GrantController {
|
||||
@GetMapping("/grant")
|
||||
public void getGrant(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
|
||||
if (id != null && id > 0) {
|
||||
modelMap.put("grantDto", grantService.findOneDto(id));
|
||||
GrantDto grantDto = grantService.findOneDto(id);
|
||||
attachPaper(grantDto);
|
||||
modelMap.put("grantDto", grantDto);
|
||||
} else {
|
||||
modelMap.put("grantDto", new GrantDto());
|
||||
}
|
||||
@ -78,6 +81,12 @@ public class GrantController {
|
||||
return GRANT_PAGE;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/grant", params = "attachPaper")
|
||||
public String attachPaper(GrantDto grantDto) {
|
||||
grantService.attachPaper(grantDto);
|
||||
return GRANT_PAGE;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/grant", params = "addDeadline")
|
||||
public String addDeadline(@Valid GrantDto grantDto, Errors errors) {
|
||||
filterEmptyDeadlines(grantDto);
|
||||
@ -88,6 +97,13 @@ public class GrantController {
|
||||
return GRANT_PAGE;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/grant", params = "removeDeadline")
|
||||
public String removeDeadline(GrantDto grantDto,
|
||||
@RequestParam(value = "removeDeadline") Integer deadlineId) {
|
||||
grantService.removeDeadline(grantDto, deadlineId);
|
||||
return GRANT_PAGE;
|
||||
}
|
||||
|
||||
@PostMapping(value = "/grant", params = "createProject")
|
||||
public String createProject(@Valid GrantDto grantDto, Errors errors) throws IOException {
|
||||
if (errors.hasErrors()) {
|
||||
@ -113,6 +129,11 @@ public class GrantController {
|
||||
return grantService.getGrantAuthors(grantDto);
|
||||
}
|
||||
|
||||
@ModelAttribute("allPapers")
|
||||
public List<PaperDto> getAllPapers() {
|
||||
return grantService.getAllUncompletedPapers();
|
||||
}
|
||||
|
||||
private void filterEmptyDeadlines(GrantDto grantDto) {
|
||||
grantDto.setDeadlines(grantDto.getDeadlines().stream()
|
||||
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
||||
|
@ -1,10 +1,15 @@
|
||||
package ru.ulstu.grant.model;
|
||||
|
||||
import org.hibernate.annotations.Fetch;
|
||||
import org.hibernate.annotations.FetchMode;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
import ru.ulstu.core.model.BaseEntity;
|
||||
import ru.ulstu.core.model.UserContainer;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.file.model.FileData;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.project.model.Project;
|
||||
import ru.ulstu.timeline.model.Event;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
@ -13,12 +18,12 @@ import javax.persistence.EnumType;
|
||||
import javax.persistence.Enumerated;
|
||||
import javax.persistence.FetchType;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.JoinTable;
|
||||
import javax.persistence.ManyToMany;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
import javax.persistence.Table;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
@ -62,14 +67,12 @@ public class Grant extends BaseEntity implements UserContainer {
|
||||
@OrderBy("date")
|
||||
private List<Deadline> deadlines = new ArrayList<>();
|
||||
|
||||
//Описание гранта
|
||||
@NotNull
|
||||
private String comment;
|
||||
|
||||
//Заявка на грант
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "file_id")
|
||||
private FileData application;
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "grant_id", unique = true)
|
||||
@Fetch(FetchMode.SUBSELECT)
|
||||
private List<FileData> files = new ArrayList<>();
|
||||
|
||||
@ManyToOne(cascade = CascadeType.ALL)
|
||||
@JoinColumn(name = "project_id")
|
||||
@ -83,6 +86,17 @@ public class Grant extends BaseEntity implements UserContainer {
|
||||
@JoinColumn(name = "leader_id")
|
||||
private User leader;
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@JoinTable(name = "grants_papers",
|
||||
joinColumns = {@JoinColumn(name = "grant_id")},
|
||||
inverseJoinColumns = {@JoinColumn(name = "paper_id")})
|
||||
@Fetch(FetchMode.SUBSELECT)
|
||||
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() {
|
||||
return status;
|
||||
}
|
||||
@ -107,12 +121,12 @@ public class Grant extends BaseEntity implements UserContainer {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public FileData getApplication() {
|
||||
return application;
|
||||
public List<FileData> getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
public void setApplication(FileData application) {
|
||||
this.application = application;
|
||||
public void setFiles(List<FileData> files) {
|
||||
this.files = files;
|
||||
}
|
||||
|
||||
public String getTitle() {
|
||||
@ -152,6 +166,22 @@ public class Grant extends BaseEntity implements UserContainer {
|
||||
this.leader = leader;
|
||||
}
|
||||
|
||||
public List<Paper> getPapers() {
|
||||
return papers;
|
||||
}
|
||||
|
||||
public void setPapers(List<Paper> papers) {
|
||||
this.papers = papers;
|
||||
}
|
||||
|
||||
public List<Event> getEvents() {
|
||||
return events;
|
||||
}
|
||||
|
||||
public void setEvents(List<Event> events) {
|
||||
this.events = events;
|
||||
}
|
||||
|
||||
public Optional<Deadline> getNextDeadline() {
|
||||
return deadlines
|
||||
.stream()
|
||||
|
@ -4,6 +4,8 @@ import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.file.model.FileDataDto;
|
||||
import ru.ulstu.paper.model.PaperDto;
|
||||
import ru.ulstu.project.model.ProjectDto;
|
||||
import ru.ulstu.user.model.UserDto;
|
||||
|
||||
@ -24,7 +26,7 @@ public class GrantDto {
|
||||
private Grant.GrantStatus status;
|
||||
private List<Deadline> deadlines = new ArrayList<>();
|
||||
private String comment;
|
||||
private String applicationFileName;
|
||||
private List<FileDataDto> files = new ArrayList<>();
|
||||
private ProjectDto project;
|
||||
private Set<Integer> authorIds;
|
||||
private Set<UserDto> authors;
|
||||
@ -32,6 +34,11 @@ public class GrantDto {
|
||||
private boolean wasLeader;
|
||||
private boolean hasAge;
|
||||
private boolean hasDegree;
|
||||
private boolean hasBAKPapers;
|
||||
private boolean hasScopusPapers;
|
||||
private List<Integer> paperIds = new ArrayList<>();
|
||||
private List<PaperDto> papers = new ArrayList<>();
|
||||
private List<Integer> removedDeadlineIds = new ArrayList<>();
|
||||
|
||||
public GrantDto() {
|
||||
deadlines.add(new Deadline());
|
||||
@ -43,25 +50,31 @@ public class GrantDto {
|
||||
@JsonProperty("status") Grant.GrantStatus status,
|
||||
@JsonProperty("deadlines") List<Deadline> deadlines,
|
||||
@JsonProperty("comment") String comment,
|
||||
@JsonProperty("files") List<FileDataDto> files,
|
||||
@JsonProperty("project") ProjectDto project,
|
||||
@JsonProperty("authorIds") Set<Integer> authorIds,
|
||||
@JsonProperty("authors") Set<UserDto> authors,
|
||||
@JsonProperty("leader") Integer leaderId,
|
||||
@JsonProperty("leaderId") Integer leaderId,
|
||||
@JsonProperty("wasLeader") boolean wasLeader,
|
||||
@JsonProperty("hasAge") boolean hasAge,
|
||||
@JsonProperty("hasDegree") boolean hasDegree) {
|
||||
@JsonProperty("hasDegree") boolean hasDegree,
|
||||
@JsonProperty("paperIds") List<Integer> paperIds,
|
||||
@JsonProperty("papers") List<PaperDto> papers) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.status = status;
|
||||
this.deadlines = deadlines;
|
||||
this.comment = comment;
|
||||
this.applicationFileName = null;
|
||||
this.files = files;
|
||||
this.project = project;
|
||||
this.authorIds = authorIds;
|
||||
this.authors = authors;
|
||||
this.leaderId = leaderId;
|
||||
this.wasLeader = wasLeader;
|
||||
this.hasAge = hasAge;
|
||||
this.hasDegree = hasDegree;
|
||||
this.paperIds = paperIds;
|
||||
this.papers = papers;
|
||||
}
|
||||
|
||||
public GrantDto(Grant grant) {
|
||||
@ -70,14 +83,16 @@ public class GrantDto {
|
||||
this.status = grant.getStatus();
|
||||
this.deadlines = grant.getDeadlines();
|
||||
this.comment = grant.getComment();
|
||||
this.files = convert(grant.getFiles(), FileDataDto::new);
|
||||
this.project = grant.getProject() == null ? null : new ProjectDto(grant.getProject());
|
||||
this.applicationFileName = grant.getApplication() == null ? null : grant.getApplication().getName();
|
||||
this.authorIds = convert(grant.getAuthors(), user -> user.getId());
|
||||
this.authors = convert(grant.getAuthors(), UserDto::new);
|
||||
this.leaderId = grant.getLeader().getId();
|
||||
this.wasLeader = false;
|
||||
this.hasAge = false;
|
||||
this.hasDegree = false;
|
||||
this.paperIds = convert(grant.getPapers(), paper -> paper.getId());
|
||||
this.papers = convert(grant.getPapers(), PaperDto::new);
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
@ -120,6 +135,14 @@ public class GrantDto {
|
||||
this.comment = comment;
|
||||
}
|
||||
|
||||
public List<FileDataDto> getFiles() {
|
||||
return files;
|
||||
}
|
||||
|
||||
public void setFiles(List<FileDataDto> files) {
|
||||
this.files = files;
|
||||
}
|
||||
|
||||
public ProjectDto getProject() {
|
||||
return project;
|
||||
}
|
||||
@ -128,14 +151,6 @@ public class GrantDto {
|
||||
this.project = project;
|
||||
}
|
||||
|
||||
public String getApplicationFileName() {
|
||||
return applicationFileName;
|
||||
}
|
||||
|
||||
public void setApplicationFileName(String applicationFileName) {
|
||||
this.applicationFileName = applicationFileName;
|
||||
}
|
||||
|
||||
public Set<Integer> getAuthorIds() {
|
||||
return authorIds;
|
||||
}
|
||||
@ -190,4 +205,44 @@ public class GrantDto {
|
||||
public void setHasDegree(boolean hasDegree) {
|
||||
this.hasDegree = hasDegree;
|
||||
}
|
||||
|
||||
public List<Integer> getPaperIds() {
|
||||
return paperIds;
|
||||
}
|
||||
|
||||
public void setPaperIds(List<Integer> paperIds) {
|
||||
this.paperIds = paperIds;
|
||||
}
|
||||
|
||||
public List<PaperDto> getPapers() {
|
||||
return papers;
|
||||
}
|
||||
|
||||
public void setPapers(List<PaperDto> papers) {
|
||||
this.papers = papers;
|
||||
}
|
||||
|
||||
public List<Integer> getRemovedDeadlineIds() {
|
||||
return removedDeadlineIds;
|
||||
}
|
||||
|
||||
public void setRemovedDeadlineIds(List<Integer> 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,72 @@
|
||||
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,46 +5,63 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.deadline.service.DeadlineService;
|
||||
import ru.ulstu.file.model.FileDataDto;
|
||||
import ru.ulstu.file.service.FileService;
|
||||
import ru.ulstu.grant.model.Grant;
|
||||
import ru.ulstu.grant.model.GrantDto;
|
||||
import ru.ulstu.grant.repository.GrantRepository;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.paper.model.PaperDto;
|
||||
import ru.ulstu.paper.service.PaperService;
|
||||
import ru.ulstu.project.model.Project;
|
||||
import ru.ulstu.project.model.ProjectDto;
|
||||
import ru.ulstu.project.service.ProjectService;
|
||||
import ru.ulstu.timeline.service.EventService;
|
||||
import ru.ulstu.user.model.User;
|
||||
import ru.ulstu.user.service.UserService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
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 ru.ulstu.core.util.StreamApiUtils.convert;
|
||||
import static ru.ulstu.grant.model.Grant.GrantStatus.APPLICATION;
|
||||
|
||||
@Service
|
||||
public class GrantService {
|
||||
private final static int MAX_DISPLAY_SIZE = 40;
|
||||
private final static int MAX_DISPLAY_SIZE = 50;
|
||||
|
||||
private final GrantRepository grantRepository;
|
||||
private final ProjectService projectService;
|
||||
private final DeadlineService deadlineService;
|
||||
private final FileService fileService;
|
||||
private final UserService userService;
|
||||
private final PaperService paperService;
|
||||
private final EventService eventService;
|
||||
private final GrantNotificationService grantNotificationService;
|
||||
|
||||
public GrantService(GrantRepository grantRepository,
|
||||
FileService fileService,
|
||||
DeadlineService deadlineService,
|
||||
ProjectService projectService,
|
||||
UserService userService) {
|
||||
UserService userService,
|
||||
PaperService paperService,
|
||||
EventService eventService,
|
||||
GrantNotificationService grantNotificationService) {
|
||||
this.grantRepository = grantRepository;
|
||||
this.fileService = fileService;
|
||||
this.deadlineService = deadlineService;
|
||||
this.projectService = projectService;
|
||||
this.userService = userService;
|
||||
this.paperService = paperService;
|
||||
this.eventService = eventService;
|
||||
this.grantNotificationService = grantNotificationService;
|
||||
}
|
||||
|
||||
public List<Grant> findAll() {
|
||||
@ -58,13 +75,15 @@ public class GrantService {
|
||||
}
|
||||
|
||||
public GrantDto findOneDto(Integer id) {
|
||||
return new GrantDto(grantRepository.getOne(id));
|
||||
return new GrantDto(grantRepository.findOne(id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Integer create(GrantDto grantDto) throws IOException {
|
||||
Grant newGrant = copyFromDto(new Grant(), grantDto);
|
||||
newGrant = grantRepository.save(newGrant);
|
||||
eventService.createFromGrant(newGrant);
|
||||
grantNotificationService.sendCreateNotification(newGrant);
|
||||
return newGrant.getId();
|
||||
}
|
||||
|
||||
@ -76,9 +95,9 @@ public class GrantService {
|
||||
grant.setProject(projectService.findById(grantDto.getProject().getId()));
|
||||
}
|
||||
grant.setDeadlines(deadlineService.saveOrCreate(grantDto.getDeadlines()));
|
||||
if (grantDto.getApplicationFileName() != null) {
|
||||
grant.setApplication(fileService.createFileFromTmp(grantDto.getApplicationFileName()));
|
||||
}
|
||||
grant.setFiles(fileService.saveOrCreate(grantDto.getFiles().stream()
|
||||
.filter(f -> !f.isDeleted())
|
||||
.collect(toList())));
|
||||
grant.getAuthors().clear();
|
||||
if (grantDto.getAuthorIds() != null && !grantDto.getAuthorIds().isEmpty()) {
|
||||
grantDto.getAuthorIds().forEach(authorIds -> grant.getAuthors().add(userService.findById(authorIds)));
|
||||
@ -86,6 +105,10 @@ public class GrantService {
|
||||
if (grantDto.getLeaderId() != null) {
|
||||
grant.setLeader(userService.findById(grantDto.getLeaderId()));
|
||||
}
|
||||
grant.getPapers().clear();
|
||||
if (grantDto.getPaperIds() != null && !grantDto.getPaperIds().isEmpty()) {
|
||||
grantDto.getPaperIds().forEach(paperIds -> grant.getPapers().add(paperService.findPaperById(paperIds)));
|
||||
}
|
||||
return grant;
|
||||
}
|
||||
|
||||
@ -96,21 +119,37 @@ public class GrantService {
|
||||
|
||||
@Transactional
|
||||
public Integer update(GrantDto grantDto) throws IOException {
|
||||
Grant grant = grantRepository.getOne(grantDto.getId());
|
||||
Grant.GrantStatus oldStatus = grant.getStatus();
|
||||
if (grantDto.getApplicationFileName() != null && grant.getApplication() != null) {
|
||||
fileService.deleteFile(grant.getApplication());
|
||||
Grant grant = grantRepository.findOne(grantDto.getId());
|
||||
Set<User> oldAuthors = new HashSet<>(grant.getAuthors());
|
||||
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);
|
||||
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();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Integer grantId) throws IOException {
|
||||
Grant grant = grantRepository.getOne(grantId);
|
||||
if (grant.getApplication() != null) {
|
||||
fileService.deleteFile(grant.getApplication());
|
||||
}
|
||||
Grant grant = grantRepository.findOne(grantId);
|
||||
grantRepository.delete(grant);
|
||||
}
|
||||
|
||||
@ -119,7 +158,7 @@ public class GrantService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Grant create(String title, Project projectId, Date deadlineDate, User user) {
|
||||
public Grant create(String title, Project projectId, Date deadlineDate, User user, Paper paper) {
|
||||
Grant grant = new Grant();
|
||||
grant.setTitle(title);
|
||||
grant.setComment("Комментарий к гранту 1");
|
||||
@ -128,7 +167,12 @@ public class GrantService {
|
||||
grant.getDeadlines().add(new Deadline(deadlineDate, "первый дедлайн"));
|
||||
grant.getAuthors().add(user);
|
||||
grant.setLeader(user);
|
||||
grant.getPapers().add(paper);
|
||||
grant = grantRepository.save(grant);
|
||||
|
||||
eventService.createFromGrant(grant);
|
||||
grantNotificationService.sendCreateNotification(grant);
|
||||
|
||||
return grant;
|
||||
}
|
||||
|
||||
@ -143,18 +187,78 @@ public class GrantService {
|
||||
public List<User> getGrantAuthors(GrantDto grantDto) {
|
||||
List<User> filteredUsers = userService.filterByAgeAndDegree(grantDto.isHasAge(), grantDto.isHasDegree());
|
||||
if (grantDto.isWasLeader()) {
|
||||
filteredUsers = filteredUsers
|
||||
.stream()
|
||||
.filter(getCompletedGrantLeaders()::contains)
|
||||
.collect(Collectors.toList());
|
||||
filteredUsers = checkContains(filteredUsers, getCompletedGrantLeaders());
|
||||
}
|
||||
if (grantDto.isHasBAKPapers()) {
|
||||
filteredUsers = checkContains(filteredUsers, getBAKAuthors());
|
||||
}
|
||||
if (grantDto.isHasScopusPapers()) {
|
||||
filteredUsers = checkContains(filteredUsers, getScopusAuthors());
|
||||
}
|
||||
return filteredUsers;
|
||||
}
|
||||
|
||||
private List<User> checkContains(List<User> filteredUsers, List<User> checkUsers) {
|
||||
return filteredUsers.stream()
|
||||
.filter(checkUsers::contains)
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
private List<User> getCompletedGrantLeaders() {
|
||||
return grantRepository.findByStatus(Grant.GrantStatus.COMPLETED)
|
||||
.stream()
|
||||
.map(Grant::getLeader)
|
||||
.collect(Collectors.toList());
|
||||
.collect(toList());
|
||||
}
|
||||
|
||||
public List<PaperDto> getGrantPapers(List<Integer> paperIds) {
|
||||
return paperService.findAllSelect(paperIds);
|
||||
}
|
||||
|
||||
public List<PaperDto> getAllUncompletedPapers() {
|
||||
List<PaperDto> papers = paperService.findAllNotCompleted();
|
||||
papers.stream()
|
||||
.forEach(paper ->
|
||||
paper.setTitle(StringUtils.abbreviate(paper.getTitle(), MAX_DISPLAY_SIZE)));
|
||||
return papers;
|
||||
}
|
||||
|
||||
public void attachPaper(GrantDto grantDto) {
|
||||
if (!grantDto.getPaperIds().isEmpty()) {
|
||||
grantDto.getPapers().clear();
|
||||
grantDto.setPapers(getGrantPapers(grantDto.getPaperIds()));
|
||||
} else {
|
||||
grantDto.getPapers().clear();
|
||||
}
|
||||
}
|
||||
|
||||
public void removeDeadline(GrantDto grantDto, Integer deadlineId) {
|
||||
if (grantDto.getDeadlines().get(deadlineId).getId() != null) {
|
||||
grantDto.getRemovedDeadlineIds().add(grantDto.getDeadlines().get(deadlineId).getId());
|
||||
}
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
7
src/main/java/ru/ulstu/name/BaseRepository.java
Normal file
7
src/main/java/ru/ulstu/name/BaseRepository.java
Normal file
@ -0,0 +1,7 @@
|
||||
package ru.ulstu.name;
|
||||
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface BaseRepository {
|
||||
String findByNameAndNotId(@Param("name") String name, @Param("id") Integer id);
|
||||
}
|
16
src/main/java/ru/ulstu/name/BaseService.java
Normal file
16
src/main/java/ru/ulstu/name/BaseService.java
Normal file
@ -0,0 +1,16 @@
|
||||
package ru.ulstu.name;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.Errors;
|
||||
|
||||
@Service
|
||||
public abstract class BaseService {
|
||||
|
||||
public BaseRepository baseRepository;
|
||||
|
||||
public void checkUniqueName(NameContainer nameContainer, Errors errors, Integer id, String checkField, String errorMessage) {
|
||||
if (nameContainer.getName().equals(baseRepository.findByNameAndNotId(nameContainer.getName(), id))) {
|
||||
errors.rejectValue(checkField, "errorCode", errorMessage);
|
||||
}
|
||||
}
|
||||
}
|
14
src/main/java/ru/ulstu/name/NameContainer.java
Normal file
14
src/main/java/ru/ulstu/name/NameContainer.java
Normal file
@ -0,0 +1,14 @@
|
||||
package ru.ulstu.name;
|
||||
|
||||
public abstract class NameContainer {
|
||||
|
||||
private String name = "";
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
}
|
@ -8,14 +8,14 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import ru.ulstu.conference.service.ConferenceService;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.paper.model.PaperDto;
|
||||
import ru.ulstu.paper.model.PaperFilterDto;
|
||||
import ru.ulstu.paper.model.PaperListDto;
|
||||
import ru.ulstu.paper.service.LatexService;
|
||||
import ru.ulstu.paper.service.PaperService;
|
||||
import ru.ulstu.user.model.User;
|
||||
@ -38,23 +38,34 @@ import static org.springframework.util.StringUtils.isEmpty;
|
||||
@ApiIgnore
|
||||
public class PaperController {
|
||||
private final PaperService paperService;
|
||||
private final ConferenceService conferenceService;
|
||||
private final LatexService latexService;
|
||||
|
||||
public PaperController(PaperService paperService, LatexService latexService) {
|
||||
public PaperController(PaperService paperService,
|
||||
ConferenceService conferenceService,
|
||||
LatexService latexService) {
|
||||
this.paperService = paperService;
|
||||
this.conferenceService = conferenceService;
|
||||
this.latexService = latexService;
|
||||
}
|
||||
|
||||
@GetMapping("/papers")
|
||||
public void getPapers(ModelMap modelMap) {
|
||||
modelMap.put("filteredPapers", new PaperFilterDto(paperService.findAllDto(), null, null));
|
||||
modelMap.put("filteredPapers", new PaperListDto(paperService.findAllDto(), null, null));
|
||||
}
|
||||
|
||||
@PostMapping("/papers")
|
||||
public void filterPapers(@Valid PaperFilterDto paperFilterDto, ModelMap modelMap) {
|
||||
modelMap.put("filteredPapers", new PaperFilterDto(paperService.filter(paperFilterDto),
|
||||
paperFilterDto.getFilterAuthorId(),
|
||||
paperFilterDto.getYear()));
|
||||
public void listPapers(@Valid PaperListDto paperListDto, ModelMap modelMap) {
|
||||
if (paperListDto.getPaperDeleteId() != null) {
|
||||
if (conferenceService.isAttachedToConference(paperListDto.getPaperDeleteId())) {
|
||||
modelMap.put("flashMessage", "Статью нельзя удалить, она прикреплена к конференции");
|
||||
} else {
|
||||
paperService.delete(paperListDto.getPaperDeleteId());
|
||||
}
|
||||
}
|
||||
modelMap.put("filteredPapers", new PaperListDto(paperService.filter(paperListDto),
|
||||
paperListDto.getFilterAuthorId(),
|
||||
paperListDto.getYear()));
|
||||
}
|
||||
|
||||
@GetMapping("/dashboard")
|
||||
@ -94,12 +105,6 @@ public class PaperController {
|
||||
return "/papers/paper";
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{paper-id}")
|
||||
public String delete(@PathVariable("paper-id") Integer paperId) throws IOException {
|
||||
paperService.delete(paperId);
|
||||
return "redirect:/papers/papers";
|
||||
}
|
||||
|
||||
@ModelAttribute("allStatuses")
|
||||
public List<Paper.PaperStatus> getPaperStatuses() {
|
||||
return paperService.getPaperStatuses();
|
||||
|
@ -11,7 +11,8 @@ import org.springframework.web.bind.annotation.RestController;
|
||||
import ru.ulstu.configuration.Constants;
|
||||
import ru.ulstu.core.model.response.Response;
|
||||
import ru.ulstu.paper.model.PaperDto;
|
||||
import ru.ulstu.paper.model.PaperFilterDto;
|
||||
import ru.ulstu.paper.model.PaperListDto;
|
||||
import ru.ulstu.paper.model.ReferenceDto;
|
||||
import ru.ulstu.paper.service.PaperService;
|
||||
|
||||
import javax.validation.Valid;
|
||||
@ -58,12 +59,17 @@ public class PaperRestController {
|
||||
}
|
||||
|
||||
@PostMapping("/filter")
|
||||
public Response<List<PaperDto>> filter(@RequestBody @Valid PaperFilterDto paperFilterDto) throws IOException {
|
||||
return new Response<>(paperService.filter(paperFilterDto));
|
||||
public Response<List<PaperDto>> filter(@RequestBody @Valid PaperListDto paperListDto) throws IOException {
|
||||
return new Response<>(paperService.filter(paperListDto));
|
||||
}
|
||||
|
||||
@GetMapping("formatted-list")
|
||||
public Response<List<String>> getFormattedPaperList() {
|
||||
return new Response<>(paperService.getFormattedPaperList());
|
||||
}
|
||||
|
||||
@PostMapping("/getFormattedReference")
|
||||
public Response<String> getFormattedReference(@RequestBody @Valid ReferenceDto referenceDto) {
|
||||
return new Response<>(paperService.getFormattedReference(referenceDto));
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,7 @@
|
||||
package ru.ulstu.paper.error;
|
||||
|
||||
public class PaperConferenceRelationExistException extends RuntimeException {
|
||||
public PaperConferenceRelationExistException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
@ -2,10 +2,13 @@ package ru.ulstu.paper.model;
|
||||
|
||||
import org.hibernate.annotations.Fetch;
|
||||
import org.hibernate.annotations.FetchMode;
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
import ru.ulstu.conference.model.Conference;
|
||||
import ru.ulstu.core.model.BaseEntity;
|
||||
import ru.ulstu.core.model.UserContainer;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.file.model.FileData;
|
||||
import ru.ulstu.grant.model.Grant;
|
||||
import ru.ulstu.timeline.model.Event;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
@ -21,7 +24,6 @@ import javax.persistence.OneToMany;
|
||||
import javax.persistence.OrderBy;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
@ -114,6 +116,12 @@ public class Paper extends BaseEntity implements UserContainer {
|
||||
@Column(name = "latex_text")
|
||||
private String latexText;
|
||||
|
||||
@ManyToMany(mappedBy = "papers")
|
||||
private List<Conference> conferences;
|
||||
|
||||
@ManyToMany(mappedBy = "papers")
|
||||
private List<Grant> grants;
|
||||
|
||||
public PaperStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
@ -218,6 +226,22 @@ public class Paper extends BaseEntity implements UserContainer {
|
||||
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
|
||||
public Set<User> getUsers() {
|
||||
return getAuthors();
|
||||
|
@ -2,15 +2,16 @@ package ru.ulstu.paper.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class PaperFilterDto {
|
||||
public class PaperListDto {
|
||||
private List<PaperDto> papers;
|
||||
private Integer filterAuthorId;
|
||||
private Integer paperDeleteId;
|
||||
private Integer year;
|
||||
|
||||
public PaperFilterDto() {
|
||||
public PaperListDto() {
|
||||
}
|
||||
|
||||
public PaperFilterDto(List<PaperDto> paperDtos, Integer filterAuthorId, Integer year) {
|
||||
public PaperListDto(List<PaperDto> paperDtos, Integer filterAuthorId, Integer year) {
|
||||
this.papers = paperDtos;
|
||||
this.filterAuthorId = filterAuthorId;
|
||||
this.year = year;
|
||||
@ -39,4 +40,12 @@ public class PaperFilterDto {
|
||||
public void setYear(Integer year) {
|
||||
this.year = year;
|
||||
}
|
||||
|
||||
public Integer getPaperDeleteId() {
|
||||
return paperDeleteId;
|
||||
}
|
||||
|
||||
public void setPaperDeleteId(Integer paperDeleteId) {
|
||||
this.paperDeleteId = paperDeleteId;
|
||||
}
|
||||
}
|
129
src/main/java/ru/ulstu/paper/model/ReferenceDto.java
Normal file
129
src/main/java/ru/ulstu/paper/model/ReferenceDto.java
Normal file
@ -0,0 +1,129 @@
|
||||
package ru.ulstu.paper.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
|
||||
public class ReferenceDto {
|
||||
public enum ReferenceType {
|
||||
ARTICLE("Статья"),
|
||||
BOOK("Книга");
|
||||
|
||||
private String typeName;
|
||||
|
||||
ReferenceType(String name) {
|
||||
this.typeName = name;
|
||||
}
|
||||
|
||||
public String getTypeName() {
|
||||
return typeName;
|
||||
}
|
||||
}
|
||||
|
||||
public enum FormatStandard {
|
||||
GOST("ГОСТ"),
|
||||
SPRINGER("Springer");
|
||||
|
||||
private String standardName;
|
||||
|
||||
FormatStandard(String name) {
|
||||
this.standardName = name;
|
||||
}
|
||||
|
||||
public String getStandardName() {
|
||||
return standardName;
|
||||
}
|
||||
}
|
||||
|
||||
private String authors;
|
||||
private String publicationTitle;
|
||||
private Integer publicationYear;
|
||||
private String publisher;
|
||||
private String pages;
|
||||
private String journalOrCollectionTitle;
|
||||
private ReferenceType referenceType;
|
||||
private FormatStandard formatStandard;
|
||||
|
||||
@JsonCreator
|
||||
public ReferenceDto(
|
||||
@JsonProperty("authors") String authors,
|
||||
@JsonProperty("publicationTitle") String publicationTitle,
|
||||
@JsonProperty("publicationYear") Integer publicationYear,
|
||||
@JsonProperty("publisher") String publisher,
|
||||
@JsonProperty("pages") String pages,
|
||||
@JsonProperty("journalOrCollectionTitle") String journalOrCollectionTitle,
|
||||
@JsonProperty("referenceType") ReferenceType referenceType,
|
||||
@JsonProperty("formatStandard") FormatStandard formatStandard) {
|
||||
this.authors = authors;
|
||||
this.publicationTitle = publicationTitle;
|
||||
this.publicationYear = publicationYear;
|
||||
this.publisher = publisher;
|
||||
this.pages = pages;
|
||||
this.journalOrCollectionTitle = journalOrCollectionTitle;
|
||||
this.referenceType = referenceType;
|
||||
this.formatStandard = formatStandard;
|
||||
}
|
||||
|
||||
public String getAuthors() {
|
||||
return authors;
|
||||
}
|
||||
|
||||
public void setAuthors(String authors) {
|
||||
this.authors = authors;
|
||||
}
|
||||
|
||||
public String getPublicationTitle() {
|
||||
return publicationTitle;
|
||||
}
|
||||
|
||||
public void setPublicationTitle(String publicationTitle) {
|
||||
this.publicationTitle = publicationTitle;
|
||||
}
|
||||
|
||||
public Integer getPublicationYear() {
|
||||
return publicationYear;
|
||||
}
|
||||
|
||||
public void setPublicationYear(Integer publicationYear) {
|
||||
this.publicationYear = publicationYear;
|
||||
}
|
||||
|
||||
public String getPublisher() {
|
||||
return publisher;
|
||||
}
|
||||
|
||||
public void setPublisher(String publisher) {
|
||||
this.publisher = publisher;
|
||||
}
|
||||
|
||||
public String getPages() {
|
||||
return pages;
|
||||
}
|
||||
|
||||
public void setPages(String pages) {
|
||||
this.pages = pages;
|
||||
}
|
||||
|
||||
public String getJournalOrCollectionTitle() {
|
||||
return journalOrCollectionTitle;
|
||||
}
|
||||
|
||||
public void setJournalOrCollectionTitle(String journalOrCollectionTitle) {
|
||||
this.journalOrCollectionTitle = journalOrCollectionTitle;
|
||||
}
|
||||
|
||||
public ReferenceType getReferenceType() {
|
||||
return referenceType;
|
||||
}
|
||||
|
||||
public void setReferenceType(ReferenceType referenceType) {
|
||||
this.referenceType = referenceType;
|
||||
}
|
||||
|
||||
public FormatStandard getFormatStandard() {
|
||||
return formatStandard;
|
||||
}
|
||||
|
||||
public void setFormatStandard(FormatStandard formatStandard) {
|
||||
this.formatStandard = formatStandard;
|
||||
}
|
||||
}
|
@ -14,4 +14,14 @@ public interface PaperRepository extends JpaRepository<Paper, Integer> {
|
||||
List<Paper> filter(@Param("author") User author, @Param("year") Integer year);
|
||||
|
||||
List<Paper> findByIdNotIn(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);
|
||||
}
|
||||
|
@ -9,13 +9,15 @@ import ru.ulstu.file.model.FileDataDto;
|
||||
import ru.ulstu.file.service.FileService;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.paper.model.PaperDto;
|
||||
import ru.ulstu.paper.model.PaperFilterDto;
|
||||
import ru.ulstu.paper.model.PaperListDto;
|
||||
import ru.ulstu.paper.model.ReferenceDto;
|
||||
import ru.ulstu.paper.repository.PaperRepository;
|
||||
import ru.ulstu.timeline.service.EventService;
|
||||
import ru.ulstu.user.model.User;
|
||||
import ru.ulstu.user.service.UserService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.text.MessageFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
@ -32,6 +34,9 @@ import static ru.ulstu.paper.model.Paper.PaperStatus.DRAFT;
|
||||
import static ru.ulstu.paper.model.Paper.PaperStatus.FAILED;
|
||||
import static ru.ulstu.paper.model.Paper.PaperStatus.ON_PREPARATION;
|
||||
import static ru.ulstu.paper.model.Paper.PaperType.OTHER;
|
||||
import static ru.ulstu.paper.model.ReferenceDto.FormatStandard.GOST;
|
||||
import static ru.ulstu.paper.model.ReferenceDto.ReferenceType.ARTICLE;
|
||||
import static ru.ulstu.paper.model.ReferenceDto.ReferenceType.BOOK;
|
||||
|
||||
@Service
|
||||
public class PaperService {
|
||||
@ -81,7 +86,7 @@ public class PaperService {
|
||||
}
|
||||
|
||||
public PaperDto findOneDto(Integer id) {
|
||||
return new PaperDto(paperRepository.getOne(id));
|
||||
return new PaperDto(paperRepository.findOne(id));
|
||||
}
|
||||
|
||||
@Transactional
|
||||
@ -93,6 +98,14 @@ public class PaperService {
|
||||
return newPaper.getId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Paper create(Paper paper) {
|
||||
Paper newPaper = paperRepository.save(paper);
|
||||
paperNotificationService.sendCreateNotification(newPaper);
|
||||
eventService.createFromPaper(newPaper);
|
||||
return newPaper;
|
||||
}
|
||||
|
||||
private Paper copyFromDto(Paper paper, PaperDto paperDto) throws IOException {
|
||||
paper.setComment(paperDto.getComment());
|
||||
paper.setUrl(paperDto.getUrl());
|
||||
@ -116,7 +129,7 @@ public class PaperService {
|
||||
|
||||
@Transactional
|
||||
public Integer update(PaperDto paperDto) throws IOException {
|
||||
Paper paper = paperRepository.getOne(paperDto.getId());
|
||||
Paper paper = paperRepository.findOne(paperDto.getId());
|
||||
Paper.PaperStatus oldStatus = paper.getStatus();
|
||||
Set<User> oldAuthors = new HashSet<>(paper.getAuthors());
|
||||
|
||||
@ -142,8 +155,8 @@ public class PaperService {
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Integer paperId) throws IOException {
|
||||
Paper paper = paperRepository.getOne(paperId);
|
||||
public void delete(Integer paperId) {
|
||||
Paper paper = paperRepository.findOne(paperId);
|
||||
paperRepository.delete(paper);
|
||||
}
|
||||
|
||||
@ -173,7 +186,7 @@ public class PaperService {
|
||||
return paper;
|
||||
}
|
||||
|
||||
public List<PaperDto> filter(PaperFilterDto filterDto) {
|
||||
public List<PaperDto> filter(PaperListDto filterDto) {
|
||||
return convert(sortPapers(paperRepository.filter(
|
||||
filterDto.getFilterAuthorId() == null ? null : userService.findById(filterDto.getFilterAuthorId()),
|
||||
filterDto.getYear())), PaperDto::new);
|
||||
@ -220,20 +233,27 @@ public class PaperService {
|
||||
}
|
||||
|
||||
public PaperDto findById(Integer paperId) {
|
||||
return new PaperDto(paperRepository.getOne(paperId));
|
||||
return new PaperDto(paperRepository.findOne(paperId));
|
||||
}
|
||||
|
||||
public Paper findEntityById(Integer paperId) {
|
||||
return paperRepository.getOne(paperId);
|
||||
public Paper findPaperById(Integer paperId) {
|
||||
return paperRepository.findOne(paperId);
|
||||
}
|
||||
|
||||
public List<Paper> findAllNotSelect(List<Integer> paperIds) {
|
||||
if (!paperIds.isEmpty()) {
|
||||
return sortPapers(paperRepository.findByIdNotIn(paperIds));
|
||||
return sortPapers(paperRepository.findByIdNotInAndConferencesIsNullAndStatusNot(paperIds, COMPLETED));
|
||||
} else {
|
||||
return sortPapers(paperRepository.findAll());
|
||||
return sortPapers(paperRepository.findByConferencesIsNullAndStatusNot(COMPLETED));
|
||||
}
|
||||
}
|
||||
|
||||
public List<PaperDto> findAllNotCompleted() {
|
||||
return convert(paperRepository.findByStatusNot(COMPLETED), PaperDto::new);
|
||||
}
|
||||
|
||||
public List<PaperDto> findAllSelect(List<Integer> paperIds) {
|
||||
return convert(paperRepository.findAllByIdIn(paperIds), PaperDto::new);
|
||||
}
|
||||
|
||||
public List<User> getPaperAuthors() {
|
||||
@ -260,4 +280,34 @@ public class PaperService {
|
||||
.map(User::getUserAbbreviate)
|
||||
.collect(Collectors.joining(", "));
|
||||
}
|
||||
|
||||
public String getFormattedReference(ReferenceDto referenceDto) {
|
||||
return referenceDto.getFormatStandard() == GOST
|
||||
? getGostReference(referenceDto)
|
||||
: getSpringerReference(referenceDto);
|
||||
}
|
||||
|
||||
public String getGostReference(ReferenceDto referenceDto) {
|
||||
return MessageFormat.format(referenceDto.getReferenceType() == BOOK ? "{0} {1} - {2}{3}. - {4}с." : "{0} {1}{5} {2}{3}. С. {4}.",
|
||||
referenceDto.getAuthors(),
|
||||
referenceDto.getPublicationTitle(),
|
||||
StringUtils.isEmpty(referenceDto.getPublisher()) ? "" : referenceDto.getPublisher() + ", ",
|
||||
referenceDto.getPublicationYear().toString(),
|
||||
referenceDto.getPages(),
|
||||
StringUtils.isEmpty(referenceDto.getJournalOrCollectionTitle()) ? "." : " // " + referenceDto.getJournalOrCollectionTitle() + ".");
|
||||
}
|
||||
|
||||
public String getSpringerReference(ReferenceDto referenceDto) {
|
||||
return MessageFormat.format("{0} ({1}) {2}.{3} {4}pp {5}",
|
||||
referenceDto.getAuthors(),
|
||||
referenceDto.getPublicationYear().toString(),
|
||||
referenceDto.getPublicationTitle(),
|
||||
referenceDto.getReferenceType() == ARTICLE ? " " + referenceDto.getJournalOrCollectionTitle() + "," : "",
|
||||
StringUtils.isEmpty(referenceDto.getPublisher()) ? "" : referenceDto.getPublisher() + ", ",
|
||||
referenceDto.getPages());
|
||||
}
|
||||
|
||||
public List<Paper> findAllCompletedByType(Paper.PaperType type) {
|
||||
return paperRepository.findByTypeAndStatus(type, Paper.PaperStatus.COMPLETED);
|
||||
}
|
||||
}
|
||||
|
73
src/main/java/ru/ulstu/ping/model/Ping.java
Normal file
73
src/main/java/ru/ulstu/ping/model/Ping.java
Normal file
@ -0,0 +1,73 @@
|
||||
package ru.ulstu.ping.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import ru.ulstu.conference.model.Conference;
|
||||
import ru.ulstu.core.model.BaseEntity;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import java.util.Date;
|
||||
|
||||
@Entity
|
||||
@Table(name = "ping")
|
||||
public class Ping extends BaseEntity {
|
||||
@Temporal(value = TemporalType.TIMESTAMP)
|
||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||
private Date date;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "users_id")
|
||||
private User user;
|
||||
|
||||
@ManyToOne(optional = false)
|
||||
@JoinColumn(name = "conference_id")
|
||||
private Conference conference;
|
||||
|
||||
public Ping() {
|
||||
}
|
||||
|
||||
public Ping(Date date, User user) {
|
||||
this.date = date;
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public Ping(@JsonProperty("id") Integer id,
|
||||
@JsonProperty("date") Date date,
|
||||
@JsonProperty("user") User user,
|
||||
@JsonProperty("conference") Conference conference) {
|
||||
setId(id);
|
||||
this.date = date;
|
||||
this.user = user;
|
||||
this.conference = conference;
|
||||
}
|
||||
|
||||
public Date getDate() {
|
||||
return date;
|
||||
}
|
||||
|
||||
public void setDate(Date date) {
|
||||
this.date = date;
|
||||
}
|
||||
|
||||
public User getUser() {
|
||||
return user;
|
||||
}
|
||||
|
||||
public void setUser(User user) {
|
||||
this.user = user;
|
||||
}
|
||||
|
||||
public Conference getConference() {
|
||||
return conference;
|
||||
}
|
||||
|
||||
public void setConference(Conference conference) {
|
||||
this.conference = conference;
|
||||
}
|
||||
}
|
13
src/main/java/ru/ulstu/ping/repository/PingRepository.java
Normal file
13
src/main/java/ru/ulstu/ping/repository/PingRepository.java
Normal file
@ -0,0 +1,13 @@
|
||||
package ru.ulstu.ping.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import ru.ulstu.conference.model.Conference;
|
||||
import ru.ulstu.ping.model.Ping;
|
||||
|
||||
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);
|
||||
}
|
36
src/main/java/ru/ulstu/ping/service/PingService.java
Normal file
36
src/main/java/ru/ulstu/ping/service/PingService.java
Normal file
@ -0,0 +1,36 @@
|
||||
package ru.ulstu.ping.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.ulstu.conference.model.Conference;
|
||||
import ru.ulstu.ping.model.Ping;
|
||||
import ru.ulstu.ping.repository.PingRepository;
|
||||
import ru.ulstu.user.service.UserService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
|
||||
@Service
|
||||
public class PingService {
|
||||
private final PingRepository pingRepository;
|
||||
private final UserService userService;
|
||||
|
||||
public PingService(PingRepository pingRepository,
|
||||
UserService userService) {
|
||||
this.pingRepository = pingRepository;
|
||||
this.userService = userService;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void addPing(Conference conference) throws IOException {
|
||||
Ping newPing = new Ping(new Date(), userService.getCurrentUser());
|
||||
newPing.setConference(conference);
|
||||
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)));
|
||||
}
|
||||
}
|
@ -5,6 +5,7 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
@ -78,6 +79,12 @@ public class ProjectController {
|
||||
return "/projects/project";
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{project-id}")
|
||||
public String delete(@PathVariable("project-id") Integer projectId) throws IOException {
|
||||
projectService.delete(projectId);
|
||||
return String.format("redirect:%s", "/projects/projects");
|
||||
}
|
||||
|
||||
private void filterEmptyDeadlines(ProjectDto projectDto) {
|
||||
projectDto.setDeadlines(projectDto.getDeadlines().stream()
|
||||
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
||||
|
@ -62,6 +62,25 @@ public class ProjectService {
|
||||
return newProject;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Project update(ProjectDto projectDto) throws IOException {
|
||||
Project project = projectRepository.findOne(projectDto.getId());
|
||||
if (projectDto.getApplicationFileName() != null && project.getApplication() != null) {
|
||||
fileService.deleteFile(project.getApplication());
|
||||
}
|
||||
projectRepository.save(copyFromDto(project, projectDto));
|
||||
return project;
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Integer projectId) throws IOException {
|
||||
Project project = projectRepository.findOne(projectId);
|
||||
if (project.getApplication() != null) {
|
||||
fileService.deleteFile(project.getApplication());
|
||||
}
|
||||
projectRepository.delete(project);
|
||||
}
|
||||
|
||||
private Project copyFromDto(Project project, ProjectDto projectDto) throws IOException {
|
||||
project.setDescription(projectDto.getDescription());
|
||||
project.setStatus(projectDto.getStatus() == null ? APPLICATION : projectDto.getStatus());
|
||||
@ -85,10 +104,6 @@ public class ProjectService {
|
||||
}
|
||||
}
|
||||
|
||||
private Project update(ProjectDto projectDto) {
|
||||
throw new RuntimeException("not implemented yet");
|
||||
}
|
||||
|
||||
public Project findById(Integer id) {
|
||||
return projectRepository.getOne(id);
|
||||
}
|
||||
|
@ -5,13 +5,16 @@ import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.Errors;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.ModelAttribute;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.students.model.Task;
|
||||
import ru.ulstu.students.model.TaskDto;
|
||||
import ru.ulstu.students.model.TaskFilterDto;
|
||||
import ru.ulstu.students.service.TaskService;
|
||||
import ru.ulstu.tags.model.Tag;
|
||||
import springfox.documentation.annotations.ApiIgnore;
|
||||
|
||||
import javax.validation.Valid;
|
||||
@ -35,16 +38,16 @@ public class TaskController {
|
||||
this.taskService = taskService;
|
||||
}
|
||||
|
||||
@GetMapping("/tasks")
|
||||
public void getTasks(ModelMap modelMap) {
|
||||
modelMap.put("tasks", taskService.findAllDto());
|
||||
}
|
||||
|
||||
@GetMapping("/dashboard")
|
||||
public void getDashboard(ModelMap modelMap) {
|
||||
modelMap.put("tasks", taskService.findAllDto());
|
||||
}
|
||||
|
||||
@GetMapping("/tasks")
|
||||
public void getTask(ModelMap modelMap) {
|
||||
modelMap.put("filteredTasks", new TaskFilterDto(taskService.findAllDto(), null, null, null));
|
||||
}
|
||||
|
||||
@GetMapping("/task")
|
||||
public void getTask(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
|
||||
if (id != null && id > 0) {
|
||||
@ -54,6 +57,14 @@ public class TaskController {
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/tasks")
|
||||
public void filterTasks(@Valid TaskFilterDto taskFilterDto, ModelMap modelMap) {
|
||||
modelMap.put("filteredTasks", new TaskFilterDto(taskService.filter(taskFilterDto),
|
||||
taskFilterDto.getStatus(),
|
||||
taskFilterDto.getTag(),
|
||||
taskFilterDto.getOrder()));
|
||||
}
|
||||
|
||||
@PostMapping(value = "/task", params = "save")
|
||||
public String save(@Valid TaskDto taskDto, Errors errors) throws IOException {
|
||||
filterEmptyDeadlines(taskDto);
|
||||
@ -77,11 +88,23 @@ public class TaskController {
|
||||
return TASK_PAGE;
|
||||
}
|
||||
|
||||
@GetMapping("/delete/{task-id}")
|
||||
public String delete(@PathVariable("task-id") Integer taskId) throws IOException {
|
||||
taskService.delete(taskId);
|
||||
return String.format(REDIRECT_TO, TASKS_PAGE);
|
||||
}
|
||||
|
||||
|
||||
@ModelAttribute("allStatuses")
|
||||
public List<Task.TaskStatus> getTaskStatuses() {
|
||||
return taskService.getTaskStatuses();
|
||||
}
|
||||
|
||||
@ModelAttribute("allTags")
|
||||
public List<Tag> getTags() {
|
||||
return taskService.getTags();
|
||||
}
|
||||
|
||||
private void filterEmptyDeadlines(TaskDto taskDto) {
|
||||
taskDto.setDeadlines(taskDto.getDeadlines().stream()
|
||||
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
||||
|
@ -50,7 +50,7 @@ public class Task extends BaseEntity {
|
||||
private String description;
|
||||
|
||||
@Enumerated(value = EnumType.STRING)
|
||||
private ru.ulstu.students.model.Task.TaskStatus status = TaskStatus.IN_WORK;
|
||||
private TaskStatus status = TaskStatus.IN_WORK;
|
||||
|
||||
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||
@JoinColumn(name = "task_id", unique = true)
|
||||
@ -67,6 +67,7 @@ public class Task extends BaseEntity {
|
||||
private Date updateDate = new Date();
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
@Fetch(FetchMode.SUBSELECT)
|
||||
@JoinTable(name = "task_tags",
|
||||
joinColumns = {@JoinColumn(name = "task_id")},
|
||||
inverseJoinColumns = {@JoinColumn(name = "tag_id")})
|
||||
@ -127,4 +128,5 @@ public class Task extends BaseEntity {
|
||||
public void setTags(List<Tag> tags) {
|
||||
this.tags = tags;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -26,7 +26,7 @@ public class TaskDto {
|
||||
private Date createDate;
|
||||
private Date updateDate;
|
||||
private Set<Integer> tagIds;
|
||||
private List<Tag> tags;
|
||||
private List<Tag> tags = new ArrayList<>();
|
||||
|
||||
public TaskDto() {
|
||||
deadlines.add(new Deadline());
|
||||
|
54
src/main/java/ru/ulstu/students/model/TaskFilterDto.java
Normal file
54
src/main/java/ru/ulstu/students/model/TaskFilterDto.java
Normal file
@ -0,0 +1,54 @@
|
||||
package ru.ulstu.students.model;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class TaskFilterDto {
|
||||
|
||||
private List<TaskDto> tasks;
|
||||
private Task.TaskStatus status;
|
||||
private Integer tagId;
|
||||
private String order;
|
||||
|
||||
public TaskFilterDto(List<TaskDto> tasks, Task.TaskStatus status, Integer tagId, String order) {
|
||||
this.tasks = tasks;
|
||||
this.status = status;
|
||||
this.tagId = tagId;
|
||||
this.order = order;
|
||||
}
|
||||
|
||||
public TaskFilterDto() {
|
||||
|
||||
}
|
||||
|
||||
public List<TaskDto> getTasks() {
|
||||
return tasks;
|
||||
}
|
||||
|
||||
public void setTasks(List<TaskDto> tasks) {
|
||||
this.tasks = tasks;
|
||||
}
|
||||
|
||||
public Task.TaskStatus getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(Task.TaskStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public Integer getTag() {
|
||||
return tagId;
|
||||
}
|
||||
|
||||
public void setTag(Integer tagId) {
|
||||
this.tagId = tagId;
|
||||
}
|
||||
|
||||
public String getOrder() {
|
||||
return order;
|
||||
}
|
||||
|
||||
public void setOrder(String order) {
|
||||
this.order = order;
|
||||
}
|
||||
}
|
@ -1,7 +1,18 @@
|
||||
package ru.ulstu.students.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
import ru.ulstu.students.model.Task;
|
||||
import ru.ulstu.tags.model.Tag;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface TaskRepository extends JpaRepository<Task, Integer> {
|
||||
|
||||
@Query("SELECT t FROM Task t WHERE (t.status = :status OR :status IS NULL) AND (:tag IS NULL OR :tag MEMBER OF t.tags) ORDER BY create_date DESC")
|
||||
List<Task> filterNew(@Param("status") Task.TaskStatus status, @Param("tag") Tag tag);
|
||||
|
||||
@Query("SELECT t FROM Task t WHERE (t.status = :status OR :status IS NULL) AND (:tag IS NULL OR :tag MEMBER OF t.tags) ORDER BY create_date ASC")
|
||||
List<Task> filterOld(@Param("status") Task.TaskStatus status, @Param("tag") Tag tag);
|
||||
}
|
||||
|
@ -1,13 +1,17 @@
|
||||
package ru.ulstu.students.service;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.ulstu.deadline.service.DeadlineService;
|
||||
import ru.ulstu.students.model.Task;
|
||||
import ru.ulstu.students.model.TaskDto;
|
||||
import ru.ulstu.students.model.TaskFilterDto;
|
||||
import ru.ulstu.students.repository.TaskRepository;
|
||||
import ru.ulstu.tags.model.Tag;
|
||||
import ru.ulstu.tags.service.TagService;
|
||||
import ru.ulstu.timeline.service.EventService;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
@ -26,16 +30,18 @@ public class TaskService {
|
||||
private final TaskRepository taskRepository;
|
||||
private final DeadlineService deadlineService;
|
||||
private final TagService tagService;
|
||||
private final EventService eventService;
|
||||
|
||||
public TaskService(TaskRepository grantRepository,
|
||||
DeadlineService deadlineService, TagService tagService) {
|
||||
this.taskRepository = grantRepository;
|
||||
public TaskService(TaskRepository taskRepository,
|
||||
DeadlineService deadlineService, TagService tagService, EventService eventService) {
|
||||
this.taskRepository = taskRepository;
|
||||
this.deadlineService = deadlineService;
|
||||
this.tagService = tagService;
|
||||
this.eventService = eventService;
|
||||
}
|
||||
|
||||
public List<Task> findAll() {
|
||||
return taskRepository.findAll();
|
||||
return taskRepository.findAll(new Sort(Sort.Direction.DESC, "createDate"));
|
||||
}
|
||||
|
||||
public List<TaskDto> findAllDto() {
|
||||
@ -45,13 +51,26 @@ public class TaskService {
|
||||
}
|
||||
|
||||
public TaskDto findOneDto(Integer id) {
|
||||
return new TaskDto(taskRepository.getOne(id));
|
||||
return new TaskDto(taskRepository.findOne(id));
|
||||
}
|
||||
|
||||
public List<TaskDto> filter(TaskFilterDto filterDto) {
|
||||
if (filterDto.getOrder().compareTo("new") == 0) {
|
||||
return convert(taskRepository.filterNew(
|
||||
filterDto.getStatus(),
|
||||
filterDto.getTag() == null ? null : tagService.findById(filterDto.getTag())), TaskDto::new);
|
||||
} else {
|
||||
return convert(taskRepository.filterOld(
|
||||
filterDto.getStatus(),
|
||||
filterDto.getTag() == null ? null : tagService.findById(filterDto.getTag())), TaskDto::new);
|
||||
}
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public Integer create(TaskDto taskDto) throws IOException {
|
||||
Task newTask = copyFromDto(new Task(), taskDto);
|
||||
newTask = taskRepository.save(newTask);
|
||||
eventService.createFromTask(newTask);
|
||||
return newTask.getId();
|
||||
}
|
||||
|
||||
@ -69,15 +88,18 @@ public class TaskService {
|
||||
|
||||
@Transactional
|
||||
public Integer update(TaskDto taskDto) throws IOException {
|
||||
Task task = taskRepository.getOne(taskDto.getId());
|
||||
Task task = taskRepository.findOne(taskDto.getId());
|
||||
taskRepository.save(copyFromDto(task, taskDto));
|
||||
eventService.updateTaskDeadlines(task);
|
||||
return task.getId();
|
||||
}
|
||||
|
||||
@Transactional
|
||||
public void delete(Integer taskId) throws IOException {
|
||||
Task task = taskRepository.getOne(taskId);
|
||||
taskRepository.delete(task);
|
||||
if (taskRepository.exists(taskId)) {
|
||||
taskRepository.delete(taskId);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void save(TaskDto taskDto) throws IOException {
|
||||
@ -92,4 +114,8 @@ public class TaskService {
|
||||
return Arrays.asList(Task.TaskStatus.values());
|
||||
}
|
||||
|
||||
public List<Tag> getTags() {
|
||||
return tagService.getTags();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -50,4 +50,12 @@ public class TagService {
|
||||
return newTag;
|
||||
}
|
||||
|
||||
public List<Tag> getTags() {
|
||||
return tagRepository.findAll();
|
||||
}
|
||||
|
||||
public Tag findById(Integer tagId) {
|
||||
return tagRepository.findOne(tagId);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,11 @@
|
||||
package ru.ulstu.timeline.model;
|
||||
|
||||
import org.hibernate.validator.constraints.NotBlank;
|
||||
import ru.ulstu.conference.model.Conference;
|
||||
import ru.ulstu.core.model.BaseEntity;
|
||||
import ru.ulstu.grant.model.Grant;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.students.model.Task;
|
||||
import ru.ulstu.user.model.User;
|
||||
|
||||
import javax.persistence.CascadeType;
|
||||
@ -16,8 +20,8 @@ import javax.persistence.ManyToOne;
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Temporal;
|
||||
import javax.persistence.TemporalType;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@ -62,7 +66,7 @@ public class Event extends BaseEntity {
|
||||
private String description;
|
||||
|
||||
@ManyToMany(fetch = FetchType.EAGER)
|
||||
private List<User> recipients;
|
||||
private List<User> recipients = new ArrayList<User>();
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "child_id")
|
||||
@ -76,6 +80,18 @@ public class Event extends BaseEntity {
|
||||
@JoinColumn(name = "paper_id")
|
||||
private Paper paper;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "conference_id")
|
||||
private Conference conference;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "grant_id")
|
||||
private Grant grant;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "task_id")
|
||||
private Task task;
|
||||
|
||||
public String getTitle() {
|
||||
return title;
|
||||
}
|
||||
@ -163,4 +179,28 @@ public class Event extends BaseEntity {
|
||||
public void setPaper(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;
|
||||
}
|
||||
|
||||
public Task getTask() {
|
||||
return task;
|
||||
}
|
||||
|
||||
public void setTask(Task task) {
|
||||
this.task = task;
|
||||
}
|
||||
}
|
||||
|
@ -2,8 +2,11 @@ package ru.ulstu.timeline.model;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import javax.validation.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.students.model.TaskDto;
|
||||
import ru.ulstu.user.model.UserDto;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
@ -25,6 +28,9 @@ public class EventDto {
|
||||
private final String description;
|
||||
private final List<UserDto> recipients;
|
||||
private PaperDto paperDto;
|
||||
private ConferenceDto conferenceDto;
|
||||
private GrantDto grantDto;
|
||||
private TaskDto taskDto;
|
||||
|
||||
@JsonCreator
|
||||
public EventDto(@JsonProperty("id") Integer id,
|
||||
@ -36,7 +42,10 @@ public class EventDto {
|
||||
@JsonProperty("updateDate") Date updateDate,
|
||||
@JsonProperty("description") String description,
|
||||
@JsonProperty("paperDto") PaperDto paperDto,
|
||||
@JsonProperty("recipients") List<UserDto> recipients) {
|
||||
@JsonProperty("recipients") List<UserDto> recipients,
|
||||
@JsonProperty("conferenceDto") ConferenceDto conferenceDto,
|
||||
@JsonProperty("grantDto") GrantDto grantDto,
|
||||
@JsonProperty("taskDto") TaskDto taskDto) {
|
||||
this.id = id;
|
||||
this.title = title;
|
||||
this.period = period;
|
||||
@ -47,6 +56,9 @@ public class EventDto {
|
||||
this.description = description;
|
||||
this.recipients = recipients;
|
||||
this.paperDto = paperDto;
|
||||
this.conferenceDto = conferenceDto;
|
||||
this.grantDto = grantDto;
|
||||
this.taskDto = taskDto;
|
||||
}
|
||||
|
||||
public EventDto(Event event) {
|
||||
@ -58,8 +70,19 @@ public class EventDto {
|
||||
this.createDate = event.getCreateDate();
|
||||
this.updateDate = event.getUpdateDate();
|
||||
this.description = event.getDescription();
|
||||
this.paperDto = new PaperDto(event.getPaper());
|
||||
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());
|
||||
}
|
||||
if (taskDto != null) {
|
||||
this.taskDto = new TaskDto(event.getTask());
|
||||
}
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
@ -105,4 +128,28 @@ public class EventDto {
|
||||
public void setPaperDto(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;
|
||||
}
|
||||
|
||||
public TaskDto getTaskDto() {
|
||||
return taskDto;
|
||||
}
|
||||
|
||||
public void setTaskDto(TaskDto taskDto) {
|
||||
this.taskDto = taskDto;
|
||||
}
|
||||
}
|
||||
|
@ -2,7 +2,10 @@ package ru.ulstu.timeline.repository;
|
||||
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
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.students.model.Task;
|
||||
import ru.ulstu.timeline.model.Event;
|
||||
|
||||
import java.util.List;
|
||||
@ -15,4 +18,10 @@ public interface EventRepository extends JpaRepository<Event, Integer> {
|
||||
List<Event> findAllFuture();
|
||||
|
||||
List<Event> findAllByPaper(Paper paper);
|
||||
|
||||
List<Event> findAllByConference(Conference conference);
|
||||
|
||||
List<Event> findAllByGrant(Grant grant);
|
||||
|
||||
List<Event> findAllByTask(Task task);
|
||||
}
|
||||
|
@ -4,8 +4,11 @@ import org.apache.commons.lang3.time.DateUtils;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import ru.ulstu.conference.model.Conference;
|
||||
import ru.ulstu.deadline.model.Deadline;
|
||||
import ru.ulstu.grant.model.Grant;
|
||||
import ru.ulstu.paper.model.Paper;
|
||||
import ru.ulstu.students.model.Task;
|
||||
import ru.ulstu.timeline.model.Event;
|
||||
import ru.ulstu.timeline.model.EventDto;
|
||||
import ru.ulstu.timeline.model.Timeline;
|
||||
@ -140,4 +143,99 @@ public class EventService {
|
||||
public List<EventDto> findAllFutureDto() {
|
||||
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);
|
||||
}
|
||||
|
||||
public void removeConferencesEvent(Conference conference) {
|
||||
List<Event> eventList = eventRepository.findAllByConference(conference);
|
||||
eventList.forEach(event -> eventRepository.delete(event.getId()));
|
||||
}
|
||||
|
||||
public void createFromTask(Task newTask) {
|
||||
List<Timeline> timelines = timelineService.findAll();
|
||||
Timeline timeline = timelines.isEmpty() ? new Timeline() : timelines.get(0);
|
||||
|
||||
for (Deadline deadline : newTask.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() + "' задачи '" + newTask.getTitle() + "'");
|
||||
newEvent.getRecipients().add(userService.getCurrentUser());
|
||||
newEvent.setTask(newTask);
|
||||
eventRepository.save(newEvent);
|
||||
|
||||
timeline.getEvents().add(newEvent);
|
||||
timelineService.save(timeline);
|
||||
}
|
||||
}
|
||||
|
||||
public void updateTaskDeadlines(Task task) {
|
||||
eventRepository.delete(eventRepository.findAllByTask(task));
|
||||
createFromTask(task);
|
||||
}
|
||||
}
|
||||
|
17
src/main/resources/db/changelog-20190419_000000-schema.xml
Normal file
17
src/main/resources/db/changelog-20190419_000000-schema.xml
Normal file
@ -0,0 +1,17 @@
|
||||
<?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="20190419_000000-1">
|
||||
<createTable tableName="grants_papers">
|
||||
<column name="grant_id" type="integer"/>
|
||||
<column name="paper_id" type="integer"/>
|
||||
</createTable>
|
||||
<addForeignKeyConstraint baseTableName="grants_papers" baseColumnNames="grant_id"
|
||||
constraintName="fk_grants_grants_papers" referencedTableName="grants"
|
||||
referencedColumnNames="id"/>
|
||||
<addForeignKeyConstraint baseTableName="grants_papers" baseColumnNames="paper_id"
|
||||
constraintName="fk_paper_grants_papers" referencedTableName="paper"
|
||||
referencedColumnNames="id"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
28
src/main/resources/db/changelog-20190424_000000-schema.xml
Normal file
28
src/main/resources/db/changelog-20190424_000000-schema.xml
Normal file
@ -0,0 +1,28 @@
|
||||
<?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="20190424_000000-1">
|
||||
<createTable tableName="ping">
|
||||
<column name="id" type="integer">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="date" type="timestamp">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="users_id" type="integer">
|
||||
<constraints nullable="false"/>
|
||||
</column>
|
||||
<column name="conference_id" type="integer"/>
|
||||
<column name="version" type="integer"/>
|
||||
</createTable>
|
||||
<addPrimaryKey columnNames="id" constraintName="pk_ping" tableName="ping"/>
|
||||
<addForeignKeyConstraint baseTableName="ping" baseColumnNames="users_id"
|
||||
constraintName="fk_ping_users_id" referencedTableName="users"
|
||||
referencedColumnNames="id"/>
|
||||
<addForeignKeyConstraint baseTableName="ping" baseColumnNames="conference_id"
|
||||
constraintName="fk_ping_conference_id" referencedTableName="conference"
|
||||
referencedColumnNames="id"/>
|
||||
</changeSet>
|
||||
|
||||
</databaseChangeLog>
|
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>
|
14
src/main/resources/db/changelog-20190505_000000-schema.xml
Normal file
14
src/main/resources/db/changelog-20190505_000000-schema.xml
Normal file
@ -0,0 +1,14 @@
|
||||
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||
<changeSet author="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>
|
@ -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>
|
13
src/main/resources/db/changelog-20190511_000000-schema.xml
Normal file
13
src/main/resources/db/changelog-20190511_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="nastya" id="20190511_000000-1">
|
||||
<addColumn tableName="event">
|
||||
<column name="task_id" type="integer"></column>
|
||||
</addColumn>
|
||||
<addForeignKeyConstraint baseTableName="event" baseColumnNames="task_id"
|
||||
constraintName="fk_event_task_id" referencedTableName="task"
|
||||
referencedColumnNames="id"/>
|
||||
</changeSet>
|
||||
</databaseChangeLog>
|
@ -30,7 +30,15 @@
|
||||
<include file="db/common/changelog-20190312_130000-schema.xml"/>
|
||||
<include file="db/changelog-20190402_000000-schema.xml"/>
|
||||
<include file="db/changelog-20190404_000000-schema.xml"/>
|
||||
<include file="db/changelog-20190419_000000-schema.xml"/>
|
||||
<include file="db/changelog-20190421_000000-schema.xml"/>
|
||||
<include file="db/changelog-20190422_000000-schema.xml"/>
|
||||
<include file="db/common/changelog-20190423_100000-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-20190507_000000-schema.xml"/>
|
||||
<include file="db/changelog-20190507_000001-schema.xml"/>
|
||||
<include file="db/changelog-20190511_000000-schema.xml"/>
|
||||
</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>
|
@ -12,9 +12,11 @@
|
||||
<p>
|
||||
Вам нужно поработать над статьей "<a th:href="@{|${baseUrl}/papers/paper?id=${paper.id}|}"><span th:text="${paper.title}">Title</span></a>".
|
||||
</p>
|
||||
<p>
|
||||
<div th:with="nextDeadline=${paper.nextDeadline}" th:remove="tag">
|
||||
<p th:if="${nextDeadline.isPresent()}">
|
||||
Срок исполнения: <span th:text="${#dates.format(paper.nextDeadline.get().date, 'dd.MM.yyyy HH:mm')}"></span>.
|
||||
</p>
|
||||
</div>
|
||||
<p>
|
||||
Regards,
|
||||
<br/>
|
||||
|
@ -2,11 +2,15 @@ body {
|
||||
min-width: 400px;
|
||||
}
|
||||
|
||||
.conference-row .col:hover {
|
||||
background-color: #f3f3f3;
|
||||
.conference-row .d-flex:hover {
|
||||
background-color: #f1f1f1;
|
||||
border-radius: .25rem;
|
||||
}
|
||||
|
||||
.conference-row .d-flex:hover .icon-delete {
|
||||
visibility: visible;
|
||||
}
|
||||
|
||||
.filter-option-inner-inner {
|
||||
color: white;
|
||||
}
|
||||
@ -15,8 +19,28 @@ body {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.conference-row .col .text-decoration {
|
||||
.conference-row .d-flex .text-decoration {
|
||||
text-decoration: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.conference-row .d-flex .text-decoration:nth-child(1) {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
.conference-row .d-flex .icon-delete {
|
||||
width: 29px;
|
||||
height: 29px;
|
||||
margin: auto;
|
||||
border: none;
|
||||
visibility: hidden;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.conference-row .d-flex {
|
||||
margin: 0 15px;
|
||||
}
|
||||
|
||||
|
||||
@ -52,7 +76,6 @@ body {
|
||||
height: 40px;
|
||||
max-height: 40px;
|
||||
}
|
||||
|
||||
.member select {
|
||||
appearance: none;
|
||||
-moz-appearance: none;
|
||||
@ -62,13 +85,17 @@ body {
|
||||
padding: 0.5rem 1.75em 0.5rem 0.5em;
|
||||
display: inline-block;
|
||||
background: transparent url("https://cdn3.iconfinder.com/data/icons/faticons/32/arrow-down-01-16.png") no-repeat right 7px center;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.member select:nth-child(4) {
|
||||
border-right: 1px solid #ced4da;
|
||||
}
|
||||
|
||||
.member select:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
|
||||
.member-name {
|
||||
padding: .75rem 1.25rem;
|
||||
@ -78,6 +105,16 @@ body {
|
||||
border-right: 1px solid #ced4da;
|
||||
}
|
||||
|
||||
#ping-button[disabled=disabled] {
|
||||
background-color: #ced4da;
|
||||
border-color: #c2c5c7;
|
||||
}
|
||||
|
||||
#ping-button[disabled=disabled]:hover {
|
||||
background-color: #737475 !important;
|
||||
border-color: #5d5e5f !important;
|
||||
}
|
||||
|
||||
#take-part[disabled=disabled] {
|
||||
background-color: #ced4da;
|
||||
border-color: #c2c5c7;
|
||||
@ -103,13 +140,34 @@ body {
|
||||
|
||||
.paper-name {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.paper-name:hover {
|
||||
background-color: #f1f1f1;
|
||||
}
|
||||
|
||||
.paper-name span {
|
||||
margin: 6px 15px;
|
||||
margin: 7px 10px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.paper-name span:nth-child(1) {
|
||||
margin: 3px 0px 3px 10px;
|
||||
float: left;
|
||||
}
|
||||
|
||||
.paper-name span:nth-child(2) {
|
||||
max-width: 326px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
max-width: 445px;
|
||||
}
|
||||
|
||||
|
||||
|
||||
.icon {
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
@ -118,14 +176,14 @@ body {
|
||||
}
|
||||
|
||||
.icon-delete {
|
||||
background-color: #f44;
|
||||
background-color: #ff7272;
|
||||
background-image: url(/img/conference/delete.png);
|
||||
background-repeat: round;
|
||||
color: transparent !important;
|
||||
}
|
||||
|
||||
.icon-delete:hover {
|
||||
background-color: #ff2929;
|
||||
background-color: #ff0000 !important;
|
||||
transition: background-color .15s ease-in-out;
|
||||
}
|
||||
|
||||
@ -154,6 +212,22 @@ body {
|
||||
float: right;
|
||||
}
|
||||
|
||||
.note-1 {
|
||||
background-color: #bfffce;
|
||||
}
|
||||
|
||||
.note-2 {
|
||||
background-color: #eaffb4;
|
||||
}
|
||||
|
||||
.note-3 {
|
||||
background-color: #fff69f;
|
||||
}
|
||||
|
||||
.note-4 {
|
||||
background-color: #ff9973;
|
||||
}
|
||||
|
||||
@media (max-width: 1199px) and (min-width: 768px){
|
||||
.paper-control {
|
||||
display: block!important;
|
||||
|
@ -10,3 +10,34 @@
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
}
|
||||
|
||||
.div-view-paper {
|
||||
margin-top: 6px;
|
||||
}
|
||||
|
||||
.div-selected-papers {
|
||||
border: 0px;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.icon-paper {
|
||||
height: 22px;
|
||||
width: 22px;
|
||||
margin: 3px;
|
||||
}
|
||||
|
||||
.btn-delete-deadline {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.div-file-name{
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.div-loader {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.div-row-file {
|
||||
margin-bottom: 2px;
|
||||
}
|
@ -13,6 +13,21 @@
|
||||
cursor: text;
|
||||
}
|
||||
|
||||
.filter .bootstrap-select{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.filter-option-inner-inner{
|
||||
font-size: 12px;
|
||||
text-transform: uppercase;
|
||||
font-weight: normal;
|
||||
line-height: 25px;
|
||||
}
|
||||
|
||||
.sorting .bootstrap-select{
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.input-tag-name {
|
||||
border: none;
|
||||
box-shadow: none;
|
||||
@ -24,6 +39,42 @@
|
||||
max-width: inherit;
|
||||
}
|
||||
|
||||
.task-row{
|
||||
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.task-row .col:hover{
|
||||
|
||||
background-color: #f8f9fa;
|
||||
|
||||
}
|
||||
|
||||
.task-row .col > a{
|
||||
display: block;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.task-row .col:hover .remove-task{
|
||||
|
||||
visibility: visible;
|
||||
|
||||
}
|
||||
|
||||
.remove-task{
|
||||
visibility: hidden;
|
||||
position: absolute;
|
||||
right: -20px;
|
||||
top: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
.remove-task:hover{
|
||||
|
||||
background-color: #ebebeb;
|
||||
}
|
||||
|
||||
.tag {
|
||||
display: inline-block;
|
||||
padding: .2em .6em .3em;
|
||||
|
@ -1,7 +1,6 @@
|
||||
$(document).ready(function () {
|
||||
|
||||
$('a[data-confirm]').click(function (ev) {
|
||||
var href = $(this).attr('href');
|
||||
$('input[data-confirm]').click(function(ev) {
|
||||
var value = $(this).attr('value');
|
||||
if (!$('#dataConfirmModal').length) {
|
||||
$('#modalDelete').append('<div class="modal fade" id="dataConfirmModal" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true"\n' +
|
||||
' >\n' +
|
||||
@ -14,7 +13,7 @@ $(document).ready(function () {
|
||||
' </div>\n' +
|
||||
|
||||
' <div class="modal-footer">\n' +
|
||||
' <a class="btn btn-primary" id="dataConfirmOK">Да</a>' +
|
||||
' <button type="submit" name="deleteConference" class="btn btn-primary" id="deleteConference">Да</button>'+
|
||||
' <button class="btn primary" data-dismiss="modal" aria-hidden="true">Нет</button>'+
|
||||
' </div>\n' +
|
||||
' </div>\n' +
|
||||
@ -22,8 +21,9 @@ $(document).ready(function () {
|
||||
' </div>');
|
||||
}
|
||||
$('#dataConfirmModal').find('#myModalLabel').text($(this).attr('data-confirm'));
|
||||
$('#dataConfirmOK').attr('href', href);
|
||||
$('#deleteConference').attr('value', value);
|
||||
$('#dataConfirmModal').modal({show:true});
|
||||
return false;
|
||||
});
|
||||
|
||||
});
|
||||
|
@ -13,7 +13,8 @@ $(document).ready(function () {
|
||||
});
|
||||
|
||||
$('a[data-confirm]').click(function(ev) {
|
||||
var href = $(this).attr('href');
|
||||
var id = $(this).parent().parent().find('.id-class').val();
|
||||
|
||||
if (!$('#dataConfirmModal').length) {
|
||||
$('#modalDelete').append('<div class="modal fade" id="dataConfirmModal" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true"\n' +
|
||||
' >\n' +
|
||||
@ -34,7 +35,10 @@ $(document).ready(function () {
|
||||
' </div>');
|
||||
}
|
||||
$('#dataConfirmModal').find('#myModalLabel').text($(this).attr('data-confirm'));
|
||||
$('#dataConfirmOK').attr('href', href);
|
||||
$('#dataConfirmOK').click(function () {
|
||||
$("#paperDeleteId").val(id);
|
||||
$('form').submit();
|
||||
});
|
||||
$('#dataConfirmModal').modal({show:true});
|
||||
return false;
|
||||
});
|
||||
|
42
src/main/resources/public/js/projects.js
Normal file
42
src/main/resources/public/js/projects.js
Normal file
@ -0,0 +1,42 @@
|
||||
/*<![CDATA[*/
|
||||
$(document).ready(function () {
|
||||
$(".project-row").mouseenter(function (event) {
|
||||
var projectRow = $(event.target).closest(".project-row");
|
||||
$(projectRow).css("background-color", "#f8f9fa");
|
||||
$(projectRow).find(".remove-paper").removeClass("d-none");
|
||||
|
||||
});
|
||||
$(".project-row").mouseleave(function (event) {
|
||||
var projectRow = $(event.target).closest(".project-row");
|
||||
$(projectRow).css("background-color", "white");
|
||||
$(projectRow).find(".remove-paper").addClass("d-none");
|
||||
});
|
||||
|
||||
$('a[data-confirm]').click(function(ev) {
|
||||
var href = $(this).attr('href');
|
||||
if (!$('#dataConfirmModal').length) {
|
||||
$('#modalDelete').append('<div class="modal fade" id="dataConfirmModal" tabindex="-1" role="dialog" aria-labelledby="mySmallModalLabel" aria-hidden="true"\n' +
|
||||
' >\n' +
|
||||
' <div class="modal-dialog modal-sm">\n' +
|
||||
' <div class="modal-content">\n' +
|
||||
' <div class="modal-header">\n' +
|
||||
' <h8 class="modal-title" id="myModalLabel">Удалить проект?</h8>\n' +
|
||||
' <button type="button" class="close" data-dismiss="modal" aria-label="Закрыть"><span\n' +
|
||||
' aria-hidden="true">×</span></button>\n' +
|
||||
' </div>\n' +
|
||||
|
||||
' <div class="modal-footer">\n' +
|
||||
' <a class="btn btn-primary" id="dataConfirmOK">Да</a>'+
|
||||
' <button class="btn primary" data-dismiss="modal" aria-hidden="true">Нет</button>'+
|
||||
' </div>\n' +
|
||||
' </div>\n' +
|
||||
' </div>\n' +
|
||||
' </div>');
|
||||
}
|
||||
$('#dataConfirmModal').find('#myModalLabel').text($(this).attr('data-confirm'));
|
||||
$('#dataConfirmOK').attr('href', href);
|
||||
$('#dataConfirmModal').modal({show:true});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
/*]]>*/
|
@ -70,17 +70,17 @@ $(document).ready(function () {
|
||||
});
|
||||
|
||||
$("span[data-role=remove]").click(removeTag);
|
||||
$(".task-row").mouseenter(function (event) {
|
||||
var taskRow = $(event.target).closest(".task-row");
|
||||
$(taskRow).css("background-color", "#f8f9fa");
|
||||
$(taskRow).find(".remove-task").removeClass("d-none");
|
||||
|
||||
});
|
||||
$(".task-row").mouseleave(function (event) {
|
||||
var taskRow = $(event.target).closest(".task-row");
|
||||
$(taskRow).css("background-color", "white");
|
||||
$(taskRow).closest(".task-row").find(".remove-task").addClass("d-none");
|
||||
});
|
||||
// $(".task-row").mouseenter(function (event) {
|
||||
// var taskRow = $(event.target).closest(".task-row");
|
||||
// $(taskRow).css("background-color", "#f8f9fa");
|
||||
// $(taskRow).find(".remove-task").removeClass("d-none");
|
||||
//
|
||||
// });
|
||||
// $(".task-row").mouseleave(function (event) {
|
||||
// var taskRow = $(event.target).closest(".task-row");
|
||||
// $(taskRow).css("background-color", "white");
|
||||
// $(taskRow).closest(".task-row").find(".remove-task").addClass("d-none");
|
||||
// });
|
||||
|
||||
$('a[data-confirm]').click(function(ev) {
|
||||
var href = $(this).attr('href');
|
||||
@ -90,7 +90,7 @@ $(document).ready(function () {
|
||||
' <div class="modal-dialog modal-sm">\n' +
|
||||
' <div class="modal-content">\n' +
|
||||
' <div class="modal-header">\n' +
|
||||
' <h8 class="modal-title" id="myModalLabel">Удалить статью?</h8>\n' +
|
||||
' <h8 class="modal-title" id="myModalLabel">Удалить задачу?</h8>\n' +
|
||||
' <button type="button" class="close" data-dismiss="modal" aria-label="Закрыть"><span\n' +
|
||||
' aria-hidden="true">×</span></button>\n' +
|
||||
' </div>\n' +
|
||||
|
@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}" xmlns:th="">
|
||||
layout:decorator="default" xmlns:th="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/html">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="../css/conference.css"/>
|
||||
</head>
|
||||
@ -30,10 +30,11 @@
|
||||
<label for="title">Название:</label>
|
||||
<input class="form-control" th:field="*{title}" id="title" type="text"
|
||||
placeholder="Название конференции"/>
|
||||
</div>
|
||||
|
||||
<p th:if="${#fields.hasErrors('title')}" th:errors="*{title}"
|
||||
class="alert alert-danger">Incorrect title</p>
|
||||
<p class="help-block text-danger"></p>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label for="url">URL:</label>
|
||||
@ -121,7 +122,11 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group d-flex justify-content-end">
|
||||
<div class="form-group d-flex justify-content-between flex-wrap">
|
||||
<!--<input type="hidden" th:value="*{ping}" th:name="ping"/>-->
|
||||
<input id="ping-button" class="btn btn-primary"
|
||||
type="submit" name="pingConference" value="Ping участникам"
|
||||
th:disabled="*{id == null ? 'true' : 'false'}"/>
|
||||
<input type="hidden" th:value="*{disabledTakePart}" th:name="disabledTakePart"/>
|
||||
<input id="take-part" class="btn btn-primary"
|
||||
type="submit" name="takePart" value="Принять участие"
|
||||
@ -131,15 +136,25 @@
|
||||
<div class="form-group">
|
||||
<label for="papers">Статьи:</label>
|
||||
<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"
|
||||
th:each="paper, rowStat : *{papers}">
|
||||
<input type="hidden" th:field="*{papers[__${rowStat.index}__].id}"/>
|
||||
<input type="hidden" th:field="*{papers[__${rowStat.index}__].title}"/>
|
||||
<input type="hidden" th:field="*{papers[__${rowStat.index}__].status}"/>
|
||||
<a class="paper-name"
|
||||
th:href="@{'/papers/paper?id=' + *{papers[__${rowStat.index}__].id} + ''}">
|
||||
th:href="@{'/papers/paper?id=' + *{papers[__${rowStat.index}__].id} + ''}"
|
||||
th:if="*{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>
|
||||
</a>
|
||||
<a class="paper-name"
|
||||
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>
|
||||
<img class="icon-paper" src="/img/conference/paper.png"/>
|
||||
</a>
|
||||
<input type="submit" class="icon icon-delete grey-border"
|
||||
alt="Удалить" name="removePaper" th:value="${rowStat.index}"/>
|
||||
@ -156,7 +171,7 @@
|
||||
</option>
|
||||
</select>
|
||||
<button id="add-paper" class="btn btn-primary"
|
||||
type="button">
|
||||
type="submit" name="addPaper">
|
||||
Добавить статью
|
||||
</button>
|
||||
</div>
|
||||
|
@ -8,7 +8,9 @@
|
||||
<body>
|
||||
|
||||
<div layout:fragment="content">
|
||||
<form id="conferences-form" method="post" th:action="@{'/conferences/conferences'}">
|
||||
<form id="conferences-form" method="post" th:action="@{'/conferences/conferences'}"
|
||||
th:object="${filteredConferences}">
|
||||
|
||||
<section id="conferences">
|
||||
<div class="container">
|
||||
<div class="row" id="conference-list">
|
||||
@ -18,9 +20,12 @@
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="alert alert-danger" th:if="${#fields.hasErrors('*')}">
|
||||
<p th:each="err : ${#fields.errors('*')}" th:text="${err}"></p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-9 col-sm-12">
|
||||
<th:block th:each="conference : ${filteredConferences.conferences}">
|
||||
<th:block th:each="conference : *{conferences}">
|
||||
<div th:replace="conferences/fragments/confLineFragment :: confLine(conference=${conference})"/>
|
||||
</th:block>
|
||||
</div>
|
||||
|
@ -4,6 +4,7 @@
|
||||
layout:decorator="default" xmlns:th="">
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="../css/conference.css"/>
|
||||
<script src="https://code.highcharts.com/highcharts.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<div layout:fragment="content">
|
||||
@ -21,8 +22,127 @@
|
||||
<div th:replace="conferences/fragments/confDashboardFragment :: confDashboard(conference=${conference})"/>
|
||||
</th:block>
|
||||
</div>
|
||||
<hr/>
|
||||
<!--chart example-->
|
||||
<nav>
|
||||
<div class="nav nav-tabs" id="nav-tab" role="tablist">
|
||||
<a class="nav-item nav-link active" id="nav-main-tab" data-toggle="tab"
|
||||
href="#nav-stat1" role="tab" aria-controls="nav-stat1" aria-selected="true">Стат1</a>
|
||||
<a class="nav-item nav-link" id="nav-latex-tab" data-toggle="tab"
|
||||
href="#nav-stat2" role="tab" aria-controls="nav-stat2" aria-selected="false">Стат2</a>
|
||||
</div>
|
||||
</nav>
|
||||
<div class="tab-content" id="nav-tabContent">
|
||||
<div class="tab-pane fade show active" id="nav-stat1" role="tabpanel"
|
||||
aria-labelledby="nav-main-tab">
|
||||
<div id="salesByType" style="width:100%; height:400px;"></div>
|
||||
</div>
|
||||
<div class="tab-pane fade" id="nav-stat2" role="tabpanel"
|
||||
aria-labelledby="nav-profile-tab">
|
||||
<div id="salesByRegion" style="width:100%; height:400px;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!--chart example-->
|
||||
</div>
|
||||
</section>
|
||||
<script th:inline="javascript">
|
||||
/*<![CDATA[*/
|
||||
|
||||
// chart example
|
||||
$(function () {
|
||||
Highcharts.setOptions({
|
||||
lang: {
|
||||
decimalPoint: '.',
|
||||
thousandsSep: ','
|
||||
}
|
||||
});
|
||||
|
||||
drawSalesByTypeChart();
|
||||
drawSalesByRegionChart();
|
||||
});
|
||||
|
||||
|
||||
function drawSalesByRegionChart() {
|
||||
var salesByRegionChart = Highcharts.chart('salesByRegion', {
|
||||
chart: {
|
||||
type: 'pie',
|
||||
margin: 40
|
||||
},
|
||||
title: {
|
||||
text: 'Sales by Region'
|
||||
},
|
||||
tooltip: {
|
||||
pointFormat: "${point.y:,.0f}"
|
||||
},
|
||||
plotOptions: {
|
||||
pie: {
|
||||
allowPointSelect: true,
|
||||
depth: 35
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: 'Regions',
|
||||
colorByPoint:true,
|
||||
data: [{
|
||||
name: 'Northeast',
|
||||
y: /*[[${northeastSales}]]*/ 0
|
||||
},{
|
||||
name: 'South',
|
||||
y: /*[[${southSales}]]*/ 0
|
||||
},{
|
||||
name: 'Midwest',
|
||||
y: /*[[${midwestSales}]]*/ 0
|
||||
},{
|
||||
name: 'West',
|
||||
y: /*[[${westSales}]]*/ 0
|
||||
}]
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
function drawSalesByTypeChart() {
|
||||
var salesByTypeChart = Highcharts.chart('salesByType', {
|
||||
chart: {
|
||||
type: 'column',
|
||||
margin: 75
|
||||
},
|
||||
title: {
|
||||
text: 'Sales by Lure Type'
|
||||
},
|
||||
xAxis: {
|
||||
categories: ['May', 'June', 'July']
|
||||
},
|
||||
yAxis: {
|
||||
title: {
|
||||
text: 'Sales (US $)'
|
||||
}
|
||||
},
|
||||
tooltip: {
|
||||
pointFormat: "${point.y:,.0f}"
|
||||
},
|
||||
plotOptions: {
|
||||
column: {
|
||||
depth: 60,
|
||||
stacking: true,
|
||||
grouping: false,
|
||||
groupZPadding: 10
|
||||
}
|
||||
},
|
||||
series: [{
|
||||
name: 'Inshore',
|
||||
data: /*[[${inshoreSales}]]*/ []
|
||||
}, {
|
||||
name: 'Nearshore',
|
||||
data: /*[[${nearshoreSales}]]*/ []
|
||||
}, {
|
||||
name: 'Offshore',
|
||||
data: /*[[${offshoreSales}]]*/ []
|
||||
}]
|
||||
});
|
||||
}
|
||||
/*]]>*/
|
||||
|
||||
</script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
@ -4,12 +4,13 @@
|
||||
<meta charset="UTF-8"/>
|
||||
</head>
|
||||
<body>
|
||||
<div th:fragment="confDashboard (conference)" class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 dashboard-card">
|
||||
<div th:fragment="confDashboard (conference)" th:class="@{'col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 dashboard-card ' +
|
||||
${conference.ping == 0 ? '' :
|
||||
conference.ping < 5 ? 'note-1' :
|
||||
conference.ping < 10 ? 'note-2' :
|
||||
conference.ping < 15 ? 'note-3' : 'note-4'} + ''}">
|
||||
<div class="row">
|
||||
<div class="col-2">
|
||||
|
||||
</div>
|
||||
<div class="col col-10 text-right">
|
||||
<div class="col text-right">
|
||||
<p th:if="${conference.url!=null and conference.url!=''}"><a target="_blank" th:href="${conference.url}"><i
|
||||
class="fa fa-external-link fa-1x"
|
||||
aria-hidden="true"></i></a></p>
|
||||
|
@ -5,16 +5,15 @@
|
||||
</head>
|
||||
<body>
|
||||
<div th:fragment="confLine (conference)" class="row text-left conference-row h3" style="background-color: white;">
|
||||
<div class="col d-flex justify-content-between">
|
||||
<div class="d-flex justify-content-between w-100">
|
||||
<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}"/>
|
||||
</a>
|
||||
<input class="id-class" type="hidden" th:value="${conference.id}"/>
|
||||
<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>
|
||||
<input type="submit" class="icon icon-delete grey-border"
|
||||
alt="Удалить" th:value="${conference.id}"
|
||||
data-confirm="Удалить конференцию?"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -21,7 +21,7 @@
|
||||
<div class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3">
|
||||
<a href="./conference?id=0" class="btn btn-light toolbar-button">
|
||||
<i class="fa fa-plus-circle" aria-hidden="true"></i>
|
||||
Новая конференцию</a>
|
||||
Новая конференция</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
@ -55,7 +55,8 @@
|
||||
<a class="nav-link js-scroll-trigger" target="_blank" href="http://is.ulstu.ru">Сайт кафедры</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link js-scroll-trigger" target="_blank" th:href="@{'http://timetable.athene.tech?filter='+${currentUser}}">Расписание</a>
|
||||
<a class="nav-link js-scroll-trigger" target="_blank"
|
||||
th:href="@{'http://timetable.athene.tech?filter='+${currentUser}}">Расписание</a>
|
||||
</li>
|
||||
<li class="nav-item">
|
||||
<a class="nav-link js-scroll-trigger" target="_blank" href="https://kias.rfbr.ru/">КИАС РФФИ</a>
|
||||
@ -103,6 +104,17 @@
|
||||
<script src="/js/core.js"></script>
|
||||
<script src="/js/config.js"></script>
|
||||
<script src="/js/odin.js"></script>
|
||||
<script th:inline="javascript">
|
||||
|
||||
/*<![CDATA[*/
|
||||
var message = /*[[${flashMessage}]]*/ "";
|
||||
if (message && message.length > 0) {
|
||||
showFeedbackMessage(message, MessageTypesEnum.DANGER);
|
||||
}
|
||||
/*]]>*/
|
||||
|
||||
|
||||
</script>
|
||||
<th:block layout:fragment="scripts">
|
||||
</th:block>
|
||||
<!-- Yandex.Metrika counter -->
|
||||
@ -117,22 +129,29 @@
|
||||
accurateTrackBounce: true,
|
||||
webvisor: true
|
||||
});
|
||||
} catch(e) { }
|
||||
} catch (e) {
|
||||
}
|
||||
});
|
||||
|
||||
var n = d.getElementsByTagName("script")[0],
|
||||
s = d.createElement("script"),
|
||||
f = function () { n.parentNode.insertBefore(s, n); };
|
||||
f = function () {
|
||||
n.parentNode.insertBefore(s, n);
|
||||
};
|
||||
s.type = "text/javascript";
|
||||
s.async = true;
|
||||
s.src = "https://mc.yandex.ru/metrika/tag.js";
|
||||
|
||||
if (w.opera == "[object Opera]") {
|
||||
d.addEventListener("DOMContentLoaded", f, false);
|
||||
} else { f(); }
|
||||
} else {
|
||||
f();
|
||||
}
|
||||
})(document, window, "yandex_metrika_callbacks2");
|
||||
</script>
|
||||
<noscript><div><img src="https://mc.yandex.ru/watch/49387279" style="position:absolute; left:-9999px;" alt="" /></div></noscript>
|
||||
<noscript>
|
||||
<div><img src="https://mc.yandex.ru/watch/49387279" style="position:absolute; left:-9999px;" alt=""/></div>
|
||||
</noscript>
|
||||
<!-- /Yandex.Metrika counter -->
|
||||
</body>
|
||||
</html>
|
||||
|
@ -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>
|
@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en"
|
||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||
layout:decorate="~{default}" xmlns:th="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/html">
|
||||
layout:decorator="default" xmlns:th="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/html">
|
||||
<head>
|
||||
<link rel="stylesheet" href="../css/grant.css"/>
|
||||
</head>
|
||||
@ -48,6 +48,7 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Дедлайны показателей:</label>
|
||||
<input type="hidden" th:field="*{removedDeadlineIds}"/>
|
||||
<div class="row" th:each="deadline, rowStat : *{deadlines}">
|
||||
<input type="hidden" th:field="*{deadlines[__${rowStat.index}__].id}"/>
|
||||
<div class="col-6 div-deadline-date">
|
||||
@ -59,11 +60,14 @@
|
||||
th:field="*{deadlines[__${rowStat.index}__].description}"/>
|
||||
</div>
|
||||
<div class="col-2">
|
||||
<a class="btn btn-danger float-right"
|
||||
th:onclick="|$('#deadlines${rowStat.index}\\.description').val('');
|
||||
$('#deadlines${rowStat.index}\\.date').val('');
|
||||
$('#addDeadline').click();|"><span><i class="fa fa-times" aria-hidden="true"></i></span>
|
||||
</a>
|
||||
<button type="submit"
|
||||
class="btn btn-danger float-right btn-delete-deadline"
|
||||
id="removeDeadline" name="removeDeadline"
|
||||
th:value="${rowStat.index}">
|
||||
<span aria-hidden="true">
|
||||
<i class="fa fa-times"/>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<p th:if="${#fields.hasErrors('deadlines')}" th:errors="*{deadlines}"
|
||||
@ -73,12 +77,14 @@
|
||||
<input type="submit" id="addDeadline" name="addDeadline" class="btn btn-primary"
|
||||
value="Добавить дедлайн"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="loader">Загрузить заявку:</label>
|
||||
<div class="form-group div-loader">
|
||||
<label for="loader">Загрузить файлы:</label>
|
||||
<div id="loader">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" id="files-list">
|
||||
<div th:replace="grants/fragments/grantFilesListFragment :: filesList(isLatexAttach = ${false})"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6 col-sm-12">
|
||||
<label data-toggle="collapse"
|
||||
@ -86,7 +92,8 @@
|
||||
aria-expanded="false"
|
||||
aria-controls="collapse-filter">Фильтр рабочей группы
|
||||
</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">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
@ -107,14 +114,16 @@
|
||||
<label class="form-check-label" for="f3">Cтепень к.т.н.</label>
|
||||
</div>
|
||||
<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-х публикаций в
|
||||
scopus</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<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/>
|
||||
</div>
|
||||
<div class="col">
|
||||
@ -143,9 +152,9 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Участники гранта:</label>
|
||||
<select class="selectpicker form-control" multiple="true"
|
||||
<select class="selectpicker form-control" multiple="true" data-live-search="true"
|
||||
title="-- Выберите участников --" id="authors"
|
||||
th:field="*{authorIds}">
|
||||
th:field="*{authorIds}" data-size="5">
|
||||
<option th:each="author : ${allAuthors}" th:value="${author.id}"
|
||||
th:text="${author.lastName}"> Участник
|
||||
</option>
|
||||
@ -153,9 +162,74 @@
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Список статей:</label>
|
||||
<p><a href="./#" class="btn btn-primary"><i class="fa fa-plus-circle"
|
||||
aria-hidden="true">
|
||||
</i> Добавить статью</a></p>
|
||||
<div class="row">
|
||||
<div class="col-8">
|
||||
<select class="selectpicker form-control" multiple="true"
|
||||
data-live-search="true"
|
||||
title="Прикрепить статью" id="allPapers"
|
||||
th:field="*{paperIds}" data-size="5">
|
||||
<option th:each="paper : ${allPapers}" th:value="${paper.id}"
|
||||
th:text="${paper.title}">Статья для прикрепления
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-4 div-view-paper">
|
||||
<a th:onclick="|$('#attachPaper').click();|">
|
||||
<span aria-hidden="true">
|
||||
<label>Отобразить</label>
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<input type="submit" hidden="hidden" id="attachPaper" name="attachPaper"
|
||||
value="Отобразить прикрепленную статью"/>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="form-control list-group div-selected-papers" id="selected-papers">
|
||||
<div th:each="paper, rowStat : *{papers}">
|
||||
<input type="hidden" th:field="*{papers[__${rowStat.index}__].id}"/>
|
||||
<div class="col">
|
||||
<a th:href="@{'/papers/paper?id=' + *{papers[__${rowStat.index}__].id} + ''}">
|
||||
<img class="icon-paper" src="/img/conference/paper.png"/>
|
||||
<span th:text="*{papers[__${rowStat.index}__].title}">
|
||||
Название статьи
|
||||
</span>
|
||||
</a>
|
||||
</div>
|
||||
<div class="col">
|
||||
<label>Статус: </label>
|
||||
<span th:text="*{papers[__${rowStat.index}__].status.statusName}">
|
||||
Статус статьи
|
||||
</span>
|
||||
</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 class="form-group">
|
||||
<div th:if="*{project} == null">
|
||||
@ -190,18 +264,100 @@
|
||||
new FileLoader({
|
||||
div: "loader",
|
||||
url: urlFileUpload,
|
||||
maxSize: 1.5,
|
||||
extensions: ["doc", "docx", "xls", "jpg", "pdf", "txt", "png"],
|
||||
maxSize: -1,
|
||||
extensions: [],
|
||||
callback: function (response) {
|
||||
showFeedbackMessage("Файл успешно загружен");
|
||||
console.debug(response);
|
||||
addNewFile(response);
|
||||
}
|
||||
});
|
||||
$('.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 type="text/javascript">
|
||||
function updateAuthors() {
|
||||
|
@ -12,8 +12,7 @@
|
||||
<span class="text-muted" th:text="${paper.authorsString}"/>
|
||||
</a>
|
||||
<input class="id-class" type="hidden" th:value="${paper.id}"/>
|
||||
<a class="remove-paper pull-right d-none" th:href="@{'/papers/delete/'+${paper.id}}"
|
||||
data-confirm="Удалить статью?">
|
||||
<a class="remove-paper pull-right d-none" href="#" data-confirm="Удалить статью?">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
|
@ -7,7 +7,8 @@
|
||||
<body>
|
||||
|
||||
<div class="container" layout:fragment="content">
|
||||
<form id="papers-form" method="post" th:action="@{'/papers/papers'}">
|
||||
<form id="papers-form" method="post" th:action="@{'/papers/papers'}"
|
||||
th:object="${filteredPapers}">
|
||||
<input th:type="hidden" name="paperDeleteId" id="paperDeleteId"/>
|
||||
<section id="papers">
|
||||
<div class="container">
|
||||
@ -17,7 +18,11 @@
|
||||
<div th:replace="papers/fragments/paperNavigationFragment"/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="alert alert-danger" th:if="${#fields.hasErrors('*')}">
|
||||
<p th:each="err : ${#fields.errors('*')}" th:text="${err}"></p>
|
||||
</div>
|
||||
<div class="col-md-9 col-sm-12">
|
||||
<th:block th:each="paper : ${filteredPapers.papers}">
|
||||
<div th:replace="papers/fragments/paperLineFragment :: paperLine(paper=${paper})"/>
|
||||
@ -43,7 +48,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:replace="fragments/noRecordsFragment :: noRecords(entities=${filteredPapers.papers}, noRecordsMessage=' одной статьи', url='paper')"/>
|
||||
<!--<div th:replace="fragments/noRecordsFragment :: noRecords(entities=${filteredPapers.papers}, noRecordsMessage=' одной статьи', url='paper')"/>-->
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
@ -11,7 +11,6 @@
|
||||
</div>
|
||||
<div class="col col-10 text-right">
|
||||
<h7 class="service-heading" th:text="${project.title}"> title</h7>
|
||||
<p class="text-muted" th:text="${project.status.statusName}"> status</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -12,6 +12,10 @@
|
||||
<span class="text-muted" th:text="${project.description}"/>
|
||||
</a>
|
||||
<input class="id-class" type="hidden" th:value="${project.id}"/>
|
||||
<a class="remove-paper pull-right d-none" th:href="@{'/projects/delete/'+${project.id}}"
|
||||
data-confirm="Удалить проект?">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<meta charset="UTF-8"/>
|
||||
</head>
|
||||
<body>
|
||||
<span th:fragment="paperStatus (paperStatus)" class="fa-stack fa-1x">
|
||||
<span th:fragment="projectStatus (projectStatus)" class="fa-stack fa-1x">
|
||||
<th:block th:switch="${projectStatus.name()}">
|
||||
<div th:case="'APPLICATION'">
|
||||
<i class="fa fa-circle fa-stack-2x text-draft"></i>
|
||||
|
@ -27,7 +27,9 @@
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<div id="modalDelete"/>
|
||||
</form>
|
||||
<script src="/js/projects.js"></script>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -14,10 +14,10 @@
|
||||
</div>
|
||||
<hr/>
|
||||
<div class="row justify-content-center" id="dashboard">
|
||||
<div th:replace="students/fragments/taskDashboardFragment"/>
|
||||
<!--<th:block th:each="task : ${tasks}">-->
|
||||
<!--<div th:replace="students/fragments/taskDashboardFragment :: taskDashboard(task=${task})"/>-->
|
||||
<!--</th:block>-->
|
||||
<th:block th:each="task : ${tasks}">
|
||||
<div th:replace="students/fragments/taskDashboardFragment :: taskDashboard(task=${task})"/>
|
||||
</th:block>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
@ -6,16 +6,16 @@
|
||||
<body>
|
||||
<div th:fragment="taskLine (task)" class="row text-left task-row" style="background-color: white;">
|
||||
<div class="col">
|
||||
<span th:replace="students/fragments/taskStatusFragment :: taskStatus(taskStatus=${task.status})"/>
|
||||
<a th:href="@{'task?id='+${task.id}}">
|
||||
<span th:replace="students/fragments/taskStatusFragment :: taskStatus(taskStatus=${task.status})"/>
|
||||
<span class="h6" th:text="${task.title}"></span>
|
||||
<span class="text-muted" th:text="${task.tagsString}"/>
|
||||
</a>
|
||||
<input class="id-class" type="hidden" th:value="${task.id}"/>
|
||||
<a class="remove-task pull-right d-none" th:href="@{'/students/delete/'+${task.id}}"
|
||||
<a class="remove-task pull-right" th:href="@{'/students/delete/'+${task.id}}"
|
||||
data-confirm="Удалить задачу?">
|
||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||
</a>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
@ -6,9 +6,6 @@
|
||||
<body>
|
||||
<span th:fragment="taskStatus (taskStatus)" class="fa-stack fa-1x">
|
||||
<th:block th:switch="${taskStatus.name()}">
|
||||
<!--<div th:case="'ATTENTION'">-->
|
||||
<!--<i class="fa fa-circle fa-stack-2x text-warning"></i>-->
|
||||
<!--</div>-->
|
||||
<div th:case="'IN_WORK'">
|
||||
<i class="fa fa-circle fa-stack-2x text-primary"></i>
|
||||
</div>
|
||||
|
@ -7,7 +7,7 @@
|
||||
|
||||
<body>
|
||||
<div class="container" layout:fragment="content">
|
||||
<form id="tasks-form" method="post" th:action="@{'/tasks/tasks'}">
|
||||
<form id="tasks-form" method="post" th:action="@{'/students/tasks'}">
|
||||
<input th:type="hidden" name="taskDeleteId" id="taskDeleteId"/>
|
||||
<section id="tasks">
|
||||
<div class="container">
|
||||
@ -20,26 +20,42 @@
|
||||
<hr/>
|
||||
<div class="row">
|
||||
<div class="col-md-9 col-sm-12">
|
||||
<th:block th:each="task : ${tasks}">
|
||||
<th:block th:each="task : ${filteredTasks.tasks}">
|
||||
<div th:replace="students/fragments/taskLineFragment :: taskLine(task=${task})"/>
|
||||
</th:block>
|
||||
</div>
|
||||
<div class="col-md-3 col-sm-12">
|
||||
<div class="sorting">
|
||||
<h5>Сортировать:</h5>
|
||||
<select class="form-control selectpicker" size="auto" th:field="${filteredTasks.order}"
|
||||
id="order"
|
||||
onchange="this.form.submit();">
|
||||
<option th:value="new">
|
||||
Сначала новые
|
||||
</option>
|
||||
<option th:value="old">
|
||||
Сначала старые
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="filter">
|
||||
<h5>Фильтр:</h5>
|
||||
<select class="form-control" id="status"
|
||||
<select class="form-control selectpicker" size="auto" th:field="${filteredTasks.status}"
|
||||
id="status"
|
||||
onchange="this.form.submit();">
|
||||
<option value="">Все статусы</option>
|
||||
<!--<option th:each="author: ${allAuthors}" th:value="${author.id}"-->
|
||||
<!--th:text="${author.lastName}">lastName-->
|
||||
<!--</option>-->
|
||||
<option th:each="status: ${allStatuses}" th:value="${status}"
|
||||
th:text="${status.statusName}">
|
||||
status
|
||||
</option>
|
||||
</select>
|
||||
<select class="form-control" id="tags"
|
||||
<select class="form-control selectpicker" size="auto" data-live-search="true"
|
||||
th:field="${filteredTasks.tag}" id="tags"
|
||||
onchange="this.form.submit();">
|
||||
<option value="">Все типы</option>
|
||||
<!--<option th:each="year: ${allYears}" th:value="${year}"-->
|
||||
<!--th:text="${year}">year-->
|
||||
<!--</option>-->
|
||||
<option value="">Все теги</option>
|
||||
<option th:each="tag: ${allTags}" th:value="${tag.id}"
|
||||
th:text="${tag.tagName}">tag
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
230
src/test/java/IndexConferenceTest.java
Normal file
230
src/test/java/IndexConferenceTest.java
Normal file
@ -0,0 +1,230 @@
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import conference.ConferencePage;
|
||||
import conference.ConferencesDashboardPage;
|
||||
import conference.ConferencesPage;
|
||||
import core.PageObject;
|
||||
import core.TestTemplate;
|
||||
import org.junit.Assert;
|
||||
import org.junit.FixMethodOrder;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.junit.runners.MethodSorters;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebElement;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import ru.ulstu.NgTrackerApplication;
|
||||
import ru.ulstu.configuration.ApplicationProperties;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RunWith(SpringRunner.class)
|
||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||
@SpringBootTest(classes = NgTrackerApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
|
||||
public class IndexConferenceTest extends TestTemplate {
|
||||
private final Map<PageObject, List<String>> navigationHolder = ImmutableMap.of(
|
||||
new ConferencesPage(), Arrays.asList("КОНФЕРЕНЦИИ", "/conferences/conferences"),
|
||||
new ConferencePage(), Arrays.asList("РЕДАКТИРОВАНИЕ КОНФЕРЕНЦИИ", "/conferences/conference?id=0"),
|
||||
new ConferencesDashboardPage(), Arrays.asList("АКТУАЛЬНЫЕ КОНФЕРЕНЦИИ", "/conferences/dashboard")
|
||||
);
|
||||
|
||||
@Autowired
|
||||
private ApplicationProperties applicationProperties;
|
||||
|
||||
@Test
|
||||
public void testACreateNewConference() {
|
||||
Map.Entry<PageObject, List<String>> page = Iterables.get(navigationHolder.entrySet(), 1);
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + page.getValue().get(1));
|
||||
ConferencePage conferencePage = (ConferencePage) getContext().initPage(page.getKey());
|
||||
ConferencesPage conferencesPage = (ConferencesPage) getContext().initPage(Iterables.get(navigationHolder.entrySet(), 0).getKey());
|
||||
|
||||
String newConferenceName = "test " + (new Date()).getTime();
|
||||
conferencePage.setName(newConferenceName);
|
||||
conferencePage.clickSaveBut();
|
||||
|
||||
Assert.assertTrue(conferencesPage.checkNameInList(newConferenceName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBChangeConferenceNameAndSave() {
|
||||
Map.Entry<PageObject, List<String>> page = Iterables.get(navigationHolder.entrySet(), 0);
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + page.getValue().get(1));
|
||||
ConferencesPage conferencesPage = (ConferencesPage) getContext().initPage(page.getKey());
|
||||
ConferencePage conferencePage = (ConferencePage) getContext().initPage(Iterables.get(navigationHolder.entrySet(), 1).getKey());
|
||||
|
||||
conferencesPage.getFirstConference();
|
||||
String newConferenceName = "test " + (new Date()).getTime();
|
||||
conferencePage.clearName();
|
||||
conferencePage.setName(newConferenceName);
|
||||
conferencePage.clickSaveBut();
|
||||
|
||||
Assert.assertTrue(conferencesPage.checkNameInList(newConferenceName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCAddDeadlineAndSave() {
|
||||
Map.Entry<PageObject, List<String>> page = Iterables.get(navigationHolder.entrySet(), 0);
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + page.getValue().get(1));
|
||||
ConferencesPage conferencesPage = (ConferencesPage) getContext().initPage(page.getKey());
|
||||
ConferencePage conferencePage = (ConferencePage) getContext().initPage(Iterables.get(navigationHolder.entrySet(), 1).getKey());
|
||||
|
||||
conferencesPage.getFirstConference();
|
||||
String conferenceId = conferencePage.getId();
|
||||
Integer deadlineCount = conferencePage.getDeadlineCount();
|
||||
|
||||
String description = "test";
|
||||
String date = "09.09.2019";
|
||||
String dateValue = "2019-09-09";
|
||||
conferencePage.clickAddDeadlineBut();
|
||||
conferencePage.setDeadlineDescription(description, deadlineCount);
|
||||
conferencePage.setDeadlineDate(date, deadlineCount);
|
||||
conferencePage.clickSaveBut();
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + String.format("/conferences/conference?id=%s", conferenceId));
|
||||
|
||||
Assert.assertTrue(conferencePage.checkDeadline(description, dateValue));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDTakePartAndSave() {
|
||||
Map.Entry<PageObject, List<String>> page = Iterables.get(navigationHolder.entrySet(), 0);
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + page.getValue().get(1));
|
||||
ConferencesPage conferencesPage = (ConferencesPage) getContext().initPage(page.getKey());
|
||||
ConferencePage conferencePage = (ConferencePage) getContext().initPage(Iterables.get(navigationHolder.entrySet(), 1).getKey());
|
||||
|
||||
conferencesPage.getFirstConference();
|
||||
String conferenceId = conferencePage.getId();
|
||||
Integer membersCount = conferencePage.getMemberCount();
|
||||
|
||||
conferencePage.clickTakePartBut();
|
||||
conferencePage.clickSaveBut();
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + String.format("/conferences/conference?id=%s", conferenceId));
|
||||
|
||||
Assert.assertTrue(membersCount + 1 == conferencePage.getMemberCount()
|
||||
&& conferencePage.isTakePartButDisabledValueTrue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEDeleteDeadlineAndSave() {
|
||||
Map.Entry<PageObject, List<String>> page = Iterables.get(navigationHolder.entrySet(), 0);
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + page.getValue().get(1));
|
||||
ConferencesPage conferencesPage = (ConferencesPage) getContext().initPage(page.getKey());
|
||||
ConferencePage conferencePage = (ConferencePage) getContext().initPage(Iterables.get(navigationHolder.entrySet(), 1).getKey());
|
||||
|
||||
conferencesPage.getFirstConference();
|
||||
String conferenceId = conferencePage.getId();
|
||||
Integer deadlineCount = conferencePage.getDeadlineCount();
|
||||
|
||||
conferencePage.clickDeleteDeadlineBut();
|
||||
conferencePage.clickSaveBut();
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + String.format("/conferences/conference?id=%s", conferenceId));
|
||||
|
||||
Assert.assertEquals(deadlineCount - 1, (int) conferencePage.getDeadlineCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFAttachArticle() {
|
||||
Map.Entry<PageObject, List<String>> page = Iterables.get(navigationHolder.entrySet(), 0);
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + page.getValue().get(1));
|
||||
ConferencesPage conferencesPage = (ConferencesPage) getContext().initPage(page.getKey());
|
||||
ConferencePage conferencePage = (ConferencePage) getContext().initPage(Iterables.get(navigationHolder.entrySet(), 1).getKey());
|
||||
|
||||
conferencesPage.getFirstConference();
|
||||
String conferenceId = conferencePage.getId();
|
||||
Integer paperCount = conferencePage.getArticlesCount();
|
||||
|
||||
conferencePage.showAllowToAttachArticles();
|
||||
WebElement paper = conferencePage.selectArticle();
|
||||
String paperName = paper.findElement(By.className("text")).getText();
|
||||
conferencePage.clickSaveBut();
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + String.format("/conferences/conference?id=%s", conferenceId));
|
||||
|
||||
Assert.assertTrue(paperCount + 1 == conferencePage.getArticlesCount()
|
||||
&& conferencePage.checkArticle(paperName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGAddArticle() {
|
||||
Map.Entry<PageObject, List<String>> page = Iterables.get(navigationHolder.entrySet(), 0);
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + page.getValue().get(1));
|
||||
ConferencesPage conferencesPage = (ConferencesPage) getContext().initPage(page.getKey());
|
||||
ConferencePage conferencePage = (ConferencePage) getContext().initPage(Iterables.get(navigationHolder.entrySet(), 1).getKey());
|
||||
|
||||
conferencesPage.getFirstConference();
|
||||
String conferenceId = conferencePage.getId();
|
||||
Integer paperCount = conferencePage.getArticlesCount();
|
||||
|
||||
conferencePage.clickAddPaperBut();
|
||||
List<WebElement> webElements = conferencePage.getArticles();
|
||||
String paperName = webElements.get(webElements.size() - 1).findElements(By.tagName("input")).get(1).getAttribute("value");
|
||||
conferencePage.clickSaveBut();
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + String.format("/conferences/conference?id=%s", conferenceId));
|
||||
|
||||
Assert.assertTrue(paperCount + 1 == conferencePage.getArticlesCount()
|
||||
&& conferencePage.checkArticle(paperName));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHUndockArticle() {
|
||||
Map.Entry<PageObject, List<String>> page = Iterables.get(navigationHolder.entrySet(), 0);
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + page.getValue().get(1));
|
||||
ConferencesPage conferencesPage = (ConferencesPage) getContext().initPage(page.getKey());
|
||||
ConferencePage conferencePage = (ConferencePage) getContext().initPage(Iterables.get(navigationHolder.entrySet(), 1).getKey());
|
||||
|
||||
conferencesPage.getFirstConference();
|
||||
String conferenceId = conferencePage.getId();
|
||||
Integer paperCount = conferencePage.getArticlesCount();
|
||||
|
||||
conferencePage.clickUndockArticleBut();
|
||||
conferencePage.clickSaveBut();
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + String.format("/conferences/conference?id=%s", conferenceId));
|
||||
|
||||
Assert.assertEquals(paperCount - 1, (int) conferencePage.getArticlesCount());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testISortAndFilterConferenceList() {
|
||||
Map.Entry<PageObject, List<String>> page = Iterables.get(navigationHolder.entrySet(), 0);
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + page.getValue().get(1));
|
||||
ConferencesPage conferencesPage = (ConferencesPage) getContext().initPage(page.getKey());
|
||||
|
||||
conferencesPage.selectMember();
|
||||
conferencesPage.selectYear();
|
||||
|
||||
Assert.assertEquals(1, conferencesPage.getConferencesList().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testJDeleteConf() throws InterruptedException {
|
||||
Map.Entry<PageObject, List<String>> page = Iterables.get(navigationHolder.entrySet(), 0);
|
||||
|
||||
getContext().goTo(applicationProperties.getBaseUrl() + page.getValue().get(1));
|
||||
ConferencesPage conferencesPage = (ConferencesPage) getContext().initPage(page.getKey());
|
||||
|
||||
Integer size = conferencesPage.getConferencesList().size();
|
||||
conferencesPage.deleteFirst();
|
||||
Thread.sleep(3000);
|
||||
conferencesPage.clickConfirm();
|
||||
|
||||
Assert.assertEquals(size - 1, conferencesPage.getConferencesList().size());
|
||||
}
|
||||
}
|
116
src/test/java/conference/ConferencePage.java
Normal file
116
src/test/java/conference/ConferencePage.java
Normal file
@ -0,0 +1,116 @@
|
||||
package conference;
|
||||
|
||||
import core.PageObject;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebElement;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ConferencePage extends PageObject {
|
||||
|
||||
public String getSubTitle() {
|
||||
return driver.findElement(By.tagName("h3")).getText();
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return driver.findElement(By.id("id")).getAttribute("value");
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
driver.findElement(By.id("title")).sendKeys(name);
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return driver.findElement(By.id("title")).getAttribute("value");
|
||||
}
|
||||
|
||||
public void clearName() {
|
||||
driver.findElement(By.id("title")).clear();
|
||||
}
|
||||
|
||||
public void clickSaveBut() {
|
||||
driver.findElement(By.id("send-message-button")).click();
|
||||
}
|
||||
|
||||
public void clickAddDeadlineBut() {
|
||||
driver.findElement(By.id("addDeadline")).click();
|
||||
}
|
||||
|
||||
public List<WebElement> getDeadlineList() {
|
||||
return driver.findElements(By.className("deadline"));
|
||||
}
|
||||
|
||||
public Integer getDeadlineCount() {
|
||||
return driver.findElements(By.className("deadline")).size();
|
||||
}
|
||||
|
||||
public void setDeadlineDescription(String description, Integer i) {
|
||||
driver.findElement(By.id(String.format("deadlines%d.description", i))).sendKeys(description);
|
||||
}
|
||||
|
||||
public void setDeadlineDate(String date, Integer i) {
|
||||
driver.findElement(By.id(String.format("deadlines%d.date", i))).sendKeys(date);
|
||||
}
|
||||
|
||||
public void clickTakePartBut() {
|
||||
driver.findElement(By.id("take-part")).click();
|
||||
}
|
||||
|
||||
public Boolean isTakePartButDisabledValueTrue() {
|
||||
return driver.findElement(By.id("take-part")).getAttribute("disabled").equals("true");
|
||||
}
|
||||
|
||||
public Integer getMemberCount() {
|
||||
return driver.findElements(By.className("member")).size();
|
||||
}
|
||||
|
||||
public void clickDeleteDeadlineBut() {
|
||||
driver.findElement(By.xpath("//*[@id=\"deadlines\"]/div/input[4]")).click();
|
||||
}
|
||||
|
||||
public void showAllowToAttachArticles() {
|
||||
driver.findElement(By.cssSelector("button[data-id=\"paperIds\"]")).click();
|
||||
}
|
||||
|
||||
public void clickAddPaperBut() {
|
||||
driver.findElement(By.id("add-paper")).click();
|
||||
}
|
||||
|
||||
|
||||
public List<WebElement> getArticles() {
|
||||
return driver.findElements(By.className("paper"));
|
||||
}
|
||||
|
||||
public Integer getArticlesCount() {
|
||||
return driver.findElements(By.className("paper")).size();
|
||||
}
|
||||
|
||||
public WebElement selectArticle() {
|
||||
WebElement webElement = driver.findElement(By.xpath("//*[@id=\"conference-form\"]/div/div[2]/div[5]/div/div/div[2]/ul/li[1]/a"));
|
||||
webElement.click();
|
||||
return webElement;
|
||||
}
|
||||
|
||||
public void clickUndockArticleBut() {
|
||||
driver.findElement(By.name("removePaper")).click();
|
||||
}
|
||||
|
||||
public boolean checkDeadline(String description, String dateValue) {
|
||||
return getDeadlineList()
|
||||
.stream()
|
||||
.anyMatch(webElement -> {
|
||||
return webElement.findElement(By.className("deadline-text")).getAttribute("value").equals(description)
|
||||
&& webElement.findElement(By.cssSelector("input[type=\"date\"]")).getAttribute("value").equals(dateValue);
|
||||
});
|
||||
}
|
||||
|
||||
public boolean checkArticle(String paperName) {
|
||||
return getArticles()
|
||||
.stream()
|
||||
.anyMatch(webElement -> webElement
|
||||
.findElements(By.tagName("input"))
|
||||
.get(1).getAttribute("value")
|
||||
.equals(paperName));
|
||||
}
|
||||
|
||||
}
|
11
src/test/java/conference/ConferencesDashboardPage.java
Normal file
11
src/test/java/conference/ConferencesDashboardPage.java
Normal file
@ -0,0 +1,11 @@
|
||||
package conference;
|
||||
|
||||
import core.PageObject;
|
||||
import org.openqa.selenium.By;
|
||||
|
||||
public class ConferencesDashboardPage extends PageObject {
|
||||
|
||||
public String getSubTitle() {
|
||||
return driver.findElement(By.tagName("h2")).getText();
|
||||
}
|
||||
}
|
47
src/test/java/conference/ConferencesPage.java
Normal file
47
src/test/java/conference/ConferencesPage.java
Normal file
@ -0,0 +1,47 @@
|
||||
package conference;
|
||||
|
||||
import core.PageObject;
|
||||
import org.openqa.selenium.By;
|
||||
import org.openqa.selenium.WebElement;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ConferencesPage extends PageObject {
|
||||
|
||||
public String getSubTitle() {
|
||||
return driver.findElement(By.tagName("h3")).getText();
|
||||
}
|
||||
|
||||
public List<WebElement> getConferencesList() {
|
||||
return driver.findElements(By.cssSelector("span.h6.float-left.m-2"));
|
||||
}
|
||||
|
||||
public void getFirstConference() {
|
||||
driver.findElement(By.xpath("//*[@id=\"conferences\"]/div/div[2]/div[1]/div[1]/div/a")).click();
|
||||
}
|
||||
|
||||
public void selectMember() {
|
||||
driver.findElements(By.className("bootstrap-select")).get(0).findElement(By.className("btn")).click();
|
||||
driver.findElements(By.className("bootstrap-select")).get(0).findElements(By.className("dropdown-item")).get(1).click();
|
||||
}
|
||||
|
||||
public void selectYear() {
|
||||
driver.findElements(By.className("bootstrap-select")).get(1).findElement(By.className("btn")).click();
|
||||
driver.findElements(By.className("bootstrap-select")).get(1).findElements(By.className("dropdown-item")).get(1).click();
|
||||
}
|
||||
|
||||
public void deleteFirst() {
|
||||
js.executeScript("$('input[data-confirm]').click();");
|
||||
}
|
||||
|
||||
public void clickConfirm() {
|
||||
driver.findElement(By.id("deleteConference")).click();
|
||||
}
|
||||
|
||||
|
||||
public boolean checkNameInList(String newConferenceName) {
|
||||
return getConferencesList()
|
||||
.stream()
|
||||
.anyMatch(webElement -> webElement.getText().equals(newConferenceName));
|
||||
}
|
||||
}
|
@ -1,14 +1,17 @@
|
||||
package core;
|
||||
|
||||
import org.openqa.selenium.JavascriptExecutor;
|
||||
import org.openqa.selenium.WebDriver;
|
||||
|
||||
public abstract class PageObject {
|
||||
protected WebDriver driver;
|
||||
protected JavascriptExecutor js;
|
||||
|
||||
public abstract String getSubTitle();
|
||||
|
||||
public PageObject setDriver(WebDriver driver) {
|
||||
this.driver = driver;
|
||||
js = (JavascriptExecutor) driver;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user