diff --git a/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/beans.xml b/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/beans.xml
index b83fc94b7..194f21e6e 100644
--- a/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/beans.xml
+++ b/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/beans.xml
@@ -1,6 +1,7 @@
+
+ bean-discovery-mode="all">
\ No newline at end of file
diff --git a/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/web.xml b/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/web.xml
index 42fb40ecd..08945269c 100644
--- a/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/web.xml
+++ b/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/web.xml
@@ -27,6 +27,15 @@
org.apache.shiro.web.env.EnvironmentLoaderListener
+
+
+
Faces Servlet
javax.faces.webapp.FacesServlet
@@ -46,4 +55,19 @@
javax.faces.FACELETS_SKIP_COMMENTS
true
+
+
+ vaadin-servlet
+ com.vaadin.cdi.server.VaadinCDIServlet
+
+
+
+ vaadin-servlet
+ /vaadin/
+
+
+ vaadin-servlet
+ /VAADIN/
+
+
diff --git a/ccm-bundle-devel/pom.xml b/ccm-bundle-devel/pom.xml
index a7d938add..cf08bcbd5 100644
--- a/ccm-bundle-devel/pom.xml
+++ b/ccm-bundle-devel/pom.xml
@@ -59,6 +59,34 @@
org.apache.logging.log4j
log4j-api
+
+
+
+ com.vaadin
+ vaadin-compatibility-server
+
+
+ com.vaadin
+ vaadin-compatibility-shared
+
+
+
+ com.vaadin
+ vaadin-compatibility-themes
+
+
+ com.vaadin
+ vaadin-compatibility-client-compiled
+ 8.0.4
+
+
+ com.vaadin
+ vaadin-cdi
+
diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/AssetSearchPage.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/AssetSearchPage.java
index 7d3c85c3b..e40950dcd 100644
--- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/AssetSearchPage.java
+++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/assets/AssetSearchPage.java
@@ -24,15 +24,19 @@ import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.SimpleContainer;
+import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.event.FormInitListener;
import com.arsdigita.bebop.event.FormSectionEvent;
import com.arsdigita.bebop.form.Submit;
import com.arsdigita.bebop.form.TextField;
import com.arsdigita.bebop.parameters.LongParameter;
import com.arsdigita.bebop.parameters.StringParameter;
+import com.arsdigita.bebop.table.TableColumn;
+import com.arsdigita.bebop.table.TableColumnModel;
import com.arsdigita.cms.dispatcher.CMSPage;
import com.arsdigita.globalization.GlobalizedMessage;
import com.arsdigita.toolbox.ui.LayoutPanel;
+
import org.librecms.CmsConstants;
/**
@@ -46,6 +50,10 @@ public class AssetSearchPage extends CMSPage {
private static final String WIDGET_PARAM = "widget";
private static final String ASSET_TYPE_PARAM = "assettype";
+ private static final int RESULTS_TABLE_COL_TITLE = 0;
+ private static final int RESULTS_TABLE_COL_PLACE = 1;
+ private static final int RESULTS_TABLE_COL_TYPE = 2;
+
private final LongParameter contentSectionId;
private TextField query;
@@ -65,27 +73,59 @@ public class AssetSearchPage extends CMSPage {
final Form queryForm = new Form("asset-search-page-query-form");
queryForm.add(new Label(new GlobalizedMessage(
- "cms.ui.assets.search_page.query",
- CmsConstants.CMS_BUNDLE)));
+ "cms.ui.assets.search_page.query",
+ CmsConstants.CMS_BUNDLE)));
query = new TextField("asset-search-page-query-form");
queryForm.add(query);
final Submit querySubmit = new Submit(new GlobalizedMessage(
- "cms.ui.assets.search_page.query.submit"));
+ "cms.ui.assets.search_page.query.submit"));
queryForm.add(querySubmit);
-
+
queryForm.addInitListener(new FormInitListener() {
+
@Override
- public void init(final FormSectionEvent event)
- throws FormProcessException {
-
+ public void init(final FormSectionEvent event)
+ throws FormProcessException {
+
final PageState state = event.getPageState();
final FormData data = event.getFormData();
-
+
final String query = (String) data.get(QUERY_PARAM);
-
+
}
+
});
+ mainPanel.setLeft(queryForm);
+
+ final Table resultsTable = new Table();
+ resultsTable.setEmptyView(
+ new Label(
+ new GlobalizedMessage(
+ "cms.ui.assets.search_page.none",
+ CmsConstants.CMS_BUNDLE)));
+ resultsTable.setClassAttr("dataTable");
+
+ final TableColumnModel columnModel = resultsTable.getColumnModel();
+ columnModel.add(new TableColumn(
+ RESULTS_TABLE_COL_TITLE,
+ new GlobalizedMessage(
+ "cms.ui.assets.search_page.results_table.title",
+ CmsConstants.CMS_BUNDLE)));
+ columnModel.add(new TableColumn(
+ RESULTS_TABLE_COL_PLACE,
+ new GlobalizedMessage(
+ "cms.ui.assets.search_page.results_table.place",
+ CmsConstants.CMS_BUNDLE)));
+ columnModel.add(new TableColumn(
+ RESULTS_TABLE_COL_TYPE,
+ new GlobalizedMessage(
+ "cms.ui.assets.search_page.results_table.type",
+ CmsConstants.CMS_BUNDLE)));
+
+
+ mainPanel.setBody(resultsTable);
+
}
}
diff --git a/ccm-cms/src/main/java/org/librecms/assets/AssetSearchService.java b/ccm-cms/src/main/java/org/librecms/assets/AssetSearchService.java
new file mode 100644
index 000000000..132a961f7
--- /dev/null
+++ b/ccm-cms/src/main/java/org/librecms/assets/AssetSearchService.java
@@ -0,0 +1,321 @@
+/*
+ * 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.librecms.assets;
+
+import com.arsdigita.kernel.KernelConfig;
+
+import org.libreccm.l10n.GlobalizationHelper;
+import org.librecms.contentsection.Asset;
+import org.librecms.contentsection.AssetRepository;
+
+import org.librecms.contentsection.ContentSection;
+import org.librecms.contentsection.ContentSectionRepository;
+import org.librecms.contentsection.Folder;
+import org.librecms.contentsection.FolderRepository;
+import org.librecms.contentsection.FolderType;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.ResourceBundle;
+import java.util.stream.Collectors;
+
+import javax.enterprise.context.RequestScoped;
+import javax.inject.Inject;
+import javax.transaction.Transactional;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+
+/**
+ *
+ * @author Jens Pelzetter
+ */
+@RequestScoped
+@Path("/{content-section}/assets")
+public class AssetSearchService {
+
+ @Inject
+ private AssetRepository assetRepo;
+
+ @Inject
+ private AssetTypesManager assetTypesManager;
+
+ @Inject
+ private ContentSectionRepository sectionRepo;
+
+ @Inject
+ private FolderRepository folderRepo;
+
+ @Inject
+ private GlobalizationHelper globalizationHelper;
+
+ private Class extends Asset> toAssetClass(final String type) {
+ final Class> clazz;
+ try {
+ clazz = Class.forName(type);
+ } catch (ClassNotFoundException ex) {
+ throw new IllegalArgumentException(String.format(
+ "Type '%s' is not a valid class.",
+ type));
+ }
+
+ if (clazz.isAssignableFrom(Asset.class)) {
+ @SuppressWarnings("unchecked")
+ final Class extends Asset> typeClass
+ = (Class extends Asset>) clazz;
+ return typeClass;
+ } else {
+ throw new IllegalArgumentException(String.format(
+ "Type '%s is not a subclass of '%s'.",
+ type,
+ Asset.class.getName()));
+ }
+ }
+
+ public List findAssetsByQuery(final String query) {
+ return assetRepo.findByTitle(query);
+ }
+
+ public List findAssetsByType(final String type) {
+ return AssetSearchService.this.findAssets(toAssetClass(type));
+ }
+
+ public List findAssets(final Class extends Asset> type) {
+ return assetRepo.findByType(type);
+ }
+
+ public List findAssets(final String query, final String type) {
+
+ final Class> clazz;
+ try {
+ clazz = Class.forName(type);
+ } catch (ClassNotFoundException ex) {
+ throw new IllegalArgumentException(String.format(
+ "Type '%s' is not a valid class.",
+ type));
+ }
+
+ if (clazz.isAssignableFrom(Asset.class)) {
+ @SuppressWarnings("unchecked")
+ final Class extends Asset> typeClass
+ = (Class extends Asset>) clazz;
+ return AssetSearchService.this.findAssets(query, typeClass);
+ } else {
+ throw new IllegalArgumentException(String.format(
+ "Type '%s is not a subclass of '%s'.",
+ type,
+ Asset.class.getName()));
+ }
+
+ }
+
+ public List findAssets(final ContentSection section,
+ final String path) {
+ final Optional folder = folderRepo
+ .findByPath(section,
+ path,
+ FolderType.ASSETS_FOLDER);
+
+ if (!folder.isPresent()) {
+ return Collections.emptyList();
+ }
+
+ return assetRepo.findByFolder(folder.get());
+ }
+
+ public List findAssets(final String query,
+ final Class extends Asset> type) {
+ return assetRepo.findByTitleAndType(query, type);
+
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public List findAssetsByType(final ContentSection section,
+ final String path,
+ final String type) {
+
+ final Optional folder = folderRepo
+ .findByPath(section,
+ path,
+ FolderType.ASSETS_FOLDER);
+
+ if (!folder.isPresent()) {
+ return Collections.emptyList();
+ }
+
+ return assetRepo.filterByFolderAndType(folder.get(),
+ toAssetClass(type));
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public List findAssetsByQuery(final ContentSection section,
+ final String path,
+ final String query) {
+
+ final Optional folder = folderRepo
+ .findByPath(section,
+ path,
+ FolderType.ASSETS_FOLDER);
+
+ if (!folder.isPresent()) {
+ return Collections.emptyList();
+ }
+
+ return assetRepo.filterByFolderAndTitle(folder.get(),
+ query);
+ }
+
+ @Transactional(Transactional.TxType.REQUIRED)
+ public List findAssets(final ContentSection section,
+ final String path,
+ final String query,
+ final String type) {
+
+ final Optional folder = folderRepo
+ .findByPath(section,
+ path,
+ FolderType.ASSETS_FOLDER);
+
+ if (!folder.isPresent()) {
+ return Collections.emptyList();
+ }
+
+ return assetRepo.filterByFolderAndTypeAndTitle(folder.get(),
+ toAssetClass(type),
+ query);
+
+ }
+
+ @GET
+ @Produces("text/json")
+ @Transactional(Transactional.TxType.REQUIRED)
+ public List