Applications administration, Shortcuts administration

Jens Pelzetter 2020-11-28 17:53:01 +01:00
parent 21633451bc
commit b610f9258c
16 changed files with 294 additions and 129 deletions

View File

@ -216,6 +216,14 @@
<include>WEB-INF/</include>
</includes>
</overlay>
<overlay>
<groupId>org.libreccm</groupId>
<artifactId>ccm-shortcuts</artifactId>
<type>jar</type>
<includes>
<include>WEB-INF/</include>
</includes>
</overlay>
<overlay>
<groupId>org.libreccm</groupId>
<artifactId>ccm-core</artifactId>

View File

@ -101,5 +101,11 @@
<Logger name="com.arsdigita.web.DefaultApplicationFileResolver"
level="debug">
</Logger>
<Logger name = "org.libreccm.ui.admin.AdminApplication"
level="debug">
</Logger>
<Logger name="org.libreccm.ui.admin.applications.ApplicationsPage"
level="debug">
</Logger>
</Loggers>
</Configuration>

View File

@ -18,9 +18,12 @@
*/
package org.libreccm.ui.admin;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.ui.IsAuthenticatedFilter;
import java.util.HashSet;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
@ -38,6 +41,10 @@ import javax.ws.rs.core.Application;
@ApplicationPath("/@admin")
public class AdminApplication extends Application {
private static final Logger LOGGER = LogManager.getLogger(
AdminApplication.class
);
/**
* Injection point for the admin pages.
*/
@ -58,12 +65,11 @@ public class AdminApplication extends Application {
.collect(Collectors.toSet())
);
return classes;
LOGGER.debug(
"Adding classes to AdminApplication: {}", Objects.toString(classes)
);
// final Set<Class<?>> classes = new HashSet<>();
// classes.add(SystemInformationController.class);
//// classes.add(UsersApi.class);
// return classes;
return classes;
}
}

View File

@ -32,13 +32,11 @@ import java.util.Map;
import java.util.stream.Collectors;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.enterprise.util.AnnotationLiteral;
import javax.inject.Inject;
import javax.mvc.Controller;
import javax.mvc.Models;
import javax.mvc.MvcContext;
import javax.transaction.Transactional;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
@ -63,17 +61,14 @@ public class ApplicationsController {
@Inject
private Models models;
@Inject
private MvcContext mvc;
@Inject
@Any
private Instance<ApplicationController> applicationControllers;
// @Inject
// private MvcContext mvc;
@GET
@Path("/")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String getApplicationTypes() {
final List<ApplicationTypeInfoItem> appTypes = appManager
.getApplicationTypes()
@ -104,46 +99,26 @@ public class ApplicationsController {
appRepository.findByType(applicationType.name()).size()
);
final IsApplicationControllerForLiteral literal
= new IsApplicationControllerForLiteral(applicationType.name());
final Class<? extends ApplicationController> controllerClass
= applicationType.applicationController();
final Instance<ApplicationController> instance = applicationControllers
.select(literal);
if (instance.isResolvable()) {
final ApplicationController controller = instance.get();
if (!DefaultApplicationController.class
.isAssignableFrom(controllerClass)) {
// item.setControllerLink(
// mvc.uri(
// String.format(
// "%s#getApplication", controllerClass.getSimpleName()
// )
// ).toString()
// );
item.setControllerLink(
mvc.uri(
String.format(
"%s#getApplication",
controller.getClass().getSimpleName()
)
).toString()
controllerClass.getSimpleName())
);
}
return item;
}
private class IsApplicationControllerForLiteral
extends AnnotationLiteral<IsApplicationControllerFor>
implements IsApplicationControllerFor {
private static final long serialVersionUID = 1L;
private final String value;
public IsApplicationControllerForLiteral(
final String value
) {
this.value = value;
}
@Override
public String value() {
return value;
}
}
}

View File

