- 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
master
jensp 2015-03-13 12:29:33 +00:00
parent 05580fc24a
commit 1e3cb64455
23 changed files with 360 additions and 219 deletions

View File

@ -15,7 +15,7 @@
name="LibreCMS-SL" name="LibreCMS-SL"
prettyName="LibreCMS (Slimline Bundle)" prettyName="LibreCMS (Slimline Bundle)"
version="2.3.0" version="2.3.0"
release="trunk-r2915" release="trunk-r3276"
webxml="libre-web.xml" webxml="libre-web.xml"
webapp="ROOT" webapp="ROOT"
xsi:schemaLocation="http://ccm.redhat.com/ccm-project file:tools-ng/common/xsd/project.xsd"> xsi:schemaLocation="http://ccm.redhat.com/ccm-project file:tools-ng/common/xsd/project.xsd">

View File

@ -59,6 +59,7 @@ public class CategoryWidget extends Widget {
protected String getType() { protected String getType() {
return "category"; return "category";
} }
@Override @Override
public boolean isCompound() { public boolean isCompound() {
return false; return false;
@ -71,42 +72,42 @@ public class CategoryWidget extends Widget {
CMS.CMS_XML_NS); CMS.CMS_XML_NS);
exportAttributes(widget); exportAttributes(widget);
widget.addAttribute("mode", (String)state.getValue(m_mode)); widget.addAttribute("mode", (String) state.getValue(m_mode));
widget.addAttribute("name", getName()); 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) { 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, new OID(Category.BASE_DATA_OBJECT_TYPE,
(BigDecimal)state.getValue(m_root)) (BigDecimal) state.getValue(m_root))
); );
CategoryCollection cats = root.getDescendants(); CategoryCollection categories = root.getDescendants();
cats.addEqualsFilter("parents.link.relationType", "child"); categories.addEqualsFilter("parents.link.relationType", "child");
cats.addPath("parents.link.sortKey"); categories.addPath("parents.link.sortKey");
cats.addPath("parents.id"); categories.addPath("parents.id");
Map children = new HashMap(); final Map children = new HashMap();
while (cats.next()) { while (categories.next()) {
Category cat = cats.getCategory(); final Category cat = categories.getCategory();
BigDecimal parentID = (BigDecimal)cats.get("parents.id"); final BigDecimal parentID = (BigDecimal) categories.get("parents.id");
List childList = (List)children.get(parentID); List childList = (List) children.get(parentID);
if (childList == null) { if (childList == null) {
childList = new ArrayList(); childList = new ArrayList();
children.put(parentID, childList); children.put(parentID, childList);
} }
childList.add(new CategorySortKeyPair childList.add(
(cat,(BigDecimal)cats.get("parents.link.sortKey"))); 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, public void generateCategory(Element parent,
@ -134,15 +135,15 @@ public class CategoryWidget extends Widget {
String fullname = path == null ? "/" : path + " > " + cat.getName(); String fullname = path == null ? "/" : path + " > " + cat.getName();
el.addAttribute("fullname", fullname); el.addAttribute("fullname", fullname);
StringBuilder nodeID = new StringBuilder(parent.getAttribute("node-id")); StringBuilder nodeID = new StringBuilder(parent.getAttribute("node-id"));
if (nodeID.length() > 0) { if (nodeID.length() > 0) {
nodeID.append("-"); nodeID.append("-");
} }
nodeID.append(cat.getID()); nodeID.append(cat.getID());
el.addAttribute("node-id", nodeID.toString()); el.addAttribute("node-id", nodeID.toString());
parent.addContent(el); parent.addContent(el);
List c = (List)children.get(cat.getID()); List c = (List) children.get(cat.getID());
if (c != null) { if (c != null) {
Iterator i = c.iterator(); Iterator i = c.iterator();
while (i.hasNext()) { while (i.hasNext()) {
@ -154,7 +155,9 @@ public class CategoryWidget extends Widget {
} }
} }
} }
private class CategorySortKeyPair { private class CategorySortKeyPair {
private Category m_category; private Category m_category;
private BigDecimal m_sortKey; private BigDecimal m_sortKey;
@ -162,11 +165,15 @@ public class CategoryWidget extends Widget {
m_category = category; m_category = category;
m_sortKey = sortKey; m_sortKey = sortKey;
} }
public Category getCategory() { public Category getCategory() {
return m_category; return m_category;
} }
public BigDecimal getSortKey() { public BigDecimal getSortKey() {
return m_sortKey; return m_sortKey;
} }
} }
} }

View File

@ -38,24 +38,22 @@ public class ItemCategoryForm extends ACSObjectCategoryForm {
private static Logger s_log = Logger.getLogger(ItemCategoryForm.class); private static Logger s_log = Logger.getLogger(ItemCategoryForm.class);
public ItemCategoryForm(BigDecimalParameter root, StringParameter mode, Widget widget) { public ItemCategoryForm(BigDecimalParameter root, StringParameter mode, Widget widget) {
super(root, mode, widget); super(root, mode, widget);
s_log.debug("creating new ItemTerm Form with widget " + widget); s_log.debug("creating new ItemTerm Form with widget " + widget);
} }
public ItemCategoryForm(BigDecimalParameter root, StringParameter mode) { 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() * @see com.arsdigita.categorization.ui.ACSObjectCategoryForm#getObject()
*/ */
protected ACSObject getObject(PageState state) { protected ACSObject getObject(PageState state) {
ContentItem item = CMS.getContext().getContentItem(); ContentItem item = CMS.getContext().getContentItem();
return item.getParent(); return item.getParent();
} }

View File

@ -43,18 +43,18 @@ import com.arsdigita.domain.DomainObjectFactory;
import com.arsdigita.kernel.ACSObject; import com.arsdigita.kernel.ACSObject;
import com.arsdigita.persistence.OID; import com.arsdigita.persistence.OID;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set;
/** /**
* Abstract form for assigning categories to acs_objects. The assigned * Abstract form for assigning categories to acs_objects. The assigned categories are those
* categories are those specified by the category widget, which is * specified by the category widget, which is retrieved by the concrete subclass' implementation of
* retrieved by the concrete subclass' implementation of getCategoryWidget. * getCategoryWidget.
* *
* The category widget may be an implementation of CategoryWidget, which * The category widget may be an implementation of CategoryWidget, which generates a javascript tree
* generates a javascript tree of categories. Implementations need only * of categories. Implementations need only specify an XML prefix and namespace.
* specify an XML prefix and namespace.
* *
* The object that is to be assigned to the categories is specified * The object that is to be assigned to the categories is specified by the concrete subclass'
* by the concrete subclass' implentation of getObject * implentation of getObject
* *
* @author chris.gilbert@westsussex.gov.uk * @author chris.gilbert@westsussex.gov.uk
* *
@ -74,7 +74,6 @@ public abstract class ACSObjectCategoryForm extends Form {
Widget categoryWidget) { Widget categoryWidget) {
super("category", new BoxPanel(BoxPanel.VERTICAL)); super("category", new BoxPanel(BoxPanel.VERTICAL));
m_category = categoryWidget; m_category = categoryWidget;
m_category.addValidationListener(new NotNullValidationListener()); m_category.addValidationListener(new NotNullValidationListener());
m_buttons = new SaveCancelSection(); m_buttons = new SaveCancelSection();
@ -85,20 +84,27 @@ public abstract class ACSObjectCategoryForm extends Form {
addInitListener(new FormInitListener() { addInitListener(new FormInitListener() {
@Override @Override
public void init(FormSectionEvent ev) public void init(FormSectionEvent ev) throws FormProcessException {
throws FormProcessException {
PageState state = ev.getPageState(); final PageState state = ev.getPageState();
ACSObject object = getObject(state); final ACSObject object = getObject(state);
List ids = new ArrayList(); final List<BigDecimal> selectedCats = new ArrayList<BigDecimal>();
CategoryCollection cats = new CategorizedObject(object).getParents(); final Set<BigDecimal> ancestorCats = new HashSet<BigDecimal>();
while (cats.next()) { final CategoryCollection categories = new CategorizedObject(object).getParents();
ids.add(cats.getCategory().getID()); while (categories.next()) {
final Category category = categories.getCategory();
selectedCats.add(category.getID());
addAncestorCats(ancestorCats, category);
} }
m_category.setValue(state, final BigDecimal[][] paramArray = new BigDecimal[2][];
ids.toArray(new BigDecimal[ids.size()])); paramArray[0] = selectedCats.toArray(new BigDecimal[selectedCats.size()]);
paramArray[1] = ancestorCats.toArray(new BigDecimal[ancestorCats.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); BigDecimal[] ids = (BigDecimal[]) m_category.getValue(state);
for (BigDecimal id : ids) { for (BigDecimal id : ids) {
Category cat = (Category) DomainObjectFactory 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)) { if (!curSelectedCat.contains(id)) {
cat.addChild(object); cat.addChild(object);
} else { } else {
@ -144,9 +150,21 @@ public abstract class ACSObjectCategoryForm extends Form {
fireCompletionEvent(state); fireCompletionEvent(state);
throw new FormProcessException("Submission cancelled", throw new FormProcessException("Submission cancelled",
GlobalizationUtil.globalize( GlobalizationUtil.globalize(
"categorization.cancel.msg")); "categorization.cancel.msg"));
} }
} }
}); });
} }
private void addAncestorCats(final Set<BigDecimal> ancestorCats, final Category category) {
final CategoryCollection ascendants = category.getDefaultAscendants();
while(ascendants.next()) {
final Category ascendant = ascendants.getCategory();
ancestorCats.add(ascendant.getID());
}
}
} }

View File

@ -41,26 +41,24 @@ import java.util.Iterator;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
/** /**
* This is a simple extension of the QueryComponent that * This is a simple extension of the QueryComponent that provides management of the 'terms'
* provides management of the 'terms' parameter and uses * parameter and uses FilterGenerators to populate a query specification
* FilterGenerators to populate a query specification
* <p> * <p>
* Typical use would be as follows: * Typical use would be as follows:
*<pre> * <pre>
* Form f = new Form("search"); * Form f = new Form("search");
* BaseQueryComponent q = new BaseQueryComponent(); * BaseQueryComponent q = new BaseQueryComponent();
* q.add(new ObjectTypeFilterComponent("com.arsdigita.kernel.User"); * q.add(new ObjectTypeFilterComponent("com.arsdigita.kernel.User");
* q.add(new PermissionGenerator(PrivilegeDescriptor.READ)); * q.add(new PermissionGenerator(PrivilegeDescriptor.READ));
* q.add(new Submit("Go")); * q.add(new Submit("Go"));
* f.add(q); * f.add(q);
*</pre> * </pre>
*/ */
public class BaseQueryComponent extends QueryComponent { public class BaseQueryComponent extends QueryComponent {
private static final Logger s_log = private static final Logger s_log
Logger.getLogger(BaseQueryComponent.class); = Logger.getLogger(BaseQueryComponent.class);
private Set m_filters; private Set m_filters;
private Form m_form; private Form m_form;
@ -86,7 +84,7 @@ public class BaseQueryComponent extends QueryComponent {
if (s_log.isDebugEnabled()) { 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"); s_log.debug("Adding " + m_terms.getName() + " to form model");
m_terms.setPassIn(true); m_terms.setPassIn(true);
model.addFormParam(m_terms); model.addFormParam(m_terms);
m_form = form; m_form = form;
@ -99,27 +97,25 @@ public class BaseQueryComponent extends QueryComponent {
FormData fd = m_form.getFormData(state); FormData fd = m_form.getFormData(state);
if (fd != null) { if (fd != null) {
ParameterData data = fd.getParameter(m_terms.getName()); ParameterData data = fd.getParameter(m_terms.getName());
s_log.debug("Search terms were : " + (String)data.getValue()); s_log.debug("Search terms were : " + (String) data.getValue());
return (String)data.getValue(); return (String) data.getValue();
} }
return null; return null;
} }
protected FilterSpecification[] getFilters(PageState state) { protected FilterSpecification[] getFilters(PageState state) {
FilterSpecification[] filters = new FilterSpecification[m_filters.size()]; FilterSpecification[] filters = new FilterSpecification[m_filters.size()];
Iterator i = m_filters.iterator(); Iterator i = m_filters.iterator();
int c = 0; int c = 0;
while (i.hasNext()) { while (i.hasNext()) {
FilterGenerator filter = (FilterGenerator)i.next(); FilterGenerator filter = (FilterGenerator) i.next();
filters[c++] = filter.getFilter(state); filters[c++] = filter.getFilter(state);
} }
return filters; return filters;
} }
/** /**
* *
* @param state * @param state
@ -152,7 +148,7 @@ public class BaseQueryComponent extends QueryComponent {
while (i.hasNext()) { while (i.hasNext()) {
Element error = Search.newElement("error"); Element error = Search.newElement("error");
error.setText( error.setText(
(String) ((GlobalizedMessage) i.next()).localize(state.getRequest()) (String) ((GlobalizedMessage) i.next()).localize(state.getRequest())
); );
parent.addContent(error); parent.addContent(error);
} }
@ -164,6 +160,7 @@ public class BaseQueryComponent extends QueryComponent {
} }
private class FilterTraversal extends Traversal { private class FilterTraversal extends Traversal {
private Set m_filters; private Set m_filters;
public FilterTraversal(Set filters) { public FilterTraversal(Set filters) {

View File

@ -30,8 +30,8 @@ import com.arsdigita.util.Assert;
/** /**
* A base class for generating a query specification * A base class for generating a query specification
* from the state. Subclasses must implement two * from the state. Subclasses must implement two
* methods, one for getting the query tmers, * methods, one for getting the query terms,
* the other for gettting a set of filter specs. * the other for getting a set of filter specs.
*/ */
public abstract class QueryComponent extends SimpleContainer public abstract class QueryComponent extends SimpleContainer
implements QueryGenerator { implements QueryGenerator {

View File

@ -21,7 +21,6 @@ package com.arsdigita.search.ui;
import com.arsdigita.bebop.SimpleComponent; import com.arsdigita.bebop.SimpleComponent;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.parameters.IntegerParameter; import com.arsdigita.bebop.parameters.IntegerParameter;
import com.arsdigita.bebop.util.GlobalizationUtil;
import com.arsdigita.globalization.Globalization; import com.arsdigita.globalization.Globalization;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;

View File

@ -7,7 +7,7 @@
</text> </text>
<text id="category-step/header"> <text id="category-step/header">
<translation lang="de">Kategorienzuweisen bearbeiten</translation> <translation lang="de">Zugewiesene Kategorien</translation>
<translation lang="en">Edit assigned categories</translation> <translation lang="en">Edit assigned categories</translation>
</text> </text>

View File

@ -33,7 +33,7 @@
xmlns:cms="http://www.arsdigita.com/cms/1.0" xmlns:cms="http://www.arsdigita.com/cms/1.0"
xmlns:foundry="http://foundry.libreccm.org" xmlns:foundry="http://foundry.libreccm.org"
xmlns:nav="http://ccm.redhat.com/navigation" 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"> version="2.0">
<!-- DE Seitenstruktur --> <!-- DE Seitenstruktur -->

View File

@ -28,14 +28,13 @@
<!-- Autor: Sören Bernstein --> <!-- Autor: Sören Bernstein -->
<xsl:stylesheet <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:bebop="http://www.arsdigita.com/bebop/1.0"
xmlns:bebop="http://www.arsdigita.com/bebop/1.0" xmlns:cms="http://www.arsdigita.com/cms/1.0"
xmlns:cms="http://www.arsdigita.com/cms/1.0" xmlns:foundry="http://foundry.libreccm.org"
xmlns:foundry="http://foundry.libreccm.org" xmlns:nav="http://ccm.redhat.com/navigation"
xmlns:nav="http://ccm.redhat.com/navigation" exclude-result-prefixes="xsl bebop cms foundry nav"
exclude-result-prefixes="xsl bebop cms foundry nav" version="1.0">
version="1.0">
<!-- DE Benutze DHTML-Editor (HTMLArea) --> <!-- DE Benutze DHTML-Editor (HTMLArea) -->
<!-- EN Use DHTML-Editor (HTMLArea) --> <!-- EN Use DHTML-Editor (HTMLArea) -->

View File

@ -49,6 +49,7 @@
<xsl:if test="not(./@method)"> <xsl:if test="not(./@method)">
<xsl:attribute name="method">post</xsl:attribute> <xsl:attribute name="method">post</xsl:attribute>
</xsl:if> </xsl:if>
<xsl:attribute name="here" select="'foo'"/>
<xsl:call-template name="foundry:process-datatree-attributes"/> <xsl:call-template name="foundry:process-datatree-attributes"/>
<xsl:apply-templates/> <xsl:apply-templates/>
</form> </form>

View File

@ -26,14 +26,13 @@
Processing bebop images Processing bebop images
--> -->
<xsl:stylesheet <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:bebop="http://www.arsdigita.com/bebop/1.0"
xmlns:bebop="http://www.arsdigita.com/bebop/1.0" xmlns:cms="http://www.arsdigita.com/cms/1.0"
xmlns:cms="http://www.arsdigita.com/cms/1.0" xmlns:foundry="http://foundry.libreccm.org"
xmlns:foundry="http://foundry.libreccm.org" xmlns:nav="http://ccm.redhat.com/navigation"
xmlns:nav="http://ccm.redhat.com/navigation" exclude-result-prefixes="xsl bebop cms foundry nav"
exclude-result-prefixes="xsl bebop cms foundry nav" version="2.0">
version="1.0">
<!-- DE Verarbeite Bilder - Ignoriere javascript-mode --> <!-- DE Verarbeite Bilder - Ignoriere javascript-mode -->
<!-- EN Processing images - inore javascript-mode --> <!-- EN Processing images - inore javascript-mode -->

View File

@ -33,7 +33,7 @@
xmlns:foundry="http://foundry.libreccm.org" xmlns:foundry="http://foundry.libreccm.org"
xmlns:nav="http://ccm.redhat.com/navigation" xmlns:nav="http://ccm.redhat.com/navigation"
exclude-result-prefixes="xsl bebop cms foundry nav" exclude-result-prefixes="xsl bebop cms foundry nav"
version="1.0"> version="2.0">
<!-- DE Ein Text-Label mit Formatierung --> <!-- DE Ein Text-Label mit Formatierung -->
<!-- EN A formatted text label --> <!-- EN A formatted text label -->

View File

@ -26,14 +26,13 @@
Processing bebop lists Processing bebop lists
--> -->
<xsl:stylesheet <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:bebop="http://www.arsdigita.com/bebop/1.0"
xmlns:bebop="http://www.arsdigita.com/bebop/1.0" xmlns:cms="http://www.arsdigita.com/cms/1.0"
xmlns:cms="http://www.arsdigita.com/cms/1.0" xmlns:foundry="http://foundry.libreccm.org"
xmlns:foundry="http://foundry.libreccm.org" xmlns:nav="http://ccm.redhat.com/navigation"
xmlns:nav="http://ccm.redhat.com/navigation" exclude-result-prefixes="xsl bebop cms foundry nav"
exclude-result-prefixes="xsl bebop cms foundry nav" version="2.0">
version="1.0">
<!-- DE Eine verticale Liste als UL, wenn es keine item-path-Liste ist --> <!-- DE Eine verticale Liste als UL, wenn es keine item-path-Liste ist -->
<!-- EN A vertical list as ul, if it is not an item-path type list --> <!-- EN A vertical list as ul, if it is not an item-path type list -->

View File

@ -33,7 +33,7 @@
xmlns:cms="http://www.arsdigita.com/cms/1.0" xmlns:cms="http://www.arsdigita.com/cms/1.0"
xmlns:foundry="http://foundry.libreccm.org" xmlns:foundry="http://foundry.libreccm.org"
xmlns:nav="http://ccm.redhat.com/navigation" 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"> version="2.0">
<!-- DE Schreibe den PageState in versteckte Input-Felder --> <!-- DE Schreibe den PageState in versteckte Input-Felder -->

View File

@ -33,7 +33,6 @@
xmlns:cms="http://www.arsdigita.com/cms/1.0" xmlns:cms="http://www.arsdigita.com/cms/1.0"
xmlns:foundry="http://foundry.libreccm.org" xmlns:foundry="http://foundry.libreccm.org"
xmlns:nav="http://ccm.redhat.com/navigation" xmlns:nav="http://ccm.redhat.com/navigation"
xmlns:mandalay="http://mandalay.quasiweb.de"
exclude-result-prefixes="xsl bebop cms foundry nav" exclude-result-prefixes="xsl bebop cms foundry nav"
version="2.0"> version="2.0">

View File

@ -29,13 +29,13 @@
<!-- Autor: Sören Bernstein --> <!-- Autor: Sören Bernstein -->
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" <xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:bebop="http://www.arsdigita.com/bebop/1.0" xmlns:bebop="http://www.arsdigita.com/bebop/1.0"
xmlns:cms="http://www.arsdigita.com/cms/1.0" xmlns:cms="http://www.arsdigita.com/cms/1.0"
xmlns:foundry="http://foundry.libreccm.org" xmlns:foundry="http://foundry.libreccm.org"
xmlns:nav="http://ccm.redhat.com/navigation" xmlns:nav="http://ccm.redhat.com/navigation"
exclude-result-prefixes="xsl bebop cms foundry nav" exclude-result-prefixes="xsl bebop cms foundry nav"
version="2.0"> version="2.0">
<!-- DE Erzeuge einen Div-Container mit Tabellenreitern --> <!-- DE Erzeuge einen Div-Container mit Tabellenreitern -->
<!-- EN Create a div container with tab --> <!-- EN Create a div container with tab -->

View File

@ -32,7 +32,7 @@
xmlns:foundry="http://foundry.libreccm.org" xmlns:foundry="http://foundry.libreccm.org"
xmlns:nav="http://ccm.redhat.com/navigation" xmlns:nav="http://ccm.redhat.com/navigation"
exclude-result-prefixes="xsl bebop cms foundry nav" exclude-result-prefixes="xsl bebop cms foundry nav"
version="1.0"> version="2.0">
<!-- DE Erzeuge Tabelle. Da die einzelnen Bestandteile (thead, tbody und tfoot) nicht <!-- DE Erzeuge Tabelle. Da die einzelnen Bestandteile (thead, tbody und tfoot) nicht
in der von HTML vorgesehenen Reihenfolge im XML stehen, müssen diese hier in in der von HTML vorgesehenen Reihenfolge im XML stehen, müssen diese hier in

View File

@ -282,16 +282,20 @@
<!--<script type="text/javascript" src="{$context-prefix}/assets/jquery.js"/> --> <!--<script type="text/javascript" src="{$context-prefix}/assets/jquery.js"/> -->
<!--<script type="text/javascript" src="{$theme-prefix}/includes/cms/category-step.js"/> --> <!--<script type="text/javascript" src="{$theme-prefix}/includes/cms/category-step.js"/> -->
<xsl:choose> <xsl:choose>
<xsl:when test="@mode='javascript'"> <xsl:when test="./@mode = 'javascript'">
<ul> <ul>
<xsl:apply-templates select="cms:category" mode="javascript"/> <xsl:apply-templates select="cms:category" mode="javascript"/>
</ul> </ul>
<xsl:apply-templates select="cms:selectedCategories"/> <xsl:apply-templates select="cms:selectedCategories"/>
<xsl:apply-templates select="cms:selectedAncestorCategories"/>
<script type="text/javascript">
colorAncestors();
</script>
</xsl:when> </xsl:when>
<xsl:otherwise> <xsl:otherwise>
<select name="@name" size="30" multiple="multiple"> <select name="./@name" size="30" multiple="multiple">
<xsl:apply-templates mode="plain"> <xsl:apply-templates mode="plain">
<xsl:sort data-type="number" select="@sortKey"/> <xsl:sort data-type="number" select="./@sortKey"/>
</xsl:apply-templates> </xsl:apply-templates>
</select> </select>
</xsl:otherwise> </xsl:otherwise>
@ -299,14 +303,26 @@
</xsl:template> </xsl:template>
<xsl:template match="cms:selectedCategories"> <xsl:template match="cms:selectedCategories">
<select id="catWdHd" name="{../@name}" size="5" multiple="multiple" style="display: none"> <select id="catWdHd"
name="{../@name}"
size="5"
multiple="multiple"
style="display: none">
<xsl:apply-templates select="cms:category" mode="hidden"/> <xsl:apply-templates select="cms:category" mode="hidden"/>
</select> </select>
</xsl:template> </xsl:template>
<xsl:template match="cms:selectedAncestorCategories">
<input id = "selectedAncestorCategories"
name = "selectedAncestorCategories"
value = "{string-join(./cms:category/@id, ',')}"
type = "hidden" />
</xsl:template>
<xsl:template match="cms:category" mode="hidden"> <xsl:template match="cms:category" mode="hidden">
<option value="{@id}"> <option value="{./@id}">
<xsl:value-of select="@id"/> <xsl:value-of select="./@id"/>
</option> </option>
<xsl:apply-templates select="cms:category" mode="hidden"/> <xsl:apply-templates select="cms:category" mode="hidden"/>
</xsl:template> </xsl:template>
@ -326,7 +342,7 @@
</xsl:otherwise> </xsl:otherwise>
</xsl:choose> </xsl:choose>
</xsl:variable> </xsl:variable>
<li id="catSelf{@id}"> <li id="catSelf{@id}" class="notSelectedAncestorCategory">
<!-- Treefunctions (expand and collapse) --> <!-- Treefunctions (expand and collapse) -->
<xsl:variable name="tree-toogle-mode"> <xsl:variable name="tree-toogle-mode">
<xsl:choose> <xsl:choose>

View File

@ -25,6 +25,36 @@
These functions are part of the ajax-pages to assign categories. 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 // DE Lade einen Kategorienzweig nach, wenn dieser aufgeklappt wird
// EN Loading a branch of categories when it is expanded // EN Loading a branch of categories when it is expanded
function catBranchToggle(id, selCats) { function catBranchToggle(id, selCats) {
@ -35,7 +65,9 @@ function catBranchToggle(id, selCats) {
if (elBranch.innerHTML == "" || elBranch.innerHTML == "...") { if (elBranch.innerHTML == "" || elBranch.innerHTML == "...") {
elBranch.innerHTML = "..."; elBranch.innerHTML = "...";
elBranch.style.display = "block"; 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 { } else {
elBranch.style.display = "block"; elBranch.style.display = "block";
} }
@ -46,6 +78,9 @@ function catBranchToggle(id, selCats) {
elToggleTreeImage.src = elToggleTreeImage.src.replace("Collapse", "Expand"); elToggleTreeImage.src = elToggleTreeImage.src.replace("Collapse", "Expand");
elToggleTreeImage.alt = "[+]"; elToggleTreeImage.alt = "[+]";
} }
colorAncestors();
return false; return false;
} }
@ -64,6 +99,9 @@ function catToggle(id, selCats) {
elToggleTreeImage.src = elToggleTreeImage.src.replace("Collapse", "Expand"); elToggleTreeImage.src = elToggleTreeImage.src.replace("Collapse", "Expand");
elToggleTreeImage.alt = "[+]"; elToggleTreeImage.alt = "[+]";
} }
colorAncestors();
return false; return false;
} }

View File

@ -1056,6 +1056,14 @@ form[name="category"] table table{
background: none; 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 { div.bebop-segment {
margin-bottom:1em; margin-bottom:1em;
padding-bottom:0.5em; padding-bottom:0.5em;

View File

@ -7,7 +7,7 @@
</text> </text>
<text id="category-step/header"> <text id="category-step/header">
<translation lang="de">Kategorienzuweisen bearbeiten</translation> <translation lang="de">Zugewiesene Kategorien bearbeiten</translation>
<translation lang="en">Edit assigned categories</translation> <translation lang="en">Edit assigned categories</translation>
</text> </text>

View File

@ -54,23 +54,24 @@ import com.arsdigita.xml.XML;
* *
* @author mbooth@redhat.com * @author mbooth@redhat.com
* *
* Chris Gilbert - updated to identify each node uniquely (correct behaviour * Chris Gilbert - updated to identify each node uniquely (correct behaviour for
* for polyhierarchical trees) - also, allow ajax update on all branches or * polyhierarchical trees) - also, allow ajax update on all branches or just top
* just top level branch * level branch
* *
* nb - widget applies to allocation of categories to any ACSObject hence * nb - widget applies to allocation of categories to any ACSObject hence xml
* xml prefix should be more generic eg bebop rather than cms. cms retained * prefix should be more generic eg bebop rather than cms. cms retained for
* for compatibility with existing stylesheets * compatibility with existing stylesheets
*/ */
// NON Javadoc comment: // NON Javadoc comment:
// Copied from c.ad.aplaws.ui in order to make forum-categorised independend from // Copied from c.ad.aplaws.ui in order to make forum-categorised independend from
// a specific ccm-???-aplaws, i.e. a specific integration layer. // a specific ccm-???-aplaws, i.e. a specific integration layer.
public class TermWidget extends Widget { public class TermWidget extends Widget {
private StringParameter m_mode; private final StringParameter m_mode;
private ACSObjectCategoryPicker m_picker; 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"))); super(new ArrayParameter(new BigDecimalParameter("category")));
m_mode = mode; m_mode = mode;
@ -89,32 +90,83 @@ public class TermWidget extends Widget {
} }
@Override @Override
protected void generateWidget(PageState state, Element parent) { protected void generateWidget(final PageState state, final Element parent) {
Domain domain = m_picker.getDomain(state); final Domain domain = m_picker.getDomain(state);
Element widget = parent.newChildElement("cms:categoryWidget", final Element widget = parent.newChildElement("cms:categoryWidget",
CMS.CMS_XML_NS); CMS.CMS_XML_NS);
exportAttributes(widget); exportAttributes(widget);
widget.addAttribute("mode", (String) state.getValue(m_mode)); widget.addAttribute("mode", (String) state.getValue(m_mode));
widget.addAttribute("name", getName()); widget.addAttribute("name", getName());
Set ids = new HashSet(); final Set<BigDecimal> selectedCats = new HashSet<BigDecimal>();
BigDecimal[] values = (BigDecimal[]) getValue(state);
if (values != null) { //jensp 2015-03-12: In same cases we need to be able to pass the selected categories *and*
ids.addAll(Arrays.asList(values)); //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<BigDecimal> selectedAncestors = new HashSet<BigDecimal>();
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[][]");
} }
Element selEl = widget.newChildElement("cms:selectedCategories", CMS.CMS_XML_NS); //BigDecimal[] values = (BigDecimal[]) getValue(state);
selEl.addAttribute("name", this.getName()); if (values != null) {
Iterator selCats = ids.iterator(); selectedCats.addAll(Arrays.asList(values));
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<BigDecimal> 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 // 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(); // DomainCollection terms = domain.getTerms();
terms.addPath("model.parents.link.sortKey"); terms.addPath("model.parents.link.sortKey");
terms.addPath("model.parents.id"); terms.addPath("model.parents.id");
@ -135,14 +187,15 @@ public class TermWidget extends Widget {
List roots = new LinkedList(); List roots = new LinkedList();
while (terms.next()) { while (terms.next()) {
Term term = (Term) terms.getDomainObject(); 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. * Used by kea based keyphrase extraction facility. (Added r1885)
* (Added r1885)
* *
* @Author: terry_permeance * @Author: terry_permeance
*/ */
@ -150,20 +203,25 @@ public class TermWidget extends Widget {
if (indexer != null) { if (indexer != null) {
ContentItem item = CMS.getContext().getContentItem(); ContentItem item = CMS.getContext().getContentItem();
List<RankedTerm> autoTerms = indexer.index(item, 16); List<RankedTerm> 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<RankedTerm> i = autoTerms.iterator(); i.hasNext();) { for (Iterator<RankedTerm> i = autoTerms.iterator(); i.hasNext();) {
RankedTerm nextRankedTerm = i.next(); RankedTerm nextRankedTerm = i.next();
Category cat = nextRankedTerm.getTerm().getModel(); Category cat = nextRankedTerm.getTerm().getModel();
if (!ids.contains(cat.getID())) { if (!selectedCats.contains(cat.getID())) {
String fullname = cat.getQualifiedName(" > ", false); String fullname = cat.getQualifiedName(" > ", false);
if (fullname != null) { 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("id", XML.format(cat.getID()));
catEl.addAttribute("name", cat.getName()); catEl.addAttribute("name", cat.getName());
catEl.addAttribute("description", cat.getDescription()); catEl.addAttribute("description", cat.getDescription());
catEl.addAttribute("isAbstract", cat.isAbstract() ? "1" : "0"); catEl.addAttribute("isAbstract", cat.isAbstract() ? "1"
catEl.addAttribute("isEnabled", cat.isEnabled() ? "1" : "0"); : "0");
catEl.addAttribute("sortKey", nextRankedTerm.getRanking().toString()); catEl.addAttribute("isEnabled", cat.isEnabled() ? "1"
: "0");
catEl.addAttribute("sortKey", nextRankedTerm
.getRanking().toString());
catEl.addAttribute("fullname", fullname); catEl.addAttribute("fullname", fullname);
} }
} }
@ -172,10 +230,10 @@ public class TermWidget extends Widget {
if (Terms.getConfig().ajaxExpandAllBranches()) { if (Terms.getConfig().ajaxExpandAllBranches()) {
// add attribute to the parent node, so that in stylesheet // add attribute to the parent node, so that in stylesheet
// we can look for any ancestor with this attribute (can't // we can look for any ancestor with this attribute (can't
// add attribute to categoryWidget element as that is not // add attribute to categoryWidget element as that is not
// visible when subbranches are transformed) // visible when subbranches are transformed)
el.addAttribute("expand", "all" ); el.addAttribute("expand", "all");
} }
for (Iterator i = roots.iterator(); i.hasNext();) { for (Iterator i = roots.iterator(); i.hasNext();) {
@ -183,20 +241,22 @@ public class TermWidget extends Widget {
Term term = pair.getTerm(); Term term = pair.getTerm();
BigDecimal sortKey = pair.getSortKey(); BigDecimal sortKey = pair.getSortKey();
generateRootTerm(el, term, ids, sortKey); generateRootTerm(el, term, selectedCats, sortKey);
} }
} }
public static Element generateCategory(Element parent, public static Element generateCategory(Element parent,
Category cat, Category cat,
Set selected, Set selected,
BigDecimal sortKey) { BigDecimal sortKey) {
Element el = parent.newChildElement("cms:category", CMS.CMS_XML_NS); Element el = parent.newChildElement("cms:category", CMS.CMS_XML_NS);
el.addAttribute("id", XML.format(cat.getID())); el.addAttribute("id", XML.format(cat.getID()));
el.addAttribute("name", cat.getName()); el.addAttribute("name", cat.getName());
el.addAttribute("description", cat.getDescription()); 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("isAbstract", cat.isAbstract() ? "1" : "0");
el.addAttribute("isEnabled", cat.isEnabled() ? "1" : "0"); el.addAttribute("isEnabled", cat.isEnabled() ? "1" : "0");
if (sortKey != null) { if (sortKey != null) {
@ -204,7 +264,8 @@ public class TermWidget extends Widget {
} }
// sort order attribute added to every node so that we can // sort order attribute added to every node so that we can
// correctly transform xml fragments returned by ajax // correctly transform xml fragments returned by ajax
el.addAttribute("order", ContentSection.getConfig().getCategoryTreeOrder()); el.addAttribute("order", ContentSection.getConfig()
.getCategoryTreeOrder());
el.addAttribute("genCat", "true"); el.addAttribute("genCat", "true");
StringBuilder path = new StringBuilder(parent.getAttribute("fullname")); StringBuilder path = new StringBuilder(parent.getAttribute("fullname"));
@ -230,9 +291,9 @@ public class TermWidget extends Widget {
} }
public static Element generateTerm(Element parent, public static Element generateTerm(Element parent,
Term term, Term term,
Set selected, Set selected,
BigDecimal sortKey) { BigDecimal sortKey) {
Category cat = term.getModel(); Category cat = term.getModel();
Element el = generateCategory(parent, cat, selected, sortKey); Element el = generateCategory(parent, cat, selected, sortKey);
@ -242,22 +303,23 @@ public class TermWidget extends Widget {
} }
private static void generateRootTerm(Element parent, private static void generateRootTerm(Element parent,
Term term, Term term,
Set selected, Set selected,
BigDecimal sortKey) { BigDecimal sortKey) {
Element el = generateTerm(parent, term, selected, sortKey); Element el = generateTerm(parent, term, selected, sortKey);
el.addAttribute("root", "1"); el.addAttribute("root", "1");
} }
public static void generateSubtree(Element parent, Category root, Set ids) { public static void generateSubtree(Element parent, Category root, Set ids) {
DataCollection terms = SessionManager.getSession().retrieve( 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.roTransParents.id", root.getID());
terms.addEqualsFilter("model.parents.link.relationType", "child"); terms.addEqualsFilter("model.parents.link.relationType", "child");
Map children = new HashMap(); Map children = new HashMap();
while (terms.next()) { 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"); BigDecimal parentID = (BigDecimal) terms.get("model.parents.id");
List childList = (List) children.get(parentID); List childList = (List) children.get(parentID);
@ -266,18 +328,20 @@ public class TermWidget extends Widget {
children.put(parentID, childList); 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); Element el = generateCategory(parent, root, ids, null);
el.addAttribute("fullname", root.getName()); el.addAttribute("fullname", root.getName());
el.addAttribute("node-id", root.getID().toString()); el.addAttribute("node-id", root.getID().toString());
el.addAttribute("order", ContentSection.getConfig().getCategoryTreeOrder()); el.addAttribute("order", ContentSection.getConfig()
if (Terms.getConfig().ajaxExpandAllBranches()) { .getCategoryTreeOrder());
if (Terms.getConfig().ajaxExpandAllBranches()) {
// recognisable attribute has to be in the XML for each snippet that is transformed, // recognisable attribute has to be in the XML for each snippet that is transformed,
// hence add it to the parent // hence add it to the parent
el.addAttribute("expand", "all" ); el.addAttribute("expand", "all");
} }
List roots = (List) children.get(root.getID()); List roots = (List) children.get(root.getID());
if (null != roots) { if (null != roots) {
@ -293,10 +357,10 @@ public class TermWidget extends Widget {
} }
private static void generateTermWithChildren(Element parent, private static void generateTermWithChildren(Element parent,
Term term, Term term,
Set selected, Set selected,
BigDecimal sortKey, BigDecimal sortKey,
Map children) { Map children) {
Category cat = term.getModel(); Category cat = term.getModel();
Element el = generateCategory(parent, cat, selected, sortKey); Element el = generateCategory(parent, cat, selected, sortKey);
@ -312,17 +376,14 @@ public class TermWidget extends Widget {
BigDecimal childSortKey = pair.getSortKey(); BigDecimal childSortKey = pair.getSortKey();
// either generate next level down, or get all levels below current // either generate next level down, or get all levels below current
if (Terms.getConfig().ajaxExpandAllBranches()) { if (Terms.getConfig().ajaxExpandAllBranches()) {
generateTerm(el, child, selected, childSortKey); generateTerm(el, child, selected, childSortKey);
} else { } else {
generateTermWithChildren(el, child, selected, childSortKey, generateTermWithChildren(el, child, selected, childSortKey,
children); children);
} }
} }
} }
} }
@ -344,5 +405,7 @@ public class TermWidget extends Widget {
public BigDecimal getSortKey() { public BigDecimal getSortKey() {
return m_sortKey; return m_sortKey;
} }
} }
} }