#101 files attach modified
This commit is contained in:
parent
9013d79228
commit
632c6299b7
@ -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() {
|
||||||
|
@ -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() {
|
||||||
|
@ -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)));
|
||||||
|
13
src/main/resources/db/changelog-20190529_000001-schema.xml
Normal file
13
src/main/resources/db/changelog-20190529_000001-schema.xml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.1" encoding="UTF-8" standalone="no"?>
|
||||||
|
<databaseChangeLog xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.1.xsd">
|
||||||
|
<changeSet author="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>
|
@ -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>
|
@ -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>
|
@ -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>
|
||||||
|
Loading…
Reference in New Issue
Block a user