MVC controller and models for managing pages.

pull/10/head
Jens Pelzetter 2021-11-20 14:52:02 +01:00
parent 1ac439a428
commit f998b2e5cf
5 changed files with 692 additions and 11 deletions

View File

@ -119,6 +119,14 @@ public class Page extends CcmObject implements Serializable {
.orElse(null); .orElse(null);
} }
public void addProperty(final String key, final String value) {
properties.put(key, value);
}
public void removeProperty(final String key) {
properties.remove(key);
}
public void setProperties(final Map<String, String> properties) { public void setProperties(final Map<String, String> properties) {
this.properties = Optional this.properties = Optional
.ofNullable(properties) .ofNullable(properties)

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.ui;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named("CmsPageDetailsModel")
public class PageDetailsModel {
private String site;
private String categoryDomain;
private String category;
private Map<String, String> pageProperties;
public String getSite() {
return site;
}
protected void setSite(String site) {
this.site = site;
}
public String getCategoryDomain() {
return categoryDomain;
}
protected void setCategoryDomain(final String categoryDomain) {
this.categoryDomain = categoryDomain;
}
public String getCategory() {
return category;
}
protected void setCategory(String category) {
this.category = category;
}
public Map<String, String> getPageProperties() {
return Collections.unmodifiableMap(pageProperties);
}
protected void setPageProperties(final Map<String, String> pageProperties) {
this.pageProperties = new HashMap<>(pageProperties);
}
}

View File

@ -0,0 +1,78 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.ui;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class PageTreeNodeModel {
private String categoryName;
private List<PageTreeNodeModel> children;
private boolean pageAssigned;
private Map<String, String> properties;
public PageTreeNodeModel() {
children = new ArrayList<>();
properties = new HashMap<>();
}
public String getCategoryName() {
return categoryName;
}
protected void setCategoryName(final String categoryName) {
this.categoryName = categoryName;
}
public List<PageTreeNodeModel> getChildren() {
return Collections.unmodifiableList(children);
}
protected void setChildren(final List<PageTreeNodeModel> children) {
this.children = new ArrayList<>(children);
}
public boolean isPageAssigned() {
return pageAssigned;
}
public void setPageAssigned(final boolean pageAssigned) {
this.pageAssigned = pageAssigned;
}
public Map<String, String> getProperties() {
return Collections.unmodifiableMap(properties);
}
public void setProperties(final Map<String, String> properties) {
this.properties = new HashMap<>(properties);
}
}

View File

@ -18,18 +18,38 @@
*/ */
package org.librecms.ui; package org.librecms.ui;
import org.libreccm.api.Identifier;
import org.libreccm.api.IdentifierParser;
import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryRepository;
import org.libreccm.categorization.Domain; import org.libreccm.categorization.Domain;
import org.libreccm.categorization.DomainRepository;
import org.libreccm.core.CoreConstants; import org.libreccm.core.CoreConstants;
import org.libreccm.security.AuthorizationRequired; import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege; import org.libreccm.security.RequiresPrivilege;
import org.libreccm.sites.Site;
import org.libreccm.sites.SiteRepository;
import org.librecms.pages.Page;
import org.librecms.pages.PageManager;
import org.librecms.pages.PageRepository;
import org.librecms.pages.Pages;
import org.librecms.pages.PagesManager;
import org.librecms.pages.PagesRepository;
import java.util.HashMap;
import java.util.Optional;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.mvc.Controller; import javax.mvc.Controller;
import javax.mvc.Models;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import javax.ws.rs.FormParam; import javax.ws.rs.FormParam;
import javax.ws.rs.GET; import javax.ws.rs.GET;
import javax.ws.rs.POST; import javax.ws.rs.POST;
import javax.ws.rs.Path; import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
/** /**
* *
@ -40,6 +60,42 @@ import javax.ws.rs.Path;
@Path("/pages") @Path("/pages")
public class PagesController { public class PagesController {
private static final String PAGES_LIST_TEMPLATE
= "org/librecms/ui/cms/pages.xhtml";
@Inject
private CategoryRepository categoryRepo;
@Inject
private DomainRepository domainRepo;
@Inject
private IdentifierParser identifierParser;
@Inject
private Models models;
@Inject
private PagesDetailsModel pagesDetailsModel;
@Inject
private PagesManager pagesManager;
@Inject
private PagesRepository pagesRepo;
@Inject
private PageDetailsModel pageDetailsModel;
@Inject
private PageRepository pageRepo;
@Inject
private PageManager pageManager;
@Inject
private SiteRepository siteRepo;
/** /**
* Shows all available pages instances. * Shows all available pages instances.
* *
@ -49,7 +105,7 @@ public class PagesController {
@Path("/") @Path("/")
@AuthorizationRequired @AuthorizationRequired
public String getPages() { public String getPages() {
return "org/librecms/ui/cms/pages.xhtml"; return PAGES_LIST_TEMPLATE;
} }
/** /**
@ -73,18 +129,405 @@ public class PagesController {
@FormParam("primaryUrl") final String primaryUrlParam, @FormParam("primaryUrl") final String primaryUrlParam,
@FormParam("categoryDomain") final String categoryDomainParam @FormParam("categoryDomain") final String categoryDomainParam
) { ) {
// ToDo final Optional<Site> siteResult = siteRepo.findByDomain(siteParam);
throw new UnsupportedOperationException(); if (siteResult.isEmpty()) {
models.put("siteNotFound", true);
models.put("site", siteParam);
}
final Optional<Domain> domainResult = domainRepo.findByDomainKey(
categoryDomainParam
);
if (domainResult.isEmpty()) {
models.put("domainNotFound", true);
models.put("domainKey", categoryDomainParam);
return PAGES_LIST_TEMPLATE;
}
if (primaryUrlParam == null || primaryUrlParam.isBlank()) {
models.put("primaryUrlNullOrEmpty", true);
return PAGES_LIST_TEMPLATE;
}
final Site site = siteResult.get();
final Domain domain = domainResult.get();
final String primaryUrl = primaryUrlParam;
pagesManager.createPages(primaryUrl, site, domain);
return "redirect:/pages";
}
@GET
@Path("/{pagesInstance}")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String showPagesDetails(
@PathParam("pagesInstance") final String pagesInstance
) {
final Optional<Pages> pagesResult = findPages(pagesInstance);
if (pagesResult.isEmpty()) {
return showPagesNotFound(pagesInstance);
}
final Pages pages = pagesResult.get();
pagesDetailsModel.setCategoryDomain(
pages.getCategoryDomain().getDomainKey()
);
pagesDetailsModel.setPrimaryUrl(pages.getPrimaryUrl());
pagesDetailsModel.setSite(pages.getSite().getDomainOfSite());
pagesDetailsModel.setPageTreeRoot(
buildPageTreeNodeModel(pages.getCategoryDomain().getRoot())
);
return "org/librecms/ui/cms/pages-details.xhtml";
} }
//ToDo: Update Pages instance
//ToDo: Delete Pages instance
//ToDo: Show details for Pages instance //ToDo: Show details for Pages instance
//ToDo: Show details for page @POST
//ToDo: Create Page for category @Path("/{pagesInstance}/@edit")
//ToDo: Edit Page for category @AuthorizationRequired
//ToDo: Remove page from category @RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
//ToDo: Add page property @Transactional(Transactional.TxType.REQUIRED)
//ToDo: Edit page property public String updatePagesInstance(
@PathParam("pagesInstance") final String pagesInstance,
@FormParam("primaryUrl") final String primaryUrlParam
) {
final Optional<Pages> pagesResult = findPages(pagesInstance);
if (pagesResult.isEmpty()) {
return showPagesNotFound(pagesInstance);
}
if (primaryUrlParam == null || primaryUrlParam.isBlank()) {
models.put("primaryUrlNullOrEmpty", true);
return PAGES_LIST_TEMPLATE;
}
final Pages pages = pagesResult.get();
pages.setPrimaryUrl(primaryUrlParam);
pagesRepo.save(pages);
return String.format(
"/pages/%s", pagesInstance
);
}
@POST
@Path("/{pagesInstance}/@delete")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String deletePagesInstance(
@PathParam("pagesInstance") final String pagesInstance
) {
final Optional<Pages> pagesResult = findPages(pagesInstance);
if (pagesResult.isEmpty()) {
return showPagesNotFound(pagesInstance);
}
final Pages pages = pagesResult.get();
pagesRepo.delete(pages);
return String.format(
"/pages/%s", pagesInstance
);
}
@POST
@Path("/{pagesInstance}/{category}/@add")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String createPage(
@PathParam("pagesInstance") final String pagesInstance,
@PathParam("category") final String categoryParam
) {
final Optional<Pages> pagesResult = findPages(pagesInstance);
if (pagesResult.isEmpty()) {
return showPagesNotFound(pagesInstance);
}
final Pages pages = pagesResult.get();
final Optional<Category> categoryResult = categoryRepo.findByPath(
pages.getCategoryDomain(),
categoryParam
);
if (categoryResult.isEmpty()) {
models.put("categoryNotFound", true);
models.put(
"categoryDomain", pages.getCategoryDomain().getDomainKey()
);
models.put("category", categoryParam);
return showPagesDetails(pagesInstance);
}
final Category category = categoryResult.get();
pageManager.createPageForCategory(category);
return String.format(
"redirect:/pages/%s/%s",
pagesInstance,
categoryParam
);
}
@GET
@Path("/{pagesInstance}/{category}/@details")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String showPageDetails(
@PathParam("pagesInstance") final String pagesInstance,
@PathParam("category") final String categoryParam
) {
final Optional<Pages> pagesResult = findPages(pagesInstance);
if (pagesResult.isEmpty()) {
return showPagesNotFound(pagesInstance);
}
final Pages pages = pagesResult.get();
final Optional<Category> categoryResult = categoryRepo.findByPath(
pages.getCategoryDomain(),
categoryParam
);
if (categoryResult.isEmpty()) {
models.put("categoryNotFound", true);
models.put(
"categoryDomain", pages.getCategoryDomain().getDomainKey()
);
models.put("category", categoryParam);
return showPagesDetails(pagesInstance);
}
final Category category = categoryResult.get();
final Page page = pageManager.findPageForCategory(category);
pageDetailsModel.setCategory(category.getName());
pageDetailsModel.setCategoryDomain(
pages.getCategoryDomain().getDomainKey()
);
pageDetailsModel.setPageProperties(page.getProperties());
pageDetailsModel.setSite(pages.getSite().getDomainOfSite());
return "org/librecms/ui/cms/pages-detail.xhtml";
}
@POST
@Path("/{pagesInstance}/{category}/@remove")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String removePage(
@PathParam("pagesInstance") final String pagesInstance,
@PathParam("category") final String categoryParam
) {
final Optional<Pages> pagesResult = findPages(pagesInstance);
if (pagesResult.isEmpty()) {
return showPagesNotFound(pagesInstance);
}
final Pages pages = pagesResult.get();
final Optional<Category> categoryResult = categoryRepo.findByPath(
pages.getCategoryDomain(),
categoryParam
);
if (categoryResult.isEmpty()) {
models.put("categoryNotFound", true);
models.put(
"categoryDomain", pages.getCategoryDomain().getDomainKey()
);
models.put("category", categoryParam);
return showPagesDetails(pagesInstance);
}
final Category category = categoryResult.get();
final Page page = pageManager.findPageForCategory(category);
pageRepo.delete(page);
return String.format("redirect:/pages/%s", pagesInstance);
}
@POST
@Path("/{pagesInstance}/{category}/@add-property")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String addPageProperty(
@PathParam("pagesInstance") final String pagesInstance,
@PathParam("category") final String categoryParam,
@FormParam("propertyKey") final String propertyKey,
@FormParam("propertyValue") final String propertyValue
) {
final Optional<Pages> pagesResult = findPages(pagesInstance);
if (pagesResult.isEmpty()) {
return showPagesNotFound(pagesInstance);
}
final Pages pages = pagesResult.get();
final Optional<Category> categoryResult = categoryRepo.findByPath(
pages.getCategoryDomain(),
categoryParam
);
if (categoryResult.isEmpty()) {
models.put("categoryNotFound", true);
models.put(
"categoryDomain", pages.getCategoryDomain().getDomainKey()
);
models.put("category", categoryParam);
return showPagesDetails(pagesInstance);
}
final Category category = categoryResult.get();
if (propertyKey == null || propertyKey.isBlank()) {
models.put("propertyKeyEmpty", true);
return showPageDetails(pagesInstance, categoryParam);
}
if (propertyValue == null || propertyValue.isBlank()) {
models.put("propertyValueEmpty", true);
return showPageDetails(pagesInstance, categoryParam);
}
final Page page = pageManager.findPageForCategory(category);
page.addProperty(propertyKey, propertyValue);
pageRepo.save(page);
return String.format(
"redirect:/pages/%s/%s",
pagesInstance,
categoryParam
);
}
@POST
@Path("/{pagesInstance}/{category}/{propertyKey}/@edit")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String updatePageProperty(
@PathParam("pagesInstance") final String pagesInstance,
@PathParam("category") final String categoryParam,
@PathParam("propertyKey") final String propertyKey,
@FormParam("propertyValue") final String propertyValue
) {
return addPageProperty(
pagesInstance,
categoryParam,
propertyKey,
propertyValue
);
}
@POST
@Path("/{pagesInstance}/{category}/{propertyKey}/@remove")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String removePageProperty(
@PathParam("pagesInstance") final String pagesInstance,
@PathParam("category") final String categoryParam,
@PathParam("propertyKey") final String propertyKey
) {
final Optional<Pages> pagesResult = findPages(pagesInstance);
if (pagesResult.isEmpty()) {
return showPagesNotFound(pagesInstance);
}
final Pages pages = pagesResult.get();
final Optional<Category> categoryResult = categoryRepo.findByPath(
pages.getCategoryDomain(),
categoryParam
);
if (categoryResult.isEmpty()) {
models.put("categoryNotFound", true);
models.put(
"categoryDomain", pages.getCategoryDomain().getDomainKey()
);
models.put("category", categoryParam);
return showPagesDetails(pagesInstance);
}
final Category category = categoryResult.get();
if (propertyKey == null || propertyKey.isBlank()) {
models.put("propertyKeyEmpty", true);
return showPageDetails(pagesInstance, categoryParam);
}
final Page page = pageManager.findPageForCategory(category);
page.removeProperty(propertyKey);
pageRepo.save(page);
return String.format(
"redirect:/pages/%s/%s",
pagesInstance,
categoryParam
);
}
//ToDo: Remove page property //ToDo: Remove page property
private Optional<Pages> findPages(final String identifierParam) {
final Identifier identifier = identifierParser.parseIdentifier(
identifierParam
);
switch (identifier.getType()) {
case UUID:
return pagesRepo.findPagesForSite(
identifier.getIdentifier()
);
case ID:
return pagesRepo.findById(
Long.parseLong(identifier.getIdentifier())
);
default:
return pagesRepo.findPagesForSite(
identifier.getIdentifier()
);
}
}
private String showPagesNotFound(final String pagesInstance) {
models.put("pagesInstanceNotFound", true);
models.put("pagesInstance", pagesInstance);
return PAGES_LIST_TEMPLATE;
}
private PageTreeNodeModel buildPageTreeNodeModel(
final Category category
) {
final Optional<Page> pageResult = pageRepo.findPageForCategory(
category
);
final PageTreeNodeModel node = new PageTreeNodeModel();
node.setCategoryName(category.getName());
node.setPageAssigned(pageResult.isPresent());
node.setProperties(
pageResult
.map(Page::getProperties)
.orElse(new HashMap<>())
);
node.setChildren(
category
.getSubCategories()
.stream()
.map(this::buildPageTreeNodeModel)
.collect(Collectors.toList())
);
return node;
}
} }

View File

@ -0,0 +1,76 @@
/*
* Copyright (C) 2021 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.librecms.ui;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Named;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
@Named("CmsPagesDetailsModel")
public class PagesDetailsModel {
private String site;
private String primaryUrl;
private String categoryDomain;
private PageTreeNodeModel pageTreeRoot;
public String getSite() {
return site;
}
protected void setSite(final String site) {
this.site = site;
}
public String getPrimaryUrl() {
return primaryUrl;
}
protected void setPrimaryUrl(final String primaryUrl) {
this.primaryUrl = primaryUrl;
}
public String getCategoryDomain() {
return categoryDomain;
}
protected void setCategoryDomain(final String categoryDomain) {
this.categoryDomain = categoryDomain;
}
public PageTreeNodeModel getPageTreeRoot() {
return pageTreeRoot;
}
protected void setPageTreeRoot(final PageTreeNodeModel pageTreeRoot) {
this.pageTreeRoot = pageTreeRoot;
}
}