CCM NG/ccm-core: Some more testing with Vaadin

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4685 8810af33-2d31-482b-a856-94f89814c4df
ccm-docs
jensp 2017-04-23 17:30:53 +00:00
parent d69b9688ea
commit 46a94bddf2
16 changed files with 13037 additions and 20 deletions

View File

@ -95,6 +95,14 @@
<artifactId>ccm-theme-foundry</artifactId>
<type>jar</type>
</overlay>
<overlay>
<groupId>org.libreccm</groupId>
<artifactId>ccm-core</artifactId>
<type>jar</type>
<includes>
<include>VAADIN/</include>
</includes>
</overlay>
<overlay>
<groupId>org.librecms</groupId>
<artifactId>ccm-cms</artifactId>

View File

@ -206,17 +206,17 @@
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-themes</artifactId>
<version>8.0.4</version>
<!--<version>8.0.4</version>-->
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-client-compiled</artifactId>
<version>8.0.4</version>
<!--<version>8.0.4</version>-->
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-compatibility-client-compiled</artifactId>
<version>8.0.4</version>
<!--<version>8.0.4</version>-->
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
@ -376,6 +376,22 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>clean</goal>
<goal>resources</goal>
<goal>update-theme</goal>
<goal>update-widgetset</goal>
<goal>compile-theme</goal>
<goal>compile</goal>
</goals>
</execution>
</executions>
</plugin>
<!--<plugin>
<groupId>org.jboss.tattletale</groupId>
<artifactId>tattletale-maven</artifactId>

View File

