#42 merge with dev
This commit is contained in:
commit
97d7d00098
@ -5,6 +5,7 @@ import org.springframework.stereotype.Controller;
|
|||||||
import org.springframework.ui.ModelMap;
|
import org.springframework.ui.ModelMap;
|
||||||
import org.springframework.validation.Errors;
|
import org.springframework.validation.Errors;
|
||||||
import org.springframework.web.bind.annotation.GetMapping;
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PathVariable;
|
||||||
import org.springframework.web.bind.annotation.PostMapping;
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
import org.springframework.web.bind.annotation.RequestParam;
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
@ -12,10 +13,13 @@ import ru.ulstu.conference.model.ConferenceDto;
|
|||||||
import ru.ulstu.conference.model.ConferenceFilterDto;
|
import ru.ulstu.conference.model.ConferenceFilterDto;
|
||||||
import ru.ulstu.conference.service.ConferenceService;
|
import ru.ulstu.conference.service.ConferenceService;
|
||||||
import ru.ulstu.deadline.model.Deadline;
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
|
import ru.ulstu.paper.model.Paper;
|
||||||
import springfox.documentation.annotations.ApiIgnore;
|
import springfox.documentation.annotations.ApiIgnore;
|
||||||
|
|
||||||
import javax.validation.Valid;
|
import javax.validation.Valid;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
import static org.springframework.util.StringUtils.isEmpty;
|
import static org.springframework.util.StringUtils.isEmpty;
|
||||||
@ -43,34 +47,67 @@ public class ConferenceController {
|
|||||||
@GetMapping("/conference")
|
@GetMapping("/conference")
|
||||||
public void getConference(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
|
public void getConference(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
|
||||||
if (id != null && id > 0) {
|
if (id != null && id > 0) {
|
||||||
modelMap.put("conferenceDto", conferenceService.findOneDto(id));
|
ConferenceDto conferenceDto = conferenceService.findOneDto(id);
|
||||||
|
conferenceDto.setNotSelectedPapers(getNotSelectPapers(conferenceDto.getPaperIds()));
|
||||||
|
modelMap.put("conferenceDto", conferenceDto);
|
||||||
} else {
|
} else {
|
||||||
modelMap.put("conferenceDto", new ConferenceDto());
|
ConferenceDto conferenceDto = new ConferenceDto();
|
||||||
|
conferenceDto.setNotSelectedPapers(getNotSelectPapers(new ArrayList<Integer>()));
|
||||||
|
modelMap.put("conferenceDto", conferenceDto);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/conference", params = "save")
|
@PostMapping(value = "/conference", params = "save")
|
||||||
public String save(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
public String save(@Valid ConferenceDto conferenceDto, Errors errors) throws IOException {
|
||||||
filterEmptyDeadlines(conferenceDto);
|
filterEmptyDeadlines(conferenceDto);
|
||||||
if (conferenceDto.getDeadlines().isEmpty()) {
|
if (errors.hasErrors()) {
|
||||||
errors.rejectValue("deadlines", "errorCode", "Не может быть пустым");
|
|
||||||
}
|
|
||||||
if (errors.hasErrors())
|
|
||||||
return CONFERENCE_PAGE;
|
return CONFERENCE_PAGE;
|
||||||
|
}
|
||||||
conferenceService.save(conferenceDto);
|
conferenceService.save(conferenceDto);
|
||||||
return String.format(REDIRECT_TO, CONFERENCES_PAGE);
|
return String.format(REDIRECT_TO, CONFERENCES_PAGE);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GetMapping("/delete/{conference-id}")
|
||||||
|
public String delete(@PathVariable("conference-id") Integer conferenceId) throws IOException {
|
||||||
|
conferenceService.delete(conferenceId);
|
||||||
|
return String.format(REDIRECT_TO, CONFERENCES_PAGE);
|
||||||
|
}
|
||||||
|
|
||||||
@PostMapping(value = "/conference", params = "addDeadline")
|
@PostMapping(value = "/conference", params = "addDeadline")
|
||||||
public String addDeadline(@Valid ConferenceDto conferenceDto, Errors errors) {
|
public String addDeadline(@Valid ConferenceDto conferenceDto, Errors errors) {
|
||||||
filterEmptyDeadlines(conferenceDto);
|
filterEmptyDeadlines(conferenceDto);
|
||||||
if (errors.hasErrors())
|
if (errors.hasErrors()) {
|
||||||
return CONFERENCE_PAGE;
|
return CONFERENCE_PAGE;
|
||||||
|
}
|
||||||
conferenceDto.getDeadlines().add(new Deadline());
|
conferenceDto.getDeadlines().add(new Deadline());
|
||||||
return CONFERENCE_PAGE;
|
return CONFERENCE_PAGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/conference", params = "removeDeadline")
|
||||||
|
public String removeDeadline(@Valid ConferenceDto conferenceDto, Errors errors,
|
||||||
|
@RequestParam(value = "removeDeadline") Integer deadlineIndex) throws IOException {
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
return CONFERENCE_PAGE;
|
||||||
|
}
|
||||||
|
conferenceService.removeDeadline(conferenceDto, deadlineIndex);
|
||||||
|
return CONFERENCE_PAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/conference", params = "removePaper")
|
||||||
|
public String removePaper(@Valid ConferenceDto conferenceDto, Errors errors,
|
||||||
|
@RequestParam(value = "removePaper") Integer paperIndex) throws IOException {
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
return CONFERENCE_PAGE;
|
||||||
|
}
|
||||||
|
conferenceService.removePaper(conferenceDto, paperIndex);
|
||||||
|
return CONFERENCE_PAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Paper> getNotSelectPapers(List<Integer> paperIds) {
|
||||||
|
return conferenceService.getConferencePapers(paperIds);
|
||||||
|
}
|
||||||
|
|
||||||
private void filterEmptyDeadlines(ConferenceDto conferenceDto) {
|
private void filterEmptyDeadlines(ConferenceDto conferenceDto) {
|
||||||
conferenceDto.setDeadlines(conferenceDto.getDeadlines().stream()
|
conferenceDto.setDeadlines(conferenceDto.getDeadlines().stream()
|
||||||
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
||||||
|
@ -56,12 +56,11 @@ public class Conference extends BaseEntity {
|
|||||||
@OrderBy("date")
|
@OrderBy("date")
|
||||||
private List<Deadline> deadlines = new ArrayList<>();
|
private List<Deadline> deadlines = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
@ManyToMany(fetch = FetchType.EAGER)
|
@ManyToMany(fetch = FetchType.EAGER)
|
||||||
@JoinTable(name = "paper_conference",
|
@JoinTable(name = "paper_conference",
|
||||||
joinColumns = {@JoinColumn(name = "conference_id")},
|
joinColumns = {@JoinColumn(name = "conference_id")},
|
||||||
inverseJoinColumns = {@JoinColumn(name = "paper_id")})
|
inverseJoinColumns = {@JoinColumn(name = "paper_id")})
|
||||||
private Set<Paper> papers = new HashSet<>();
|
private List<Paper> papers = new ArrayList<>();
|
||||||
|
|
||||||
@ManyToMany(fetch = FetchType.EAGER)
|
@ManyToMany(fetch = FetchType.EAGER)
|
||||||
@JoinTable(name = "users_conference",
|
@JoinTable(name = "users_conference",
|
||||||
@ -125,11 +124,11 @@ public class Conference extends BaseEntity {
|
|||||||
this.deadlines = deadlines;
|
this.deadlines = deadlines;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Paper> getPapers() {
|
public List<Paper> getPapers() {
|
||||||
return papers;
|
return papers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPapers(Set<Paper> papers) {
|
public void setPapers(List<Paper> papers) {
|
||||||
this.papers = papers;
|
this.papers = papers;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
|
|||||||
import org.hibernate.validator.constraints.NotEmpty;
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
import org.springframework.format.annotation.DateTimeFormat;
|
import org.springframework.format.annotation.DateTimeFormat;
|
||||||
import ru.ulstu.deadline.model.Deadline;
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
import ru.ulstu.paper.model.PaperDto;
|
import ru.ulstu.paper.model.Paper;
|
||||||
import ru.ulstu.user.model.UserDto;
|
import ru.ulstu.user.model.UserDto;
|
||||||
|
|
||||||
import javax.persistence.Temporal;
|
import javax.persistence.Temporal;
|
||||||
@ -36,16 +36,18 @@ public class ConferenceDto {
|
|||||||
@Temporal(TemporalType.TIMESTAMP)
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
@DateTimeFormat(pattern = "yyyy-MM-dd")
|
||||||
private Date endDate = new Date();
|
private Date endDate = new Date();
|
||||||
@NotEmpty
|
|
||||||
private List<Deadline> deadlines = new ArrayList<>();
|
private List<Deadline> deadlines = new ArrayList<>();
|
||||||
|
private List<Integer> removedDeadlineIds = new ArrayList<>();
|
||||||
private Set<Integer> userIds = new HashSet<>();
|
private Set<Integer> userIds = new HashSet<>();
|
||||||
private Set<Integer> paperIds = new HashSet<>();
|
private List<Integer> paperIds = new ArrayList<>();
|
||||||
private Set<PaperDto> papers = new HashSet<>();
|
private List<Paper> papers = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
|
private List<Paper> notSelectedPapers = new ArrayList<>();
|
||||||
private Set<UserDto> users = new HashSet<>();
|
private Set<UserDto> users = new HashSet<>();
|
||||||
private Integer filterUserId;
|
private Integer filterUserId;
|
||||||
|
|
||||||
public ConferenceDto() {
|
public ConferenceDto() {
|
||||||
deadlines.add(new Deadline());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonCreator
|
@JsonCreator
|
||||||
@ -58,9 +60,10 @@ public class ConferenceDto {
|
|||||||
@JsonProperty("endDate") Date endDate,
|
@JsonProperty("endDate") Date endDate,
|
||||||
@JsonProperty("deadlines") List<Deadline> deadlines,
|
@JsonProperty("deadlines") List<Deadline> deadlines,
|
||||||
@JsonProperty("userIds") Set<Integer> userIds,
|
@JsonProperty("userIds") Set<Integer> userIds,
|
||||||
@JsonProperty("paperIds") Set<Integer> paperIds,
|
@JsonProperty("paperIds") List<Integer> paperIds,
|
||||||
@JsonProperty("users") Set<UserDto> users,
|
@JsonProperty("users") Set<UserDto> users,
|
||||||
@JsonProperty("papers") Set<PaperDto> papers) {
|
@JsonProperty("papers") List<Paper> papers,
|
||||||
|
@JsonProperty("notSelectedPapers") List<Paper> notSelectedPapers) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.title = title;
|
this.title = title;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
@ -73,6 +76,7 @@ public class ConferenceDto {
|
|||||||
this.paperIds = paperIds;
|
this.paperIds = paperIds;
|
||||||
this.users = users;
|
this.users = users;
|
||||||
this.papers = papers;
|
this.papers = papers;
|
||||||
|
this.notSelectedPapers = notSelectedPapers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConferenceDto(Conference conference) {
|
public ConferenceDto(Conference conference) {
|
||||||
@ -87,7 +91,7 @@ public class ConferenceDto {
|
|||||||
this.userIds = convert(conference.getUsers(), user -> user.getId());
|
this.userIds = convert(conference.getUsers(), user -> user.getId());
|
||||||
this.paperIds = convert(conference.getPapers(), paper -> paper.getId());
|
this.paperIds = convert(conference.getPapers(), paper -> paper.getId());
|
||||||
this.users = convert(conference.getUsers(), UserDto::new);
|
this.users = convert(conference.getUsers(), UserDto::new);
|
||||||
this.papers = convert(conference.getPapers(), PaperDto::new);
|
this.papers = conference.getPapers();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -163,19 +167,19 @@ public class ConferenceDto {
|
|||||||
this.userIds = userIds;
|
this.userIds = userIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<Integer> getPaperIds() {
|
public List<Integer> getPaperIds() {
|
||||||
return paperIds;
|
return paperIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPaperIds(Set<Integer> paperIds) {
|
public void setPaperIds(List<Integer> paperIds) {
|
||||||
this.paperIds = paperIds;
|
this.paperIds = paperIds;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<PaperDto> getPapers() {
|
public List<Paper> getPapers() {
|
||||||
return papers;
|
return papers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPapers(Set<PaperDto> papers) {
|
public void setPapers(List<Paper> papers) {
|
||||||
this.papers = papers;
|
this.papers = papers;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,4 +198,21 @@ public class ConferenceDto {
|
|||||||
public void setFilterUserId(Integer filterUserId) {
|
public void setFilterUserId(Integer filterUserId) {
|
||||||
this.filterUserId = filterUserId;
|
this.filterUserId = filterUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<Integer> getRemovedDeadlineIds() {
|
||||||
|
return removedDeadlineIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRemovedDeadlineIds(List<Integer> removedDeadlineIds) {
|
||||||
|
this.removedDeadlineIds = removedDeadlineIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Paper> getNotSelectedPapers() {
|
||||||
|
return notSelectedPapers;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotSelectedPapers(List<Paper> notSelectedPapers) {
|
||||||
|
this.notSelectedPapers = notSelectedPapers;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,8 @@ import ru.ulstu.conference.model.Conference;
|
|||||||
import ru.ulstu.conference.model.ConferenceDto;
|
import ru.ulstu.conference.model.ConferenceDto;
|
||||||
import ru.ulstu.conference.repository.ConferenceRepository;
|
import ru.ulstu.conference.repository.ConferenceRepository;
|
||||||
import ru.ulstu.deadline.service.DeadlineService;
|
import ru.ulstu.deadline.service.DeadlineService;
|
||||||
|
import ru.ulstu.paper.model.Paper;
|
||||||
|
import ru.ulstu.paper.service.PaperService;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -20,11 +22,14 @@ public class ConferenceService {
|
|||||||
|
|
||||||
private final ConferenceRepository conferenceRepository;
|
private final ConferenceRepository conferenceRepository;
|
||||||
private final DeadlineService deadlineService;
|
private final DeadlineService deadlineService;
|
||||||
|
private final PaperService paperService;
|
||||||
|
|
||||||
public ConferenceService(ConferenceRepository conferenceRepository,
|
public ConferenceService(ConferenceRepository conferenceRepository,
|
||||||
DeadlineService deadlineService) {
|
DeadlineService deadlineService,
|
||||||
|
PaperService paperService) {
|
||||||
this.conferenceRepository = conferenceRepository;
|
this.conferenceRepository = conferenceRepository;
|
||||||
this.deadlineService = deadlineService;
|
this.deadlineService = deadlineService;
|
||||||
|
this.paperService = paperService;
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<Conference> findAll() {
|
public List<Conference> findAll() {
|
||||||
@ -53,20 +58,40 @@ public class ConferenceService {
|
|||||||
public Integer create(ConferenceDto conferenceDto) throws IOException {
|
public Integer create(ConferenceDto conferenceDto) throws IOException {
|
||||||
Conference newConference = copyFromDto(new Conference(), conferenceDto);
|
Conference newConference = copyFromDto(new Conference(), conferenceDto);
|
||||||
newConference = conferenceRepository.save(newConference);
|
newConference = conferenceRepository.save(newConference);
|
||||||
|
|
||||||
|
|
||||||
return newConference.getId();
|
return newConference.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Transactional
|
@Transactional
|
||||||
public Integer update(ConferenceDto conferenceDto) throws IOException {
|
public Integer update(ConferenceDto conferenceDto) throws IOException {
|
||||||
Conference conference = conferenceRepository.findOne(conferenceDto.getId());
|
Conference conference = conferenceRepository.findOne(conferenceDto.getId());
|
||||||
|
|
||||||
conferenceRepository.save(copyFromDto(conference, conferenceDto));
|
conferenceRepository.save(copyFromDto(conference, conferenceDto));
|
||||||
|
conferenceDto.getRemovedDeadlineIds().forEach(deadlineService::remove);
|
||||||
return conference.getId();
|
return conference.getId();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void delete(Integer conferenceId) {
|
||||||
|
if (conferenceRepository.exists(conferenceId)) {
|
||||||
|
conferenceRepository.delete(conferenceId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removeDeadline(ConferenceDto conferenceDto, Integer deadlineIndex) throws IOException {
|
||||||
|
if (conferenceDto.getDeadlines().get(deadlineIndex).getId() != null) {
|
||||||
|
conferenceDto.getRemovedDeadlineIds().add(conferenceDto.getDeadlines().get(deadlineIndex).getId());
|
||||||
|
}
|
||||||
|
conferenceDto.getDeadlines().remove((int) deadlineIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void removePaper(ConferenceDto conferenceDto, Integer paperIndex) throws IOException {
|
||||||
|
Paper removedPaper = conferenceDto.getPapers().remove((int) paperIndex);
|
||||||
|
conferenceDto.getNotSelectedPapers().add(removedPaper);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Paper> getConferencePapers(List<Integer> paperIds) {
|
||||||
|
return paperService.findAllNotSelect(paperIds);
|
||||||
|
}
|
||||||
|
|
||||||
private Conference copyFromDto(Conference conference, ConferenceDto conferenceDto) throws IOException {
|
private Conference copyFromDto(Conference conference, ConferenceDto conferenceDto) throws IOException {
|
||||||
conference.setTitle(conferenceDto.getTitle());
|
conference.setTitle(conferenceDto.getTitle());
|
||||||
conference.setDescription(conferenceDto.getDescription());
|
conference.setDescription(conferenceDto.getDescription());
|
||||||
@ -74,9 +99,12 @@ public class ConferenceService {
|
|||||||
conference.setPing(0);
|
conference.setPing(0);
|
||||||
conference.setBeginDate(conferenceDto.getBeginDate());
|
conference.setBeginDate(conferenceDto.getBeginDate());
|
||||||
conference.setEndDate(conferenceDto.getEndDate());
|
conference.setEndDate(conferenceDto.getEndDate());
|
||||||
|
conference.setPapers(conferenceDto.getPapers());
|
||||||
conference.setDeadlines(deadlineService.saveOrCreate(conferenceDto.getDeadlines()));
|
conference.setDeadlines(deadlineService.saveOrCreate(conferenceDto.getDeadlines()));
|
||||||
|
if (conferenceDto.getPaperIds() != null && !conferenceDto.getPaperIds().isEmpty()) {
|
||||||
|
conferenceDto.getPaperIds().forEach(paperId ->
|
||||||
|
conference.getPapers().add(paperService.findEntityById(paperId)));
|
||||||
|
}
|
||||||
return conference;
|
return conference;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,4 +41,9 @@ public class DeadlineService {
|
|||||||
newDeadline = deadlineRepository.save(newDeadline);
|
newDeadline = deadlineRepository.save(newDeadline);
|
||||||
return newDeadline;
|
return newDeadline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void remove(Integer deadlineId) {
|
||||||
|
deadlineRepository.delete(deadlineId);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,4 +12,6 @@ public interface PaperRepository extends JpaRepository<Paper, Integer> {
|
|||||||
|
|
||||||
@Query("SELECT p FROM Paper p WHERE (:author IS NULL OR :author MEMBER OF p.authors) AND (YEAR(p.createDate) = :year OR :year IS NULL)")
|
@Query("SELECT p FROM Paper p WHERE (:author IS NULL OR :author MEMBER OF p.authors) AND (YEAR(p.createDate) = :year OR :year IS NULL)")
|
||||||
List<Paper> filter(@Param("author") User author, @Param("year") Integer year);
|
List<Paper> filter(@Param("author") User author, @Param("year") Integer year);
|
||||||
|
|
||||||
|
List<Paper> findByIdNotIn(List<Integer> paperIds);
|
||||||
}
|
}
|
||||||
|
@ -215,6 +215,19 @@ public class PaperService {
|
|||||||
return new PaperDto(paperRepository.findOne(paperId));
|
return new PaperDto(paperRepository.findOne(paperId));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Paper findEntityById(Integer paperId) {
|
||||||
|
return paperRepository.findOne(paperId);
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Paper> findAllNotSelect(List<Integer> paperIds) {
|
||||||
|
if (!paperIds.isEmpty()) {
|
||||||
|
return sortPapers(paperRepository.findByIdNotIn(paperIds));
|
||||||
|
} else {
|
||||||
|
return sortPapers(paperRepository.findAll());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public List<User> getPaperAuthors() {
|
public List<User> getPaperAuthors() {
|
||||||
return userService.findAll();
|
return userService.findAll();
|
||||||
}
|
}
|
||||||
|
16
src/main/java/ru/ulstu/students/controller/Navigation.java
Normal file
16
src/main/java/ru/ulstu/students/controller/Navigation.java
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package ru.ulstu.students.controller;
|
||||||
|
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
|
||||||
|
public class Navigation {
|
||||||
|
public static final String REDIRECT_TO = "redirect:%s";
|
||||||
|
public static final String TASKS_PAGE = "/students/tasks";
|
||||||
|
public static final String TASK_PAGE = "/students/task";
|
||||||
|
|
||||||
|
public static String hasErrors(Errors errors, String page) {
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
return page;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,84 @@
|
|||||||
|
package ru.ulstu.students.controller;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Controller;
|
||||||
|
import org.springframework.ui.ModelMap;
|
||||||
|
import org.springframework.validation.Errors;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
|
import ru.ulstu.students.model.Task;
|
||||||
|
import ru.ulstu.students.model.TaskDto;
|
||||||
|
import ru.ulstu.students.service.TaskService;
|
||||||
|
import springfox.documentation.annotations.ApiIgnore;
|
||||||
|
|
||||||
|
import javax.validation.Valid;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static org.springframework.util.StringUtils.isEmpty;
|
||||||
|
import static ru.ulstu.students.controller.Navigation.*;
|
||||||
|
|
||||||
|
@Controller()
|
||||||
|
@RequestMapping(value = "/students")
|
||||||
|
@ApiIgnore
|
||||||
|
public class TaskController {
|
||||||
|
|
||||||
|
private final TaskService taskService;
|
||||||
|
|
||||||
|
public TaskController(TaskService taskService) {
|
||||||
|
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("/task")
|
||||||
|
public void getTask(ModelMap modelMap, @RequestParam(value = "id") Integer id) {
|
||||||
|
if (id != null && id > 0) {
|
||||||
|
modelMap.put("taskDto", taskService.findOneDto(id));
|
||||||
|
} else {
|
||||||
|
modelMap.put("taskDto", new TaskDto());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/task", params = "save")
|
||||||
|
public String save(@Valid TaskDto taskDto, Errors errors) throws IOException {
|
||||||
|
filterEmptyDeadlines(taskDto);
|
||||||
|
if (taskDto.getDeadlines().isEmpty()) {
|
||||||
|
errors.rejectValue("deadlines", "errorCode", "Не может быть пустым");
|
||||||
|
}
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
return TASK_PAGE;
|
||||||
|
}
|
||||||
|
taskService.save(taskDto);
|
||||||
|
return String.format(REDIRECT_TO, TASKS_PAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping(value = "/task", params = "addDeadline")
|
||||||
|
public String addDeadline(@Valid TaskDto taskDto, Errors errors) {
|
||||||
|
filterEmptyDeadlines(taskDto);
|
||||||
|
if (errors.hasErrors()) {
|
||||||
|
return TASK_PAGE;
|
||||||
|
}
|
||||||
|
taskDto.getDeadlines().add(new Deadline());
|
||||||
|
return TASK_PAGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ModelAttribute("allStatuses")
|
||||||
|
public List<Task.TaskStatus> getTaskStatuses() {
|
||||||
|
return taskService.getTaskStatuses();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void filterEmptyDeadlines(TaskDto taskDto) {
|
||||||
|
taskDto.setDeadlines(taskDto.getDeadlines().stream()
|
||||||
|
.filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription()))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
}
|
||||||
|
}
|
118
src/main/java/ru/ulstu/students/model/Task.java
Normal file
118
src/main/java/ru/ulstu/students/model/Task.java
Normal file
@ -0,0 +1,118 @@
|
|||||||
|
package ru.ulstu.students.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.deadline.model.Deadline;
|
||||||
|
import ru.ulstu.tags.model.Tag;
|
||||||
|
|
||||||
|
import javax.persistence.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
public class Task extends BaseEntity {
|
||||||
|
|
||||||
|
public enum TaskStatus {
|
||||||
|
IN_WORK("В работе"),
|
||||||
|
COMPLETED("Завершен"),
|
||||||
|
FAILED("Провалены сроки"),
|
||||||
|
LOADED_FROM_KIAS("Загружен автоматически");
|
||||||
|
|
||||||
|
private String statusName;
|
||||||
|
|
||||||
|
TaskStatus(String name) {
|
||||||
|
this.statusName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getStatusName() {
|
||||||
|
return statusName;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
@Enumerated(value = EnumType.STRING)
|
||||||
|
private ru.ulstu.students.model.Task.TaskStatus status = TaskStatus.IN_WORK;
|
||||||
|
|
||||||
|
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
|
||||||
|
@JoinColumn(name = "task_id", unique = true)
|
||||||
|
@Fetch(FetchMode.SUBSELECT)
|
||||||
|
@OrderBy("date")
|
||||||
|
private List<Deadline> deadlines = new ArrayList<>();
|
||||||
|
|
||||||
|
@Column(name = "create_date")
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
private Date createDate = new Date();
|
||||||
|
|
||||||
|
@Column(name = "update_date")
|
||||||
|
@Temporal(TemporalType.TIMESTAMP)
|
||||||
|
private Date updateDate = new Date();
|
||||||
|
|
||||||
|
@ManyToMany(fetch = FetchType.EAGER)
|
||||||
|
@JoinTable(name = "task_tags",
|
||||||
|
joinColumns = {@JoinColumn(name = "task_id")},
|
||||||
|
inverseJoinColumns = {@JoinColumn(name = "tag_id")})
|
||||||
|
private List<Tag> tags = new ArrayList<>();
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(TaskStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Deadline> getDeadlines() {
|
||||||
|
return deadlines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeadlines(List<Deadline> deadlines) {
|
||||||
|
this.deadlines = deadlines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreateDate() {
|
||||||
|
return createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateDate(Date createDate) {
|
||||||
|
this.createDate = createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getUpdateDate() {
|
||||||
|
return updateDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateDate(Date updateDate) {
|
||||||
|
this.updateDate = updateDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Tag> getTags() {
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTags(List<Tag> tags) {
|
||||||
|
this.tags = tags;
|
||||||
|
}
|
||||||
|
}
|
144
src/main/java/ru/ulstu/students/model/TaskDto.java
Normal file
144
src/main/java/ru/ulstu/students/model/TaskDto.java
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
package ru.ulstu.students.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
|
import ru.ulstu.deadline.model.Deadline;
|
||||||
|
import ru.ulstu.tags.model.Tag;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public class TaskDto {
|
||||||
|
|
||||||
|
private final static int MAX_TAGS_LENGTH = 50;
|
||||||
|
|
||||||
|
private Integer id;
|
||||||
|
@NotEmpty
|
||||||
|
private String title;
|
||||||
|
private String description;
|
||||||
|
private Task.TaskStatus status;
|
||||||
|
private List<Deadline> deadlines = new ArrayList<>();
|
||||||
|
private Date createDate;
|
||||||
|
private Date updateDate;
|
||||||
|
private Set<Integer> tagIds;
|
||||||
|
private List<Tag> tags;
|
||||||
|
|
||||||
|
public TaskDto() {
|
||||||
|
deadlines.add(new Deadline());
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public TaskDto(@JsonProperty("id") Integer id,
|
||||||
|
@JsonProperty("title") String title,
|
||||||
|
@JsonProperty("description") String description,
|
||||||
|
@JsonProperty("createDate") Date createDate,
|
||||||
|
@JsonProperty("updateDate") Date updateDate,
|
||||||
|
@JsonProperty("status") Task.TaskStatus status,
|
||||||
|
@JsonProperty("deadlines") List<Deadline> deadlines,
|
||||||
|
@JsonProperty("tagIds") Set<Integer> tagIds,
|
||||||
|
@JsonProperty("tags") List<Tag> tags) {
|
||||||
|
this.id = id;
|
||||||
|
this.title = title;
|
||||||
|
this.status = status;
|
||||||
|
this.deadlines = deadlines;
|
||||||
|
this.createDate = createDate;
|
||||||
|
this.updateDate = updateDate;
|
||||||
|
this.description = description;
|
||||||
|
this.tags = tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskDto(Task task) {
|
||||||
|
this.id = task.getId();
|
||||||
|
this.title = task.getTitle();
|
||||||
|
this.status = task.getStatus();
|
||||||
|
this.deadlines = task.getDeadlines();
|
||||||
|
this.createDate = task.getCreateDate();
|
||||||
|
this.updateDate = task.getUpdateDate();
|
||||||
|
this.description = task.getDescription();
|
||||||
|
this.tags = task.getTags();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Integer id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTitle() {
|
||||||
|
return title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTitle(String title) {
|
||||||
|
this.title = title;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Task.TaskStatus getStatus() {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStatus(Task.TaskStatus status) {
|
||||||
|
this.status = status;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Deadline> getDeadlines() {
|
||||||
|
return deadlines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDeadlines(List<Deadline> deadlines) {
|
||||||
|
this.deadlines = deadlines;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getCreateDate() {
|
||||||
|
return createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCreateDate(Date createDate) {
|
||||||
|
this.createDate = createDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Date getUpdateDate() {
|
||||||
|
return updateDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUpdateDate(Date updateDate) {
|
||||||
|
this.updateDate = updateDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<Integer> getTagIds() {
|
||||||
|
return tagIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTagIds(Set<Integer> tagIds) {
|
||||||
|
this.tagIds = tagIds;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Tag> getTags() {
|
||||||
|
return tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTags(List<Tag> tags) {
|
||||||
|
this.tags = tags;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTagsString() {
|
||||||
|
return StringUtils.abbreviate(tags
|
||||||
|
.stream()
|
||||||
|
.map(tag -> tag.getTagName())
|
||||||
|
.collect(Collectors.joining(", ")), MAX_TAGS_LENGTH);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
package ru.ulstu.students.repository;
|
||||||
|
|
||||||
|
import org.springframework.data.jpa.repository.JpaRepository;
|
||||||
|
import ru.ulstu.students.model.Task;
|
||||||
|
|
||||||
|
public interface TaskRepository extends JpaRepository<Task, Integer> {
|
||||||
|
}
|
95
src/main/java/ru/ulstu/students/service/TaskService.java
Normal file
95
src/main/java/ru/ulstu/students/service/TaskService.java
Normal file
@ -0,0 +1,95 @@
|
|||||||
|
package ru.ulstu.students.service;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
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.repository.TaskRepository;
|
||||||
|
import ru.ulstu.tags.service.TagService;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.springframework.util.ObjectUtils.isEmpty;
|
||||||
|
import static ru.ulstu.core.util.StreamApiUtils.convert;
|
||||||
|
import static ru.ulstu.students.model.Task.TaskStatus.IN_WORK;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TaskService {
|
||||||
|
|
||||||
|
private final static int MAX_DISPLAY_SIZE = 40;
|
||||||
|
|
||||||
|
private final TaskRepository taskRepository;
|
||||||
|
private final DeadlineService deadlineService;
|
||||||
|
private final TagService tagService;
|
||||||
|
|
||||||
|
public TaskService(TaskRepository grantRepository,
|
||||||
|
DeadlineService deadlineService, TagService tagService) {
|
||||||
|
this.taskRepository = grantRepository;
|
||||||
|
this.deadlineService = deadlineService;
|
||||||
|
this.tagService = tagService;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Task> findAll() {
|
||||||
|
return taskRepository.findAll();
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<TaskDto> findAllDto() {
|
||||||
|
List<TaskDto> tasks = convert(findAll(), TaskDto::new);
|
||||||
|
tasks.forEach(taskDto -> taskDto.setTitle(StringUtils.abbreviate(taskDto.getTitle(), MAX_DISPLAY_SIZE)));
|
||||||
|
return tasks;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TaskDto findOneDto(Integer id) {
|
||||||
|
return new TaskDto(taskRepository.findOne(id));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Integer create(TaskDto taskDto) throws IOException {
|
||||||
|
Task newTask = copyFromDto(new Task(), taskDto);
|
||||||
|
newTask = taskRepository.save(newTask);
|
||||||
|
return newTask.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Task copyFromDto(Task task, TaskDto taskDto) throws IOException {
|
||||||
|
task.setTitle(taskDto.getTitle());
|
||||||
|
task.setDescription(taskDto.getDescription());
|
||||||
|
task.setStatus(taskDto.getStatus() == null ? IN_WORK : taskDto.getStatus());
|
||||||
|
task.setDeadlines(deadlineService.saveOrCreate(taskDto.getDeadlines()));
|
||||||
|
task.setCreateDate(task.getCreateDate() == null ? new Date() : task.getCreateDate());
|
||||||
|
task.setUpdateDate(new Date());
|
||||||
|
task.getTags().clear();
|
||||||
|
task.setTags(tagService.saveOrCreate(taskDto.getTags()));
|
||||||
|
return task;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Integer update(TaskDto taskDto) throws IOException {
|
||||||
|
Task task = taskRepository.findOne(taskDto.getId());
|
||||||
|
taskRepository.save(copyFromDto(task, taskDto));
|
||||||
|
return task.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public void delete(Integer taskId) throws IOException {
|
||||||
|
Task task = taskRepository.findOne(taskId);
|
||||||
|
taskRepository.delete(task);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void save(TaskDto taskDto) throws IOException {
|
||||||
|
if (isEmpty(taskDto.getId())) {
|
||||||
|
create(taskDto);
|
||||||
|
} else {
|
||||||
|
update(taskDto);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Task.TaskStatus> getTaskStatuses() {
|
||||||
|
return Arrays.asList(Task.TaskStatus.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
44
src/main/java/ru/ulstu/tags/model/Tag.java
Normal file
44
src/main/java/ru/ulstu/tags/model/Tag.java
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
package ru.ulstu.tags.model;
|
||||||
|
|
||||||
|
import com.fasterxml.jackson.annotation.JsonCreator;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||||
|
import org.hibernate.validator.constraints.NotEmpty;
|
||||||
|
import ru.ulstu.core.model.BaseEntity;
|
||||||
|
|
||||||
|
import javax.persistence.Column;
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
import javax.persistence.Table;
|
||||||
|
import javax.validation.constraints.Size;
|
||||||
|
|
||||||
|
@Entity
|
||||||
|
@Table(name = "tag")
|
||||||
|
public class Tag extends BaseEntity {
|
||||||
|
|
||||||
|
@NotEmpty
|
||||||
|
@Size(max = 50)
|
||||||
|
@Column(name = "tag_name")
|
||||||
|
private String tagName;
|
||||||
|
|
||||||
|
public Tag() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonCreator
|
||||||
|
public Tag(@JsonProperty("id") Integer id,
|
||||||
|
@JsonProperty("tag_name") String tagName) {
|
||||||
|
this.setId(id);
|
||||||
|
this.tagName = tagName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Tag(String name) {
|
||||||
|
this.tagName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTagName() {
|
||||||
|
return tagName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTagName(String tagName) {
|
||||||
|
this.tagName = tagName;
|
||||||
|
}
|
||||||
|
}
|
12
src/main/java/ru/ulstu/tags/repository/TagRepository.java
Normal file
12
src/main/java/ru/ulstu/tags/repository/TagRepository.java
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
package ru.ulstu.tags.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.tags.model.Tag;
|
||||||
|
|
||||||
|
public interface TagRepository extends JpaRepository<Tag, Integer> {
|
||||||
|
|
||||||
|
@Query("SELECT t FROM Tag t WHERE (t.tagName = :tagName)")
|
||||||
|
Tag findByName(@Param("tagName") String tagName);
|
||||||
|
}
|
53
src/main/java/ru/ulstu/tags/service/TagService.java
Normal file
53
src/main/java/ru/ulstu/tags/service/TagService.java
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
package ru.ulstu.tags.service;
|
||||||
|
|
||||||
|
import org.springframework.stereotype.Service;
|
||||||
|
import ru.ulstu.tags.model.Tag;
|
||||||
|
import ru.ulstu.tags.repository.TagRepository;
|
||||||
|
|
||||||
|
import javax.transaction.Transactional;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
@Service
|
||||||
|
public class TagService {
|
||||||
|
|
||||||
|
private final TagRepository tagRepository;
|
||||||
|
|
||||||
|
|
||||||
|
public TagService(TagRepository tagRepository) {
|
||||||
|
|
||||||
|
this.tagRepository = tagRepository;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<Tag> saveOrCreate(List<Tag> tags) {
|
||||||
|
return tags
|
||||||
|
.stream()
|
||||||
|
.map(tag -> {
|
||||||
|
if (tag.getId() != null) {
|
||||||
|
return getExistById(tag);
|
||||||
|
} else {
|
||||||
|
Tag existTag = isExistByName(tag.getTagName());
|
||||||
|
return existTag != null ? existTag : create(tag);
|
||||||
|
}
|
||||||
|
}).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Tag getExistById(Tag tag) {
|
||||||
|
return tagRepository.findOne(tag.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Tag isExistByName(String tagName) {
|
||||||
|
return tagRepository.findByName(tagName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Transactional
|
||||||
|
public Tag create(Tag tag) {
|
||||||
|
Tag newTag = new Tag();
|
||||||
|
newTag.setTagName(tag.getTagName());
|
||||||
|
newTag = tagRepository.save(newTag);
|
||||||
|
return newTag;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
# Server Settings
|
# Server Settings
|
||||||
spring.main.banner-mode=off
|
spring.main.banner-mode=off
|
||||||
server.port=8443
|
server.port=8443
|
||||||
server.http.port=8080
|
server.http.port=8888
|
||||||
spring.http.multipart.maxFileSize=20MB
|
spring.http.multipart.maxFileSize=20MB
|
||||||
spring.http.multipart.maxRequestSize=20MB
|
spring.http.multipart.maxRequestSize=20MB
|
||||||
# Thymeleaf Settings
|
# Thymeleaf Settings
|
||||||
@ -24,7 +24,7 @@ spring.mail.properties.mail.smtp.socketFactory.class=javax.net.ssl.SSLSocketFact
|
|||||||
# JPA Settings
|
# JPA Settings
|
||||||
spring.datasource.url=jdbc:postgresql://localhost:5432/ng-tracker
|
spring.datasource.url=jdbc:postgresql://localhost:5432/ng-tracker
|
||||||
spring.datasource.username=postgres
|
spring.datasource.username=postgres
|
||||||
spring.datasource.password=postgres
|
spring.datasource.password=superuser
|
||||||
spring.datasource.driverclassName=org.postgresql.Driver
|
spring.datasource.driverclassName=org.postgresql.Driver
|
||||||
spring.jpa.hibernate.ddl-auto=validate
|
spring.jpa.hibernate.ddl-auto=validate
|
||||||
# Liquibase Settings
|
# Liquibase Settings
|
||||||
|
17
src/main/resources/db/changelog-20190410_000000-schema.xml
Normal file
17
src/main/resources/db/changelog-20190410_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="nastya" id="20190410_000000-1">
|
||||||
|
<addColumn tableName="tag">
|
||||||
|
<column name="version" type="integer"/>
|
||||||
|
</addColumn>
|
||||||
|
<renameColumn tableName="tag" oldColumnName="tagname" newColumnName="tag_name"/>
|
||||||
|
</changeSet>
|
||||||
|
|
||||||
|
<changeSet author="nastya" id="20190410_000000-2">
|
||||||
|
<addColumn tableName="task">
|
||||||
|
<column name="version" type="integer"/>
|
||||||
|
</addColumn>
|
||||||
|
</changeSet>
|
||||||
|
</databaseChangeLog>
|
@ -23,6 +23,7 @@
|
|||||||
<include file="db/changelog-20190327_000000-schema.xml"/>
|
<include file="db/changelog-20190327_000000-schema.xml"/>
|
||||||
<include file="db/changelog-20190331_000000-schema.xml"/>
|
<include file="db/changelog-20190331_000000-schema.xml"/>
|
||||||
<include file="db/changelog-20190331_000010-schema.xml"/>
|
<include file="db/changelog-20190331_000010-schema.xml"/>
|
||||||
|
<include file="db/changelog-20190410_000000-schema.xml"/>
|
||||||
<include file="db/common/changelog-20190312_130000-schema.xml"/>
|
<include file="db/common/changelog-20190312_130000-schema.xml"/>
|
||||||
<include file="db/changelog-20190402_000000-schema.xml"/>
|
<include file="db/changelog-20190402_000000-schema.xml"/>
|
||||||
<include file="db/changelog-20190404_000000-schema.xml"/>
|
<include file="db/changelog-20190404_000000-schema.xml"/>
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -2,6 +2,15 @@ body {
|
|||||||
min-width: 400px;
|
min-width: 400px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.conference-row .col:hover {
|
||||||
|
background-color: #eaeaea;
|
||||||
|
border-radius: .25rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filter-option-inner-inner {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -19,6 +28,7 @@ body {
|
|||||||
.deadline {
|
.deadline {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
|
min-height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.deadline-text {
|
.deadline-text {
|
||||||
@ -43,6 +53,8 @@ body {
|
|||||||
|
|
||||||
.paper {
|
.paper {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
min-height: 40px;
|
||||||
|
height: 40px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.paper-name {
|
.paper-name {
|
||||||
@ -63,6 +75,9 @@ body {
|
|||||||
|
|
||||||
.icon-delete {
|
.icon-delete {
|
||||||
background-color: #f44;
|
background-color: #f44;
|
||||||
|
background-image: url(/img/conference/delete.png);
|
||||||
|
background-repeat: round;
|
||||||
|
color: transparent !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.icon-delete:hover {
|
.icon-delete:hover {
|
||||||
@ -95,13 +110,14 @@ body {
|
|||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 1199px) {
|
@media (max-width: 1199px) and (min-width: 768px){
|
||||||
.paper-control {
|
.paper-control {
|
||||||
display: block!important;
|
display: block!important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@media (max-width: 991px) {
|
@media (max-width: 991px) {
|
||||||
|
|
||||||
.dates-panel {
|
.dates-panel {
|
||||||
display: block!important;
|
display: block!important;
|
||||||
}
|
}
|
||||||
|
@ -1,24 +1,65 @@
|
|||||||
.bootstrap-tagsinput{
|
.tags-container {
|
||||||
|
|
||||||
width: 100%;
|
width: 100%;
|
||||||
padding: .375rem .75rem;
|
padding: .375rem .75rem;
|
||||||
|
background-color: #fff;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
|
||||||
|
display: inline-block;
|
||||||
|
color: #555;
|
||||||
|
vertical-align: middle;
|
||||||
|
border-radius: 4px;
|
||||||
|
max-width: 100%;
|
||||||
|
line-height: 22px;
|
||||||
|
cursor: text;
|
||||||
}
|
}
|
||||||
|
|
||||||
.bootstrap-tagsinput .label{
|
.input-tag-name {
|
||||||
|
border: none;
|
||||||
display: inline;
|
box-shadow: none;
|
||||||
padding: .2em .6em .3em;
|
outline: none;
|
||||||
font-size: 75%;
|
background-color: transparent;
|
||||||
font-weight: 700;
|
padding: 0 6px;
|
||||||
line-height: 2.5;
|
margin: 0;
|
||||||
color: #fff;
|
width: auto;
|
||||||
text-align: center;
|
max-width: inherit;
|
||||||
white-space: nowrap;
|
|
||||||
vertical-align: baseline;
|
|
||||||
border-radius: .25em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.bootstrap-tagsinput .label-info{
|
.tag {
|
||||||
|
display: inline-block;
|
||||||
|
padding: .2em .6em .3em;
|
||||||
|
background-color: orange;
|
||||||
|
border-radius: .25em;
|
||||||
|
margin-right: 4px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
|
||||||
|
font-size: 75%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-name span[data-role="remove"] {
|
||||||
|
margin-left: 8px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-name span[data-role="remove"]:after {
|
||||||
|
content: "x";
|
||||||
|
padding: 0px 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.tag-name input[type="text"] {
|
||||||
|
background: transparent;
|
||||||
|
border: none;
|
||||||
|
display: inline-flex;
|
||||||
|
font-size: 100%;
|
||||||
|
font-weight: 700;
|
||||||
|
line-height: 1.5;
|
||||||
|
color: #fff;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
outline: none;
|
||||||
|
cursor: default;
|
||||||
|
|
||||||
background-color: orange;
|
|
||||||
}
|
}
|
||||||
|
@ -1,27 +1,41 @@
|
|||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
$('.data-href-js').click( function() {
|
$(".conference-row").mouseenter(function (event) {
|
||||||
window.location = $(this).attr('data-href');
|
var conferenceRow = $(event.target).closest(".conference-row");
|
||||||
|
$(conferenceRow).css("background-color", "#f8f9fa");
|
||||||
|
$(conferenceRow).find(".remove-conference").removeClass("d-none");
|
||||||
|
|
||||||
|
});
|
||||||
|
$(".conference-row").mouseleave(function (event) {
|
||||||
|
var conferenceRow = $(event.target).closest(".conference-row");
|
||||||
|
$(conferenceRow).css("background-color", "white");
|
||||||
|
$(conferenceRow).closest(".conference-row").find(".remove-conference").addClass("d-none");
|
||||||
});
|
});
|
||||||
|
|
||||||
$('.circle').parent().click( function() {
|
$('a[data-confirm]').click(function(ev) {
|
||||||
$(this).children('.circle').toggleClass('circle-active');
|
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' +
|
||||||
|
|
||||||
$('.checkbox-js').parent().click( function() {
|
' <div class="modal-footer">\n' +
|
||||||
$(this).children('.checkbox').toggleClass('selected');
|
' <a class="btn btn-primary" id="dataConfirmOK">Да</a>'+
|
||||||
});
|
' <button class="btn primary" data-dismiss="modal" aria-hidden="true">Нет</button>'+
|
||||||
|
' </div>\n' +
|
||||||
$('#select-all-js').click( function() {
|
' </div>\n' +
|
||||||
$(this).toggleClass('selected');
|
' </div>\n' +
|
||||||
|
' </div>');
|
||||||
var childNodes = $('.conference-item .form-check .checkbox')
|
}
|
||||||
.each(function(i, elem) {
|
$('#dataConfirmModal').find('#myModalLabel').text($(this).attr('data-confirm'));
|
||||||
if ($(this).hasClass('selected') && !$('#select-all-js').hasClass('selected')) {
|
$('#dataConfirmOK').attr('href', href);
|
||||||
$(this).toggleClass('selected');
|
$('#dataConfirmModal').modal({show:true});
|
||||||
} else if (!$(this).hasClass('selected') && $('#select-all-js').hasClass('selected')){
|
return false;
|
||||||
$(this).toggleClass('selected');
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -1,5 +1,75 @@
|
|||||||
/*<![CDATA[*/
|
/*<![CDATA[*/
|
||||||
$(document).ready(function () {
|
$(document).ready(function () {
|
||||||
|
|
||||||
|
$("#tags .tag .tag-name input[type=text]").each(function() {
|
||||||
|
$(this).attr("size", $(this).val().length)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$("#task-form").keydown(function(event){
|
||||||
|
if(event.keyCode == 13) {
|
||||||
|
event.preventDefault();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function removeTag () {
|
||||||
|
$(this).parent().parent().remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
$("#input-tag").keyup(function (event) {
|
||||||
|
if(event.keyCode == 13 || event.keyCode == 188) {
|
||||||
|
var tagNumber = $("#tags .tag").length;
|
||||||
|
var tagName = $.trim($(this).val());
|
||||||
|
var addTag = true;
|
||||||
|
// проверка, добавлен ли этот тег
|
||||||
|
$("#tags .tag .tag-name input[type=text]").each(function() {
|
||||||
|
if(tagName === $(this).val()) {
|
||||||
|
addTag = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
// если тег не добавлен
|
||||||
|
if(addTag) {
|
||||||
|
// контейнер тега
|
||||||
|
var newTagRow = $("<div/>")
|
||||||
|
.attr("id", 'tags' + tagNumber)
|
||||||
|
.addClass("tag");
|
||||||
|
// контейнер id
|
||||||
|
var idInput = $("<input/>")
|
||||||
|
.attr("type", "hidden")
|
||||||
|
.attr("id", "tags" + tagNumber + ".id")
|
||||||
|
.attr("name", "tags[" + tagNumber + "].id")
|
||||||
|
.attr("value", '');
|
||||||
|
// контейнер текста
|
||||||
|
var conDiv = $("<div/>")
|
||||||
|
.addClass("tag-name");
|
||||||
|
// текст тега
|
||||||
|
var nameInput = $("<input/>")
|
||||||
|
.attr("type", "text")
|
||||||
|
.attr("id", "tags" + tagNumber + ".tagName")
|
||||||
|
.attr("name", "tags[" + tagNumber + "].tagName")
|
||||||
|
.attr("value", tagName)
|
||||||
|
.attr("readonly", "true")
|
||||||
|
.attr("size", tagName.length);
|
||||||
|
// кнопка удалить тег
|
||||||
|
var removeSpan = $("<span/>")
|
||||||
|
.attr("data-role", "remove")
|
||||||
|
.bind("click", removeTag);
|
||||||
|
|
||||||
|
conDiv.append(nameInput);
|
||||||
|
conDiv.append(removeSpan);
|
||||||
|
newTagRow.append(idInput);
|
||||||
|
newTagRow.append(conDiv);
|
||||||
|
$(this).before(newTagRow);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(this).val('');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$("span[data-role=remove]").click(removeTag);
|
||||||
$(".task-row").mouseenter(function (event) {
|
$(".task-row").mouseenter(function (event) {
|
||||||
var taskRow = $(event.target).closest(".task-row");
|
var taskRow = $(event.target).closest(".task-row");
|
||||||
$(taskRow).css("background-color", "#f8f9fa");
|
$(taskRow).css("background-color", "#f8f9fa");
|
||||||
|
@ -50,6 +50,7 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="deadlines">Дедлайны:</label>
|
<label for="deadlines">Дедлайны:</label>
|
||||||
<div class="deadline-list form-control list-group" id="deadlines">
|
<div class="deadline-list form-control list-group" id="deadlines">
|
||||||
|
<input type="hidden" th:field="*{removedDeadlineIds}"/>
|
||||||
<div class="deadline d-flex p-0 list-group-item list-group-horizontal"
|
<div class="deadline d-flex p-0 list-group-item list-group-horizontal"
|
||||||
th:each="deadline, rowStat : *{deadlines}">
|
th:each="deadline, rowStat : *{deadlines}">
|
||||||
<input type="hidden" th:field="*{deadlines[__${rowStat.index}__].id}"/>
|
<input type="hidden" th:field="*{deadlines[__${rowStat.index}__].id}"/>
|
||||||
@ -58,11 +59,8 @@
|
|||||||
th:field="*{deadlines[__${rowStat.index}__].description}"/>
|
th:field="*{deadlines[__${rowStat.index}__].description}"/>
|
||||||
<input class="list-group-item" type="date" name="deadline"
|
<input class="list-group-item" type="date" name="deadline"
|
||||||
th:field="*{deadlines[__${rowStat.index}__].date}"/>
|
th:field="*{deadlines[__${rowStat.index}__].date}"/>
|
||||||
<img class="icon icon-delete grey-border" src="/img/conference/delete.png"
|
<input type="submit" class="icon icon-delete grey-border"
|
||||||
alt="Удалить"
|
alt="Удалить" name="removeDeadline" th:value="${rowStat.index}"/>
|
||||||
th:onclick="|$('#deadlines${rowStat.index}\\.description').val('');
|
|
||||||
$('#deadlines${rowStat.index}\\.date').val('');
|
|
||||||
$('#addDeadline').click();|"/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -136,23 +134,30 @@
|
|||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="papers">Статьи:</label>
|
<label for="papers">Статьи:</label>
|
||||||
<div class="paper-list form-control list-group" id="papers">
|
<div class="paper-list form-control list-group" id="papers">
|
||||||
<div class="paper d-flex list-group-item p-0">
|
<input th:type="hidden" th:field="*{papers}"/>
|
||||||
<a class="paper-name" href="/papers/papers">
|
<div class="paper d-flex list-group-item p-0"
|
||||||
<span>
|
th:each="paper, rowStat : *{papers}">
|
||||||
|
<a class="paper-name"
|
||||||
|
th:href="@{'/papers/paper?id=' + *{papers[__${rowStat.index}__].id} + ''}">
|
||||||
|
<span th:text="*{papers[__${rowStat.index}__].title}">
|
||||||
Имя статьи
|
Имя статьи
|
||||||
</span>
|
</span>
|
||||||
<img class="icon-paper" src="/img/conference/paper.png"/>
|
<img class="icon-paper" src="/img/conference/paper.png"/>
|
||||||
</a>
|
</a>
|
||||||
<img class="icon grey-border icon-delete" src="/img/conference/delete.png"
|
<input type="submit" class="icon icon-delete grey-border"
|
||||||
alt="Удалить"/>
|
alt="Удалить" name="removePaper" th:value="${rowStat.index}"/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="paper-control form-group d-flex justify-content-end">
|
<div class="paper-control form-group d-flex justify-content-end">
|
||||||
<button id="attach-paper" class="btn btn-primary"
|
<input th:type="hidden" th:field="*{notSelectedPapers}"/>
|
||||||
type="button">
|
<select class="selectpicker form-control" multiple="true" data-live-search="true"
|
||||||
Прикрепить статью
|
title="Прикрепить статью" data-style="btn-primary" data-size="5"
|
||||||
</button>
|
th:field="*{paperIds}">
|
||||||
|
<option th:each="paper: *{notSelectedPapers}" th:value="${paper.id}"
|
||||||
|
th:text="${paper.title}">Status
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
<button id="add-paper" class="btn btn-primary"
|
<button id="add-paper" class="btn btn-primary"
|
||||||
type="button">
|
type="button">
|
||||||
Добавить статью
|
Добавить статью
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout"
|
||||||
layout:decorator="default" xmlns:th="">
|
layout:decorator="default" xmlns:th="">
|
||||||
<head>
|
<head>
|
||||||
|
<link rel="stylesheet" type="text/css" href="../css/conference.css"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
@ -46,7 +47,7 @@
|
|||||||
|
|
||||||
<div id="modalDelete"/>
|
<div id="modalDelete"/>
|
||||||
</form>
|
</form>
|
||||||
<script></script>
|
<script src="../js/conference.js"></script>
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
|
@ -4,13 +4,13 @@
|
|||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div th:fragment="confLine (conference)" class="row text-left paper-row" style="background-color: white;">
|
<div th:fragment="confLine (conference)" class="row text-left conference-row h3" style="background-color: white;">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<a th:href="@{'conference?id='+${conference.id}}">
|
<a th:href="@{'conference?id='+${conference.id}}">
|
||||||
<span class="h6" th:text="${conference.title}"/>
|
<span class="h5" th:text="${conference.title}"/>
|
||||||
</a>
|
</a>
|
||||||
<input class="id-class" type="hidden"/>
|
<input class="id-class" type="hidden" th:value="${conference.id}"/>
|
||||||
<a class="remove-paper pull-right d-none"
|
<a class="remove-paper pull-right" th:href="@{'/conferences/delete/'+${conference.id}}"
|
||||||
data-confirm="Удалить статью?">
|
data-confirm="Удалить статью?">
|
||||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -10,12 +10,6 @@
|
|||||||
<!-- Portfolio Grid -->
|
<!-- Portfolio Grid -->
|
||||||
<section class="bg-light" id="portfolio">
|
<section class="bg-light" id="portfolio">
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12 text-center">
|
|
||||||
<h2 class="section-heading text-uppercase">Work hard</h2>
|
|
||||||
<h3 class="section-subheading text-muted">sometimes</h3>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-4 col-sm-6 portfolio-item">
|
<div class="col-md-4 col-sm-6 portfolio-item">
|
||||||
<a class="portfolio-link" href="./papers/papers">
|
<a class="portfolio-link" href="./papers/papers">
|
||||||
|
@ -7,14 +7,14 @@
|
|||||||
<div th:fragment="taskDashboard (task)" class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 dashboard-card">
|
<div th:fragment="taskDashboard (task)" class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3 dashboard-card">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<!--<span th:replace="students/fragments/taskStatusFragment :: taskStatus(taskStatus=${task.status})"/>-->
|
<span th:replace="students/fragments/taskStatusFragment :: taskStatus(taskStatus=${task.status})"/>
|
||||||
<span th:replace="students/fragments/taskStatusFragment"/>
|
<!--<span th:replace="students/fragments/taskStatusFragment"/>-->
|
||||||
</div>
|
</div>
|
||||||
<div class="col col-10 text-right">
|
<div class="col col-10 text-right">
|
||||||
<!--<h7 class="service-heading" th:text="${task.title}"> title</h7>-->
|
<h7 class="service-heading" th:text="${task.title}"> title</h7>
|
||||||
<!--<p class="text-muted" th:text="${task.typeString}">authors</p>-->
|
<p class="text-muted" th:text="${task.status.statusName}"> status</p>
|
||||||
<h7 class="service-heading" th:text="Title"> title</h7>
|
<!--<h7 class="service-heading" th:text="Title"> title</h7>-->
|
||||||
<p class="text-muted" th:text="Type">type</p>
|
<!--<p class="text-muted" th:text="Type">type</p>-->
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -4,15 +4,15 @@
|
|||||||
<meta charset="UTF-8"/>
|
<meta charset="UTF-8"/>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="row text-left task-row" style="background-color: white;">
|
<div th:fragment="taskLine (task)" class="row text-left task-row" style="background-color: white;">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<span th:replace="students/fragments/taskStatusFragment"/>
|
<span th:replace="students/fragments/taskStatusFragment :: taskStatus(taskStatus=${task.status})"/>
|
||||||
<a th:href="@{'task?id='+ 1}">
|
<a th:href="@{'task?id='+${task.id}}">
|
||||||
<span class="h6">Первая хадач</span>
|
<span class="h6" th:text="${task.title}"></span>
|
||||||
<span class="text-muted">Курсовая работа</span>
|
<span class="text-muted" th:text="${task.tagsString}"/>
|
||||||
</a>
|
</a>
|
||||||
<input class="id-class" type="hidden" th:value="1"/>
|
<input class="id-class" type="hidden" th:value="${task.id}"/>
|
||||||
<a class="remove-task pull-right d-none" th:href="@{'/students/delete/'+1}"
|
<a class="remove-task pull-right d-none" th:href="@{'/students/delete/'+${task.id}}"
|
||||||
data-confirm="Удалить задачу?">
|
data-confirm="Удалить задачу?">
|
||||||
<i class="fa fa-trash" aria-hidden="true"></i>
|
<i class="fa fa-trash" aria-hidden="true"></i>
|
||||||
</a>
|
</a>
|
||||||
|
@ -15,8 +15,8 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3">
|
<div class="col-12 col-sm-12 col-md-12 col-lg-4 col-xl-3">
|
||||||
<a href="./task" class="btn btn-light toolbar-button"><i class="fa fa-plus-circle"
|
<a href="./task?id=0" class="btn btn-light toolbar-button"><i class="fa fa-plus-circle"
|
||||||
aria-hidden="true"></i>
|
aria-hidden="true"></i>
|
||||||
Добавить задачу</a>
|
Добавить задачу</a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,18 +5,14 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<span th:fragment="taskStatus (taskStatus)" class="fa-stack fa-1x">
|
<span th:fragment="taskStatus (taskStatus)" class="fa-stack fa-1x">
|
||||||
<!--<th:block th:switch="${taskStatus.name()}">-->
|
<th:block th:switch="${taskStatus.name()}">
|
||||||
<th:block th:switch="'ON_PREPARATION'">
|
<!--<div th:case="'ATTENTION'">-->
|
||||||
<div th:case="'ATTENTION'">
|
<!--<i class="fa fa-circle fa-stack-2x text-warning"></i>-->
|
||||||
<i class="fa fa-circle fa-stack-2x text-warning"></i>
|
<!--</div>-->
|
||||||
</div>
|
<div th:case="'IN_WORK'">
|
||||||
<div th:case="'DRAFT'">
|
|
||||||
<i class="fa fa-circle fa-stack-2x text-draft"></i>
|
|
||||||
</div>
|
|
||||||
<div th:case="'ON_PREPARATION'">
|
|
||||||
<i class="fa fa-circle fa-stack-2x text-primary"></i>
|
<i class="fa fa-circle fa-stack-2x text-primary"></i>
|
||||||
</div>
|
</div>
|
||||||
<div th:case="'ON_REVIEW'">
|
<div th:case="'LOADED_FROM_KIAS'">
|
||||||
<i class="fa fa-circle fa-stack-2x text-review"></i>
|
<i class="fa fa-circle fa-stack-2x text-review"></i>
|
||||||
</div>
|
</div>
|
||||||
<div th:case="'COMPLETED'">
|
<div th:case="'COMPLETED'">
|
||||||
@ -25,12 +21,6 @@
|
|||||||
<div th:case="'FAILED'">
|
<div th:case="'FAILED'">
|
||||||
<i class="fa fa-circle fa-stack-2x text-failed"></i>
|
<i class="fa fa-circle fa-stack-2x text-failed"></i>
|
||||||
</div>
|
</div>
|
||||||
<div th:case="'ACCEPTED'">
|
|
||||||
<i class="fa fa-circle fa-stack-2x text-accepted"></i>
|
|
||||||
</div>
|
|
||||||
<div th:case="'NOT_ACCEPTED'">
|
|
||||||
<i class="fa fa-circle fa-stack-2x text-not-accepted"></i>
|
|
||||||
</div>
|
|
||||||
</th:block>
|
</th:block>
|
||||||
<i class="fa fa-check fa-stack-1x fa-inverse"></i>
|
<i class="fa fa-check fa-stack-1x fa-inverse"></i>
|
||||||
</span>
|
</span>
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
<div class="container" layout:fragment="content">
|
<div class="container" layout:fragment="content">
|
||||||
|
|
||||||
<section id="paper">
|
<section id="paper">
|
||||||
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-tagsinput/0.8.0/bootstrap-tagsinput.min.js"></script>
|
||||||
<div class="container">
|
<div class="container">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12 text-center">
|
<div class="col-lg-12 text-center">
|
||||||
@ -22,48 +23,72 @@
|
|||||||
<hr/>
|
<hr/>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-lg-12">
|
<div class="col-lg-12">
|
||||||
<form id="task-form" method="post">
|
<form id="task-form" method="post" th:action="@{'/students/task?id='+ *{id == null ? '' : id} + ''}"
|
||||||
|
th:object="${taskDto}">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-7 col-sm-12">
|
<div class="col-md-7 col-sm-12">
|
||||||
<input type="hidden" name="id"/>
|
<input type="hidden" name="id" th:field="*{id}"/>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="title">Название:</label>
|
<label for="title">Название:</label>
|
||||||
<input class="form-control" id="title" type="text" placeholder="Название задачи"/>
|
<input class="form-control" id="title" type="text" placeholder="Название задачи"
|
||||||
|
th:field="*{title}"/>
|
||||||
|
<p th:if="${#fields.hasErrors('title')}" th:errors="*{title}"
|
||||||
|
class="alert alert-danger">Incorrect title</p>
|
||||||
<p class="help-block text-danger"></p>
|
<p class="help-block text-danger"></p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="status">Статус:</label>
|
<label for="status">Статус:</label>
|
||||||
<select class="form-control" id="status">
|
<select class="form-control" id="status" th:field="*{status}">
|
||||||
<option>Status</option>
|
<option th:each="status : ${allStatuses}" th:value="${status}"
|
||||||
|
th:text="${status.statusName}">Status
|
||||||
|
</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="comment">Описание задачи:</label>
|
<label for="comment">Описание задачи:</label>
|
||||||
<textarea class="form-control" rows="3" id="comment"></textarea>
|
<textarea class="form-control" rows="3" id="comment"
|
||||||
|
th:field="*{description}"></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label for="tags">Теги:</label>
|
<label for="tags">Теги:</label>
|
||||||
<input class="form-control" data-role="tagsinput" placeholder="Теги задачи"
|
<div class="tags-container" id="tags">
|
||||||
id="tags"/>
|
<div class="tag" th:each="tag, rowStat : *{tags}">
|
||||||
|
<input type="hidden" th:field="*{tags[__${rowStat.index}__].id}"/>
|
||||||
|
<div class="tag-name">
|
||||||
|
<input type="text" readonly="true"
|
||||||
|
th:field="*{tags[__${rowStat.index}__].tagName}"/>
|
||||||
|
<span data-role="remove"></span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<input class="input-tag-name" type="text" placeholder="Теги задачи"
|
||||||
|
id="input-tag"/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label>Дедлайны задачи:</label>
|
<label>Дедлайны задачи:</label>
|
||||||
<div class="row">
|
<div class="row" th:each="deadline, rowStat : *{deadlines}">
|
||||||
<input type="hidden"/>
|
<input type="hidden" th:field="*{deadlines[__${rowStat.index}__].id}"/>
|
||||||
<div class="col-6">
|
<div class="col-6">
|
||||||
<input type="date" class="form-control" name="deadline"/>
|
<input type="date" class="form-control" name="deadline"
|
||||||
|
th:field="*{deadlines[__${rowStat.index}__].date}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-4">
|
<div class="col-4">
|
||||||
<input class="form-control" type="text" placeholder="Описание"/>
|
<input class="form-control" type="text" placeholder="Описание"
|
||||||
|
th:field="*{deadlines[__${rowStat.index}__].description}"/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-2">
|
<div class="col-2">
|
||||||
<a class="btn btn-danger float-right"><span
|
<a class="btn btn-danger float-right"
|
||||||
|
th:onclick="|$('#deadlines${rowStat.index}\\.description').val('');
|
||||||
|
$('#deadlines${rowStat.index}\\.date').val('');
|
||||||
|
$('#addDeadline').click();|"><span
|
||||||
aria-hidden="true"><i class="fa fa-times"/></span>
|
aria-hidden="true"><i class="fa fa-times"/></span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<p th:if="${#fields.hasErrors('deadlines')}" th:errors="*{deadlines}"
|
||||||
|
class="alert alert-danger">Incorrect title</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<input type="submit" id="addDeadline" name="addDeadline" class="btn btn-primary"
|
<input type="submit" id="addDeadline" name="addDeadline" class="btn btn-primary"
|
||||||
@ -76,10 +101,9 @@
|
|||||||
type="submit">
|
type="submit">
|
||||||
Сохранить
|
Сохранить
|
||||||
</button>
|
</button>
|
||||||
<button id="cancelButton" class="btn btn-default text-uppercase"
|
<a id="cancelButton" class="btn btn-default text-uppercase" href="/students/tasks">
|
||||||
href="/students/tasks">
|
|
||||||
Отмена
|
Отмена
|
||||||
</button>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-4 offset-md-1 col-sm-12 offset-sm-0">
|
<div class="col-md-4 offset-md-1 col-sm-12 offset-sm-0">
|
||||||
@ -89,8 +113,8 @@
|
|||||||
<h6 class="my-0">Дата создания:</h6>
|
<h6 class="my-0">Дата создания:</h6>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<small class="text-muted">
|
<small class="text-muted"
|
||||||
<!--th:text="${taskDto.createDate == null ? '' : #dates.format(taskDto.createDate, 'dd.MM.yyyy HH:mm')}">-->
|
th:text="${taskDto.createDate == null ? '' : #dates.format(taskDto.createDate, 'dd.MM.yyyy HH:mm')}">
|
||||||
text
|
text
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
@ -102,8 +126,8 @@
|
|||||||
<h6 class="my-0">Дата изменения:</h6>
|
<h6 class="my-0">Дата изменения:</h6>
|
||||||
</div>
|
</div>
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<small class="text-muted">
|
<small class="text-muted"
|
||||||
<!--th:text="${paperDto.updateDate == null ? '' : #dates.format(paperDto.updateDate, 'dd.MM.yyyy HH:mm')}">-->
|
th:text="${taskDto.updateDate == null ? '' : #dates.format(taskDto.updateDate, 'dd.MM.yyyy HH:mm')}">
|
||||||
text
|
text
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
@ -115,8 +139,8 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<script src="/js/tasks.js"></script>
|
||||||
</section>
|
</section>
|
||||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-tagsinput/0.8.0/bootstrap-tagsinput.min.js"></script>
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -20,38 +20,27 @@
|
|||||||
<hr/>
|
<hr/>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-md-9 col-sm-12">
|
<div class="col-md-9 col-sm-12">
|
||||||
<th:block>
|
<th:block th:each="task : ${tasks}">
|
||||||
<div th:replace="students/fragments/taskLineFragment"/>
|
<div th:replace="students/fragments/taskLineFragment :: taskLine(task=${task})"/>
|
||||||
</th:block>
|
</th:block>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-3 col-sm-12">
|
<div class="col-md-3 col-sm-12">
|
||||||
<div class="filter">
|
<div class="filter">
|
||||||
<h5>Фильтр:</h5>
|
<h5>Фильтр:</h5>
|
||||||
<select class="form-control" id="status"
|
<select class="form-control" id="status"
|
||||||
onchange="this.form.submit();">
|
onchange="this.form.submit();">
|
||||||
<option value="">Все статусы</option>
|
<option value="">Все статусы</option>
|
||||||
<!--<option th:each="author: ${allAuthors}" th:value="${author.id}"-->
|
<!--<option th:each="author: ${allAuthors}" th:value="${author.id}"-->
|
||||||
<!--th:text="${author.lastName}">lastName-->
|
<!--th:text="${author.lastName}">lastName-->
|
||||||
<!--</option>-->
|
<!--</option>-->
|
||||||
</select>
|
</select>
|
||||||
<select class="form-control" id="tags"
|
<select class="form-control" id="tags"
|
||||||
onchange="this.form.submit();">
|
onchange="this.form.submit();">
|
||||||
<option value="">Все типы</option>
|
<option value="">Все типы</option>
|
||||||
<option value="">Все типы</option>
|
<!--<option th:each="year: ${allYears}" th:value="${year}"-->
|
||||||
<option value="">Все типы</option>
|
<!--th:text="${year}">year-->
|
||||||
<option value="">Все типы</option>
|
<!--</option>-->
|
||||||
<option value="">Все типы</option>
|
</select>
|
||||||
<option value="">Все типы</option>
|
|
||||||
<option value="">Все типы</option>
|
|
||||||
<option value="">Все типы</option>
|
|
||||||
<option value="">Все типы</option>
|
|
||||||
<option value="">Все типы</option>
|
|
||||||
<option value="">Все типы</option>
|
|
||||||
<!--<option th:each="year: ${allYears}" th:value="${year}"-->
|
|
||||||
<!--th:text="${year}">year-->
|
|
||||||
<!--</option>-->
|
|
||||||
</select>
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user