diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ContentCenter.java b/ccm-cms/src/main/java/com/arsdigita/cms/ContentCenter.java
index 24445a50c..73eb958ae 100644
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ContentCenter.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ContentCenter.java
@@ -25,6 +25,8 @@ import org.libreccm.web.CcmApplication;
* @author Jens Pelzetter
*/
public class ContentCenter extends CcmApplication {
+
+ private static final long serialVersionUID = 6672720141286517654L;
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/AdminView.java b/ccm-core/src/main/java/org/libreccm/admin/ui/AdminView.java
index 06a81873c..5b75c3766 100644
--- a/ccm-core/src/main/java/org/libreccm/admin/ui/AdminView.java
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/AdminView.java
@@ -60,7 +60,7 @@ public class AdminView extends CustomComponent implements View {
private final SystemInformationTab sysInfoTab;
@Inject
- protected AdminView(final AdminViewController controller) {
+ AdminView(final AdminViewController controller) {
this.controller = controller;
@@ -89,6 +89,9 @@ public class AdminView extends CustomComponent implements View {
final SitesTab sitesTab = new SitesTab(controller);
tabSheet.addTab(sitesTab, "Sites");
+ final PageModelsTab pageModelsTab = new PageModelsTab(controller);
+ tabSheet.addTab(pageModelsTab, "PageModels");
+
configurationTab = new ConfigurationTab();
tabSheet.addTab(configurationTab, "Configuration");
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/AdminViewController.java b/ccm-core/src/main/java/org/libreccm/admin/ui/AdminViewController.java
index 3ff397497..d47b11c9d 100644
--- a/ccm-core/src/main/java/org/libreccm/admin/ui/AdminViewController.java
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/AdminViewController.java
@@ -36,6 +36,9 @@ class AdminViewController implements Serializable {
private static final long serialVersionUID = 4880298854970416968L;
+ @Inject
+ private ApplicationTreeDataProvider applicationTreeDataProvider;
+
@Inject
private ConfigurationsTabController confTabController;
@@ -45,6 +48,9 @@ class AdminViewController implements Serializable {
@Inject
private JpqlConsoleController jpqlConsoleController;
+ @Inject
+ private PageModelsController pageModelsController;
+
@Inject
private SitesController sitesController;
@@ -55,6 +61,10 @@ class AdminViewController implements Serializable {
super();
}
+ public ApplicationTreeDataProvider getApplicationTreeDataProvider() {
+ return applicationTreeDataProvider;
+ }
+
public ConfigurationsTabController getConfTabController() {
return confTabController;
}
@@ -66,6 +76,10 @@ class AdminViewController implements Serializable {
protected JpqlConsoleController getJpqlConsoleController() {
return jpqlConsoleController;
}
+
+ protected PageModelsController getPageModelsController() {
+ return pageModelsController;
+ }
protected SitesController getSitesController() {
return sitesController;
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeDataProvider.java b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeDataProvider.java
new file mode 100644
index 000000000..7d0d12503
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeDataProvider.java
@@ -0,0 +1,190 @@
+/*
+ * 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.vaadin.cdi.ViewScoped;
+import com.vaadin.data.provider.AbstractBackEndHierarchicalDataProvider;
+import com.vaadin.data.provider.HierarchicalQuery;
+import org.libreccm.core.UnexpectedErrorException;
+import org.libreccm.l10n.GlobalizationHelper;
+import org.libreccm.web.ApplicationManager;
+import org.libreccm.web.ApplicationRepository;
+import org.libreccm.web.ApplicationType;
+import org.libreccm.web.CcmApplication;
+
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.ResourceBundle;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@ViewScoped
+class ApplicationTreeDataProvider
+ extends AbstractBackEndHierarchicalDataProvider {
+
+ private static final long serialVersionUID = 7089444870777208500L;
+
+ @Inject
+ private ApplicationManager applicationManager;
+
+ @Inject
+ private ApplicationRepository applicationRepo;
+
+ @Inject
+ private GlobalizationHelper globalizationHelper;
+
+ private final ApplicationTreeNode rootNode;
+
+ public ApplicationTreeDataProvider() {
+ rootNode = new ApplicationTreeNode();
+ rootNode.setNodeId(ApplicationTreeNode.ROOT);
+ rootNode.setNodeType(ApplicationTreeNodeType.ROOT_NODE);
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ protected Stream fetchChildrenFromBackEnd(
+ final HierarchicalQuery query) {
+
+ final ApplicationTreeNode node = query
+ .getParentOptional()
+ .orElse(rootNode);
+
+ switch (node.getNodeType()) {
+ case APPLICATION_TYPE_NODE:
+ return fetchApplicationInstances(node);
+ case ROOT_NODE:
+ return fetchApplicationTypes();
+ default:
+ throw new IllegalArgumentException(String
+ .format("Invalid value \"%s\" for nodeType.",
+ node.getNodeType()));
+ }
+ }
+
+ private Stream fetchApplicationTypes() {
+
+ return applicationManager
+ .getApplicationTypes()
+ .values()
+ .stream()
+ .map(this::buildApplicationTreeNode)
+ .sorted();
+ }
+
+ private ApplicationTreeNode buildApplicationTreeNode(
+ final ApplicationType type) {
+
+ final ResourceBundle bundle = ResourceBundle
+ .getBundle(type.descBundle());
+
+ final String title = bundle.getString(type.titleKey());
+
+ final ApplicationTreeNode node = new ApplicationTreeNode();
+ node.setTitle(title);
+
+ if (type.singleton()) {
+ node.setNodeType(ApplicationTreeNodeType.SINGLETON_APPLICATION_NODE);
+
+ final List instances = applicationRepo
+ .findByType(type.name());
+
+ if (instances.size() > 1) {
+ throw new UnexpectedErrorException(String
+ .format("Application type \"%s\" is marked as singleton but"
+ + "there are multiple instances.",
+ type.name()));
+ }
+
+ final CcmApplication instance = instances.get(0);
+ node.setNodeId(instance.getUuid());
+ } else {
+ node.setNodeType(ApplicationTreeNodeType.APPLICATION_TYPE_NODE);
+ node.setNodeId(type.name());
+ }
+
+ return node;
+ }
+
+ private Stream fetchApplicationInstances(
+ final ApplicationTreeNode parent) {
+
+ if (parent.getNodeType()
+ != ApplicationTreeNodeType.APPLICATION_TYPE_NODE) {
+ throw new IllegalArgumentException("Provided parent node is not a "
+ + ApplicationTreeNodeType.APPLICATION_TYPE_NODE);
+ }
+
+ final String type = parent.getNodeId();
+
+ return applicationRepo
+ .findByType(type)
+ .stream()
+ .map(this::buildApplicationTreeNode)
+ .sorted();
+ }
+
+ private ApplicationTreeNode buildApplicationTreeNode(
+ final CcmApplication application) {
+
+ final ApplicationTreeNode node = new ApplicationTreeNode();
+
+ node.setNodeId(application.getUuid());
+ node.setNodeType(ApplicationTreeNodeType.APPLICATION_NODE);
+ node.setTitle(globalizationHelper
+ .getValueFromLocalizedString(application.getTitle()));
+
+ return node;
+ }
+
+ @Override
+ public int getChildCount(
+ final HierarchicalQuery query) {
+
+ return (int) fetchChildrenFromBackEnd(query).count();
+ }
+
+ @Override
+ public boolean hasChildren(final ApplicationTreeNode item) {
+
+ switch (item.getNodeType()) {
+ case APPLICATION_NODE:
+ return false;
+ case APPLICATION_TYPE_NODE:
+ return true;
+ case ROOT_NODE:
+ return true;
+ case SINGLETON_APPLICATION_NODE:
+ return false;
+ default:
+ throw new IllegalArgumentException(String
+ .format("Invalid value \"%s\" for nodeType.",
+ item.getNodeType()));
+ }
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNode.java b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNode.java
new file mode 100644
index 000000000..25f3e57a3
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNode.java
@@ -0,0 +1,149 @@
+/*
+ * 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.io.Serializable;
+import java.util.Objects;
+
+/**
+ * Class encapsulating the information displayed in a application tree.
+ *
+ * @author Jens Pelzetter
+ */
+class ApplicationTreeNode implements Serializable,
+ Comparable {
+
+ private static final long serialVersionUID = -3123536103514717506L;
+
+ protected static final String ROOT = "@ROOT@";
+
+
+ /**
+ * ID of the node. If the node is the root node, the ID will be
+ * {@link #ROOT}. If the node is an application type node the ID will be the
+ * name of the application type class. If it is an application (instance)
+ * node, the name will be the UUID of the instance.
+ */
+ private String nodeId;
+
+ /**
+ * Type of the the node.
+ */
+ private ApplicationTreeNodeType nodeType;
+
+ /**
+ * The title of the node.
+ */
+ private String title;
+
+ public String getNodeId() {
+ return nodeId;
+ }
+
+ public void setNodeId(final String nodeId) {
+ this.nodeId = nodeId;
+ }
+
+ public ApplicationTreeNodeType getNodeType() {
+ return nodeType;
+ }
+
+ public void setNodeType(final ApplicationTreeNodeType nodeType) {
+ this.nodeType = nodeType;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(final String title) {
+ this.title = title;
+ }
+
+ @Override
+ public int compareTo(final ApplicationTreeNode other) {
+
+ int result = title.compareTo(other.getTitle());
+ if (result == 0) {
+ result = nodeType.compareTo(other.getNodeType());
+ }
+
+ if (result == 0) {
+ result = nodeId.compareTo(other.getNodeId());
+ }
+
+ return result;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 5;
+ hash = 53 * hash + Objects.hashCode(this.nodeId);
+ hash = 53 * hash + Objects.hashCode(this.nodeType);
+ hash = 53 * hash + Objects.hashCode(this.title);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(final Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof ApplicationTreeNode)) {
+ return false;
+ }
+ final ApplicationTreeNode other = (ApplicationTreeNode) obj;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+ if (!Objects.equals(this.nodeId, other.getNodeId())) {
+ return false;
+ }
+ if (!Objects.equals(this.title, other.getTitle())) {
+ return false;
+ }
+ return this.nodeType == other.getNodeType();
+ }
+
+ public boolean canEqual(final Object obj) {
+ return obj instanceof ApplicationTreeNode;
+ }
+
+ @Override
+ public final String toString() {
+ return toString("");
+ }
+
+ public String toString(final String data) {
+ return String.format("%s{ "
+ + "nodeId = \"%s\", "
+ + "nodeType = \"%s\", "
+ + "title = \"%s\"%s"
+ + " }",
+ super.toString(),
+ nodeId,
+ nodeType,
+ title,
+ data);
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNodeType.java b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNodeType.java
new file mode 100644
index 000000000..5c2baa7a0
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/ApplicationTreeNodeType.java
@@ -0,0 +1,30 @@
+/*
+ * 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;
+
+/**
+ * Enum of the possible types of a node.
+ */
+enum ApplicationTreeNodeType {
+ ROOT_NODE,
+ APPLICATION_TYPE_NODE,
+ APPLICATION_NODE,
+ SINGLETON_APPLICATION_NODE
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelDetails.java b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelDetails.java
new file mode 100644
index 000000000..155cd7ab0
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelDetails.java
@@ -0,0 +1,39 @@
+/*
+ * 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.vaadin.ui.Window;
+import org.libreccm.pagemodel.PageModel;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+ class PageModelDetails extends Window {
+
+ private static final long serialVersionUID = -3617001410191320596L;
+
+ PageModelDetails(final PageModel pageModel,
+ final AdminViewController controller) {
+
+ super();
+
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsController.java b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsController.java
new file mode 100644
index 000000000..a5b7e93ca
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsController.java
@@ -0,0 +1,74 @@
+/*
+ * 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.vaadin.cdi.ViewScoped;
+import org.libreccm.pagemodel.PageModel;
+import org.libreccm.pagemodel.PageModelManager;
+import org.libreccm.pagemodel.PageModelRepository;
+
+import java.io.Serializable;
+
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@ViewScoped
+class PageModelsController implements Serializable {
+
+ private static final long serialVersionUID = 6204724295214879943L;
+
+ @Inject
+ private PageModelManager pageModelManager;
+
+ @Inject
+ private PageModelRepository pageModelRepo;
+
+ @Inject
+ private PageModelsTableDataProvider pageModelsTableDataProvider;
+
+ protected PageModelManager getPageModelManager() {
+ return pageModelManager;
+ }
+
+ protected PageModelRepository getPageModelRepo() {
+ return pageModelRepo;
+ }
+
+ protected PageModelsTableDataProvider getPageModelsTableDataProvider() {
+ return pageModelsTableDataProvider;
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ protected void deletePageModel(final long pageModelId) {
+
+ final PageModel pageModel = pageModelRepo
+ .findById(pageModelId)
+ .orElseThrow(() -> new IllegalArgumentException(String
+ .format("No PageModel with ID %d in the database.",
+ pageModelId)));
+
+ pageModelRepo.delete(pageModel);
+ pageModelsTableDataProvider.refreshAll();
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTab.java b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTab.java
new file mode 100644
index 000000000..c8810d4cc
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTab.java
@@ -0,0 +1,174 @@
+/*
+ * 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.icons.VaadinIcons;
+import com.vaadin.ui.Button;
+import com.vaadin.ui.Component;
+import com.vaadin.ui.CustomComponent;
+import com.vaadin.ui.Grid;
+import com.vaadin.ui.HorizontalSplitPanel;
+import com.vaadin.ui.Tree;
+import com.vaadin.ui.UI;
+import com.vaadin.ui.VerticalLayout;
+import com.vaadin.ui.themes.ValoTheme;
+import org.libreccm.l10n.LocalizedTextsUtil;
+import org.libreccm.pagemodel.PageModel;
+import org.libreccm.ui.ConfirmDialog;
+import org.libreccm.web.CcmApplication;
+
+import java.util.concurrent.Callable;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+class PageModelsTab extends CustomComponent {
+
+ private static final long serialVersionUID = -1116995764418892909L;
+
+ private static final String COL_NAME = "name";
+ private static final String COL_TITLE = "title";
+ private static final String COL_DESC = "description";
+ private static final String COL_LIVE = "live";
+ private static final String COL_EDIT = "edit";
+ private static final String COL_DELETE = "delete";
+
+ protected PageModelsTab(final AdminViewController adminViewController) {
+
+ super();
+
+ final Tree applicationTree = new Tree<>(
+ adminViewController.getApplicationTreeDataProvider());
+
+ applicationTree.addItemClickListener(event -> {
+ });
+ applicationTree.setItemCollapseAllowedProvider(node -> {
+ return !node.getNodeType().equals(ApplicationTreeNodeType.ROOT_NODE);
+ });
+
+ final LocalizedTextsUtil localizedTextsUtil = adminViewController
+ .getGlobalizationHelper()
+ .getLocalizedTextsUtil(AdminUiConstants.ADMIN_BUNDLE);
+
+ final Grid pageModelsGrid = new Grid<>();
+ pageModelsGrid.setDataProvider(adminViewController
+ .getPageModelsController()
+ .getPageModelsTableDataProvider());
+ pageModelsGrid
+ .addColumn(PageModelsTableRow::getName)
+ .setCaption(localizedTextsUtil
+ .getText("ui.admin.pagemodels.table.columns.headers.name"))
+ .setId(COL_NAME);
+ pageModelsGrid
+ .addColumn(PageModelsTableRow::getTitle)
+ .setCaption(localizedTextsUtil
+ .getText("ui.admin.pagemodels.table.columns.headers.title"))
+ .setId(COL_TITLE);
+ pageModelsGrid
+ .addColumn(PageModelsTableRow::getDescription)
+ .setCaption(localizedTextsUtil
+ .getText("ui.admin.pagemodels.table.columns.headers.desc"))
+ .setId(COL_DESC);
+ pageModelsGrid
+ .addColumn(PageModelsTableRow::isPublished)
+ .setCaption(localizedTextsUtil
+ .getText("ui.admin.pagemodels.table.columns.headers.islive"))
+ .setId(COL_LIVE);
+ pageModelsGrid
+ .addComponentColumn(row -> buildEditButton(row,
+ adminViewController))
+ .setId(COL_EDIT);
+ pageModelsGrid
+ .addComponentColumn(row -> buildDeleteButton(row,
+ adminViewController))
+ .setId(COL_DELETE);
+
+ super.setCompositionRoot(new HorizontalSplitPanel(applicationTree,
+ pageModelsGrid));
+
+ }
+
+ private Component buildEditButton(final PageModelsTableRow row,
+ final AdminViewController controller) {
+
+ final LocalizedTextsUtil localizedTextsUtil = controller
+ .getGlobalizationHelper()
+ .getLocalizedTextsUtil(AdminUiConstants.ADMIN_BUNDLE);
+
+ final Button button = new Button(localizedTextsUtil
+ .getText("ui.admin.pagemodels.table.columns.edit.label"),
+ VaadinIcons.EDIT);
+ button.addStyleName(ValoTheme.BUTTON_TINY);
+ button.addClickListener(event -> {
+ final PageModel pageModel = controller
+ .getPageModelsController()
+ .getPageModelRepo()
+ .findById(row.getPageModelId())
+ .orElseThrow(() -> new IllegalArgumentException(String
+ .format("No PageModel with ID %d in the database.",
+ row.getPageModelId())));
+
+ final PageModelDetails pageModelDetails = new PageModelDetails(
+ pageModel, controller);
+ pageModelDetails.center();
+ pageModelDetails.setModal(true);
+ pageModelDetails.setWidth("90%");
+ pageModelDetails.setHeight("90%");
+ UI.getCurrent().addWindow(pageModelDetails);
+ });
+
+ return button;
+ }
+
+ private Component buildDeleteButton(final PageModelsTableRow row,
+ final AdminViewController controller) {
+
+ final LocalizedTextsUtil localizedTextsUtil = controller
+ .getGlobalizationHelper()
+ .getLocalizedTextsUtil(AdminUiConstants.ADMIN_BUNDLE);
+
+ final Button button = new Button(localizedTextsUtil
+ .getText("ui.admin.pagemodels.table.columns.delete.label"),
+ VaadinIcons.CLOSE_CIRCLE_O);
+ button.addStyleNames(ValoTheme.BUTTON_TINY,
+ ValoTheme.BUTTON_DANGER);
+ button.addClickListener(event -> {
+ final ConfirmDialog confirmDialog = new ConfirmDialog(
+ () -> {
+ controller
+ .getPageModelsController()
+ .deletePageModel(row.getPageModelId());
+
+ return null;
+ });
+ confirmDialog.setMessage(localizedTextsUtil
+ .getText("ui.admin.pagemodels.delete.confirm"));
+ confirmDialog.setModal(true);
+ confirmDialog.center();
+ UI.getCurrent().addWindow(confirmDialog);
+ });
+ button.setEnabled(!row.isPublished());
+
+ return button;
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableDataProvider.java b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableDataProvider.java
new file mode 100644
index 000000000..051c668e6
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableDataProvider.java
@@ -0,0 +1,145 @@
+/*
+ * 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.vaadin.cdi.ViewScoped;
+import com.vaadin.data.provider.AbstractBackEndDataProvider;
+import com.vaadin.data.provider.Query;
+import org.libreccm.l10n.GlobalizationHelper;
+import org.libreccm.pagemodel.PageModel;
+import org.libreccm.pagemodel.PageModelManager;
+import org.libreccm.pagemodel.PageModelVersion;
+import org.libreccm.web.CcmApplication;
+
+import java.util.stream.Stream;
+
+import javax.inject.Inject;
+import javax.persistence.EntityManager;
+import javax.persistence.criteria.CriteriaBuilder;
+import javax.persistence.criteria.CriteriaQuery;
+import javax.persistence.criteria.Root;
+import javax.transaction.Transactional;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@ViewScoped
+class PageModelsTableDataProvider
+ extends AbstractBackEndDataProvider {
+
+ private static final long serialVersionUID = 8052894182508842905L;
+
+ @Inject
+ private EntityManager entityManager;
+
+ @Inject
+ private GlobalizationHelper globalizationHelper;
+
+ @Inject
+ private PageModelManager pageModelManager;
+
+ private CcmApplication application;
+
+ public CcmApplication getApplication() {
+ return application;
+ }
+
+ public void setApplication(final CcmApplication application) {
+ this.application = application;
+ refreshAll();
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ @Override
+ protected Stream fetchFromBackEnd(
+ final Query query) {
+
+ if (application == null) {
+ return Stream.empty();
+ } else {
+
+ final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+ final CriteriaQuery criteriaQuery = builder
+ .createQuery(PageModel.class);
+
+ final Root from = criteriaQuery.from(PageModel.class);
+
+ criteriaQuery
+ .where(builder
+ .and(builder.equal(from.get("application"), application),
+ builder.equal(from.get("version"),
+ PageModelVersion.DRAFT)))
+ .orderBy(builder.asc(from.get("name")))
+ .orderBy(builder.asc(from.get("title")));
+
+ return entityManager
+ .createQuery(criteriaQuery)
+ .setFirstResult(query.getOffset())
+ .setMaxResults(query.getLimit())
+ .getResultList()
+ .stream()
+ .map(this::buildRow);
+ }
+ }
+
+ private PageModelsTableRow buildRow(final PageModel model) {
+
+ final PageModelsTableRow row = new PageModelsTableRow();
+
+ row.setPageModelId(model.getPageModelId());
+ row.setName(model.getName());
+ row.setTitle(globalizationHelper
+ .getValueFromLocalizedString(model.getTitle()));
+ row.setDescription(globalizationHelper
+ .getValueFromLocalizedString(model.getDescription()));
+ row.setPublished(pageModelManager.isLive(model));
+
+ return row;
+
+ }
+
+ @Override
+ protected int sizeInBackEnd(final Query query) {
+
+ if (application == null) {
+ return 0;
+ } else {
+
+ final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
+ final CriteriaQuery criteriaQuery = builder
+ .createQuery(Long.class);
+
+ final Root from = criteriaQuery.from(PageModel.class);
+ criteriaQuery.select(builder.count(from));
+
+ criteriaQuery
+ .where(builder
+ .and(builder.equal(from.get("application"), application),
+ builder.equal(from.get("version"),
+ PageModelVersion.DRAFT)));
+
+ return entityManager
+ .createQuery(criteriaQuery)
+ .getSingleResult()
+ .intValue();
+ }
+ }
+
+}
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableRow.java b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableRow.java
new file mode 100644
index 000000000..d0cbb8633
--- /dev/null
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/PageModelsTableRow.java
@@ -0,0 +1,164 @@
+/*
+ * 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.io.Serializable;
+import java.util.Objects;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+public class PageModelsTableRow implements Serializable,
+ Comparable {
+
+ private static final long serialVersionUID = -6995542858134206603L;
+
+ private long pageModelId;
+ private String name;
+ private String title;
+ private String description;
+ private boolean published;
+
+ public long getPageModelId() {
+ return pageModelId;
+ }
+
+ public void setPageModelId(final long pageModelId) {
+ this.pageModelId = pageModelId;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setName(final String name) {
+ this.name = name;
+ }
+
+ public String getTitle() {
+ return title;
+ }
+
+ public void setTitle(final String title) {
+ this.title = title;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public void setDescription(final String description) {
+ this.description = description;
+ }
+
+ public boolean isPublished() {
+ return published;
+ }
+
+ public void setPublished(final boolean published) {
+ this.published = published;
+ }
+
+ @Override
+ public int hashCode() {
+ int hash = 3;
+ hash = 17 * hash + (int) (pageModelId ^ (pageModelId >>> 32));
+ hash = 17 * hash + Objects.hashCode(name);
+ hash = 17 * hash + Objects.hashCode(title);
+ hash = 17 * hash + Objects.hashCode(description);
+ hash = 17 * hash + (published ? 1 : 0);
+ return hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (!(obj instanceof PageModelsTableRow)) {
+ return false;
+ }
+ final PageModelsTableRow other = (PageModelsTableRow) obj;
+ if (!other.canEqual(this)) {
+ return false;
+ }
+
+ if (pageModelId != other.getPageModelId()) {
+ return false;
+ }
+ if (published != other.isPublished()) {
+ return false;
+ }
+ if (!Objects.equals(name, other.getName())) {
+ return false;
+ }
+ if (!Objects.equals(title, other.getTitle())) {
+ return false;
+ }
+ return Objects.equals(description, other.getDescription());
+ }
+
+ public boolean canEqual(final Object obj) {
+ return obj instanceof PageModelsTableRow;
+ }
+
+ @Override
+ public int compareTo(final PageModelsTableRow other) {
+
+ int result = title.compareTo(other.getTitle());
+
+ if (result == 0) {
+ result = name.compareTo(other.getName());
+ }
+
+ if (result == 0) {
+ result = Boolean.compare(published, other.isPublished());
+ }
+
+ return result;
+ }
+
+ @Override
+ public final String toString() {
+ return toString("");
+ }
+
+ public String toString(final String data) {
+
+ return String.format("%s{ "
+ + "pageModelId = %d, "
+ + "name = \"%s\", "
+ + "published = %b, "
+ + "title = \"%s\", "
+ + "description = \"%s\"%s"
+ + " }",
+ super.toString(),
+ pageModelId,
+ name,
+ published,
+ title,
+ description,
+ data);
+
+ }
+}
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/SitesController.java b/ccm-core/src/main/java/org/libreccm/admin/ui/SitesController.java
index e7a3f415e..46233773d 100644
--- a/ccm-core/src/main/java/org/libreccm/admin/ui/SitesController.java
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/SitesController.java
@@ -26,7 +26,6 @@ import org.libreccm.theming.Themes;
import java.io.Serializable;
import javax.inject.Inject;
-import javax.persistence.EntityManager;
import javax.transaction.Transactional;
/**
diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/SitesTab.java b/ccm-core/src/main/java/org/libreccm/admin/ui/SitesTab.java
index 4f6d191fe..9b317d4dd 100644
--- a/ccm-core/src/main/java/org/libreccm/admin/ui/SitesTab.java
+++ b/ccm-core/src/main/java/org/libreccm/admin/ui/SitesTab.java
@@ -103,6 +103,7 @@ class SitesTab extends CustomComponent {
final SiteEditor editor = new SiteEditor(
site, adminViewController);
editor.center();
+ editor.setModal(true);
editor.setWidth("66%");
editor.setHeight("80%");
UI.getCurrent().addWindow(editor);
diff --git a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java
index 69851b1fd..3b3a96ef6 100644
--- a/ccm-core/src/main/java/org/libreccm/core/CcmCore.java
+++ b/ccm-core/src/main/java/org/libreccm/core/CcmCore.java
@@ -26,15 +26,23 @@ import com.arsdigita.ui.login.LoginApplicationCreator;
import com.arsdigita.ui.login.LoginApplicationSetup;
import com.arsdigita.ui.login.LoginConstants;
import com.arsdigita.ui.login.LoginServlet;
+
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.admin.ui.AdminJsfApplicationCreator;
import org.libreccm.admin.ui.AdminJsfApplicationSetup;
-import org.libreccm.modules.*;
+import org.libreccm.modules.CcmModule;
+import org.libreccm.modules.InitEvent;
+import org.libreccm.modules.InstallEvent;
+import org.libreccm.modules.Module;
+import org.libreccm.modules.ShutdownEvent;
+import org.libreccm.modules.UnInstallEvent;
+
import org.libreccm.security.SystemUsersSetup;
import org.libreccm.web.ApplicationType;
import javax.persistence.EntityManager;
+
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
diff --git a/ccm-core/src/main/java/org/libreccm/web/ApplicationManager.java b/ccm-core/src/main/java/org/libreccm/web/ApplicationManager.java
index 059a4cc85..4c5917c3b 100644
--- a/ccm-core/src/main/java/org/libreccm/web/ApplicationManager.java
+++ b/ccm-core/src/main/java/org/libreccm/web/ApplicationManager.java
@@ -74,6 +74,12 @@ public class ApplicationManager {
}
}
+ /**
+ * Get all available application types.
+ *
+ * @return An unmodifiable {@link Map} containing all available application
+ * types. The key of the map is the name of the application.
+ */
public Map getApplicationTypes() {
return Collections.unmodifiableMap(applicationTypes);
}
diff --git a/ccm-core/src/test/java/org/libreccm/portation/CoreDataImportTest.java b/ccm-core/src/test/java/org/libreccm/portation/CoreDataImportTest.java
index a679ab98e..ba14ebc03 100644
--- a/ccm-core/src/test/java/org/libreccm/portation/CoreDataImportTest.java
+++ b/ccm-core/src/test/java/org/libreccm/portation/CoreDataImportTest.java
@@ -30,7 +30,7 @@ import org.jboss.arquillian.transaction.api.annotation.Transactional;
import org.jboss.shrinkwrap.api.ShrinkWrap;
import org.jboss.shrinkwrap.api.asset.EmptyAsset;
import org.jboss.shrinkwrap.api.spec.WebArchive;
-import org.junit.*;
+
import org.junit.experimental.categories.Category;
import org.junit.runner.RunWith;
import org.libreccm.security.GroupRepository;
@@ -40,6 +40,13 @@ import javax.inject.Inject;
import static org.libreccm.testutils.DependenciesHelpers.getModuleDependencies;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Test;
+
/**
* Test class. Tests the import capabilities of the core module
diff --git a/ccm-core/src/test/java/org/libreccm/portation/ImportHelper.java b/ccm-core/src/test/java/org/libreccm/portation/ImportHelper.java
index e5a354017..227ac3691 100644
--- a/ccm-core/src/test/java/org/libreccm/portation/ImportHelper.java
+++ b/ccm-core/src/test/java/org/libreccm/portation/ImportHelper.java
@@ -64,8 +64,9 @@ import javax.inject.Inject;
*/
@RequestScoped
class ImportHelper {
- //private String repoPath = "/home/jensp/pwi/libreccm/ccm/";
- private final String repoPath = "/home/tosmers/Svn/libreccm/";
+
+ private String repoPath = "/home/jensp/pwi/libreccm/ccm/";
+// private final String repoPath = "/home/tosmers/Svn/libreccm/";
private final String projectPath = "ccm_ng/ccm-core/src/test/resources/" +
"portation/trunk-iaw-exports";
private final boolean indentation = false;