From 1e3cb64455562829ba9a44a32fa3283108d1d16f Mon Sep 17 00:00:00 2001 From: jensp Date: Fri, 13 Mar 2015 12:29:33 +0000 Subject: [PATCH] - The CategoryWidget/TermWidget now highlights the ancestors of selected categories to make easier to find selected categories - Some formatting of XSL code in Foundry git-svn-id: https://svn.libreccm.org/ccm/trunk@3281 8810af33-2d31-482b-a856-94f89814c4df --- ccm-bundle/bundles/slimline/cfg/project.xml | 2 +- .../cms/ui/authoring/CategoryWidget.java | 79 ++++--- .../cms/ui/authoring/ItemCategoryForm.java | 22 +- .../ui/ACSObjectCategoryForm.java | 60 +++-- .../search/ui/BaseQueryComponent.java | 53 +++-- .../arsdigita/search/ui/QueryComponent.java | 4 +- .../com/arsdigita/search/ui/ResultsPane.java | 1 - .../web/themes/foundry-base/texts/cms.xml | 2 +- .../foundry/foundry/lib/bebop/debug.xsl | 2 +- .../foundry/foundry/lib/bebop/editors.xsl | 15 +- .../themes/foundry/foundry/lib/bebop/form.xsl | 1 + .../foundry/foundry/lib/bebop/image.xsl | 15 +- .../foundry/foundry/lib/bebop/label.xsl | 2 +- .../themes/foundry/foundry/lib/bebop/list.xsl | 15 +- .../themes/foundry/foundry/lib/bebop/page.xsl | 2 +- .../foundry/lib/bebop/property-list.xsl | 1 - .../foundry/foundry/lib/bebop/tabbed-pane.xsl | 14 +- .../foundry/foundry/lib/bebop/table.xsl | 2 +- .../foundry/lib/template-tags/admin/cms.xsl | 30 ++- .../foundry/foundry/scripts/category-step.js | 40 +++- .../themes/foundry/foundry/styles/admin.css | 8 + .../web/themes/foundry/foundry/texts/cms.xml | 2 +- .../arsdigita/london/terms/ui/TermWidget.java | 207 ++++++++++++------ 23 files changed, 360 insertions(+), 219 deletions(-) diff --git a/ccm-bundle/bundles/slimline/cfg/project.xml b/ccm-bundle/bundles/slimline/cfg/project.xml index 138798446..ae5d6ddfc 100644 --- a/ccm-bundle/bundles/slimline/cfg/project.xml +++ b/ccm-bundle/bundles/slimline/cfg/project.xml @@ -15,7 +15,7 @@ name="LibreCMS-SL" prettyName="LibreCMS (Slimline Bundle)" version="2.3.0" - release="trunk-r2915" + release="trunk-r3276" webxml="libre-web.xml" webapp="ROOT" xsi:schemaLocation="http://ccm.redhat.com/ccm-project file:tools-ng/common/xsd/project.xsd"> diff --git a/ccm-cms/src/com/arsdigita/cms/ui/authoring/CategoryWidget.java b/ccm-cms/src/com/arsdigita/cms/ui/authoring/CategoryWidget.java index 79c595795..9e6fad597 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/authoring/CategoryWidget.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/authoring/CategoryWidget.java @@ -42,7 +42,7 @@ import java.util.Iterator; import java.math.BigDecimal; public class CategoryWidget extends Widget { - + private BigDecimalParameter m_root; private StringParameter m_mode; @@ -50,7 +50,7 @@ public class CategoryWidget extends Widget { BigDecimalParameter root, StringParameter mode) { super(new ArrayParameter(new BigDecimalParameter(name))); - + m_root = root; m_mode = mode; } @@ -59,54 +59,55 @@ public class CategoryWidget extends Widget { protected String getType() { return "category"; } + @Override public boolean isCompound() { return false; } - + @Override - protected void generateWidget(PageState state, + protected void generateWidget(PageState state, Element parent) { Element widget = parent.newChildElement("cms:categoryWidget", CMS.CMS_XML_NS); exportAttributes(widget); - widget.addAttribute("mode", (String)state.getValue(m_mode)); + widget.addAttribute("mode", (String) state.getValue(m_mode)); widget.addAttribute("name", getName()); - Set ids = new HashSet(); + final Set selectedCategories = new HashSet(); - BigDecimal[] values = (BigDecimal[])getValue(state); + final BigDecimal[] values = (BigDecimal[]) getValue(state); if (values != null) { - ids.addAll(Arrays.asList(values)); + selectedCategories.addAll(Arrays.asList(values)); } - - Category root = (Category)DomainObjectFactory.newInstance( + + final Category root = (Category) DomainObjectFactory.newInstance( new OID(Category.BASE_DATA_OBJECT_TYPE, - (BigDecimal)state.getValue(m_root)) + (BigDecimal) state.getValue(m_root)) ); - CategoryCollection cats = root.getDescendants(); - cats.addEqualsFilter("parents.link.relationType", "child"); - cats.addPath("parents.link.sortKey"); - cats.addPath("parents.id"); - - Map children = new HashMap(); - while (cats.next()) { - Category cat = cats.getCategory(); - BigDecimal parentID = (BigDecimal)cats.get("parents.id"); - - List childList = (List)children.get(parentID); + CategoryCollection categories = root.getDescendants(); + categories.addEqualsFilter("parents.link.relationType", "child"); + categories.addPath("parents.link.sortKey"); + categories.addPath("parents.id"); + + final Map children = new HashMap(); + while (categories.next()) { + final Category cat = categories.getCategory(); + final BigDecimal parentID = (BigDecimal) categories.get("parents.id"); + + List childList = (List) children.get(parentID); if (childList == null) { childList = new ArrayList(); children.put(parentID, childList); } - - childList.add(new CategorySortKeyPair - (cat,(BigDecimal)cats.get("parents.link.sortKey"))); + + childList.add( + new CategorySortKeyPair(cat, (BigDecimal) categories.get("parents.link.sortKey"))); } - - generateCategory(widget, null, root, null, ids, children); + + generateCategory(widget, null, root, null, selectedCategories, children); } public void generateCategory(Element parent, @@ -117,7 +118,7 @@ public class CategoryWidget extends Widget { Map children) { Element el = new Element("cms:category", CMS.CMS_XML_NS); - + el.addAttribute("id", XML.format(cat.getID())); el.addAttribute("name", cat.getName()); el.addAttribute("description", cat.getDescription()); @@ -131,30 +132,32 @@ public class CategoryWidget extends Widget { // be used to transform xml fragments returned by ajax in the Aplaws // extension el.addAttribute("order", ContentSection.getConfig().getCategoryTreeOrder()); - + String fullname = path == null ? "/" : path + " > " + cat.getName(); el.addAttribute("fullname", fullname); - StringBuilder nodeID = new StringBuilder(parent.getAttribute("node-id")); - if (nodeID.length() > 0) { + StringBuilder nodeID = new StringBuilder(parent.getAttribute("node-id")); + if (nodeID.length() > 0) { nodeID.append("-"); } - nodeID.append(cat.getID()); - el.addAttribute("node-id", nodeID.toString()); + nodeID.append(cat.getID()); + el.addAttribute("node-id", nodeID.toString()); parent.addContent(el); - List c = (List)children.get(cat.getID()); + List c = (List) children.get(cat.getID()); if (c != null) { Iterator i = c.iterator(); while (i.hasNext()) { CategorySortKeyPair pair = (CategorySortKeyPair) i.next(); Category child = pair.getCategory(); BigDecimal childSortKey = pair.getSortKey(); - generateCategory(el, fullname, child, + generateCategory(el, fullname, child, childSortKey, selected, children); } - } + } } + private class CategorySortKeyPair { + private Category m_category; private BigDecimal m_sortKey; @@ -162,11 +165,15 @@ public class CategoryWidget extends Widget { m_category = category; m_sortKey = sortKey; } + public Category getCategory() { return m_category; } + public BigDecimal getSortKey() { return m_sortKey; } + } + } diff --git a/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryForm.java b/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryForm.java index d1b0d73ee..9d232ed71 100755 --- a/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryForm.java +++ b/ccm-cms/src/com/arsdigita/cms/ui/authoring/ItemCategoryForm.java @@ -29,34 +29,32 @@ import com.arsdigita.cms.CMS; import com.arsdigita.cms.ContentItem; import com.arsdigita.kernel.ACSObject; -/** +/** * (No description available yet). - * + * * Usage of this class is configured in parameter c.ad.cms.category_authoring_add_form */ public class ItemCategoryForm extends ACSObjectCategoryForm { private static Logger s_log = Logger.getLogger(ItemCategoryForm.class); - public ItemCategoryForm(BigDecimalParameter root, StringParameter mode, Widget widget) { - super(root, mode, widget); - s_log.debug("creating new ItemTerm Form with widget " + widget); - + super(root, mode, widget); + s_log.debug("creating new ItemTerm Form with widget " + widget); + } public ItemCategoryForm(BigDecimalParameter root, StringParameter mode) { - this(root, mode, new CategoryWidget("category", root, mode)); + this(root, mode, new CategoryWidget("category", root, mode)); } - - + /* * @see com.arsdigita.categorization.ui.ACSObjectCategoryForm#getObject() */ protected ACSObject getObject(PageState state) { - ContentItem item = CMS.getContext().getContentItem(); - return item.getParent(); - + ContentItem item = CMS.getContext().getContentItem(); + return item.getParent(); + } } diff --git a/ccm-core/src/com/arsdigita/categorization/ui/ACSObjectCategoryForm.java b/ccm-core/src/com/arsdigita/categorization/ui/ACSObjectCategoryForm.java index ede2495f6..7cbba770f 100755 --- a/ccm-core/src/com/arsdigita/categorization/ui/ACSObjectCategoryForm.java +++ b/ccm-core/src/com/arsdigita/categorization/ui/ACSObjectCategoryForm.java @@ -43,18 +43,18 @@ import com.arsdigita.domain.DomainObjectFactory; import com.arsdigita.kernel.ACSObject; import com.arsdigita.persistence.OID; import java.util.HashSet; +import java.util.Set; /** - * Abstract form for assigning categories to acs_objects. The assigned - * categories are those specified by the category widget, which is - * retrieved by the concrete subclass' implementation of getCategoryWidget. + * Abstract form for assigning categories to acs_objects. The assigned categories are those + * specified by the category widget, which is retrieved by the concrete subclass' implementation of + * getCategoryWidget. * - * The category widget may be an implementation of CategoryWidget, which - * generates a javascript tree of categories. Implementations need only - * specify an XML prefix and namespace. + * The category widget may be an implementation of CategoryWidget, which generates a javascript tree + * of categories. Implementations need only specify an XML prefix and namespace. * - * The object that is to be assigned to the categories is specified - * by the concrete subclass' implentation of getObject + * The object that is to be assigned to the categories is specified by the concrete subclass' + * implentation of getObject * * @author chris.gilbert@westsussex.gov.uk * @@ -74,7 +74,6 @@ public abstract class ACSObjectCategoryForm extends Form { Widget categoryWidget) { super("category", new BoxPanel(BoxPanel.VERTICAL)); - m_category = categoryWidget; m_category.addValidationListener(new NotNullValidationListener()); m_buttons = new SaveCancelSection(); @@ -85,20 +84,27 @@ public abstract class ACSObjectCategoryForm extends Form { addInitListener(new FormInitListener() { @Override - public void init(FormSectionEvent ev) - throws FormProcessException { + public void init(FormSectionEvent ev) throws FormProcessException { - PageState state = ev.getPageState(); - ACSObject object = getObject(state); + final PageState state = ev.getPageState(); + final ACSObject object = getObject(state); - List ids = new ArrayList(); - CategoryCollection cats = new CategorizedObject(object).getParents(); - while (cats.next()) { - ids.add(cats.getCategory().getID()); + final List selectedCats = new ArrayList(); + final Set ancestorCats = new HashSet(); + final CategoryCollection categories = new CategorizedObject(object).getParents(); + while (categories.next()) { + final Category category = categories.getCategory(); + selectedCats.add(category.getID()); + addAncestorCats(ancestorCats, category); } + + final BigDecimal[][] paramArray = new BigDecimal[2][]; + paramArray[0] = selectedCats.toArray(new BigDecimal[selectedCats.size()]); + paramArray[1] = ancestorCats.toArray(new BigDecimal[ancestorCats.size()]); - m_category.setValue(state, - ids.toArray(new BigDecimal[ids.size()])); +// m_category.setValue(state, +// selectedCats.toArray(new BigDecimal[selectedCats.size()])); + m_category.setValue(state, paramArray); } }); @@ -121,7 +127,7 @@ public abstract class ACSObjectCategoryForm extends Form { BigDecimal[] ids = (BigDecimal[]) m_category.getValue(state); for (BigDecimal id : ids) { Category cat = (Category) DomainObjectFactory - .newInstance(new OID(Category.BASE_DATA_OBJECT_TYPE, id)); + .newInstance(new OID(Category.BASE_DATA_OBJECT_TYPE, id)); if (!curSelectedCat.contains(id)) { cat.addChild(object); } else { @@ -144,9 +150,21 @@ public abstract class ACSObjectCategoryForm extends Form { fireCompletionEvent(state); throw new FormProcessException("Submission cancelled", GlobalizationUtil.globalize( - "categorization.cancel.msg")); + "categorization.cancel.msg")); } } }); } + + private void addAncestorCats(final Set ancestorCats, final Category category) { + + final CategoryCollection ascendants = category.getDefaultAscendants(); + + while(ascendants.next()) { + final Category ascendant = ascendants.getCategory(); + ancestorCats.add(ascendant.getID()); + + } + + } } diff --git a/ccm-core/src/com/arsdigita/search/ui/BaseQueryComponent.java b/ccm-core/src/com/arsdigita/search/ui/BaseQueryComponent.java index 141b2e8c6..0a08b52b8 100755 --- a/ccm-core/src/com/arsdigita/search/ui/BaseQueryComponent.java +++ b/ccm-core/src/com/arsdigita/search/ui/BaseQueryComponent.java @@ -41,27 +41,25 @@ import java.util.Iterator; import org.apache.log4j.Logger; - /** - * This is a simple extension of the QueryComponent that - * provides management of the 'terms' parameter and uses - * FilterGenerators to populate a query specification + * This is a simple extension of the QueryComponent that provides management of the 'terms' + * parameter and uses FilterGenerators to populate a query specification *

