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?