#101 files attach modified

This commit is contained in:
a.vasin 2019-05-30 00:08:13 +04:00
parent 9013d79228
commit 632c6299b7
7 changed files with 176 additions and 26 deletions

View File

@ -69,9 +69,10 @@ public class Project extends BaseEntity implements UserContainer {
@NotNull @NotNull
private String repository; private String repository;
@ManyToOne @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinColumn(name = "file_id") @JoinColumn(name = "project_id", unique = true)
private FileData application; @Fetch(FetchMode.SUBSELECT)
private List<FileData> files = new ArrayList<>();
@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@JoinColumn(name = "project_id") @JoinColumn(name = "project_id")
@ -135,12 +136,12 @@ public class Project extends BaseEntity implements UserContainer {
this.deadlines = deadlines; this.deadlines = deadlines;
} }
public FileData getApplication() { public List<FileData> getFiles() {
return application; return files;
} }
public void setApplication(FileData application) { public void setFiles(List<FileData> files) {
this.application = application; this.files = files;
} }
public List<Event> getEvents() { public List<Event> getEvents() {

View File

@ -5,7 +5,7 @@ import com.fasterxml.jackson.annotation.JsonProperty;
import org.hibernate.validator.constraints.NotEmpty; import org.hibernate.validator.constraints.NotEmpty;
import org.thymeleaf.util.StringUtils; import org.thymeleaf.util.StringUtils;
import ru.ulstu.deadline.model.Deadline; 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.grant.model.GrantDto;
import ru.ulstu.user.model.User; import ru.ulstu.user.model.User;
import ru.ulstu.user.model.UserDto; import ru.ulstu.user.model.UserDto;
@ -28,7 +28,7 @@ public class ProjectDto {
private List<Deadline> deadlines = new ArrayList<>(); private List<Deadline> deadlines = new ArrayList<>();
private GrantDto grant; private GrantDto grant;
private String repository; private String repository;
private String applicationFileName; private List<FileDataDto> files = new ArrayList<>();
private List<Integer> removedDeadlineIds = new ArrayList<>(); private List<Integer> removedDeadlineIds = new ArrayList<>();
private Set<Integer> executorIds; private Set<Integer> executorIds;
private List<UserDto> executors; private List<UserDto> executors;
@ -51,6 +51,7 @@ public class ProjectDto {
@JsonProperty("description") String description, @JsonProperty("description") String description,
@JsonProperty("grant") GrantDto grant, @JsonProperty("grant") GrantDto grant,
@JsonProperty("repository") String repository, @JsonProperty("repository") String repository,
@JsonProperty("files") List<FileDataDto> files,
@JsonProperty("deadlines") List<Deadline> deadlines, @JsonProperty("deadlines") List<Deadline> deadlines,
@JsonProperty("executorIds") Set<Integer> executorIds, @JsonProperty("executorIds") Set<Integer> executorIds,
@JsonProperty("executors") List<UserDto> executors, @JsonProperty("executors") List<UserDto> executors,
@ -63,7 +64,7 @@ public class ProjectDto {
this.grant = grant; this.grant = grant;
this.repository = repository; this.repository = repository;
this.deadlines = deadlines; this.deadlines = deadlines;
this.applicationFileName = null; this.files = files;
this.executorIds = executorIds; this.executorIds = executorIds;
this.executors = executors; this.executors = executors;
this.grantIds = grantIds; this.grantIds = grantIds;
@ -77,7 +78,7 @@ public class ProjectDto {
this.title = project.getTitle(); this.title = project.getTitle();
this.status = project.getStatus(); this.status = project.getStatus();
this.description = project.getDescription(); 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.grant = project.getGrant() == null ? null : new GrantDto(project.getGrant());
this.repository = project.getRepository(); this.repository = project.getRepository();
this.deadlines = project.getDeadlines(); this.deadlines = project.getDeadlines();
@ -143,12 +144,12 @@ public class ProjectDto {
this.deadlines = deadlines; this.deadlines = deadlines;
} }
public String getApplicationFileName() { public List<FileDataDto> getFiles() {
return applicationFileName; return files;
} }
public void setApplicationFileName(String applicationFileName) { public void setFiles(List<FileDataDto> files) {
this.applicationFileName = applicationFileName; this.files = files;
} }
public List<Integer> getRemovedDeadlineIds() { public List<Integer> getRemovedDeadlineIds() {

View File

@ -4,6 +4,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.thymeleaf.util.StringUtils; import org.thymeleaf.util.StringUtils;
import ru.ulstu.deadline.service.DeadlineService; import ru.ulstu.deadline.service.DeadlineService;
import ru.ulstu.file.model.FileDataDto;
import ru.ulstu.file.service.FileService; import ru.ulstu.file.service.FileService;
import ru.ulstu.grant.model.GrantDto; import ru.ulstu.grant.model.GrantDto;
import ru.ulstu.grant.repository.GrantRepository; import ru.ulstu.grant.repository.GrantRepository;
@ -19,6 +20,7 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import static java.util.stream.Collectors.toList;
import static org.springframework.util.ObjectUtils.isEmpty; import static org.springframework.util.ObjectUtils.isEmpty;
import static ru.ulstu.core.util.StreamApiUtils.convert; import static ru.ulstu.core.util.StreamApiUtils.convert;
import static ru.ulstu.project.model.Project.ProjectStatus.TECHNICAL_TASK; import static ru.ulstu.project.model.Project.ProjectStatus.TECHNICAL_TASK;
@ -77,20 +79,19 @@ public class ProjectService {
@Transactional @Transactional
public Project update(ProjectDto projectDto) throws IOException { public Project update(ProjectDto projectDto) throws IOException {
Project project = projectRepository.findOne(projectDto.getId()); Project project = projectRepository.findOne(projectDto.getId());
if (projectDto.getApplicationFileName() != null && project.getApplication() != null) {
fileService.deleteFile(project.getApplication());
}
projectRepository.save(copyFromDto(project, projectDto)); projectRepository.save(copyFromDto(project, projectDto));
eventService.updateProjectDeadlines(project); eventService.updateProjectDeadlines(project);
for (FileDataDto file : projectDto.getFiles().stream()
.filter(f -> f.isDeleted() && f.getId() != null)
.collect(toList())) {
fileService.delete(file.getId());
}
return project; return project;
} }
@Transactional @Transactional
public void delete(Integer projectId) throws IOException { public void delete(Integer projectId) throws IOException {
Project project = projectRepository.findOne(projectId); Project project = projectRepository.findOne(projectId);
if (project.getApplication() != null) {
fileService.deleteFile(project.getApplication());
}
projectRepository.delete(project); projectRepository.delete(project);
} }
@ -103,9 +104,9 @@ public class ProjectService {
} }
project.setRepository(projectDto.getRepository()); project.setRepository(projectDto.getRepository());
project.setDeadlines(deadlineService.saveOrCreate(projectDto.getDeadlines())); project.setDeadlines(deadlineService.saveOrCreate(projectDto.getDeadlines()));
if (projectDto.getApplicationFileName() != null) { project.setFiles(fileService.saveOrCreate(projectDto.getFiles().stream()
project.setApplication(fileService.createFileFromTmp(projectDto.getApplicationFileName())); .filter(f -> !f.isDeleted())
} .collect(toList())));
project.getGrants().clear(); project.getGrants().clear();
if (projectDto.getGrantIds() != null && !projectDto.getGrantIds().isEmpty()) { if (projectDto.getGrantIds() != null && !projectDto.getGrantIds().isEmpty()) {
projectDto.getGrantIds().forEach(grantIds -> project.getGrants().add(grantRepository.findGrantById(grantIds))); projectDto.getGrantIds().forEach(grantIds -> project.getGrants().add(grantRepository.findGrantById(grantIds)));

View File

@ -0,0 +1,13 @@
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
<changeSet author="anton" id="20190529_000001-1">
<addColumn tableName="file">
<column name="project_id" type="integer"/>
</addColumn>
<addForeignKeyConstraint baseTableName="file" baseColumnNames="project_id"
constraintName="fk_file_project" referencedTableName="project"
referencedColumnNames="id"/>
</changeSet>
</databaseChangeLog>

View File

@ -51,4 +51,5 @@
<include file="db/changelog-20190528_000000-schema.xml"/> <include file="db/changelog-20190528_000000-schema.xml"/>
<include file="db/changelog-20190528_000002-schema.xml"/> <include file="db/changelog-20190528_000002-schema.xml"/>
<include file="db/changelog-20190529_000000-schema.xml"/> <include file="db/changelog-20190529_000000-schema.xml"/>
<include file="db/changelog-20190529_000001-schema.xml"/>
</databaseChangeLog> </databaseChangeLog>

View File

@ -0,0 +1,40 @@
<!DOCTYPE HTML>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8"/>
</head>
<body>
<body>
<div th:fragment="filesList">
<th:block th:each="file, rowStat : *{files}">
<div class="row" th:id="|files${rowStat.index}|"
th:style="${file.deleted} ? 'display: none;' :''">
<input type="hidden" th:field="*{files[__${rowStat.index}__].id}"/>
<input type="hidden"
th:field="*{files[__${rowStat.index}__].deleted}"/>
<input type="hidden"
th:field="*{files[__${rowStat.index}__].name}"/>
<input type="hidden"
th:field="*{files[__${rowStat.index}__].tmpFileName}"/>
<div class="col-2">
<a class="btn btn-danger float-right"
th:onclick="|$('#files${rowStat.index}\\.deleted').val('true'); $('#files${rowStat.index}').hide(); |">
<span aria-hidden="true"><i class="fa fa-times"/></span>
</a>
</div>
<div class="col-10">
<a th:onclick="${file.id==null} ? 'downloadFile('+${file.tmpFileName}+',null,\''+${file.name}+'\')':
'downloadFile(null,'+${file.id}+',\''+${file.name}+'\')' "
href="javascript:void(0)"
th:text="*{files[__${rowStat.index}__].name}">
</a>
</div>
</div>
</th:block>
</div>
</body>
</body>
</html>

View File

@ -119,6 +119,13 @@
value="Добавить дедлайн"/> value="Добавить дедлайн"/>
</div> </div>
<div class="form-group files-list" id="files-list">
<label>Файлы:</label>
<div th:replace="projects/fragments/projectFilesListFragment"/>
</div>
<div class="form-group"> <div class="form-group">
<label for="loader">Загрузить файл:</label> <label for="loader">Загрузить файл:</label>
<div id="loader"> <div id="loader">
@ -154,17 +161,103 @@
new FileLoader({ new FileLoader({
div: "loader", div: "loader",
url: urlFileUpload, url: urlFileUpload,
maxSize: 2, maxSize: -1,
extensions: ["doc", "docx", "xls", "jpg", "png", "pdf", "txt"], extensions: [],
callback: function (response) { callback: function (response) {
showFeedbackMessage("Файл успешно загружен"); showFeedbackMessage("Файл успешно загружен");
console.debug(response); console.debug(response);
addNewFile(response, $("#files-list"));
} }
}); });
$('.selectpicker').selectpicker(); $('.selectpicker').selectpicker();
}); });
/*]]>*/ /*]]>*/
function addNewFile(fileDto, listElement) {
var fileNumber = $('.files-list div.row').length;
var newFileRow = $("<div/>")
.attr("id", 'files' + fileNumber)
.addClass("row");
var idInput = $("<input/>")
.attr("type", "hidden")
.attr("id", "files" + fileNumber + ".id")
.attr("value", '')
.attr("name", "files[" + fileNumber + "].id");
newFileRow.append(idInput);
var flagInput = $("<input/>")
.attr("type", "hidden")
.attr("id", "files" + fileNumber + ".deleted")
.attr("value", "false")
.attr("name", "files[" + fileNumber + "].deleted");
newFileRow.append(flagInput);
var nameInput = $("<input/>")
.attr("type", "hidden")
.attr("id", "files" + fileNumber + ".name")
.attr("value", fileDto.fileName)
.attr("name", "files[" + fileNumber + "].name");
newFileRow.append(nameInput);
var tmpFileNameInput = $("<input/>")
.attr("type", "hidden")
.attr("id", "files" + fileNumber + ".tmpFileName")
.attr("value", fileDto.tmpFileName)
.attr("name", "files[" + fileNumber + "].tmpFileName");
newFileRow.append(tmpFileNameInput);
var nextDiv = $("<div/>")
.addClass("col-2");
var nextA = $("<a/>")
.addClass("btn btn-danger float-right")
.attr("onclick", "$('#files" + fileNumber + "\\\\.deleted').val('true'); $('#files" + fileNumber + "').hide();")
.append(($("<span/>").attr("aria-hidden", "true")).append($("<i/>").addClass("fa fa-times")))
;
nextDiv.append(nextA)
newFileRow.append(nextDiv);
var nameDiv = $("<div/>")
.addClass("col-10")
.append($("<a/>").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 {
}
}
}
</script> </script>
</div> </div>