* Typical use would be as follows: - *

+ * 
  * Form f = new Form("search");
  * BaseQueryComponent q = new BaseQueryComponent();
  * q.add(new ObjectTypeFilterComponent("com.arsdigita.kernel.User");
  * q.add(new PermissionGenerator(PrivilegeDescriptor.READ));
  * q.add(new Submit("Go"));
  * f.add(q);
- *
+ *
*/ public class BaseQueryComponent extends QueryComponent { - private static final Logger s_log = - Logger.getLogger(BaseQueryComponent.class); - + private static final Logger s_log + = Logger.getLogger(BaseQueryComponent.class); + private Set m_filters; private Form m_form; private StringParameter m_terms = new StringParameter("terms"); @@ -73,25 +71,25 @@ public class BaseQueryComponent extends QueryComponent { super("query"); m_filters = new HashSet(); } - + @Override public void register(Page p) { super.register(p); - + findFilters(m_filters); } - + @Override public void register(Form form, FormModel model) { if (s_log.isDebugEnabled()) { s_log.debug("Adding " + m_terms.getName() + " to form model"); } - s_log.debug("Adding " + m_terms.getName() + " to form model"); + s_log.debug("Adding " + m_terms.getName() + " to form model"); m_terms.setPassIn(true); model.addFormParam(m_terms); m_form = form; } - + /** * Gets the current search terms */ @@ -99,41 +97,39 @@ public class BaseQueryComponent extends QueryComponent { FormData fd = m_form.getFormData(state); if (fd != null) { ParameterData data = fd.getParameter(m_terms.getName()); - s_log.debug("Search terms were : " + (String)data.getValue()); - return (String)data.getValue(); + s_log.debug("Search terms were : " + (String) data.getValue()); + return (String) data.getValue(); } return null; } - protected FilterSpecification[] getFilters(PageState state) { FilterSpecification[] filters = new FilterSpecification[m_filters.size()]; - + Iterator i = m_filters.iterator(); int c = 0; while (i.hasNext()) { - FilterGenerator filter = (FilterGenerator)i.next(); + FilterGenerator filter = (FilterGenerator) i.next(); filters[c++] = filter.getFilter(state); } return filters; } - /** - * + * * @param state - * @param parent + * @param parent */ @Override public void generateXML(PageState state, Element parent) { Element content = generateParent(parent); - + Element terms = Search.newElement("terms"); terms.addAttribute("param", m_terms.getName()); - terms.addAttribute("value", - Globalization.decodeParameter(state.getRequest(), + terms.addAttribute("value", + Globalization.decodeParameter(state.getRequest(), m_terms.getName())); generateErrorXML(state, terms); content.addContent(terms); @@ -152,7 +148,7 @@ public class BaseQueryComponent extends QueryComponent { while (i.hasNext()) { Element error = Search.newElement("error"); error.setText( - (String) ((GlobalizedMessage) i.next()).localize(state.getRequest()) + (String) ((GlobalizedMessage) i.next()).localize(state.getRequest()) ); parent.addContent(error); } @@ -162,10 +158,11 @@ public class BaseQueryComponent extends QueryComponent { FilterTraversal trav = new FilterTraversal(filters); trav.preorder(this); } - + private class FilterTraversal extends Traversal { + private Set m_filters; - + public FilterTraversal(Set filters) { m_filters = filters; } diff --git a/ccm-core/src/com/arsdigita/search/ui/QueryComponent.java b/ccm-core/src/com/arsdigita/search/ui/QueryComponent.java index 022634c46..0e960a510 100755 --- a/ccm-core/src/com/arsdigita/search/ui/QueryComponent.java +++ b/ccm-core/src/com/arsdigita/search/ui/QueryComponent.java @@ -30,8 +30,8 @@ import com.arsdigita.util.Assert; /** * A base class for generating a query specification * from the state. Subclasses must implement two - * methods, one for getting the query tmers, - * the other for gettting a set of filter specs. + * methods, one for getting the query terms, + * the other for getting a set of filter specs. */ public abstract class QueryComponent extends SimpleContainer implements QueryGenerator { diff --git a/ccm-core/src/com/arsdigita/search/ui/ResultsPane.java b/ccm-core/src/com/arsdigita/search/ui/ResultsPane.java index 36fb14243..93c10d62f 100755 --- a/ccm-core/src/com/arsdigita/search/ui/ResultsPane.java +++ b/ccm-core/src/com/arsdigita/search/ui/ResultsPane.java @@ -21,7 +21,6 @@ package com.arsdigita.search.ui; import com.arsdigita.bebop.SimpleComponent; import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.parameters.IntegerParameter; -import com.arsdigita.bebop.util.GlobalizationUtil; import com.arsdigita.globalization.Globalization; import com.arsdigita.globalization.GlobalizedMessage; diff --git a/ccm-core/web/themes/foundry-base/texts/cms.xml b/ccm-core/web/themes/foundry-base/texts/cms.xml index 9ddf6d823..00d5c4025 100644 --- a/ccm-core/web/themes/foundry-base/texts/cms.xml +++ b/ccm-core/web/themes/foundry-base/texts/cms.xml @@ -7,7 +7,7 @@ - Kategorienzuweisen bearbeiten + Zugewiesene Kategorien Edit assigned categories diff --git a/ccm-core/web/themes/foundry/foundry/lib/bebop/debug.xsl b/ccm-core/web/themes/foundry/foundry/lib/bebop/debug.xsl index 94f2c40f2..d4ab21320 100644 --- a/ccm-core/web/themes/foundry/foundry/lib/bebop/debug.xsl +++ b/ccm-core/web/themes/foundry/foundry/lib/bebop/debug.xsl @@ -33,7 +33,7 @@ xmlns:cms="http://www.arsdigita.com/cms/1.0" xmlns:foundry="http://foundry.libreccm.org" xmlns:nav="http://ccm.redhat.com/navigation" - exclude-result-prefixes="xsl bebop cms nav" + exclude-result-prefixes="xsl bebop cms foundry nav" version="2.0"> diff --git a/ccm-core/web/themes/foundry/foundry/lib/bebop/editors.xsl b/ccm-core/web/themes/foundry/foundry/lib/bebop/editors.xsl index f9c917bf3..fbdf4ed5b 100644 --- a/ccm-core/web/themes/foundry/foundry/lib/bebop/editors.xsl +++ b/ccm-core/web/themes/foundry/foundry/lib/bebop/editors.xsl @@ -28,14 +28,13 @@ - + diff --git a/ccm-core/web/themes/foundry/foundry/lib/bebop/form.xsl b/ccm-core/web/themes/foundry/foundry/lib/bebop/form.xsl index 8516f3f06..b309e1c52 100755 --- a/ccm-core/web/themes/foundry/foundry/lib/bebop/form.xsl +++ b/ccm-core/web/themes/foundry/foundry/lib/bebop/form.xsl @@ -49,6 +49,7 @@ post + diff --git a/ccm-core/web/themes/foundry/foundry/lib/bebop/image.xsl b/ccm-core/web/themes/foundry/foundry/lib/bebop/image.xsl index 674df96da..378d4965b 100644 --- a/ccm-core/web/themes/foundry/foundry/lib/bebop/image.xsl +++ b/ccm-core/web/themes/foundry/foundry/lib/bebop/image.xsl @@ -26,14 +26,13 @@ Processing bebop images --> - + diff --git a/ccm-core/web/themes/foundry/foundry/lib/bebop/label.xsl b/ccm-core/web/themes/foundry/foundry/lib/bebop/label.xsl index 13f224f25..056c860d8 100644 --- a/ccm-core/web/themes/foundry/foundry/lib/bebop/label.xsl +++ b/ccm-core/web/themes/foundry/foundry/lib/bebop/label.xsl @@ -33,7 +33,7 @@ xmlns:foundry="http://foundry.libreccm.org" xmlns:nav="http://ccm.redhat.com/navigation" exclude-result-prefixes="xsl bebop cms foundry nav" - version="1.0"> + version="2.0"> diff --git a/ccm-core/web/themes/foundry/foundry/lib/bebop/list.xsl b/ccm-core/web/themes/foundry/foundry/lib/bebop/list.xsl index a3a0e3a80..28109dbff 100644 --- a/ccm-core/web/themes/foundry/foundry/lib/bebop/list.xsl +++ b/ccm-core/web/themes/foundry/foundry/lib/bebop/list.xsl @@ -26,14 +26,13 @@ Processing bebop lists --> - + diff --git a/ccm-core/web/themes/foundry/foundry/lib/bebop/page.xsl b/ccm-core/web/themes/foundry/foundry/lib/bebop/page.xsl index cc82a379b..3386f0d6c 100644 --- a/ccm-core/web/themes/foundry/foundry/lib/bebop/page.xsl +++ b/ccm-core/web/themes/foundry/foundry/lib/bebop/page.xsl @@ -33,7 +33,7 @@ xmlns:cms="http://www.arsdigita.com/cms/1.0" xmlns:foundry="http://foundry.libreccm.org" xmlns:nav="http://ccm.redhat.com/navigation" - exclude-result-prefixes="xsl bebop foundry cms" + exclude-result-prefixes="xsl bebop cms foundry nav" version="2.0"> diff --git a/ccm-core/web/themes/foundry/foundry/lib/bebop/property-list.xsl b/ccm-core/web/themes/foundry/foundry/lib/bebop/property-list.xsl index 9c37caccf..85be0c725 100644 --- a/ccm-core/web/themes/foundry/foundry/lib/bebop/property-list.xsl +++ b/ccm-core/web/themes/foundry/foundry/lib/bebop/property-list.xsl @@ -33,7 +33,6 @@ xmlns:cms="http://www.arsdigita.com/cms/1.0" xmlns:foundry="http://foundry.libreccm.org" xmlns:nav="http://ccm.redhat.com/navigation" - xmlns:mandalay="http://mandalay.quasiweb.de" exclude-result-prefixes="xsl bebop cms foundry nav" version="2.0"> diff --git a/ccm-core/web/themes/foundry/foundry/lib/bebop/tabbed-pane.xsl b/ccm-core/web/themes/foundry/foundry/lib/bebop/tabbed-pane.xsl index 5b330b825..523e210d0 100644 --- a/ccm-core/web/themes/foundry/foundry/lib/bebop/tabbed-pane.xsl +++ b/ccm-core/web/themes/foundry/foundry/lib/bebop/tabbed-pane.xsl @@ -29,13 +29,13 @@ - + diff --git a/ccm-core/web/themes/foundry/foundry/lib/bebop/table.xsl b/ccm-core/web/themes/foundry/foundry/lib/bebop/table.xsl index b5ad7fe2e..0e6c5a679 100644 --- a/ccm-core/web/themes/foundry/foundry/lib/bebop/table.xsl +++ b/ccm-core/web/themes/foundry/foundry/lib/bebop/table.xsl @@ -32,7 +32,7 @@ xmlns:foundry="http://foundry.libreccm.org" xmlns:nav="http://ccm.redhat.com/navigation" exclude-result-prefixes="xsl bebop cms foundry nav" - version="1.0"> + version="2.0"> - +
+ +
- - + @@ -299,14 +303,26 @@ - + + + + + - @@ -326,7 +342,7 @@
-
  • +
  • diff --git a/ccm-core/web/themes/foundry/foundry/scripts/category-step.js b/ccm-core/web/themes/foundry/foundry/scripts/category-step.js index 58636329f..169aced6e 100644 --- a/ccm-core/web/themes/foundry/foundry/scripts/category-step.js +++ b/ccm-core/web/themes/foundry/foundry/scripts/category-step.js @@ -25,6 +25,36 @@ These functions are part of the ajax-pages to assign categories. */ +function colorAncestors() { + var ancestorCategories = + document.category.selectedAncestorCategories.value.split(","); + + for (var i = 0; i < ancestorCategories.length; ++i) { + //alert("trying to find catSelf" + ancestorCategories[i]); + console.log("trying to find catSelf" + ancestorCategories[i]); + var elem = document.getElementById("catSelf" + ancestorCategories[i]); + if (elem !== null) { + //alert("found catSelf" + ancestorCategories[i]); + console.log("found catSelf" + ancestorCategories[i]); + var oldClasses = elem.className.split(" "); + var classes = ""; + for (var j = 0; j < oldClasses.length; ++j) { + if (oldClasses[j] !== "selectedAncestorCategory" + && oldClasses[j] !== "notSelectedAncestorCategory") { + classes = classes + " " + oldClasses[j]; + } + } + classes = classes + " selectedAncestorCategory"; + + //alert("setting class for catSelf" + ancestorCategories[i] + " to " + classes); + elem.className = classes; +// if (oldClassName.indexOf("selectedAncestorCategory") === -1) { +// elem.className = elem.className + "selectedAncestorCategory"; +// } + } + } +} + // DE Lade einen Kategorienzweig nach, wenn dieser aufgeklappt wird // EN Loading a branch of categories when it is expanded function catBranchToggle(id, selCats) { @@ -35,7 +65,9 @@ function catBranchToggle(id, selCats) { if (elBranch.innerHTML == "" || elBranch.innerHTML == "...") { elBranch.innerHTML = "..."; elBranch.style.display = "block"; - $(elBranch).load("load-cat.jsp", "nodeID=" + id + "&selectedCats=" + selCats); + $(elBranch).load("load-cat.jsp", "nodeID=" + id + "&selectedCats=" + selCats, function () { + colorAncestors() + }); } else { elBranch.style.display = "block"; } @@ -46,6 +78,9 @@ function catBranchToggle(id, selCats) { elToggleTreeImage.src = elToggleTreeImage.src.replace("Collapse", "Expand"); elToggleTreeImage.alt = "[+]"; } + + colorAncestors(); + return false; } @@ -64,6 +99,9 @@ function catToggle(id, selCats) { elToggleTreeImage.src = elToggleTreeImage.src.replace("Collapse", "Expand"); elToggleTreeImage.alt = "[+]"; } + + colorAncestors(); + return false; } diff --git a/ccm-core/web/themes/foundry/foundry/styles/admin.css b/ccm-core/web/themes/foundry/foundry/styles/admin.css index 556ca8aab..930041733 100644 --- a/ccm-core/web/themes/foundry/foundry/styles/admin.css +++ b/ccm-core/web/themes/foundry/foundry/styles/admin.css @@ -1056,6 +1056,14 @@ form[name="category"] table table{ background: none; } +form[name="category"] ul li.notSelectedAncestorCategory { + background-color: #e6dcde; +} + +form[name="category"] ul li ul li.selectedAncestorCategory { + background-color: #fff; +} + div.bebop-segment { margin-bottom:1em; padding-bottom:0.5em; diff --git a/ccm-core/web/themes/foundry/foundry/texts/cms.xml b/ccm-core/web/themes/foundry/foundry/texts/cms.xml index f001779c6..6f14e9b2e 100644 --- a/ccm-core/web/themes/foundry/foundry/texts/cms.xml +++ b/ccm-core/web/themes/foundry/foundry/texts/cms.xml @@ -7,7 +7,7 @@ - Kategorienzuweisen bearbeiten + Zugewiesene Kategorien bearbeiten Edit assigned categories diff --git a/ccm-ldn-terms/src/com/arsdigita/london/terms/ui/TermWidget.java b/ccm-ldn-terms/src/com/arsdigita/london/terms/ui/TermWidget.java index d7567a1d2..333cf2a97 100644 --- a/ccm-ldn-terms/src/com/arsdigita/london/terms/ui/TermWidget.java +++ b/ccm-ldn-terms/src/com/arsdigita/london/terms/ui/TermWidget.java @@ -53,24 +53,25 @@ import com.arsdigita.xml.XML; * A Widget for selecting Terms. Based heavily on CategoryWidget. * * @author mbooth@redhat.com - * - * Chris Gilbert - updated to identify each node uniquely (correct behaviour - * for polyhierarchical trees) - also, allow ajax update on all branches or - * just top level branch - * - * nb - widget applies to allocation of categories to any ACSObject hence - * xml prefix should be more generic eg bebop rather than cms. cms retained - * for compatibility with existing stylesheets + * + * Chris Gilbert - updated to identify each node uniquely (correct behaviour for + * polyhierarchical trees) - also, allow ajax update on all branches or just top + * level branch + * + * nb - widget applies to allocation of categories to any ACSObject hence xml + * prefix should be more generic eg bebop rather than cms. cms retained for + * compatibility with existing stylesheets */ // NON Javadoc comment: // Copied from c.ad.aplaws.ui in order to make forum-categorised independend from // a specific ccm-???-aplaws, i.e. a specific integration layer. public class TermWidget extends Widget { - private StringParameter m_mode; - private ACSObjectCategoryPicker m_picker; + private final StringParameter m_mode; + private final ACSObjectCategoryPicker m_picker; - public TermWidget(StringParameter mode, ACSObjectCategoryPicker picker) { + public TermWidget(final StringParameter mode, + final ACSObjectCategoryPicker picker) { super(new ArrayParameter(new BigDecimalParameter("category"))); m_mode = mode; @@ -89,32 +90,83 @@ public class TermWidget extends Widget { } @Override - protected void generateWidget(PageState state, Element parent) { - Domain domain = m_picker.getDomain(state); + protected void generateWidget(final PageState state, final Element parent) { + final Domain domain = m_picker.getDomain(state); - Element widget = parent.newChildElement("cms:categoryWidget", - CMS.CMS_XML_NS); + final Element widget = parent.newChildElement("cms:categoryWidget", + CMS.CMS_XML_NS); exportAttributes(widget); widget.addAttribute("mode", (String) state.getValue(m_mode)); widget.addAttribute("name", getName()); - Set ids = new HashSet(); - BigDecimal[] values = (BigDecimal[]) getValue(state); + final Set selectedCats = new HashSet(); + + //jensp 2015-03-12: In same cases we need to be able to pass the selected categories *and* + //the selected roots for displaying the categories nicely. To maintain backwards + //compatibility we check the type of the value and work either with the selected categories + //only or with the selected categories and their roots. + final Set selectedAncestors = new HashSet(); + + final BigDecimal[] values; + final BigDecimal[] selAncestorsValues; //selectedAncestors + final Object valueObj = getValue(state); + if (valueObj instanceof BigDecimal[][]) { + if (((BigDecimal[][]) valueObj).length >= 1) { + values = ((BigDecimal[][]) valueObj)[0]; + } else { + throw new IllegalArgumentException( + "Value of TermWidget is of type BigDecimal[][] but the array is empty."); + } + + if (((BigDecimal[][]) valueObj).length >= 2) { + selAncestorsValues = ((BigDecimal[][]) valueObj)[1]; + } else { + selAncestorsValues = null; + } + } else if (valueObj instanceof BigDecimal[]) { + values = (BigDecimal[]) valueObj; + selAncestorsValues = null; + } else { + throw new IllegalArgumentException( + "Value of TermWidget is not of type BigDecimal[] or BigDecimal[][]"); + } + + //BigDecimal[] values = (BigDecimal[]) getValue(state); if (values != null) { - ids.addAll(Arrays.asList(values)); + selectedCats.addAll(Arrays.asList(values)); } - Element selEl = widget.newChildElement("cms:selectedCategories", CMS.CMS_XML_NS); - selEl.addAttribute("name", this.getName()); - Iterator selCats = ids.iterator(); - while (selCats.hasNext()) { - Element selCat = selEl.newChildElement("cms:category", CMS.CMS_XML_NS); - selCat.addAttribute("id", selCats.next().toString()); + if (selAncestorsValues != null) { + selectedAncestors.addAll(Arrays.asList(selAncestorsValues)); } + final Element selEl = widget.newChildElement( + "cms:selectedCategories", CMS.CMS_XML_NS); + selEl.addAttribute("name", getName()); + final Iterator selCats = selectedCats.iterator(); +// while (selCats.hasNext()) { +// final Element selCat = selEl.newChildElement("cms:category", +// CMS.CMS_XML_NS); +// selCat.addAttribute("id", selCats.next().toString()); +// } + for(BigDecimal selectedCat : selectedCats) { + final Element selectedCatElem = selEl.newChildElement( + "cms:category", CMS.CMS_XML_NS); + selectedCatElem.addAttribute("id", selectedCat.toString()); + } + + final Element selAncestorsElem = widget.newChildElement( + "cms:selectedAncestorCategories", CMS.CMS_XML_NS); + selAncestorsElem.addAttribute("name", getName()); + for(BigDecimal selAncestor : selectedAncestors) { + final Element selAncestorElem = selAncestorsElem.newChildElement( + "cms:category", CMS.CMS_XML_NS); + selAncestorElem.addAttribute("id", selAncestor.toString()); + } + // only root terms at first, the rest is loaded on-demand via AJAX - DomainCollection terms = domain.getRootTerms(); + final DomainCollection terms = domain.getRootTerms(); // DomainCollection terms = domain.getTerms(); terms.addPath("model.parents.link.sortKey"); terms.addPath("model.parents.id"); @@ -135,35 +187,41 @@ public class TermWidget extends Widget { List roots = new LinkedList(); while (terms.next()) { Term term = (Term) terms.getDomainObject(); - roots.add(new TermSortKeyPair(term, (BigDecimal) terms.get("model.parents.link.sortKey"))); + roots.add(new TermSortKeyPair(term, (BigDecimal) terms.get( + "model.parents.link.sortKey"))); } - Element el = generateCategory(widget, domain.getModel(), ids, null); + Element el = generateCategory(widget, domain.getModel(), selectedCats, + null); /** - * Used by kea based keyphrase extraction facility. - * (Added r1885) - * + * Used by kea based keyphrase extraction facility. (Added r1885) + * * @Author: terry_permeance */ Indexer indexer = Indexer.retrieve(domain); if (indexer != null) { ContentItem item = CMS.getContext().getContentItem(); List autoTerms = indexer.index(item, 16); - Element autoCategories = widget.newChildElement("cms:autoCategories", CMS.CMS_XML_NS); + Element autoCategories = widget + .newChildElement("cms:autoCategories", CMS.CMS_XML_NS); for (Iterator i = autoTerms.iterator(); i.hasNext();) { RankedTerm nextRankedTerm = i.next(); Category cat = nextRankedTerm.getTerm().getModel(); - if (!ids.contains(cat.getID())) { + if (!selectedCats.contains(cat.getID())) { String fullname = cat.getQualifiedName(" > ", false); if (fullname != null) { - Element catEl = autoCategories.newChildElement("cms:category", CMS.CMS_XML_NS); + Element catEl = autoCategories.newChildElement( + "cms:category", CMS.CMS_XML_NS); catEl.addAttribute("id", XML.format(cat.getID())); catEl.addAttribute("name", cat.getName()); catEl.addAttribute("description", cat.getDescription()); - catEl.addAttribute("isAbstract", cat.isAbstract() ? "1" : "0"); - catEl.addAttribute("isEnabled", cat.isEnabled() ? "1" : "0"); - catEl.addAttribute("sortKey", nextRankedTerm.getRanking().toString()); + catEl.addAttribute("isAbstract", cat.isAbstract() ? "1" + : "0"); + catEl.addAttribute("isEnabled", cat.isEnabled() ? "1" + : "0"); + catEl.addAttribute("sortKey", nextRankedTerm + .getRanking().toString()); catEl.addAttribute("fullname", fullname); } } @@ -172,10 +230,10 @@ public class TermWidget extends Widget { if (Terms.getConfig().ajaxExpandAllBranches()) { // add attribute to the parent node, so that in stylesheet - // we can look for any ancestor with this attribute (can't - // add attribute to categoryWidget element as that is not - // visible when subbranches are transformed) - el.addAttribute("expand", "all" ); + // we can look for any ancestor with this attribute (can't + // add attribute to categoryWidget element as that is not + // visible when subbranches are transformed) + el.addAttribute("expand", "all"); } for (Iterator i = roots.iterator(); i.hasNext();) { @@ -183,20 +241,22 @@ public class TermWidget extends Widget { Term term = pair.getTerm(); BigDecimal sortKey = pair.getSortKey(); - generateRootTerm(el, term, ids, sortKey); + generateRootTerm(el, term, selectedCats, sortKey); } } public static Element generateCategory(Element parent, - Category cat, - Set selected, - BigDecimal sortKey) { + Category cat, + Set selected, + BigDecimal sortKey) { Element el = parent.newChildElement("cms:category", CMS.CMS_XML_NS); el.addAttribute("id", XML.format(cat.getID())); el.addAttribute("name", cat.getName()); el.addAttribute("description", cat.getDescription()); - el.addAttribute("isSelected", selected.contains(cat.getID()) ? "1" : "0"); + el + .addAttribute("isSelected", selected.contains(cat.getID()) ? "1" + : "0"); el.addAttribute("isAbstract", cat.isAbstract() ? "1" : "0"); el.addAttribute("isEnabled", cat.isEnabled() ? "1" : "0"); if (sortKey != null) { @@ -204,13 +264,14 @@ public class TermWidget extends Widget { } // sort order attribute added to every node so that we can // correctly transform xml fragments returned by ajax - el.addAttribute("order", ContentSection.getConfig().getCategoryTreeOrder()); + el.addAttribute("order", ContentSection.getConfig() + .getCategoryTreeOrder()); el.addAttribute("genCat", "true"); StringBuilder path = new StringBuilder(parent.getAttribute("fullname")); if (path.length() > 0) { path.append(" > "); - + } path.append(cat.getName()); el.addAttribute("fullname", path.toString()); @@ -221,7 +282,7 @@ public class TermWidget extends Widget { StringBuilder nodeID = new StringBuilder(parent.getAttribute("node-id")); if (nodeID.length() > 0) { nodeID.append("-"); - + } nodeID.append(cat.getID()); el.addAttribute("node-id", nodeID.toString()); @@ -230,9 +291,9 @@ public class TermWidget extends Widget { } public static Element generateTerm(Element parent, - Term term, - Set selected, - BigDecimal sortKey) { + Term term, + Set selected, + BigDecimal sortKey) { Category cat = term.getModel(); Element el = generateCategory(parent, cat, selected, sortKey); @@ -242,22 +303,23 @@ public class TermWidget extends Widget { } private static void generateRootTerm(Element parent, - Term term, - Set selected, - BigDecimal sortKey) { + Term term, + Set selected, + BigDecimal sortKey) { Element el = generateTerm(parent, term, selected, sortKey); el.addAttribute("root", "1"); } public static void generateSubtree(Element parent, Category root, Set ids) { DataCollection terms = SessionManager.getSession().retrieve( - Term.BASE_DATA_OBJECT_TYPE); + Term.BASE_DATA_OBJECT_TYPE); terms.addEqualsFilter("model.roTransParents.id", root.getID()); terms.addEqualsFilter("model.parents.link.relationType", "child"); Map children = new HashMap(); while (terms.next()) { - Term term = (Term) DomainObjectFactory.newInstance(terms.getDataObject()); + Term term = (Term) DomainObjectFactory.newInstance(terms + .getDataObject()); BigDecimal parentID = (BigDecimal) terms.get("model.parents.id"); List childList = (List) children.get(parentID); @@ -266,18 +328,20 @@ public class TermWidget extends Widget { children.put(parentID, childList); } - childList.add(new TermSortKeyPair(term, (BigDecimal) terms.get("model.parents.link.sortKey"))); + childList.add(new TermSortKeyPair(term, (BigDecimal) terms.get( + "model.parents.link.sortKey"))); } Element el = generateCategory(parent, root, ids, null); el.addAttribute("fullname", root.getName()); el.addAttribute("node-id", root.getID().toString()); - el.addAttribute("order", ContentSection.getConfig().getCategoryTreeOrder()); - if (Terms.getConfig().ajaxExpandAllBranches()) { + el.addAttribute("order", ContentSection.getConfig() + .getCategoryTreeOrder()); + if (Terms.getConfig().ajaxExpandAllBranches()) { // recognisable attribute has to be in the XML for each snippet that is transformed, - // hence add it to the parent - el.addAttribute("expand", "all" ); - } + // hence add it to the parent + el.addAttribute("expand", "all"); + } List roots = (List) children.get(root.getID()); if (null != roots) { @@ -293,10 +357,10 @@ public class TermWidget extends Widget { } private static void generateTermWithChildren(Element parent, - Term term, - Set selected, - BigDecimal sortKey, - Map children) { + Term term, + Set selected, + BigDecimal sortKey, + Map children) { Category cat = term.getModel(); Element el = generateCategory(parent, cat, selected, sortKey); @@ -312,17 +376,14 @@ public class TermWidget extends Widget { BigDecimal childSortKey = pair.getSortKey(); // either generate next level down, or get all levels below current - if (Terms.getConfig().ajaxExpandAllBranches()) { - generateTerm(el, child, selected, childSortKey); + generateTerm(el, child, selected, childSortKey); } else { - generateTermWithChildren(el, child, selected, childSortKey, - children); + generateTermWithChildren(el, child, selected, childSortKey, + children); } - - } } } @@ -344,5 +405,7 @@ public class TermWidget extends Widget { public BigDecimal getSortKey() { return m_sortKey; } + } + }