Editing of title, description and owners of a category system

Former-commit-id: 9376ade5d9
pull/7/head
Jens Pelzetter 2020-11-14 22:05:23 +01:00
parent e88f99155d
commit f9dd40289d
7 changed files with 912 additions and 130 deletions

View File

@ -119,6 +119,41 @@ public class DomainManager implements Serializable {
domainRepo.save(domain);
}
/**
* Adds a {@code CcmApplication} to the owners of a {@link Domain}.If the
provided {@code CcmApplication} is already an owner of the provided
{@code Domain} the method does nothing.
*
* @param application The {@code CcmApplication} to add to the owners of the
* {@code Domain}.
* @param domain The {@code Domain} to which owners the
* {@code CcmApplication is added}.
* @param context Context for the mapping
*/
@AuthorizationRequired
@RequiresPrivilege(CategorizationConstants.PRIVILEGE_MANAGE_DOMAINS)
@Transactional(Transactional.TxType.REQUIRED)
public void addDomainOwner(
final CcmApplication application,
final Domain domain,
final String context
) {
final DomainOwnership ownership = new DomainOwnership();
ownership.setUuid(UUID.randomUUID().toString());
ownership.setDomain(domain);
ownership.setOwner(application);
ownership.setContext(context);
ownership.setOwnerOrder(domain.getOwners().size() + 1);
ownership.setDomainOrder(application.getDomains().size() + 1);
application.addDomain(ownership);
domain.addOwner(ownership);
entityManager.persist(ownership);
applicationRepo.save(application);
domainRepo.save(domain);
}
/**
* Removes a {@code CcmApplication} from the owners of a {@code Domain}. If
* the provided {@code CcmApplication} is not an owner of the provided

View File

@ -20,7 +20,12 @@ package org.libreccm.ui.admin.categories;
import org.libreccm.categorization.Domain;
import org.libreccm.categorization.DomainOwnership;
import org.libreccm.configuration.ConfigurationManager;
import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.l10n.LocalizedTextsUtil;
import org.libreccm.ui.Message;
import org.libreccm.web.ApplicationRepository;
import org.libreccm.web.CcmApplication;
import java.time.LocalDate;
import java.time.ZoneOffset;
@ -29,12 +34,14 @@ 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.Set;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.inject.Named;
import javax.transaction.Transactional;
@ -46,6 +53,12 @@ import javax.transaction.Transactional;
@Named("CategorySystemDetailsModel")
public class CategorySystemDetailsModel {
@Inject
private ApplicationRepository applicationRepository;
@Inject
private GlobalizationHelper globalizationHelper;
private long categorySystemId;
private String uuid;
@ -60,12 +73,18 @@ public class CategorySystemDetailsModel {
private Map<String, String> title;
private List<String> unusedTitleLocales;
private Map<String, String> description;
private List<String> unusedDescriptionLocales;
private List<CategorySystemOwnerRow> owners;
private List<CategorySystemOwnerOption> ownerOptions;
private final List<Message> messages;
private Set<String> invalidFields;
public CategorySystemDetailsModel() {
@ -137,14 +156,34 @@ public class CategorySystemDetailsModel {
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 List<CategorySystemOwnerRow> getOwners() {
return Collections.unmodifiableList(owners);
}
public List<CategorySystemOwnerOption> getOwnerOptions() {
return Collections.unmodifiableList(ownerOptions);
}
public boolean isNew() {
return categorySystemId == 0;
}
@ -156,15 +195,15 @@ public class CategorySystemDetailsModel {
public void addMessage(final Message message) {
messages.add(message);
}
public Set<String> getInvalidFields() {
return Collections.unmodifiableSet(invalidFields);
}
protected void addInvalidField(final String invalidField) {
invalidFields.add(invalidField);
}
protected void setInvalidFields(final Set<String> invalidFields) {
this.invalidFields = new HashSet<>(invalidFields);
}
@ -185,6 +224,8 @@ public class CategorySystemDetailsModel {
.withZone(ZoneOffset.systemDefault())
.format(domain.getReleased());
}
final List<Locale> availableLocales = globalizationHelper
.getAvailableLocales();
title = domain
.getTitle()
.getValues()
@ -196,6 +237,16 @@ public class CategorySystemDetailsModel {
entry -> entry.getValue()
)
);
final Set<Locale> titleLocales = domain
.getTitle()
.getAvailableLocales();
unusedTitleLocales = availableLocales
.stream()
.filter(locale -> !titleLocales.contains(locale))
.map(Locale::toString)
.sorted()
.collect(Collectors.toList());
description = domain
.getDescription()
.getValues()
@ -207,6 +258,15 @@ public class CategorySystemDetailsModel {
entry -> entry.getValue()
)
);
final Set<Locale> descriptionLocales = domain
.getDescription()
.getAvailableLocales();
unusedDescriptionLocales = availableLocales
.stream()
.filter(locale -> !descriptionLocales.contains(locale))
.map(Locale::toString)
.sorted()
.collect(Collectors.toList());
owners = domain
.getOwners()
@ -214,6 +274,20 @@ public class CategorySystemDetailsModel {
.map(this::buildOwnerRow)
.sorted()
.collect(Collectors.toList());
final List<CcmApplication> ownerApplications = domain
.getOwners()
.stream()
.map(DomainOwnership::getOwner)
.collect(Collectors.toList());
ownerOptions = applicationRepository
.findAll()
.stream()
.filter(application -> !ownerApplications.contains(application))
.map(CategorySystemOwnerOption::new)
.sorted()
.collect(Collectors.toList());
}
private CategorySystemOwnerRow buildOwnerRow(
@ -221,10 +295,14 @@ public class CategorySystemDetailsModel {
) {
final CategorySystemOwnerRow ownerRow = new CategorySystemOwnerRow();
ownerRow.setOwnershipId(ownership.getOwnershipId());
ownerRow.setUuid(ownership.getUuid());
ownerRow.setUuid(ownership.getOwner().getUuid());
ownerRow.setContext(ownership.getContext());
ownerRow.setOwnerOrder(ownership.getOwnerOrder());
ownerRow.setOwnerAppName(ownership.getOwner().getDisplayName());
if (ownership.getOwner().getDisplayName() == null) {
ownerRow.setOwnerAppName(ownership.getOwner().getApplicationType());
} else {
ownerRow.setOwnerAppName(ownership.getOwner().getDisplayName());
}
return ownerRow;
}

View File

@ -0,0 +1,69 @@
/*
* 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.web.CcmApplication;
import java.util.Objects;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class CategorySystemOwnerOption
implements Comparable<CategorySystemOwnerOption> {
private final long applicationId;
private final String applicationUuid;
private final String applicationName;
public CategorySystemOwnerOption(final CcmApplication application) {
applicationId = application.getObjectId();
applicationUuid = application.getUuid();
if (application.getDisplayName() == null) {
applicationName = application.getApplicationType();
} else {
applicationName = application.getDisplayName();
}
}
public long getApplicationId() {
return applicationId;
}
public String getApplicationUuid() {
return applicationUuid;
}
public String getApplicationName() {
return applicationName;
}
@Override
public int compareTo(final CategorySystemOwnerOption other) {
return Objects.compare(
applicationName,
Objects.requireNonNull(other).getApplicationName(),
String::compareTo
);
}
}

View File

@ -85,7 +85,6 @@ public class CategorySystemsController {
// public String getCategoryManager() {
// return getCategorySystems();
// }
@GET
@Path("/")
@AuthorizationRequired
@ -291,8 +290,10 @@ public class CategorySystemsController {
final Locale locale = new Locale(localeParam);
domain.getTitle().addValue(locale, value);
domainRepository.save(domain);
categorySystemDetailsModel.setCategorySystem(domain);
return "org/libreccm/ui/admin/categories/categorysystem-form.xhtml";
return String.format(
"redirect:categorymanager/categorysystems/ID-%d/details",
domain.getObjectId()
);
} else {
categorySystemDetailsModel.addMessage(
new Message(
@ -310,6 +311,7 @@ public class CategorySystemsController {
@POST
@Path("/{categorySystemIdentifier}/title/${locale}/edit")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String editTitle(
@PathParam("categorySystemIdentifier")
final String categorySystemIdentifier,
@ -345,8 +347,10 @@ public class CategorySystemsController {
final Locale locale = new Locale(localeParam);
domain.getTitle().addValue(locale, value);
domainRepository.save(domain);
categorySystemDetailsModel.setCategorySystem(domain);
return "org/libreccm/ui/admin/categories/categorysystem-form.xhtml";
return String.format(
"redirect:categorymanager/categorysystems/ID-%d/details",
domain.getObjectId()
);
} else {
categorySystemDetailsModel.addMessage(
new Message(
@ -364,11 +368,15 @@ public class CategorySystemsController {
@POST
@Path("/{categorySystemIdentifier}/title/${locale}/remove")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String removeTitle(
@PathParam("categorySystemIdentifier")
final String categorySystemIdentifier,
@PathParam("locale") final String localeParam
@PathParam("locale") final String localeParam,
@FormParam("confirmed")
final String confirmed
) {
final Identifier identifier = identifierParser.parseIdentifier(
categorySystemIdentifier
);
@ -395,11 +403,15 @@ public class CategorySystemsController {
if (result.isPresent()) {
final Domain domain = result.get();
final Locale locale = new Locale(localeParam);
domain.getTitle().removeValue(locale);
domainRepository.save(domain);
categorySystemDetailsModel.setCategorySystem(domain);
return "org/libreccm/ui/admin/categories/categorysystem-form.xhtml";
if (Objects.equals(confirmed, "true")) {
final Locale locale = new Locale(localeParam);
domain.getTitle().removeValue(locale);
domainRepository.save(domain);
}
return String.format(
"redirect:categorymanager/categorysystems/ID-%d/details",
domain.getObjectId()
);
} else {
categorySystemDetailsModel.addMessage(
new Message(
@ -417,6 +429,7 @@ public class CategorySystemsController {
@POST
@Path("/{categorySystemIdentifier}/description/add")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String addDescription(
@PathParam("categorySystemIdentifier")
final String categorySystemIdentifier,
@ -452,8 +465,10 @@ public class CategorySystemsController {
final Locale locale = new Locale(localeParam);
domain.getDescription().addValue(locale, value);
domainRepository.save(domain);
categorySystemDetailsModel.setCategorySystem(domain);
return "org/libreccm/ui/admin/categories/categorysystem-form.xhtml";
return String.format(
"redirect:categorymanager/categorysystems/ID-%d/details",
domain.getObjectId()
);
} else {
categorySystemDetailsModel.addMessage(
new Message(
@ -470,8 +485,10 @@ public class CategorySystemsController {
@POST
@Path(
"categorysystems/{categorySystemIdentifier}/description/${locale}/edit")
"categorysystems/{categorySystemIdentifier}/description/${locale}/edit"
)
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String editDescription(
@PathParam("categorySystemIdentifier")
final String categorySystemIdentifier,
@ -507,8 +524,10 @@ public class CategorySystemsController {
final Locale locale = new Locale(localeParam);
domain.getDescription().addValue(locale, value);
domainRepository.save(domain);
categorySystemDetailsModel.setCategorySystem(domain);
return "org/libreccm/ui/admin/categories/categorysystem-form.xhtml";
return String.format(
"redirect:categorymanager/categorysystems/ID-%d/details",
domain.getObjectId()
);
} else {
categorySystemDetailsModel.addMessage(
new Message(
@ -527,10 +546,13 @@ public class CategorySystemsController {
@Path(
"categorysystems/{categorySystemIdentifier}/description/${locale}/remove")
@AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED)
public String removeDescription(
@PathParam("categorySystemIdentifier")
final String categorySystemIdentifier,
@PathParam("locale") final String localeParam
@PathParam("locale") final String localeParam,
@FormParam("confirmed")
final String confirmed
) {
final Identifier identifier = identifierParser.parseIdentifier(
categorySystemIdentifier
@ -558,11 +580,15 @@ public class CategorySystemsController {
if (result.isPresent()) {
final Domain domain = result.get();
final Locale locale = new Locale(localeParam);
domain.getDescription().removeValue(locale);
domainRepository.save(domain);
categorySystemDetailsModel.setCategorySystem(domain);
return "org/libreccm/ui/admin/categories/categorysystem-form.xhtml";
if (Objects.equals(confirmed, "true")) {
final Locale locale = new Locale(localeParam);
domain.getDescription().removeValue(locale);
domainRepository.save(domain);
}
return String.format(
"redirect:categorymanager/categorysystems/ID-%d/details",
domain.getObjectId()
);
} else {
categorySystemDetailsModel.addMessage(
new Message(
@ -581,10 +607,12 @@ public class CategorySystemsController {
@Path("/{categorySystemIdentifier}/owners/add")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String addOwner(
@PathParam("categorySystemIdentifier")
final String categorySystemIdentifier,
@FormParam("applicationUuid") final String applicationUuid
@FormParam("applicationUuid") final String applicationUuid,
@FormParam("context") final String context
) {
final Identifier identifier = identifierParser.parseIdentifier(
categorySystemIdentifier
@ -628,11 +656,16 @@ public class CategorySystemsController {
}
final CcmApplication owner = appResult.get();
domainManager.addDomainOwner(owner, domain);
if (context == null
|| context.isEmpty()
|| context.matches("\\s*")) {
domainManager.addDomainOwner(owner, domain);
} else {
domainManager.addDomainOwner(owner, domain, context);
}
return String.format(
"redirect:categorymanager/categorysystems/%s",
"redirect:categorymanager/categorysystems/ID-%s/details",
categorySystemIdentifier
);
} else {
@ -650,13 +683,15 @@ public class CategorySystemsController {
}
@POST
@Path("/{categorySystemIdentifier}/owners/remove")
@Path("/{categorySystemIdentifier}/owners/${applicationUuid}/remove")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String removeOwner(
@PathParam("categorySystemIdentifier")
final String categorySystemIdentifier,
@FormParam("applicationUuid") final String applicationUuid
@PathParam("applicationUuid") final String applicationUuid,
@FormParam("confirmed") final String confirmed
) {
final Identifier identifier = identifierParser.parseIdentifier(
categorySystemIdentifier
@ -699,12 +734,13 @@ public class CategorySystemsController {
return "org/libreccm/ui/admin/categories/application-not-found.xhtml";
}
final CcmApplication owner = appResult.get();
domainManager.removeDomainOwner(owner, domain);
if (Objects.equals(confirmed, "true")) {
final CcmApplication owner = appResult.get();
domainManager.removeDomainOwner(owner, domain);
}
return String.format(
"redirect:categorymanager/categorysystems/%s",
"redirect:categorymanager/categorysystems/ID-%s/details",
categorySystemIdentifier
);
} else {

View File

@ -1,4 +1,4 @@
<!DOCTYPE html>
<!DOCTYPE html [<!ENTITY times '&#215;'>]>
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
@ -90,20 +90,92 @@
<h2>
#{AdminMessages['categorysystems.details.title.heading']}
</h2>
<div class="text-right mb-2">
<a class="btn btn-secondary"
href="#">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#circle-plus" />
</svg>
<span>#{AdminMessages['categorysystems.details.title.add']}</span>
</a>
</div>
<c:choose>
<c:if test="#{CategorySystemDetailsModel.hasUnusedTitleLocales()}">
<div class="mb-2">
<div class="text-right">
<button class="btn btn-secondary"
data-target="#categorysystem-title-add"
data-toggle="modal"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#plus-circle" />
</svg>
<span>#{AdminMessages['categorysystems.details.title.add']}</span>
</button>
</div>
<div class="modal fade"
data-backdrop="static"
id="categorysystem-title-add"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('CategorySystemsController#addTitle', {'categorySystemIdentifier': CategorySystemDetailsModel.identifier })}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="modal-title">
#{AdminMessages['categorysystems.details.title.add.dialog.title']}
</h3>
<button aria-label="#{AdminMessages['categorysystems.details.title.add.dialog.close']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="categorysystem-title-add-locale">
#{AdminMessages['categorysystems.details.title.add.dialog.locale.label']}
</label>
<select aria-describedby="categorysystem-title-add-locale-help"
id="categorysystem-title-add-locale"
name="locale"
required="true">
<c:forEach items="#{CategorySystemDetailsModel.unusedTitleLocales}" var="locale">
<option value="#{locale}">#{locale}</option>
</c:forEach>
</select>
<small class="form-text text-muted"
id="categorysystem-title-add-locale-help">
#{AdminMessages['categorysystems.details.title.add.dialog.locale.help']}
</small>
</div>
<div class="form-group">
<label for="categorysystem-title-add-value">
#{AdminMessages['categorysystems.details.title.add.dialog.value.label']}
</label>
<input aria-describedby="categorysystem-title-add-value-help"
class="form-control"
id="categorysystem-title-add-value"
name="value"
required="true"
type="text" />
<small class="form-text text-muted"
id="categorysystem-title-add-locale-help">
#{AdminMessages['categorysystems.details.title.add.dialog.value.help']}
</small>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{AdminMessages['categorysystems.details.title.add.dialog.close']}
</button>
<button type="submit" class="btn btn-primary">
#{AdminMessages['categorysystems.details.title.add.dialog.submit']}
</button>
</div>
</form>
</div>
</div>
</div>
</c:if>
<c:choose>
<c:when test="#{CategorySystemDetailsModel.getTitle().isEmpty()}">
<p>
#{AdminMessages['categorysystems.details.title.none']}
@ -131,28 +203,137 @@
#{entry.value}
</td>
<td>
<button class="btn btn-info"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#pen" />
</svg>
<span>#{AdminMessages['categorysystems.details.title.table.actions.edit']}</span>
</button>
<div class="text-center">
<button class="btn btn-info"
data-target="#categorysystem-title-#{entry.key}-edit"
data-toggle="modal"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#pen" />
</svg>
<span>#{AdminMessages['categorysystems.details.title.table.actions.edit']}</span>
</button>
</div>
<div aria-describedby="categorysystem-title-#{entry.key}-edit-title"
aria-hidden="true"
class="modal fade"
data-backdrop="static"
id="categorysystem-title-#{entry.key}-edit"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('CategorySystemsController#editTitle', {'categorySystemIdentifier': CategorySystemDetailsModel.identifier, 'locale': entry.key })}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="modal-title" id="categorysystem-title-#{entry.key}-edit-title">
#{AdminMessages['categorysystems.details.title.table.actions.edit.dialog.title']}
</h3>
<button aria-label="#{AdminMessages['categorysystems.details.title.edit.dialog.close']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<input name="locale"
value="#{entry.key}"
type="hidden" />
<div class="form-group">
<label for="categorysystem-title-#{entry.key}-edit-value">
#{AdminMessages['categorysystems.details.title.edit.dialog.value.label']}
</label>
<input aria-describedby="categorysystem-title-#{entry.key}-edit-value-help"
class="form-control"
id="categorysystem-title-#{entry.key}-edit-value"
name="value"
required="true"
type="text"
value="#{entry.value}" />
<small class="form-text text-muted"
id="categorysystem-title-#{entry.key}-edit-value-help">
#{AdminMessages['categorysystems.details.title.edit.dialog.value.help']}
</small>
</div>
</div>
<div class="modal-footer">
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{AdminMessages['categorysystems.details.title.edit.dialog.close']}
</button>
<button type="submit" class="btn btn-primary">
#{AdminMessages['categorysystems.details.title.edit.dialog.submit']}
</button>
</div>
</div>
</form>
</div>
</div>
</td>
<td>
<button class="btn btn-danger"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#x-circle" />
</svg>
<span>#{AdminMessages['categorysystems.details.title.table.actions.remove']}</span>
</button>
<div class="text-center">
<button class="btn btn-danger"
data-target="#categorysystem-title-#{entry.key}-remove"
data-toggle="modal"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#x-circle" />
</svg>
<span>#{AdminMessages['categorysystems.details.title.table.actions.remove']}</span>
</button>
</div>
<div aria-describedby="categorysystem-title-#{entry.key}-remove-title"
aria-hidden="true"
class="modal fade"
data-backdrop="static"
id="categorysystem-title-#{entry.key}-remove"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('CategorySystemsController#removeTitle', {'categorySystemIdentifier': CategorySystemDetailsModel.identifier, 'locale': entry.key })}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="modal-title" id="categorysystem-title-#{entry.key}-remove-title">
#{AdminMessages['categorysystems.details.title.table.actions.remove.dialog.title']}
</h3>
<button aria-label="#{AdminMessages['categorysystems.details.title.remove.dialog.close']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>
#{AdminMessages.getMessage('categorysystems.details.title.remove.dialog.message', [entry.key, entry.value])}
</p>
<input name="confirmed"
type="hidden"
value="true" />
</div>
<div class="modal-footer">
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{AdminMessages['categorysystems.details.title.remove.dialog.close']}
</button>
<button type="submit" class="btn btn-danger">
#{AdminMessages['categorysystems.details.title.remove.dialog.submit']}
</button>
</div>
</div>
</form>
</div>
</div>
</td>
</tr>
</c:forEach>
@ -164,21 +345,92 @@
<h2>
#{AdminMessages['categorysystems.details.description.heading']}
</h2>
<div class="text-right mb-2">
<a class="btn btn-secondary"
href="
">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#circle-plus" />
</svg>
<span>#{AdminMessages['categorysystems.details.description.add']}</span>
</a>
</div>
<c:if test="#{CategorySystemDetailsModel.hasUnusedDescriptionLocales()}">
<div class="mb-2">
<div class="text-right">
<button class="btn btn-secondary"
data-target="#categorysystem-description-add"
data-toggle="modal"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#plus-circle" />
</svg>
<span>#{AdminMessages['categorysystems.details.description.add']}</span>
</button>
</div>
</div>
<div class="modal fade"
data-backdrop="static"
id="categorysystem-description-add"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('CategorySystemsController#addDescription', {'categorySystemIdentifier': CategorySystemDetailsModel.identifier })}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="modal-title">
#{AdminMessages['categorysystems.details.description.add.dialog.title']}
</h3>
<button aria-label="#{AdminMessages['categorysystems.details.title.add.dialog.close']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="categorysystem-description-add-locale">
#{AdminMessages['categorysystems.details.description.add.dialog.locale.label']}
</label>
<select aria-describedby="categorysystem-description-add-locale-help"
id="categorysystem-description-add-locale"
name="locale"
required="true">
<c:forEach items="#{CategorySystemDetailsModel.unusedDescriptionLocales}" var="locale">
<option value="#{locale}">#{locale}</option>
</c:forEach>
</select>
<small class="form-text text-muted"
id="categorysystem-description-add-locale-help">
#{AdminMessages['categorysystems.details.description.add.dialog.locale.help']}
</small>
</div>
<div class="form-group">
<label for="categorysystem-description-add-value">
#{AdminMessages['categorysystems.details.description.add.dialog.value.label']}
</label>
<textarea aria-describedby="categorysystem-description-add-value-help"
class="form-control"
cols="80"
id="categorysystem-description-add-value"
name="value"
required="true"
rows="10"></textarea>
<small class="form-text text-muted"
id="categorysystem-description-add-locale-help">
#{AdminMessages['categorysystems.details.description.add.dialog.value.help']}
</small>
</div>
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{AdminMessages['categorysystems.details.description.add.dialog.close']}
</button>
<button type="submit" class="btn btn-primary">
#{AdminMessages['categorysystems.details.description.add.dialog.submit']}
</button>
</div>
</form>
</div>
</div>
</c:if>
<c:choose>
<c:when test="#{CategorySystemDetailsModel.getDescription().isEmpty()}">
<p>
#{AdminMessages['categorysystems.details.description.none']}
@ -196,7 +448,7 @@
</tr>
</thead>
<tbody>
<c:forEach items="#{CategorySystemDetailsModel.title}"
<c:forEach items="#{CategorySystemDetailsModel.description}"
var="entry">
<tr>
<td>
@ -206,28 +458,137 @@
#{entry.value}
</td>
<td>
<button class="btn btn-info"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#pen" />
</svg>
<span>#{AdminMessages['categorysystems.details.description.table.actions.edit']}</span>
</button>
<div class="text-center">
<button class="btn btn-info"
data-target="#categorysystem-description-#{entry.key}-edit"
data-toggle="modal"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#pen" />
</svg>
<span>#{AdminMessages['categorysystems.details.description.table.actions.edit']}</span>
</button>
</div>
<div aria-describedby="categorysystem-description-#{entry.key}-edit-title"
aria-hidden="true"
class="modal fade"
data-backdrop="static"
id="categorysystem-description-#{entry.key}-edit"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('CategorySystemsController#editDescription', {'categorySystemIdentifier': CategorySystemDetailsModel.identifier, 'locale': entry.key })}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="modal-title"
id="categorysystem-description-#{entry.key}-edit-title">
#{AdminMessages['categorysystems.details.description.table.actions.edit.dialog.title']}
</h3>
<button aria-label="#{AdminMessages['categorysystems.details.description.edit.dialog.close']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<input name="locale"
value="#{entry.key}"
type="hidden" />
<div class="form-group">
<label for="categorysystem-description-#{entry.key}-edit-value">
#{AdminMessages['categorysystems.details.description.edit.dialog.value.label']}
</label>
<textarea aria-describedby="categorysystem-description-#{entry.key}-edit-value-help"
class="form-control"
cols="80"
id="categorysystem-description-#{entry.key}-edit-value"
name="value"
required="true"
rows="10"
type="text">#{entry.value}</textarea>
<small class="form-text text-muted"
id="categorysystem-description-#{entry.key}-edit-value-help">
#{AdminMessages['categorysystems.details.description.edit.dialog.value.help']}
</small>
</div>
</div>
<div class="modal-footer">
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{AdminMessages['categorysystems.details.description.edit.dialog.close']}
</button>
<button type="submit" class="btn btn-primary">
#{AdminMessages['categorysystems.details.description.edit.dialog.submit']}
</button>
</div>
</div>
</form>
</div>
</div>
</td>
<td>
<button class="btn btn-danger"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#x-circle" />
</svg>
<span>#{AdminMessages['categorysystems.details.description.table.actions.remove']}</span>
</button>
<div class="text-center">
<button class="btn btn-danger"
data-target="#categorysystem-description-#{entry.key}-remove"
data-toggle="modal"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#x-circle" />
</svg>
<span>#{AdminMessages['categorysystems.details.description.table.actions.remove']}</span>
</button>
</div>
<div aria-describedby="categorysystem-description-#{entry.key}-remove-title"
aria-hidden="true"
class="modal fade"
data-backdrop="static"
id="categorysystem-description-#{entry.key}-remove"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('CategorySystemsController#removeDescription', {'categorySystemIdentifier': CategorySystemDetailsModel.identifier, 'locale': entry.key })}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="modal-description" id="categorysystem-description-#{entry.key}-remove-title">
#{AdminMessages['categorysystems.details.description.table.actions.remove.dialog.title']}
</h3>
<button aria-label="#{AdminMessages['categorysystems.details.description.remove.dialog.close']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>
#{AdminMessages.getMessage('categorysystems.details.description.remove.dialog.message', [entry.key, entry.value])}
</p>
<input name="confirmed"
type="hidden"
value="true" />
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{AdminMessages['categorysystems.details.description.remove.dialog.close']}
</button>
<button type="submit" class="btn btn-danger">
#{AdminMessages['categorysystems.details.description.remove.dialog.submit']}
</button>
</div>
</form>
</div>
</div>
</td>
</tr>
</c:forEach>
@ -239,18 +600,88 @@
<h2>
#{AdminMessages['categorysystems.details.owners.heading']}
</h2>
<div class="text-right mb-2">
<a class="btn btn-secondary"
href="
">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#circle-plus" />
</svg>
<span>#{AdminMessages['categorysystems.details.owners.add']}</span>
</a>
<div class="mb-2">
<div class="text-right">
<button class="btn btn-secondary"
data-target="#categorysystem-owner-add"
data-toggle="modal"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#plus-circle" />
</svg>
<span>#{AdminMessages['categorysystems.details.owners.add']}</span>
</button>
</div>
<div class="modal fade"
data-backdrop="static"
id="categorysystem-owner-add"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('CategorySystemsController#addOwner', {'categorySystemIdentifier': CategorySystemDetailsModel.identifier })}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="modal-title">
#{AdminMessages['categorysstems.details.owner.add.dialog.title']}
</h3>
<button aria-label="#{AdminMessages['categorysystems.details.owner.add.dialog.close']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="categorysystem-owner-add-application">
#{AdminMessages['categorysystems.details.owner.add.dialog.application.label']}
</label>
<select aria-describedby="categorysystem-owner-add-application-help"
id="categorysystem-owner-add-appliaction"
name="applicationUuid"
required="true"
size="1">
<c:forEach items="#{CategorySystemDetailsModel.ownerOptions}" var="application">
<option value="#{application.applicationUuid}">
#{application.applicationName}
</option>
</c:forEach>
</select>
<small class="form-text text-muted"
id="categorysystem-owner-add-application-help">
#{AdminMessages['categorysystems.details.owner.add.dialog.application.help']}
</small>
</div>
<div class="form-group">
<label for="categorysystem-owner-add-context">
#{AdminMessages['categorysystems.details.owner.add.dialog.context.label']}
</label>
<input aria-describedby="categorysystem-owner-add-context-help"
id="categorysystem-owner-add-context"
name="context"
type="text" />
<small class="form-text text-muted"
id="categorysystem-owner-add-context-help">
#{AdminMessages['categorysystems.details.owner.add.dialog.context.help']}
</small>
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{AdminMessages['categorysystems.details.owner.add.dialog.close']}
</button>
<button type="submit" class="btn btn-primary">
#{AdminMessages['categorysystems.details.owner.add.dialog.submit']}
</button>
</div>
</div>
</form>
</div>
</div>
</div>
<c:choose>
<c:when test="#{CategorySystemDetailsModel.getOwners().isEmpty()}">
@ -259,7 +690,7 @@
</p>
</c:when>
<c:otherwise>
<table>
<table class="table table-hover">
<thead>
<tr>
<th>
@ -284,16 +715,63 @@
#{owner.context}
</td>
<td>
<button class="btn btn-danger"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#x-circle" />
</svg>
<span>#{AdminMessages['categorysystems.details.owners.remove']}</span>
</button>
<div class="text-center">
<button class="btn btn-danger"
data-target="#categorysystem-owner-#{owner.uuid}-remove"
data-toggle="modal"
type="button">
<svg class="bi"
width="1em"
height="1em"
fill="currentColor">
<use xlink:href="#{request.contextPath}/assets/bootstrap/bootstrap-icons.svg#x-circle" />
</svg>
<span>#{AdminMessages['categorysystems.details.owners.remove']}</span>
</button>
</div>
<div aria-describedby="categorysystem-owner-#{owner.uuid}-remove-title"
aria-hidden="true"
class="modal fade"
data-backdrop="static"
id="categorysystem-owner-#{owner.uuid}-remove"
tabindex="-1">
<div class="modal-dialog">
<form action="#{mvc.uri('CategorySystemsController#removeOwner', { 'categorySystemIdentifier': CategorySystemDetailsModel.identifier, 'applicationUuid': owner.uuid })}"
class="modal-content"
method="post">
<div class="modal-header">
<h3 class="modal-title"
id="categorysystem-owner-#{owner.uuid}-remove-title">
#{AdminMessages['categorysystems.details.owners.remove.title']}
</h3>
<button aria-label="#{AdminMessages['categorysystems.details.owners.remove.close']}"
class="close"
data-dismiss="modal"
type="button">
<span aria-hidden="true">&times;</span>
</button>
</div>
<div class="modal-body">
<p>
#{AdminMessages.getMessage('categorysystems.details.owners.remove.message', [owner.ownerAppName])}
</p>
<input type="hidden"
name="confirmed"
value="true" />
</div>
<div class="modal-footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{AdminMessages['categorysystems.details.owners.remove.close']}
</button>
<button type="submit" class="btn btn-danger">
#{AdminMessages['categorysystems.details.owners.remove.submit']}
</button>
</div>
</form>
</div>
</div>
</td>
</tr>
</c:forEach>

View File

@ -301,3 +301,46 @@ categorysystems.delete.confirm.title=Confirm Delete
categorysystems.delete.confirm.message=Are you sure to delete the category system {0} and all its categories?
categorysystems.delete.confirm.cancel=Cancel
categorysystems.delete.confirm.yes=Delete Category System
categorysystems.details.title.add.dialog.title=Add localized title
categorysystems.details.title.add.dialog.close=Cancel
categorysystems.details.title.add.dialog.submit=Add title
categorysystems.details.title.add.dialog.value.label=Localized title
categorysystems.details.title.add.dialog.value.help=The localized title to add
categorysystems.details.title.add.dialog.locale.label=Locale
categorysystems.details.title.add.dialog.locale.help=The locale (language) of the title value to add
categorysystems.details.title.table.actions.edit.dialog.title=Edit title
categorysystems.details.title.edit.dialog.close=Cancel
categorysystems.details.title.edit.dialog.value.label=Localized Title
categorysystems.details.title.edit.dialog.value.help=The new value for the title
categorysystems.details.title.edit.dialog.submit=Save
categorysystems.details.title.table.actions.remove.dialog.title=Remove localized title
categorysystems.details.title.remove.dialog.close=Cancel
categorysystems.details.title.remove.dialog.message=Are your sure to delete title "{1}" for locale?
categorysystems.details.title.remove.dialog.submit=Delete title
categorysystems.details.description.add.dialog.title=Add localized description
categorysystems.details.description.add.dialog.locale.label=Locale
categorysystems.details.description.add.dialog.locale.help=The locale (language) of the description value to add
categorysystems.details.description.add.dialog.value.label=Localized description
categorysystems.details.description.add.dialog.value.help=The localized description to add
categorysystems.details.description.add.dialog.close=Cancel
categorysystems.details.description.add.dialog.submit=Add description
categorysystems.details.description.table.actions.edit.dialog.title=Edit description
categorysystems.details.description.edit.dialog.close=Cancel
categorysystems.details.description.edit.dialog.value.label=Localized description
categorysystems.details.description.edit.dialog.value.help=The localized description
categorysystems.details.description.edit.dialog.submit=Save
categorysystems.details.description.table.actions.remove.dialog.title=Removed localized description
categorysystems.details.description.remove.dialog.close=Cancel
categorysystems.details.description.remove.dialog.message=Are your sure to delete the description for locale {0}?
categorysystems.details.description.remove.dialog.submit=Remove localized description
categorysstems.details.owner.add.dialog.title=Add Application Mapping
categorysystems.details.owner.add.dialog.application.label=Application
categorysystems.details.owner.add.dialog.application.help=Application for that a new mapping is added
categorysystems.details.owner.add.dialog.close=Cancel
categorysystems.details.owner.add.dialog.submit=Add application mapping
categorysystems.details.owners.remove.title=Remove application mapping
categorysystems.details.owners.remove.close=Cancel
categorysystems.details.owners.remove.message=Are your sure to remove the mapping for application {0}?
categorysystems.details.owners.remove.submit=Remove mapping
categorysystems.details.owner.add.dialog.context.label=Context
categorysystems.details.owner.add.dialog.context.help=Context for the mapping

View File

@ -301,3 +301,46 @@ categorysystems.delete.confirm.title=L\u00f6schen best\u00e4tigen
categorysystems.delete.confirm.message=Sind Sie sicher, dass Sie das Kategoriensystem {0} mit allen seinen Kategorien l\u00f6schen wollen?
categorysystems.delete.confirm.cancel=Abbrechen
categorysystems.delete.confirm.yes=Kategoriensystem l\u00f6schen
categorysystems.details.title.add.dialog.title=Lokalisierten Titel hinzuf\u00fcgen
categorysystems.details.title.add.dialog.close=Abbrechen
categorysystems.details.title.add.dialog.submit=Titel hinzuf\u00fcgen
categorysystems.details.title.add.dialog.value.label=Lokalisierter Titel
categorysystems.details.title.add.dialog.value.help=Der hinzuzuf\u00fcgendende Titel
categorysystems.details.title.add.dialog.locale.label=Sprache
categorysystems.details.title.add.dialog.locale.help=Die Sprache des Titels
categorysystems.details.title.table.actions.edit.dialog.title=Titel bearbeiten
categorysystems.details.title.edit.dialog.close=Abbrechen
categorysystems.details.title.edit.dialog.value.label=Lokalisierter Titel
categorysystems.details.title.edit.dialog.value.help=Neuer Wert f\u00fcr den Titel
categorysystems.details.title.edit.dialog.submit=Speichern
categorysystems.details.title.table.actions.remove.dialog.title=Lokalisierten Titel entfernen
categorysystems.details.title.remove.dialog.close=Abbrechen
categorysystems.details.title.remove.dialog.message=Sind Sie sicher, dass Sie den Titel "{1}" f\u00fcr die Sprache {0} entfernen wollen?
categorysystems.details.title.remove.dialog.submit=Titel entfernen
categorysystems.details.description.add.dialog.title=Lokalisierte Beschreibung hinzuf\u00fcgen
categorysystems.details.description.add.dialog.locale.label=Sprache
categorysystems.details.description.add.dialog.locale.help=Die Sprache der Beschreibung
categorysystems.details.description.add.dialog.value.label=Lokalisierte Beschreibung
categorysystems.details.description.add.dialog.value.help=Die hinzuzuf\u00fcgende Beschreibung
categorysystems.details.description.add.dialog.close=Abbrechen
categorysystems.details.description.add.dialog.submit=Beschreibung hinzuf\u00fcgen
categorysystems.details.description.table.actions.edit.dialog.title=Beschreibung bearbeiten
categorysystems.details.description.edit.dialog.close=Abbrechen
categorysystems.details.description.edit.dialog.value.label=Lokalisierte Beschreibung
categorysystems.details.description.edit.dialog.value.help=Die lokalisierte Beschreibung
categorysystems.details.description.edit.dialog.submit=Speichern
categorysystems.details.description.table.actions.remove.dialog.title=Lokalisierte Beschreibung entfernen
categorysystems.details.description.remove.dialog.close=Abbrechen
categorysystems.details.description.remove.dialog.message=Sind Sie sicher das die Beschreibung f\u00fcr die Sprache {0} entfernen wollen?
categorysystems.details.description.remove.dialog.submit=Lokalisierte Beschreibung entfernen
categorysstems.details.owner.add.dialog.title=Applikation hinzuf\u00fcgen
categorysystems.details.owner.add.dialog.application.label=Anwendung
categorysystems.details.owner.add.dialog.application.help=Hinzuzuf\u00fcgende Anwendung
categorysystems.details.owner.add.dialog.close=Abbrechen
categorysystems.details.owner.add.dialog.submit=Anwendung hinzuf\u00fcgen
categorysystems.details.owners.remove.title=Anwendung entfernen
categorysystems.details.owners.remove.close=Cancel
categorysystems.details.owners.remove.message=Sind Sie sicher das die Application {0} entfernen wollen?
categorysystems.details.owners.remove.submit=Zuordnung entfernen
categorysystems.details.owner.add.dialog.context.label=Context
categorysystems.details.owner.add.dialog.context.help=Context for the mapping