diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTab.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTab.java
index acea7ba64..adfbe458a 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTab.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTab.java
@@ -33,6 +33,8 @@ import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.toolbox.ui.LayoutPanel;
+import org.libreccm.categorization.Category;
+
import static com.arsdigita.ui.admin.AdminUiConstants.*;
/**
@@ -65,6 +67,13 @@ public class CategoriesTab extends LayoutPanel {
private final Label categoriesTreeHeader;
private final BoxPanel categoriesTreePanel;
+ private final CategoryDetails categoryDetails;
+ private final CategoryTitleForm categoryTitleForm;
+ private final CategoryDescriptionForm categoryDescriptionForm;
+ private final CategoryCreateForm categoryCreateForm;
+ private final CategoryEditForm categoryEditForm;
+ private final CategoryMover categoryMover;
+
public CategoriesTab() {
super();
@@ -72,29 +81,29 @@ public class CategoriesTab extends LayoutPanel {
domainIdParameter = new StringParameter("selected_domain_id");
selectedDomainId = new ParameterSingleSelectionModel<>(
- domainIdParameter);
+ domainIdParameter);
categoryIdParameter = new StringParameter("selected_category_id");
selectedCategoryId = new ParameterSingleSelectionModel<>(
- categoryIdParameter);
+ categoryIdParameter);
languageParameter = new StringParameter("selected_language");
selectedLanguage = new ParameterSingleSelectionModel<>(
- languageParameter);
+ languageParameter);
final SegmentedPanel left = new SegmentedPanel();
domainsFilterFormHeader = new Label(new GlobalizedMessage(
- "ui.admin.categories.domains.table.filter.header",
- ADMIN_BUNDLE));
+ "ui.admin.categories.domains.table.filter.header",
+ ADMIN_BUNDLE));
domainsFilterForm = new Form("domainFilterForm");
final TextField domainsFilter = new TextField(DOMAINS_FILTER);
domainsFilterForm.add(domainsFilter);
domainsFilterForm.add(new Submit(new GlobalizedMessage(
- "ui.admin.categories.domains.table.filter", ADMIN_BUNDLE)));
+ "ui.admin.categories.domains.table.filter", ADMIN_BUNDLE)));
final ActionLink clearLink = new ActionLink(new GlobalizedMessage(
- "ui.admin.categories.domains.table.filter.clear",
- ADMIN_BUNDLE));
+ "ui.admin.categories.domains.table.filter.clear",
+ ADMIN_BUNDLE));
clearLink.addActionListener(e -> {
final PageState state = e.getPageState();
domainsFilter.setValue(state, null);
@@ -103,17 +112,29 @@ public class CategoriesTab extends LayoutPanel {
left.addSegment(domainsFilterFormHeader, domainsFilterForm);
categoriesTreeHeader = new Label(new GlobalizedMessage(
- "ui.admin.categories.tree.header",
- ADMIN_BUNDLE));
+ "ui.admin.categories.tree.header",
+ ADMIN_BUNDLE));
categoriesTreePanel = new BoxPanel(BoxPanel.VERTICAL);
final Tree categoriesTree = new Tree(new CategoriesTreeModelBuilder(
- selectedDomainId));
- categoriesTree.addActionListener(e -> {
+ selectedDomainId));
+ categoriesTree.addChangeListener(e -> {
+ final PageState state = e.getPageState();
+ selectedCategoryId.setSelectedKey(
+ state, (String) categoriesTree.getSelectedKey(state));
+
+ showCategoryDetails(state);
});
+ selectedCategoryId.addChangeListener(e -> {
+ final PageState state = e.getPageState();
+
+ categoriesTree.setSelectedKey(state, selectedCategoryId
+ .getSelectedKey(state));
+ });
+
final ActionLink backToDomain = new ActionLink(new GlobalizedMessage(
- "ui.admin.categories.tree.back",
- ADMIN_BUNDLE));
+ "ui.admin.categories.tree.back",
+ ADMIN_BUNDLE));
backToDomain.addActionListener(e -> {
final PageState state = e.getPageState();
categoriesTree.getSelectionModel().clearSelection(state);
@@ -128,12 +149,12 @@ public class CategoriesTab extends LayoutPanel {
final BoxPanel body = new BoxPanel(BoxPanel.VERTICAL);
final DomainsTable domainsTable = new DomainsTable(
- this, selectedDomainId, domainsFilter);
+ this, selectedDomainId, domainsFilter);
domainsTable.setStyleAttr("min-width: 30em;");
domainsTablePanel = new BoxPanel(BoxPanel.VERTICAL);
domainsTablePanel.add(domainsTable);
final ActionLink addDomain = new ActionLink(new GlobalizedMessage(
- "ui.admin.categories.domains.create_new", ADMIN_BUNDLE));
+ "ui.admin.categories.domains.create_new", ADMIN_BUNDLE));
addDomain.addActionListener(e -> {
showDomainForm(e.getPageState());
});
@@ -159,6 +180,33 @@ public class CategoriesTab extends LayoutPanel {
selectedLanguage);
body.add(domainDescriptionForm);
+ categoryDetails = new CategoryDetails(this,
+ selectedDomainId,
+ selectedCategoryId,
+ selectedLanguage);
+ body.add(categoryDetails);
+
+ categoryTitleForm = new CategoryTitleForm(this,
+ selectedCategoryId,
+ selectedLanguage);
+ body.add(categoryTitleForm);
+
+ categoryDescriptionForm = new CategoryDescriptionForm(this,
+ selectedCategoryId,
+ selectedLanguage);
+ body.add(categoryDescriptionForm);
+
+ categoryCreateForm = new CategoryCreateForm(this, selectedCategoryId);
+ body.add(categoryCreateForm);
+
+ categoryEditForm = new CategoryEditForm(this, selectedCategoryId);
+ body.add(categoryEditForm);
+
+ categoryMover = new CategoryMover(this,
+ selectedDomainId,
+ selectedCategoryId);
+ body.add(categoryMover);
+
setBody(body);
}
@@ -178,8 +226,16 @@ public class CategoriesTab extends LayoutPanel {
page.setVisibleDefault(domainDetails, false);
page.setVisibleDefault(domainTitleForm, false);
page.setVisibleDefault(domainDescriptionForm, false);
+
page.setVisibleDefault(categoriesTreeHeader, false);
page.setVisibleDefault(categoriesTreePanel, false);
+
+ page.setVisibleDefault(categoryDetails, false);
+ page.setVisibleDefault(categoryTitleForm, false);
+ page.setVisibleDefault(categoryDescriptionForm, false);
+ page.setVisibleDefault(categoryCreateForm, false);
+ page.setVisibleDefault(categoryEditForm, false);
+ page.setVisibleDefault(categoryMover, false);
}
protected void showDomainsTable(final PageState state) {
@@ -190,9 +246,16 @@ public class CategoriesTab extends LayoutPanel {
domainDetails.setVisible(state, false);
domainTitleForm.setVisible(state, false);
domainDescriptionForm.setVisible(state, false);
+
categoriesTreeHeader.setVisible(state, false);
categoriesTreePanel.setVisible(state, false);
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, false);
}
protected void showDomainForm(final PageState state) {
@@ -203,8 +266,16 @@ public class CategoriesTab extends LayoutPanel {
domainDetails.setVisible(state, false);
domainTitleForm.setVisible(state, false);
domainDescriptionForm.setVisible(state, false);
+
categoriesTreeHeader.setVisible(state, false);
categoriesTreePanel.setVisible(state, false);
+
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, false);
}
protected void hideDomainForm(final PageState state) {
@@ -216,8 +287,16 @@ public class CategoriesTab extends LayoutPanel {
domainDetails.setVisible(state, false);
domainTitleForm.setVisible(state, false);
domainDescriptionForm.setVisible(state, false);
+
categoriesTreeHeader.setVisible(state, false);
categoriesTreePanel.setVisible(state, false);
+
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, false);
} else {
showDomainDetails(state);
}
@@ -232,8 +311,16 @@ public class CategoriesTab extends LayoutPanel {
domainDetails.setVisible(state, true);
domainTitleForm.setVisible(state, false);
domainDescriptionForm.setVisible(state, false);
+
categoriesTreeHeader.setVisible(state, true);
categoriesTreePanel.setVisible(state, true);
+
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, false);
}
protected void hideDomainDetails(final PageState state) {
@@ -246,8 +333,16 @@ public class CategoriesTab extends LayoutPanel {
domainDetails.setVisible(state, false);
domainTitleForm.setVisible(state, false);
domainDescriptionForm.setVisible(state, false);
+
categoriesTreeHeader.setVisible(state, false);
categoriesTreePanel.setVisible(state, false);
+
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, false);
}
protected void showDomainTitleForm(final PageState state) {
@@ -258,8 +353,16 @@ public class CategoriesTab extends LayoutPanel {
domainDetails.setVisible(state, false);
domainTitleForm.setVisible(state, true);
domainDescriptionForm.setVisible(state, false);
+
categoriesTreeHeader.setVisible(state, false);
categoriesTreePanel.setVisible(state, false);
+
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, false);
}
protected void hideDomainTitleForm(final PageState state) {
@@ -276,8 +379,16 @@ public class CategoriesTab extends LayoutPanel {
domainDetails.setVisible(state, false);
domainTitleForm.setVisible(state, false);
domainDescriptionForm.setVisible(state, true);
+
categoriesTreeHeader.setVisible(state, false);
categoriesTreePanel.setVisible(state, false);
+
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, false);
}
protected void hideDomainDescriptionForm(final PageState state) {
@@ -287,41 +398,157 @@ public class CategoriesTab extends LayoutPanel {
}
protected void showCategoryDetails(final PageState state) {
+ domainsFilterFormHeader.setVisible(state, false);
+ domainsFilterForm.setVisible(state, false);
+ domainsTablePanel.setVisible(state, false);
+ domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, false);
+ categoriesTreeHeader.setVisible(state, true);
+ categoriesTreePanel.setVisible(state, true);
+
+ categoryDetails.setVisible(state, true);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, false);
}
protected void hideCategoryDetails(final PageState state) {
+ selectedCategoryId.clearSelection(state);
+ showDomainDetails(state);
}
protected void showCategoryCreateForm(final PageState state) {
+ domainsFilterFormHeader.setVisible(state, false);
+ domainsFilterForm.setVisible(state, false);
+ domainsTablePanel.setVisible(state, false);
+ domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, false);
+ categoriesTreeHeader.setVisible(state, false);
+ categoriesTreePanel.setVisible(state, false);
+
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, true);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, false);
}
protected void hideCategoryCreateForm(final PageState state) {
-
+ //Show category details of new category (or the selected category if
+ //creation was canceled
+ showCategoryDetails(state);
}
protected void showCategoryEditForm(final PageState state) {
+ domainsFilterFormHeader.setVisible(state, false);
+ domainsFilterForm.setVisible(state, false);
+ domainsTablePanel.setVisible(state, false);
+ domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, false);
+ categoriesTreeHeader.setVisible(state, false);
+ categoriesTreePanel.setVisible(state, false);
+
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, true);
+ categoryMover.setVisible(state, false);
}
protected void hideCategoryEditForm(final PageState state) {
-
+ //We want to go back to the details of the selected category, therefore
+ //we don't reset the selection.
+ showCategoryDetails(state);
}
protected void showCategoryTitleForm(final PageState state) {
+ domainsFilterFormHeader.setVisible(state, false);
+ domainsFilterForm.setVisible(state, false);
+ domainsTablePanel.setVisible(state, false);
+ domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, false);
+ categoriesTreeHeader.setVisible(state, false);
+ categoriesTreePanel.setVisible(state, false);
+
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, true);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, false);
}
protected void hideCategoryTitleForm(final PageState state) {
+ selectedLanguage.clearSelection(state);
+ showCategoryDetails(state);
}
protected void showCategoryDescriptionForm(final PageState state) {
+ domainsFilterFormHeader.setVisible(state, false);
+ domainsFilterForm.setVisible(state, false);
+ domainsTablePanel.setVisible(state, false);
+ domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, false);
+ categoriesTreeHeader.setVisible(state, false);
+ categoriesTreePanel.setVisible(state, false);
+
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, true);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, false);
}
protected void hideCategoryDescriptionForm(final PageState state) {
+ selectedLanguage.clearSelection(state);
+
+ showCategoryDetails(state);
}
+
+ protected void showCategoryMover(final PageState state) {
+ domainsFilterFormHeader.setVisible(state, false);
+ domainsFilterForm.setVisible(state, false);
+ domainsTablePanel.setVisible(state, false);
+ domainForm.setVisible(state, false);
+ domainDetails.setVisible(state, false);
+ domainTitleForm.setVisible(state, false);
+ domainDescriptionForm.setVisible(state, false);
+
+ categoriesTreeHeader.setVisible(state, false);
+ categoriesTreePanel.setVisible(state, false);
+
+ categoryDetails.setVisible(state, false);
+ categoryTitleForm.setVisible(state, false);
+ categoryDescriptionForm.setVisible(state, false);
+ categoryCreateForm.setVisible(state, false);
+ categoryEditForm.setVisible(state, false);
+ categoryMover.setVisible(state, true);
+ }
+
+ protected void hideCategoryMover(final PageState state) {
+ showCategoryDetails(state);
+ }
+
}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTreeModel.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTreeModel.java
index 21a14a46d..684162924 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTreeModel.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoriesTreeModel.java
@@ -23,7 +23,9 @@ import com.arsdigita.bebop.tree.TreeModel;
import com.arsdigita.bebop.tree.TreeNode;
import org.libreccm.categorization.Category;
+import org.libreccm.categorization.CategoryRepository;
import org.libreccm.categorization.Domain;
+import org.libreccm.cdi.utils.CdiUtil;
import java.util.Iterator;
import java.util.List;
@@ -42,13 +44,20 @@ public class CategoriesTreeModel implements TreeModel {
@Override
public TreeNode getRoot(final PageState data) {
- return new CategoryTreeNode(domain.getRoot());
+ final CategoryRepository categoryRepository = CdiUtil.createCdiUtil()
+ .findBean(CategoryRepository.class);
+ final Category category = categoryRepository.findById(domain.getRoot()
+ .getObjectId());
+ return new CategoryTreeNode(category);
}
@Override
public boolean hasChildren(final TreeNode node,
final PageState state) {
- final Category category = ((CategoryTreeNode) node).getCategory();
+ final CategoryRepository categoryRepo = CdiUtil.createCdiUtil()
+ .findBean(CategoryRepository.class);
+ final Category category = categoryRepo.findById(
+ ((CategoryTreeNode) node).getCategory().getObjectId());
return (category.getSubCategories() != null
&& !category.getSubCategories().isEmpty());
@@ -57,8 +66,12 @@ public class CategoriesTreeModel implements TreeModel {
@Override
public Iterator getChildren(final TreeNode node,
final PageState state) {
- return new SubCategoryNodesIterator(((CategoryTreeNode) node)
- .getCategory().getSubCategories());
+ final CategoryRepository categoryRepo = CdiUtil.createCdiUtil()
+ .findBean(CategoryRepository.class);
+ final Category category = categoryRepo.findById(
+ ((CategoryTreeNode) node).getCategory().getObjectId());
+
+ return new SubCategoryNodesIterator(category.getSubCategories());
}
private class CategoryTreeNode implements TreeNode {
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryCreateForm.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryCreateForm.java
new file mode 100644
index 000000000..7a9b2e4e9
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryCreateForm.java
@@ -0,0 +1,131 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.globalization.GlobalizedMessage;
+
+import org.apache.logging.log4j.util.Strings;
+import org.libreccm.categorization.Category;
+import org.libreccm.categorization.CategoryManager;
+import org.libreccm.categorization.CategoryRepository;
+import org.libreccm.cdi.utils.CdiUtil;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class CategoryCreateForm extends Form {
+
+ private static final String CATEGORY_NAME = "categoryName";
+
+ private final ParameterSingleSelectionModel selectedCategoryId;
+
+ private final TextField categoryName;
+ private final SaveCancelSection saveCancelSection;
+
+ public CategoryCreateForm(
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedCategoryId) {
+
+ super("categoryCreateForm");
+
+ this.selectedCategoryId = selectedCategoryId;
+
+ final Label heading = new Label(e -> {
+ final PageState state = e.getPageState();
+ final Label target = (Label) e.getTarget();
+
+ final CategoryRepository categoryRepository = CdiUtil
+ .createCdiUtil().findBean(CategoryRepository.class);
+ final Category category = categoryRepository.findById(Long
+ .parseLong(selectedCategoryId.getSelectedKey(state)));
+ target.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.category.create_new_subcategory",
+ ADMIN_BUNDLE,
+ new String[]{category.getName()}));
+ });
+ heading.setClassAttr("heading");
+ add(heading);
+
+ categoryName = new TextField(CATEGORY_NAME);
+ categoryName.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.category.name.label", ADMIN_BUNDLE));
+ add(categoryName);
+
+ saveCancelSection = new SaveCancelSection();
+ add(saveCancelSection);
+
+ addValidationListener(e -> {
+ final PageState state = e.getPageState();
+
+ if (saveCancelSection.getSaveButton().isSelected(state)) {
+ final FormData data = e.getFormData();
+ final String categoryNameData = data.getString(CATEGORY_NAME);
+
+ if (Strings.isBlank(categoryNameData)) {
+ data.addError(
+ CATEGORY_NAME,
+ new GlobalizedMessage(
+ "ui.admin.categories.category.name.errors.not_blank",
+ ADMIN_BUNDLE));
+ }
+ }
+ });
+
+ addProcessListener(e -> {
+ final PageState state = e.getPageState();
+
+ if (saveCancelSection.getSaveButton().isSelected(state)) {
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final CategoryRepository categoryRepository = cdiUtil.findBean(
+ CategoryRepository.class);
+ final CategoryManager categoryManager = cdiUtil.findBean(
+ CategoryManager.class);
+
+ final Category selectedCategory = categoryRepository.findById(
+ Long.parseLong(selectedCategoryId.getSelectedKey(state)));
+
+ final FormData data = e.getFormData();
+ final String categoryNameData = data.getString(CATEGORY_NAME);
+
+ final Category category = new Category();
+ category.setName(categoryNameData);
+
+ categoryRepository.save(category);
+ categoryManager.addSubCategoryToCategory(category,
+ selectedCategory);
+
+ selectedCategoryId.setSelectedKey(
+ state, Long.toString(category.getObjectId()));
+ }
+
+ categoriesTab.hideCategoryCreateForm(state);
+ });
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDescriptionForm.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDescriptionForm.java
index 0339ab715..8b14da93d 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDescriptionForm.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDescriptionForm.java
@@ -30,11 +30,10 @@ import com.arsdigita.bebop.form.TextArea;
import com.arsdigita.globalization.GlobalizedMessage;
import java.util.Locale;
+
import org.apache.logging.log4j.util.Strings;
import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryRepository;
-import org.libreccm.categorization.Domain;
-import org.libreccm.categorization.DomainRepository;
import org.libreccm.cdi.utils.CdiUtil;
import static com.arsdigita.ui.admin.AdminUiConstants.*;
@@ -83,7 +82,7 @@ public class CategoryDescriptionForm extends Form {
final Label target = (Label) e.getTarget();
- if (selectedCategory.getTitle().hasValue(selectedLocale)) {
+ if (selectedCategory.getDescription().hasValue(selectedLocale)) {
target.setLabel(new GlobalizedMessage(
"ui.admin.categories.category.description.edit_for_lang",
ADMIN_BUNDLE,
@@ -102,7 +101,7 @@ public class CategoryDescriptionForm extends Form {
description = new TextArea(LOCALIZED_CATEGORY_DESC);
description.setLabel(new GlobalizedMessage(
- "ui.admin.categories.domain.description.label", ADMIN_BUNDLE));
+ "ui.admin.categories.category.description.label", ADMIN_BUNDLE));
description.setCols(60);
description.setRows(10);
add(description);
@@ -121,7 +120,7 @@ public class CategoryDescriptionForm extends Form {
final Locale selectedLocale = new Locale(selectedLanguage
.getSelectedKey(state));
- if (selectedCategory.getTitle().hasValue(selectedLocale)) {
+ if (selectedCategory.getDescription().hasValue(selectedLocale)) {
description.setValue(state, selectedCategory.getDescription()
.getValue(selectedLocale));
}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDescriptionTable.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDescriptionTable.java
index 2018a1c06..9351e11d0 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDescriptionTable.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDescriptionTable.java
@@ -59,9 +59,9 @@ public class CategoryDescriptionTable extends Table {
private final ParameterSingleSelectionModel selectedLanguage;
public CategoryDescriptionTable(
- final CategoriesTab categoriesTab,
- final ParameterSingleSelectionModel selectedCategoryId,
- final ParameterSingleSelectionModel selectedLanguage) {
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedCategoryId,
+ final ParameterSingleSelectionModel selectedLanguage) {
super();
@@ -72,30 +72,30 @@ public class CategoryDescriptionTable extends Table {
setIdAttr("categoryDescriptionTable");
setEmptyView(new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.description.none",
- ADMIN_BUNDLE)));
+ "ui.admin.categories.category_details.description.none",
+ ADMIN_BUNDLE)));
final TableColumnModel columnModel = getColumnModel();
columnModel.add(new TableColumn(
- COL_LOCALE,
- new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.description.col_lang",
- ADMIN_BUNDLE))));
+ COL_LOCALE,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.description.col_lang",
+ ADMIN_BUNDLE))));
columnModel.add(new TableColumn(
- COL_VALUE,
- new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.description.col_value",
- ADMIN_BUNDLE))));
+ COL_VALUE,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.description.col_value",
+ ADMIN_BUNDLE))));
columnModel.add(new TableColumn(
- COL_EDIT,
- new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.description.col_del",
- ADMIN_BUNDLE))));
+ COL_EDIT,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.description.col_edit",
+ ADMIN_BUNDLE))));
columnModel.add(new TableColumn(
- COL_DEL,
- new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.description.col_del",
- ADMIN_BUNDLE))));
+ COL_DEL,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.description.col_del",
+ ADMIN_BUNDLE))));
columnModel.get(COL_EDIT).setCellRenderer(new TableCellRenderer() {
@@ -109,6 +109,7 @@ public class CategoryDescriptionTable extends Table {
final int column) {
return new ControlLink((Component) value);
}
+
});
columnModel.get(COL_DEL).setCellRenderer(new TableCellRenderer() {
@@ -126,15 +127,17 @@ public class CategoryDescriptionTable extends Table {
} else {
final ControlLink link = new ControlLink((Component) value);
link.setConfirmation(new GlobalizedMessage(
- "ui.admin.categories.category_details.description"
- + ".del_confirm",
- ADMIN_BUNDLE));
+ "ui.admin.categories.category_details.description"
+ + ".del_confirm",
+ ADMIN_BUNDLE));
return link;
}
}
+
});
addTableActionListener(new TableActionListener() {
+
@Override
public void cellSelected(final TableActionEvent event) {
final PageState state = event.getPageState();
@@ -147,13 +150,13 @@ public class CategoryDescriptionTable extends Table {
break;
case COL_DEL:
final Locale locale = new Locale((String) event
- .getRowKey());
+ .getRowKey());
final CategoryRepository categoryRepository = CdiUtil.
- createCdiUtil().findBean(
- CategoryRepository.class);
+ createCdiUtil().findBean(
+ CategoryRepository.class);
final Category category = categoryRepository.findById(
- Long.parseLong(selectedCategoryId.
- getSelectedKey(state)));
+ Long.parseLong(selectedCategoryId.
+ getSelectedKey(state)));
category.getDescription().removeValue(locale);
categoryRepository.save(category);
@@ -166,14 +169,15 @@ public class CategoryDescriptionTable extends Table {
public void headSelected(final TableActionEvent event) {
//Nothing
}
+
});
setModelBuilder(new CategoryDescriptionTableModelBuilder());
}
private class CategoryDescriptionTableModelBuilder
- extends LockableImpl
- implements TableModelBuilder {
+ extends LockableImpl
+ implements TableModelBuilder {
@Override
public TableModel makeModel(final Table table,
@@ -182,6 +186,7 @@ public class CategoryDescriptionTable extends Table {
return new CategoryDescriptionTableModel(state);
}
+
}
private class CategoryDescriptionTableModel implements TableModel {
@@ -192,13 +197,15 @@ public class CategoryDescriptionTable extends Table {
public CategoryDescriptionTableModel(final PageState state) {
final CategoryRepository categoryRepository = CdiUtil.
- createCdiUtil().findBean(CategoryRepository.class);
+ createCdiUtil().findBean(CategoryRepository.class);
selectedCategory = categoryRepository.findById(Long.parseLong(
- selectedCategoryId.getSelectedKey(state)));
+ selectedCategoryId.getSelectedKey(state)));
locales = new ArrayList<>();
- locales.addAll(selectedCategory.getDescription().
- getAvailableLocales());
+ if (selectedCategory.getDescription() != null) {
+ locales.addAll(
+ selectedCategory.getDescription().getAvailableLocales());
+ }
locales.sort((l1, l2) -> {
return l1.toString().compareTo(l2.toString());
});
@@ -227,15 +234,15 @@ public class CategoryDescriptionTable extends Table {
return selectedCategory.getDescription().getValue(locale);
case COL_EDIT:
return new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.description.edit",
- ADMIN_BUNDLE));
+ "ui.admin.categories.category_details.description.edit",
+ ADMIN_BUNDLE));
case COL_DEL:
return new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.description.del",
- ADMIN_BUNDLE));
+ "ui.admin.categories.category_details.description.del",
+ ADMIN_BUNDLE));
default:
throw new IllegalArgumentException(
- "Not a valid column index");
+ "Not a valid column index");
}
}
@@ -245,4 +252,5 @@ public class CategoryDescriptionTable extends Table {
}
}
+
}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDetails.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDetails.java
index 3fc7d02a2..42974a20b 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDetails.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryDetails.java
@@ -55,12 +55,13 @@ class CategoryDetails extends SegmentedPanel {
private final ParameterSingleSelectionModel selectedLanguage;
private final CategoryTitleAddForm categoryTitleAddForm;
private final CategoryDescriptionAddForm categoryDescriptionAddForm;
+ private final SubCategoriesTable subCategoriesTable;
public CategoryDetails(
- final CategoriesTab categoriesTab,
- final ParameterSingleSelectionModel selectedDomainId,
- final ParameterSingleSelectionModel selectedCategoryId,
- final ParameterSingleSelectionModel selectedLanguage) {
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedDomainId,
+ final ParameterSingleSelectionModel selectedCategoryId,
+ final ParameterSingleSelectionModel selectedLanguage) {
this.categoriesTab = categoriesTab;
this.selectedDomainId = selectedDomainId;
@@ -68,43 +69,86 @@ class CategoryDetails extends SegmentedPanel {
this.selectedLanguage = selectedLanguage;
final ActionLink backLink = new ActionLink(new GlobalizedMessage(
- "ui.admin.categories.category_details.back", ADMIN_BUNDLE));
+ "ui.admin.categories.category_details.back", ADMIN_BUNDLE));
backLink.addActionListener(e -> {
final PageState state = e.getPageState();
categoriesTab.hideCategoryDetails(state);
});
addSegment("category-details-back", backLink);
+ final Label heading = new Label(e -> {
+ final PageState state = e.getPageState();
+ final Label target = (Label) e.getTarget();
+
+ final CategoryRepository categoryRepo = CdiUtil.createCdiUtil()
+ .findBean(CategoryRepository.class);
+ final Category category = categoryRepo.findById(Long.parseLong(
+ selectedCategoryId.getSelectedKey(state)));
+
+ target.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.category_details.heading",
+ ADMIN_BUNDLE,
+ new String[]{category.getName()}));
+
+ });
+ heading.setClassAttr("heading");
+ add(heading);
+
final BoxPanel propertiesPanel = new BoxPanel(BoxPanel.VERTICAL);
propertiesPanel.add(new PropertySheet(
- new CategoryPropertySheetModelBuilder(selectedCategoryId)));
+ new CategoryPropertySheetModelBuilder(selectedCategoryId)));
final ActionLink editBasicPropertiesLink = new ActionLink(
- new GlobalizedMessage(
- "ui.admin.categories.category_details.basic_properties.edit",
- ADMIN_BUNDLE));
+ new GlobalizedMessage(
+ "ui.admin.categories.category_details.basic_properties.edit",
+ ADMIN_BUNDLE));
editBasicPropertiesLink.addActionListener(e -> {
final PageState state = e.getPageState();
categoriesTab.showCategoryEditForm(state);
});
propertiesPanel.add(editBasicPropertiesLink);
+ final ActionLink moveLink = new ActionLink(new GlobalizedMessage(
+ "ui.admin.categories.category_details.move_category", ADMIN_BUNDLE)) {
+
+ @Override
+ public boolean isVisible(final PageState state) {
+ if (super.isVisible(state)) {
+ final CategoryRepository categoryRepo = CdiUtil
+ .createCdiUtil().findBean(CategoryRepository.class);
+ final Category category = categoryRepo.findById(Long
+ .parseLong(selectedCategoryId.getSelectedKey(state)));
+
+ //If the category has no parent category it is the root
+ //category of a domain and can't be moved
+ return category.getParentCategory() != null;
+ } else {
+ return false;
+ }
+ }
+
+ };
+ moveLink.addActionListener(e -> {
+ final PageState state = e.getPageState();
+ categoriesTab.showCategoryMover(state);
+ });
+ propertiesPanel.add(moveLink);
addSegment(
- new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.basic_properties",
- ADMIN_BUNDLE)),
- propertiesPanel
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.basic_properties",
+ ADMIN_BUNDLE)),
+ propertiesPanel
);
final BoxPanel titlesPanel = new BoxPanel(BoxPanel.VERTICAL);
titlesPanel.add(new CategoryTitleTable(categoriesTab,
- selectedDomainId,
+ selectedCategoryId,
selectedLanguage));
categoryTitleAddForm = new CategoryTitleAddForm();
titlesPanel.add(categoryTitleAddForm);
addSegment(
- new Label(new GlobalizedMessage(
- "ui.admin.categories.domain_details.domain_title",
- ADMIN_BUNDLE)),
- titlesPanel);
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.category_title",
+ ADMIN_BUNDLE)),
+ titlesPanel);
final BoxPanel descPanel = new BoxPanel(BoxPanel.VERTICAL);
descPanel.add(new CategoryDescriptionTable(categoriesTab,
@@ -113,10 +157,29 @@ class CategoryDetails extends SegmentedPanel {
categoryDescriptionAddForm = new CategoryDescriptionAddForm();
descPanel.add(categoryDescriptionAddForm);
addSegment(
- new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.description",
- ADMIN_BUNDLE)),
- descPanel);
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.description",
+ ADMIN_BUNDLE)),
+ descPanel);
+
+ final BoxPanel subCategoriesPanel = new BoxPanel(BoxPanel.VERTICAL);
+ subCategoriesTable = new SubCategoriesTable(categoriesTab,
+ selectedCategoryId);
+ subCategoriesPanel.add(subCategoriesTable);
+ final ActionLink addSubCategory = new ActionLink(new GlobalizedMessage(
+ "ui.admin.categories.category_details.subcategories.add",
+ ADMIN_BUNDLE));
+ addSubCategory.addActionListener(e -> {
+ final PageState state = e.getPageState();
+
+ categoriesTab.showCategoryCreateForm(state);
+ });
+ subCategoriesPanel.add(addSubCategory);
+ addSegment(
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.subcategories.header",
+ ADMIN_BUNDLE)),
+ subCategoriesPanel);
}
private class CategoryTitleAddForm extends Form {
@@ -127,22 +190,22 @@ class CategoryDetails extends SegmentedPanel {
super("categoryTitleAddForm", new BoxPanel(BoxPanel.HORIZONTAL));
final SingleSelect titleSelectLang = new SingleSelect(
- TITLE_SELECT_LANG);
+ TITLE_SELECT_LANG);
titleSelectLang.setLabel(new GlobalizedMessage(
- "ui.admin.categories.category_details.category_title.add.label",
- ADMIN_BUNDLE));
+ "ui.admin.categories.category_details.category_title.add.label",
+ ADMIN_BUNDLE));
try {
titleSelectLang.addPrintListener(e -> {
final PageState state = e.getPageState();
final CategoryRepository categoryRepository = CdiUtil.
- createCdiUtil().findBean(CategoryRepository.class);
+ createCdiUtil().findBean(CategoryRepository.class);
final Category category = categoryRepository.findById(
- Long.parseLong(selectedCategoryId.getSelectedKey(
- state)));
+ Long.parseLong(selectedCategoryId.getSelectedKey(
+ state)));
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Set supportedLanguages = kernelConfig.
- getSupportedLanguages();
+ getSupportedLanguages();
final Set assignedLanguages = new HashSet<>();
category.getTitle().getAvailableLocales().forEach(l -> {
assignedLanguages.add(l.toString());
@@ -164,8 +227,8 @@ class CategoryDetails extends SegmentedPanel {
add(titleSelectLang);
add(new Submit(new GlobalizedMessage(
- "ui.admin.categories.category_details.category_title.add.submit",
- ADMIN_BUNDLE)));
+ "ui.admin.categories.category_details.category_title.add.submit",
+ ADMIN_BUNDLE)));
addProcessListener(e -> {
final PageState state = e.getPageState();
@@ -182,13 +245,13 @@ class CategoryDetails extends SegmentedPanel {
public boolean isVisible(final PageState state) {
if (super.isVisible(state)) {
final CategoryRepository categoryRepository = CdiUtil.
- createCdiUtil().findBean(CategoryRepository.class);
+ createCdiUtil().findBean(CategoryRepository.class);
final Category category = categoryRepository.findById(
- Long.parseLong(selectedCategoryId.getSelectedKey(
- state)));
+ Long.parseLong(selectedCategoryId.getSelectedKey(
+ state)));
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Set supportedLanguages = kernelConfig.
- getSupportedLanguages();
+ getSupportedLanguages();
final Set assignedLanguages = new HashSet<>();
category.getTitle().getAvailableLocales().forEach(l -> {
assignedLanguages.add(l.toString());
@@ -201,6 +264,7 @@ class CategoryDetails extends SegmentedPanel {
return false;
}
}
+
}
private class CategoryDescriptionAddForm extends Form {
@@ -211,27 +275,27 @@ class CategoryDetails extends SegmentedPanel {
super("categoryAddDescLang", new BoxPanel(BoxPanel.HORIZONTAL));
final SingleSelect descSelectLang = new SingleSelect(
- DESC_SELECT_LANG);
+ DESC_SELECT_LANG);
descSelectLang.setLabel(new GlobalizedMessage(
- "ui.admin.categories.category_details.category_desc.add.label",
- ADMIN_BUNDLE));
+ "ui.admin.categories.category_details.category_desc.add.label",
+ ADMIN_BUNDLE));
try {
descSelectLang.addPrintListener(e -> {
final PageState state = e.getPageState();
final CategoryRepository categoryRepository = CdiUtil.
- createCdiUtil().findBean(CategoryRepository.class);
+ createCdiUtil().findBean(CategoryRepository.class);
final Category category = categoryRepository.findById(
- Long.parseLong(selectedCategoryId.getSelectedKey(
- state)));
+ Long.parseLong(selectedCategoryId.getSelectedKey(
+ state)));
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Set supportedLanguages = kernelConfig.
- getSupportedLanguages();
+ getSupportedLanguages();
final Set assignedLanguages = new HashSet<>();
category.getDescription().getAvailableLocales().forEach(
- l -> {
- assignedLanguages.add(l.toString());
- });
+ l -> {
+ assignedLanguages.add(l.toString());
+ });
final SingleSelect target = (SingleSelect) e.getTarget();
@@ -250,8 +314,8 @@ class CategoryDetails extends SegmentedPanel {
add(descSelectLang);
add(new Submit(new GlobalizedMessage(
- "ui.admin.categories.category_details.category_desc.add.submit",
- ADMIN_BUNDLE)));
+ "ui.admin.categories.category_details.category_desc.add.submit",
+ ADMIN_BUNDLE)));
addProcessListener(e -> {
final PageState state = e.getPageState();
@@ -268,18 +332,18 @@ class CategoryDetails extends SegmentedPanel {
public boolean isVisible(final PageState state) {
if (super.isVisible(state)) {
final CategoryRepository categoryRepository = CdiUtil.
- createCdiUtil().findBean(CategoryRepository.class);
+ createCdiUtil().findBean(CategoryRepository.class);
final Category category = categoryRepository.findById(
- Long.parseLong(selectedCategoryId.getSelectedKey(
- state)));
+ Long.parseLong(selectedCategoryId.getSelectedKey(
+ state)));
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Set supportedLanguages = kernelConfig.
- getSupportedLanguages();
+ getSupportedLanguages();
final Set assignedLanguages = new HashSet<>();
category.getDescription().getAvailableLocales().forEach(
- l -> {
- assignedLanguages.add(l.toString());
- });
+ l -> {
+ assignedLanguages.add(l.toString());
+ });
//If all supported languages are assigned the form is not
//visible
@@ -288,6 +352,7 @@ class CategoryDetails extends SegmentedPanel {
return false;
}
}
+
}
}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryEditForm.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryEditForm.java
new file mode 100644
index 000000000..8bec85dc8
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryEditForm.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.FormData;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.form.CheckboxGroup;
+import com.arsdigita.bebop.form.Option;
+import com.arsdigita.bebop.form.TextField;
+import com.arsdigita.globalization.GlobalizedMessage;
+
+import org.apache.logging.log4j.util.Strings;
+import org.libreccm.categorization.Category;
+import org.libreccm.categorization.CategoryManager;
+import org.libreccm.categorization.CategoryRepository;
+import org.libreccm.cdi.utils.CdiUtil;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class CategoryEditForm extends Form {
+
+ private static final String CATEGORY_NAME = "categoryName";
+ private static final String CATEGORY_PROPERTIES = "categoryProperties";
+
+ private static final String ENABLED = "enabled";
+ private static final String VISIBLE = "visible";
+ private static final String ABSTRACT = "abstract";
+
+ private final ParameterSingleSelectionModel selectedCategoryId;
+
+ private final TextField categoryName;
+ private final CheckboxGroup properties;
+ private final SaveCancelSection saveCancelSection;
+
+ public CategoryEditForm(
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedCategoryId) {
+
+ super("categoryEditForm");
+
+ this.selectedCategoryId = selectedCategoryId;
+
+ final Label heading = new Label(e -> {
+ final PageState state = e.getPageState();
+ final Label target = (Label) e.getTarget();
+
+ final CategoryRepository categoryRepository = CdiUtil
+ .createCdiUtil().findBean(CategoryRepository.class);
+ final Category category = categoryRepository.findById(Long
+ .parseLong(selectedCategoryId.getSelectedKey(state)));
+ target.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.category.edit_category",
+ ADMIN_BUNDLE,
+ new String[]{category.getName()}));
+ });
+ heading.setClassAttr("heading");
+ add(heading);
+
+ categoryName = new TextField(CATEGORY_NAME);
+ categoryName.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.category.name.label", ADMIN_BUNDLE));
+ add(categoryName);
+
+ properties = new CheckboxGroup(CATEGORY_PROPERTIES);
+ properties.addOption(new Option(
+ ENABLED,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.name.enabled",
+ ADMIN_BUNDLE))));
+ properties.addOption(new Option(
+ VISIBLE,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.name.visible",
+ ADMIN_BUNDLE))));
+ properties.addOption(new Option(
+ ABSTRACT,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.name.abstract",
+ ADMIN_BUNDLE))));
+ add(properties);
+
+ saveCancelSection = new SaveCancelSection();
+ add(saveCancelSection);
+
+ addInitListener(e -> {
+ final PageState state = e.getPageState();
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final CategoryRepository categoryRepository = cdiUtil.findBean(
+ CategoryRepository.class);
+ final Category category = categoryRepository.findById(Long
+ .parseLong(selectedCategoryId.getSelectedKey(state)));
+
+ categoryName.setValue(state, category.getName());
+ final List props = new ArrayList<>();
+ if (category.isEnabled()) {
+ props.add(ENABLED);
+ }
+ if (category.isVisible()) {
+ props.add(VISIBLE);
+ }
+ if (category.isAbstractCategory()) {
+ props.add(ABSTRACT);
+ }
+ properties.setValue(state, props.toArray(new String[props.size()]));
+ });
+
+ addValidationListener(e -> {
+ final PageState state = e.getPageState();
+
+ if (saveCancelSection.getSaveButton().isSelected(state)) {
+ final FormData data = e.getFormData();
+ final String categoryNameData = data.getString(CATEGORY_NAME);
+
+ if (Strings.isBlank(categoryNameData)) {
+ data.addError(
+ CATEGORY_NAME,
+ new GlobalizedMessage(
+ "ui.admin.categories.category.name.errors.not_blank",
+ ADMIN_BUNDLE));
+ }
+ }
+ });
+
+ addProcessListener(e -> {
+ final PageState state = e.getPageState();
+
+ if (saveCancelSection.getSaveButton().isSelected(state)) {
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final CategoryRepository categoryRepository = cdiUtil.findBean(
+ CategoryRepository.class);
+ final CategoryManager categoryManager = cdiUtil.findBean(
+ CategoryManager.class);
+
+ final Category category = categoryRepository.findById(
+ Long.parseLong(selectedCategoryId.getSelectedKey(state)));
+
+ final FormData data = e.getFormData();
+ final String categoryNameData = data.getString(CATEGORY_NAME);
+
+ category.setName(categoryNameData);
+
+ final List propertiesData = Arrays.asList((String[]) data.get(
+ CATEGORY_PROPERTIES));
+ category.setEnabled(propertiesData.contains(ENABLED));
+ category.setVisible(propertiesData.contains(VISIBLE));
+ category.setAbstractCategory(propertiesData.contains(ABSTRACT));
+
+ categoryRepository.save(category);
+ }
+
+ categoriesTab.hideCategoryEditForm(state);
+ });
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryMover.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryMover.java
new file mode 100644
index 000000000..26e53790b
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryMover.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.BoxPanel;
+import com.arsdigita.bebop.Form;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.SaveCancelSection;
+import com.arsdigita.bebop.Tree;
+import com.arsdigita.globalization.GlobalizedMessage;
+
+import org.libreccm.categorization.Category;
+import org.libreccm.categorization.CategoryManager;
+import org.libreccm.categorization.CategoryRepository;
+import org.libreccm.cdi.utils.CdiUtil;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class CategoryMover extends Form {
+
+ private final CategoriesTab categoriesTab;
+ private final ParameterSingleSelectionModel selectedDomainId;
+ private final ParameterSingleSelectionModel selectedCategoryId;
+
+ private final Tree categoryTree;
+ private final SaveCancelSection saveCancelSection;
+
+ public CategoryMover(
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedDomainId,
+ final ParameterSingleSelectionModel selectedCategoryId) {
+
+ super("categoryMover", new BoxPanel(BoxPanel.VERTICAL));
+
+ this.categoriesTab = categoriesTab;
+ this.selectedDomainId = selectedDomainId;
+ this.selectedCategoryId = selectedCategoryId;
+
+ final Label heading = new Label(e -> {
+ final PageState state = e.getPageState();
+ final Label target = (Label) e.getTarget();
+
+ final CategoryRepository categoryRepo = CdiUtil
+ .createCdiUtil().findBean(CategoryRepository.class);
+ final Category category = categoryRepo.findById(Long.parseLong(
+ selectedCategoryId.getSelectedKey(state)));
+
+ target.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.category.move.heading",
+ ADMIN_BUNDLE,
+ new String[]{category.getName()}));
+ });
+ heading.setClassAttr("heading");
+ add(heading);
+
+ categoryTree = new Tree(new CategoryMoverModelBuilder(
+ selectedDomainId, selectedCategoryId));
+ add(categoryTree);
+
+ saveCancelSection = new SaveCancelSection();
+ add(saveCancelSection);
+
+ addProcessListener(e -> {
+ final PageState state = e.getPageState();
+
+ if (saveCancelSection.getSaveButton().isSelected(state)) {
+
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final CategoryRepository categoryRepo = cdiUtil.findBean(
+ CategoryRepository.class);
+ final CategoryManager categoryManager = cdiUtil.findBean(
+ CategoryManager.class);
+
+ final Category category = categoryRepo.findById(Long.parseLong(
+ selectedCategoryId.getSelectedKey(state)));
+ final Category parent = category.getParentCategory();
+ final Category target = categoryRepo.findById(Long.parseLong(
+ (String) categoryTree.getSelectedKey(state)));
+
+ categoryManager.removeSubCategoryFromCategory(category, parent);
+ categoryManager.addSubCategoryToCategory(category, target);
+ }
+
+ categoriesTab.hideCategoryMover(state);
+ });
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryMoverModel.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryMoverModel.java
new file mode 100644
index 000000000..4c9d64bce
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryMoverModel.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.tree.TreeModel;
+import com.arsdigita.bebop.tree.TreeNode;
+
+import org.libreccm.categorization.Category;
+import org.libreccm.categorization.CategoryRepository;
+import org.libreccm.categorization.Domain;
+import org.libreccm.cdi.utils.CdiUtil;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class CategoryMoverModel implements TreeModel {
+
+ private final Domain domain;
+ private final Category selectedCategory;
+
+ public CategoryMoverModel(final Domain domain,
+ final Category selectedCategory) {
+ this.domain = domain;
+ this.selectedCategory = selectedCategory;
+ }
+
+ @Override
+ public TreeNode getRoot(final PageState data) {
+ final CategoryRepository categoryRepository = CdiUtil.createCdiUtil()
+ .findBean(CategoryRepository.class);
+ final Category category = categoryRepository.findById(domain.getRoot()
+ .getObjectId());
+ return new CategoryMoverNode(category);
+ }
+
+ /**
+ * Creates a list of the sub categories of the provided node
+ * without
+ * the selected category. This prevents the selected category and its sub
+ * categories from be added to tree. Therefore the user can't move a
+ * category beneath itself.
+ *
+ * @param node The current node.
+ *
+ * @return A list of the subcategories of the category managed by the
+ * provided node.
+ */
+ private List getSubCategories(final TreeNode node) {
+ final CategoryRepository categoryRepo = CdiUtil.createCdiUtil()
+ .findBean(CategoryRepository.class);
+ final Category category = categoryRepo.findById(
+ ((CategoryMoverNode) node).getCategory().getObjectId());
+
+ final List subCategories = new ArrayList<>();
+ category.getSubCategories().forEach(c -> {
+ if (!c.equals(selectedCategory)) {
+ subCategories.add(c);
+ }
+ });
+
+ return subCategories;
+ }
+
+ @Override
+ public boolean hasChildren(final TreeNode node, final PageState state) {
+ final List subCategories = getSubCategories(node);
+ return (subCategories != null && !subCategories.isEmpty()) ;
+ }
+
+ @Override
+ public Iterator getChildren(final TreeNode node, final PageState state) {
+ return new SubCategoryNodesIterator(getSubCategories(node));
+ }
+
+ private class CategoryMoverNode implements TreeNode {
+
+ private final Category category;
+
+ public CategoryMoverNode(final Category category) {
+ this.category = category;
+ }
+
+ public Category getCategory() {
+ return category;
+ }
+
+ @Override
+ public Object getKey() {
+ return Long.toString(category.getObjectId());
+ }
+
+ @Override
+ public Object getElement() {
+ return category.getName();
+ }
+
+ }
+
+ private class SubCategoryNodesIterator
+ implements Iterator {
+
+ private final Iterator subCategoriesIterator;
+
+ public SubCategoryNodesIterator(final List subCategories) {
+ subCategoriesIterator = subCategories.iterator();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return subCategoriesIterator.hasNext();
+ }
+
+ @Override
+ public CategoryMoverNode next() {
+ return new CategoryMoverNode(subCategoriesIterator.next());
+ }
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryMoverModelBuilder.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryMoverModelBuilder.java
new file mode 100644
index 000000000..0bde20f24
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryMoverModelBuilder.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.Tree;
+import com.arsdigita.bebop.tree.TreeModel;
+import com.arsdigita.bebop.tree.TreeModelBuilder;
+import com.arsdigita.util.LockableImpl;
+
+import org.libreccm.categorization.Category;
+import org.libreccm.categorization.CategoryRepository;
+import org.libreccm.categorization.Domain;
+import org.libreccm.categorization.DomainRepository;
+import org.libreccm.cdi.utils.CdiUtil;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class CategoryMoverModelBuilder
+ extends LockableImpl
+ implements TreeModelBuilder {
+
+ private final ParameterSingleSelectionModel selectedDomainId;
+ private final ParameterSingleSelectionModel selectedCategoryId;
+
+ public CategoryMoverModelBuilder(
+ final ParameterSingleSelectionModel selectedDomainId,
+ final ParameterSingleSelectionModel selectedCategoryId) {
+
+ this.selectedDomainId = selectedDomainId;
+ this.selectedCategoryId = selectedCategoryId;
+
+ }
+
+ @Override
+ public TreeModel makeModel(final Tree tree, final PageState state) {
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+
+ final DomainRepository domainRepository = cdiUtil.findBean(
+ DomainRepository.class);
+ final Domain domain = domainRepository.findById(Long.parseLong(
+ selectedDomainId.getSelectedKey(state)));
+
+ final CategoryRepository categoryRepository = cdiUtil.findBean(
+ CategoryRepository.class);
+ final Category category = categoryRepository.findById(Long.parseLong(
+ selectedCategoryId.getSelectedKey(state)));
+
+ return new CategoryMoverModel(domain, category);
+ }
+
+}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryPropertySheetModel.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryPropertySheetModel.java
index 3541776d7..302ead517 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryPropertySheetModel.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryPropertySheetModel.java
@@ -33,7 +33,10 @@ import static com.arsdigita.ui.admin.AdminUiConstants.*;
public class CategoryPropertySheetModel implements PropertySheetModel {
private static enum CategoryProperty {
- NAME
+ NAME,
+ ENABLED,
+ VISIBLE,
+ ABSTRACT
}
private final Category selectedCategory;
@@ -84,9 +87,15 @@ public class CategoryPropertySheetModel implements PropertySheetModel {
switch (currentProperty) {
case NAME:
return selectedCategory.getName();
+ case ENABLED:
+ return Boolean.toString(selectedCategory.isEnabled());
+ case VISIBLE:
+ return Boolean.toString(selectedCategory.isVisible());
+ case ABSTRACT:
+ return Boolean.toString(selectedCategory.isAbstractCategory());
default:
return "";
}
}
-
+
}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryTitleTable.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryTitleTable.java
index 8cd2a4359..b97b12e02 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryTitleTable.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/CategoryTitleTable.java
@@ -59,9 +59,9 @@ public class CategoryTitleTable extends Table {
private final ParameterSingleSelectionModel selectedLanguage;
public CategoryTitleTable(
- final CategoriesTab categoriesTab,
- final ParameterSingleSelectionModel selectedCategoryId,
- final ParameterSingleSelectionModel selectedLanguage) {
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedCategoryId,
+ final ParameterSingleSelectionModel selectedLanguage) {
super();
@@ -72,29 +72,29 @@ public class CategoryTitleTable extends Table {
setIdAttr("categoryTitleTable");
setEmptyView(new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.title.none", ADMIN_BUNDLE)));
+ "ui.admin.categories.category_details.title.none", ADMIN_BUNDLE)));
final TableColumnModel columnModel = getColumnModel();
columnModel.add(new TableColumn(
- COL_LOCALE,
- new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.title.col_lang",
- ADMIN_BUNDLE))));
+ COL_LOCALE,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.title.col_lang",
+ ADMIN_BUNDLE))));
columnModel.add(new TableColumn(
- COL_VALUE,
- new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.title.col_value",
- ADMIN_BUNDLE))));
+ COL_VALUE,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.title.col_value",
+ ADMIN_BUNDLE))));
columnModel.add(new TableColumn(
- COL_EDIT,
- new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.title.col_edit",
- ADMIN_BUNDLE))));
+ COL_EDIT,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.title.col_edit",
+ ADMIN_BUNDLE))));
columnModel.add(new TableColumn(
- COL_DEL,
- new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.title.col_del",
- ADMIN_BUNDLE))));
+ COL_DEL,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category_details.title.col_del",
+ ADMIN_BUNDLE))));
columnModel.get(COL_EDIT).setCellRenderer(new TableCellRenderer() {
@@ -126,14 +126,16 @@ public class CategoryTitleTable extends Table {
} else {
final ControlLink link = new ControlLink((Component) value);
link.setConfirmation(new GlobalizedMessage(
- "ui.admin.categories.category_details.title.del_confirm",
- ADMIN_BUNDLE));
+ "ui.admin.categories.category_details.title.del_confirm",
+ ADMIN_BUNDLE));
return link;
}
}
+
});
addTableActionListener(new TableActionListener() {
+
@Override
public void cellSelected(final TableActionEvent event) {
final PageState state = event.getPageState();
@@ -146,13 +148,13 @@ public class CategoryTitleTable extends Table {
break;
case COL_DEL:
final Locale locale = new Locale((String) event.
- getRowKey());
+ getRowKey());
final CategoryRepository categoryRepository = CdiUtil.
- createCdiUtil().findBean(
- CategoryRepository.class);
+ createCdiUtil().findBean(
+ CategoryRepository.class);
final Category category = categoryRepository.findById(
- Long.parseLong(selectedCategoryId.
- getSelectedKey(state)));
+ Long.parseLong(selectedCategoryId.
+ getSelectedKey(state)));
category.getTitle().removeValue(locale);
categoryRepository.save(category);
@@ -165,6 +167,7 @@ public class CategoryTitleTable extends Table {
public void headSelected(final TableActionEvent event) {
//Nothing
}
+
});
setModelBuilder(new CategoryTitleTableModelBuilder());
@@ -172,12 +175,11 @@ public class CategoryTitleTable extends Table {
}
private class CategoryTitleTableModelBuilder
- extends LockableImpl
- implements TableModelBuilder {
+ extends LockableImpl
+ implements TableModelBuilder {
@Override
- public TableModel makeModel(final Table table,
- final PageState state) {
+ public TableModel makeModel(final Table table, final PageState state) {
table.getRowSelectionModel().clearSelection(state);
return new CategoryTitleTableModel(state);
@@ -193,12 +195,15 @@ public class CategoryTitleTable extends Table {
public CategoryTitleTableModel(final PageState state) {
final CategoryRepository categoryRepository = CdiUtil.
- createCdiUtil().findBean(CategoryRepository.class);
+ createCdiUtil().findBean(CategoryRepository.class);
selectedCategory = categoryRepository.findById(Long.parseLong(
- selectedCategoryId.getSelectedKey(state)));
+ selectedCategoryId.getSelectedKey(state)));
locales = new ArrayList<>();
- locales.addAll(selectedCategory.getTitle().getAvailableLocales());
+ if (selectedCategory.getTitle() != null) {
+ locales.addAll(
+ selectedCategory.getTitle().getAvailableLocales());
+ }
locales.sort((l1, l2) -> {
return l1.toString().compareTo(l2.toString());
});
@@ -226,17 +231,17 @@ public class CategoryTitleTable extends Table {
return selectedCategory.getTitle().getValue(locale);
case COL_EDIT:
return new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.title.edit",
- ADMIN_BUNDLE
+ "ui.admin.categories.category_details.title.edit",
+ ADMIN_BUNDLE
));
case COL_DEL:
return new Label(new GlobalizedMessage(
- "ui.admin.categories.category_details.title.del",
- ADMIN_BUNDLE
+ "ui.admin.categories.category_details.title.del",
+ ADMIN_BUNDLE
));
default:
throw new IllegalArgumentException(
- "Not a valid column index");
+ "Not a valid column index");
}
}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDescriptionTable.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDescriptionTable.java
index 2e8accaa5..b14301a5c 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDescriptionTable.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDescriptionTable.java
@@ -91,7 +91,7 @@ class DomainDescriptionTable extends Table {
columnModel.add(new TableColumn(
COL_EDIT,
new Label(new GlobalizedMessage(
- "ui.admin.categories.domain_details.description.col_del",
+ "ui.admin.categories.domain_details.description.col_edit",
ADMIN_BUNDLE))));
columnModel.add(new TableColumn(
COL_DEL,
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDetails.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDetails.java
index eeac4b853..364595278 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDetails.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainDetails.java
@@ -58,39 +58,56 @@ class DomainDetails extends SegmentedPanel {
private final DomainDescriptionAddForm domainDescriptionAddForm;
public DomainDetails(
- final CategoriesTab categoriesTab,
- final ParameterSingleSelectionModel selectedDomainId,
- final ParameterSingleSelectionModel selectedLanguage) {
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedDomainId,
+ final ParameterSingleSelectionModel selectedLanguage) {
this.categoriesTab = categoriesTab;
this.selectedDomainId = selectedDomainId;
this.selectedLanguage = selectedLanguage;
final ActionLink backLink = new ActionLink(new GlobalizedMessage(
- "ui.admin.categories.domain_details.back", ADMIN_BUNDLE));
+ "ui.admin.categories.domain_details.back", ADMIN_BUNDLE));
backLink.addActionListener(e -> {
final PageState state = e.getPageState();
categoriesTab.hideDomainDetails(state);
});
addSegment("domain-details-back", backLink);
+ final Label heading = new Label(e -> {
+ final PageState state = e.getPageState();
+ final Label target = (Label) e.getTarget();
+
+ final DomainRepository domainRepository = CdiUtil.createCdiUtil()
+ .findBean(DomainRepository.class);
+ final Domain domain = domainRepository.findById(Long.parseLong(
+ selectedDomainId.getSelectedKey(state)));
+
+ target.setLabel(new GlobalizedMessage(
+ "ui.admin.categories.domain.details.heading",
+ ADMIN_BUNDLE,
+ new String[]{domain.getDomainKey()}));
+ });
+ heading.setClassAttr("heading");
+ add(heading);
+
final BoxPanel propertiesPanel = new BoxPanel(BoxPanel.VERTICAL);
propertiesPanel.add(new PropertySheet(
- new DomainPropertySheetModelBuilder(selectedDomainId)));
+ new DomainPropertySheetModelBuilder(selectedDomainId)));
final ActionLink editBasicPropertiesLink = new ActionLink(
- new GlobalizedMessage(
- "ui.admin.categories.domain_details.basic_properties.edit",
- ADMIN_BUNDLE));
+ new GlobalizedMessage(
+ "ui.admin.categories.domain_details.basic_properties.edit",
+ ADMIN_BUNDLE));
editBasicPropertiesLink.addActionListener(e -> {
final PageState state = e.getPageState();
categoriesTab.showDomainForm(state);
});
propertiesPanel.add(editBasicPropertiesLink);
addSegment(
- new Label(new GlobalizedMessage(
- "ui.admin.categories.domain_details.basic_properties",
- ADMIN_BUNDLE)),
- propertiesPanel);
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.basic_properties",
+ ADMIN_BUNDLE)),
+ propertiesPanel);
final BoxPanel titlesPanel = new BoxPanel(BoxPanel.VERTICAL);
titlesPanel.add(new DomainTitleTable(categoriesTab,
@@ -99,10 +116,10 @@ class DomainDetails extends SegmentedPanel {
domainTitleAddForm = new DomainTitleAddForm();
titlesPanel.add(domainTitleAddForm);
addSegment(
- new Label(new GlobalizedMessage(
- "ui.admin.categories.domain_details.domain_title",
- ADMIN_BUNDLE)),
- titlesPanel);
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.domain_title",
+ ADMIN_BUNDLE)),
+ titlesPanel);
final BoxPanel descPanel = new BoxPanel(BoxPanel.VERTICAL);
descPanel.add(new DomainDescriptionTable(categoriesTab,
@@ -111,20 +128,20 @@ class DomainDetails extends SegmentedPanel {
domainDescriptionAddForm = new DomainDescriptionAddForm();
descPanel.add(domainDescriptionAddForm);
addSegment(
- new Label(new GlobalizedMessage(
- "ui.admin.categories.domain_details.description",
- ADMIN_BUNDLE)),
- descPanel);
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.description",
+ ADMIN_BUNDLE)),
+ descPanel);
final BoxPanel mappingsPanel = new BoxPanel(BoxPanel.VERTICAL);
mappingsPanel.add(new DomainMappingsTable(categoriesTab,
selectedDomainId));
mappingsPanel.add(new DomainMappingAddForm(selectedDomainId));
addSegment(
- new Label(new GlobalizedMessage(
- "ui.admin.categories.domain_details.mappings",
- ADMIN_BUNDLE)),
- mappingsPanel);
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.domain_details.mappings",
+ ADMIN_BUNDLE)),
+ mappingsPanel);
}
private class DomainTitleAddForm extends Form {
@@ -135,21 +152,21 @@ class DomainDetails extends SegmentedPanel {
super("domainAddTitleLang", new BoxPanel(BoxPanel.HORIZONTAL));
final SingleSelect titleSelectLang = new SingleSelect(
- TITLE_SELECT_LANG);
+ TITLE_SELECT_LANG);
titleSelectLang.setLabel(new GlobalizedMessage(
- "ui.admin.categories.domain_details.domain_title.add.label",
- ADMIN_BUNDLE));
+ "ui.admin.categories.domain_details.domain_title.add.label",
+ ADMIN_BUNDLE));
try {
titleSelectLang.addPrintListener(e -> {
final PageState state = e.getPageState();
final DomainRepository domainRepository = CdiUtil
- .createCdiUtil().findBean(DomainRepository.class);
+ .createCdiUtil().findBean(DomainRepository.class);
final Domain domain = domainRepository.findById(Long
- .parseLong(selectedDomainId.getSelectedKey(state)));
+ .parseLong(selectedDomainId.getSelectedKey(state)));
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Set supportedLanguages = kernelConfig
- .getSupportedLanguages();
+ .getSupportedLanguages();
final Set assignedLanguages = new HashSet<>();
domain.getTitle().getAvailableLocales().forEach(l -> {
assignedLanguages.add(l.toString());
@@ -171,8 +188,8 @@ class DomainDetails extends SegmentedPanel {
add(titleSelectLang);
add(new Submit(new GlobalizedMessage(
- "ui.admin.categories.domain_details.domain_title.add.submit",
- ADMIN_BUNDLE)));
+ "ui.admin.categories.domain_details.domain_title.add.submit",
+ ADMIN_BUNDLE)));
addProcessListener(e -> {
final PageState state = e.getPageState();
@@ -189,13 +206,13 @@ class DomainDetails extends SegmentedPanel {
public boolean isVisible(final PageState state) {
if (super.isVisible(state)) {
final DomainRepository domainRepository = CdiUtil
- .createCdiUtil().findBean(DomainRepository.class);
+ .createCdiUtil().findBean(DomainRepository.class);
final Domain domain = domainRepository.findById(Long
- .parseLong(
- selectedDomainId.getSelectedKey(state)));
+ .parseLong(
+ selectedDomainId.getSelectedKey(state)));
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Set supportedLanguages = kernelConfig
- .getSupportedLanguages();
+ .getSupportedLanguages();
final Set assignedLanguages = new HashSet<>();
domain.getTitle().getAvailableLocales().forEach(l -> {
assignedLanguages.add(l.toString());
@@ -219,22 +236,22 @@ class DomainDetails extends SegmentedPanel {
super("domainAddDescLang", new BoxPanel(BoxPanel.HORIZONTAL));
final SingleSelect descSelectLang = new SingleSelect(
- DESC_SELECT_LANG);
+ DESC_SELECT_LANG);
descSelectLang.setLabel(new GlobalizedMessage(
- "ui.admin.categories.domain_details.domain_desc.add.label",
- ADMIN_BUNDLE));
+ "ui.admin.categories.domain_details.domain_desc.add.label",
+ ADMIN_BUNDLE));
try {
descSelectLang.addPrintListener(e -> {
final PageState state = e.getPageState();
final DomainRepository domainRepository = CdiUtil
- .createCdiUtil().findBean(DomainRepository.class);
+ .createCdiUtil().findBean(DomainRepository.class);
final Domain domain = domainRepository.findById(Long
- .parseLong(
- selectedDomainId.getSelectedKey(state)));
+ .parseLong(
+ selectedDomainId.getSelectedKey(state)));
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Set supportedLanguages = kernelConfig
- .getSupportedLanguages();
+ .getSupportedLanguages();
final Set assignedLanguages = new HashSet<>();
domain.getDescription().getAvailableLocales().forEach(l -> {
assignedLanguages.add(l.toString());
@@ -256,8 +273,8 @@ class DomainDetails extends SegmentedPanel {
add(descSelectLang);
add(new Submit(new GlobalizedMessage(
- "ui.admin.categories.domain_details.domain_desc.add.submit",
- ADMIN_BUNDLE)));
+ "ui.admin.categories.domain_details.domain_desc.add.submit",
+ ADMIN_BUNDLE)));
addProcessListener(e -> {
final PageState state = e.getPageState();
@@ -275,13 +292,13 @@ class DomainDetails extends SegmentedPanel {
public boolean isVisible(final PageState state) {
if (super.isVisible(state)) {
final DomainRepository domainRepository = CdiUtil
- .createCdiUtil().findBean(DomainRepository.class);
+ .createCdiUtil().findBean(DomainRepository.class);
final Domain domain = domainRepository.findById(Long
- .parseLong(
- selectedDomainId.getSelectedKey(state)));
+ .parseLong(
+ selectedDomainId.getSelectedKey(state)));
final KernelConfig kernelConfig = KernelConfig.getConfig();
final Set supportedLanguages = kernelConfig
- .getSupportedLanguages();
+ .getSupportedLanguages();
final Set assignedLanguages = new HashSet<>();
domain.getDescription().getAvailableLocales().forEach(l -> {
assignedLanguages.add(l.toString());
@@ -295,5 +312,7 @@ class DomainDetails extends SegmentedPanel {
return false;
}
}
+
}
+
}
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainForm.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainForm.java
index fa88eb18b..1c2c67223 100644
--- a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainForm.java
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/DomainForm.java
@@ -61,6 +61,7 @@ class DomainForm extends Form {
public DomainForm(
final CategoriesTab categoriesTab,
final ParameterSingleSelectionModel selectedDomainId) {
+
super("domainForm");
this.selectedDomainId = selectedDomainId;
diff --git a/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/SubCategoriesTable.java b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/SubCategoriesTable.java
new file mode 100644
index 000000000..551246ba1
--- /dev/null
+++ b/ccm-core/src/main/java/com/arsdigita/ui/admin/categories/SubCategoriesTable.java
@@ -0,0 +1,350 @@
+/*
+ * Copyright (C) 2016 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 com.arsdigita.ui.admin.categories;
+
+import com.arsdigita.bebop.Component;
+import com.arsdigita.bebop.ControlLink;
+import com.arsdigita.bebop.Label;
+import com.arsdigita.bebop.PageState;
+import com.arsdigita.bebop.ParameterSingleSelectionModel;
+import com.arsdigita.bebop.Table;
+import com.arsdigita.bebop.Text;
+import com.arsdigita.bebop.event.TableActionEvent;
+import com.arsdigita.bebop.event.TableActionListener;
+import com.arsdigita.bebop.table.TableCellRenderer;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.table.TableColumnModel;
+import com.arsdigita.bebop.table.TableModel;
+import com.arsdigita.bebop.table.TableModelBuilder;
+import com.arsdigita.globalization.GlobalizedMessage;
+import com.arsdigita.util.LockableImpl;
+
+import org.libreccm.categorization.Categorization;
+import org.libreccm.categorization.Category;
+import org.libreccm.categorization.CategoryManager;
+import org.libreccm.categorization.CategoryRepository;
+import org.libreccm.cdi.utils.CdiUtil;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import static com.arsdigita.ui.admin.AdminUiConstants.*;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class SubCategoriesTable extends Table {
+
+ private static final int COL_NAME = 0;
+ private static final int COL_UP = 1;
+ private static final int COL_DOWN = 2;
+ private static final int COL_EDIT = 3;
+ private static final int COL_DEL = 4;
+
+ private final CategoriesTab categoriesTab;
+ private final ParameterSingleSelectionModel selectedCategoryId;
+
+ public SubCategoriesTable(
+ final CategoriesTab categoriesTab,
+ final ParameterSingleSelectionModel selectedCategoryId) {
+
+ super();
+
+ this.categoriesTab = categoriesTab;
+ this.selectedCategoryId = selectedCategoryId;
+
+ setIdAttr("subCategoriesTable");
+
+ setEmptyView(new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.no_subcategories",
+ ADMIN_BUNDLE)));
+
+ final TableColumnModel columnModel = getColumnModel();
+ columnModel.add(new TableColumn(
+ COL_NAME,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.subcategories.col_name",
+ ADMIN_BUNDLE))
+ ));
+ columnModel.add(new TableColumn(
+ COL_UP,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.subcategories.col_up",
+ ADMIN_BUNDLE))
+ ));
+ columnModel.add(new TableColumn(
+ COL_DOWN,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.subcategories.col_down",
+ ADMIN_BUNDLE))
+ ));
+ columnModel.add(new TableColumn(
+ COL_EDIT,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.subcategories.col_edit",
+ ADMIN_BUNDLE))
+ ));
+ columnModel.add(new TableColumn(
+ COL_DEL,
+ new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.subcategories.col_del",
+ ADMIN_BUNDLE))
+ ));
+
+ columnModel.get(COL_UP).setCellRenderer(new TableCellRenderer() {
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ if (value == null) {
+ return new Text("");
+ } else {
+ return new ControlLink((Component) value);
+ }
+ }
+
+ });
+
+ columnModel.get(COL_DOWN).setCellRenderer(new TableCellRenderer() {
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ if (value == null) {
+ return new Text("");
+ } else {
+ return new ControlLink((Component) value);
+ }
+ }
+
+ });
+
+ columnModel.get(COL_EDIT).setCellRenderer(new TableCellRenderer() {
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ return new ControlLink((Component) value);
+ }
+
+ });
+
+ columnModel.get(COL_DEL).setCellRenderer(new TableCellRenderer() {
+
+ @Override
+ public Component getComponent(final Table table,
+ final PageState state,
+ final Object value,
+ final boolean isSelected,
+ final Object key,
+ final int row,
+ final int column) {
+ if (value == null) {
+ return new Text("");
+ } else {
+ final ControlLink link = new ControlLink((Component) value);
+ link.setConfirmation(new GlobalizedMessage(
+ "ui.admin.categories.category.subcategories.del_confirm",
+ ADMIN_BUNDLE));
+ return link;
+ }
+ }
+
+ });
+
+ addTableActionListener(new TableActionListener() {
+
+ @Override
+ public void cellSelected(final TableActionEvent event) {
+ final PageState state = event.getPageState();
+
+ switch (event.getColumn()) {
+ case COL_UP: {
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final CategoryRepository categoryRepo = cdiUtil
+ .findBean(CategoryRepository.class);
+ final CategoryManager categoryManager = cdiUtil
+ .findBean(CategoryManager.class);
+ final Category parentCategory = categoryRepo.findById(
+ Long.parseLong(selectedCategoryId.getSelectedKey(
+ state)));
+ final Category subCategory = categoryRepo.findById(Long
+ .parseLong((String) event.getRowKey()));
+ categoryManager.decreaseCategoryOrder(subCategory,
+ parentCategory);
+ break;
+ }
+ case COL_DOWN: {
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final CategoryRepository categoryRepo = cdiUtil
+ .findBean(CategoryRepository.class);
+ final CategoryManager categoryManager = cdiUtil
+ .findBean(CategoryManager.class);
+ final Category parentCategory = categoryRepo.findById(
+ Long.parseLong(selectedCategoryId.getSelectedKey(
+ state)));
+ final Category subCategory = categoryRepo.findById(Long
+ .parseLong((String) event.getRowKey()));
+ categoryManager.increaseCategoryOrder(subCategory,
+ parentCategory);
+ break;
+ }
+ case COL_EDIT: {
+ selectedCategoryId.setSelectedKey(state,
+ event.getRowKey());
+ categoriesTab.showCategoryEditForm(state);
+ break;
+ }
+ case COL_DEL: {
+ final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
+ final CategoryRepository categoryRepo = cdiUtil
+ .findBean(CategoryRepository.class);
+ final Category category = categoryRepo.findById(Long
+ .parseLong((String) event.getRowKey()));
+ categoryRepo.delete(category);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void headSelected(final TableActionEvent event) {
+ //Nothing
+ }
+
+ });
+
+ setModelBuilder(new SubCategoriesTableModelBuilder());
+ }
+
+ private class SubCategoriesTableModelBuilder
+ extends LockableImpl
+ implements TableModelBuilder {
+
+ @Override
+ public TableModel makeModel(final Table table, final PageState state) {
+ table.getRowSelectionModel().clearSelection(state);
+
+ return new SubCategoriesTableModel(state);
+ }
+
+ }
+
+ private class SubCategoriesTableModel implements TableModel {
+
+ private final List subCategories;
+ private int index = -1;
+
+ public SubCategoriesTableModel(final PageState state) {
+ final CategoryRepository categoryRepo = CdiUtil.
+ createCdiUtil().findBean(CategoryRepository.class);
+ final Category category = categoryRepo.findById(Long.parseLong(
+ selectedCategoryId.getSelectedKey(state)));
+
+ subCategories = new ArrayList<>(category.getSubCategories());
+ subCategories.sort((c1, c2) -> {
+ return Long.compare(c1.getCategoryOrder(),
+ c2.getCategoryOrder());
+ });
+ }
+
+ @Override
+ public int getColumnCount() {
+ return 5;
+ }
+
+ @Override
+ public boolean nextRow() {
+ index++;
+ return index < subCategories.size();
+ }
+
+ @Override
+ public Object getElementAt(final int columnIndex) {
+ final Category subCategory = subCategories.get(index);
+
+ switch (columnIndex) {
+ case COL_NAME:
+ return subCategory.getName();
+ case COL_UP:
+ if (index == 0) {
+ return null;
+ } else {
+ return new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.subcategories.up",
+ ADMIN_BUNDLE));
+ }
+ case COL_DOWN:
+ if (index == subCategories.size() - 1) {
+ return null;
+ } else {
+ return new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.subcategories.down",
+ ADMIN_BUNDLE));
+ }
+ case COL_EDIT:
+ return new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.subcategories.edit",
+ ADMIN_BUNDLE));
+ case COL_DEL:
+ if (isDeletable(subCategory)) {
+ return new Label(new GlobalizedMessage(
+ "ui.admin.categories.category.subcategories.del",
+ ADMIN_BUNDLE));
+ } else {
+ return null;
+ }
+ default:
+ throw new IllegalArgumentException(
+ "Not a valid column index");
+ }
+ }
+
+ private boolean isDeletable(final Category category) {
+ final List subCats = category.getSubCategories();
+ final List objects = category.getObjects();
+
+ return (subCats == null || subCats.isEmpty())
+ && (objects == null || objects.isEmpty());
+ }
+
+ @Override
+ public Object getKeyAt(final int columnIndex) {
+ return subCategories.get(index).getObjectId();
+ }
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/categorization/Category.java b/ccm-core/src/main/java/org/libreccm/categorization/Category.java
index 78ea37175..246b755cc 100644
--- a/ccm-core/src/main/java/org/libreccm/categorization/Category.java
+++ b/ccm-core/src/main/java/org/libreccm/categorization/Category.java
@@ -22,6 +22,7 @@ import static org.libreccm.core.CoreConstants.*;
import org.hibernate.validator.constraints.NotBlank;
import org.libreccm.core.CcmObject;
+import org.libreccm.core.DefaultEntityGraph;
import org.libreccm.l10n.LocalizedString;
import java.io.Serializable;
@@ -37,8 +38,12 @@ import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToOne;
+import javax.persistence.NamedAttributeNode;
+import javax.persistence.NamedEntityGraph;
+import javax.persistence.NamedEntityGraphs;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
+import javax.persistence.NamedSubgraph;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import javax.validation.constraints.Pattern;
@@ -59,13 +64,34 @@ import javax.validation.constraints.Pattern;
@Entity
@Table(name = "CATEGORIES", schema = DB_SCHEMA)
@NamedQueries({
- @NamedQuery(name = "Category.topLevelCategories",
- query = "SELECT c FROM Category c WHERE c.parentCategory IS NULL"),
+ @NamedQuery(name = "Category.topLevelCategories",
+ query
+ = "SELECT c FROM Category c WHERE c.parentCategory IS NULL"),
@NamedQuery(name = "Category.findByName",
query = "SELECT c FROM Category c WHERE c.name = :name")
})
+@NamedEntityGraphs({
+ @NamedEntityGraph(
+ name = "Category.withSubCategoriesAndObjects",
+ attributeNodes = {
+ @NamedAttributeNode(value = "subCategories",
+ subgraph = "subCategories"),
+ @NamedAttributeNode(value = "objects")
+ },
+ subgraphs = {
+ @NamedSubgraph(
+ name = "subCategories",
+ attributeNodes = {
+ @NamedAttributeNode("subCategories"),
+ @NamedAttributeNode("objects")
+ }
+ )
+ }
+ )
+})
+@DefaultEntityGraph("Category.withSubCategoriesAndObjects")
public class Category extends CcmObject implements Serializable {
-
+
private static final long serialVersionUID = -7250208963391878547L;
/**
@@ -74,7 +100,7 @@ public class Category extends CcmObject implements Serializable {
*/
@Column(name = "UNIQUE_ID")
private String uniqueId;
-
+
/**
* The name of the category. This is used as URL stub, therefore only the
* characters a to z, A to Z and 0 to 9 are allowed.
@@ -89,12 +115,12 @@ public class Category extends CcmObject implements Serializable {
*/
@Embedded
@AssociationOverride(
- name = "values",
- joinTable = @JoinTable(name = "CATEGORY_TITLES",
- schema = DB_SCHEMA,
- joinColumns = {
- @JoinColumn(name = "OBJECT_ID")}
- ))
+ name = "values",
+ joinTable = @JoinTable(name = "CATEGORY_TITLES",
+ schema = DB_SCHEMA,
+ joinColumns = {
+ @JoinColumn(name = "OBJECT_ID")}
+ ))
private LocalizedString title;
/**
@@ -102,12 +128,12 @@ public class Category extends CcmObject implements Serializable {
*/
@Embedded
@AssociationOverride(
- name = "values",
- joinTable = @JoinTable(name = "CATEGORY_DESCRIPTIONS",
- schema = DB_SCHEMA,
- joinColumns = {
- @JoinColumn(name = "OBJECT_ID")}
- ))
+ name = "values",
+ joinTable = @JoinTable(name = "CATEGORY_DESCRIPTIONS",
+ schema = DB_SCHEMA,
+ joinColumns = {
+ @JoinColumn(name = "OBJECT_ID")}
+ ))
private LocalizedString description;
/**
@@ -164,7 +190,7 @@ public class Category extends CcmObject implements Serializable {
objects = new ArrayList<>();
subCategories = new ArrayList<>();
enabled = true;
- visible= true;
+ visible = true;
abstractCategory = false;
categoryOrder = 0;
}
@@ -316,7 +342,7 @@ public class Category extends CcmObject implements Serializable {
if (!super.equals(obj)) {
return false;
}
-
+
if (obj == null) {
return false;
}
@@ -363,12 +389,12 @@ public class Category extends CcmObject implements Serializable {
@Override
public String toString(final String data) {
return super.toString(String.format(", uniqueId = %s, "
- + "name = \"%s\", "
- + "title = %s, "
- + "enabled = %b, "
- + "visible = %b, "
- + "abstractCategory = %s, "
- + "categoryOrder = %d%s",
+ + "name = \"%s\", "
+ + "title = %s, "
+ + "enabled = %b, "
+ + "visible = %b, "
+ + "abstractCategory = %s, "
+ + "categoryOrder = %d%s",
uniqueId,
name,
Objects.toString(title),
diff --git a/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java b/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java
index bc4da789d..a04d654a4 100644
--- a/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java
+++ b/ccm-core/src/main/java/org/libreccm/categorization/CategoryManager.java
@@ -23,6 +23,7 @@ import org.apache.logging.log4j.Logger;
import org.libreccm.core.CcmObject;
import org.libreccm.core.CcmObjectRepository;
+import java.util.ArrayList;
import java.util.List;
import javax.enterprise.context.RequestScoped;
@@ -186,11 +187,61 @@ public class CategoryManager {
* object is not assigned to
* the provided category.
*/
+ @Transactional(Transactional.TxType.REQUIRED)
public void increaseObjectOrder(final CcmObject object,
final Category category)
throws ObjectNotAssignedToCategoryException {
- // TODO implement method
- throw new UnsupportedOperationException();
+
+ if (object == null) {
+ throw new IllegalArgumentException("The object can't be null.");
+ }
+
+ if (category == null) {
+ throw new IllegalArgumentException("The category can't be null");
+ }
+
+ final Categorization categorization;
+ final Categorization nextCategorization;
+
+ Categorization current = null;
+ int index = 0;
+ final List objects = new ArrayList<>(category
+ .getObjects());
+ objects.sort((o1, o2) -> {
+ return Long.compare(o1.getObjectOrder(), o2.getObjectOrder());
+ });
+ while (index < objects.size()) {
+ current = objects.get(index);
+ if (current.getCategorizedObject().equals(object)) {
+ break;
+ }
+ index++;
+ }
+
+ categorization = current;
+ if ((index + 1) < objects.size()) {
+ nextCategorization = objects.get(index + 1);
+ } else {
+ //No next object, returning silently.
+ return;
+ }
+
+ if (categorization == null) {
+ //Object is not part of the category.
+ throw new ObjectNotAssignedToCategoryException(String.format(
+ "The object %s is not assigned to the category %s (UUID: %s).",
+ object.getUuid(),
+ category.getName(),
+ category.getUuid()));
+ }
+
+ final long order = categorization.getObjectOrder();
+ final long nextOrder = nextCategorization.getObjectOrder();
+
+ categorization.setObjectOrder(nextOrder);
+ nextCategorization.setObjectOrder(order);
+
+ categoryRepo.save(category);
}
/**
@@ -207,11 +258,61 @@ public class CategoryManager {
* object is not assigned to
* the provided category.
*/
+ @Transactional(Transactional.TxType.REQUIRED)
public void decreaseObjectOrder(final CcmObject object,
final Category category)
throws ObjectNotAssignedToCategoryException {
- // TODO implement method
- throw new UnsupportedOperationException();
+
+ if (object == null) {
+ throw new IllegalArgumentException("The object can't be null.");
+ }
+
+ if (category == null) {
+ throw new IllegalArgumentException("The category can't be null");
+ }
+
+ final Categorization categorization;
+ final Categorization prevCategorization;
+
+ Categorization current = null;
+ int index = 0;
+ final List objects = new ArrayList<>(category
+ .getObjects());
+ objects.sort((o1, o2) -> {
+ return Long.compare(o1.getObjectOrder(), o2.getObjectOrder());
+ });
+ while (index < objects.size()) {
+ current = objects.get(index);
+ if (current.getCategorizedObject().equals(object)) {
+ break;
+ }
+ index++;
+ }
+
+ categorization = current;
+ if ((index - 1) >= 0) {
+ prevCategorization = objects.get(index - 1);
+ } else {
+ //No previous object, returning silently.
+ return;
+ }
+
+ if (categorization == null) {
+ //Object is not part of the category.
+ throw new ObjectNotAssignedToCategoryException(String.format(
+ "The object %s is not assigned to the category %s (UUID: %s).",
+ object.getUuid(),
+ category.getName(),
+ category.getUuid()));
+ }
+
+ final long order = categorization.getObjectOrder();
+ final long prevOrder = prevCategorization.getObjectOrder();
+
+ categorization.setObjectOrder(prevOrder);
+ prevCategorization.setObjectOrder(order);
+
+ categoryRepo.save(category);
}
/**
@@ -229,14 +330,13 @@ public class CategoryManager {
* assigned to the provided
* category.
*/
- public void swapObjects(final CcmObject objectA,
- final CcmObject objectB,
- final Category category)
- throws ObjectNotAssignedToCategoryException {
- // TODO implement method
- throw new UnsupportedOperationException();
- }
-
+// public void swapObjects(final CcmObject objectA,
+// final CcmObject objectB,
+// final Category category)
+// throws ObjectNotAssignedToCategoryException {
+// // TODO implement method
+// throw new UnsupportedOperationException();
+// }
/**
* Adds a category as an subcategory to another category. If the category is
* assigned to another category that association is removed.
@@ -246,20 +346,25 @@ public class CategoryManager {
* @param parentCategory The category to which the category is added as
* subcategory. Can't be {@code null}.
*/
+ @Transactional(Transactional.TxType.REQUIRED)
public void addSubCategoryToCategory(final Category subCategory,
final Category parentCategory) {
- if (subCategory.getParentCategory() != null) {
- final Category oldParent = subCategory.getParentCategory();
- removeSubCategoryFromCategory(subCategory, oldParent);
+ final Category sub = categoryRepo.findById(subCategory.getObjectId());
+ final Category parent = categoryRepo.findById(parentCategory
+ .getObjectId());
+
+ if (sub.getParentCategory() != null) {
+ final Category oldParent = sub.getParentCategory();
+ removeSubCategoryFromCategory(sub, oldParent);
}
- final int order = parentCategory.getCategories().size() + 1;
- parentCategory.addSubCategory(subCategory);
- subCategory.setParentCategory(parentCategory);
- subCategory.setCategoryOrder(order);
+ final int order = parent.getSubCategories().size() + 1;
+ parent.addSubCategory(sub);
+ sub.setParentCategory(parent);
+ sub.setCategoryOrder(order);
- categoryRepo.save(parentCategory);
- categoryRepo.save(subCategory);
+ categoryRepo.save(parent);
+ categoryRepo.save(sub);
}
/**
@@ -275,6 +380,7 @@ public class CategoryManager {
* assigned to the provided parent
* category.
*/
+ @Transactional(Transactional.TxType.REQUIRED)
public void removeSubCategoryFromCategory(final Category subCategory,
final Category parentCategory) {
@@ -314,10 +420,59 @@ public class CategoryManager {
* subcategory of the provided parent
* category.
*/
+ @Transactional(Transactional.TxType.REQUIRED)
public void increaseCategoryOrder(final Category subCategory,
final Category parentCategory) {
- // TODO implement method
- throw new UnsupportedOperationException();
+
+ if (parentCategory == null) {
+ throw new IllegalArgumentException("parentCategory can't be null.");
+ }
+
+ if (subCategory == null) {
+ throw new IllegalArgumentException("subCategory can't be null.");
+ }
+
+ boolean found = false;
+ int index = 0;
+ final List subCategories = new ArrayList<>(parentCategory
+ .getSubCategories());
+ subCategories.sort((c1, c2) -> {
+ return Long.compare(c1.getCategoryOrder(), c2.getCategoryOrder());
+ });
+ while (index < subCategories.size()) {
+ if (subCategories.get(index).equals(subCategory)) {
+ found = true;
+ break;
+ }
+ index++;
+ }
+
+ if (!found) {
+ throw new IllegalArgumentException(String.format(
+ "The category %s (UUID: %s) is not a subcategory of the "
+ + "category %s (UUID: %s)",
+ subCategory.getName(),
+ subCategory.getUuid(),
+ parentCategory.getName(),
+ parentCategory.getUuid()));
+ }
+
+ final Category nextCategory;
+ if ((index + 1) < subCategories.size()) {
+ nextCategory = subCategories.get(index + 1);
+ } else {
+ //No next category, returning sliently.
+ return;
+ }
+
+ final long order = subCategory.getCategoryOrder();
+ final long nextOrder = nextCategory.getCategoryOrder();
+
+ subCategory.setCategoryOrder(nextOrder);
+ nextCategory.setCategoryOrder(order);
+
+ categoryRepo.save(subCategory);
+ categoryRepo.save(nextCategory);
}
/**
@@ -337,8 +492,56 @@ public class CategoryManager {
*/
public void decreaseCategoryOrder(final Category subCategory,
final Category parentCategory) {
- // TODO implement method
- throw new UnsupportedOperationException();
+
+ if (parentCategory == null) {
+ throw new IllegalArgumentException("parentCategory can't be null.");
+ }
+
+ if (subCategory == null) {
+ throw new IllegalArgumentException("subCategory can't be null.");
+ }
+
+ boolean found = false;
+ int index = 0;
+ final List subCategories = new ArrayList<>(parentCategory
+ .getSubCategories());
+ subCategories.sort((c1, c2) -> {
+ return Long.compare(c1.getCategoryOrder(), c2.getCategoryOrder());
+ });
+ while (index < subCategories.size()) {
+ if (subCategories.get(index).equals(subCategory)) {
+ found = true;
+ break;
+ }
+ index++;
+ }
+
+ if (!found) {
+ throw new IllegalArgumentException(String.format(
+ "The category %s (UUID: %s) is not a subcategory of the "
+ + "category %s (UUID: %s)",
+ subCategory.getName(),
+ subCategory.getUuid(),
+ parentCategory.getName(),
+ parentCategory.getUuid()));
+ }
+
+ final Category prevCategory;
+ if ((index - 1) >= 0) {
+ prevCategory = subCategories.get(index - 1);
+ } else {
+ //No previous object, returning silently
+ return;
+ }
+
+ final long order = subCategory.getCategoryOrder();
+ final long prevOrder = prevCategory.getCategoryOrder();
+
+ subCategory.setCategoryOrder(prevOrder);
+ prevCategory.setCategoryOrder(order);
+
+ categoryRepo.save(subCategory);
+ categoryRepo.save(prevCategory);
}
/**
@@ -353,11 +556,10 @@ public class CategoryManager {
* subcategories of the provided parent
* category.qq
*/
- public void swapCategories(final Category subCategoryA,
- final Category subCategoryB,
- final Category parentCategory) {
- // TODO implement method
- throw new UnsupportedOperationException();
- }
-
+// public void swapCategories(final Category subCategoryA,
+// final Category subCategoryB,
+// final Category parentCategory) {
+// // TODO implement method
+// throw new UnsupportedOperationException();
+// }
}
diff --git a/ccm-core/src/main/java/org/libreccm/categorization/CategoryRepository.java b/ccm-core/src/main/java/org/libreccm/categorization/CategoryRepository.java
index 750303c0f..70f284227 100644
--- a/ccm-core/src/main/java/org/libreccm/categorization/CategoryRepository.java
+++ b/ccm-core/src/main/java/org/libreccm/categorization/CategoryRepository.java
@@ -57,7 +57,7 @@ public class CategoryRepository extends AbstractEntityRepository
public void initNewEntity(final Category category) {
category.setUuid(UUID.randomUUID().toString());
}
-
+
/**
* Retrieves a list of all top level categories (Categories without a parent
* category).
@@ -151,17 +151,4 @@ public class CategoryRepository extends AbstractEntityRepository
return current;
}
-
- /**
- * Retrieves all categories which are not assigned to another category as
- * subcategory or the an {@link Domain} as root category.
- *
- * @return A list of all orphaned categories. Normally this list should be
- * empty.
- */
- public List getOrphanedCategories() {
- // TODO implement method
- throw new UnsupportedOperationException();
- }
-
}
diff --git a/ccm-core/src/main/java/org/libreccm/categorization/Domain.java b/ccm-core/src/main/java/org/libreccm/categorization/Domain.java
index 7f1a34d3a..069924bff 100644
--- a/ccm-core/src/main/java/org/libreccm/categorization/Domain.java
+++ b/ccm-core/src/main/java/org/libreccm/categorization/Domain.java
@@ -98,7 +98,10 @@ import javax.xml.bind.annotation.XmlRootElement;
name = "subCategories",
attributeNodes = {
@NamedAttributeNode("subCategories")
- })}),
+ }
+ )
+ }
+ ),
@NamedEntityGraph(
name = "Domain.withOwners",
attributeNodes = {
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
index 331f7f0a4..4bfefb51b 100644
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties
@@ -459,3 +459,69 @@ ui.admin.configuration.setting.localized_string.col_lang=Language
ui.admin.configuration.setting.localized_string.col_value=Value
ui.admin.configuration.setting.localized_string.col_del=Delete
ui.admin.configuration.setting.localized_string.col_edit=Edit
+ui.admin.categories.category.create_new_subcategory=Create new sub category below category {0}
+ui.admin.categories.category.name.label=Name
+ui.admin.categories.category.name.errors.not_blank=The name of a category can't be blank.
+ui.admin.categories.category.description.edit.back=Back to category properties
+ui.admin.categories.category.description.edit_for_lang=Edit description of category {0} for locale {1}
+ui.admin.categories.category.description.add_for_lang=Add description for category {0} for locale {1}
+ui.admin.categories.category.description.label=Description
+ui.admin.categories.category.description.error.not_blank=The description of a category can't be blank.
+ui.admin.categories.category_details.description.none=No descriptions
+ui.admin.categories.category_details.description.col_lang=Language
+ui.admin.categories.category_details.description.col_value=Description
+ui.admin.categories.category_details.description.col_edit=Edit
+ui.admin.categories.category_details.description.col_del=Delete
+ui.admin.categories.category_details.description.del_confirm=Are you sure do delete this description?
+ui.admin.categories.category_details.description.edit=Edit
+ui.admin.categories.category_details.description.del=Delete
+ui.admin.categories.category_details.back=Back
+ui.admin.categories.category_details.basic_properties.edit=Edit basic properties
+ui.admin.categories.category_details.basic_properties=Basic properties
+ui.admin.categories.category_details.category_title=Title of the category
+ui.admin.categories.category_details.description=Description of the category
+ui.admin.categories.category_details.category_title.add.label=Add title
+ui.admin.categories.category_details.category_title.add.submit=Add
+ui.admin.categories.category_details.category_desc.add.label=Add description
+ui.admin.categories.category_details.category_desc.add.submit=Add
+ui.admin.categories.category.edit_category=Edit category {0}
+ui.admin.categories.category.property_sheet.name=Name
+ui.admin.categories.category.title.edit.back=Back
+ui.admin.categories.category.title.edit_for_lang=Edit title of category {0} for locale {1}
+ui.admin.categories.category.title.add_for_lang=Add title for locale {1} to category {0}
+ui.admin.categories.category.title.label=Title
+ui.admin.categories.category.title.error.not_blank=The title of category can't be blank.
+ui.admin.categories.category_details.title.none=No titles
+ui.admin.categories.category_details.title.col_lang=Language
+ui.admin.categories.category_details.title.col_value=Title
+ui.admin.categories.category_details.title.col_edit=Edit
+ui.admin.categories.category_details.title.col_del=Delete
+ui.admin.categories.category_details.title.del_confirm=Are you sure to delete this title?
+ui.admin.categories.category_details.title.edit=Edit
+ui.admin.categories.category_details.title.del=Delete
+ui.admin.categories.domain_details.description.col_edit=Edit
+ui.admin.categories.domain_details.description.edit=Edit
+ui.admin.categories.domain_details.title.col_edit=Edit
+ui.admin.categories.category.no_subcategories=This category has no subcategories
+ui.admin.categories.category.subcategories.col_name=Name
+ui.admin.categories.category.subcategories.col_up=\u25b2 Up
+ui.admin.categories.category.subcategories.col_down=\u25bc Down
+ui.admin.categories.category.subcategories.col_edit=Edit
+ui.admin.categories.category.subcategories.del_confirm=Are you sure to delete this category?
+ui.admin.categories.category.subcategories.up=\u25b2 Up
+ui.admin.categories.category.subcategories.down=\u25bc Down
+ui.admin.categories.category.subcategories.edit=Edit
+ui.admin.categories.category.subcategories.del=Delete
+ui.admin.categories.category.move.heading=Move category {0}
+ui.admin.categories.domain.details.heading=Details for domain {0}
+ui.admin.categories.category_details.heading=Details for category {0}
+ui.admin.categories.category_details.subcategories.add=Add subcategory
+ui.admin.categories.category_details.subcategories.header=Subcategories
+ui.admin.categories.category.subcategories.col_del=Delete
+ui.admin.categories.category_details.move_category=Move category
+ui.admin.categories.category.property_sheet.visible=Visible?
+ui.admin.categories.category.property_sheet.enabled=Enabled?
+ui.admin.categories.category.property_sheet.abstract=Abstract?
+ui.admin.categories.category.name.enabled=Enabled?
+ui.admin.categories.category.name.visible=Visible?
+ui.admin.categories.category.name.abstract=Abstract?
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
index ad952c343..c3db94e2c 100644
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties
@@ -364,7 +364,7 @@ ui.admin.categories.domain_form.fields.released=Freigegeben
ui.admin.categories.domain_form.errors.domain_key_blank=Der Key einer Domain darf nicht leer sein.
ui.admin.categories.domain_form.errors.version_blank=Die Version einer Domain darf nicht leer sein.
ui.admin.categories.domain_form.fields.root_category_name=Name der Wurzelkategorie
-ui.admin.categories.domain_details.back=Zur\u00fcck zur List der Domains
+ui.admin.categories.domain_details.back=Zur\u00fcck zur Liste der Domains
ui.admin.categories.domain_details.basic_properties.edit=Basiseigenschaften bearbeiten
ui.admin.categories.domain_details.basic_properties=Basiseigenschaften
ui.admin.categories.domain_details.domain_title=Lokalisierter Titel der Domain
@@ -410,7 +410,7 @@ ui.admin.categories.domain_details.mappings.create=hinzuf\u00fcgen
ui.admin.categories.doamin_details.mappings.error.please_select_app=Bitte w\u00e4hlen Sie eine Applikation aus.
ui.admin.categories.domain_details.mappings.remove.confirm=Sind Sie sicher, dass Sie dieses Mapping entfernen wollen?
ui.admin.categories.tree.header=Kategorien
-ui.admin.categories.tree.back=Zur\u00fcck zur Domain Eigenschaften
+ui.admin.categories.tree.back=Zur\u00fcck zur den Eigenschaften der Domain
ui.admin.configuration.classes.filter.heading=Konfigurationen filtern
ui.admin.configuration.classes.filter.submit=Anwenden
ui.admin.configuration.classes.filter.clear=Zur\u00fccksetzen
@@ -462,3 +462,69 @@ ui.admin.configuration.setting.localized_string.col_lang=Sprache
ui.admin.configuration.setting.localized_string.col_value=Wert
ui.admin.configuration.setting.localized_string.col_del=L\u00f6schen
ui.admin.configuration.setting.localized_string.col_edit=Bearbeiten
+ui.admin.categories.category.create_new_subcategory=Neue Unterkategorie f\u00fcr Kategorie {0} erstellen
+ui.admin.categories.category.name.label=Name
+ui.admin.categories.category.name.errors.not_blank=Der Name einer Kategorie darf nicht leer sein.
+ui.admin.categories.category.description.edit.back=Zur\u00fcck zu den Eigenschaften der Kategorie
+ui.admin.categories.category.description.edit_for_lang=Beschreibung der Kategorie {0} f\u00fcr {1} bearbeiten
+ui.admin.categories.category.description.add_for_lang=Beschreibung f\u00fcr {1} zur Kategorie {0} hinzuf\u00fcgen
+ui.admin.categories.category.description.label=Beschreibung
+ui.admin.categories.category.description.error.not_blank=Die Beschreibung einer Kategorie darf nicht leer sein.
+ui.admin.categories.category_details.description.none=Keine Beschreibungen
+ui.admin.categories.category_details.description.col_lang=Sprache
+ui.admin.categories.category_details.description.col_value=Beschreibung
+ui.admin.categories.category_details.description.col_edit=Bearbeiten
+ui.admin.categories.category_details.description.col_del=L\u00f6schen
+ui.admin.categories.category_details.description.del_confirm=Sind Sie sicher, dass Sie diese Beschreibung l\u00f6schen wollen?
+ui.admin.categories.category_details.description.edit=Bearbeiten
+ui.admin.categories.category_details.description.del=L\u00f6schen
+ui.admin.categories.category_details.back=Zur\u00fcck
+ui.admin.categories.category_details.basic_properties.edit=Basiseigenschaften bearbeiten
+ui.admin.categories.category_details.basic_properties=Basiseigenschaften
+ui.admin.categories.category_details.category_title=Titel der Kategorie
+ui.admin.categories.category_details.description=Beschreibung der Kategorie
+ui.admin.categories.category_details.category_title.add.label=Titel hinzuf\u00fcgen
+ui.admin.categories.category_details.category_title.add.submit=Hinzuf\u00fcgen
+ui.admin.categories.category_details.category_desc.add.label=Beschreibung hinzuf\u00fcgen
+ui.admin.categories.category_details.category_desc.add.submit=Hinzuf\u00fcgen
+ui.admin.categories.category.edit_category=Kategorie {0} bearbeiten
+ui.admin.categories.category.property_sheet.name=Name
+ui.admin.categories.category.title.edit.back=Zur\u00fcck
+ui.admin.categories.category.title.edit_for_lang=Titel der Kategorie {0} f\u00fcr Sprache {1} bearbeiten
+ui.admin.categories.category.title.add_for_lang=Titel f\u00fcr Sprache {1} zur Kategorie {0} hinzuf\u00fcgen
+ui.admin.categories.category.title.label=Titel
+ui.admin.categories.category.title.error.not_blank=Der Titel einer Kategorie darf nicht leer sein.
+ui.admin.categories.category_details.title.none=Keine Titel
+ui.admin.categories.category_details.title.col_lang=Sprache
+ui.admin.categories.category_details.title.col_value=Titel
+ui.admin.categories.category_details.title.col_edit=Bearbeiten
+ui.admin.categories.category_details.title.col_del=L\u00f6schen
+ui.admin.categories.category_details.title.del_confirm=Sind Sie sicher, dass Sie diesen Titel l\u00f6schen wollen?
+ui.admin.categories.category_details.title.edit=Bearbeiten
+ui.admin.categories.category_details.title.del=L\u00f6schen
+ui.admin.categories.domain_details.description.col_edit=Bearbeiten
+ui.admin.categories.domain_details.description.edit=Bearbeiten
+ui.admin.categories.domain_details.title.col_edit=Bearbeiten
+ui.admin.categories.category.no_subcategories=Diese Kategorie hat keine Unterkategorien
+ui.admin.categories.category.subcategories.col_name=Name
+ui.admin.categories.category.subcategories.col_up=\u25b2 Hoch
+ui.admin.categories.category.subcategories.col_down=\u25bc Runter
+ui.admin.categories.category.subcategories.col_edit=Bearbeiten
+ui.admin.categories.category.subcategories.del_confirm=Sind Sie sicher, dass Sie diese Kategorie l\u00f6schen wollen?
+ui.admin.categories.category.subcategories.up=\u25b2 Hoch
+ui.admin.categories.category.subcategories.down=\u25bc Runter
+ui.admin.categories.category.subcategories.edit=Bearbeiten
+ui.admin.categories.category.subcategories.del=L\u00f6schen
+ui.admin.categories.category.move.heading=Kategorie {0} verschieben
+ui.admin.categories.domain.details.heading=Eigenschaften der Domain {0}
+ui.admin.categories.category_details.heading=Eigenschaften der Kategorie {0}
+ui.admin.categories.category_details.subcategories.add=Unterkategorie hinzuf\u00fcgen
+ui.admin.categories.category_details.subcategories.header=Unterkategorien
+ui.admin.categories.category.subcategories.col_del=L\u00f6schen
+ui.admin.categories.category_details.move_category=Kategorie verschieben
+ui.admin.categories.category.property_sheet.visible=Sichtbar?
+ui.admin.categories.category.property_sheet.enabled=Aktiviert?
+ui.admin.categories.category.property_sheet.abstract=Abstrakt?
+ui.admin.categories.category.name.enabled=Aktiviert?
+ui.admin.categories.category.name.visible=Sichtbar?
+ui.admin.categories.category.name.abstract=Abstrakt?
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
index 010db66d8..690aa6120 100755
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties
@@ -435,3 +435,89 @@ ui.admin.configuration.setting.localized_string.col_lang=Language
ui.admin.configuration.setting.localized_string.col_value=Value
ui.admin.configuration.setting.localized_string.col_del=Delete
ui.admin.configuration.setting.localized_string.col_edit=Edit
+ui.admin.categories.category.create_new_subcategory=Create new sub category below category {0}
+ui.admin.categories.category.name.label=Name
+ui.admin.categories.category.name.errors.not_blank=The name of a category can't be blank.
+ui.admin.categories.category.description.edit.back=Back to category properties
+ui.admin.categories.category.description.edit_for_lang=Edit description of category {0} for locale {1}
+ui.admin.categories.category.description.add_for_lang=Add description for category {0} for locale {1}
+ui.admin.categories.category.description.label=Description
+ui.admin.categories.category.description.error.not_blank=The description of a category can't be blank.
+ui.admin.categories.category_details.description.none=No descriptions
+ui.admin.categories.category_details.description.col_lang=Language
+ui.admin.categories.category_details.description.col_value=Description
+ui.admin.categories.category_details.description.col_edit=Edit
+ui.admin.categories.category_details.description.col_del=Delete
+ui.admin.categories.category_details.description.del_confirm=Are you sure do delete this description?
+ui.admin.categories.category_details.description.edit=Edit
+ui.admin.categories.category_details.description.del=Delete
+ui.admin.categories.category_details.back=Back
+ui.admin.categories.category_details.basic_properties.edit=Edit basic properties
+ui.admin.categories.category_details.basic_properties=Basic properties
+ui.admin.categories.category_details.category_title=Title of the category
+ui.admin.categories.category_details.description=Description of the category
+ui.admin.categories.category_details.category_title.add.label=Add title
+ui.admin.categories.category_details.category_title.add.submit=Add
+ui.admin.categories.category_details.category_desc.add.label=Add description
+ui.admin.categories.category_details.category_desc.add.submit=Add
+ui.admin.categories.category.edit_category=Edit category {0}
+ui.admin.categories.category.property_sheet.name=Name
+ui.admin.categories.category.title.edit.back=Back
+ui.admin.categories.category.title.edit_for_lang=Edit title of category {0} for locale {1}
+ui.admin.categories.category.title.add_for_lang=Add title for locale {1} to category {0}
+ui.admin.categories.category.title.label=Title
+ui.admin.categories.category.title.error.not_blank=The title of category can't be blank.
+ui.admin.categories.category_details.title.none=No titles
+ui.admin.categories.category_details.title.col_lang=Language
+ui.admin.categories.category_details.title.col_value=Title
+ui.admin.categories.category_details.title.col_edit=Edit
+ui.admin.categories.category_details.title.col_del=Delete
+ui.admin.categories.category_details.title.del_confirm=Are you sure to delete this title?
+ui.admin.categories.category_details.title.edit=Edit
+ui.admin.categories.category_details.title.del=Delete
+ui.admin.categories.domain_details.description.col_edit=Edit
+ui.admin.categories.domain_details.description.edit=Edit
+ui.admin.categories.domain_details.title.col_edit=Edit
+ui.admin.categories.category.no_subcategories=This category has no subcategories
+ui.admin.categories.category.subcategories.col_name=Name
+ui.admin.categories.category.subcategories.col_up=\u25b2 Up
+ui.admin.categories.category.subcategories.col_down=\u25bc Down
+ui.admin.categories.category.subcategories.col_edit=Edit
+ui.admin.categories.category.subcategories.del_confirm=Are you sure to delete this category?
+ui.admin.categories.category.subcategories.up=\u25b2 Up
+ui.admin.categories.category.subcategories.down=\u25bc Down
+ui.admin.categories.category.subcategories.edit=Edit
+ui.admin.categories.category.subcategories.del=Delete
+ui.admin.categories.category.move.heading=Move category {0}
+ui.admin.categories.domain.details.heading=Details for domain {0}
+ui.admin.categories.category_details.heading=Details for category {0}
+ui.admin.categories.category_details.subcategories.add=Add subcategory
+ui.admin.categories.category_details.subcategories.header=Subcategories
+ui.admin.categories.category.subcategories.col_del=Delete
+ui.admin.categories.category_details.move_category=Move category
+ui.admin.categories.category.property_sheet.visible=Visible?
+ui.admin.categories.category.property_sheet.enabled=Enabled?
+ui.admin.applicationsMultiInstanceApplicationPane.instances.table.col_desc.header=Description
+ui.admin.applicationsMultiInstanceApplicationPane.instances.table.col_title.header=Title
+ui.admin.applicationsMultiInstanceApplicationPane.instances.table.col_url.header=Path
+ui.admin.applications.placeholder=There is no administration panel for instances of this application type yet.
+ui.admin.applications.parent.label=Select parent application
+ui.admin.applications.no_settings=This application has no settings (yet).
+ui.admin.applications.form_not_compatible_now=This application administration form is not yet compatible with this application pane. Please use the applications own administration form.
+ui.admin.applications.ApplicationInstancePane.path.label=Path of the application
+ui.admin.applications.ApplicationInfoSection.desc.label=Description
+ui.admin.applications.ApplicationInfoSection.app_class.label=Application Class
+ui.admin.applications.ApplicationInfoSection.heading=Application information
+ui.admin.applications.ApplicationInfoSection.singleton.label=Singleton
+ui.admin.applications.ApplicationInfoSection.singleton.no=No
+ui.admin.applications.ApplicationInfoSection.singleton.yes=Yes
+ui.admin.applications.ApplicationInfoSection.singleton_instance.no_instance_found=No instance found
+ui.admin.applications.ApplicationInfoSection.title.label=Title
+ui.admin.applications.ApplicationInfoSection.singleton_instance.path.label=Path of the singleton instance
+ui.admin.applications.ApplicationInstancePane.desc.label=Description
+ui.admin.applications.ApplicationInstancePane.info.heading=Instance data
+ui.admin.applications.ApplicationInstancePane.manage.heading=Instance specific settings
+ui.admin.categories.category.property_sheet.abstract=Abstract?
+ui.admin.categories.category.name.enabled=Enabled?
+ui.admin.categories.category.name.visible=Visible?
+ui.admin.categories.category.name.abstract=Abstract?
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
index d4ff2bea6..976dd24cb 100755
--- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
+++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties
@@ -77,7 +77,7 @@ ui.admin.user.userpasswordform.passwordlabel=Mot de passe:
ui.admin.user.userpasswordform.question=Question:
ui.admin.user.userpasswordform.submit=Changer
ui.admin.tab.applications=Applications
-ui.admin.applications.tree.heading=
+ui.admin.applications.tree.heading=Applications
ui.admin.applications.url.validation.not_blank=The URL of an application instance can is mandatory.
ui.admin.applications.url.valiation.minmaxlength=The length of an URL of an application instance must be between 1 and 100 characters.
ui.admin.applications.title.validation.not_blank=Title is mandatory for an application instance.
@@ -426,3 +426,89 @@ ui.admin.configuration.setting.localized_string.col_lang=Language
ui.admin.configuration.setting.localized_string.col_value=Value
ui.admin.configuration.setting.localized_string.col_del=Delete
ui.admin.configuration.setting.localized_string.col_edit=Edit
+ui.admin.categories.category.create_new_subcategory=Create new sub category below category {0}
+ui.admin.categories.category.name.label=Name
+ui.admin.categories.category.name.errors.not_blank=The name of a category can't be blank.
+ui.admin.categories.category.description.edit.back=Back to category properties
+ui.admin.categories.category.description.edit_for_lang=Edit description of category {0} for locale {1}
+ui.admin.categories.category.description.add_for_lang=Add description for category {0} for locale {1}
+ui.admin.categories.category.description.label=Description
+ui.admin.categories.category.description.error.not_blank=The description of a category can't be blank.
+ui.admin.categories.category_details.description.none=No descriptions
+ui.admin.categories.category_details.description.col_lang=Language
+ui.admin.categories.category_details.description.col_value=Description
+ui.admin.categories.category_details.description.col_edit=Edit
+ui.admin.categories.category_details.description.col_del=Delete
+ui.admin.categories.category_details.description.del_confirm=Are you sure do delete this description?
+ui.admin.categories.category_details.description.edit=Edit
+ui.admin.categories.category_details.description.del=Delete
+ui.admin.categories.category_details.back=Back
+ui.admin.categories.category_details.basic_properties.edit=Edit basic properties
+ui.admin.categories.category_details.basic_properties=Basic properties
+ui.admin.categories.category_details.category_title=Title of the category
+ui.admin.categories.category_details.description=Description of the category
+ui.admin.categories.category_details.category_title.add.label=Add title
+ui.admin.categories.category_details.category_title.add.submit=Add
+ui.admin.categories.category_details.category_desc.add.label=Add description
+ui.admin.categories.category_details.category_desc.add.submit=Add
+ui.admin.categories.category.edit_category=Edit category {0}
+ui.admin.categories.category.property_sheet.name=Name
+ui.admin.categories.category.title.edit.back=Back
+ui.admin.categories.category.title.edit_for_lang=Edit title of category {0} for locale {1}
+ui.admin.categories.category.title.add_for_lang=Add title for locale {1} to category {0}
+ui.admin.categories.category.title.label=Title
+ui.admin.categories.category.title.error.not_blank=The title of category can't be blank.
+ui.admin.categories.category_details.title.none=No titles
+ui.admin.categories.category_details.title.col_lang=Language
+ui.admin.categories.category_details.title.col_value=Title
+ui.admin.categories.category_details.title.col_edit=Edit
+ui.admin.categories.category_details.title.col_del=Delete
+ui.admin.categories.category_details.title.del_confirm=Are you sure to delete this title?
+ui.admin.categories.category_details.title.edit=Edit
+ui.admin.categories.category_details.title.del=Delete
+ui.admin.categories.domain_details.description.col_edit=Edit
+ui.admin.categories.domain_details.description.edit=Edit
+ui.admin.categories.domain_details.title.col_edit=Edit
+ui.admin.categories.category.no_subcategories=This category has no subcategories
+ui.admin.categories.category.subcategories.col_name=Name
+ui.admin.categories.category.subcategories.col_up=\u25b2 Up
+ui.admin.categories.category.subcategories.col_down=\u25bc Down
+ui.admin.categories.category.subcategories.col_edit=Edit
+ui.admin.categories.category.subcategories.del_confirm=Are you sure to delete this category?
+ui.admin.categories.category.subcategories.up=\u25b2 Up
+ui.admin.categories.category.subcategories.down=\u25bc Down
+ui.admin.categories.category.subcategories.edit=Edit
+ui.admin.categories.category.subcategories.del=Delete
+ui.admin.categories.category.move.heading=Move category {0}
+ui.admin.categories.domain.details.heading=Details for domain {0}
+ui.admin.categories.category_details.heading=Details for category {0}
+ui.admin.categories.category_details.subcategories.add=Add subcategory
+ui.admin.categories.category_details.subcategories.header=Subcategories
+ui.admin.categories.category.subcategories.col_del=Delete
+ui.admin.categories.category_details.move_category=Move category
+ui.admin.categories.category.property_sheet.visible=Visible?
+ui.admin.categories.category.property_sheet.enabled=Enabled?
+ui.admin.applicationsMultiInstanceApplicationPane.instances.table.col_desc.header=Description
+ui.admin.applicationsMultiInstanceApplicationPane.instances.table.col_title.header=Title
+ui.admin.applicationsMultiInstanceApplicationPane.instances.table.col_url.header=Path
+ui.admin.applications.placeholder=There is no administration panel for instances of this application type yet.
+ui.admin.applications.parent.label=Select parent application
+ui.admin.applications.no_settings=This application has no settings (yet).
+ui.admin.applications.form_not_compatible_now=This application administration form is not yet compatible with this application pane. Please use the applications own administration form.
+ui.admin.applications.ApplicationInstancePane.path.label=Path of the application
+ui.admin.applications.ApplicationInfoSection.desc.label=Description
+ui.admin.applications.ApplicationInfoSection.app_class.label=Application Class
+ui.admin.applications.ApplicationInfoSection.heading=Application information
+ui.admin.applications.ApplicationInfoSection.singleton.label=Singleton
+ui.admin.applications.ApplicationInfoSection.singleton.no=No
+ui.admin.applications.ApplicationInfoSection.singleton.yes=Yes
+ui.admin.applications.ApplicationInfoSection.singleton_instance.no_instance_found=No instance found
+ui.admin.applications.ApplicationInfoSection.title.label=Title
+ui.admin.applications.ApplicationInfoSection.singleton_instance.path.label=Path of the singleton instance
+ui.admin.applications.ApplicationInstancePane.desc.label=Description
+ui.admin.applications.ApplicationInstancePane.info.heading=Instance data
+ui.admin.applications.ApplicationInstancePane.manage.heading=Instance specific settings
+ui.admin.categories.category.property_sheet.abstract=Abstract?
+ui.admin.categories.category.name.enabled=Enabled?
+ui.admin.categories.category.name.visible=Visible?
+ui.admin.categories.category.name.abstract=Abstract?