@ -18,15 +18,17 @@
*/
package org.libreccm.ui.admin.applications;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.ui.admin.AdminConstants;
import org.libreccm.ui.admin.AdminPage;
import org.libreccm.web.ApplicationManager;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;
import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Any;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
/**
@ -36,19 +38,26 @@ import javax.inject.Inject;
@ApplicationScoped
public class ApplicationsPage implements AdminPage {
private static final Logger LOGGER = LogManager.getLogger(
ApplicationsPage.class
);
@Inject
@Any
private Instance<ApplicationController> applicationControllers;
private ApplicationManager applicationManager;
@Override
public Set<Class<?>> getControllerClasses() {
final Set<Class<?>> classes = new HashSet<>();
classes.add(ApplicationsController.class);
applicationControllers
classes.addAll(
applicationManager
.getApplicationTypes()
.entrySet()
.stream()
.map(controller -> controller.getClass())
.forEach(classes::add);
.map(type -> type.getValue().applicationController())
.collect(Collectors.toSet())
);
return classes;
}

View File

@ -18,31 +18,22 @@
*/
package org.libreccm.ui.admin.applications;
import org.libreccm.web.CcmApplication;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import javax.enterprise.context.RequestScoped;
import javax.mvc.Controller;
import javax.ws.rs.Path;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@Qualifier
@Retention(RetentionPolicy.RUNTIME)
@Target(
{
ElementType.METHOD,
ElementType.FIELD,
ElementType.PARAMETER,
ElementType.TYPE
}
)
public @interface IsApplicationControllerFor {
@RequestScoped
@Controller
@Path("/application")
public class DefaultApplicationController implements ApplicationController {
String value();
@Override
public String getApplication() {
return "";
}
}

View File

@ -23,6 +23,9 @@ import com.arsdigita.ui.admin.applications.AbstractAppSettingsPane;
import com.arsdigita.ui.admin.applications.DefaultApplicationInstanceForm;
import com.arsdigita.ui.admin.applications.DefaultApplicationSettingsPane;
import org.libreccm.ui.admin.applications.ApplicationController;
import org.libreccm.ui.admin.applications.DefaultApplicationController;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
@ -119,4 +122,6 @@ public @interface ApplicationType {
Class<? extends AbstractAppSettingsPane> settingsPane() default DefaultApplicationSettingsPane.class;
Class<? extends ApplicationController> applicationController() default DefaultApplicationController.class;
}

View File

@ -53,6 +53,7 @@
<div class="form-group">
<label for="#{cc.attrs.inputId}">${cc.attrs.label}</label>
<input aria-describedby="#{cc.attrs.inputId}-help"
class="form-control"
id="#{cc.attrs.inputId}"
maxlength="#{(not empty cc.attrs.maxlength) ? cc.attrs.maxlength : null}"
minlength="#{(not empty cc.attrs.minlength) ? cc.attrs.minlength : null}"

View File

@ -1,7 +1,6 @@
<!DOCTYPE html>
<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"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/libreccm/ui/admin/ccm-admin.xhtml">
@ -23,12 +22,14 @@
<li class="list-group-item">
<div class="d-flex w-100 justify-content-between align-items-center">
<h2>
<c:choose>
<c:when test="#{type.controllerLink != null}">
<a href="#{type.controllerLink}">#{type.title}</a>
<a href="#{mvc.uri(type.controllerLink)}">#{type.title}</a>
</c:when>
<c:otherwise>
#{type.title}
<span>#{type.title}</span>
</c:otherwise>
</c:choose>
</h2>
<small class="badge badge-info badge-pill">
<c:choose>

View File

@ -2,10 +2,10 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:bootstrap="http://xmlns.jcp.org/jsf/composite/components/bootstrap"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:libreccm="http://xmlns.jcp.org/jsf/composite/components/libreccm"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets"
xmlns:f="http://xmlns.jcp.org/jsf/core">
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/libreccm/ui/admin/ccm-admin.xhtml">
<ui:param name="activePage" value="categories" />

View File

@ -27,6 +27,7 @@ import org.libreccm.modules.RequiredModule;
import org.libreccm.modules.ShutdownEvent;
import org.libreccm.modules.UnInstallEvent;
import org.libreccm.shortcuts.ui.ShortcutsSettingsPane;
import org.libreccm.ui.admin.applications.shortcuts.ShortcutsApplicationController;
import org.libreccm.web.ApplicationType;
/**
@ -40,11 +41,15 @@ import org.libreccm.web.ApplicationType;
@RequiredModule(module = CcmCore.class)
},
applicationTypes = {
@ApplicationType(name = ShortcutsConstants.SHORTCUTS_APP_TYPE,
@ApplicationType(
name = ShortcutsConstants.SHORTCUTS_APP_TYPE,
descBundle = ShortcutsConstants.SHORTCUTS_BUNDLE,
singleton = true,
settingsPane = ShortcutsSettingsPane.class,
creator = ShortcutsApplicationCreator.class)})
creator = ShortcutsApplicationCreator.class,
applicationController = ShortcutsApplicationController.class
)}
)
public class Shortcuts implements CcmModule {
@Override

View File

@ -18,17 +18,25 @@
*/
package org.libreccm.ui.admin.applications.shortcuts;
import org.libreccm.core.CoreConstants;
import org.libreccm.security.AuthorizationRequired;
import org.libreccm.security.RequiresPrivilege;
import org.libreccm.shortcuts.Shortcut;
import org.libreccm.shortcuts.ShortcutRepository;
import org.libreccm.shortcuts.ShortcutsConstants;
import org.libreccm.ui.admin.applications.ApplicationController;
import org.libreccm.ui.admin.applications.IsApplicationControllerFor;
import java.util.Optional;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.mvc.Controller;
import javax.mvc.Models;
import javax.transaction.Transactional;
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;
/**
*
@ -36,8 +44,7 @@ import javax.ws.rs.Path;
*/
@RequestScoped
@Controller
//@IsApplicationControllerFor(ShortcutsConstants.SHORTCUTS_APP_TYPE)
@Path("/application")
@Path("/applications/shortcuts")
public class ShortcutsApplicationController implements ApplicationController {
@Inject
@ -48,6 +55,9 @@ public class ShortcutsApplicationController implements ApplicationController {
@GET
@Path("/")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
@Override
public String getApplication() {
models.put("shortcuts", shortcutRepository.findAll());
@ -55,4 +65,64 @@ public class ShortcutsApplicationController implements ApplicationController {
return "org/libreccm/ui/admin/applications/shortcuts/shortcuts.xhtml";
}
@POST
@Path("/add")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String addShortcut(
@FormParam("urlKey") final String urlKey,
@FormParam("redirect") final String redirect
) {
final Shortcut shortcut = new Shortcut();
shortcut.setUrlKey(urlKey);
shortcut.setRedirect(redirect);
shortcutRepository.save(shortcut);
return "redirect:applications/shortcuts";
}
@POST
@Path("/{shortcutId}/edit")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String updateShortcut(
@PathParam("shortcutId") final long shortcutId,
@FormParam("urlKey") final String urlKey,
@FormParam("redirect") final String redirect
) {
final Optional<Shortcut> result = shortcutRepository
.findById(shortcutId);
if (result.isPresent()) {
final Shortcut shortcut = result.get();
shortcut.setUrlKey(urlKey);
shortcut.setRedirect(redirect);
shortcutRepository.save(shortcut);
}
return "redirect:applications/shortcuts";
}
@POST
@Path("/{shortcutId}/remove")
@AuthorizationRequired
@RequiresPrivilege(CoreConstants.PRIVILEGE_ADMIN)
@Transactional(Transactional.TxType.REQUIRED)
public String removeShortcut(
@PathParam("shortcutId") final long shortcutId
) {
final Optional<Shortcut> result = shortcutRepository
.findById(shortcutId);
if (result.isPresent()) {
shortcutRepository.delete(result.get());
}
return "redirect:applications/shortcuts";
}
}

View File

@ -2,7 +2,9 @@
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:bootstrap="http://xmlns.jcp.org/jsf/composite/components/bootstrap"
xmlns:c="http://xmlns.jcp.org/jsp/jstl/core"
xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:h="http://xmlns.jcp.org/jsf/html"
xmlns:libreccm="http://xmlns.jcp.org/jsf/composite/components/libreccm"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets">
<ui:composition template="/WEB-INF/views/org/libreccm/ui/admin/ccm-admin.xhtml">
@ -22,19 +24,43 @@
<div class="container">
<h1>#{ShortcutAdminMessages['application_title']}</h1>
<div class="text-right mb-2">
<a class="btn btn-secondary"
href="#">
<bootstrap:svgIcon icon="plus-circle" />
<span>#{ShortcutAdminMessages['shortcuts.ui.admin.add_shortcut']}</span>
</a>
<div class="mb-2">
<bootstrap:modalForm actionTarget="#{mvc.uri('ShortcutsApplicationController#addShortcut')}"
buttonIcon="plus-circle"
buttonText="#{ShortcutAdminMessages['shortcuts.ui.admin.add_shortcut']}"
buttonTextClass="text-right"
dialogId="shortcuts-add-form">
<f:facet name="title">
<h3>#{ShortcutAdminMessages['shortcuts.ui.admin.add_shortcut.dialog.title']}</h3>
</f:facet>
<f:facet name="body">
<bootstrap:formGroupText help="#{ShortcutAdminMessages['shortcuts.ui.admin.add_shortcut.dialog.urlkey.help']}"
inputId="shortcuts-add-form-urlkey"
label="#{ShortcutAdminMessages['shortcuts.ui.admin.add_shortcut.dialog.urlkey.label']}"
name="urlKey" />
<bootstrap:formGroupText help="#{ShortcutAdminMessages['shortcuts.ui.admin.add_shortcut.dialog.redirect.help']}"
inputId="shortcuts-add-form-redirect"
label="#{ShortcutAdminMessages['shortcuts.ui.admin.add_shortcut.dialog.redirect.label']}"
name="redirect" />
</f:facet>
<f:facet name="footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{ShortcutAdminMessages['shortcuts.ui.admin.add_shortcut.dialog.cancel']}
</button>
<button type="submit" class="btn btn-primary">
#{ShortcutAdminMessages['shortcuts.ui.admin.add_shortcut.dialog.submit']}
</button>
</f:facet>
</bootstrap:modalForm>
</div>
<table class="table table-hover">
<thead>
<tr>
<th>#{ShortcutAdminMessages['shortcuts.ui.admin.shortcuts_table.col_url_key.header']}</th>
<th>#{ShortcutAdminMessages['shortcuts.ui.admin.shortcuts_table.col_redirect.header']}</th>
<th class="text-center" colspan="2"><th>#{ShortcutAdminMessages['shortcuts.ui.admin.shortcuts_table.col_actions.header']}</th></th>
<th class="text-center" colspan="2">#{ShortcutAdminMessages['shortcuts.ui.admin.shortcuts_table.col_actions.header']}</th>
</tr>
</thead>
<tbody>
@ -43,18 +69,46 @@
<td>#{shortcut.urlKey}</td>
<td>#{shortcut.redirect}</td>
<td>
<a class="btn btn-info"
href="#">
<bootstrap:svgIcon icon="pen"/>
#{ShortcutAdminMessages['shortcuts.ui.admin.shortcuts_table.edit']}
</a>
<bootstrap:modalForm actionTarget="#{mvc.uri('ShortcutsApplicationController#updateShortcut', { 'shortcutId': shortcut.shortcutId })}"
buttonIcon="pen"
buttonText="#{ShortcutAdminMessages['shortcuts.ui.admin.shortcuts_table.edit']}"
buttonTextClass="text-center"
dialogId="shortcut-#{shortcut.shortcutId}-edit-form">
<f:facet name="title">
<h3>#{ShortcutAdminMessages['shortcuts.ui.admin.edit_shortcut.dialog.title']}</h3>
</f:facet>
<f:facet name="body">
<bootstrap:formGroupText help="#{ShortcutAdminMessages['shortcuts.ui.admin.edit_shortcut.dialog.urlkey.help']}"
inputId="shortcut-#{shortcut.shortcutId}-edit-form-urlkey"
label="#{ShortcutAdminMessages['shortcuts.ui.admin.edit_shortcut.dialog.urlkey.label']}"
name="urlKey"
value="#{shortcut.urlKey}" />
<bootstrap:formGroupText help="#{ShortcutAdminMessages['shortcuts.ui.admin.edit_shortcut.dialog.redirect.help']}"
inputId="shortcut-#{shortcut.shortcutId}-edit-form-redirect"
label="#{ShortcutAdminMessages['shortcuts.ui.admin.edit_shortcut.dialog.redirect.label']}"
name="redirect"
value="#{shortcut.redirect}" />
</f:facet>
<f:facet name="footer">
<button class="btn btn-secondary"
data-dismiss="modal"
type="button" >
#{ShortcutAdminMessages['shortcuts.ui.admin.edit_shortcut.dialog.cancel']}
</button>
<button type="submit" class="btn btn-primary">
#{ShortcutAdminMessages['shortcuts.ui.admin.edit_shortcut.dialog.submit']}
</button>
</f:facet>
</bootstrap:modalForm>
</td>
<td>
<a class="btn btn-danger"
href="#">
<bootstrap:svgIcon icon="x-circle"/>
#{ShortcutAdminMessages['shortcuts.ui.admin.shortcuts_table.delete']}
</a>
<libreccm:deleteDialog actionTarget="#{mvc.uri('ShortcutsApplicationController#removeShortcut', { 'shortcutId': shortcut.shortcutId })}"
buttonText="#{ShortcutAdminMessages['shortcuts.ui.admin.shortcuts_table.delete']}"
cancelLabel="#{ShortcutAdminMessages['shortcuts.ui.admin.delete_dialog.cancel']}"
confirmLabel="#{ShortcutAdminMessages['shortcuts.ui.admin.delete_dialog.confirm']}"
dialogId="remove-shortcut-dialog-#{shortcut.shortcutId}"
dialogTitle="#{ShortcutAdminMessages['shortcuts.ui.admin.delete_dialog.title']}"
message="#{ShortcutAdminMessages.getMessage('shortcuts.ui.admin.delete_dialog.message', [shortcut.urlKey, shortcut.redirect])}"/>
</td>
</tr>
</c:forEach>

View File

@ -33,3 +33,20 @@ shortcuts.ui.admin.redirect.error.invalid=The target of the redirect must be a a
shortcuts.ui.admin.heading=Manage shortcuts
shortcuts.ui.admin.table.empty=No shortcuts definied yet
shortcuts.ui.admin.add_shortcut=Add shortcut
shortcuts.ui.admin.delete_dialog.cancel=Cancel
shortcuts.ui.admin.delete_dialog.confirm=Remove shortcut
shortcuts.ui.admin.delete_dialog.title=Confirm removal of shortcut
shortcuts.ui.admin.delete_dialog.message=Are you sure to remove the shortcut which redirects the URL {0} to {1}?
shortcuts.ui.admin.add_shortcut.dialog.title=Add shortcut
shortcuts.ui.admin.add_shortcut.dialog.urlkey.help=The short URL to redirect
shortcuts.ui.admin.add_shortcut.dialog.urlkey.label=Short URL
shortcuts.ui.admin.add_shortcut.dialog.redirect.help=The target URL to which the user is redirected
shortcuts.ui.admin.add_shortcut.dialog.redirect.label=Redirect target
shortcuts.ui.admin.add_shortcut.dialog.cancel=Cancel
shortcuts.ui.admin.add_shortcut.dialog.submit=Create shortcut
shortcuts.ui.admin.edit_shortcut.dialog.urlkey.help=The short URL
shortcuts.ui.admin.edit_shortcut.dialog.urlkey.label=Short URL
shortcuts.ui.admin.edit_shortcut.dialog.redirect.help=The target URL to which the user is redirected
shortcuts.ui.admin.edit_shortcut.dialog.redirect.label=Redirect target
shortcuts.ui.admin.edit_shortcut.dialog.cancel=Cancel
shortcuts.ui.admin.edit_shortcut.dialog.submit=Save

View File

@ -33,3 +33,20 @@ shortcuts.ui.admin.heading=Shortcuts verwalten
shortcuts.ui.admin.table.empty=Es wurden noch keine Shortcuts angelegt.
shortcuts.ui.admin.add_shortcut=Shortcut hinzuf\u00fcgen
shortcuts.ui.admin.shortcuts_table.col_actions.header=Aktionen
shortcuts.ui.admin.delete_dialog.cancel=Abbbrechen
shortcuts.ui.admin.delete_dialog.confirm=Shortcut entfernen
shortcuts.ui.admin.delete_dialog.title=Confirm removal of shortcut
shortcuts.ui.admin.delete_dialog.message=Sind Sie sicher, dass Sie den Shortcut f\u00fcr die Umleitung von {0} nach {1} entfernen wollen?
shortcuts.ui.admin.add_shortcut.dialog.title=Shortcut hinzuf\u00fcgen
shortcuts.ui.admin.add_shortcut.dialog.urlkey.help=Die Kurz-URL, die umgeleitetet werden soll
shortcuts.ui.admin.add_shortcut.dialog.urlkey.label=Kurz-URL
shortcuts.ui.admin.add_shortcut.dialog.redirect.help=An diese URL wird weitergeleitet.
shortcuts.ui.admin.add_shortcut.dialog.redirect.label=Weiterleitungsziel
shortcuts.ui.admin.add_shortcut.dialog.cancel=Abbrechen
shortcuts.ui.admin.add_shortcut.dialog.submit=Shortcut anlegen
shortcuts.ui.admin.edit_shortcut.dialog.urlkey.help=Die Kurz-URL, die umgeleitetet werden soll
shortcuts.ui.admin.edit_shortcut.dialog.urlkey.label=Kurz-URL
shortcuts.ui.admin.edit_shortcut.dialog.redirect.help=An diese URL wird weitergeleitet.
shortcuts.ui.admin.edit_shortcut.dialog.redirect.label=Weiterleitungsziel
shortcuts.ui.admin.edit_shortcut.dialog.cancel=Abbrechen
shortcuts.ui.admin.edit_shortcut.dialog.submit=Speichern