From 5965e3ca433839d03802c4910e89b0de7c12c75d Mon Sep 17 00:00:00 2001 From: Jens Pelzetter Date: Thu, 11 Feb 2021 21:02:56 +0100 Subject: [PATCH] Controller for managing categories in category systems assigned to a Content Section Former-commit-id: 327431ed5e069959e238a69382773d5fd9bc469c --- .gitignore | 1 + .../contentsections/CategoriesController.java | 920 +++++++++++++++++- .../ui/contentsections/RetrieveResult.java | 67 ++ 3 files changed, 957 insertions(+), 31 deletions(-) create mode 100644 ccm-cms/src/main/java/org/librecms/ui/contentsections/RetrieveResult.java diff --git a/.gitignore b/.gitignore index 144b13113..8ef41e266 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ target .tscache *.vscode /ccm-core/nbproject/ +/ccm-cms/nbproject/ diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java index b8f68b89d..255741366 100644 --- a/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/CategoriesController.java @@ -7,8 +7,14 @@ package org.librecms.ui.contentsections; import org.libreccm.api.Identifier; import org.libreccm.api.IdentifierParser; +import org.libreccm.categorization.Categorization; +import org.libreccm.categorization.Category; +import org.libreccm.categorization.CategoryManager; +import org.libreccm.categorization.CategoryRepository; import org.libreccm.categorization.Domain; import org.libreccm.categorization.DomainOwnership; +import org.libreccm.categorization.ObjectNotAssignedToCategoryException; +import org.libreccm.core.CcmObject; import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.security.AuthorizationRequired; import org.librecms.contentsection.ContentSection; @@ -17,6 +23,8 @@ import org.librecms.contentsection.ContentSectionRepository; import java.time.ZoneId; import java.time.format.DateTimeFormatter; import java.util.List; +import java.util.Locale; +import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; @@ -25,7 +33,9 @@ import javax.inject.Inject; import javax.mvc.Controller; import javax.mvc.Models; import javax.transaction.Transactional; +import javax.ws.rs.FormParam; import javax.ws.rs.GET; +import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; @@ -38,6 +48,15 @@ import javax.ws.rs.PathParam; @Path("/{sectionIdentifier}/categorysystems") public class CategoriesController { + @Inject + private CategoryManager categoryManager; + + @Inject + private CategoryRepository categoryRepo; + + @Inject + private CategorySystemModel categorySystemModel; + @Inject private ContentSectionRepository sectionRepo; @@ -77,7 +96,7 @@ public class CategoriesController { } @GET - @Path("/{key}") + @Path("/{key}/categories") @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) public String showCategorySystem( @@ -88,44 +107,741 @@ public class CategoriesController { } @GET - @Path("/{key}/{categoryPath:(.+)?}") + @Path("/{context}/categories/{categoryPath:(.+)?}") @AuthorizationRequired @Transactional(Transactional.TxType.REQUIRED) public String showCategorySystem( @PathParam("sectionIdentifier") final String sectionIdentifier, - @PathParam("key") final String domainKey, + @PathParam("context") final String context, @PathParam("categoryPath") final String categoryPath ) { - //ToDo: Category System Model with - //* List of category systems - //* Category tree - //* Display of active category (if none = root?) with edit options - // listed below - // - - throw new UnsupportedOperationException(); + final Optional sectionResult = retrieveContentSection( + sectionIdentifier); + if (!sectionResult.isPresent()) { + models.put("sectionIdentifier", sectionIdentifier); + return "org/librecms/ui/contentsection/contentsection-not-found.xhtml"; + } + final ContentSection section = sectionResult.get(); + + final Optional domainResult = section + .getDomains() + .stream() + .filter(domain -> domain.getContext().equals(context)) + .findAny(); + if (!domainResult.isPresent()) { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + return "org/librecms/ui/contentsection/categorysystems/categorysystem-not-found.xhtml"; + } + categorySystemModel.setSelectedCategorySystem( + domainResult + .map(this::buildDomainListEntryModel) + .get() + ); + + categorySystemModel + .setCategorySystems( + section + .getDomains() + .stream() + .map(this::buildDomainListEntryModel) + .collect(Collectors.toList()) + ); + + final Domain domain = domainResult.get().getDomain(); + categorySystemModel.setCategoryTree(buildCategoryTree(domain)); + + final Category category; + if (categoryPath.isEmpty()) { + category = domain.getRoot(); + } else { + final Optional categoryResult = categoryRepo + .findByPath(domain, categoryPath); + if (!categoryResult.isPresent()) { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + models.put("categoryPath", categoryPath); + return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; + } + category = categoryResult.get(); + } + + categorySystemModel.setSelectedCategory(buildCategoryModel(category)); + + return "org/librecms/ui/contentsection/categorysystems/categorysystem.xhtml"; + } + + @POST + @Path("/{context}/categories/{categoryPath:(.+)?}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String renameCategory( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath, + @FormParam("categoryName") final String categoryName + ) { +// final Optional sectionResult = retrieveContentSection( +// sectionIdentifier); +// if (!sectionResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// return "org/librecms/ui/contentsection/contentsection-not-found.xhtml"; +// } +// final ContentSection section = sectionResult.get(); +// +// final Optional domainResult = section +// .getDomains() +// .stream() +// .filter(domain -> domain.getContext().equals(context)) +// .findAny(); +// if (!domainResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// return "org/librecms/ui/contentsection/categorysystems/categorysystem-not-found.xhtml"; +// } +// final Domain domain = domainResult.get().getDomain(); + if (categoryPath.isEmpty()) { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + models.put("categoryPath", categoryPath); + return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; + } +// final Category category; +// final Optional categoryResult = categoryRepo +// .findByPath(domain, categoryPath); +// if (!categoryResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// models.put("categoryPath", categoryPath); +// return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; +// } +// category = categoryResult.get(); + + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + if (result.isSuccessful()) { + final Category category = result.getResult(); + category.setName(categoryName); + categoryRepo.save(category); + + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryPath + ); + } else { + return result.getResponseTemplate(); + } + } + + @POST + @Path("/{context}/categories/@title/add") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String addTitle( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @FormParam("locale") final String localeParam, + @FormParam("value") final String value + ) { + return addTitle(sectionIdentifier, context, "", localeParam, value); + } + + @POST + @Path("/{context}/categories/{categoryPath:(.+)?}/@title/add") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String addTitle( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath, + @FormParam("locale") final String localeParam, + @FormParam("value") final String value + ) { +// final Optional sectionResult = retrieveContentSection( +// sectionIdentifier); +// if (!sectionResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// return "org/librecms/ui/contentsection/contentsection-not-found.xhtml"; +// } +// final ContentSection section = sectionResult.get(); +// +// final Optional domainResult = section +// .getDomains() +// .stream() +// .filter(domain -> domain.getContext().equals(context)) +// .findAny(); +// if (!domainResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// return "org/librecms/ui/contentsection/categorysystems/categorysystem-not-found.xhtml"; +// } +// final Domain domain = domainResult.get().getDomain(); +// if (categoryPath.isEmpty()) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// models.put("categoryPath", categoryPath); +// return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; +// } +// final Category category; +// final Optional categoryResult = categoryRepo +// .findByPath(domain, categoryPath); +// if (!categoryResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// models.put("categoryPath", categoryPath); +// return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; +// } +// category = categoryResult.get(); + + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + if (result.isSuccessful()) { + final Category category = result.getResult(); + final Locale locale = new Locale(localeParam); + category.getTitle().addValue(locale, value); + categoryRepo.save(category); + + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryPath + ); + } else { + return result.getResponseTemplate(); + } + } + + @POST + @Path("/{context}/categories/@title/edit/{locale}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String editTitle( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("locale") final String localeParam, + @FormParam("value") final String value + ) { + return editTitle( + sectionIdentifier, context, "", localeParam, value + ); + } + + @POST + @Path("/{context}/categories/{categoryPath:(.+)?}/@title/edit/{locale}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String editTitle( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath, + @PathParam("locale") final String localeParam, + @FormParam("value") final String value + ) { +// final Optional sectionResult = retrieveContentSection( +// sectionIdentifier); +// if (!sectionResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// return "org/librecms/ui/contentsection/contentsection-not-found.xhtml"; +// } +// final ContentSection section = sectionResult.get(); +// +// final Optional domainResult = section +// .getDomains() +// .stream() +// .filter(domain -> domain.getContext().equals(context)) +// .findAny(); +// if (!domainResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// return "org/librecms/ui/contentsection/categorysystems/categorysystem-not-found.xhtml"; +// } +// final Domain domain = domainResult.get().getDomain(); +// if (categoryPath.isEmpty()) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// models.put("categoryPath", categoryPath); +// return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; +// } +// final Category category; +// final Optional categoryResult = categoryRepo +// .findByPath(domain, categoryPath); +// if (!categoryResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// models.put("categoryPath", categoryPath); +// return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; +// } +// category = categoryResult.get(); + + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + if (result.isSuccessful()) { + final Category category = result.getResult(); + final Locale locale = new Locale(localeParam); + category.getTitle().addValue(locale, value); + categoryRepo.save(category); + + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryPath + ); + } else { + return result.getResponseTemplate(); + } + } + + @POST + @Path("/{context}/categories/@title/remove/{locale}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String removeTitle( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("locale") final String localeParam, + @FormParam("value") final String value + ) { + return removeTitle(sectionIdentifier, context, "", localeParam, value); + } + + @POST + @Path("/{context}/categories/{categoryPath:(.+)?}/@title/remove/{locale}") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String removeTitle( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath, + @PathParam("locale") final String localeParam, + @FormParam("value") final String value + ) { +// final Optional sectionResult = retrieveContentSection( +// sectionIdentifier); +// if (!sectionResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// return "org/librecms/ui/contentsection/contentsection-not-found.xhtml"; +// } +// final ContentSection section = sectionResult.get(); +// +// final Optional domainResult = section +// .getDomains() +// .stream() +// .filter(domain -> domain.getContext().equals(context)) +// .findAny(); +// if (!domainResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// return "org/librecms/ui/contentsection/categorysystems/categorysystem-not-found.xhtml"; +// } +// final Domain domain = domainResult.get().getDomain(); +// if (categoryPath.isEmpty()) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// models.put("categoryPath", categoryPath); +// return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; +// } +// final Category category; +// final Optional categoryResult = categoryRepo +// .findByPath(domain, categoryPath); +// if (!categoryResult.isPresent()) { +// models.put("sectionIdentifier", sectionIdentifier); +// models.put("context", context); +// models.put("categoryPath", categoryPath); +// return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; +// } +// category = categoryResult.get(); + + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + if (result.isSuccessful()) { + final Category category = result.getResult(); + final Locale locale = new Locale(localeParam); + category.getTitle().removeValue(locale); + categoryRepo.save(category); + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryPath + ); + } else { + return result.getResponseTemplate(); + } + } + + @POST + @Path("/{context}/categories/{categoryPath:(.+)?}/@attributes") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String updateAttributes( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath, + @FormParam("isEnabled") final String isEnabled, + @FormParam("isVisible") final String isVisible, + @FormParam("isAbstract") final String isAbstract + ) { + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + if (result.isSuccessful()) { + final Category category = result.getResult(); + category.setEnabled(Objects.equals("true", isEnabled)); + category.setVisible(Objects.equals("true", isVisible)); + category.setAbstractCategory(Objects.equals("true", isAbstract)); + categoryRepo.save(category); + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryPath + ); + } else { + return result.getResponseTemplate(); + } + } + + @POST + @Path("/{context}/categories/{categoryPath:(.+)?}/@index-element") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String setIndexElement( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath, + @PathParam("indexElementUuid") final String indexElementUuid + ) { + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + if (result.isSuccessful()) { + final Category category = result.getResult(); + final Optional categorizationResult = category + .getObjects() + .stream() + .filter( + categorization -> Objects.equals( + categorization.getUuid(), indexElementUuid + ) + ).findAny(); + if (categorizationResult.isPresent()) { + final CcmObject object = categorizationResult + .get() + .getCategorizedObject(); + try { + categoryManager.setIndexObject(category, object); + } catch (ObjectNotAssignedToCategoryException ex) { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + models.put("categoryPath", categoryPath); + models.put("categorizationUuid", indexElementUuid); + return "org/librecms/ui/contentsection/categorysystems/categorization-not-found.xhtml"; + } + } else { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + models.put("categoryPath", categoryPath); + models.put("categorizationUuid", indexElementUuid); + return "org/librecms/ui/contentsection/categorysystems/categorization-not-found.xhtml"; + } + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryPath + ); + } else { + return result.getResponseTemplate(); + } + } + + @POST + @Path("/{context}/categories/{categoryPath:(.+)?}/@index-element/reset") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String resetIndexElement( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath + ) { + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + if (result.isSuccessful()) { + final Category category = result.getResult(); + categoryManager.resetIndexObject(category); + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryPath + ); + } else { + return result.getResponseTemplate(); + } + } + + @POST + @Path("/{context}/categories/{categoryPath:(.+)?}/@subcategories") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String addSubcategory( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath, + @FormParam("categoryName") final String categoryName, + @FormParam("isEnabled") final String isEnabled, + @FormParam("isVisible") final String isVisible, + @FormParam("isAbstract") final String isAbstract + ) { + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + if (result.isSuccessful()) { + final Category category = result.getResult(); + final Category subCategory = new Category(); + subCategory.setName(categoryName); + subCategory.setEnabled(Objects.equals("true", isEnabled)); + subCategory.setVisible(Objects.equals("true", isVisible)); + subCategory.setAbstractCategory(Objects.equals("true", isAbstract)); + categoryManager.addSubCategoryToCategory(subCategory, category); + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryPath + ); + } else { + return result.getResponseTemplate(); + } + } + + @POST + @Path("/{context}/categories/{categoryPath:(.+)?}/@delete") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String deleteCategory( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath + ) { + if (categoryPath.isEmpty()) { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + models.put("categoryPath", categoryPath); + return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; + } + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + if (result.isSuccessful()) { + final Category category = result.getResult(); + final Category parentCategory = category.getParentCategory(); + categoryManager.removeSubCategoryFromCategory( + category, parentCategory + ); + categoryRepo.delete(category); + + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryManager.getCategoryPath(parentCategory) + ); + } else { + return result.getResponseTemplate(); + } + } + + @POST + @Path("/{context}/categories/{categoryPath:(.+)?}/@move") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String moveCategory( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath, + @FormParam("targetIdentififer") final String targetIdentifierParam + ) { + if (categoryPath.isEmpty()) { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + models.put("categoryPath", categoryPath); + return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; + } + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + if (result.isSuccessful()) { + final Identifier targetIdentifier = identifierParser + .parseIdentifier(targetIdentifierParam); + final Optional targetResult; + switch (targetIdentifier.getType()) { + case ID: + targetResult = categoryRepo.findById( + Long.parseLong(targetIdentifier.getIdentifier()) + ); + break; + default: + targetResult = categoryRepo.findByUuid( + targetIdentifier.getIdentifier() + ); + break; + } + if (!targetResult.isPresent()) { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + models.put("categoryPath", targetIdentifier); + return "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml"; + } + + final Category category = result.getResult(); + final Category oldParent = category.getParentCategory(); + final Category target = targetResult.get(); + + categoryManager.removeSubCategoryFromCategory(category, oldParent); + categoryManager.addSubCategoryToCategory(category, target); + + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryManager.getCategoryPath(target) + ); + } else { + return result.getResponseTemplate(); + } + } + + @POST + @Path("/{context}/categories/{categoryPath:(.+)?}/@order") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String orderSubCategories( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath, + @FormParam("direction") final String direction + ) { + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + + if (result.isSuccessful()) { + final Category category = result.getResult(); + final Category parentCategory = category.getParentCategory(); + if (parentCategory == null) { + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryManager.getCategoryPath(category) + ); + } + + switch (direction) { + case "DECREASE": + categoryManager.decreaseCategoryOrder( + category, parentCategory + ); + break; + case "INCREASE": + categoryManager.increaseCategoryOrder( + category, parentCategory + ); + break; + default: + // Nothing + break; + } + + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryManager.getCategoryPath(parentCategory) + ); + } else { + return result.getResponseTemplate(); + } + } + + @POST + @Path( + "/{context}/categories/{categoryPath:(.+)?}/objects/{objectIdentifier}/@order") + @AuthorizationRequired + @Transactional(Transactional.TxType.REQUIRED) + public String orderObjects( + @PathParam("sectionIdentifier") final String sectionIdentifier, + @PathParam("context") final String context, + @PathParam("categoryPath") final String categoryPath, + @PathParam("objectIdentifier") final String objectIdentifier, + @FormParam("direction") final String direction + ) { + final RetrieveResult result = retrieveCategory( + sectionIdentifier, context, categoryPath + ); + + if (result.isSuccessful()) { + final Category category = result.getResult(); + + final Optional categorizationResult = category + .getObjects() + .stream() + .filter( + categorization -> Objects.equals( + categorization.getUuid(), objectIdentifier + ) + ).findAny(); + if (categorizationResult.isPresent()) { + final CcmObject object = categorizationResult + .get() + .getCategorizedObject(); + try { + switch (direction) { + case "DECREASE": + categoryManager.decreaseObjectOrder( + object, category + ); + break; + case "INCREASE": + categoryManager.increaseObjectOrder( + object, category + ); + break; + default: + // Nothing + break; + } + } catch (ObjectNotAssignedToCategoryException ex) { + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryManager.getCategoryPath(category) + ); + } + } + + return String.format( + "redirect:/%s/categorysystems/%s/categories/%s", + sectionIdentifier, + context, + categoryManager.getCategoryPath(category) + ); + } else { + return result.getResponseTemplate(); + } } - //ToDo: Show category details - // - //ToDo: Rename category (disabled for root category) - // - //ToDo: Add, update, remove localized title - // - //ToDo: Set enabled, visible, abstract - // - //ToDo: Set and unset index element - // - //ToDo: Move category (disabled for root category) - - //ToDo: Delete category (disabled for root category) - // - //ToDo: List subcategories - // - //ToDo: Order subcategories - // - //ToDo: Add subcategory - private Optional retrieveContentSection( final String sectionIdentifier ) { @@ -152,6 +868,49 @@ public class CategoriesController { return sectionResult; } + private RetrieveResult retrieveCategory( + final String sectionIdentifier, + final String context, + final String categoryPath + ) { + final Optional sectionResult = retrieveContentSection( + sectionIdentifier); + if (!sectionResult.isPresent()) { + models.put("sectionIdentifier", sectionIdentifier); + return RetrieveResult.failed( + "org/librecms/ui/contentsection/contentsection-not-found.xhtml" + ); + } + final ContentSection section = sectionResult.get(); + + final Optional domainResult = section + .getDomains() + .stream() + .filter(domain -> domain.getContext().equals(context)) + .findAny(); + if (!domainResult.isPresent()) { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + return RetrieveResult.failed( + "org/librecms/ui/contentsection/categorysystems/categorysystem-not-found.xhtml" + ); + } + final Domain domain = domainResult.get().getDomain(); + + final Optional categoryResult = categoryRepo + .findByPath(domain, categoryPath); + if (!categoryResult.isPresent()) { + models.put("sectionIdentifier", sectionIdentifier); + models.put("context", context); + models.put("categoryPath", categoryPath); + return RetrieveResult.failed( + "org/librecms/ui/contentsection/categorysystems/category-not-found.xhtml" + ); + } + + return RetrieveResult.successful(categoryResult.get()); + } + private DomainListEntryModel buildDomainListEntryModel( final DomainOwnership ownership ) { @@ -172,4 +931,103 @@ public class CategoriesController { return model; } + private CategoryTreeNodeModel buildCategoryTree(final Domain domain) { + return buildCategoryTreeNode(domain.getRoot()); + } + + private CategoryTreeNodeModel buildCategoryTreeNode( + final Category category + ) { + final CategoryTreeNodeModel model = new CategoryTreeNodeModel(); + model.setTitle( + globalizationHelper.getValueFromLocalizedString( + category.getTitle() + ) + ); + model.setPath(categoryManager.getCategoryPath(category)); + if (!category.getSubCategories().isEmpty()) { + model.setSubCategories( + category + .getSubCategories() + .stream() + .map(this::buildCategoryTreeNode) + .collect(Collectors.toList()) + ); + } + + return model; + } + + private CategoryModel buildCategoryModel(final Category category) { + final CategoryModel model = new CategoryModel(); + model.setAbstractCategory(category.isAbstractCategory()); + model.setCategoryId(category.getObjectId()); + model.setCategoryOrder(category.getCategoryOrder()); + model.setDescription( + globalizationHelper.getValueFromLocalizedString( + category.getDescription() + ) + ); + model.setEnabled(category.isEnabled()); + model.setName(category.getName()); + model.setObjects( + category + .getObjects() + .stream() + .map(this::buildCategorizedObjectModel) + .collect(Collectors.toList()) + ); + model.setPath(categoryManager.getCategoryPath(category)); + model.setSubCategories( + category + .getSubCategories() + .stream() + .map(this::buildSubCategoriesModel) + .collect(Collectors.toList()) + ); + model.setTitle( + globalizationHelper.getValueFromLocalizedString( + category.getTitle() + ) + ); + model.setUniqueId(category.getUniqueId()); + model.setVisible(category.isVisible()); + return model; + } + + private CategoryModel buildSubCategoriesModel(final Category category) { + final CategoryModel model = new CategoryModel(); + model.setAbstractCategory(category.isAbstractCategory()); + model.setCategoryId(category.getObjectId()); + model.setCategoryOrder(category.getCategoryOrder()); + model.setDescription( + globalizationHelper.getValueFromLocalizedString( + category.getDescription() + ) + ); + model.setEnabled(category.isEnabled()); + model.setName(category.getName()); + model.setPath(categoryManager.getCategoryPath(category)); + model.setTitle( + globalizationHelper.getValueFromLocalizedString( + category.getTitle() + ) + ); + model.setUniqueId(category.getUniqueId()); + model.setVisible(category.isVisible()); + return model; + } + + private CategorizedObjectModel buildCategorizedObjectModel( + final Categorization categorization + ) { + final CcmObject object = categorization.getCategorizedObject(); + final CategorizedObjectModel model = new CategorizedObjectModel(); + model.setDisplayName(object.getDisplayName()); + model.setIndexObject(categorization.isIndexObject()); + model.setObjectOrder(categorization.getObjectOrder()); + model.setType(categorization.getType()); + return model; + } + } diff --git a/ccm-cms/src/main/java/org/librecms/ui/contentsections/RetrieveResult.java b/ccm-cms/src/main/java/org/librecms/ui/contentsections/RetrieveResult.java new file mode 100644 index 000000000..e83091d5a --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/ui/contentsections/RetrieveResult.java @@ -0,0 +1,67 @@ +/* + * 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.contentsections; + +import java.util.Objects; + +/** + * + * @author Jens Pelzetter + * @param + */ +public class RetrieveResult { + + private T result; + + private String responseTemplate; + + private boolean successful; + + private RetrieveResult() { + + } + + public static RetrieveResult successful(final R result) { + final RetrieveResult retrieveResult = new RetrieveResult<>(); + retrieveResult.setResult(Objects.requireNonNull(result)); + retrieveResult.setSuccessful(true); + return retrieveResult; + } + + public static RetrieveResult failed(final String responseTemplate) { + final RetrieveResult retrieveResult = new RetrieveResult<>(); + retrieveResult.setResponseTemplate( + Objects.requireNonNull(responseTemplate) + ); + retrieveResult.setSuccessful(false); + return retrieveResult; + } + + public T getResult() { + return result; + } + + private void setResult(final T result) { + this.result = result; + } + + public String getResponseTemplate() { + return responseTemplate; + } + + private void setResponseTemplate(final String responseTemplate) { + this.responseTemplate = responseTemplate; + } + + public boolean isSuccessful() { + return successful; + } + + private void setSuccessful(final boolean successful) { + this.successful = successful; + } + +}