@ -18,6 +18,7 @@
*/
package org.libreccm.admin.ui;
import com.vaadin.annotations.Theme;
import com.vaadin.cdi.CDIUI;
import com.vaadin.cdi.CDIViewProvider;
import com.vaadin.cdi.URLMapping;
@ -27,8 +28,11 @@ import com.vaadin.server.VaadinRequest;
import com.vaadin.ui.Notification;
import com.vaadin.ui.UI;
import org.apache.shiro.subject.Subject;
import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.security.PermissionChecker;
import java.util.Locale;
import javax.inject.Inject;
/**
@ -37,6 +41,7 @@ import javax.inject.Inject;
*/
@URLMapping("vaadin")
@CDIUI("admin")
@Theme("ccm-core")
public class AdminUIVaadin extends UI {
private static final long serialVersionUID = -1352590567964037112L;
@ -53,12 +58,17 @@ public class AdminUIVaadin extends UI {
@Inject
private PermissionChecker permissionChecker;
@Inject
private GlobalizationHelper globalizationHelper;
@Override
protected void init(VaadinRequest request) {
final Navigator navigator = new Navigator(this, this);
navigator.addProvider(viewProvider);
setLocale(globalizationHelper.getNegotiatedLocale());
navigator.addViewChangeListener(new AuthNavListener());
if (subject.isAuthenticated()) {

View File

@ -23,10 +23,16 @@ import com.arsdigita.ui.admin.AdminUiConstants;
import com.vaadin.cdi.CDIView;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.server.ClassResource;
import com.vaadin.server.VaadinServlet;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Grid;
import com.vaadin.ui.GridLayout;
import com.vaadin.ui.Image;
import com.vaadin.ui.Label;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.VerticalLayout;
import org.apache.shiro.subject.Subject;
@ -39,6 +45,9 @@ import java.util.ResourceBundle;
import javax.annotation.PostConstruct;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.servlet.ServletContext;
import javax.servlet.ServletRequest;
/**
*
@ -58,6 +67,12 @@ public class AdminView extends CustomComponent implements View {
private static final String COL_EMAIL = "email";
private static final String COL_BANNED = "banned";
@Inject
private ServletContext servletContext;
@Inject
private JpqlConsoleController jpqlConsoleController;
@Inject
private Subject subject;
@ -75,6 +90,8 @@ public class AdminView extends CustomComponent implements View {
private final TabSheet tabSheet;
private final Grid<User> usersTable;
private final JpqlConsole jpqlConsole;
public AdminView() {
tabSheet = new TabSheet();
@ -112,18 +129,74 @@ public class AdminView extends CustomComponent implements View {
tabSheet.addTab(userGroupsRoles, "Users/Groups/Roles");
final CssLayout header = new CssLayout() {
final ServletContext servletContext = VaadinServlet
.getCurrent()
.getServletContext();
if ("true".equals(servletContext.getInitParameter("ccm.develmode"))) {
jpqlConsole = new JpqlConsole(this);
tabSheet.addTab(jpqlConsole, "JPQL Console");
} else {
jpqlConsole = null;
}
private static final long serialVersionUID = -4372147161604688854L;
@Override
protected String getCss(final Component component) {
return null;
}
};
// final CssLayout header = new CssLayout() {
//
// private static final long serialVersionUID = -4372147161604688854L;
//
// @Override
// protected String getCss(final Component component) {
// /*if ((component instanceof Image)
// && "libreccm-logo".equals(component.getId())) {
//
// return "position: absolute; top: 10px; left: 10px;";
//
// } else if ((component instanceof Label)
// && "libreccm-headerinfoline".equals(component
// .getId())) {
// return "background-color: #8b8e8a; width: 100%; position: absolute; top:120px; left: 0";
// }*/
// return "";
//
//// return ".v-csslayout {\n"
//// + "background-color: #56a1bd;\n"
//// + "background-image: -ie-linear-gradient(top , #56a1db 5%, #024c68 95%\n"
//// + "background-image: -moz-linear-gradient(top , #56a1db 5%, #024c68 95%\n"
//// + "background-image: -webkit-linear-gradient(top , #56a1db 5%, #024c68 95%\n"
//// + "background-image: linear-gradient(top , #56a1db 5%, #024c68 95%\n"
//// + "}\n"
//// + "\n"
//// + ".libreccm-logo {\n"
//// + "border-left: 10px solid #0f0;\n"
//// + "}\n";
// }
//
// };
// header.setWidth("100%");
header.setHeight("5em");
// header.setHeight("5em");
final GridLayout header = new GridLayout(5, 1);
header.setWidth("100%");
header.addStyleName("libreccm-header");
// final Image logo = new Image(
// "",
// new ClassResource("/themes/libreccm-default/images/libreccm.png"));
// logo.setId("libreccm-logo");
// logo.addStyleName("libreccm-logo");
// header.addComponent(logo, 0, 0);
// header.setComponentAlignment(logo, Alignment.MIDDLE_LEFT);
final Label headerInfoLine = new Label("LibreCCM");
headerInfoLine.setId("libreccm-headerinfoline");
// headerInfoLine.setWidth("100%");
header.addComponent(headerInfoLine, 3, 0, 4, 0);
header.setComponentAlignment(headerInfoLine, Alignment.TOP_RIGHT);
final Image logo = new Image(
null,
new ClassResource("/themes/libreccm-default/images/libreccm.png"));
logo.setId("libreccm-logo");
logo.addStyleName("libreccm-logo");
header.addComponent(logo, 0, 0);
header.setComponentAlignment(logo, Alignment.MIDDLE_LEFT);
final CssLayout footer = new CssLayout();
// footer.setWidth("100%");
@ -131,7 +204,9 @@ public class AdminView extends CustomComponent implements View {
final VerticalLayout viewLayout = new VerticalLayout();
viewLayout.addComponent(header);
viewLayout.addComponent(tabSheet);
viewLayout.addComponent(footer);
setCompositionRoot(viewLayout);
}
@ -150,7 +225,11 @@ public class AdminView extends CustomComponent implements View {
// getUI().getNavigator().navigateTo(LoginView.VIEWNAME);
// }
usersTable.setItems(userRepo.findAll());
}
protected JpqlConsoleController getJpqlConsoleController() {
return jpqlConsoleController;
}
}

View File

@ -0,0 +1,228 @@
/*
* Copyright (C) 2017 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.admin.ui;
import com.arsdigita.ui.admin.AdminUiConstants;
import com.vaadin.ui.Button;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Panel;
import com.vaadin.ui.TextArea;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Objects;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.stream.Collectors;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceException;
import javax.persistence.Query;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class JpqlConsole extends CustomComponent {
private static final long serialVersionUID = 2585630538827827614L;
private AdminView view;
private final TextArea queryArea;
// private final FormLayout queryForm;
// private final VerticalLayout resultsLayout;
private final Label noResultsLabel;
private final Panel resultsPanel;
public JpqlConsole(final AdminView view) {
this.view = view;
final ResourceBundle bundle = ResourceBundle.getBundle(
AdminUiConstants.ADMIN_BUNDLE, UI.getCurrent().getLocale());
queryArea = new TextArea(bundle.getString("ui.admin.jpqlconsole.query"));
queryArea.setWidth("100%");
final Button executeQueryButton = new Button(bundle
.getString("ui.admin.jpqlconsole.query.execute"));
executeQueryButton.addClickListener(event -> executeQuery());
final Button clearQueryButton = new Button(bundle
.getString("ui.admin.jpqlconsole.query.clear"));
clearQueryButton.addClickListener(event -> queryArea.clear());
// queryForm = new FormLayout(queryArea
// executeQueryButton,
// clearQueryButton);
final HorizontalLayout queryButtonsLayout = new HorizontalLayout(
clearQueryButton,
executeQueryButton);
final VerticalLayout queryLayout = new VerticalLayout(queryArea,
queryButtonsLayout);
noResultsLabel = new Label(bundle
.getString("ui.admin.jpqlconsole.results.none"));
resultsPanel = new Panel("Query results",
noResultsLabel);
// resultsLayout = new VerticalLayout(noResultsLabel);
// final VerticalSplitPanel splitPanel = new VerticalSplitPanel();
//// splitPanel.setSizeFull();
// splitPanel.setHeight("100%");
// splitPanel.setSplitPosition(33.3f, Unit.PERCENTAGE);
// splitPanel.setFirstComponent(queryForm);
// splitPanel.setSecondComponent(resultsLayout);
setCompositionRoot(new VerticalLayout(queryLayout, resultsPanel));
}
private void executeQuery() {
final String queryStr = queryArea.getValue();
if (queryStr == null || queryStr.trim().isEmpty()) {
return;
}
if (!queryStr.toLowerCase().startsWith("select")) {
Notification.show("Only SELECT queries",
"Only SELECT queries are supported",
Notification.Type.WARNING_MESSAGE);
return;
}
// final Query query;
// try {
// query = entityManager.createQuery(queryStr);
// } catch (IllegalArgumentException ex) {
// Notification.show("Query is malformed.",
// ex.getMessage(),
// Notification.Type.ERROR_MESSAGE);
// return;
// }
final List<?> result;
try {
result = view.getJpqlConsoleController().executeQuery(queryStr);
} catch (IllegalArgumentException ex) {
Notification.show("Query is malformed.",
ex.getMessage(),
Notification.Type.ERROR_MESSAGE);
return;
} catch (PersistenceException ex) {
Notification.show("Failed to execute query",
ex.getMessage(),
Notification.Type.ERROR_MESSAGE);
return;
}
Set<Class<?>> classes = result
.stream()
.map(Object::getClass)
.collect(Collectors.toSet());
final Set<PropertyDescriptor> properties = new HashSet<>();
try {
for (final Class<?> clazz : classes) {
final BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
final PropertyDescriptor[] props = beanInfo
.getPropertyDescriptors();
properties.addAll(Arrays.asList(props));
}
for (final Class<?> clazz : classes) {
final BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
final PropertyDescriptor[] props = beanInfo
.getPropertyDescriptors();
properties.retainAll(Arrays.asList(props));
}
} catch (IntrospectionException ex) {
Notification.show(
"Error displaying result. Failed to introspect classes.",
Notification.Type.ERROR_MESSAGE);
return;
}
final List<PropertyDescriptor> propertiesList = properties
.stream()
.filter(prop -> {
return !Collection.class
.isAssignableFrom(prop.getPropertyType());
})
.collect(Collectors.toList());
propertiesList.sort((prop1, prop2) -> {
return prop1.getName().compareTo(prop2.getName());
});
final List<String> propertyNames = propertiesList
.stream()
.map(PropertyDescriptor::getName)
.collect(Collectors.toList());
final Label count = new Label(String.format("Found %d results",
result.size()));
final Label propertiesLabel = new Label(String.join(", ",
propertyNames));
final VerticalLayout data = new VerticalLayout(count, propertiesLabel);
resultsPanel.setContent(data);
// while(classes.size() > 1) {
// final Set<Class<?>> oldClasses = classes;
// classes = oldClasses
// .stream()
// .map(clazz -> getSuperClass(clazz))
// .collect(Collectors.toSet());
// }
//
// final Class<?> baseClass = classes.iterator().next();
//
// final Label count = new Label(String.format("Found %d results",
// result.size()));
// final Label baseClassLabel;
// if (baseClass == null) {
// baseClassLabel = new Label("Base class is null");
// } else {
// baseClassLabel = new Label(String.format("Base class is '%s'.",
// baseClass.getName()));
// }
// final VerticalLayout data = new VerticalLayout(count, baseClassLabel);
// resultsPanel.setContent(data);
}
private Class<?> getSuperClass(final Class<?> clazz) {
if (Object.class.equals(clazz.getSuperclass())) {
return clazz;
} else {
return clazz.getSuperclass();
}
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (C) 2017 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.admin.ui;
import java.util.List;
import java.util.Objects;
import javax.enterprise.context.RequestScoped;
import javax.inject.Inject;
import javax.persistence.EntityManager;
import javax.persistence.Query;
import javax.transaction.Transactional;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@RequestScoped
class JpqlConsoleController {
@Inject
private EntityManager entityManager;
@Transactional(Transactional.TxType.REQUIRED)
protected List<?> executeQuery(final String queryStr) {
Objects.requireNonNull(queryStr);
final Query query = entityManager.createQuery(queryStr);
return query.getResultList();
}
}

View File

@ -21,13 +21,18 @@ package org.libreccm.admin.ui;
import com.arsdigita.kernel.KernelConfig;
import com.vaadin.cdi.CDIView;
import com.vaadin.event.Action;
import com.vaadin.event.Action.Handler;
import com.vaadin.event.ShortcutAction;
import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.server.UserError;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.FormLayout;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Panel;
import com.vaadin.ui.PasswordField;
import com.vaadin.ui.TextField;
@ -85,14 +90,64 @@ public class LoginView extends CustomComponent implements View {
submitButton = new Button("Login");
submitButton.addClickListener(event -> login(event));
submitButton.setEnabled(false);
formLayout.addComponent(submitButton);
userName.addValueChangeListener(event -> {
if (userName.getValue() != null
&& !userName.getValue().trim().isEmpty()
&& password.getValue() != null
&& !password.getValue().trim().isEmpty()) {
submitButton.setEnabled(true);
submitButton.setClickShortcut(ShortcutAction.KeyCode.ENTER);
}
});
password.addValueChangeListener(event -> {
if (userName.getValue() != null
&& !userName.getValue().trim().isEmpty()
&& password.getValue() != null
&& !password.getValue().trim().isEmpty()) {
submitButton.setEnabled(true);
submitButton.setClickShortcut(ShortcutAction.KeyCode.ENTER);
}
});
// userName.addFocusListener(event -> {
// if (userName.getValue() != null
// && !userName.getValue().trim().isEmpty()
// && password.getValue() != null
// && !password.getValue().trim().isEmpty()) {
// submitButton.setClickShortcut(ShortcutAction.KeyCode.ENTER);
// }
// });
// userName.addBlurListener(event -> {
// if (userName.getValue() != null
// && !userName.getValue().trim().isEmpty()
// && password.getValue() != null
// && !password.getValue().trim().isEmpty()) {
// submitButton.removeClickShortcut();
// }
// });
password.addFocusListener(event -> {
submitButton.setClickShortcut(ShortcutAction.KeyCode.ENTER);
});
password.addBlurListener(event -> {
submitButton.removeClickShortcut();
});
loginPanel = new Panel("Login", formLayout);
loginPanel.setWidth("24em");
loginPanel.setWidth(
"24em");
final VerticalLayout viewLayout = new VerticalLayout(loginPanel);
viewLayout.setComponentAlignment(loginPanel, Alignment.MIDDLE_CENTER);
setCompositionRoot(viewLayout);
}
@PostConstruct
@ -111,8 +166,11 @@ public class LoginView extends CustomComponent implements View {
try {
subject.login(token);
} catch (AuthenticationException ex) {
formLayout.setComponentError(
submitButton.setComponentError(
new UserError(bundle.getString("login.error.loginFail")));
Notification.show(bundle.getString("login.error.loginFail"),
Notification.Type.ERROR_MESSAGE);
password.setValue("");
return;
}
@ -123,7 +181,8 @@ public class LoginView extends CustomComponent implements View {
public void enter(final ViewChangeListener.ViewChangeEvent event) {
final KernelConfig kernelConfig = confManager
.findConfiguration(KernelConfig.class);
.findConfiguration(KernelConfig.class
);
loginPanel
.setCaption(bundle.getString("login.userRegistrationForm.title"));
if (kernelConfig.emailIsPrimaryIdentifier()) {

View File

@ -0,0 +1,7 @@
/* This file is automatically managed and will be overwritten from time to time. */
/* Do not manually edit this file. */
/* Import and include this mixin into your project theme to include the addon themes */
@mixin addons {
}

View File

@ -0,0 +1,17 @@
/* Styles for Vaadin used in the CCM Core module */
@import "../valo/valo.scss";
@mixin ccm-core {
@include valo;
.libreccm-header {
border-bottom: 5px solid #0f0;
.libreccm-logo {
max-height: 100px;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
@import "addons.scss";
@import "ccm-core.scss";
@include addons;
@include ccm-core;

View File

@ -557,3 +557,5 @@ ui.admin.jpqlconsole.query.execute=Execute
ui.admin.jpqlconsole.query.clear=Clear
ui.admin.user.banned_yes=Yes
ui.admin.user.banned_no=No
ui.admin.jpqlconsole.query=Query
ui.admin.jpqlconsole.results.none=No results

View File

@ -561,3 +561,5 @@ ui.admin.jpqlconsole.query.execute=Ausf\u00fchren
ui.admin.jpqlconsole.query.clear=Zur\u00fccksetzen
ui.admin.user.banned_yes=Ja
ui.admin.user.banned_no=Nein
ui.admin.jpqlconsole.query=Abfrage
ui.admin.jpqlconsole.results.none=Keine Ergebnisse

View File

@ -554,3 +554,5 @@ ui.admin.jpqlconsole.query.execute=Excute
ui.admin.jpqlconsole.query.clear=Clear
ui.admin.user.banned_yes=Yes
ui.admin.user.banned_no=No
ui.admin.jpqlconsole.query=Query
ui.admin.jpqlconsole.results.none=No results

View File

@ -545,3 +545,5 @@ ui.admin.jpqlconsole.query.execute=Execute
ui.admin.jpqlconsole.query.clear=Clear
ui.admin.user.banned_yes=Yes
ui.admin.user.banned_no=No
ui.admin.jpqlconsole.query=Query
ui.admin.jpqlconsole.results.none=No results

26
pom.xml
View File

@ -216,6 +216,11 @@
<artifactId>wildfly-swarm-plugin</artifactId>
<version>2017.1.1</version>
</plugin>
<plugin>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-maven-plugin</artifactId>
<version>8.0.5</version>
</plugin>
</plugins>
</pluginManagement>
@ -319,26 +324,41 @@
</dependency>
<!-- Vaadin dependencies for Vaadin prototype -->
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-compatibility-client-compiled</artifactId>
<version>8.0.5</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-compatibility-server</artifactId>
<version>8.0.4</version>
<version>8.0.5</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-compatibility-shared</artifactId>
<version>8.0.4</version>
<version>8.0.5</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-compatibility-themes</artifactId>
<version>8.0.4</version>
<version>8.0.5</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-cdi</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-client-compiled</artifactId>
<version>8.0.5</version>
</dependency>
<dependency>
<groupId>com.vaadin</groupId>
<artifactId>vaadin-themes</artifactId>
<version>8.0.5</version>
</dependency>
<!--
*********************