diff --git a/src/main/java/ru/ulstu/grant/controller/GrantController.java b/src/main/java/ru/ulstu/grant/controller/GrantController.java new file mode 100644 index 0000000..415dd0b --- /dev/null +++ b/src/main/java/ru/ulstu/grant/controller/GrantController.java @@ -0,0 +1,101 @@ +package ru.ulstu.grant.controller; + +import org.springframework.stereotype.Controller; +import org.springframework.ui.ModelMap; +import org.springframework.validation.Errors; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.ModelAttribute; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import ru.ulstu.deadline.model.DeadlineDto; +import ru.ulstu.grant.model.Grant; +import ru.ulstu.grant.model.GrantDto; +import ru.ulstu.grant.service.GrantService; + +import javax.validation.Valid; +import java.io.IOException; +import java.util.List; +import java.util.stream.Collectors; + +import static org.springframework.util.StringUtils.isEmpty; + + +@Controller() +@RequestMapping(value = "/grants") +public class GrantController { + private final GrantService grantService; + + public GrantController(GrantService grantService) { + this.grantService = grantService; + } + + @GetMapping("/grants") + public void getGrants(ModelMap modelMap) { + modelMap.put("grants", grantService.findAllDto()); + } + + @GetMapping("/dashboard") + public void getDashboard(ModelMap modelMap) { + modelMap.put("grants", grantService.findAllDto()); + } + + @GetMapping("/grant") + public void getGrant(ModelMap modelMap, @RequestParam(value = "id") Integer id) { + if (id != null && id > 0) { + modelMap.put("grantDto", grantService.findOneDto(id)); + } else { + modelMap.put("grantDto", new GrantDto()); + } + } + + @PostMapping(value = "/grant", params = "save") + public String save(@Valid GrantDto grantDto, Errors errors) throws IOException { + filterEmptyDeadlines(grantDto); + if (grantDto.getDeadlines().isEmpty()) { + errors.rejectValue("deadlines", "errorCode", "Не может быть пустым"); + } + if (errors.hasErrors()) { + return "/grants/grant"; + } + grantService.save(grantDto); + return "redirect:/grants/grants"; + } + + @PostMapping(value = "/grant", params = "addDeadline") + public String addDeadline(@Valid GrantDto grantDto, Errors errors) { + filterEmptyDeadlines(grantDto); + if (errors.hasErrors()) { + return "/grants/grant"; + } + grantDto.getDeadlines().add(new DeadlineDto()); + return "/grants/grant"; + } + + @PostMapping(value = "/grant", params = "createProject") + public String createProject(@Valid GrantDto grantDto, Errors errors) { + if (errors.hasErrors()) { + return "/grants/grant"; + } + grantService.createProject(grantDto); + return "/grants/grant"; + } + + @GetMapping("/delete/{grant-id}") + public String delete(@PathVariable("grant-id") Integer grantId) throws IOException { + grantService.delete(grantId); + return "redirect:/grants/grants"; + } + + @ModelAttribute("allStatuses") + public List getGrantStatuses() { + return grantService.getGrantStatuses(); + } + + private void filterEmptyDeadlines(GrantDto grantDto) { + grantDto.setDeadlines(grantDto.getDeadlines().stream() + .filter(dto -> dto.getDate() != null || !isEmpty(dto.getDescription())) + .collect(Collectors.toList())); + } +} diff --git a/src/main/java/ru/ulstu/grant/model/Grant.java b/src/main/java/ru/ulstu/grant/model/Grant.java index 092317b..8d40e3a 100644 --- a/src/main/java/ru/ulstu/grant/model/Grant.java +++ b/src/main/java/ru/ulstu/grant/model/Grant.java @@ -2,22 +2,28 @@ package ru.ulstu.grant.model; import org.hibernate.validator.constraints.NotBlank; import ru.ulstu.core.model.BaseEntity; -import ru.ulstu.core.model.UserContainer; import ru.ulstu.deadline.model.Deadline; import ru.ulstu.file.model.FileData; import ru.ulstu.project.model.Project; -import ru.ulstu.user.model.User; -import javax.persistence.*; +import javax.persistence.CascadeType; +import javax.persistence.Entity; +import javax.persistence.EnumType; +import javax.persistence.Enumerated; +import javax.persistence.JoinColumn; +import javax.persistence.ManyToOne; +import javax.persistence.OneToMany; +import javax.persistence.Table; import javax.validation.constraints.NotNull; import java.util.ArrayList; +import java.util.Comparator; import java.util.Date; -import java.util.HashSet; import java.util.List; -import java.util.Set; +import java.util.Optional; @Entity -public class Grant extends BaseEntity { +@Table(name = "grants") +public class Grant extends BaseEntity { public enum GrantStatus { APPLICATION("Заявка"), ON_COMPETITION("Отправлен на конкурс"), @@ -26,14 +32,14 @@ public class Grant extends BaseEntity { COMPLETED("Завершен"), FAILED("Провалены сроки"); - private String name; + private String statusName; - GrantStatus(String name) { - this.name = name; + GrantStatus(String statusName) { + this.statusName = statusName; } - public String getName() { - return name; + public String getStatusName() { + return statusName; } } @@ -88,13 +94,17 @@ public class Grant extends BaseEntity { return application; } - public void setApplication(FileData application) { this.application = application; } + public void setApplication(FileData application) { + this.application = application; + } public String getTitle() { return title; } - public void setTitle(String title) { this.title = title; } + public void setTitle(String title) { + this.title = title; + } public Project getProject() { return project; @@ -103,4 +113,13 @@ public class Grant extends BaseEntity { public void setProject(Project project) { this.project = project; } + + public Optional getNextDeadline() { + return deadlines + .stream() + .filter(deadline -> deadline.getDate() != null) + .sorted(Comparator.comparing(Deadline::getDate)) + .filter(d -> d.getDate().after(new Date())) + .findFirst(); + } } diff --git a/src/main/java/ru/ulstu/grant/model/GrantDto.java b/src/main/java/ru/ulstu/grant/model/GrantDto.java index 922df89..0f1850a 100644 --- a/src/main/java/ru/ulstu/grant/model/GrantDto.java +++ b/src/main/java/ru/ulstu/grant/model/GrantDto.java @@ -4,21 +4,27 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.hibernate.validator.constraints.NotEmpty; import ru.ulstu.deadline.model.DeadlineDto; +import ru.ulstu.grant.model.Grant; import ru.ulstu.project.model.ProjectDto; +import java.util.ArrayList; import java.util.List; import static ru.ulstu.core.util.StreamApiUtils.convert; public class GrantDto { - private final Integer id; + private Integer id; @NotEmpty - private final String title; - private final Grant.GrantStatus status; - private final List deadlines; - private final String comment; - private final String applicationFileName; - private final ProjectDto project; + private String title; + private Grant.GrantStatus status; + private List deadlines = new ArrayList<>(); + private String comment; + private String applicationFileName; + private ProjectDto project; + + public GrantDto() { + deadlines.add(new DeadlineDto()); + } @JsonCreator public GrantDto(@JsonProperty("id") Integer id, @@ -50,27 +56,46 @@ public class GrantDto { return id; } + public void setId(Integer id) {this.id = id;} + public String getTitle() { return title; } + public void setTitle(String title) {this.title = title;} + public Grant.GrantStatus getStatus() { return status; } + public void setStatus(Grant.GrantStatus status) { + this.status = status; + } + public List getDeadlines() { return deadlines; } + public void setDeadlines(List deadlines) { + this.deadlines = deadlines; + } + public String getComment() { return comment; } + public void setComment(String comment) {this.comment = comment;} + public ProjectDto getProject() { return project; } + public void setProject(ProjectDto project) {this.project = project;} + public String getApplicationFileName() { return applicationFileName; } + + public void setApplicationFileName(String applicationFileName) { + this.applicationFileName = applicationFileName;} } diff --git a/src/main/java/ru/ulstu/grant/model/GrantStatusDto.java b/src/main/java/ru/ulstu/grant/model/GrantStatusDto.java index dae40e2..34676d6 100644 --- a/src/main/java/ru/ulstu/grant/model/GrantStatusDto.java +++ b/src/main/java/ru/ulstu/grant/model/GrantStatusDto.java @@ -6,7 +6,7 @@ public class GrantStatusDto { public GrantStatusDto(Grant.GrantStatus status) { this.id = status.name(); - this.name = status.getName(); + this.name = status.getStatusName(); } public String getId() { diff --git a/src/main/java/ru/ulstu/grant/repository/GrantRepository.java b/src/main/java/ru/ulstu/grant/repository/GrantRepository.java new file mode 100644 index 0000000..92dec43 --- /dev/null +++ b/src/main/java/ru/ulstu/grant/repository/GrantRepository.java @@ -0,0 +1,8 @@ +package ru.ulstu.grant.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.ulstu.grant.model.Grant; + +public interface GrantRepository extends JpaRepository { + +} diff --git a/src/main/java/ru/ulstu/grant/service/GrantService.java b/src/main/java/ru/ulstu/grant/service/GrantService.java new file mode 100644 index 0000000..31d0a04 --- /dev/null +++ b/src/main/java/ru/ulstu/grant/service/GrantService.java @@ -0,0 +1,128 @@ +package ru.ulstu.grant.service; + +import org.apache.commons.lang3.StringUtils; +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.service.FileService; +import ru.ulstu.grant.model.Grant; +import ru.ulstu.grant.model.GrantDto; +import ru.ulstu.grant.repository.GrantRepository; +import ru.ulstu.project.model.Project; +import ru.ulstu.project.model.ProjectDto; +import ru.ulstu.project.service.ProjectService; + +import 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.grant.model.Grant.GrantStatus.APPLICATION; + +@Service +public class GrantService { + private final static int MAX_DISPLAY_SIZE = 40; + + private final GrantRepository grantRepository; + private final ProjectService projectService; + private final DeadlineService deadlineService; + private final FileService fileService; + + public GrantService(GrantRepository grantRepository, + FileService fileService, + DeadlineService deadlineService, + ProjectService projectService) { + this.grantRepository = grantRepository; + this.projectService = projectService; + this.fileService = fileService; + this.deadlineService = deadlineService; + } + + public List findAll() { + return grantRepository.findAll(); + } + + public List findAllDto() { + List grants = convert(findAll(), GrantDto::new); + grants.forEach(grantDto -> grantDto.setTitle(StringUtils.abbreviate(grantDto.getTitle(), MAX_DISPLAY_SIZE))); + return grants; + } + + public GrantDto findOneDto(Integer 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); + return newGrant.getId(); + } + + private Grant copyFromDto(Grant grant, GrantDto grantDto) throws IOException { + grant.setComment(grantDto.getComment()); + grant.setStatus(grantDto.getStatus() == null ? APPLICATION : grantDto.getStatus()); + grant.setTitle(grantDto.getTitle()); + if (grantDto.getProject() != null && grantDto.getProject().getId() != null) { + grant.setProject(projectService.findById(grantDto.getProject().getId())); + } + grant.setDeadlines(deadlineService.saveOrCreate(grantDto.getDeadlines())); + if (grantDto.getApplicationFileName() != null) { + grant.setApplication(fileService.createFileFromTmp(grantDto.getApplicationFileName())); + } + return grant; + } + + public void createProject(GrantDto grantDto) { + grantDto.setProject( + new ProjectDto(projectService.save(new ProjectDto(grantDto.getTitle())))); + } + + @Transactional + public Integer update(GrantDto grantDto) throws IOException { + Grant grant = grantRepository.findOne(grantDto.getId()); + Grant.GrantStatus oldStatus = grant.getStatus(); + if (grantDto.getApplicationFileName() != null && grant.getApplication() != null) { + fileService.deleteFile(grant.getApplication()); + } + grantRepository.save(copyFromDto(grant, grantDto)); + return grant.getId(); + } + + @Transactional + public void delete(Integer grantId) throws IOException { + Grant grant = grantRepository.findOne(grantId); + if (grant.getApplication() != null) { + fileService.deleteFile(grant.getApplication()); + } + //возможно при удалении гранта будет удаляться и проект, к нему привязанный + grantRepository.delete(grant); + } + + public List getGrantStatuses() { + return Arrays.asList(Grant.GrantStatus.values()); + } + + @Transactional + public Grant create(String title, Project project_id, Date deadlineDate) { + Grant grant = new Grant(); + grant.setTitle(title); + grant.setComment("Комментарий к гранту 1"); + grant.setProject(project_id); + grant.setStatus(APPLICATION); + grant.getDeadlines().add(new Deadline(deadlineDate, "первый дедлайн")); + grant = grantRepository.save(grant); + return grant; + } + + public void save(GrantDto grantDto) throws IOException { + if (isEmpty(grantDto.getId())) { + create(grantDto); + } else { + update(grantDto); + } + } +} diff --git a/src/main/java/ru/ulstu/project/model/ProjectDto.java b/src/main/java/ru/ulstu/project/model/ProjectDto.java index 69e9b1b..7c2664e 100644 --- a/src/main/java/ru/ulstu/project/model/ProjectDto.java +++ b/src/main/java/ru/ulstu/project/model/ProjectDto.java @@ -4,18 +4,26 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import org.hibernate.validator.constraints.NotEmpty; import ru.ulstu.deadline.model.DeadlineDto; +import ru.ulstu.project.model.Project; +import java.util.ArrayList; import java.util.List; import static ru.ulstu.core.util.StreamApiUtils.convert; public class ProjectDto { - private final Integer id; + private Integer id; @NotEmpty - private final String title; + private String title; - private final List deadlines; + private List deadlines = new ArrayList<>(); + + public ProjectDto() {} + + public ProjectDto(String title) { + this.title = title; + } @JsonCreator public ProjectDto(@JsonProperty("id") Integer id, @@ -26,6 +34,7 @@ public class ProjectDto { this.deadlines = deadlines; } + public ProjectDto(Project project) { this.id = project.getId(); this.title = project.getTitle(); @@ -39,4 +48,19 @@ public class ProjectDto { public String getTitle() { return title; } + + public void setId(Integer id) { + this.id = id; + } + + public void setTitle(String title) { + this.title = title; + } + + public void setDeadlines(List deadlines) { + this.deadlines = deadlines; + } + public List getDeadlines() { + return deadlines; + } } diff --git a/src/main/java/ru/ulstu/project/repository/ProjectRepository.java b/src/main/java/ru/ulstu/project/repository/ProjectRepository.java new file mode 100644 index 0000000..6a78075 --- /dev/null +++ b/src/main/java/ru/ulstu/project/repository/ProjectRepository.java @@ -0,0 +1,8 @@ +package ru.ulstu.project.repository; + +import org.springframework.data.jpa.repository.JpaRepository; +import ru.ulstu.project.model.Project; + +public interface ProjectRepository extends JpaRepository { + +} diff --git a/src/main/java/ru/ulstu/project/service/ProjectService.java b/src/main/java/ru/ulstu/project/service/ProjectService.java new file mode 100644 index 0000000..b54a60a --- /dev/null +++ b/src/main/java/ru/ulstu/project/service/ProjectService.java @@ -0,0 +1,59 @@ +package ru.ulstu.project.service; + +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.ulstu.deadline.service.DeadlineService; +import ru.ulstu.project.model.Project; +import ru.ulstu.project.model.ProjectDto; +import ru.ulstu.project.repository.ProjectRepository; + +import java.util.List; + +import static org.springframework.util.ObjectUtils.isEmpty; + +@Service +public class ProjectService { + + private final ProjectRepository projectRepository; + private final DeadlineService deadlineService; + + public ProjectService(ProjectRepository projectRepository, + DeadlineService deadlineService) { + this.projectRepository = projectRepository; + this.deadlineService = deadlineService; + } + + public List findAll() { + return projectRepository.findAll(); + } + + @Transactional + public Project create(ProjectDto projectDto) { + Project newProject = copyFromDto(new Project(), projectDto); + newProject = projectRepository.save(newProject); + return newProject; + } + + private Project copyFromDto(Project project, ProjectDto projectDto) { + project.setTitle(projectDto.getTitle()); + project.setDeadlines(deadlineService.saveOrCreate(projectDto.getDeadlines())); + return project; + } + + public Project save(ProjectDto projectDto) { + if (isEmpty(projectDto.getId())) { + return create(projectDto); + } else { + return update(projectDto); + } + } + + private Project update(ProjectDto projectDto) { + throw new RuntimeException("not implemented yet"); + } + + public Project findById(Integer id) { + return projectRepository.findOne(id); + } + +} diff --git a/src/main/resources/db/changelog-20181224_000000-schema.xml b/src/main/resources/db/changelog-20181224_000000-schema.xml new file mode 100644 index 0000000..61f932b --- /dev/null +++ b/src/main/resources/db/changelog-20181224_000000-schema.xml @@ -0,0 +1,9 @@ + + + + + + diff --git a/src/main/resources/db/changelog-master.xml b/src/main/resources/db/changelog-master.xml index 6c7147b..c07b1df 100644 --- a/src/main/resources/db/changelog-master.xml +++ b/src/main/resources/db/changelog-master.xml @@ -17,4 +17,5 @@ + \ No newline at end of file diff --git a/src/main/resources/public/js/grants.js b/src/main/resources/public/js/grants.js new file mode 100644 index 0000000..c33b4df --- /dev/null +++ b/src/main/resources/public/js/grants.js @@ -0,0 +1,42 @@ +/*\n' + + ' \n' + + ' '); + } + $('#dataConfirmModal').find('#myModalLabel').text($(this).attr('data-confirm')); + $('#dataConfirmOK').attr('href', href); + $('#dataConfirmModal').modal({show:true}); + return false; + }); +}); +/*]]>*/ \ No newline at end of file diff --git a/src/main/resources/templates/grants/dashboard.html b/src/main/resources/templates/grants/dashboard.html index afadb51..b469875 100644 --- a/src/main/resources/templates/grants/dashboard.html +++ b/src/main/resources/templates/grants/dashboard.html @@ -1,177 +1,24 @@ + layout:decorator="default" xmlns:th="http://www.w3.org/1999/xhtml"> -
-
-
- +
+

Гранты

+
-
-
-
-
- - - - -
- -
- Название гранта -

Краткое описание

-

Статус: статус

-
- -
-
-
-
-
- - - - -
-
- Название гранта -

Краткое описание

-

Статус: статус

-
-
-
-
-
-
- - - - -
-
- Название гранта -

Краткое описание

-

Статус: статус

-
-
-
-
-
-
- - - - -
-
- Название гранта -

Краткое описание

-

Статус: статус

-
-
-
-
-
-
- - - - -
-
- Название гранта -

Краткое описание

-

Статус: статус

-
-
-
-
-
-
- - - - -
-
- Название гранта -

Краткое описание

-

Статус: статус

-
-
-
-
-
-
- - - - -
-
- Название гранта -

Краткое описание

-

Статус: статус

-
-
-
-
-
-
- - - - -
-
- Название гранта -

Краткое описание

-

Статус: статус

-
-
-
-
-
-
- - - - -
-
- Название гранта -

Краткое описание

-

Статус: статус

-
-
-
+
+ +
+
-
- \ No newline at end of file diff --git a/src/main/resources/templates/grants/fragments/grantDashboardFragment.html b/src/main/resources/templates/grants/fragments/grantDashboardFragment.html new file mode 100644 index 0000000..df3e3d0 --- /dev/null +++ b/src/main/resources/templates/grants/fragments/grantDashboardFragment.html @@ -0,0 +1,19 @@ + + + + + + +
+
+
+ +
+
+ title +

status

+
+
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/grants/fragments/grantLineFragment.html b/src/main/resources/templates/grants/fragments/grantLineFragment.html new file mode 100644 index 0000000..1048897 --- /dev/null +++ b/src/main/resources/templates/grants/fragments/grantLineFragment.html @@ -0,0 +1,22 @@ + + + + + + +
+
+ + + + + + + + + +
+
+ + \ No newline at end of file diff --git a/src/main/resources/templates/grants/fragments/grantNavigationFragment.html b/src/main/resources/templates/grants/fragments/grantNavigationFragment.html new file mode 100644 index 0000000..7545077 --- /dev/null +++ b/src/main/resources/templates/grants/fragments/grantNavigationFragment.html @@ -0,0 +1,26 @@ + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/templates/grants/fragments/grantStatusFragment.html b/src/main/resources/templates/grants/fragments/grantStatusFragment.html new file mode 100644 index 0000000..a8a4d9e --- /dev/null +++ b/src/main/resources/templates/grants/fragments/grantStatusFragment.html @@ -0,0 +1,31 @@ + + + + + + + + +
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+ + \ No newline at end of file diff --git a/src/main/resources/templates/grants/grant.html b/src/main/resources/templates/grants/grant.html index 2f74adb..2e1e281 100644 --- a/src/main/resources/templates/grants/grant.html +++ b/src/main/resources/templates/grants/grant.html @@ -1,7 +1,7 @@ + layout:decorator="default" xmlns:th="http://www.w3.org/1999/xhtml" xmlns="http://www.w3.org/1999/html"> @@ -14,49 +14,68 @@

Редактирование гранта

- +
-
+
+
- - + + +

Incorrect title

- +
-
- + +
+
+ +
+ +
+ +
+
+ +
+
+ + +
+
+

Incorrect title

- - +
+
@@ -70,100 +89,22 @@
- -

Добавить проект

-
-
- -

Добавить показатель

-
-
- -

Добавить показатель

-
-
- - -
-

Редактировать - участников гранта

-
- -
@@ -188,10 +129,7 @@ console.debug(response); } }); - - getFromRest(urlPaperStatuses, function (response) { - fillSelect($("#status"), response); - }); + $('.selectpicker').selectpicker(); }); /*]]>*/ diff --git a/src/main/resources/templates/grants/grants.html b/src/main/resources/templates/grants/grants.html new file mode 100644 index 0000000..83083a0 --- /dev/null +++ b/src/main/resources/templates/grants/grants.html @@ -0,0 +1,36 @@ + + + + + +
+ + +
+
+
+
+

Гранты

+
+
+
+
+
+ +
+ +
+
+
+
+
+
+ +
+ + +
+ +