parent
81a6e93ddb
commit
5b7ba6c146
|
|
@ -9,7 +9,6 @@ import org.apache.logging.log4j.LogManager;
|
||||||
import org.apache.logging.log4j.Logger;
|
import org.apache.logging.log4j.Logger;
|
||||||
import org.libreccm.api.Identifier;
|
import org.libreccm.api.Identifier;
|
||||||
import org.libreccm.api.IdentifierParser;
|
import org.libreccm.api.IdentifierParser;
|
||||||
import org.libreccm.core.CcmObject;
|
|
||||||
import org.libreccm.l10n.GlobalizationHelper;
|
import org.libreccm.l10n.GlobalizationHelper;
|
||||||
import org.libreccm.security.AuthorizationRequired;
|
import org.libreccm.security.AuthorizationRequired;
|
||||||
import org.libreccm.security.PermissionChecker;
|
import org.libreccm.security.PermissionChecker;
|
||||||
|
|
@ -26,12 +25,15 @@ import org.librecms.contentsection.DocumentFolderEntry;
|
||||||
import org.librecms.contentsection.Folder;
|
import org.librecms.contentsection.Folder;
|
||||||
import org.librecms.contentsection.FolderManager;
|
import org.librecms.contentsection.FolderManager;
|
||||||
import org.librecms.contentsection.FolderRepository;
|
import org.librecms.contentsection.FolderRepository;
|
||||||
|
import org.librecms.contentsection.FolderType;
|
||||||
import org.librecms.contentsection.privileges.ItemPrivileges;
|
import org.librecms.contentsection.privileges.ItemPrivileges;
|
||||||
import org.librecms.contenttypes.Article;
|
import org.librecms.contenttypes.Article;
|
||||||
|
|
||||||
import java.time.LocalDate;
|
import java.time.LocalDate;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
import java.time.format.DateTimeFormatter;
|
import java.time.format.DateTimeFormatter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
@ -111,11 +113,13 @@ public class ContentSectionController {
|
||||||
private PermissionChecker permissionChecker;
|
private PermissionChecker permissionChecker;
|
||||||
|
|
||||||
@GET
|
@GET
|
||||||
@Path("/document-folders")
|
@Path("/document-folders{folderPath:(/.+)?}")
|
||||||
@AuthorizationRequired
|
@AuthorizationRequired
|
||||||
@Transactional(Transactional.TxType.REQUIRED)
|
@Transactional(Transactional.TxType.REQUIRED)
|
||||||
public String listItems(
|
public String listItems(
|
||||||
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
@PathParam("sectionIdentifier") final String sectionIdentifier,
|
||||||
|
@PathParam("folderPath") final String folderPath,
|
||||||
|
@QueryParam("filterTerm") @DefaultValue("") final String filterTerm,
|
||||||
@QueryParam("firstResult") @DefaultValue("0") final int firstResult,
|
@QueryParam("firstResult") @DefaultValue("0") final int firstResult,
|
||||||
@QueryParam("maxResults") @DefaultValue("20") final int maxResults
|
@QueryParam("maxResults") @DefaultValue("20") final int maxResults
|
||||||
) {
|
) {
|
||||||
|
|
@ -155,22 +159,60 @@ public class ContentSectionController {
|
||||||
System.currentTimeMillis() - permissionCheckStart
|
System.currentTimeMillis() - permissionCheckStart
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final Folder folder;
|
||||||
|
if (folderPath.isBlank()) {
|
||||||
|
folder = section.getRootDocumentsFolder();
|
||||||
|
documentFolderModel.setBreadcrumbs(Collections.emptyList());
|
||||||
|
} else {
|
||||||
|
final Optional<Folder> folderResult = folderRepo
|
||||||
|
.findByPath(section,
|
||||||
|
folderPath,
|
||||||
|
FolderType.DOCUMENTS_FOLDER
|
||||||
|
);
|
||||||
|
if (folderResult.isPresent()) {
|
||||||
|
folder = folderResult.get();
|
||||||
|
final List<DocumentFolderBreadcrumbModel> breadcrumbs
|
||||||
|
= new ArrayList<>();
|
||||||
|
final List<String> tokens = Arrays
|
||||||
|
.stream(folderPath.split("/"))
|
||||||
|
.filter(token -> !token.isEmpty())
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
for (final String token : tokens) {
|
||||||
|
final String path = breadcrumbs
|
||||||
|
.stream()
|
||||||
|
.map(DocumentFolderBreadcrumbModel::getPathToken)
|
||||||
|
.collect(Collectors.joining("/"));
|
||||||
|
final DocumentFolderBreadcrumbModel breadcrumb
|
||||||
|
= new DocumentFolderBreadcrumbModel();
|
||||||
|
breadcrumb.setPath(path);
|
||||||
|
breadcrumb.setPathToken(token);
|
||||||
|
breadcrumbs.add(breadcrumb);
|
||||||
|
}
|
||||||
|
breadcrumbs
|
||||||
|
.get(breadcrumbs.size() - 1)
|
||||||
|
.setCurrentFolder(true);
|
||||||
|
documentFolderModel.setBreadcrumbs(breadcrumbs);
|
||||||
|
} else {
|
||||||
|
models.put("contentSection", section.getLabel());
|
||||||
|
models.put("folderPath", folderPath);
|
||||||
|
return "org/librecms/ui/content-section/document-folder-not-found.xhtml";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final long objectsStart = System.currentTimeMillis();
|
final long objectsStart = System.currentTimeMillis();
|
||||||
final List<DocumentFolderEntry> folderEntries = folderRepo
|
final List<DocumentFolderEntry> folderEntries = folderRepo
|
||||||
.getDocumentFolderEntries(
|
.getDocumentFolderEntries(
|
||||||
section.getRootDocumentsFolder(),
|
folder,
|
||||||
firstResult,
|
firstResult,
|
||||||
maxResults,
|
maxResults,
|
||||||
""
|
filterTerm
|
||||||
);
|
);
|
||||||
LOGGER.info(
|
LOGGER.info(
|
||||||
"Retrieved objects in {} ms",
|
"Retrieved objects in {} ms",
|
||||||
System.currentTimeMillis() - objectsStart
|
System.currentTimeMillis() - objectsStart
|
||||||
);
|
);
|
||||||
documentFolderModel.setCount(
|
documentFolderModel.setCount(
|
||||||
folderRepo.countDocumentFolderEntries(
|
folderRepo.countDocumentFolderEntries(folder, filterTerm)
|
||||||
section.getRootDocumentsFolder(), ""
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
documentFolderModel.setFirstResult(firstResult);
|
documentFolderModel.setFirstResult(firstResult);
|
||||||
documentFolderModel.setMaxResults(maxResults);
|
documentFolderModel.setMaxResults(maxResults);
|
||||||
|
|
@ -179,6 +221,8 @@ public class ContentSectionController {
|
||||||
System.currentTimeMillis() - objectsStart
|
System.currentTimeMillis() - objectsStart
|
||||||
);
|
);
|
||||||
|
|
||||||
|
contentSectionModel.setFolders(buildFolderTree(section, folder));
|
||||||
|
|
||||||
final long rowsStart = System.currentTimeMillis();
|
final long rowsStart = System.currentTimeMillis();
|
||||||
documentFolderModel.setRows(
|
documentFolderModel.setRows(
|
||||||
folderEntries
|
folderEntries
|
||||||
|
|
@ -186,8 +230,10 @@ public class ContentSectionController {
|
||||||
.map(entry -> buildRowModel(section, entry))
|
.map(entry -> buildRowModel(section, entry))
|
||||||
.collect(Collectors.toList())
|
.collect(Collectors.toList())
|
||||||
);
|
);
|
||||||
LOGGER.info("Build rows in {} ms.", System.currentTimeMillis()
|
LOGGER.info(
|
||||||
- rowsStart);
|
"Build rows in {} ms.",
|
||||||
|
System.currentTimeMillis() - rowsStart
|
||||||
|
);
|
||||||
|
|
||||||
return "org/librecms/ui/content-section/document-folder.xhtml";
|
return "org/librecms/ui/content-section/document-folder.xhtml";
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -294,6 +340,60 @@ public class ContentSectionController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private List<FolderTreeNode> buildFolderTree(
|
||||||
|
final ContentSection section, final Folder currentFolder
|
||||||
|
) {
|
||||||
|
final Folder root = section.getRootDocumentsFolder();
|
||||||
|
final String currentFolderPath = folderManager
|
||||||
|
.getFolderPath(currentFolder)
|
||||||
|
.substring(
|
||||||
|
folderManager
|
||||||
|
.getFolderPath(section.getRootDocumentsFolder())
|
||||||
|
.length() - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
return root
|
||||||
|
.getSubFolders()
|
||||||
|
.stream()
|
||||||
|
.sorted()
|
||||||
|
.map(folder -> buildFolderTreeNode(section, currentFolderPath,
|
||||||
|
folder))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
private FolderTreeNode buildFolderTreeNode(
|
||||||
|
final ContentSection section,
|
||||||
|
final String currentFolderPath,
|
||||||
|
final Folder folder
|
||||||
|
) {
|
||||||
|
final String folderPath = folderManager
|
||||||
|
.getFolderPath(folder)
|
||||||
|
.substring(
|
||||||
|
folderManager
|
||||||
|
.getFolderPath(section.getRootDocumentsFolder())
|
||||||
|
.length() - 1
|
||||||
|
);
|
||||||
|
|
||||||
|
final FolderTreeNode node = new FolderTreeNode();
|
||||||
|
node.setFolderId(folder.getObjectId());
|
||||||
|
node.setUuid(folder.getUuid());
|
||||||
|
node.setName(folder.getName());
|
||||||
|
node.setOpen(currentFolderPath.startsWith(folderPath));
|
||||||
|
node.setSelected(currentFolderPath.equals(folderPath));
|
||||||
|
node.setSubFolders(
|
||||||
|
folder
|
||||||
|
.getSubFolders()
|
||||||
|
.stream()
|
||||||
|
.sorted()
|
||||||
|
.map(subFolder -> buildFolderTreeNode(section,
|
||||||
|
currentFolderPath,
|
||||||
|
subFolder))
|
||||||
|
.collect(Collectors.toList())
|
||||||
|
);
|
||||||
|
|
||||||
|
return node;
|
||||||
|
}
|
||||||
|
|
||||||
private DocumentFolderRowModel buildRowModel(
|
private DocumentFolderRowModel buildRowModel(
|
||||||
final ContentSection section, final DocumentFolderEntry entry
|
final ContentSection section, final DocumentFolderEntry entry
|
||||||
) {
|
) {
|
||||||
|
|
@ -312,6 +412,15 @@ public class ContentSectionController {
|
||||||
== FolderManager.FolderIsDeletable.YES
|
== FolderManager.FolderIsDeletable.YES
|
||||||
);
|
);
|
||||||
row.setFolder(true);
|
row.setFolder(true);
|
||||||
|
row.setFolderPath(
|
||||||
|
folderManager
|
||||||
|
.getFolderPath(folder)
|
||||||
|
.substring(
|
||||||
|
folderManager
|
||||||
|
.getFolderPath(section.getRootDocumentsFolder())
|
||||||
|
.length()
|
||||||
|
)
|
||||||
|
);
|
||||||
row.setLanguages(Collections.emptySortedSet());
|
row.setLanguages(Collections.emptySortedSet());
|
||||||
row.setLastEditPublished(false);
|
row.setLastEditPublished(false);
|
||||||
row.setLastEdited("");
|
row.setLastEdited("");
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,9 @@ package org.librecms.ui;
|
||||||
|
|
||||||
import org.librecms.contentsection.ContentSection;
|
import org.librecms.contentsection.ContentSection;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
|
@ -23,6 +26,8 @@ public class ContentSectionModel {
|
||||||
|
|
||||||
private ContentSection section;
|
private ContentSection section;
|
||||||
|
|
||||||
|
private List<FolderTreeNode> folders;
|
||||||
|
|
||||||
protected void setSection(final ContentSection section) {
|
protected void setSection(final ContentSection section) {
|
||||||
this.section = Objects.requireNonNull(
|
this.section = Objects.requireNonNull(
|
||||||
section, "Parameter section can't be null"
|
section, "Parameter section can't be null"
|
||||||
|
|
@ -36,4 +41,12 @@ public class ContentSectionModel {
|
||||||
.orElse("");
|
.orElse("");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<FolderTreeNode> getFolders() {
|
||||||
|
return Collections.unmodifiableList(folders);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setFolders(final List<FolderTreeNode> folders) {
|
||||||
|
this.folders = new ArrayList<>(folders);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.librecms.ui;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class DocumentFolderBreadcrumbModel {
|
||||||
|
|
||||||
|
private String pathToken;
|
||||||
|
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
private boolean currentFolder;
|
||||||
|
|
||||||
|
public String getPathToken() {
|
||||||
|
return pathToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPathToken(final String pathToken) {
|
||||||
|
this.pathToken = pathToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPath(final String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isCurrentFolder() {
|
||||||
|
return currentFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentFolder(final boolean currentFolder) {
|
||||||
|
this.currentFolder = currentFolder;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -29,6 +29,8 @@ public class DocumentFolderModel {
|
||||||
|
|
||||||
private List<DocumentFolderRowModel> rows;
|
private List<DocumentFolderRowModel> rows;
|
||||||
|
|
||||||
|
private List<DocumentFolderBreadcrumbModel> breadcrumbs;
|
||||||
|
|
||||||
public long getCount() {
|
public long getCount() {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
@ -41,6 +43,7 @@ public class DocumentFolderModel {
|
||||||
return firstResult;
|
return firstResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected void setFirstResult(final int firstResult) {
|
protected void setFirstResult(final int firstResult) {
|
||||||
this.firstResult = firstResult;
|
this.firstResult = firstResult;
|
||||||
}
|
}
|
||||||
|
|
@ -69,4 +72,15 @@ public class DocumentFolderModel {
|
||||||
this.rows = new ArrayList<>(rows);
|
this.rows = new ArrayList<>(rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<DocumentFolderBreadcrumbModel> getBreadcrumbs() {
|
||||||
|
return Collections.unmodifiableList(breadcrumbs);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBreadcrumbs(
|
||||||
|
final List<DocumentFolderBreadcrumbModel> breadcrumbs
|
||||||
|
) {
|
||||||
|
this.breadcrumbs = new ArrayList<>(breadcrumbs);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,8 @@ public class DocumentFolderRowModel {
|
||||||
|
|
||||||
private boolean folder;
|
private boolean folder;
|
||||||
|
|
||||||
|
private String folderPath;
|
||||||
|
|
||||||
private SortedSet<String> languages;
|
private SortedSet<String> languages;
|
||||||
|
|
||||||
private String lastEdited;
|
private String lastEdited;
|
||||||
|
|
@ -54,6 +56,14 @@ public class DocumentFolderRowModel {
|
||||||
return folder;
|
return folder;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getFolderPath() {
|
||||||
|
return folderPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void setFolderPath(final String folderPath) {
|
||||||
|
this.folderPath = folderPath;
|
||||||
|
}
|
||||||
|
|
||||||
protected void setFolder(final boolean folder) {
|
protected void setFolder(final boolean folder) {
|
||||||
this.folder = folder;
|
this.folder = folder;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,88 @@
|
||||||
|
/*
|
||||||
|
* To change this license header, choose License Headers in Project Properties.
|
||||||
|
* To change this template file, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
package org.librecms.ui;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
|
||||||
|
*/
|
||||||
|
public class FolderTreeNode {
|
||||||
|
|
||||||
|
private long folderId;
|
||||||
|
|
||||||
|
private String uuid;
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
private String path;
|
||||||
|
|
||||||
|
private List<FolderTreeNode> subFolders;
|
||||||
|
|
||||||
|
private boolean open;
|
||||||
|
|
||||||
|
private boolean selected;
|
||||||
|
|
||||||
|
public long getFolderId() {
|
||||||
|
return folderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setFolderId(final long folderId) {
|
||||||
|
this.folderId = folderId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUuid() {
|
||||||
|
return uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUuid(final String uuid) {
|
||||||
|
this.uuid = uuid;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setName(final String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getPath() {
|
||||||
|
return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPath(final String path) {
|
||||||
|
this.path = path;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<FolderTreeNode> getSubFolders() {
|
||||||
|
return subFolders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSubFolders(final List<FolderTreeNode> subFolders) {
|
||||||
|
this.subFolders = subFolders;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isOpen() {
|
||||||
|
return open;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOpen(final boolean open) {
|
||||||
|
this.open = open;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSelected() {
|
||||||
|
return selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSelected(final boolean selected) {
|
||||||
|
this.selected = selected;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||||
|
xmlns:cc="http://xmlns.jcp.org/jsf/composite"
|
||||||
|
xmlns:cms="http://xmlns.jcp.org/jsf/composite/components/cms">
|
||||||
|
<cc:interface shortDescription="Component for nodes in a folder tree">
|
||||||
|
<cc:attribute name="basePath"
|
||||||
|
required="true"
|
||||||
|
shortDescription="Base path (mvc.basePath and contentsection" />
|
||||||
|
<cc:attribute name="collapsed"
|
||||||
|
required="true"
|
||||||
|
shortDescription="Is the folder collapsed?"
|
||||||
|
type="boolean" />
|
||||||
|
<cc:attribute name="name"
|
||||||
|
required="true"
|
||||||
|
shortDescription="The name of the folder." />
|
||||||
|
<cc:attribute name="path"
|
||||||
|
required="true"
|
||||||
|
shortDescription="The path of the folder." />
|
||||||
|
<cc:attribute name="selected"
|
||||||
|
required="true"
|
||||||
|
shortDescription="Is the folder selected?"
|
||||||
|
type="boolean" />
|
||||||
|
<cc:attribute name="subFolders"
|
||||||
|
required="false"
|
||||||
|
type="java.util.Collection" />
|
||||||
|
</cc:interface>
|
||||||
|
<cc:implementation>
|
||||||
|
<c:choose>
|
||||||
|
<c:when test="#{not empty subFolders}">
|
||||||
|
<li class="folder-tree-node list-group-item">
|
||||||
|
<div class="d-flex">
|
||||||
|
<button class="btn btn-light p-0 subfolders-toggler"
|
||||||
|
data-toggle="collapse"
|
||||||
|
data-target="##{cc.attrs.name}-subfolders"
|
||||||
|
aria-expanded="false"
|
||||||
|
aria-controls="##{cc.attrs.name}-subfolders"
|
||||||
|
type="button">
|
||||||
|
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.foldersnav.subfolders.expand']}
|
||||||
|
</span>
|
||||||
|
</button>
|
||||||
|
<a class="pl-0"
|
||||||
|
href="#{cc.attrs.basePath}/#{cc.attrs.path}">#{cc.attrs.name}</a>
|
||||||
|
</div>
|
||||||
|
<ul class="border-0 #{collapsed ? 'collapse' : 'collapse.show'} list-group"
|
||||||
|
id="##{cc.attrs.name}-subfolders">
|
||||||
|
<c:forEach items="#{cc.attrs.subFolders}"
|
||||||
|
var="subFolder">
|
||||||
|
<cms:treeNode basePath="#{cc.attrs.basePath}"
|
||||||
|
collapsed="#{!subFolder.open}"
|
||||||
|
name="#{subFolder.name}"
|
||||||
|
path="#{subFolder.path}"
|
||||||
|
selected="#{subFolder.selected}"
|
||||||
|
subFolders="#{subFolder.subFolders}" />
|
||||||
|
</c:forEach>
|
||||||
|
</ul>
|
||||||
|
</li>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<li class="folder-tree-node list-group-item">
|
||||||
|
<a href="#{cc.attrs.href}">#{cc.attrs.name}</a>
|
||||||
|
</li>
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
|
</cc:implementation>
|
||||||
|
</html>
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<ui:composition template="/WEB-INF/views/org/librecms/ui/content-section/contentsection.xhtml">
|
<ui:composition template="/WEB-INF/views/org/librecms/ui/content-section/contentsection.xhtml">
|
||||||
|
|
||||||
<ui:param name="activePage" value="folderBrowser" />
|
<ui:param name="activePage" value="folderBrowser" />
|
||||||
<ui:param name="title" value="#{CmsAdminMessages['folderbrowser.title']}" />
|
<ui:param name="title" value="#{CmsAdminMessages['contentsection.not_found.title']}" />
|
||||||
<ui:define name="breadcrumb">
|
<ui:define name="breadcrumb">
|
||||||
<li class="breadcrumb-item">
|
<li class="breadcrumb-item">
|
||||||
#{CmsAdminMessages['contentsections.list.label']}
|
#{CmsAdminMessages['contentsections.list.label']}
|
||||||
|
|
|
||||||
|
|
@ -26,10 +26,10 @@
|
||||||
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
<div class="collapse navbar-collapse" id="navbarSupportedContent">
|
||||||
<ul class="navbar-nav mr-auto">
|
<ul class="navbar-nav mr-auto">
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link #{activePage == 'folderBrowser' ? 'active' : ''}"
|
<a class="nav-link #{activePage == 'documentFolders' ? 'active' : ''}"
|
||||||
href='#{mvc.basePath}/#{ContentSectionModel.sectionName}/folderbrowser'>
|
href='#{mvc.basePath}/#{ContentSectionModel.sectionName}/document-folders'>
|
||||||
<bootstrap:svgIcon icon="folder2-open" />
|
<bootstrap:svgIcon icon="folder2-open" />
|
||||||
<span>#{CmsAdminMessages['folderbrowser.title']}</span>
|
<span>#{CmsAdminMessages['contentsection.documentfolder.title']}</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<!DOCTYPE html [<!ENTITY times '×'>]>
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
|
xmlns:bootstrap="http://xmlns.jcp.org/jsf/composite/components/bootstrap"
|
||||||
|
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||||
|
xmlns:libreccm="http://xmlns.jcp.org/jsf/composite/components/libreccm"
|
||||||
|
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
|
||||||
|
<ui:composition template="/WEB-INF/views/org/librecms/ui/content-section/contentsection.xhtml">
|
||||||
|
|
||||||
|
<ui:param name="activePage" value="documentFolders" />
|
||||||
|
<ui:param name="title" value="#{CmsAdminMessages['contentsection.documentfolder.title']}" />
|
||||||
|
<ui:define name="breadcrumb">
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
#{CmsAdminMessages['contentsection.documentfolder.title']}
|
||||||
|
</li>
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
<ui:define name="main">
|
||||||
|
<div class="container">
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
#{CmsAdminMessages.getMessage("contentsections.documentfolder.not_found", [contentSection, folderPath])}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</ui:define>
|
||||||
|
|
||||||
|
</ui:composition>
|
||||||
|
</html>
|
||||||
|
|
||||||
|
|
@ -2,27 +2,63 @@
|
||||||
<html xmlns="http://www.w3.org/1999/xhtml"
|
<html xmlns="http://www.w3.org/1999/xhtml"
|
||||||
xmlns:bootstrap="http://xmlns.jcp.org/jsf/composite/components/bootstrap"
|
xmlns:bootstrap="http://xmlns.jcp.org/jsf/composite/components/bootstrap"
|
||||||
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
|
||||||
|
xmlns:cms="http://xmlns.jcp.org/jsf/composite/components/cms"
|
||||||
xmlns:libreccm="http://xmlns.jcp.org/jsf/composite/components/libreccm"
|
xmlns:libreccm="http://xmlns.jcp.org/jsf/composite/components/libreccm"
|
||||||
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
|
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
|
||||||
<ui:composition template="/WEB-INF/views/org/librecms/ui/content-section/contentsection.xhtml">
|
<ui:composition template="/WEB-INF/views/org/librecms/ui/content-section/contentsection.xhtml">
|
||||||
|
|
||||||
<ui:param name="activePage" value="folderBrowser" />
|
<ui:param name="activePage" value="documentFolders" />
|
||||||
<ui:param name="title" value="#{CmsAdminMessages['contentsection.documentfolder.title']}" />
|
<ui:param name="title" value="#{CmsAdminMessages['contentsection.documentfolder.title']}" />
|
||||||
<ui:define name="breadcrumb">
|
<ui:define name="breadcrumb">
|
||||||
<li class="breadcrumb-item">
|
<c:choose>
|
||||||
#{CmsAdminMessages['contentsections.list.label']}
|
<c:when test="#{DocumentFolderModel.breadcrumbs.isEmpty()}">
|
||||||
|
<li aria-current="page" class="breadcrumb-item">
|
||||||
|
#{CmsAdminMessages['contentsection.documentfolder.title']}
|
||||||
</li>
|
</li>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
<a href="#{mvc.basePath}/#{ContentSectionModel.sectionName}/document-folders">
|
||||||
|
#{CmsAdminMessages['contentsection.documentfolder.title']}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
|
<c:forEach items="#{DocumentFolderModel.breadcrumbs}"
|
||||||
|
var="breadcrumb">
|
||||||
|
<c:choose>
|
||||||
|
<c:when test="#{breadcrumb.currentFolder}">
|
||||||
|
<li class="breadcrumb-item #{breadcrumb.currentFolder ? 'active' : ''}">
|
||||||
|
#{breadcrumb.pathToken}
|
||||||
|
</li>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<li class="breadcrumb-item">
|
||||||
|
<a href="#{mvc.basePath}/#{ContentSectionModel.sectionName}/document-folders/#{breadcrumb.path}">#{breadcrumb.pathToken}</a>
|
||||||
|
</li>
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
|
|
||||||
|
</c:forEach>
|
||||||
</ui:define>
|
</ui:define>
|
||||||
|
|
||||||
<ui:define name="main">
|
<ui:define name="main">
|
||||||
<div class="container-fluid">
|
<div class="container-fluid">
|
||||||
<h1>#{CmsAdminMessages.getMessage("contentsection.documentfolder.heading", [ContentSectionModel.sectionName])}</h1>
|
<h1>#{CmsAdminMessages.getMessage("contentsection.documentfolder.heading", [ContentSectionModel.sectionName])}</h1>
|
||||||
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<nav class="col-sm-3 documentfolder">
|
<nav class="col-sm-3 documentfolder foldertree">
|
||||||
<ul class="list-group">
|
<ul class="list-group">
|
||||||
<li class="list-group-item">
|
<c:forEach items="#{ContentSectionModel.folders}"
|
||||||
|
var="folder">
|
||||||
|
<cms:treeNode basePath="#{mvc.basePath}/#{ContentSectionModel.sectionName}/document-folders"
|
||||||
|
collapsed="#{!folder.open}"
|
||||||
|
name="#{folder.name}"
|
||||||
|
path="#{folder.path}"
|
||||||
|
selected="#{folder.selected}"
|
||||||
|
subFolders="#{folder.subFolders}" />
|
||||||
|
</c:forEach>
|
||||||
|
<!-- <li class="list-group-item">
|
||||||
<a class="" href="#">Folder 1</a>
|
<a class="" href="#">Folder 1</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
|
|
@ -33,7 +69,7 @@
|
||||||
aria-expanded="false"
|
aria-expanded="false"
|
||||||
aria-controls="folder-2-subfolders"
|
aria-controls="folder-2-subfolders"
|
||||||
type="button">
|
type="button">
|
||||||
<!--<bootstrap:svgIcon icon="caret-right-fill" />-->
|
<bootstrap:svgIcon icon="caret-right-fill" />
|
||||||
<span class="sr-only">
|
<span class="sr-only">
|
||||||
#{CmsAdminMessages['contentsection.documentfolder.foldersnav.subfolders.expand']}
|
#{CmsAdminMessages['contentsection.documentfolder.foldersnav.subfolders.expand']}
|
||||||
</span>
|
</span>
|
||||||
|
|
@ -61,14 +97,43 @@
|
||||||
</li>
|
</li>
|
||||||
<li class="list-group-item">
|
<li class="list-group-item">
|
||||||
<a class="" href="#">Folder 5</a>
|
<a class="" href="#">Folder 5</a>
|
||||||
</li>
|
</li>-->
|
||||||
</ul>
|
</ul>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="col-sm-9">
|
<div class="col-sm-9">
|
||||||
<div class="d-flex">
|
<div class="d-flex justify-content-between mb-2">
|
||||||
|
<form action="#" class="form-inline mr-2" method="GET">
|
||||||
|
<div class="input-group">
|
||||||
|
<div class="input-group-prepend">
|
||||||
|
<label class="mr-2" for="document-folder-filter">
|
||||||
|
<span>#{CmsAdminMessages['contentsection.documentfolder.filter.label']}</span>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<input id="documentfolder-filter"
|
||||||
|
name="filterTerm"
|
||||||
|
type="text" />
|
||||||
|
<div class="input-group-append">
|
||||||
|
<button class="btn btn-secondary"
|
||||||
|
type="submit">
|
||||||
|
<bootstrap:svgIcon icon="search" />
|
||||||
|
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.filter.submit']}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
<p>
|
<p>
|
||||||
${CmsAdminMessages.getMessage("contentsection.documentfolder.pageof", [DocumentFolderModel.currentPage, DocumentFolderModel.numberOfPages, DocumentFolderModel.maxResults, DocumentFolderModel.count])}
|
${CmsAdminMessages.getMessage("contentsection.documentfolder.pageof", [DocumentFolderModel.currentPage, DocumentFolderModel.numberOfPages])}
|
||||||
</p>
|
</p>
|
||||||
|
<div>
|
||||||
|
<button class="btn btn-primary" title="#{CmsAdminMessages['contentsection.documentfolder.add_subfolder']}">
|
||||||
|
<bootstrap:svgIcon icon="folder-plus" />
|
||||||
|
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.add_subfolder']}</span>
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-primary" title="#{CmsAdminMessages['contentsection.documentfolder.add_document']}">
|
||||||
|
<bootstrap:svgIcon icon="file-earmark-plus" />
|
||||||
|
<span class="sr-only">#{CmsAdminMessages['contentsection.documentfolder.add_document']}</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<table class="table table-hover documentfolder">
|
<table class="table table-hover documentfolder">
|
||||||
<thead class="thead-light">
|
<thead class="thead-light">
|
||||||
|
|
@ -100,7 +165,16 @@
|
||||||
<c:forEach items="#{DocumentFolderModel.rows}"
|
<c:forEach items="#{DocumentFolderModel.rows}"
|
||||||
var="row">
|
var="row">
|
||||||
<tr>
|
<tr>
|
||||||
<td><a href="#">#{row.name}</a></td>
|
<td>
|
||||||
|
<c:choose>
|
||||||
|
<c:when test="#{row.folder}">
|
||||||
|
<a href="#{mvc.basePath}/#{ContentSectionModel.sectionName}/document-folders/#{row.folderPath}">#{row.name}</a>
|
||||||
|
</c:when>
|
||||||
|
<c:otherwise>
|
||||||
|
<a href="#">#{row.name}</a>
|
||||||
|
</c:otherwise>
|
||||||
|
</c:choose>
|
||||||
|
</td>
|
||||||
<td>
|
<td>
|
||||||
#{row.languagesAsString}
|
#{row.languagesAsString}
|
||||||
</td>
|
</td>
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,7 @@
|
||||||
<ui:composition template="/WEB-INF/views/org/librecms/ui/content-section/contentsection.xhtml">
|
<ui:composition template="/WEB-INF/views/org/librecms/ui/content-section/contentsection.xhtml">
|
||||||
|
|
||||||
<ui:param name="activePage" value="folderBrowser" />
|
<ui:param name="activePage" value="folderBrowser" />
|
||||||
<ui:param name="title" value="#{CmsAdminMessages['folderbrowser.title']}" />
|
<ui:param name="title" value="Test data generator" />
|
||||||
<ui:define name="breadcrumb">
|
<ui:define name="breadcrumb">
|
||||||
<li class="breadcrumb-item">
|
<li class="breadcrumb-item">
|
||||||
#{CmsAdminMessages['contentsections.list.label']}
|
#{CmsAdminMessages['contentsections.list.label']}
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ contentsections.edit_dialog.close=Cancel
|
||||||
contentsections.edit_dialog.name.label=Name
|
contentsections.edit_dialog.name.label=Name
|
||||||
contentsections.edit_dialog.save=Rename content section
|
contentsections.edit_dialog.save=Rename content section
|
||||||
contentsections.edit_dialog.name.help=The name of the content section. Can only contain the letters a to z, the numbers 0-9, the hyphen and the underscore.
|
contentsections.edit_dialog.name.help=The name of the content section. Can only contain the letters a to z, the numbers 0-9, the hyphen and the underscore.
|
||||||
contentsection.documentfolder.title=Document Folders
|
contentsection.documentfolder.title=Documents
|
||||||
contentsection.documentfolder.heading=Content Section {0} Documents Folder
|
contentsection.documentfolder.heading=Content Section {0} Documents Folder
|
||||||
contentsection.documentfolder.headers.name.label=Name
|
contentsection.documentfolder.headers.name.label=Name
|
||||||
contentsection.documentfolder.headers.languages.label=Languages
|
contentsection.documentfolder.headers.languages.label=Languages
|
||||||
|
|
@ -44,4 +44,10 @@ contentsection.documentfolder.pagination.next_page=Next page
|
||||||
contentsection.not_found=No content section identifed by {0} available.
|
contentsection.not_found=No content section identifed by {0} available.
|
||||||
contentsection.accessdenied=Your are not permitted to access content section {0}.
|
contentsection.accessdenied=Your are not permitted to access content section {0}.
|
||||||
contentsection.documentfolder.types.folder=Folder
|
contentsection.documentfolder.types.folder=Folder
|
||||||
contentsection.documentfolder.pageof=Page {0} of {1}. Showing max. {2} of {3} documents per page.
|
contentsection.documentfolder.pageof=Page {0} of {1}.
|
||||||
|
contentsection.documentfolder.add_document=Create document
|
||||||
|
contentsection.documentfolder.add_subfolder=Add subfolder
|
||||||
|
contentsection.documentfolder.filter.label=Filter documents
|
||||||
|
contentsection.documentfolder.filter.submit=Apply filter
|
||||||
|
contentsections.documentfolder.not_found=Not folder with path {1} found in content section {0}.
|
||||||
|
contentsection.not_found.title=Content Section not found
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ contentsections.edit_dialog.close=Abbrechen
|
||||||
contentsections.edit_dialog.name.label=Name
|
contentsections.edit_dialog.name.label=Name
|
||||||
contentsections.edit_dialog.save=Content Section umbenennen
|
contentsections.edit_dialog.save=Content Section umbenennen
|
||||||
contentsections.edit_dialog.name.help=Der Name der Content Section. Darf nur die Zeichen a bis z, 0-9, the Bindestrich und den Unterstrich enthalten.
|
contentsections.edit_dialog.name.help=Der Name der Content Section. Darf nur die Zeichen a bis z, 0-9, the Bindestrich und den Unterstrich enthalten.
|
||||||
contentsection.documentfolder.title=Dokumenten-Ordner
|
contentsection.documentfolder.title=Dokumente
|
||||||
contentsection.documentfolder.heading=Content Section {0} Dokumenten-Ordner
|
contentsection.documentfolder.heading=Content Section {0} Dokumenten-Ordner
|
||||||
contentsection.documentfolder.headers.name.label=Name
|
contentsection.documentfolder.headers.name.label=Name
|
||||||
contentsection.documentfolder.headers.languages.label=Sprachen
|
contentsection.documentfolder.headers.languages.label=Sprachen
|
||||||
|
|
@ -44,4 +44,10 @@ contentsection.documentfolder.pagination.next_page=Eine Seite weiter
|
||||||
contentsection.not_found=Keine Content Section mit dem Identifier {0} gefunden.
|
contentsection.not_found=Keine Content Section mit dem Identifier {0} gefunden.
|
||||||
contentsection.accessdenied=Sind sind nicht berechtigt auf die Content Section {0} zuzugreifen.
|
contentsection.accessdenied=Sind sind nicht berechtigt auf die Content Section {0} zuzugreifen.
|
||||||
contentsection.documentfolder.types.folder=Ordner
|
contentsection.documentfolder.types.folder=Ordner
|
||||||
contentsection.documentfolder.pageof=Seite {0} von {1}. Zeige max. {2} von {3} Dokumenten pro Seite.
|
contentsection.documentfolder.pageof=Seite {0} von {1}.
|
||||||
|
contentsection.documentfolder.add_document=Neues Dokument erstellen
|
||||||
|
contentsection.documentfolder.add_subfolder=Unterordner erstellen
|
||||||
|
contentsection.documentfolder.filter.label=Dokumente filtern
|
||||||
|
contentsection.documentfolder.filter.submit=Filter anwenden
|
||||||
|
contentsections.documentfolder.not_found=Es wurde kein Ordner mit dem Pfad {1} in der Content Section {0} gefunden.
|
||||||
|
contentsection.not_found.title=Content Section nicht gefunden
|
||||||
|
|
|
||||||
|
|
@ -38,7 +38,7 @@ $pre-scrollable-max-height: 21.25rem;
|
||||||
// Navbar default colors have insufficient contrast
|
// Navbar default colors have insufficient contrast
|
||||||
$navbar-dark-color: #fff;
|
$navbar-dark-color: #fff;
|
||||||
|
|
||||||
nav.folderbrowser {
|
nav.foldertree {
|
||||||
& > ul.nav {
|
& > ul.nav {
|
||||||
margin-left: 1em;
|
margin-left: 1em;
|
||||||
margin-right: 1em;
|
margin-right: 1em;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue