CCM NG: Content Center Category Tab

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@5161 8810af33-2d31-482b-a856-94f89814c4df

Former-commit-id: b76d079348
pull/2/head
jensp 2017-12-07 16:49:36 +00:00
parent e4bab905e9
commit 7c23d97bc2
4 changed files with 221 additions and 46 deletions

View File

@ -34,6 +34,7 @@ import com.arsdigita.bebop.event.ChangeListener;
import com.arsdigita.bebop.event.FormSectionEvent; import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.parameters.ParameterModel; import com.arsdigita.bebop.parameters.ParameterModel;
import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ui.BaseAdminPane; import com.arsdigita.cms.ui.BaseAdminPane;
import com.arsdigita.cms.ui.BaseDeleteForm; import com.arsdigita.cms.ui.BaseDeleteForm;
import com.arsdigita.cms.ui.BaseTree; import com.arsdigita.cms.ui.BaseTree;
@ -47,13 +48,13 @@ import org.apache.logging.log4j.Logger;
import org.libreccm.categorization.Categorization; import org.libreccm.categorization.Categorization;
import org.libreccm.categorization.Category; import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryRepository; import org.libreccm.categorization.CategoryRepository;
import org.libreccm.categorization.DomainOwnership;
import org.libreccm.cdi.utils.CdiUtil; import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.core.UnexpectedErrorException; import org.libreccm.core.UnexpectedErrorException;
import org.libreccm.security.PermissionChecker; import org.libreccm.security.PermissionChecker;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.privileges.AdminPrivileges; import org.librecms.contentsection.privileges.AdminPrivileges;
/** /**
* A split pane for the Category Administration UI. * A split pane for the Category Administration UI.
* *
@ -78,8 +79,8 @@ public final class CategoryAdminPane extends BaseAdminPane {
m_contextModel = new UseContextSelectionModel(new StringParameter( m_contextModel = new UseContextSelectionModel(new StringParameter(
CONTEXT_SELECTED)); CONTEXT_SELECTED));
/* Left column */ // Left column
/* Use context section */ // Use context section
List list = new List(new CategoryUseContextModelBuilder()); List list = new List(new CategoryUseContextModelBuilder());
list.setSelectionModel(m_contextModel); list.setSelectionModel(m_contextModel);
list.addChangeListener(new ContextSelectionListener()); list.addChangeListener(new ContextSelectionListener());
@ -303,9 +304,12 @@ public final class CategoryAdminPane extends BaseAdminPane {
} }
@Override @Override
public Object getSelectedKey(PageState state) { public Object getSelectedKey(final PageState state) {
Object val = super.getSelectedKey(state); Object val = super.getSelectedKey(state);
if (val == null || ((String) val).length() == 0) { if (val == null
|| ((CharSequence) val).length() == 0) {
val = DEFAULT_USE_CONTEXT; val = DEFAULT_USE_CONTEXT;
state.setValue(getStateParameter(), val); state.setValue(getStateParameter(), val);
fireStateChanged(state); fireStateChanged(state);
@ -315,16 +319,24 @@ public final class CategoryAdminPane extends BaseAdminPane {
} }
public String getUseContext(PageState state) { public String getUseContext(final PageState state) {
String selected = (String) m_contextModel.getSelectedKey(state); String selected = (String) m_contextModel.getSelectedKey(state);
return (DEFAULT_USE_CONTEXT).equals(selected) ? (String) null : selected; if (DEFAULT_USE_CONTEXT.equals(selected)) {
return null;
} else {
return selected;
}
// return (DEFAULT_USE_CONTEXT).equals(selected) ? (String) null : selected;
} }
public class ContextSelectionListener implements ChangeListener { private class ContextSelectionListener implements ChangeListener {
@Override
public final void stateChanged(final ChangeEvent event) { public final void stateChanged(final ChangeEvent event) {
LOGGER.debug("Selection state changed; I may change " LOGGER.debug("Selection state changed; I may change "
+ "the body's visible pane"); + "the body's visible pane");
final PageState state = event.getPageState(); final PageState state = event.getPageState();
@ -336,13 +348,27 @@ public final class CategoryAdminPane extends BaseAdminPane {
.getSelectedKey(state); .getSelectedKey(state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final CategoryRepository categoryRepo = cdiUtil final CategoryRepository categoryRepo = cdiUtil
.findBean(CategoryRepository.class); .findBean(CategoryRepository.class);
final Category root = categoryRepo final Category root;
.findById(Long.parseLong(rootCategoryId)) if (DEFAULT_USE_CONTEXT.equals(rootCategoryId)) {
.orElseThrow(() -> new UnexpectedErrorException(String final ContentSection section = CMS
.format("No Category with ID %s in the database.", .getContext()
rootCategoryId))); .getContentSection();
final CategoryAdminController controller = CdiUtil
.createCdiUtil()
.findBean(CategoryAdminController.class);
final java.util.List<DomainOwnership> ownerships
= controller
.retrieveDomains(section);
root = ownerships.get(0).getDomain().getRoot();
} else {
root = categoryRepo
.findById(Long.parseLong(rootCategoryId))
.orElseThrow(() -> new UnexpectedErrorException(String
.format("No Category with ID %s in the database.",
rootCategoryId)));
}
if (root != null) { if (root != null) {
m_model.setSelectedKey(state, root.getUniqueId()); m_model.setSelectedKey(state, root.getUniqueId());
m_categoryTree.reset(state); m_categoryTree.reset(state);
@ -351,7 +377,7 @@ public final class CategoryAdminPane extends BaseAdminPane {
} }
if (m_model.isSelected(state)) { if (m_model.isSelected(state)) {
LOGGER.debug("The selection model is selected; displaying " LOGGER.debug("The selection model is selected; displaying "
+ "the item pane"); + "the item pane");
getBody().push(state, getItemPane()); getBody().push(state, getItemPane());
} }

View File

@ -23,9 +23,16 @@ import com.arsdigita.bebop.SingleSelectionModel;
import com.arsdigita.bebop.Tree; import com.arsdigita.bebop.Tree;
import com.arsdigita.bebop.tree.TreeModel; import com.arsdigita.bebop.tree.TreeModel;
import com.arsdigita.bebop.tree.TreeModelBuilder; import com.arsdigita.bebop.tree.TreeModelBuilder;
import com.arsdigita.cms.CMS;
import com.arsdigita.util.LockableImpl; import com.arsdigita.util.LockableImpl;
import org.libreccm.categorization.Category; import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryRepository;
import org.libreccm.categorization.CategoryTreeModelLite; import org.libreccm.categorization.CategoryTreeModelLite;
import org.libreccm.categorization.DomainOwnership;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.core.UnexpectedErrorException;
import org.librecms.contentsection.ContentSection;
/** /**
* Lists category tree. * Lists category tree.
@ -34,7 +41,7 @@ import org.libreccm.categorization.CategoryTreeModelLite;
* @author <a href="mailto:yannick.buelter@yabue.de">Yannick Bülter</a> * @author <a href="mailto:yannick.buelter@yabue.de">Yannick Bülter</a>
*/ */
class CategoryTreeModelBuilder extends LockableImpl class CategoryTreeModelBuilder extends LockableImpl
implements TreeModelBuilder { implements TreeModelBuilder {
private static String DEFAULT_USE_CONTEXT = "<default>"; private static String DEFAULT_USE_CONTEXT = "<default>";
@ -49,22 +56,34 @@ class CategoryTreeModelBuilder extends LockableImpl
m_contextModel = contextModel; m_contextModel = contextModel;
} }
@Override
public final TreeModel makeModel(final Tree tree, final PageState state) { public final TreeModel makeModel(final Tree tree, final PageState state) {
final Category category = (Category) m_contextModel.getSelectedKey(state);
final CategoryTreeModelLite model = new CategoryTreeModelLite(category); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final Category root;
if (DEFAULT_USE_CONTEXT.equals(m_contextModel.getSelectedKey(state))) {
final ContentSection section = CMS
.getContext()
.getContentSection();
return model; final CategoryAdminController controller = cdiUtil
} .findBean(CategoryAdminController.class);
final java.util.List<DomainOwnership> ownerships
private String getUseContext(PageState state) { = controller
String context = null; .retrieveDomains(section);
if (m_contextModel != null) { root = ownerships.get(0).getDomain().getRoot();
context = (String) m_contextModel.getSelectedKey(state); } else {
if ((DEFAULT_USE_CONTEXT).equals(context)) { final CategoryRepository categoryRepo = cdiUtil
context = null; .findBean(CategoryRepository.class);
} root = categoryRepo
.findById(Long.parseLong((String) m_contextModel
.getSelectedKey(state)))
.orElseThrow(() -> new UnexpectedErrorException(String
.format("No Category with ID %s in the database.",
m_contextModel.getSelectedKey(state))));
} }
return context;
return new CategoryTreeModelLite(root);
} }
} }

View File

@ -18,49 +18,52 @@
*/ */
package org.libreccm.categorization; package org.libreccm.categorization;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.tree.TreeModel; import com.arsdigita.bebop.tree.TreeModel;
import com.arsdigita.bebop.tree.TreeNode; import com.arsdigita.bebop.tree.TreeNode;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
import org.libreccm.cdi.utils.CdiUtil;
import org.libreccm.l10n.GlobalizationHelper;
import java.util.Iterator; import java.util.Iterator;
import java.util.Objects;
import java.util.stream.Collectors;
/** /**
* Implements the {@link com.arsdigita.bebop.tree.TreeModel} interface for * Implements the {@link com.arsdigita.bebop.tree.TreeModel} interface for
* categories. * categories.
* *
* @author Daniel Berrange * @author Daniel Berrange
* @version $Revision: #17 $ $DateTime: 2004/08/16 18:10:38 $ * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter </a>
*/ */
public class CategoryTreeModelLite implements TreeModel { public class CategoryTreeModelLite implements TreeModel {
private static final Logger LOGGER = LogManager.getLogger( private static final Logger LOGGER = LogManager.getLogger(
CategoryTreeModelLite.class); CategoryTreeModelLite.class);
// String m_order = null; // String m_order = null;
final Category category; private final Category root;
/** /**
* Initializes with the passed in the root Category. * Initialises with the passed in the root Category.
* *
* @param root the root category for this TreeModel * @param root the root category for this TreeModel
*/ */
// public CategoryTreeModelLite(Category root) { // public CategoryTreeModelLite(Category root) {
// this(root, null); // this(root, null);
// } // }
/** /**
* Initializes with the passed in the root Category. * Initializes with the passed in the root Category.
* *
* @param root the root category for this TreeModel * @param root the root category for this TreeModel
*/ */
public CategoryTreeModelLite(Category root) { public CategoryTreeModelLite(final Category root) {
// super(root.getUniqueId(), // super(root.getUniqueId(),
// "com.arsdigita.categorization.getRootCategory", // "com.arsdigita.categorization.getRootCategory",
// "com.arsdigita.categorization.getSubCategories"); // "com.arsdigita.categorization.getSubCategories");
// m_order = order; // m_order = order;
category = root; this.root = root;
} }
// @Override // @Override
@ -68,20 +71,82 @@ public class CategoryTreeModelLite implements TreeModel {
// String getSubCategories) { // String getSubCategories) {
// return new CategoryTreeIterator(node, getSubCategories, m_order); // return new CategoryTreeIterator(node, getSubCategories, m_order);
// } // }
@Override @Override
public TreeNode getRoot(PageState data) { public TreeNode getRoot(final PageState data) {
return null; return new CategoryTreeNode(root);
} }
@Override @Override
public boolean hasChildren(TreeNode n, PageState data) { public boolean hasChildren(final TreeNode node,
return false; final PageState state) {
Objects.requireNonNull(node);
if (node.getKey() == null
|| !(node.getKey() instanceof Long)) {
throw new IllegalArgumentException(
"The key of the provided TreeNode is null or not a Long.");
}
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final CategoryTreeModelLiteController controller = cdiUtil
.findBean(CategoryTreeModelLiteController.class);
return controller.hasSubCategories((long) node.getKey());
} }
@Override @Override
public Iterator<TreeNode> getChildren(TreeNode n, PageState data) { public Iterator<TreeNode> getChildren(final TreeNode node,
return null; final PageState state) {
Objects.requireNonNull(node);
if (node.getKey() == null
|| !(node.getKey() instanceof Long)) {
throw new IllegalArgumentException(
"The key of the provided TreeNode is null or not a Long.");
}
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final CategoryTreeModelLiteController controller = cdiUtil
.findBean(CategoryTreeModelLiteController.class);
return controller
.findSubCategories((long) node.getKey())
.stream()
.map(this::buildTreeNode)
.iterator();
}
private TreeNode buildTreeNode(final Category category) {
return new CategoryTreeNode(category);
}
private class CategoryTreeNode implements TreeNode {
private final Category category;
public CategoryTreeNode(final Category category) {
this.category = category;
}
@Override
public Object getKey() {
return category.getObjectId();
}
@Override
public Object getElement() {
if (category.getTitle().getValues().isEmpty()) {
return category.getName();
} else {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final GlobalizationHelper globalizationHelper = cdiUtil
.findBean(GlobalizationHelper.class);
return globalizationHelper
.getValueFromLocalizedString(category.getTitle());
}
}
} }
// private static class CategoryTreeIterator extends DataQueryTreeIterator { // private static class CategoryTreeIterator extends DataQueryTreeIterator {

View File

@ -0,0 +1,65 @@
/*
* Copyright (C) 2017 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.libreccm.categorization;
import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.transaction.Transactional;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
class CategoryTreeModelLiteController {
@Inject
private CategoryManager categoryManager;
@Inject
private CategoryRepository categoryRepo;
@Transactional(Transactional.TxType.REQUIRED)
protected boolean hasSubCategories(final long categoryId) {
final Category category = categoryRepo
.findById(categoryId)
.orElseThrow(() -> new IllegalArgumentException(String
.format("No Category with ID %d in the database.",
categoryId)));
return categoryManager.hasSubCategories(category);
}
@Transactional
protected List<Category> findSubCategories(final long categoryId) {
final Category category = categoryRepo
.findById(categoryId)
.orElseThrow(() -> new IllegalArgumentException(String
.format("No Category with ID %d in the database.",
categoryId)));
return new ArrayList<>(category.getSubCategories());
}
}