diff --git a/src/main/java/ru/ulstu/project/model/Project.java b/src/main/java/ru/ulstu/project/model/Project.java index 27a4ae6..0c0af94 100644 --- a/src/main/java/ru/ulstu/project/model/Project.java +++ b/src/main/java/ru/ulstu/project/model/Project.java @@ -69,9 +69,10 @@ public class Project extends BaseEntity implements UserContainer { @NotNull private String repository; - @ManyToOne - @JoinColumn(name = "file_id") - private FileData application; + @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER) + @JoinColumn(name = "project_id", unique = true) + @Fetch(FetchMode.SUBSELECT) + private List files = new ArrayList<>(); @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @JoinColumn(name = "project_id") @@ -135,12 +136,12 @@ public class Project extends BaseEntity implements UserContainer { this.deadlines = deadlines; } - public FileData getApplication() { - return application; + public List getFiles() { + return files; } - public void setApplication(FileData application) { - this.application = application; + public void setFiles(List files) { + this.files = files; } public List getEvents() { diff --git a/src/main/java/ru/ulstu/project/model/ProjectDto.java b/src/main/java/ru/ulstu/project/model/ProjectDto.java index 7da4ac4..fb60703 100644 --- a/src/main/java/ru/ulstu/project/model/ProjectDto.java +++ b/src/main/java/ru/ulstu/project/model/ProjectDto.java @@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.hibernate.validator.constraints.NotEmpty; import org.thymeleaf.util.StringUtils; import ru.ulstu.deadline.model.Deadline; -import ru.ulstu.grant.model.Grant; +import ru.ulstu.file.model.FileDataDto; import ru.ulstu.grant.model.GrantDto; import ru.ulstu.user.model.User; import ru.ulstu.user.model.UserDto; @@ -28,7 +28,7 @@ public class ProjectDto { private List deadlines = new ArrayList<>(); private GrantDto grant; private String repository; - private String applicationFileName; + private List files = new ArrayList<>(); private List removedDeadlineIds = new ArrayList<>(); private Set executorIds; private List executors; @@ -51,6 +51,7 @@ public class ProjectDto { @JsonProperty("description") String description, @JsonProperty("grant") GrantDto grant, @JsonProperty("repository") String repository, + @JsonProperty("files") List files, @JsonProperty("deadlines") List deadlines, @JsonProperty("executorIds") Set executorIds, @JsonProperty("executors") List executors, @@ -63,7 +64,7 @@ public class ProjectDto { this.grant = grant; this.repository = repository; this.deadlines = deadlines; - this.applicationFileName = null; + this.files = files; this.executorIds = executorIds; this.executors = executors; this.grantIds = grantIds; @@ -77,7 +78,7 @@ public class ProjectDto { this.title = project.getTitle(); this.status = project.getStatus(); this.description = project.getDescription(); - this.applicationFileName = project.getApplication() == null ? null : project.getApplication().getName(); + this.files = convert(project.getFiles(), FileDataDto::new); this.grant = project.getGrant() == null ? null : new GrantDto(project.getGrant()); this.repository = project.getRepository(); this.deadlines = project.getDeadlines(); @@ -143,12 +144,12 @@ public class ProjectDto { this.deadlines = deadlines; } - public String getApplicationFileName() { - return applicationFileName; + public List getFiles() { + return files; } - public void setApplicationFileName(String applicationFileName) { - this.applicationFileName = applicationFileName; + public void setFiles(List files) { + this.files = files; } public List getRemovedDeadlineIds() { diff --git a/src/main/java/ru/ulstu/project/service/ProjectService.java b/src/main/java/ru/ulstu/project/service/ProjectService.java index fe0671c..e77cc88 100644 --- a/src/main/java/ru/ulstu/project/service/ProjectService.java +++ b/src/main/java/ru/ulstu/project/service/ProjectService.java @@ -4,6 +4,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.thymeleaf.util.StringUtils; import ru.ulstu.deadline.service.DeadlineService; +import ru.ulstu.file.model.FileDataDto; import ru.ulstu.file.service.FileService; import ru.ulstu.grant.model.GrantDto; import ru.ulstu.grant.repository.GrantRepository; @@ -19,6 +20,7 @@ import java.util.Arrays; import java.util.List; import java.util.Set; +import static java.util.stream.Collectors.toList; import static org.springframework.util.ObjectUtils.isEmpty; import static ru.ulstu.core.util.StreamApiUtils.convert; import static ru.ulstu.project.model.Project.ProjectStatus.TECHNICAL_TASK; @@ -77,20 +79,19 @@ public class ProjectService { @Transactional public Project update(ProjectDto projectDto) throws IOException { Project project = projectRepository.findOne(projectDto.getId()); - if (projectDto.getApplicationFileName() != null && project.getApplication() != null) { - fileService.deleteFile(project.getApplication()); - } projectRepository.save(copyFromDto(project, projectDto)); eventService.updateProjectDeadlines(project); + for (FileDataDto file : projectDto.getFiles().stream() + .filter(f -> f.isDeleted() && f.getId() != null) + .collect(toList())) { + fileService.delete(file.getId()); + } return project; } @Transactional public void delete(Integer projectId) throws IOException { Project project = projectRepository.findOne(projectId); - if (project.getApplication() != null) { - fileService.deleteFile(project.getApplication()); - } projectRepository.delete(project); } @@ -103,9 +104,9 @@ public class ProjectService { } project.setRepository(projectDto.getRepository()); project.setDeadlines(deadlineService.saveOrCreate(projectDto.getDeadlines())); - if (projectDto.getApplicationFileName() != null) { - project.setApplication(fileService.createFileFromTmp(projectDto.getApplicationFileName())); - } + project.setFiles(fileService.saveOrCreate(projectDto.getFiles().stream() + .filter(f -> !f.isDeleted()) + .collect(toList()))); project.getGrants().clear(); if (projectDto.getGrantIds() != null && !projectDto.getGrantIds().isEmpty()) { projectDto.getGrantIds().forEach(grantIds -> project.getGrants().add(grantRepository.findGrantById(grantIds))); diff --git a/src/main/resources/db/changelog-20190529_000001-schema.xml b/src/main/resources/db/changelog-20190529_000001-schema.xml new file mode 100644 index 0000000..0b6548b --- /dev/null +++ b/src/main/resources/db/changelog-20190529_000001-schema.xml @@ -0,0 +1,13 @@ + + + + + + + + + diff --git a/src/main/resources/db/changelog-master.xml b/src/main/resources/db/changelog-master.xml index 6dadded..529b597 100644 --- a/src/main/resources/db/changelog-master.xml +++ b/src/main/resources/db/changelog-master.xml @@ -51,4 +51,5 @@ + \ No newline at end of file diff --git a/src/main/resources/templates/projects/fragments/projectFilesListFragment.html b/src/main/resources/templates/projects/fragments/projectFilesListFragment.html new file mode 100644 index 0000000..0e803d9 --- /dev/null +++ b/src/main/resources/templates/projects/fragments/projectFilesListFragment.html @@ -0,0 +1,40 @@ + + + + + + + +
+ + +
+ + + + +
+ + + +
+
+ + +
+
+
+
+ + + + + \ No newline at end of file diff --git a/src/main/resources/templates/projects/project.html b/src/main/resources/templates/projects/project.html index 67dac69..0d132e9 100644 --- a/src/main/resources/templates/projects/project.html +++ b/src/main/resources/templates/projects/project.html @@ -119,6 +119,13 @@ value="Добавить дедлайн"/> +
+ + +
+ +
+
@@ -154,17 +161,103 @@ new FileLoader({ div: "loader", url: urlFileUpload, - maxSize: 2, - extensions: ["doc", "docx", "xls", "jpg", "png", "pdf", "txt"], + maxSize: -1, + extensions: [], callback: function (response) { showFeedbackMessage("Файл успешно загружен"); console.debug(response); + + addNewFile(response, $("#files-list")); } }); $('.selectpicker').selectpicker(); }); /*]]>*/ + function addNewFile(fileDto, listElement) { + var fileNumber = $('.files-list div.row').length; + var newFileRow = $("
") + .attr("id", 'files' + fileNumber) + .addClass("row"); + + var idInput = $("") + .attr("type", "hidden") + .attr("id", "files" + fileNumber + ".id") + .attr("value", '') + .attr("name", "files[" + fileNumber + "].id"); + newFileRow.append(idInput); + + var flagInput = $("") + .attr("type", "hidden") + .attr("id", "files" + fileNumber + ".deleted") + .attr("value", "false") + .attr("name", "files[" + fileNumber + "].deleted"); + newFileRow.append(flagInput); + + var nameInput = $("") + .attr("type", "hidden") + .attr("id", "files" + fileNumber + ".name") + .attr("value", fileDto.fileName) + .attr("name", "files[" + fileNumber + "].name"); + newFileRow.append(nameInput); + + var tmpFileNameInput = $("") + .attr("type", "hidden") + .attr("id", "files" + fileNumber + ".tmpFileName") + .attr("value", fileDto.tmpFileName) + .attr("name", "files[" + fileNumber + "].tmpFileName"); + newFileRow.append(tmpFileNameInput); + + var nextDiv = $("
") + .addClass("col-2"); + + var nextA = $("") + .addClass("btn btn-danger float-right") + .attr("onclick", "$('#files" + fileNumber + "\\\\.deleted').val('true'); $('#files" + fileNumber + "').hide();") + .append(($("").attr("aria-hidden", "true")).append($("").addClass("fa fa-times"))) + ; + nextDiv.append(nextA) + newFileRow.append(nextDiv); + + var nameDiv = $("
") + .addClass("col-10") + .append($("").text(fileDto.fileName) + .attr("href", 'javascript:void(0)') + .attr("onclick", "downloadFile('" + fileDto.tmpFileName + "',null,'" + fileDto.fileName + "')")); + newFileRow.append(nameDiv); + + listElement.append(newFileRow); + + } + + function downloadFile(tmpName, fileId, downloadName) { + let xhr = new XMLHttpRequest(); + if (fileId != null) xhr.open('GET', urlFileDownload + fileId); + if (tmpName != null) xhr.open('GET', urlFileDownloadTmp + tmpName); + xhr.responseType = 'blob'; + + var formData = new FormData(); + if (fileId != null) formData.append("file-id", fileId); + if (tmpName != null) formData.append("tmp-file-name", tmpName); + + xhr.send(formData); + + xhr.onload = function () { + if (this.status == 200) { + console.debug(this.response); + var blob = new Blob([this.response], {type: '*'}); + let a = document.createElement("a"); + a.style = "display: none"; + document.body.appendChild(a); + let url = window.URL.createObjectURL(blob); + a.href = url; + a.download = downloadName; + a.click(); + window.URL.revokeObjectURL(url); + } else { + } + } + }