CategoryManagement

ccm-docs
Jens Pelzetter 2020-11-21 21:57:44 +01:00
parent b3d870eb57
commit d61090d0fd
15 changed files with 565 additions and 240 deletions

View File

@ -30,6 +30,8 @@ import org.libreccm.ui.Message;
import org.libreccm.ui.MessageType;
import org.libreccm.ui.admin.AdminMessages;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.Arrays;
import java.util.Locale;
import java.util.Optional;
@ -38,13 +40,17 @@ import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.mvc.Controller;
import javax.mvc.Models;
import javax.mvc.MvcContext;
import javax.servlet.http.HttpServletRequest;
import javax.transaction.Transactional;
import javax.ws.rs.Consumes;
import javax.ws.rs.Encoded;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
/**
*
@ -163,7 +169,37 @@ public class CategoriesController {
public String newSubCategory(
@PathParam("categoryIdentifier") final String categoryIdentifier
) {
return "org/libreccm/ui/admin/categories/category-form.xhtml";
final Identifier identifier = identifierParser.parseIdentifier(
categoryIdentifier
);
final Optional<Category> result;
switch (identifier.getType()) {
case ID:
result = categoryRepository.findById(
Long.parseLong(identifier.getIdentifier())
);
break;
default:
result = categoryRepository.findByUuid(
identifier.getIdentifier()
);
break;
}
if (result.isPresent()) {
categoryDetailsModel.setParentCategory(result.get());
return "org/libreccm/ui/admin/categories/category-form.xhtml";
} else {
categoryDetailsModel.addMessage(
new Message(
adminMessages.getMessage(
"categories.not_found.message",
Arrays.asList(categoryIdentifier)
), MessageType.WARNING
)
);
return "org/libreccm/ui/admin/categories/category-not-found.xhtml";
}
}
@POST
@ -306,17 +342,16 @@ public class CategoriesController {
}
@POST
@Path("/{categoryIdentifier}/title/add")
@Path("/{identifier}/title/add")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String addTitle(
@PathParam("categoryIdentifier")
final String categoryIdentifierParam,
@PathParam("identifier") final String identifierParam,
@FormParam("locale") final String localeParam,
@FormParam("value") final String value
) {
final Identifier identifier = identifierParser.parseIdentifier(
categoryIdentifierParam
identifierParam
);
final Optional<Category> result;
switch (identifier.getType()) {
@ -347,7 +382,7 @@ public class CategoriesController {
new Message(
adminMessages.getMessage(
"categories.not_found.message",
Arrays.asList(categoryIdentifierParam)
Arrays.asList(identifierParam)
), MessageType.WARNING
)
);
@ -356,17 +391,16 @@ public class CategoriesController {
}
@POST
@Path("/{categoryIdentifier}/title/${locale}/edit")
@Path("/{identifier}/title/{locale}/edit")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String editTitle(
@PathParam("categoryIdentifier")
final String categoryIdentifierParam,
@PathParam("identifier") final String identifierParam,
@PathParam("locale") final String localeParam,
@FormParam("value") final String value
) {
final Identifier identifier = identifierParser.parseIdentifier(
categoryIdentifierParam
identifierParam
);
final Optional<Category> result;
switch (identifier.getType()) {
@ -397,7 +431,7 @@ public class CategoriesController {
new Message(
adminMessages.getMessage(
"categories.not_found.message",
Arrays.asList(categoryIdentifierParam)
Arrays.asList(identifierParam)
), MessageType.WARNING
)
);
@ -406,10 +440,11 @@ public class CategoriesController {
}
@POST
@Path("/{categoryIdentifier}/title/${locale}/remove")
@Path("/{identifier}/title/{locale}/remove")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String removeTitle(
@PathParam("categoryIdentifier")
@PathParam("identifier")
final String categoryIdentifierParam,
@PathParam("locale") final String localeParam
) {
@ -454,16 +489,16 @@ public class CategoriesController {
}
@POST
@Path("/{categoryIdentifier}description/add")
@Path("/{identifier}decsription/add")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String addDescription(
@PathParam("categoryIdentifier")
final String categoryIdentifierParam,
@PathParam("identifier") final String identifierParam,
@FormParam("locale") final String localeParam,
@FormParam("value") final String value
) {
final Identifier identifier = identifierParser.parseIdentifier(
categoryIdentifierParam
identifierParam
);
final Optional<Category> result;
switch (identifier.getType()) {
@ -494,7 +529,7 @@ public class CategoriesController {
new Message(
adminMessages.getMessage(
"categories.not_found.message",
Arrays.asList(categoryIdentifierParam)
Arrays.asList(identifierParam)
), MessageType.WARNING
)
);
@ -503,16 +538,17 @@ public class CategoriesController {
}
@POST
@Path("/{categoryIdentifier}/description/${locale}/edit")
@Path("/{identifier}/description/{locale}/edit")
@Consumes(MediaType.APPLICATION_FORM_URLENCODED)
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String editDescription(
@PathParam("categoryIdentifier")
final String categoryIdentifierParam,
@PathParam("identifier") final String identifierParam,
@PathParam("locale") final String localeParam,
@FormParam("value") final String value
) {
final Identifier identifier = identifierParser.parseIdentifier(
categoryIdentifierParam
identifierParam
);
final Optional<Category> result;
switch (identifier.getType()) {
@ -543,7 +579,7 @@ public class CategoriesController {
new Message(
adminMessages.getMessage(
"categories.not_found.message",
Arrays.asList(categoryIdentifierParam)
Arrays.asList(identifierParam)
), MessageType.WARNING
)
);
@ -552,15 +588,15 @@ public class CategoriesController {
}
@POST
@Path("/{categoryIdentifier}/description/${locale}/remove")
@Path("/{identifier}/description/{locale}/remove")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String removeDescription(
@PathParam("categoryIdentifier")
final String categoryIdentifierParam,
@PathParam("identifier") final String identifierParam,
@PathParam("locale") final String localeParam
) {
final Identifier identifier = identifierParser.parseIdentifier(
categoryIdentifierParam
identifierParam
);
final Optional<Category> result;
switch (identifier.getType()) {
@ -591,7 +627,7 @@ public class CategoriesController {
new Message(
adminMessages.getMessage(
"categories.not_found.message",
Arrays.asList(categoryIdentifierParam)
Arrays.asList(identifierParam)
), MessageType.WARNING
)
);

View File

@ -20,14 +20,19 @@ package org.libreccm.ui.admin.categories;
import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryManager;
import org.libreccm.categorization.Domain;
import org.libreccm.categorization.DomainRepository;
import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.ui.Message;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
@ -47,6 +52,12 @@ public class CategoryDetailsModel {
@Inject
private CategoryManager categoryManager;
@Inject
private DomainRepository domainRepository;
@Inject
private GlobalizationHelper globalizationHelper;
private long categoryId;
private String uuid;
@ -59,8 +70,12 @@ public class CategoryDetailsModel {
private Map<String, String> title;
private List<String> unusedTitleLocales;
private Map<String, String> description;
private List<String> unusedDescriptionLocales;
private boolean enabled;
private boolean visible;
@ -71,6 +86,8 @@ public class CategoryDetailsModel {
private CategoryNodeModel parentCategory;
private CategoryPathModel categoryPath;
private long categoryOrder;
private final List<Message> messages;
@ -109,10 +126,26 @@ public class CategoryDetailsModel {
return Collections.unmodifiableMap(title);
}
public List<String> getUnusedTitleLocales() {
return Collections.unmodifiableList(unusedTitleLocales);
}
public boolean hasUnusedTitleLocales() {
return !unusedTitleLocales.isEmpty();
}
public Map<String, String> getDescription() {
return Collections.unmodifiableMap(description);
}
public List<String> getUnusedDescriptionLocales() {
return Collections.unmodifiableList(unusedDescriptionLocales);
}
public boolean hasUnusedDescriptionLocales() {
return !unusedDescriptionLocales.isEmpty();
}
public boolean isEnabled() {
return enabled;
}
@ -137,6 +170,10 @@ public class CategoryDetailsModel {
parentCategory = buildCategoryNodeModel(parent);
}
public CategoryPathModel getCategoryPath() {
return categoryPath;
}
public long getCategoryOrder() {
return categoryOrder;
}
@ -174,6 +211,9 @@ public class CategoryDetailsModel {
uniqueId = category.getUniqueId();
name = category.getName();
path = categoryManager.getCategoryPath(category);
final List<Locale> availableLocales = globalizationHelper
.getAvailableLocales();
title = category
.getTitle()
.getValues()
@ -185,6 +225,16 @@ public class CategoryDetailsModel {
entry -> entry.getValue()
)
);
final Set<Locale> titleLocales = category
.getTitle()
.getAvailableLocales();
unusedTitleLocales = availableLocales
.stream()
.filter(locale -> !titleLocales.contains(locale))
.map(Locale::toString)
.sorted()
.collect(Collectors.toList());
description = category
.getDescription()
.getValues()
@ -196,6 +246,16 @@ public class CategoryDetailsModel {
entry -> entry.getValue()
)
);
final Set<Locale> descriptionLocales = category
.getDescription()
.getAvailableLocales();
unusedDescriptionLocales = availableLocales
.stream()
.filter(locale -> !descriptionLocales.contains(locale))
.map(Locale::toString)
.sorted()
.collect(Collectors.toList());
enabled = category.isEnabled();
visible = category.isVisible();
abstractCategory = category.isAbstractCategory();
@ -205,10 +265,23 @@ public class CategoryDetailsModel {
.map(this::buildCategoryNodeModel)
.sorted()
.collect(Collectors.toList());
parentCategory = buildCategoryNodeModel(category.getParentCategory());
if (category.getParentCategory() != null) {
parentCategory
= buildCategoryNodeModel(category.getParentCategory());
}
categoryPath = buildCategoryPathModel(category);
categoryOrder = category.getCategoryOrder();
}
private DomainNodeModel buildDomainNodeModel(final Domain domain) {
final DomainNodeModel model = new DomainNodeModel();
model.setDomainId(domain.getObjectId());
model.setUuid(domain.getUuid());
model.setDomainKey(domain.getDomainKey());
return model;
}
private CategoryNodeModel buildCategoryNodeModel(final Category category) {
final CategoryNodeModel model = new CategoryNodeModel();
model.setCategoryId(category.getObjectId());
@ -217,7 +290,32 @@ public class CategoryDetailsModel {
model.setName(category.getName());
model.setPath(categoryManager.getCategoryPath(category));
model.setCategoryOrder(category.getCategoryOrder());
model.setEnabled(category.isEnabled());
model.setVisible(category.isVisible());
model.setAbstractCategory(category.isAbstractCategory());
return model;
}
private CategoryPathModel buildCategoryPathModel(final Category category) {
return buildCategoryPathModel(category, new CategoryPathModel());
}
private CategoryPathModel buildCategoryPathModel(
final Category category,
final CategoryPathModel categoryPathModel
) {
categoryPathModel.addCategoryAtBegin(buildCategoryNodeModel(category));
final Category parent = category.getParentCategory();
if (parent == null) {
final Optional<Domain> domain = domainRepository
.findByRootCategory(category);
if (domain.isPresent()) {
categoryPathModel.setDomain(buildDomainNodeModel(domain.get()));
}
return categoryPathModel;
} else {
return buildCategoryPathModel(parent, categoryPathModel);
}
}
}

View File

@ -23,6 +23,8 @@ import org.libreccm.api.IdentifierParser;
import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryManager;
import org.libreccm.categorization.CategoryRepository;
import org.libreccm.categorization.Domain;
import org.libreccm.categorization.DomainRepository;
import org.libreccm.core.CoreConstants;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege;
@ -63,6 +65,9 @@ public class CategoryFormController {
@Inject
private CategoryRepository categoryRepository;
@Inject
private DomainRepository domainRepository;
@Inject
private IdentifierParser identifierParser;
@ -73,13 +78,13 @@ public class CategoryFormController {
private String name;
@FormParam("enabled")
private boolean enabled;
private String enabled;
@FormParam("visible")
private boolean visible;
private String visible;
@FormParam("abstractCategory")
private boolean abstractCategory;
private String abstractCategory;
@POST
@Path("/{parentCategoryIdentifier}/new")
@ -113,17 +118,33 @@ public class CategoryFormController {
final Category category = new Category();
category.setUniqueId(uniqueId);
category.setName(name);
category.setEnabled(enabled);
category.setVisible(visible);
category.setAbstractCategory(abstractCategory);
category.setEnabled(enabled != null);
category.setVisible(visible != null);
category.setAbstractCategory(abstractCategory != null);
categoryRepository.save(category);
categoryManager.addSubCategoryToCategory(category, parentCategory);
return String.format(
"redirect:categorymanager/categories/ID-%s",
parentCategory.getObjectId()
);
if (parentCategory.getParentCategory() == null) {
final Optional<Domain> categorySystem = domainRepository
.findByRootCategory(parentCategory);
if (categorySystem.isPresent()) {
return String.format(
"redirect:categorymanager/categorysystems/ID-%d/details",
categorySystem.get().getObjectId()
);
} else {
return String.format(
"redirect:categorymanager/categories/ID-%d/details",
parentCategory.getObjectId()
);
}
} else {
return String.format(
"redirect:categorymanager/categories/ID-%d/details",
parentCategory.getObjectId()
);
}
} else {
categoryDetailsModel.addMessage(
new Message(
@ -143,7 +164,7 @@ public class CategoryFormController {
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String updateCategory(
@PathParam("categoryIdentifierParam")
@PathParam("categoryIdentifier")
final String categoryIdentifierParam
) {
final Identifier identifier = identifierParser.parseIdentifier(
@ -169,9 +190,9 @@ public class CategoryFormController {
final Category category = result.get();
category.setUniqueId(uniqueId);
category.setName(name);
category.setEnabled(enabled);
category.setVisible(visible);
category.setAbstractCategory(abstractCategory);
category.setEnabled(enabled != null);
category.setVisible(visible != null);
category.setAbstractCategory(abstractCategory != null);
categoryRepository.save(category);

View File

@ -18,8 +18,6 @@
*/
package org.libreccm.ui.admin.categories;
import org.libreccm.categorization.Category;
import java.util.Objects;
/**
@ -38,6 +36,12 @@ public class CategoryNodeModel implements Comparable<CategoryNodeModel> {
private String path;
private boolean enabled;
private boolean visible;
private boolean abstractCategory;
private long categoryOrder;
public long getCategoryId() {
@ -92,6 +96,30 @@ public class CategoryNodeModel implements Comparable<CategoryNodeModel> {
this.categoryOrder = categoryOrder;
}
public boolean isEnabled() {
return enabled;
}
protected void setEnabled(final boolean enabled) {
this.enabled = enabled;
}
public boolean isVisible() {
return visible;
}
protected void setVisible(final boolean visible) {
this.visible = visible;
}
public boolean isAbstractCategory() {
return abstractCategory;
}
protected void setAbstractCategory(final boolean abstractCategory) {
this.abstractCategory = abstractCategory;
}
@Override
public int compareTo(final CategoryNodeModel other) {
int result = Long.compare(

View File

@ -0,0 +1,63 @@
/*
* Copyright (C) 2020 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.ui.admin.categories;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class CategoryPathModel {
private DomainNodeModel domain;
private List<CategoryNodeModel> categories;
public CategoryPathModel() {
categories = new ArrayList<>();
}
public DomainNodeModel getDomain() {
return domain;
}
protected void setDomain(final DomainNodeModel domain) {
this.domain = domain;
}
public List<CategoryNodeModel> getCategories() {
return Collections.unmodifiableList(categories);
}
protected void addCategory(final CategoryNodeModel category) {
categories.add(category);
}
protected void addCategoryAtBegin(final CategoryNodeModel category) {
categories.add(0, category);
}
protected void setCategories(final List<CategoryNodeModel> categories) {
this.categories = new ArrayList<>(categories);
}
}

View File

@ -18,6 +18,8 @@
*/
package org.libreccm.ui.admin.categories;
import org.libreccm.categorization.Category;
import org.libreccm.categorization.CategoryManager;
import org.libreccm.categorization.Domain;
import org.libreccm.categorization.DomainOwnership;
import org.libreccm.l10n.GlobalizationHelper;
@ -54,6 +56,9 @@ public class CategorySystemDetailsModel {
@Inject
private ApplicationRepository applicationRepository;
@Inject
private CategoryManager categoryManager;
@Inject
private GlobalizationHelper globalizationHelper;
@ -83,7 +88,7 @@ public class CategorySystemDetailsModel {
private String rootIdentifier;
private List<CategoryTableRow> categories;
private List<CategoryNodeModel> categories;
private final List<Message> messages;
@ -194,7 +199,7 @@ public class CategorySystemDetailsModel {
return Collections.unmodifiableList(ownerOptions);
}
public List<CategoryTableRow> getCategories() {
public List<CategoryNodeModel> getCategories() {
return Collections.unmodifiableList(categories);
}
@ -238,6 +243,7 @@ public class CategorySystemDetailsModel {
.withZone(ZoneOffset.systemDefault())
.format(domain.getReleased());
}
final List<Locale> availableLocales = globalizationHelper
.getAvailableLocales();
title = domain
@ -310,7 +316,7 @@ public class CategorySystemDetailsModel {
.getRoot()
.getSubCategories()
.stream()
.map(CategoryTableRow::new)
.map(this::buildCategoryTableRow)
.sorted()
.collect(Collectors.toList());
}
@ -332,4 +338,18 @@ public class CategorySystemDetailsModel {
return ownerRow;
}
private CategoryNodeModel buildCategoryTableRow(final Category category) {
final CategoryNodeModel row = new CategoryNodeModel();
row.setCategoryId(category.getObjectId());
row.setUuid(category.getUuid());
row.setUniqueId(category.getUniqueId());
row.setName(category.getName());
row.setPath(categoryManager.getCategoryPath(category));
row.setEnabled(category.isEnabled());
row.setVisible(category.isVisible());
row.setAbstractCategory(category.isAbstractCategory());
row.setCategoryOrder(category.getCategoryOrder());
return row;
}
}

View File

@ -1,137 +0,0 @@
/*
* Copyright (C) 2020 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.ui.admin.categories;
import org.libreccm.categorization.Category;
import java.util.Objects;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class CategoryTableRow implements Comparable<CategoryTableRow> {
private long categoryId;
private String uuid;
private String uniqueId;
private String name;
private boolean enabled;
private boolean visible;
private boolean abstractCategory;
private long categoryOrder;
public CategoryTableRow() {
super();
}
public CategoryTableRow(final Category category) {
categoryId = category.getObjectId();
uuid = category.getUuid();
uniqueId = category.getUniqueId();
name = category.getName();
enabled = category.isEnabled();
visible = category.isVisible();
abstractCategory = category.isAbstractCategory();
categoryOrder = category.getCategoryOrder();
}
public long getCategoryId() {
return categoryId;
}
protected void setCategoryId(final long categoryId) {
this.categoryId = categoryId;
}
public String getUuid() {
return uuid;
}
protected void setUuid(final String uuid) {
this.uuid = uuid;
}
public String getIdentifier() {
return String.format("UUID-%s", uuid);
}
public String getUniqueId() {
return uniqueId;
}
protected void setUniqueId(final String uniqueId) {
this.uniqueId = uniqueId;
}
public String getName() {
return name;
}
protected void setName(final String name) {
this.name = name;
}
public boolean isEnabled() {
return enabled;
}
protected void setEnabled(final boolean enabled) {
this.enabled = enabled;
}
public boolean isVisible() {
return visible;
}
protected void setVisible(final boolean visible) {
this.visible = visible;
}
public boolean isAbstractCategory() {
return abstractCategory;
}
protected void setAbstractCategory(final boolean abstractCategory) {
this.abstractCategory = abstractCategory;
}
public long getCategoryOrder() {
return categoryOrder;
}
protected void setCategoryOrder(final long categoryOrder) {
this.categoryOrder = categoryOrder;
}
@Override
public int compareTo(final CategoryTableRow other) {
return Long.compare(
categoryOrder, Objects.requireNonNull(other).getCategoryOrder()
);
}
}

View File

@ -0,0 +1,61 @@
/*
* Copyright (C) 2020 LibreCCM Foundation.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301 USA
*/
package org.libreccm.ui.admin.categories;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class DomainNodeModel {
private long domainId;
private String uuid;
private String domainKey;
public long getDomainId() {
return domainId;
}
protected void setDomainId(final long domainId) {
this.domainId = domainId;
}
public String getIdentifier() {
return String.format("ID-%s", domainId);
}
public String getUuid() {
return uuid;
}
protected void setUuid(final String uuid) {
this.uuid = uuid;
}
public String getDomainKey() {
return domainKey;
}
protected void setDomainKey(final String domainKey) {
this.domainKey = domainKey;
}
}

View File

@ -9,7 +9,7 @@
shortDescription="URL to POST request is send." />
<cc:attribute name="buttonText"
required="true"
shortDescription="Text pf the button toggleing the modal form."
shortDescription="Text of the button toggleing the modal form."
type="String" />
<cc:attribute name="buttonTextClass"
default=""
@ -70,35 +70,35 @@
<c:choose>
<c:when test="#{cc.attrs.headingLevel == 1}">
<h2 class="modal-title"
id="#{cc.attrs.editorId}-dialog-title">#{cc.attrs.addDialogTitle}</h2>
id="#{cc.attrs.dialogId}-dialog-title">#{cc.attrs.dialogTitle}</h2>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 2}">
<h3 class="modal-title"
id="#{cc.attrs.editorId}-dialog-title">#{cc.attrs.addDialogTitle}</h3>
id="#{cc.attrs.dialogId}-dialog-title">#{cc.attrs.dialogTitle}</h3>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 3}">
<h4 class="modal-title"
id="#{cc.attrs.editorId}-dialog-title">#{cc.attrs.addDialogTitle}</h4>
id="#{cc.attrs.dialogId}-dialog-title">#{cc.attrs.dialogTitle}</h4>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 4}">
<h5 class="modal-title"
id="#{cc.attrs.editorId}-dialog-title">#{cc.attrs.addDialogTitle}</h5>
id="#{cc.attrs.dialogId}-dialog-title">#{cc.attrs.dialogTitle}</h5>
</c:when>
<c:when test="#{cc.attrs.headingLevel == 5}">
<h6 class="modal-title"
id="#{cc.attrs.editorId}-dialog-title">#{cc.attrs.addDialogTitle}</h6>
id="#{cc.attrs.dialogId}-dialog-title">#{cc.attrs.dialogTitle}</h6>
</c:when>
<c:otherwise>
<div>#{cc.attrs.addDialogTitle}</div>
<div>#{cc.attrs.dialogTitle}</div>
</c:otherwise>
</c:choose>
<button aria-label="#{cc.attrs.addDialogCancelLabel}"
class="close"
data-dismiss="modal"
type="button" >
<span aria-hidden="true">&times;</span>
</button>
</div>
<button aria-label="#{cc.attrs.cancelLabel}"
class="close"
data-dismiss="modal"
type="button" >
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>

View File

@ -345,7 +345,8 @@
id="#{cc.attrs.editorId}-#{entry.key}-edit-dialog"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri(cc.attrs.addMethod, { 'identifier': cc.attrs.objectIdentifier, 'locale': entry.key })}"
<form accept-charset="UTF-8"
action="#{mvc.uri(cc.attrs.editMethod, { 'identifier': cc.attrs.objectIdentifier, 'locale': entry.key })}"
class="modal-content"
method="post">
<div class="modal-header">

View File

@ -45,6 +45,23 @@
<dt>#{AdminMessages['categories.details.name']}</dt>
<dd>#{CategoryDetailsModel.name}</dd>
</div>
<div>
<dt>#{AdminMessages['categories.details.path']}</dt>
<dd>
<c:if test="#{CategoryDetailsModel.categoryPath.domain != null}">
<a href="#{mvc.uri('CategorySystemsController#getCategorySystemDetails', {'categorySystemIdentifier': CategoryDetailsModel.categoryPath.domain.identifier})}">
#{CategoryDetailsModel.categoryPath.domain.domainKey}
</a>
</c:if>
<c:forEach items="#{CategoryDetailsModel.categoryPath.categories}"
var="category" >
<span>/</span>
<a href="#{mvc.uri('CategoriesController#getCategory', {'categoryIdentifier': category.identifier})}">
#{category.name}
</a>
</c:forEach>
</dd>
</div>
<div>
<dt>#{AdminMessages['categories.details.enabled']}</dt>
<dd>
@ -62,7 +79,7 @@
<dt>#{AdminMessages['categories.details.visible']}</dt>
<dd>
<c:choose>
<c:when test="#{CategoryDetailsModel.enabled}">
<c:when test="#{CategoryDetailsModel.visible}">
#{AdminMessages['categories.details.visible.yes']}
</c:when>
<c:otherwise>
@ -75,7 +92,7 @@
<dt>#{AdminMessages['categories.details.abstract_category']}</dt>
<dd>
<c:choose>
<c:when test="#{CategoryDetailsModel.enabled}">
<c:when test="#{CategoryDetailsModel.abstractCategory}">
#{AdminMessages['categories.details.abstract_category.yes']}
</c:when>
<c:otherwise>
@ -110,10 +127,10 @@
editDialogValueHelp="#{AdminMessages['categories.details.title.edit.dialog.value.help']}"
editDialogValueLabel="#{AdminMessages['categories.details.title.edit.dialog.value.label']}"
editMethod="CategoriesController#editTitle"
editorId="categorysystem-title"
editorId="category-title"
emptyText="#{AdminMessages['categories.details.title.none']}"
hasUnusedLocales="#{CategorySystemDetailsModel.hasUnusedTitleLocales()}"
objectIdentifier="#{CategorySystemDetailsModel.identifier}"
hasUnusedLocales="#{CategoryDetailsModel.hasUnusedTitleLocales()}"
objectIdentifier="#{CategoryDetailsModel.identifier}"
removeButtonLabel="#{AdminMessages['categories.details.title.table.actions.remove']}"
removeDialogCancelLabel="#{AdminMessages['categories.details.title.remove.dialog.close']}"
removeDialogSubmitLabel="#{AdminMessages['categories.details.title.remove.dialog.submit']}"
@ -124,8 +141,8 @@
tableLocaleHeading="#{AdminMessages['categories.details.title.table.headings.locale']}"
tableValueHeading="#{AdminMessages['categories.details.title.table.headings.value']}"
title="#{AdminMessages['categories.details.title.heading']}"
unusedLocales="#{CategorySystemDetailsModel.unusedTitleLocales}"
values="#{CategorySystemDetailsModel.title}" />
unusedLocales="#{CategoryDetailsModel.unusedTitleLocales}"
values="#{CategoryDetailsModel.title}" />
<libreccm:localizedStringEditor addMethod="CategoriesController#addDescription"
addButtonLabel="#{AdminMessages['categories.details.description.add']}"
@ -143,10 +160,10 @@
editDialogValueHelp="#{AdminMessages['categories.details.description.edit.dialog.value.help']}"
editDialogValueLabel="#{AdminMessages['categories.details.description.edit.dialog.value.label']}"
editMethod="CategoriesController#editDescription"
editorId="categorysystem-description"
editorId="category-description"
emptyText="#{AdminMessages['categories.details.description.none']}"
hasUnusedLocales="#{CategorySystemDetailsModel.hasUnusedDescriptionLocales()}"
objectIdentifier="#{CategorySystemDetailsModel.identifier}"
hasUnusedLocales="#{CategoryDetailsModel.hasUnusedDescriptionLocales()}"
objectIdentifier="#{CategoryDetailsModel.identifier}"
removeButtonLabel="#{AdminMessages['categories.details.description.table.actions.remove']}"
removeDialogCancelLabel="#{AdminMessages['categories.details.description.remove.dialog.close']}"
removeDialogSubmitLabel="#{AdminMessages['categories.details.description.remove.dialog.submit']}"
@ -157,15 +174,15 @@
tableLocaleHeading="#{AdminMessages['categories.details.description.table.headings.locale']}"
tableValueHeading="#{AdminMessages['categories.details.description.table.headings.value']}"
title="#{AdminMessages['categories.details.description.heading']}"
unusedLocales="#{CategorySystemDetailsModel.unusedTitleLocales}"
unusedLocales="#{CategoryDetailsModel.unusedDescriptionLocales}"
useTextarea="true"
values="#{CategorySystemDetailsModel.description}" />
values="#{CategoryDetailsModel.description}" />
<h2>#{AdminMessages['categories.details.subcategories.heading']}</h2>
<div class="mb-2">
<div class="text-right">
<a class="btn btn-secondary"
href="#{mvc.uri('CategoriesController#newSubCategory', {'categoryIdentifier': CategorySystemDetailsModel.parentIdentifier})}">
href="#{mvc.uri('CategoriesController#newSubCategory', {'categoryIdentifier': CategoryDetailsModel.identifier})}">
<bootstrap:svgIcon icon="plus-circle" />
<span>#{AdminMessages['categories.details.subcategories.add']}</span>
</a>
@ -247,6 +264,7 @@
</tr>
</c:forEach>
</tbody>
</table>
</c:otherwise>
</c:choose>

View File

@ -24,7 +24,7 @@
</c:when>
<c:otherwise>
<li class="breadcrumb-item active">
#{AdminMessages.getMessage('categories.edit.breadcrumb', CategoryDetailsModel.name)}
#{AdminMessages.getMessage('categories.edit.breadcrumb', [ CategoryDetailsModel.name ])}
</li>
</c:otherwise>
</c:choose>
@ -35,44 +35,49 @@
<h1>
<c:choose>
<c:when test="#{CategoryDetailsModel.new}">
#{AdminMessage.getMessage('categories.new.label', CategoryDetailsModel.parent.path)}
#{AdminMessage.getMessage('categories.new.label', [ CategoryDetailsModel.parent.path ])}
</c:when>
<c:otherwise>
#{AdminMessage.getMessage('categories.edit.label', CategoryDetailsModel.path)}
#{AdminMessage.getMessage('categories.edit.label', [ CategoryDetailsModel.path ])}
</c:otherwise>
</c:choose>
#{AdminMessages['categories.label']}
</h1>
<form action="#{CategoryDetailsModel.new ? mvc.uri('CategoryFormController#createCategory', {'parentCategoryIdentifier', CategoryDetailsModel.parentCategory.identifier }) : mvc.uri('CategoryFormController#updateCategory', {'categoryIdentifier', CategoryDetailsModel.identifier })}"
<form action="#{CategoryDetailsModel.new ? mvc.uri('CategoryFormController#createCategory', {'parentCategoryIdentifier': CategoryDetailsModel.parentCategory.identifier }) : mvc.uri('CategoryFormController#updateCategory', {'categoryIdentifier': CategoryDetailsModel.identifier })}"
method="post">
<bootstrap:formGroupText help="#{AdminMessages['categories.form.name.help']}"
inputId="name"
label="#{AdminMessages['categories.form.name.label']}"
name="name"
pattern="[\\w-.]*"
required="true" />
required="true"
value="#{CategoryDetailsModel.name}" />
<bootstrap:formGroupText help="#{AdminMessages['categories.form.uniqueId.help']}"
inputId="uniqueId"
label="#{AdminMessages['categories.form.uniqueId.label']}"
name="uniqueId"
required="false" />
required="false"
value="#{CategoryDetailsModel.uniqueId}" />
<bootstrap:formCheck label="#{AdminMessages['categories.form.enabled.label']}"
inputId="enabled"
name="enabled" />
name="enabled"
value="#{CategoryDetailsModel.new ? true : CategoryDetailsModel.enabled}" />
<bootstrap:formCheck label="#{AdminMessages['categories.form.visible.label']}"
inputId="visible"
name="visible" />
name="visible"
value="#{CategoryDetailsModel.new ? true : CategoryDetailsModel.visible}"/>
<bootstrap:formCheck label="#{AdminMessages['categories.form.abstractCategory.label']}"
inputId="abstractCategory"
name="abstractCategory" />
name="abstractCategory"
value="#{CategoryDetailsModel.new ? false : CategoryDetailsModel.abstractCategory}" />
<a class="btn btn-warning"
href="#{mvc.uri('CategorySystemsController#getCategorySystems')}">
href="#{mvc.uri('CategoriesController#getCategory', {'categoryIdentifier': CategoryDetailsModel.identifier })}">
#{AdminMessages['categories.form.buttons.cancel']}
</a>
<button class="btn btn-success" type="submit">
<c:choose>
<c:when test="#{CategorySystemDetailsModel.new}">
<c:when test="#{CategoryDetailsModel.new}">
#{AdminMessages['categories.form.buttons.create']}
</c:when>
<c:otherwise>

View File

@ -336,6 +336,9 @@
<th>
#{AdminMessages['categorysystems.details.categories.table.headings.abstract']}
</th>
<th class="text-center">
#{AdminMessages['categorysystems.details.categories.table.headings.actions']}
</th>
</tr>
</thead>
<tbody>
@ -380,7 +383,7 @@
<td>
<libreccm:deleteDialog
actionTarget="#{mvc.uri('CategoriesController#removeSubCategory', {'categoryIdentifier': category.identifier})}"
buttonText="#{AdminMeesages['categories.details.subcategories.delete']}"
buttonText="#{AdminMessages['categories.details.subcategories.delete']}"
buttonTextClass="text-center"
cancelLabel="#{AdminMessages['categories.details.subcategories.delete.cancel']}"
confirmLabel="#{AdminMessages['categories.details.subcategories.delete.confirm']}"

View File

@ -397,3 +397,57 @@ categories.details.subcategories.delete.cancel=Cancel
categories.details.subcategories.delete.confirm=Delete category
categories.details.subcategories.delete.title=Delete category?
categories.details.subcategories.delete.message=Are you sure to delete category {0}?
categories.details.path=Path
categories.details.id=ID
categories.details.uuid=UUID
categories.details.uniqueId=Unique ID
categories.details.name=Name
categories.details.title.heading=Localized Title
categories.details.title.add=Add localized title
categories.details.title.none=No localized title available
categories.details.description.heading=Localized description
categories.details.description.add=Add localized description
categories.details.description.none=No localized description available
categories.details.title.add.dialog.close=Cancel
categories.details.title.add.dialog.locale.help=Select the locale of the localized title
categories.details.title.add.dialog.locale.label=Locale
categories.details.title.add.dialog.submit=Add
categories.details.title.add.dialog.title=Add localized title
categories.details.title.add.dialog.value.help=The localized title
categories.details.title.add.dialog.value.label=Localized title
categories.details.title.table.actions.edit=Edit
categories.details.title.edit.dialog.close=Cancel
categories.details.title.edit.dialog.submit=Save
categories.details.title.table.actions.edit.dialog.title=Edit localized title
categories.details.title.edit.dialog.value.help=The localized title
categories.details.title.edit.dialog.value.label=Localized title
categories.details.title.table.actions.remove=Remove
categories.details.title.remove.dialog.close=Cancel
categories.details.title.remove.dialog.submit=Remove
categories.details.title.remove.dialog.message=Are you sure to remove the localized title for the following locale:
categories.details.title.table.actions.remove.dialog.title=Remove localized title?
categories.details.title.table.headings.actions=Actions
categories.details.title.table.headings.locale=Locale
categories.details.title.table.headings.value=Value
categories.details.description.add.dialog.close=Cancel
categories.details.description.add.dialog.locale.help=The locale of the localized description
categories.details.description.add.dialog.locale.label=Localized description
categories.details.description.add.dialog.submit=Add
categories.details.description.add.dialog.title=Add localized description
categories.details.description.add.dialog.value.help=The localized description
categories.details.description.add.dialog.value.label=Localized description
categories.details.description.table.actions.edit=Edit
categories.details.description.edit.dialog.close=Cancel
categories.details.description.edit.dialog.submit=Save
categories.details.description.table.actions.edit.dialog.title=Edit localized description
categories.details.description.edit.dialog.value.help=The localized description
categories.details.description.edit.dialog.value.label=Localized description
categories.details.description.table.actions.remove=Remove
categories.details.description.remove.dialog.close=Cancel
categories.details.description.remove.dialog.submit=Remove
categories.details.description.remove.dialog.message=Are you sure to remove the localized description for the following locale:
categories.details.description.table.actions.remove.dialog.title=Remove localized description?
categories.details.description.table.headings.actions=Actions
categories.details.description.table.headings.locale=Locale
categories.details.description.table.headings.value=Value
categorysystems.details.categories.table.headings.actions=Actions

View File

@ -397,3 +397,57 @@ categories.details.subcategories.delete.cancel=Abbrechen
categories.details.subcategories.delete.confirm=Kategorie l\u00f6schen
categories.details.subcategories.delete.title=Kategorie l\u00f6schen?
categories.details.subcategories.delete.message=Sind Sie sicher, dass Sie die Kategorie {0} l\u00f6schen wollen?
categories.details.path=Pfad
categories.details.id=ID
categories.details.uuid=UUID
categories.details.uniqueId=Eindeutige ID
categories.details.name=Name
categories.details.title.heading=Lokalisierter Titel
categories.details.title.add=Lokalisierten Titel hinzuf\u00fcgen
categories.details.title.none=Keine lokalisierten Titel vorhanden
categories.details.description.heading=Lokalisierte Beschreibung
categories.details.description.add=Lokalisierte Beschreibung hinzuf\u00fcgen
categories.details.description.none=Keine lokalisierte Beschreibung vorhanden
categories.details.title.add.dialog.close=Abbrechen
categories.details.title.add.dialog.locale.help=W\u00e4hlen Sie die Sprache des lokalisierten Titels
categories.details.title.add.dialog.locale.label=Sprache
categories.details.title.add.dialog.submit=Hinzuf\u00fcgen
categories.details.title.add.dialog.title=Lokalisierten Titel hinzuf\u00fcgen
categories.details.title.add.dialog.value.help=Der lokalisierte Titel
categories.details.title.add.dialog.value.label=Lokalisierter Titel
categories.details.title.table.actions.edit=Bearbeiten
categories.details.title.edit.dialog.close=Abbrechen
categories.details.title.edit.dialog.submit=Speichern
categories.details.title.table.actions.edit.dialog.title=Lokalisierten Titel bearbeiten
categories.details.title.edit.dialog.value.help=Der lokalisierte Titel
categories.details.title.edit.dialog.value.label=Lokalisierter Titel
categories.details.title.table.actions.remove=Entfernen
categories.details.title.remove.dialog.close=Abbrechen
categories.details.title.remove.dialog.submit=Entfernen
categories.details.title.remove.dialog.message=Sind Sie sicher, dass die den lokalisierten Titlel f\u00fcr die folgende Sprache entfernen wollen:
categories.details.title.table.actions.remove.dialog.title=Lokalisierten Titel entfernen?
categories.details.title.table.headings.actions=Aktionen
categories.details.title.table.headings.locale=Sprache
categories.details.title.table.headings.value=Wert
categories.details.description.add.dialog.close=Abbrechen
categories.details.description.add.dialog.locale.help=Die Sprache der lokalisierten Beschreibung
categories.details.description.add.dialog.locale.label=Lokalisierte Beschreibung
categories.details.description.add.dialog.submit=Hinzuf\u00fcgen
categories.details.description.add.dialog.title=Lokalisierte Beschreibung hinzuf\u00fcgen
categories.details.description.add.dialog.value.help=Die lokalisierte Beschreibung
categories.details.description.add.dialog.value.label=Localized description
categories.details.description.table.actions.edit=Bearbeiten
categories.details.description.edit.dialog.close=Abbrechen
categories.details.description.edit.dialog.submit=Speichern
categories.details.description.table.actions.edit.dialog.title=Lokalisierte Beschreibung bearbeiten
categories.details.description.edit.dialog.value.help=Die lokalisierte Beschreibung
categories.details.description.edit.dialog.value.label=Lokalisierte Beschreibung
categories.details.description.table.actions.remove=Entfernen
categories.details.description.remove.dialog.close=Abbrechen
categories.details.description.remove.dialog.submit=Entfernen
categories.details.description.remove.dialog.message=Sind Sie sicher, dass Sie die lokalisierte Beschreibung f\u00fcr die folgende Sprache entfernen wollen:
categories.details.description.table.actions.remove.dialog.title=Lokalisierte Beschreibung entfernen?
categories.details.description.table.headings.actions=Aktionen
categories.details.description.table.headings.locale=Sprache
categories.details.description.table.headings.value=Wert
categorysystems.details.categories.table.headings.actions=Aktionen