DocumentFolderBrower view for content sections

Jens Pelzetter 2021-01-27 21:20:49 +01:00
parent 2917078e55
commit e518759964
15 changed files with 530 additions and 71 deletions

View File

@ -9,7 +9,6 @@ import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.api.Identifier;
import org.libreccm.api.IdentifierParser;
import org.libreccm.core.CcmObject;
import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.PermissionChecker;
@ -26,12 +25,15 @@ import org.librecms.contentsection.DocumentFolderEntry;
import org.librecms.contentsection.Folder;
import org.librecms.contentsection.FolderManager;
import org.librecms.contentsection.FolderRepository;
import org.librecms.contentsection.FolderType;
import org.librecms.contentsection.privileges.ItemPrivileges;
import org.librecms.contenttypes.Article;
import java.time.LocalDate;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.List;
@ -111,11 +113,13 @@ public class ContentSectionController {
private PermissionChecker permissionChecker;
@GET
@Path("/document-folders")
@Path("/document-folders{folderPath:(/.+)?}")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String listItems(
@PathParam("sectionIdentifier") final String sectionIdentifier,
@PathParam("folderPath") final String folderPath,
@QueryParam("filterTerm") @DefaultValue("") final String filterTerm,
@QueryParam("firstResult") @DefaultValue("0") final int firstResult,
@QueryParam("maxResults") @DefaultValue("20") final int maxResults
) {
@ -155,22 +159,60 @@ public class ContentSectionController {
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 List<DocumentFolderEntry> folderEntries = folderRepo
.getDocumentFolderEntries(
section.getRootDocumentsFolder(),
folder,
firstResult,
maxResults,
""
filterTerm
);
LOGGER.info(
"Retrieved objects in {} ms",
System.currentTimeMillis() - objectsStart
);
documentFolderModel.setCount(
folderRepo.countDocumentFolderEntries(
section.getRootDocumentsFolder(), ""
)
folderRepo.countDocumentFolderEntries(folder, filterTerm)
);
documentFolderModel.setFirstResult(firstResult);
documentFolderModel.setMaxResults(maxResults);
@ -179,6 +221,8 @@ public class ContentSectionController {
System.currentTimeMillis() - objectsStart
);
contentSectionModel.setFolders(buildFolderTree(section, folder));
final long rowsStart = System.currentTimeMillis();
documentFolderModel.setRows(
folderEntries
@ -186,8 +230,10 @@ public class ContentSectionController {
.map(entry -> buildRowModel(section, entry))
.collect(Collectors.toList())
);
LOGGER.info("Build rows in {} ms.", System.currentTimeMillis()
- rowsStart);
LOGGER.info(
"Build rows in {} ms.",
System.currentTimeMillis() - rowsStart
);
return "org/librecms/ui/content-section/document-folder.xhtml";
} 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(
final ContentSection section, final DocumentFolderEntry entry
) {
@ -312,6 +412,15 @@ public class ContentSectionController {
== FolderManager.FolderIsDeletable.YES
);
row.setFolder(true);
row.setFolderPath(
folderManager
.getFolderPath(folder)
.substring(
folderManager
.getFolderPath(section.getRootDocumentsFolder())
.length()
)
);
row.setLanguages(Collections.emptySortedSet());
row.setLastEditPublished(false);
row.setLastEdited("");

View File

@ -7,6 +7,9 @@ package org.librecms.ui;
import org.librecms.contentsection.ContentSection;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
@ -23,6 +26,8 @@ public class ContentSectionModel {
private ContentSection section;
private List<FolderTreeNode> folders;
protected void setSection(final ContentSection section) {
this.section = Objects.requireNonNull(
section, "Parameter section can't be null"
@ -36,4 +41,12 @@ public class ContentSectionModel {
.orElse("");
}
public List<FolderTreeNode> getFolders() {
return Collections.unmodifiableList(folders);
}
protected void setFolders(final List<FolderTreeNode> folders) {
this.folders = new ArrayList<>(folders);
}
}

View File

@ -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;
}
}

View File

@ -29,6 +29,8 @@ public class DocumentFolderModel {
private List<DocumentFolderRowModel> rows;
private List<DocumentFolderBreadcrumbModel> breadcrumbs;
public long getCount() {
return count;
}
@ -41,6 +43,7 @@ public class DocumentFolderModel {
return firstResult;
}
protected void setFirstResult(final int firstResult) {
this.firstResult = firstResult;
}
@ -52,13 +55,13 @@ public class DocumentFolderModel {
protected void setMaxResults(final int maxResults) {
this.maxResults = maxResults;
}
public long getNumberOfPages() {
return (long) Math.ceil((double) count / maxResults);
}
public long getCurrentPage() {
return (long) Math.ceil((double) firstResult / maxResults ) + 1;
return (long) Math.ceil((double) firstResult / maxResults) + 1;
}
public List<DocumentFolderRowModel> getRows() {
@ -68,5 +71,16 @@ public class DocumentFolderModel {
protected void setRows(final List<DocumentFolderRowModel> 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);
}
}

View File

@ -19,6 +19,8 @@ public class DocumentFolderRowModel {
private boolean deletable;
private boolean folder;
private String folderPath;
private SortedSet<String> languages;
@ -53,6 +55,14 @@ public class DocumentFolderRowModel {
public boolean isFolder() {
return folder;
}
public String getFolderPath() {
return folderPath;
}
protected void setFolderPath(final String folderPath) {
this.folderPath = folderPath;
}
protected void setFolder(final boolean folder) {
this.folder = folder;

View File

@ -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;
}
}

View File

@ -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>

View File

@ -7,7 +7,7 @@
<ui:composition template="/WEB-INF/views/org/librecms/ui/content-section/contentsection.xhtml">
<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">
<li class="breadcrumb-item">
#{CmsAdminMessages['contentsections.list.label']}

View File

@ -26,10 +26,10 @@
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav mr-auto">
<li class="nav-item">
<a class="nav-link #{activePage == 'folderBrowser' ? 'active' : ''}"
href='#{mvc.basePath}/#{ContentSectionModel.sectionName}/folderbrowser'>
<a class="nav-link #{activePage == 'documentFolders' ? 'active' : ''}"
href='#{mvc.basePath}/#{ContentSectionModel.sectionName}/document-folders'>
<bootstrap:svgIcon icon="folder2-open" />
<span>#{CmsAdminMessages['folderbrowser.title']}</span>
<span>#{CmsAdminMessages['contentsection.documentfolder.title']}</span>
</a>
</li>
</ul>

View File

@ -0,0 +1,27 @@
<!DOCTYPE html [<!ENTITY times '&#215;'>]>
<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>

View File

@ -2,73 +2,138 @@
<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:cms="http://xmlns.jcp.org/jsf/composite/components/cms"
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="folderBrowser" />
<ui:param name="activePage" value="documentFolders" />
<ui:param name="title" value="#{CmsAdminMessages['contentsection.documentfolder.title']}" />
<ui:define name="breadcrumb">
<li class="breadcrumb-item">
#{CmsAdminMessages['contentsections.list.label']}
</li>
<c:choose>
<c:when test="#{DocumentFolderModel.breadcrumbs.isEmpty()}">
<li aria-current="page" class="breadcrumb-item">
#{CmsAdminMessages['contentsection.documentfolder.title']}
</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 name="main">
<div class="container-fluid">
<h1>#{CmsAdminMessages.getMessage("contentsection.documentfolder.heading", [ContentSectionModel.sectionName])}</h1>
<div class="row">
<nav class="col-sm-3 documentfolder">
<nav class="col-sm-3 documentfolder foldertree">
<ul class="list-group">
<li class="list-group-item">
<a class="" href="#">Folder 1</a>
</li>
<li class="list-group-item">
<div class="d-flex">
<button class="btn btn-light p-0 subfolders-toggler"
data-toggle="collapse"
data-target="#folder-2-subfolders"
aria-expanded="false"
aria-controls="folder-2-subfolders"
type="button">
<!--<bootstrap:svgIcon icon="caret-right-fill" />-->
<span class="sr-only">
#{CmsAdminMessages['contentsection.documentfolder.foldersnav.subfolders.expand']}
</span>
</button>
<a class="pl-0" href="#">Folder 2</a>
</div>
<ul class="border-0 collapse list-group "
id="folder-2-subfolders">
<li class="border-0 list-group-item">
<a class="" href="#">Folder 2-1</a>
</li>
<li class="border-0 list-group-item">
<a class="" href="#">Folder 2-2</a>
</li>
<li class="border-0 list-group-item">
<a class="" href="#">Folder 2-3</a>
</li>
</ul>
</li>
<li class="list-group-item">
<a class="" href="#">Folder 3</a>
</li>
<li class="list-group-item">
<a class="" href="#">Folder 4</a>
</li>
<li class="list-group-item">
<a class="" href="#">Folder 5</a>
</li>
<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>
</li>
<li class="list-group-item">
<div class="d-flex">
<button class="btn btn-light p-0 subfolders-toggler"
data-toggle="collapse"
data-target="#folder-2-subfolders"
aria-expanded="false"
aria-controls="folder-2-subfolders"
type="button">
<bootstrap:svgIcon icon="caret-right-fill" />
<span class="sr-only">
#{CmsAdminMessages['contentsection.documentfolder.foldersnav.subfolders.expand']}
</span>
</button>
<a class="pl-0" href="#">Folder 2</a>
</div>
<ul class="border-0 collapse list-group "
id="folder-2-subfolders">
<li class="border-0 list-group-item">
<a class="" href="#">Folder 2-1</a>
</li>
<li class="border-0 list-group-item">
<a class="" href="#">Folder 2-2</a>
</li>
<li class="border-0 list-group-item">
<a class="" href="#">Folder 2-3</a>
</li>
</ul>
</li>
<li class="list-group-item">
<a class="" href="#">Folder 3</a>
</li>
<li class="list-group-item">
<a class="" href="#">Folder 4</a>
</li>
<li class="list-group-item">
<a class="" href="#">Folder 5</a>
</li>-->
</ul>
</nav>
<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>
${CmsAdminMessages.getMessage("contentsection.documentfolder.pageof", [DocumentFolderModel.currentPage, DocumentFolderModel.numberOfPages, DocumentFolderModel.maxResults, DocumentFolderModel.count])}
${CmsAdminMessages.getMessage("contentsection.documentfolder.pageof", [DocumentFolderModel.currentPage, DocumentFolderModel.numberOfPages])}
</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>
<table class="table table-hover documentfolder">
<thead class="thead-light">
@ -100,7 +165,16 @@
<c:forEach items="#{DocumentFolderModel.rows}"
var="row">
<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>
#{row.languagesAsString}
</td>

View File

@ -7,7 +7,7 @@
<ui:composition template="/WEB-INF/views/org/librecms/ui/content-section/contentsection.xhtml">
<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">
<li class="breadcrumb-item">
#{CmsAdminMessages['contentsections.list.label']}

View File

@ -24,7 +24,7 @@ contentsections.edit_dialog.close=Cancel
contentsections.edit_dialog.name.label=Name
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.
contentsection.documentfolder.title=Document Folders
contentsection.documentfolder.title=Documents
contentsection.documentfolder.heading=Content Section {0} Documents Folder
contentsection.documentfolder.headers.name.label=Name
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.accessdenied=Your are not permitted to access content section {0}.
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

View File

@ -24,7 +24,7 @@ contentsections.edit_dialog.close=Abbrechen
contentsections.edit_dialog.name.label=Name
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.
contentsection.documentfolder.title=Dokumenten-Ordner
contentsection.documentfolder.title=Dokumente
contentsection.documentfolder.heading=Content Section {0} Dokumenten-Ordner
contentsection.documentfolder.headers.name.label=Name
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.accessdenied=Sind sind nicht berechtigt auf die Content Section {0} zuzugreifen.
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

View File

@ -38,7 +38,7 @@ $pre-scrollable-max-height: 21.25rem;
// Navbar default colors have insufficient contrast
$navbar-dark-color: #fff;
nav.folderbrowser {
nav.foldertree {
& > ul.nav {
margin-left: 1em;
margin-right: 1em;