Commit 0a79d0b1 authored by Maxym Borodenko's avatar Maxym Borodenko Committed by Matija Obreza

File management for institutes

- added image gallery
parent 47a337be
......@@ -21,13 +21,24 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.genesys.filerepository.InvalidRepositoryFileDataException;
import org.genesys.filerepository.InvalidRepositoryPathException;
import org.genesys.filerepository.NoSuchRepositoryFileException;
import org.genesys.filerepository.model.ImageGallery;
import org.genesys.filerepository.model.RepositoryFile;
import org.genesys.filerepository.service.ImageGalleryService;
import org.genesys.filerepository.service.RepositoryService;
import org.genesys2.server.model.genesys.Taxonomy2;
import org.genesys2.server.model.impl.FaoInstitute;
import org.genesys2.server.service.CRMException;
......@@ -47,6 +58,7 @@ import org.genesys2.server.service.impl.FilterHandler.AppliedFilters;
import org.genesys2.server.service.impl.SearchException;
import org.genesys2.spring.ResourceNotFoundException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.context.annotation.Scope;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
......@@ -55,17 +67,28 @@ import org.springframework.http.MediaType;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.InitBinder;
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.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.HandlerMapping;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
import org.springframework.web.util.UriUtils;
@Controller
@Scope("request")
@RequestMapping("/wiews")
public class WiewsController extends BaseController {
private static final String MANAGE_FILES_JSP_PATH = "/wiews/files";
@Autowired
private InstituteService instituteService;
......@@ -93,6 +116,12 @@ public class WiewsController extends BaseController {
@Autowired
private ElasticService elasticService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private ImageGalleryService imageGalleryService;
@RequestMapping("/")
public String view(ModelMap model, @RequestParam(value = "page", required = false, defaultValue = "1") int page) {
model.addAttribute("pagedData", instituteService.listPGRInstitutes(new PageRequest(page - 1, 50, new Sort("code"))));
......@@ -432,4 +461,178 @@ public class WiewsController extends BaseController {
_logger.warn("Download was aborted", e);
}
}
/* File management */
@PreAuthorize("hasRole('ADMINISTRATOR')")
@RequestMapping(value = "/{wiewsCode}/files/**", method = RequestMethod.GET)
public String listAllFiles(HttpServletRequest request, ModelMap model) throws UnsupportedEncodingException, InvalidRepositoryPathException {
String fullpath = (String) request.getAttribute(HandlerMapping.PATH_WITHIN_HANDLER_MAPPING_ATTRIBUTE);
// The /** mapping does not decode the URL
fullpath = UriUtils.decode(fullpath, "UTF-8");
return listAllFiles(model, fullpath);
}
@PreAuthorize("hasRole('ADMINISTRATOR')")
@RequestMapping(value = "/{path}/files", method = RequestMethod.GET)
public String listAllFiles(ModelMap model, @PathVariable(value = "path") String path) throws InvalidRepositoryPathException {
final String repositoryPath = path.contains("/wiews/") ? path.replace("/files/", "/") : "/wiews/" + path;
if (_logger.isDebugEnabled()) {
_logger.debug("Listing files for path=" + repositoryPath);
}
String wiewsCode = path.replace("/wiews/", "");
wiewsCode = wiewsCode.contains("/") ? wiewsCode.substring(0, wiewsCode.indexOf("/")) : wiewsCode;
List<String> subPaths = new ArrayList<>();
for (String subPath: repositoryService.listPaths(repositoryPath, new PageRequest(0, 10))) {
if (!subPath.equals(repositoryPath) && subPath.contains(repositoryPath)) {
subPaths.add(subPath.substring(repositoryPath.length()));
}
}
model.addAttribute("fileList", repositoryService.getFiles(repositoryPath));
model.addAttribute("currentPath", repositoryPath);
model.addAttribute("subPaths", subPaths);
model.addAttribute("imageGallery", imageGalleryService.loadImageGallery(repositoryPath));
model.addAttribute("wiewsCode", wiewsCode);
return MANAGE_FILES_JSP_PATH + "/index";
}
@PreAuthorize("hasRole('ADMINISTRATOR')")
@RequestMapping(value = "/upload-file", method = RequestMethod.POST)
public String uploadFile(@RequestParam MultipartFile file, @RequestParam String wiewsCode, @RequestParam String repositoryPath,
RedirectAttributes redirectAttributes) throws IOException {
final String mimeType = file.getContentType();
try {
if (mimeType.startsWith("image")) {
repositoryService.addImage(repositoryPath, file.getOriginalFilename(), file.getContentType(), file.getBytes(), null);
} else {
repositoryService.addFile(repositoryPath, file.getOriginalFilename(), file.getContentType(), file.getBytes(), null);
}
} catch (InvalidRepositoryPathException e) {
_logger.error("Invalid repository path!", e);
redirectAttributes.addFlashAttribute("errorMessage", "Invalid repository path!");
} catch (InvalidRepositoryFileDataException e) {
_logger.error("Invalid file data!", e);
redirectAttributes.addFlashAttribute("errorMessage", "Invalid file data!");
}
if (repositoryPath.equals("/wiews/".concat(wiewsCode))) {
return "redirect:" + repositoryPath + "/files";
} else {
return "redirect:" + repositoryPath.replace("/wiews/".concat(wiewsCode).concat("/"), "/wiews/".concat(wiewsCode).concat("/files/"));
}
}
@PreAuthorize("hasRole('ADMINISTRATOR')")
@RequestMapping(value = "/delete-file", method = RequestMethod.POST)
public String deleteFile(@RequestParam String uuid, @RequestParam String wiewsCode) throws NoSuchRepositoryFileException, IOException {
RepositoryFile repositoryFile = repositoryService.getFile(UUID.fromString(uuid));
repositoryService.removeFile(repositoryFile);
if (repositoryFile.getPath().equals("/wiews/".concat(wiewsCode))) {
return "redirect:" + repositoryFile.getPath() + "/files";
} else {
return "redirect:" + repositoryFile.getPath().replace("/wiews/".concat(wiewsCode).concat("/"), "/wiews/".concat(wiewsCode).concat("/files/"));
}
}
@PreAuthorize("hasRole('ADMINISTRATOR')")
@RequestMapping(value = "/{wiewsCode}/edit-file", method = RequestMethod.GET)
public String getEditPage(@RequestParam String uuid, @PathVariable(value = "wiewsCode") String wiewsCode, ModelMap model) throws NoSuchRepositoryFileException {
RepositoryFile file = repositoryService.getFile(UUID.fromString(uuid));
model.addAttribute("file", file);
model.addAttribute("wiewsCode", wiewsCode);
return MANAGE_FILES_JSP_PATH + "/edit";
}
@PreAuthorize("hasRole('ADMINISTRATOR')")
@RequestMapping(value = "/{wiewsCode}/update-file", method = RequestMethod.POST)
public String updateMetadata(@ModelAttribute RepositoryFile fileData, @RequestParam String uuid, @PathVariable(value = "wiewsCode") String wiewsCode) throws NoSuchRepositoryFileException {
RepositoryFile updatedFile = repositoryService.getFile(UUID.fromString(uuid));
repositoryService.updateMetadata(updatedFile.getUuid(), fileData);
return "redirect:/wiews/" + wiewsCode + "/files";
}
@GetMapping(value = "/{wiewsCode}/files/gallery")
public String listAllFiles(ModelMap model, @PathVariable("wiewsCode") String wiewsCode, HttpServletRequest request) {
return "redirect:/wiews/" + wiewsCode + "/files" + "/gallery" + "/1";
}
@GetMapping(value = "/{wiewsCode}/files/gallery/{page:\\d+}")
public String listAllFiles(ModelMap model, @PathVariable("page") int page, @PathVariable("wiewsCode") String wiewsCode) {
Page<ImageGallery> pagedData = imageGalleryService.listImageGalleries(new PageRequest(page - 1, 50, new Sort("path")));
model.addAttribute("pagedData", pagedData);
model.addAttribute("wiewsCode", wiewsCode);
return MANAGE_FILES_JSP_PATH + "/gallery/index";
}
@GetMapping(value = "/{wiewsCode}/files/gallery/details")
public String listAllFiles(ModelMap model, HttpServletRequest request, @PathVariable("wiewsCode") String wiewsCode) {
ImageGallery imageGallery = imageGalleryService.loadImageGallery("/wiews/" + wiewsCode);
if (imageGallery == null) {
throw new ResourceNotFoundException("No image gallery here!");
}
imageGalleryService.ensureThumbnails(imageGallery, 200, 200);
model.addAttribute("thumbnailFormat", "200x200");
model.addAttribute("imageGallery", imageGallery);
model.addAttribute("wiewsCode", wiewsCode);
return MANAGE_FILES_JSP_PATH + "/gallery/details";
}
@GetMapping(value = "/{path}/files/gallery/edit")
public String getEditPage(@RequestParam String galleryPath, ModelMap model) throws NoSuchRepositoryFileException {
ImageGallery imageGallery = imageGalleryService.loadImageGallery(galleryPath);
if (imageGallery == null) {
imageGallery = new ImageGallery();
imageGallery.setPath(galleryPath);
}
model.addAttribute("imageGallery", imageGallery);
model.addAttribute("wiewsCode", galleryPath);
return MANAGE_FILES_JSP_PATH + "/gallery/edit";
}
@PostMapping(value = "{wiewsCode}/files/gallery/update")
public String updateMetadata(@PathVariable("wiewsCode") String wiewsCode, @ModelAttribute ImageGallery imageGallery, RedirectAttributes redirectAttributes) throws NoSuchRepositoryFileException {
ImageGallery updatedGallery = imageGalleryService.loadImageGallery(imageGallery.getPath());
if (updatedGallery == null) {
updatedGallery = imageGalleryService.createImageGallery(imageGallery.getPath(), imageGallery.getTitle(), imageGallery.getDescription());
} else {
updatedGallery = imageGalleryService.updateImageGalery(updatedGallery, imageGallery.getTitle(), imageGallery.getDescription());
}
redirectAttributes.addFlashAttribute("successMessage", "repository.gallery.successfully-updated");
return "redirect:/wiews/" + wiewsCode +"/files/gallery";
}
@PostMapping(value = "{wiewsCode}/files/gallery/delete")
public String deleteFile(@RequestParam String galleryPath, RedirectAttributes redirectAttributes, @PathVariable("wiewsCode") String wiewsCode) throws InvalidRepositoryPathException {
ImageGallery imageGallery = imageGalleryService.loadImageGallery(galleryPath);
imageGalleryService.removeGallery(imageGallery);
redirectAttributes.addFlashAttribute("successMessage", "repository.gallery.removed");
return "redirect:/wiews/" + wiewsCode +"/files/gallery";
}
@InitBinder
public void initBinder(WebDataBinder binder) {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setLenient(false);
binder.registerCustomEditor(Date.class, new CustomDateEditor(dateFormat, false));
}
}
......@@ -867,6 +867,7 @@ repository.file.lastModifiedDate=Last modified date
file.upload-file=Upload file
file.upload-file.help=Select file for upload from local computer
file.manage-files=Manage files
repository.gallery=Image gallery
repository.gallery.title=Title of image gallery:
......
......@@ -6532,3 +6532,10 @@ table.accessions {
font-family: "Roboto-Bold";
font-size: 30px;
}
.margin-top-05 { margin-top: 5px; }
.margin-top-10 { margin-top: 10px; }
.margin-top-15 { margin-top: 15px; }
.margin-top-20 { margin-top: 20px; }
.margin-top-25 { margin-top: 25px; }
.margin-top-30 { margin-top: 30px; }
......@@ -494,13 +494,16 @@
</c:if>
<security:authorize access="hasRole('ADMINISTRATOR') or hasPermission(#faoInstitute, 'ADMINISTRATION')">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12">
<a href="<c:url value="/acl/${faoInstitute.getClass().name}/${faoInstitute.id}/permissions"><c:param name="back">/wiews/${faoInstitute.code}</c:param></c:url>" class="close">
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 form-group">
<a href="<c:url value="/acl/${faoInstitute.getClass().name}/${faoInstitute.id}/permissions"><c:param name="back">/wiews/${faoInstitute.code}</c:param></c:url>" class="btn btn-default">
<spring:message code="edit-acl" />
</a>
<a href="<c:url value="/wiews/${faoInstitute.code}/edit" />" class="close">
<a href="<c:url value="/wiews/${faoInstitute.code}/edit" />" class="btn btn-default">
<spring:message code="edit" />
</a>
<a href="<c:url value="/wiews/${faoInstitute.code}/files" />" class="btn btn-default">
<spring:message code="file.manage-files" />
</a>
</div>
</security:authorize>
......
<!DOCTYPE html>
<%@ include file="/WEB-INF/jsp/init.jsp" %>
<html>
<head>
<title><spring:message code="admin.page.title"/></title>
</head>
<body>
<h4>Updating metadata for file <strong><c:out value="${file.originalFilename}"/></strong></h4>
<a href="<c:url value="/wiews/${wiewsCode}/files" />" class="btn btn-default margin-top-10">
<spring:message code="cancel"/>
</a>
<form action="<c:url value="/wiews/${wiewsCode}/update-file" />" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="hidden" name="uuid" value="${file.uuid}"/>
<input type="hidden" name="md5Sum" value="${file.md5Sum}"/>
<input type="hidden" name="sha1Sum" value="${file.sha1Sum}"/>
<input type="hidden" name="path" value="${file.path}"/>
<div class="row">
<div class="col-md-6 margin-top-20">
<label for="title"><spring:message code="repository.file.title"/></label>
<input type="text" class="form-control" id="title" name="title" value="${file.title}"
placeholder="<spring:message code="repository.file.title" />">
</div>
<div class="col-md-6 margin-top-20">
<label for="subject"><spring:message code="repository.file.subject"/></label>
<input type="text" class="form-control" id="subject" name="subject" value="${file.subject}"
placeholder="<spring:message code="repository.file.subject" />">
</div>
<div class="col-md-12 margin-top-20">
<label for="description"><spring:message code="repository.file.description"/></label>
<textarea id="description" name="description" class="form-control"><c:out escapeXml="false"
value="${file.description}"/></textarea>
</div>
<div class="col-md-6 margin-top-20">
<label for="creator"><spring:message code="repository.file.creator"/></label>
<input type="text" id="creator" name="creator" class="form-control" value="${file.creator}"
placeholder="<spring:message code="repository.file.creator" />">
</div>
<div class="col-md-6 margin-top-20">
<label for="created"><spring:message code="repository.file.created"/></label>
<input type="text" id="created" name="created" class="form-control" value="${file.created}"
placeholder="<spring:message code="repository.file.created" />">
</div>
<div class="col-md-6 margin-top-20">
<label for="rightsHolder"><spring:message code="repository.file.rightsHolder"/></label>
<input type="text" id="rightsHolder" name="rightsHolder" class="form-control" value="${file.rightsHolder}"
placeholder="<spring:message code="repository.file.rightsHolder" />">
</div>
<div class="col-md-6 margin-top-20">
<label for="accessRights"><spring:message code="repository.file.accessRights"/></label>
<input type="text" id="accessRights" name="accessRights" class="form-control" value="${file.accessRights}"
placeholder="<spring:message code="repository.file.accessRights" />">
</div>
<div class="col-md-6 margin-top-20">
<label for="license"><spring:message code="repository.file.license"/></label>
<input type="text" id="license" name="license" class="form-control" value="${file.license}"
placeholder="<spring:message code="repository.file.license" />">
</div>
<div class="col-md-6 margin-top-20">
<label for="originalFilename"><spring:message code="repository.file.originalFilename"/></label>
<input type="text" id="originalFilename" name="originalFilename" class="form-control"
value="${file.originalFilename}"
placeholder="<spring:message code="repository.file.originalFilename" />">
</div>
<div class="col-md-6 margin-top-20">
<label for="contentType"><spring:message code="repository.file.contentType"/></label>
<input type="text" id="contentType" name="contentType" class="form-control" value="${file.contentType}"
placeholder="<spring:message code="repository.file.contentType" />">
</div>
<div class="col-md-6 margin-top-20">
<label for="extent"><spring:message code="repository.file.extent"/></label>
<input type="text" id="extent" name="extent" class="form-control" value="${file.extent}"
placeholder="<spring:message code="repository.file.extent" />">
</div>
<div class="col-md-6 margin-top-20">
<label for="bibliographicCitation"><spring:message code="repository.file.bibliographicCitation"/></label>
<input type="text" id="bibliographicCitation" name="bibliographicCitation" class="form-control"
value="${file.bibliographicCitation}"
placeholder="<spring:message code="repository.file.bibliographicCitation" />">
</div>
<div class="col-md-6 margin-top-20">
<label for="dateSubmitted"><spring:message code="repository.file.dateSubmitted"/></label>
<input type="text" id="dateSubmitted" name="createdDate" class="form-control" value="${file.dateSubmitted}"
placeholder="<spring:message code="repository.file.dateSubmitted" />">
</div>
<div class="col-md-6 margin-top-20">
<label for="modified"><spring:message code="repository.file.lastModifiedDate"/></label>
<input type="text" id="modified" name="lastModifiedDate" class="form-control" value="${file.modified}"
placeholder="<spring:message code="repository.file.lastModifiedDate" />">
</div>
</div>
<button type="submit" class="btn btn-primary margin-top-20">Save</button>
</form>
</body>
</html>
<!DOCTYPE html>
<%@ include file="/WEB-INF/jsp/init.jsp" %>
<html>
<head>
<title><c:out value="${imageGallery.title}"/></title>
</head>
<body>
<h1 class="col-xs-12 page-title">
<c:out value="${imageGallery.title}"/>
</h1>
<div class="free-text">
<c:out value="${imageGallery.description}"/>
</div>
<a href="<c:url value="/wiews/${wiewsCode}/files/gallery" />" class="btn btn-default"><spring:message code="cancel"/></a>
<a href="<c:url value="/wiews/${wiewsCode}/files" />" class="btn btn-default"><spring:message code="navigate.back"/></a>
<div class="row" id="imagegallery-thumbs">
<c:forEach items="${imageGallery.images}" var="image">
<div x-src="<c:out value="${image.storageFullPath}" />" class="col-xs-6 col-sm-3 col-md-2 col-lg-2">
<img style="width: 100%; margin-bottom: 15px; margin-top: 15px;" src="<c:url value="/repository/d/_thumbs${image.thumbnailPath}/${thumbnailFormat}.png" />"
alt="${image.title}"/>
</div>
</c:forEach>
</div>
<div class="imagegallery-image-frame">
<img id="imagegallery-image"/>
</div>
<content tag="javascript">
<script type="text/javascript">
$(document).ready(function () {
var imageViewer = $('#imagegallery-image')[0];
var baseHref = '<c:url value="/repository/d" />';
var galleryImages = $('#imagegallery-thumbs div');
if (galleryImages.length > 0) {
imageViewer.src = baseHref + $(galleryImages[0]).attr('x-src');
}
$('#imagegallery-thumbs div').click(function (ev) {
imageViewer.src = baseHref + $(this).attr('x-src');
});
});
</script>
</content>
</body>
</html>
<!DOCTYPE html>
<%@ include file="/WEB-INF/jsp/init.jsp" %>
<html>
<head>
<title><spring:message code="repository.gallery" /></title>
</head>
<body>
<div class="row">
<div class="col-md-12">
<a href="<c:url value="${wiewsCode}/files/gallery" />" class="btn btn-default"><spring:message
code="cancel" /></a>
<h4>
Updating metadata for image gallery
<c:out value="${imageGallery.path}" />
</h4>
<form action="<c:url value="${wiewsCode}/files/gallery/update" />" method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<input type="hidden" name="path" value="<c:out value="${imageGallery.path}" />">
<div class="form-group">
<label for="title"><spring:message
code="repository.gallery.title" /></label> <input type="text" id="title"
name="title" value="<c:out value="${imageGallery.title}" />"
class="form-control">
</div>
<div class="form-group">
<label for="title"><spring:message
code="repository.gallery.path" /></label> <span class=""><c:out
value="${imageGallery.path}" /></span>
</div>
<div class="form-group">
<label for="subject"><spring:message
code="repository.gallery.description" /></label>
<textarea id="description" name="description" class="form-control"><c:out
escapeXml="false" value="${imageGallery.description}" /></textarea>
</div>
<button type="submit" class="btn btn-default">
<spring:message code="save" />
</button>
</form>
</div>
</div>
</body>
</html>
<!DOCTYPE html>
<%@ include file="/WEB-INF/jsp/init.jsp" %>
<html>
<head>
<title><spring:message code="menu.admin.repository.galleries" /></title>
</head>
<body>
<!-- Any alerts? -->
<gui:alert type="warning" display="${not empty errorMessage}">
<c:out value="${errorMessage}" />
</gui:alert>
<gui:alert type="success" display="${not empty successMessage}">
<c:out value="${successMessage}" />
</gui:alert>
<table class="table table-striped">
<thead>
<tr>
<th class="col-xs-5"><spring:message
code="repository.gallery" /></th>
<th class="col-xs-3"><spring:message
code="repository.gallery.path" /></th>
<th class="col-xs-4"></th>
</tr>
</thead>
<tbody>
<c:forEach var="gallery" items="${pagedData.content}" varStatus="i">
<tr>
<td class="col-md-5"><a href="<c:url value="/wiews/${wiewsCode}/files/gallery/details" />"><c:out value="${gallery.title}" /></a></td>
<td class="col-md-3"><c:out value="${gallery.path}" /></td>
<td class="col-md-4 text-right">
<form action="<c:url value="/wiews/${wiewsCode}/files/gallery/delete" />"
method="post">
<a
href="<c:url value="/wiews/${wiewsCode}/files/gallery/edit"><c:param name="galleryPath" value="${gallery.path}" /></c:url>"
class="btn btn-default"><spring:message code="edit" /></a>
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<input type="hidden" name="galleryPath" value="${gallery.path}" />
<button type="submit" name="action" value="delete-file" class="btn btn-default confirm-delete"><spring:message code="delete" /></button>
</form>
</td>
</tr>
</c:forEach>
</tbody>
</table>
<content tag="javascript"> <script type="text/javascript">
$(document).ready(function() {
$('.confirm-delete').click(function(ev) {
if (! window.confirm('<spring:message code="prompt.confirm-delete" />')) {
ev.stopPropagation();
return false;
}
});
$('#repository-menu-item').addClass('active');
$('#repository-menu-item').find("a").first().addClass('active');
$('.humburger-btn').on('click', function () {
setTimeout(function() {
expandGroup ($(document).width());
}, 100);
});
});
$(window).resize(function() {