From 6dcf94069efd22a199aa369e0f6c152e27dfa8cc Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Thu, 21 Jan 2021 21:31:36 +0100 Subject: [PATCH] Model for the folder browser Former-commit-id: 80b568cc28349f44258a6bc48bdf1dd7b51cd627 --- .../org/librecms/contentsection/Folder.java | 4 +- .../contentsection/FolderRepository.java | 66 +++++- .../librecms/ui/ContentSectionController.java | 213 +++++++++++++++++- .../org/librecms/ui/FolderBrowserModel.java | 55 ++++- .../librecms/ui/FolderBrowserRowModel.java | 117 ++++++++++ .../ui/content-section/folderbrowser.xhtml | 96 ++++++-- .../org/librecms/CmsAdminMessages.properties | 1 + .../librecms/CmsAdminMessages_de.properties | 1 + 8 files changed, 509 insertions(+), 44 deletions(-) create mode 100644 ccm-cms/src/main/java/org/librecms/ui/FolderBrowserRowModel.java diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java b/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java index 33bc11ffe..5114adffd 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/Folder.java @@ -117,7 +117,7 @@ import static org.librecms.CmsConstants.*; + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' " + "AND i.version = " + "org.librecms.contentsection.ContentItemVersion.DRAFT " - + "AND (LOWER(i.displayName) LIKE LOWER(:term) " + + "AND (LOWER(i.displayName) LIKE LOWER(CONCAT('%', :term)) " // + "OR LOWER(i.name.values) LIKE LOWER(:term)" + ")) " + "ORDER BY o.displayName" @@ -148,7 +148,7 @@ import static org.librecms.CmsConstants.*; + "AND c.type = '" + CATEGORIZATION_TYPE_FOLDER + "' " + "AND i.version = " + "org.librecms.contentsection.ContentItemVersion.DRAFT " - + "AND (LOWER(i.displayName) LIKE LOWER(:term) " + + "AND (LOWER(i.displayName) LIKE LOWER(CONCAT('%', :term)) " // + "OR LOWER(i.name.values) LIKE LOWER(:term)" + "))" // query = "SELECT COUNT(o) FROM CcmObject o " diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/FolderRepository.java b/ccm-cms/src/main/java/org/librecms/contentsection/FolderRepository.java index b3200b8e0..e8207abff 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/FolderRepository.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/FolderRepository.java @@ -22,6 +22,7 @@ import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.libreccm.categorization.Category; import org.libreccm.core.AbstractEntityRepository; +import org.libreccm.core.CcmObject; import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.Permission; import org.libreccm.security.RequiresPrivilege; @@ -31,7 +32,6 @@ import java.util.List; import java.util.Objects; import java.util.Optional; import java.util.UUID; -import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; @@ -225,6 +225,70 @@ public class FolderRepository extends AbstractEntityRepository { return query.getResultList(); } + public List findObjectsInFolder(final Folder folder) { + return findObjectsInFolder(folder, ""); + } + + public List findObjectsInFolder( + final Folder folder, + final String term + ) { + return getEntityManager() + .createNamedQuery("Folder.findObjects", CcmObject.class) + .setParameter( + "folder", + Objects.requireNonNull( + folder, + "Can't retrieve objects from null." + ) + ) + .setParameter("term", term) + .getResultList(); + } + + public List findObjectsInFolder( + final Folder folder, + final int firstResult, + final int maxResults + ) { + return findObjectsInFolder( + folder, firstResult, maxResults, "" + ); + } + + public List findObjectsInFolder( + final Folder folder, + final int firstResult, + final int maxResults, + final String term + ) { + return getEntityManager() + .createNamedQuery("Folder.findObjects", CcmObject.class) + .setParameter( + "folder", + Objects.requireNonNull( + folder, + "Can't retrieve objects from null." + ) + ) + .setParameter("term", "") + .setFirstResult(firstResult) + .setMaxResults(maxResults) + .getResultList(); + } + + public long countObjectsInFolder(final Folder folder) { + return countObjectsInFolder(folder, ""); + } + + public long countObjectsInFolder(final Folder folder, final String term) { + return getEntityManager() + .createNamedQuery("Folder.countObjects", Long.class) + .setParameter("folder", folder) + .setParameter("term", term) + .getSingleResult(); + } + @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) @Override diff --git a/ccm-cms/src/main/java/org/librecms/ui/ContentSectionController.java b/ccm-cms/src/main/java/org/librecms/ui/ContentSectionController.java index 1f1ad7b33..05bed4246 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/ContentSectionController.java +++ b/ccm-cms/src/main/java/org/librecms/ui/ContentSectionController.java @@ -7,17 +7,42 @@ package org.librecms.ui; 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.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentItemL10NManager; +import org.librecms.contentsection.ContentItemManager; import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSectionRepository; +import org.librecms.contentsection.ContentType; +import org.librecms.contentsection.ContentTypeManager; +import org.librecms.contentsection.ContentTypeRepository; +import org.librecms.contentsection.Folder; +import org.librecms.contentsection.FolderManager; +import org.librecms.contentsection.FolderRepository; + +import java.time.LocalDate; +import java.time.ZoneId; +import java.time.format.DateTimeFormatter; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.TreeSet; +import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.mvc.Controller; import javax.mvc.Models; +import javax.transaction.Transactional; +import javax.ws.rs.DefaultValue; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; import javax.ws.rs.WebApplicationException; /** @@ -31,16 +56,37 @@ public class ContentSectionController { @Inject private CmsAdminMessages cmsAdminMessages; - + + @Inject + private ContentItemManager itemManager; + + @Inject + private ContentItemL10NManager itemL10NManager; + @Inject private ContentSectionModel contentSectionModel; - + + @Inject + private ContentTypeManager contentTypeManager; + + @Inject + private ContentTypeRepository contentTypeRepo; + @Inject private FolderBrowserModel folderBrowserModel; - + + @Inject + private FolderManager folderManager; + + @Inject + private FolderRepository folderRepo; + + @Inject + private GlobalizationHelper globalizationHelper; + @Inject private Models models; - + @Inject private ContentSectionRepository sectionRepo; @@ -50,8 +96,11 @@ public class ContentSectionController { @GET @Path("/folderbrowser") @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) public String listItems( - @PathParam("sectionIdentifier") final String sectionIdentifier + @PathParam("sectionIdentifier") final String sectionIdentifier, + @QueryParam("firstResult") @DefaultValue("0") final int firstResult, + @QueryParam("maxResults") @DefaultValue("20") final int maxResults ) { final Identifier identifier = identifierParser.parseIdentifier( sectionIdentifier @@ -95,12 +144,160 @@ public class ContentSectionController { ); break; } - + contentSectionModel.setSection(section); - folderBrowserModel.setSection(section); - + + final List objects = folderRepo + .findObjectsInFolder( + section.getRootDocumentsFolder(), firstResult, maxResults + ); + folderBrowserModel.setCount( + folderRepo.countObjectsInFolder(section.getRootDocumentsFolder()) + ); + folderBrowserModel.setFirstResult(firstResult); + folderBrowserModel.setMaxResults(maxResults); + + folderBrowserModel.setRows( + objects + .stream() + .map(object -> buildRowModel(section, object)) + .collect(Collectors.toList()) + ); + return "org/librecms/ui/content-section/folderbrowser.xhtml"; + + } + + private FolderBrowserRowModel buildRowModel( + final ContentSection section, final CcmObject object + ) { + Objects.requireNonNull(section); + Objects.requireNonNull(object); + if (object instanceof ContentItem) { + return buildRowModel(section, (ContentItem) object); + } else if (object instanceof Folder) { + return buildRowModel(section, (Folder) object); + } else { + final FolderBrowserRowModel row = new FolderBrowserRowModel(); + + row.setCreated(""); + row.setDeletable(false); + row.setIsFolder(false); + row.setLanguages(Collections.emptySortedSet()); + row.setLastEditPublished(false); + row.setLastEdited(""); + row.setName(object.getDisplayName()); + row.setTitle(""); + row.setType(object.getClass().getSimpleName()); + + return row; + } + } + + private FolderBrowserRowModel buildRowModel( + final ContentSection section, final ContentItem contentItem + ) { + Objects.requireNonNull(section); + Objects.requireNonNull(contentItem); + + final FolderBrowserRowModel row = new FolderBrowserRowModel(); + row.setCreated( + DateTimeFormatter.ISO_DATE.format( + LocalDate.ofInstant( + contentItem.getCreationDate().toInstant(), + ZoneId.systemDefault() + ) + ) + ); + row.setDeletable(!itemManager.isLive(contentItem)); + row.setIsFolder(false); + row.setLanguages( + new TreeSet<>( + itemL10NManager + .availableLanguages(contentItem) + .stream() + .map(Locale::toString) + .collect(Collectors.toSet()) + ) + ); + if (itemManager.isLive(contentItem)) { + final LocalDate draftLastModified = LocalDate.ofInstant( + contentItem.getLastModified().toInstant(), + ZoneId.systemDefault() + ); + final LocalDate liveLastModified = LocalDate.ofInstant( + itemManager + .getLiveVersion(contentItem, contentItem.getClass()) + .map(ContentItem::getLastModified) + .map(Date::toInstant) + .get(), + ZoneId.systemDefault() + ); + row.setLastEditPublished( + liveLastModified.isBefore(draftLastModified) + ); + + } else { + row.setLastEditPublished(false); + } + + row.setLastEdited( + DateTimeFormatter.ISO_DATE.format( + LocalDate.ofInstant( + contentItem.getLastModified().toInstant(), + ZoneId.systemDefault() + ) + ) + ); + row.setName(contentItem.getDisplayName()); + row.setNoneCmsObject(false); + row.setTitle( + globalizationHelper.getValueFromLocalizedString( + contentItem.getTitle() + ) + ); + row.setType( + contentTypeRepo + .findByContentSectionAndClass(section, contentItem.getClass()) + .map(ContentType::getLabel) + .map( + label -> globalizationHelper.getValueFromLocalizedString( + label + ) + ).orElse("?") + ); + + return row; + } + + private FolderBrowserRowModel buildRowModel( + final ContentSection section, final Folder folder + ) { + Objects.requireNonNull(section); + Objects.requireNonNull(folder); + + final FolderBrowserRowModel row = new FolderBrowserRowModel(); + row.setCreated(""); + row.setDeletable( + folderManager.folderIsDeletable(folder) + == FolderManager.FolderIsDeletable.YES + ); + row.setIsFolder(true); + row.setLanguages(Collections.emptySortedSet()); + row.setLastEditPublished(false); + row.setLastEdited(""); + row.setName(folder.getDisplayName()); + row.setNoneCmsObject(false); + row.setTitle( + globalizationHelper.getValueFromLocalizedString(folder.getTitle()) + ); + row.setType( + globalizationHelper.getLocalizedTextsUtil( + "org.libreccms.CmsAdminMessages" + ).getText("contentsection.folderbrowser.types.folder") + ); + return row; } } diff --git a/ccm-cms/src/main/java/org/librecms/ui/FolderBrowserModel.java b/ccm-cms/src/main/java/org/librecms/ui/FolderBrowserModel.java index 1a30f6a83..0a72e2533 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/FolderBrowserModel.java +++ b/ccm-cms/src/main/java/org/librecms/ui/FolderBrowserModel.java @@ -5,9 +5,10 @@ */ package org.librecms.ui; -import org.librecms.contentsection.ContentSection; +import java.util.ArrayList; -import java.util.Objects; +import java.util.Collections; +import java.util.List; import javax.enterprise.context.RequestScoped; @@ -17,15 +18,45 @@ import javax.enterprise.context.RequestScoped; */ @RequestScoped public class FolderBrowserModel { - - private ContentSection section; - - protected void setSection(final ContentSection section) { - this.section = Objects.requireNonNull( - section, "Parameter section can't be null" - ); + + private long count; + + private int firstResult; + + private int maxResults; + + private List rows; + + public long getCount() { + return count; } - - - + + public void setCount(final long count) { + this.count = count; + } + + public int getFirstResult() { + return firstResult; + } + + protected void setFirstResult(final int firstResult) { + this.firstResult = firstResult; + } + + public int getMaxResults() { + return maxResults; + } + + protected void setMaxResults(final int maxResults) { + this.maxResults = maxResults; + } + + public List getRows() { + return Collections.unmodifiableList(rows); + } + + protected void setRows(final List rows) { + this.rows = new ArrayList<>(rows); + } + } diff --git a/ccm-cms/src/main/java/org/librecms/ui/FolderBrowserRowModel.java b/ccm-cms/src/main/java/org/librecms/ui/FolderBrowserRowModel.java new file mode 100644 index 000000000..35e62f256 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/FolderBrowserRowModel.java @@ -0,0 +1,117 @@ +/* + * 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.Collections; +import java.util.SortedSet; + +/** + * + * @author Jens Pelzetter + */ +public class FolderBrowserRowModel { + + private String created; + + private boolean deletable; + + private boolean isFolder; + + private SortedSet languages; + + private String lastEdited; + + private boolean lastEditPublished; + + private String name; + + private boolean noneCmsObject; + + private String title; + + private String type; + + public String getCreated() { + return created; + } + + protected void setCreated(final String created) { + this.created = created; + } + + public boolean isDeletable() { + return deletable; + } + + protected void setDeletable(final boolean deletable) { + this.deletable = deletable; + } + + public boolean isIsFolder() { + return isFolder; + } + + protected void setIsFolder(final boolean isFolder) { + this.isFolder = isFolder; + } + + public SortedSet getLanguages() { + return Collections.unmodifiableSortedSet(languages); + } + + protected void setLanguages(final SortedSet languages) { + this.languages = languages; + } + + public String getLastEdited() { + return lastEdited; + } + + protected void setLastEdited(final String lastEdited) { + this.lastEdited = lastEdited; + } + + public boolean isLastEditPublished() { + return lastEditPublished; + } + + protected void setLastEditPublished(final boolean lastEditPublished) { + this.lastEditPublished = lastEditPublished; + } + + public String getName() { + return name; + } + + protected void setName(final String name) { + this.name = name; + } + + public boolean isNoneCmsObject() { + return noneCmsObject; + } + + public void setNoneCmsObject(boolean noneCmsObject) { + this.noneCmsObject = noneCmsObject; + } + + public String getTitle() { + return title; + } + + protected void setTitle(final String title) { + this.title = title; + } + + public String getType() { + return type; + } + + protected void setType(final String type) { + this.type = type; + } + +} diff --git a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/content-section/folderbrowser.xhtml b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/content-section/folderbrowser.xhtml index e7ccb1a1c..a9a531d4c 100644 --- a/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/content-section/folderbrowser.xhtml +++ b/ccm-cms/src/main/resources/WEB-INF/views/org/librecms/ui/content-section/folderbrowser.xhtml @@ -20,13 +20,55 @@
@@ -105,7 +147,13 @@ An item Article 2021-01-20 09:03 - 2021-01-20 10:11 (#{CmsAdminMessages['contentsection.folderbrowser.cols.lastedit.published']}) + + 2021-01-20 10:11 + + + + #{CmsAdminMessages['contentsection.folderbrowser.cols.lastedit.published']} + @@ -114,7 +162,13 @@ Unppublished item item Article 2021-01-20 10:31 - 2021-01-20 10:34 (#{CmsAdminMessages['contentsection.folderbrowser.cols.lastedit.unpublished']}) + + 2021-01-20 10:34 + + + + #{CmsAdminMessages['contentsection.folderbrowser.cols.lastedit.unpublished']} +