From 8bd923a1d95ec7ccd8cb3985817b87f8966dde6c Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Sat, 27 Mar 2021 14:01:14 +0100 Subject: [PATCH] Controller for Related Info Step --- .../contentsection/AttachmentList.java | 14 + .../AttachmentListRepository.java | 86 +++ .../documents/RelatedInfoStep.java | 535 +++++++++++++++++- 3 files changed, 625 insertions(+), 10 deletions(-) diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentList.java b/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentList.java index bc0d784c6..bec2266c8 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentList.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentList.java @@ -66,6 +66,20 @@ import static org.librecms.CmsConstants.DB_SCHEMA; query = "SELECT l FROM AttachmentList l WHERE l.listId = :listId" ) , + @NamedQuery( + name = "AttachmentList.findForItemAndId", + query = "SELECT l FROM AttachmentList l " + + "WHERE l.listId = :listId " + + "AND l.item = :item" + ) + , + @NamedQuery( + name = "AttachmentList.findForItemAndUuid", + query = "SELECT l FROM AttachmentList l " + + "WHERE l.uuid = :uuid " + + "AND l.item = :item" + ) + , @NamedQuery( name = "AttachmentList.findForItemAndName", query = "SELECT l FROM AttachmentList l " diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentListRepository.java b/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentListRepository.java index 829e6aaba..ea436bfc8 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentListRepository.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentListRepository.java @@ -7,9 +7,11 @@ package org.librecms.contentsection; import org.libreccm.core.AbstractEntityRepository; +import java.util.Optional; import java.util.UUID; import javax.enterprise.context.Dependent; +import javax.persistence.NoResultException; /** * @@ -21,6 +23,90 @@ public class AttachmentListRepository private static final long serialVersionUID = 1L; + /** + * Retrieves an attachment list for a specific item by the ID of the list. + * + * @param item The content item. + * @param listId The ID of the list. + * + * @return An {@link Optional} with the list if the item has a list with the + * provided ID. Otherwise an empty {@link Optional}. + */ + public Optional findForItemAndId( + final ContentItem item, final long listId + ) { + try { + return Optional.of( + getEntityManager() + .createNamedQuery( + "AttachmentList.findForItemAndId", + AttachmentList.class + ) + .setParameter("listId", listId) + .setParameter("item", item) + .getSingleResult() + ); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + + /** + * Retrieves an attachment list for a specific item by the UUID of the list. + * + * @param item The content item. + * @param uuid The UUID of the list. + * + * @return An {@link Optional} with the list if the item has a list with the + * provided UUID. Otherwise an empty {@link Optional}. + */ + public Optional findForItemAndUuid( + final ContentItem item, final String uuid + ) { + try { + return Optional.of( + getEntityManager() + .createNamedQuery( + "AttachmentList.findForItemAndUuid", + AttachmentList.class + ) + .setParameter("uuid", uuid) + .setParameter("item", item) + .getSingleResult() + ); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + + /** + * Retrieves an attachment list for a specific item by the name of the list. + * + * @param item The content item. + * @param name The name of the list. + * + * @return An {@link Optional} with the list if the item has a list with the + * provided name. Otherwise an empty {@link Optional}. + */ + public Optional findForItemAndName( + final ContentItem item, final String name + ) { + try { + return Optional.of( + getEntityManager() + .createNamedQuery( + "AttachmentList.findForItemAndName", + AttachmentList.class + ) + .setParameter("name", name) + .setParameter("item", item) + .getSingleResult() + ); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + @Override public Class getEntityClass() { return AttachmentList.class; diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/RelatedInfoStep.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/RelatedInfoStep.java index b1b305652..f28199853 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/RelatedInfoStep.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/documents/RelatedInfoStep.java @@ -5,30 +5,40 @@ */ package org.librecms.ui.contentsections.documents; +import org.libreccm.api.Identifier; +import org.libreccm.api.IdentifierParser; import org.libreccm.l10n.GlobalizationHelper; import org.librecms.assets.AssetTypeInfo; import org.librecms.assets.AssetTypesManager; +import org.librecms.assets.RelatedLink; +import org.librecms.contentsection.Asset; +import org.librecms.contentsection.AssetRepository; import org.librecms.contentsection.AttachmentList; import org.librecms.contentsection.AttachmentListL10NManager; import org.librecms.contentsection.AttachmentListManager; import org.librecms.contentsection.AttachmentListRepository; import org.librecms.contentsection.ContentItem; import org.librecms.contentsection.ContentItemManager; +import org.librecms.contentsection.ContentItemRepository; import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ItemAttachment; import org.librecms.contentsection.ItemAttachmentManager; import java.util.List; +import java.util.Locale; +import java.util.Optional; import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; import javax.mvc.Controller; +import javax.mvc.Models; import javax.transaction.Transactional; import javax.ws.rs.FormParam; import javax.ws.rs.POST; import javax.ws.rs.Path; +import javax.ws.rs.PathParam; /** * @@ -43,6 +53,9 @@ public class RelatedInfoStep implements MvcAuthoringStep { static final String PATH_FRAGMENT = "relatedinfo"; + @Inject + private AssetRepository assetRepo; + @Inject private AssetTypesManager assetTypesManager; @@ -55,15 +68,24 @@ public class RelatedInfoStep implements MvcAuthoringStep { @Inject private AttachmentListRepository listRepo; + @Inject + private ContentItemRepository itemRepo; + @Inject private ContentItemManager itemManager; @Inject private GlobalizationHelper globalizationHelper; + @Inject + private IdentifierParser identifierParser; + @Inject private ItemAttachmentManager attachmentManager; + @Inject + private Models models; + private ContentItem document; private ContentSection section; @@ -171,16 +193,509 @@ public class RelatedInfoStep implements MvcAuthoringStep { ); } - // ToDo Remove Attachment List - // Add attachment (attach asset) - // Add internal link - // Remove attachment - // ToDo Move attachment list to first position - // ToDo Move attachment list up - // ToDo Move attachment list down - // ToDo Move item attachment to first position - // ToDo Move item attachment up - // ToDo Move item attachment down + @POST + @Path("/attachmentlists/{attachmentListIdentifier}/@remove") + @Transactional(Transactional.TxType.REQUIRED) + public String removeAttachmentList( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam, + @FormParam("confirm") final String confirm + ) { + + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + + if ("true".equalsIgnoreCase(confirm)) { + listManager.removeAttachmentList(listResult.get()); + } + + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + @POST + @Path("/attachmentlists/{attachmentListIdentifier}/attachments") + @Transactional(Transactional.TxType.REQUIRED) + public String createAttachment( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam, + @FormParam("assetUuid") final String assetUuid + ) { + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + final AttachmentList list = listResult.get(); + + final Optional assetResult = assetRepo.findByUuid(assetUuid); + if (!assetResult.isPresent()) { + models.put("assetUuid", assetUuid); + return "org/librecms/ui/contenttypes/asset-not-found.xhtml"; + } + + final Asset asset = assetResult.get(); + + attachmentManager.attachAsset(asset, list); + + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + @POST + @Path("/attachmentlists/{attachmentListIdentifier}/internal-links") + @Transactional(Transactional.TxType.REQUIRED) + public String createInteralLink( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam, + @FormParam("targetItemUuid") final String targetItemUuid, + @FormParam("title") final String title + ) { + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + final AttachmentList list = listResult.get(); + + final Optional itemResult = itemRepo.findByUuid( + targetItemUuid + ); + if (!itemResult.isPresent()) { + models.put("targetItemUuid", targetItemUuid); + return "org/librecms/ui/contenttypes/target-item-not-found.xhtml"; + } + + final RelatedLink relatedLink = new RelatedLink(); + relatedLink.getTitle().addValue( + globalizationHelper.getNegotiatedLocale(), title + ); + relatedLink.setTargetItem(document); + + attachmentManager.attachAsset(relatedLink, list); + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + @POST + @Path( + "/attachmentlists/{attachmentListIdentifier}/internal-links/{interalLinkUuid}") + @Transactional(Transactional.TxType.REQUIRED) + public String updateInteralLinkTarget( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam, + @PathParam("internalLinkUuid") final String internalLinkUuid, + @FormParam("targetItemUuid") final String targetItemUuid + ) { + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + final AttachmentList list = listResult.get(); + + final Optional itemResult = itemRepo.findByUuid( + targetItemUuid + ); + if (!itemResult.isPresent()) { + models.put("targetItemUuid", targetItemUuid); + return "org/librecms/ui/contenttypes/target-item-not-found.xhtml"; + } + + final Optional linkResult = list + .getAttachments() + .stream() + .map(ItemAttachment::getAsset) + .filter(asset -> asset instanceof RelatedLink) + .map(asset -> (RelatedLink) asset) + .filter(link -> link.getUuid().equals(internalLinkUuid)) + .findAny(); + + if (!linkResult.isPresent()) { + models.put("contentItem", itemManager.getItemPath(document)); + models.put("listIdentifierParam", listIdentifierParam); + models.put("internalLinkUuid", internalLinkUuid); + return "org/librecms/ui/contenttypes/internal-link-asset-not-found.xhtml"; + } + + final RelatedLink link = linkResult.get(); + link.setTargetItem(document); + assetRepo.save(link); + + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + @POST + @Path( + "/attachmentlists/{attachmentListIdentifier}/internal-links/{interalLinkUuid}/title/@add") + @Transactional(Transactional.TxType.REQUIRED) + public String addInteralLinkTitle( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam, + @PathParam("internalLinkUuid") final String internalLinkUuid, + @FormParam("locale") final String localeParam, + @FormParam("value") final String value + ) { + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + final AttachmentList list = listResult.get(); + + final Optional linkResult = list + .getAttachments() + .stream() + .map(ItemAttachment::getAsset) + .filter(asset -> asset instanceof RelatedLink) + .map(asset -> (RelatedLink) asset) + .filter(link -> link.getUuid().equals(internalLinkUuid)) + .findAny(); + + if (!linkResult.isPresent()) { + models.put("contentItem", itemManager.getItemPath(document)); + models.put("listIdentifierParam", listIdentifierParam); + models.put("internalLinkUuid", internalLinkUuid); + return "org/librecms/ui/contenttypes/internal-link-asset-not-found.xhtml"; + } + + final RelatedLink link = linkResult.get(); + final Locale locale = new Locale(localeParam); + link.getTitle().addValue(locale, value); + assetRepo.save(link); + + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + @POST + @Path( + "/attachmentlists/{attachmentListIdentifier}/internal-links/{interalLinkUuid}/title/@edit/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String updateInteralLinkTitle( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam, + @PathParam("internalLinkUuid") final String internalLinkUuid, + @PathParam("locale") final String localeParam, + @FormParam("value") final String value + ) { + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + final AttachmentList list = listResult.get(); + + final Optional linkResult = list + .getAttachments() + .stream() + .map(ItemAttachment::getAsset) + .filter(asset -> asset instanceof RelatedLink) + .map(asset -> (RelatedLink) asset) + .filter(link -> link.getUuid().equals(internalLinkUuid)) + .findAny(); + + if (!linkResult.isPresent()) { + models.put("contentItem", itemManager.getItemPath(document)); + models.put("listIdentifierParam", listIdentifierParam); + models.put("internalLinkUuid", internalLinkUuid); + return "org/librecms/ui/contenttypes/internal-link-asset-not-found.xhtml"; + } + + final RelatedLink link = linkResult.get(); + final Locale locale = new Locale(localeParam); + link.getTitle().addValue(locale, value); + assetRepo.save(link); + + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + @POST + @Path( + "/attachmentlists/{attachmentListIdentifier}/internal-links/{interalLinkUuid}/title/@edit/{locale}") + @Transactional(Transactional.TxType.REQUIRED) + public String removeInteralLinkTitle( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam, + @PathParam("internalLinkUuid") final String internalLinkUuid, + @PathParam("locale") final String localeParam + ) { + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + final AttachmentList list = listResult.get(); + + final Optional linkResult = list + .getAttachments() + .stream() + .map(ItemAttachment::getAsset) + .filter(asset -> asset instanceof RelatedLink) + .map(asset -> (RelatedLink) asset) + .filter(link -> link.getUuid().equals(internalLinkUuid)) + .findAny(); + + if (!linkResult.isPresent()) { + models.put("contentItem", itemManager.getItemPath(document)); + models.put("listIdentifierParam", listIdentifierParam); + models.put("internalLinkUuid", internalLinkUuid); + return "org/librecms/ui/contenttypes/internal-link-asset-not-found.xhtml"; + } + + final RelatedLink link = linkResult.get(); + final Locale locale = new Locale(localeParam); + link.getTitle().removeValue(locale); + assetRepo.save(link); + + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + @POST + @Path( + "/attachmentlists/{attachmentListIdentifier}/attachments/{attachmentUuid}/@remove") + @Transactional(Transactional.TxType.REQUIRED) + public String removeAttachment( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam, + @PathParam("attachmentUuid") final String attachmentUuid, + @FormParam("confirm") final String confirm + ) { + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + final AttachmentList list = listResult.get(); + + final Optional> result = list + .getAttachments() + .stream() + .filter(attachment -> attachment.getUuid().equals(attachmentUuid)) + .findFirst(); + + if (result.isPresent() && "true".equalsIgnoreCase(confirm)) { + final Asset asset = result.get().getAsset(); + attachmentManager.unattachAsset(asset, list); + if (asset instanceof RelatedLink + && ((RelatedLink) asset).getTargetItem() != null) { + assetRepo.delete(asset); + } + } + + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + @POST + @Path( + "/attachmentlists/{attachmentListIdentifier}/@moveUp") + @Transactional(Transactional.TxType.REQUIRED) + public String moveListUp( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam + ) { + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + final AttachmentList list = listResult.get(); + + listManager.moveUp(list); + + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + @POST + @Path( + "/attachmentlists/{attachmentListIdentifier}/@moveDown") + @Transactional(Transactional.TxType.REQUIRED) + public String moveListDown( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam + ) { + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + final AttachmentList list = listResult.get(); + + listManager.moveDown(list); + + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + @POST + @Path( + "/attachmentlists/{attachmentListIdentifier}/attachments/{attachmentUuid}/@moveUp") + @Transactional(Transactional.TxType.REQUIRED) + public String moveAttachmentUp( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam, + @PathParam("attachmentUuid") final String attachmentUuid + ) { + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + final AttachmentList list = listResult.get(); + + final Optional> result = list + .getAttachments() + .stream() + .filter(attachment -> attachment.getUuid().equals(attachmentUuid)) + .findFirst(); + + if (result.isPresent()) { + final ItemAttachment attachment = result.get(); + final Asset asset = attachment.getAsset(); + attachmentManager.moveUp(asset, list); + } + + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + @POST + @Path( + "/attachmentlists/{attachmentListIdentifier}/attachments/{attachmentUuid}/@moveDown") + @Transactional(Transactional.TxType.REQUIRED) + public String moveAttachmentDown( + @PathParam("attachmentListIdentifier") + final String listIdentifierParam, + @PathParam("attachmentUuid") final String attachmentUuid + ) { + final Optional listResult = findAttachmentList( + listIdentifierParam + ); + if (!listResult.isPresent()) { + return showAttachmentListNotFound(listIdentifierParam); + } + final AttachmentList list = listResult.get(); + + final Optional> result = list + .getAttachments() + .stream() + .filter(attachment -> attachment.getUuid().equals(attachmentUuid)) + .findFirst(); + + if (result.isPresent()) { + final ItemAttachment attachment = result.get(); + final Asset asset = attachment.getAsset(); + attachmentManager.moveDown(asset, list); + } + + return String.format( + "redirect:/%s/@documents/%s/@authoringsteps/%s", + section.getLabel(), + getContentItemPath(), + PATH_FRAGMENT + ); + } + + private Optional findAttachmentList( + final String attachmentListIdentifier + ) { + final Identifier identifier = identifierParser.parseIdentifier( + attachmentListIdentifier + ); + final Optional listResult; + switch (identifier.getType()) { + case ID: + listResult = listRepo + .findForItemAndId( + document, Long.parseLong(identifier.getIdentifier()) + ); + break; + case UUID: + listResult = listRepo + .findForItemAndUuid( + document, identifier.getIdentifier() + ); + break; + default: + listResult = listRepo + .findForItemAndName( + document, identifier.getIdentifier() + ); + break; + } + + return listResult; + } + + private String showAttachmentListNotFound(final String listIdentifier) { + models.put("contentItem", itemManager.getItemPath(document)); + models.put("listIdentifier", listIdentifier); + return "org/librecms/ui/contenttypes/attachmentlist-not-found.xhtml"; + } + private AttachmentListDto buildAttachmentListDto( final AttachmentList attachmentList ) {