CCM NG/ccm-cms: Vaadin Prototype

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4996 8810af33-2d31-482b-a856-94f89814c4df
jensp 2017-09-11 16:38:56 +00:00
parent de06b4ea4f
commit cdf420fed0
17 changed files with 1133 additions and 24 deletions

View File

@ -18,6 +18,7 @@
*/ */
package org.librecms.contentsection; package org.librecms.contentsection;
import com.arsdigita.cms.ui.authoring.ItemCategoryStep;
import com.arsdigita.cms.ui.authoring.assets.relatedinfo.RelatedInfoStep; import com.arsdigita.cms.ui.authoring.assets.relatedinfo.RelatedInfoStep;
import com.arsdigita.cms.ui.authoring.assets.images.ImageStep; import com.arsdigita.cms.ui.authoring.assets.images.ImageStep;
@ -123,6 +124,7 @@ public class ContentSectionConfig {
@Setting @Setting
private List<String> defaultAuthoringSteps = Arrays private List<String> defaultAuthoringSteps = Arrays
.asList(new String[]{ .asList(new String[]{
ItemCategoryStep.class.getName(),
ImageStep.class.getName(), ImageStep.class.getName(),
RelatedInfoStep.class.getName()}); RelatedInfoStep.class.getName()});
@ -175,12 +177,13 @@ public class ContentSectionConfig {
public void setMaxAlerts(final int maxAlerts) { public void setMaxAlerts(final int maxAlerts) {
this.maxAlerts = maxAlerts; this.maxAlerts = maxAlerts;
} }
public List<String> getDefaultAuthoringSteps() { public List<String> getDefaultAuthoringSteps() {
return new ArrayList<>(defaultAuthoringSteps); return new ArrayList<>(defaultAuthoringSteps);
} }
public void setDefaultAuthoringSteps(final List<String> defaultAuthoringSteps) { public void setDefaultAuthoringSteps(
final List<String> defaultAuthoringSteps) {
this.defaultAuthoringSteps = new ArrayList<>(defaultAuthoringSteps); this.defaultAuthoringSteps = new ArrayList<>(defaultAuthoringSteps);
} }

View File

@ -60,18 +60,19 @@ import static org.librecms.CmsConstants.*;
, ,
@NamedQuery( @NamedQuery(
name = "Folder.findSubFolders", name = "Folder.findSubFolders",
query = "SELECT f FROM Folder f WHERE f.parentCategory = :parent " query = "SELECT f "
+ "AND LOWER(f.name) LIKE :term " + "FROM Folder f"
+ " WHERE f.parentCategory = :parent "
+ "ORDER BY f.name" + "ORDER BY f.name"
) )
, ,
// @NamedQuery( @NamedQuery(
// name = "Folder.countSubFolders", name = "Folder.countSubFolders",
// query query = "SELECT COUNT(f) "
// = "SELECT COUNT(f) FROM Folder f WHERE f.parentCategory = :parent " + "FROM Folder f "
// + "AND LOWER(f.name) LIKE :term" + "WHERE f.parentCategory = :parent"
// ) )
// , ,
// @NamedQuery( // @NamedQuery(
// name = "Folder.findItems", // name = "Folder.findItems",
// query = "SELECT c.categorizedObject " // query = "SELECT c.categorizedObject "

View File

@ -183,6 +183,31 @@ public class FolderRepository extends AbstractEntityRepository<Long, Folder> {
return Optional.of(current); return Optional.of(current);
} }
/**
* Counts the subfolders of a folder.
*
* @param parent The folder.
*
* @return The number of subfolders in the folder.
*/
public long countSubFolders(final Folder parent) {
final TypedQuery<Long> query = getEntityManager()
.createNamedQuery("Folder.countSubFolders", Long.class);
query.setParameter("parent", parent);
return query.getSingleResult();
}
public List<Folder> findSubFolders(final Folder parent) {
final TypedQuery<Folder> query = getEntityManager()
.createNamedQuery("Folder.findSubFolders", Folder.class);
query.setParameter("parent", parent);
return query.getResultList();
}
@AuthorizationRequired @AuthorizationRequired
@Transactional(Transactional.TxType.REQUIRED) @Transactional(Transactional.TxType.REQUIRED)
@Override @Override

View File

@ -37,6 +37,7 @@ public class ContentSections extends Application{
final Set<Class<?>> classes = new HashSet<>(); final Set<Class<?>> classes = new HashSet<>();
classes.add(Assets.class); classes.add(Assets.class);
classes.add(ContentItems.class);
classes.add(Images.class); classes.add(Images.class);
return classes; return classes;

View File

@ -33,6 +33,7 @@ import java.util.stream.Collectors;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import javax.enterprise.context.RequestScoped; import javax.enterprise.context.RequestScoped;
import javax.transaction.Transactional;
/** /**
* Provides informations about the available content types. * Provides informations about the available content types.
@ -291,6 +292,7 @@ public class ContentTypesManager {
* *
* @return A {@link ContentTypeInfo} describing the content type. * @return A {@link ContentTypeInfo} describing the content type.
*/ */
@Transactional(Transactional.TxType.REQUIRED)
public ContentTypeInfo getContentTypeInfo(final ContentType contentType) { public ContentTypeInfo getContentTypeInfo(final ContentType contentType) {
return getContentTypeInfo(contentType.getContentItemClass()); return getContentTypeInfo(contentType.getContentItemClass());
} }

View File

@ -0,0 +1,112 @@
/*
* 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.ui;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Grid;
import com.vaadin.ui.HorizontalSplitPanel;
import com.vaadin.ui.ItemCollapseAllowedProvider;
import com.vaadin.ui.Tree;
import org.librecms.contentsection.Folder;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public class BrowseDocuments extends CustomComponent {
private static final long serialVersionUID = -7241214812224026430L;
private static final String COL_DOCUMENT_CREATED = "created";
private static final String COL_DOCUMENT_LAST_MODIFIED = "lastmodified";
private static final String COL_DOCUMENT_NAME = "name";
private static final String COL_DOCUMENT_TITLE = "title";
private static final String COL_DOCUMENT_TYPE = "ttype";
private final ContentSectionViewController controller;
private final Tree<Folder> folderTree;
private final Grid<BrowseDocumentsItem> documentsGrid;
private final BrowseDocumentsDataProvider documentsDataProvider;
private final BrowseDocumentsFolderTreeDataProvider folderTreeDataProvider;
public BrowseDocuments(final ContentSectionViewController controller) {
super();
this.controller = controller;
folderTreeDataProvider = controller.getFolderTreeDataProvider();
folderTree = new Tree<>(folderTreeDataProvider);
folderTree.setItemCaptionGenerator(folder -> {
return controller
.getGlobalizationHelper()
.getValueFromLocalizedString(folder.getTitle());
});
documentsGrid = new Grid<>();
documentsGrid
.addColumn(BrowseDocumentsItem::getName)
.setCaption("Name")
.setId(COL_DOCUMENT_NAME);
documentsGrid
.addColumn(BrowseDocumentsItem::getTitle)
.setCaption("Title")
.setId(COL_DOCUMENT_TITLE);
documentsGrid
.addColumn(BrowseDocumentsItem::getType)
.setCaption("Type")
.setId(COL_DOCUMENT_TYPE);
documentsGrid
.addColumn(BrowseDocumentsItem::getCreationDate)
.setCaption("Created")
.setId(COL_DOCUMENT_CREATED);
documentsGrid
.addColumn(BrowseDocumentsItem::getLastModified)
.setCaption("Last modified")
.setId(COL_DOCUMENT_LAST_MODIFIED);
documentsDataProvider = controller.getBrowseDocumentsDataProvider();
documentsGrid.setDataProvider(documentsDataProvider);
documentsGrid.setWidth("100%");
documentsGrid.setHeight("100%");
folderTree.addItemClickListener(event -> {
documentsDataProvider.setCurrentFolder(event.getItem());
documentsDataProvider.refreshAll();
});
folderTree.setItemCollapseAllowedProvider(folder -> {
return folder.getParentCategory() != null;
});
final HorizontalSplitPanel splitPanel = new HorizontalSplitPanel(
folderTree, documentsGrid);
splitPanel.setSplitPosition(17.5f, Unit.PERCENTAGE);
splitPanel.setHeight("100%");
super.setCompositionRoot(splitPanel);
}
public Tree<Folder> getFolderTree() {
return folderTree;
}
public Grid<BrowseDocumentsItem> getDocumentsGrid() {
return documentsGrid;
}
}

View File

@ -0,0 +1,498 @@
/*
* 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.ui;
import com.vaadin.cdi.ViewScoped;
import com.vaadin.data.provider.AbstractBackEndDataProvider;
import com.vaadin.data.provider.Query;
import org.libreccm.categorization.Categorization;
import org.libreccm.core.CcmObject;
import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.l10n.LocalizedTextsUtil;
import org.librecms.contentsection.ContentItem;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.Folder;
import org.librecms.contenttypes.ContentTypeInfo;
import org.librecms.contenttypes.ContentTypesManager;
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.Join;
import javax.persistence.criteria.Root;
import javax.persistence.criteria.Subquery;
import javax.transaction.Transactional;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ViewScoped
class BrowseDocumentsDataProvider
extends AbstractBackEndDataProvider<BrowseDocumentsItem, String> {
private static final long serialVersionUID = 7693820518000376630L;
@Inject
private ContentSectionViewState contentSectionViewState;
@Inject
private EntityManager entityManager;
@Inject
private ContentTypesManager typesManager;
@Inject
private GlobalizationHelper globalizationHelper;
private Folder currentFolder;
protected Folder getCurrentFolder() {
return currentFolder;
}
protected void setCurrentFolder(final Folder currentFolder) {
this.currentFolder = currentFolder;
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
protected Stream<BrowseDocumentsItem> fetchFromBackEnd(
final Query<BrowseDocumentsItem, String> query) {
final Folder folder;
if (currentFolder == null) {
folder = contentSectionViewState
.getSelectedContentSection()
.getRootDocumentsFolder();
} else {
folder = currentFolder;
}
final CriteriaBuilder criteriaBuilder = entityManager
.getCriteriaBuilder();
final CriteriaQuery<CcmObject> criteriaQuery = criteriaBuilder
.createQuery(CcmObject.class);
final Subquery<Folder> folderQuery = criteriaQuery
.subquery(Folder.class);
final Root<Folder> fromFolder = folderQuery.from(Folder.class);
folderQuery.select(fromFolder);
if (query.getFilter().isPresent()) {
final String filter = query.getFilter().get();
folderQuery.where(criteriaBuilder
.and(
criteriaBuilder.equal(fromFolder.get("parentCategory"),
folder),
criteriaBuilder.or(
criteriaBuilder.like(fromFolder.get("name"),
String.format("%s%%", filter)),
criteriaBuilder.like(fromFolder.get("displayName"),
String.format("%s%%", filter)))));
} else {
folderQuery
.where(criteriaBuilder.equal(fromFolder.get("parentCategory"),
folder));
}
final Subquery<ContentItem> itemQuery = criteriaQuery
.subquery(ContentItem.class);
final Root<ContentItem> fromItem = itemQuery.from(ContentItem.class);
final Join<ContentItem, Categorization> joinCat = fromItem
.join("categories");
itemQuery.select(fromItem);
if (query.getFilter().isPresent()) {
final String filter = query.getFilter().get();
itemQuery
.where(criteriaBuilder.and(
criteriaBuilder.equal(joinCat.get("category"), folder),
criteriaBuilder.or(
criteriaBuilder.like(fromItem.get("displayName"),
String.format("%s%%", filter)),
criteriaBuilder.like(fromItem.get("name"),
String.format("%s%%", filter))
)
));
} else {
itemQuery
.where(criteriaBuilder.equal(joinCat.get("category"), folder));
}
final Root<CcmObject> from = criteriaQuery.from(CcmObject.class);
criteriaQuery.select(from);
criteriaQuery.where(
criteriaBuilder.or(
criteriaBuilder.in(from).value(folderQuery),
criteriaBuilder.in(from).value(itemQuery)
));
return entityManager
.createQuery(criteriaQuery)
.setMaxResults(query.getLimit())
.setFirstResult(query.getOffset())
.getResultList()
.stream()
.map(this::buildRow);
}
private BrowseDocumentsItem buildRow(final CcmObject object) {
final BrowseDocumentsItem row = new BrowseDocumentsItem();
if (object instanceof Folder) {
final Folder folder = (Folder) object;
row.setFolder(true);
row.setItemId(folder.getObjectId());
row.setName(folder.getName());
row.setTitle(globalizationHelper
.getValueFromLocalizedString(folder.getTitle()));
} else if (object instanceof ContentItem) {
final ContentItem item = (ContentItem) object;
row.setCreationDate(((ContentItem) object).getCreationDate());
row.setFolder(false);
row.setItemId(item.getObjectId());
row.setLastModified(item.getLastModified());
row.setName(globalizationHelper
.getValueFromLocalizedString(item.getName()));
row.setTitle(globalizationHelper
.getValueFromLocalizedString(item.getTitle()));
final ContentTypeInfo typeInfo = typesManager
.getContentTypeInfo(item.getClass());
final LocalizedTextsUtil textsUtil = globalizationHelper
.getLocalizedTextsUtil(typeInfo.getLabelBundle());
row.setType(textsUtil.getText(typeInfo.getLabelKey()));
} else {
row.setFolder(false);
row.setItemId(object.getObjectId());
row.setName(object.getDisplayName());
}
return row;
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
protected int sizeInBackEnd(
final Query<BrowseDocumentsItem, String> query) {
final Folder folder;
if (currentFolder == null) {
folder = contentSectionViewState
.getSelectedContentSection()
.getRootDocumentsFolder();
} else {
folder = currentFolder;
}
final CriteriaBuilder criteriaBuilder = entityManager
.getCriteriaBuilder();
final CriteriaQuery<Long> criteriaQuery = criteriaBuilder
.createQuery(Long.class);
final Subquery<Folder> folderQuery = criteriaQuery
.subquery(Folder.class);
final Root<Folder> fromFolder = folderQuery.from(Folder.class);
folderQuery.select(fromFolder);
if (query.getFilter().isPresent()) {
final String filter = query.getFilter().get();
folderQuery.where(criteriaBuilder
.and(
criteriaBuilder.equal(fromFolder.get("parentCategory"),
folder),
criteriaBuilder.or(
criteriaBuilder.like(fromFolder.get("name"),
String.format("%s%%", filter)),
criteriaBuilder.like(fromFolder.get("displayName"),
String.format("%s%%", filter)))));
} else {
folderQuery
.where(criteriaBuilder.equal(fromFolder.get("parentCategory"),
folder));
}
final Subquery<ContentItem> itemQuery = criteriaQuery
.subquery(ContentItem.class);
final Root<ContentItem> fromItem = itemQuery.from(ContentItem.class);
final Join<ContentItem, Categorization> joinCat = fromItem
.join("categories");
itemQuery.select(fromItem);
if (query.getFilter().isPresent()) {
final String filter = query.getFilter().get();
itemQuery
.where(criteriaBuilder.and(
criteriaBuilder.equal(joinCat.get("category"), folder),
criteriaBuilder.or(
criteriaBuilder.like(fromItem.get("displayName"),
String.format("%s%%", filter)),
criteriaBuilder.like(fromItem.get("name"),
String.format("%s%%", filter))
)
));
} else {
itemQuery
.where(criteriaBuilder.equal(joinCat.get("category"), folder));
}
final Root<CcmObject> from = criteriaQuery.from(CcmObject.class);
criteriaQuery.select(criteriaBuilder.count(from));
criteriaQuery.where(
criteriaBuilder.or(
criteriaBuilder.in(from).value(folderQuery),
criteriaBuilder.in(from).value(itemQuery)
));
return entityManager
.createQuery(criteriaQuery)
.getSingleResult()
.intValue();
}
// @Override
// protected Stream<BrowseDocumentsItem> fetchFromBackEnd(
// final Query<BrowseDocumentsItem, String> query) {
//
// final int subFoldersCount = countSubFolder(currentFolder,
// query.getFilter());
// final int itemsCount = countItems(currentFolder, query.getFilter());
//
// final int limit = query.getLimit();
// final int offset = query.getOffset();
//
// final int subFoldersLimit;
// final int subFoldersOffset;
// final int itemsLimit;
// final int itemsOffset;
// if (subFoldersCount > (limit + offset)) {
//
// subFoldersLimit = limit;
//
//
// } else {
//
// }
//
// final List<Folder> subFolders = fetchSubFolders(currentFolder,
// query.getFilter(),
// query.getLimit(),
// query.getOffset());
// final List<ContentItem> items = fetchItems(currentFolder,
// query.getFilter());
//
// final List<BrowseDocumentsItem> subFolderItems = subFolders
// .stream()
// .map(this::createBrowseDocumentsItem)
// .collect(Collectors.toList());
//
// final List<BrowseDocumentsItem> itemList = items
// .stream()
// .map(this::createBrowseDocumentsItem)
// .collect(Collectors.toList());
//
// final List<BrowseDocumentsItem> rows = new ArrayList<>();
// rows.addAll(subFolderItems);
// rows.addAll(itemList);
//
// return rows.stream();
// }
//
// private List<Folder> fetchSubFolders(final Folder folder,
// final Optional<String> filter,
// final int limit,
// final int offset) {
//
// final CriteriaBuilder builder = entityManager
// .getCriteriaBuilder();
// final CriteriaQuery<Folder> query = builder.createQuery(Folder.class);
// final Root<Folder> from = query.from(Folder.class);
//
// if (filter.isPresent()) {
// query.where(builder
// .and(builder.equal(from.get("parentCategory"), folder),
// builder.or(
// builder.like(builder.lower(from.get("name")),
// String.format("%s%%", filter.get())),
// builder.like(builder.lower(from.get("displayName")),
// String.format("%s%%", filter.get())))));
// } else {
// query.where(builder.equal(from.get("parentCategory"), folder));
// }
//
// query.orderBy(builder.asc(from.get("name")),
// builder.asc(from.get("displayName")));
//
// return entityManager
// .createQuery(query)
// .setMaxResults(limit)
// .setFirstResult(offset)
// .getResultList();
// }
//
// private List<ContentItem> fetchItems(final Folder folder,
// final Optional<String> filter) {
//
// final CriteriaBuilder builder = entityManager
// .getCriteriaBuilder();
// final CriteriaQuery<ContentItem> query = builder
// .createQuery(ContentItem.class);
// final Root<ContentItem> from = query.from(ContentItem.class);
// final Join<ContentItem, Categorization> join = from.join("categories");
//
// if (filter.isPresent()) {
// query.where(builder
// .and(builder.equal(join.get("category"), folder),
// builder.or(
// builder.like(builder.lower(from.get("name")),
// String.format("%s%%", filter.get())),
// builder.like(builder.lower(from.get("displayName")),
// String.format("%s%%", filter.get())))));
//
// } else {
// query.where(builder.equal(join.get("category"), folder));
// }
//
// return entityManager
// .createQuery(query)
// .getResultList();
// }
//
// private BrowseDocumentsItem createBrowseDocumentsItem(
// final Folder fromFolder) {
//
// final BrowseDocumentsItem item = new BrowseDocumentsItem();
// item.setItemId(fromFolder.getObjectId());
// item.setName(fromFolder.getName());
// item.setTitle(fromFolder
// .getTitle()
// .getValue(controller.getGlobalizationHelper().getNegotiatedLocale()));
// item.setFolder(true);
//
// return item;
// }
//
// private BrowseDocumentsItem createBrowseDocumentsItem(
// final ContentItem fromItem) {
//
// final BrowseDocumentsItem item = new BrowseDocumentsItem();
// item.setCreationDate(fromItem.getCreationDate());
// item.setFolder(false);
// item.setItemId(fromItem.getObjectId());
// item.setLastChanged(fromItem.getLastModified());
// item.setName(item.getName());
// item.setTitle(fromItem
// .getTitle()
// .getValue(controller.getGlobalizationHelper().getNegotiatedLocale()));
//
// final ContentTypesManager typesManager = controller
// .getContentTypesManager();
// final ContentTypeInfo typeInfo = typesManager
// .getContentTypeInfo(fromItem.getContentType());
// final LocalizedTextsUtil textsUtil = controller
// .getGlobalizationHelper()
// .getLocalizedTextsUtil(typeInfo.getLabelBundle());
// item.setType(textsUtil.getText(typeInfo.getLabelKey()));
//
// return item;
// }
//
// @Transactional(Transactional.TxType.REQUIRED)
// @Override
// protected int sizeInBackEnd(final Query<BrowseDocumentsItem, String> query) {
//
// final Folder folder;
// if (currentFolder == null) {
// folder = controller.getCurrentSection().getRootDocumentsFolder();
// } else {
// folder = currentFolder;
// }
//
// final int subFolderCount = countSubFolder(folder, query.getFilter());
// final int itemCount = countItems(folder, query.getFilter());
//
// return subFolderCount + itemCount;
// }
//
// private int countSubFolder(final Folder folder,
// final Optional<String> filter) {
//
// final CriteriaBuilder builder = entityManager
// .getCriteriaBuilder();
// final CriteriaQuery<Long> query = builder.createQuery(Long.class);
// final Root<Folder> from = query.from(Folder.class);
//
// query.select(builder.count(from));
//
// if (filter.isPresent()) {
// query.where(builder
// .and(builder.equal(from.get("parentCategory"), folder),
// builder.or(
// builder.like(builder.lower(from.get("name")),
// String.format("%s%%", filter.get())),
// builder.like(builder.lower(from.get("displayName")),
// String.format("%s%%", filter.get())))));
// } else {
// query.where(builder.equal(from.get("parentCategory"), folder));
// }
//
// return entityManager
// .createQuery(query)
// .getSingleResult()
// .intValue();
// }
//
// private int countItems(final Folder folder,
// final Optional<String> filter) {
//
// final CriteriaBuilder builder = entityManager
// .getCriteriaBuilder();
// final CriteriaQuery<Long> query = builder.createQuery(Long.class);
// final Root<ContentItem> from = query.from(ContentItem.class);
// final Join<ContentItem, Categorization> join = from.join("categories");
//
// query.select(builder.count(from));
//
// if (filter.isPresent()) {
// query.where(builder
// .and(builder.equal(join.get("category"), folder),
// builder.or(
// builder.like(builder.lower(from.get("name")),
// String.format("%s%%", filter.get())),
// builder.like(builder.lower(from.get("displayName")),
// String.format("%s%%", filter.get())))));
//
// } else {
// query.where(builder.equal(join.get("category"), folder));
// }
//
// return entityManager
// .createQuery(query)
// .getSingleResult()
// .intValue();
// }
}

View File

@ -0,0 +1,129 @@
/*
* 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.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.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionRepository;
import org.librecms.contentsection.Folder;
import org.librecms.contentsection.FolderRepository;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
import javax.inject.Inject;
import javax.transaction.Transactional;
/**
* Data provider for the tree component of the {@link BrowseDocuments}
* component.
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ViewScoped
public class BrowseDocumentsFolderTreeDataProvider
extends AbstractBackEndHierarchicalDataProvider<Folder, String> {
private static final long serialVersionUID = 5330319780008907163L;
@Inject
private ContentSectionViewState contentSectionViewState;
@Inject
private FolderRepository folderRepo;
@Inject
private ContentSectionRepository sectionRepo;
@Override
protected Stream<Folder> fetchChildrenFromBackEnd(
HierarchicalQuery<Folder, String> query) {
final Optional<Folder> selectedParent = query.getParentOptional();
final Folder parent;
if (selectedParent.isPresent()) {
parent = folderRepo
.findById(selectedParent.get().getObjectId())
.orElseThrow(() -> new IllegalArgumentException(String
.format("No folder with ID %d in the database.",
selectedParent.get().getObjectId())));
return folderRepo.findSubFolders(parent).stream();
} else {
final ContentSection section = sectionRepo
.findById(contentSectionViewState
.getSelectedContentSection()
.getObjectId())
.orElseThrow(() -> new UnexpectedErrorException(String
.format("No ContentSection with ID %d in the database.",
contentSectionViewState
.getSelectedContentSection()
.getObjectId())));
final List<Folder> result = new ArrayList<>();
result.add(section.getRootDocumentsFolder());
return result.stream();
}
}
@Transactional(Transactional.TxType.REQUIRED)
@Override
public int getChildCount(
final HierarchicalQuery<Folder, String> query) {
final Optional<Folder> selectedParent = query.getParentOptional();
final Folder parent;
if (selectedParent.isPresent()) {
parent = folderRepo
.findById(selectedParent.get().getObjectId())
.orElseThrow(() -> new IllegalArgumentException(String
.format("No folder with ID %d in the database.",
selectedParent.get().getObjectId())));
} else {
final ContentSection section = sectionRepo
.findById(contentSectionViewState
.getSelectedContentSection()
.getObjectId())
.orElseThrow(() -> new UnexpectedErrorException(String
.format("No ContentSection with ID %d in the database.",
contentSectionViewState
.getSelectedContentSection()
.getObjectId())));
parent = section.getRootDocumentsFolder();
}
return (int) folderRepo.countSubFolders(parent);
}
@Override
public boolean hasChildren(final Folder item) {
return folderRepo.countSubFolders(item) > 0;
}
}

View File

@ -0,0 +1,204 @@
/*
* 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.ui;
import java.util.Date;
import java.util.Objects;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
public final class BrowseDocumentsItem implements
Comparable<BrowseDocumentsItem> {
private long itemId;
private String name;
private String title;
private String type;
private boolean folder;
private Date creationDate;
private Date lastModified;
public long getItemId() {
return itemId;
}
public void setItemId(final long itemId) {
this.itemId = itemId;
}
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 getType() {
return type;
}
public void setType(final String type) {
this.type = type;
}
public boolean isFolder() {
return folder;
}
public void setFolder(final boolean folder) {
this.folder = folder;
}
public Date getCreationDate() {
if (creationDate == null) {
return null;
} else {
return new Date(creationDate.getTime());
}
}
public void setCreationDate(final Date creationDate) {
if (creationDate != null) {
this.creationDate = new Date(creationDate.getTime());
}
}
public Date getLastModified() {
if (lastModified == null) {
return null;
} else {
return new Date(lastModified.getTime());
}
}
public void setLastModified(final Date lastModified) {
if (lastModified != null) {
this.lastModified = new Date(lastModified.getTime());
}
}
@Override
public int compareTo(final BrowseDocumentsItem other) {
int result = title.compareTo(other.getTitle());
if (result != 0) {
return result;
}
result = name.compareTo(other.getName());
if (result != 0) {
return result;
}
result = type.compareTo(other.getType());
if (result != 0) {
return result;
}
result = lastModified.compareTo(other.getLastModified());
if (result != 0) {
return result;
}
return creationDate.compareTo(other.getCreationDate());
}
@Override
public int hashCode() {
int hash = 3;
hash = 53 * hash + (int) (itemId ^ (itemId >>> 32));
hash = 53 * hash + Objects.hashCode(name);
hash = 53 * hash + Objects.hashCode(title);
hash = 53 * hash + Objects.hashCode(type);
hash = 53 * hash + (folder ? 1 : 0);
hash = 53 * hash + Objects.hashCode(creationDate);
hash = 53 * hash + Objects.hashCode(lastModified);
return hash;
}
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof BrowseDocumentsItem)) {
return false;
}
final BrowseDocumentsItem other = (BrowseDocumentsItem) obj;
if (itemId != other.getItemId()) {
return false;
}
if (folder != other.isFolder()) {
return false;
}
if (!Objects.equals(name, other.getName())) {
return false;
}
if (!Objects.equals(title, other.getTitle())) {
return false;
}
if (!Objects.equals(type, other.getType())) {
return false;
}
if (!Objects.equals(creationDate, other.getCreationDate())) {
return false;
}
return Objects.equals(lastModified, other.getLastModified());
}
@Override
public String toString() {
return String.format("%s{ "
+ "itemId = %d, "
+ "name = \"%s\", "
+ "title = \"%s\", "
+ "type = \"%s\", "
+ "creationDate = %s, "
+ "lastChanged = %s"
+ " }",
super.toString(),
itemId,
name,
title,
type,
Objects.toString(creationDate),
Objects.toString(lastModified));
}
}

View File

@ -21,9 +21,11 @@ package org.librecms.ui;
import com.vaadin.cdi.CDIView; import com.vaadin.cdi.CDIView;
import com.vaadin.navigator.View; import com.vaadin.navigator.View;
import com.vaadin.navigator.ViewChangeListener; import com.vaadin.navigator.ViewChangeListener;
import com.vaadin.ui.CustomComponent;
import com.vaadin.ui.Label; import com.vaadin.ui.Label;
import com.vaadin.ui.Panel; import com.vaadin.ui.Panel;
import com.vaadin.ui.TabSheet; import com.vaadin.ui.TabSheet;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.themes.ValoTheme; import com.vaadin.ui.themes.ValoTheme;
import org.librecms.contentsection.ContentSection; import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionRepository; import org.librecms.contentsection.ContentSectionRepository;
@ -38,7 +40,7 @@ import javax.inject.Inject;
*/ */
@CDIView(value = ContentSectionView.VIEWNAME, @CDIView(value = ContentSectionView.VIEWNAME,
uis = {CmsUI.class}) uis = {CmsUI.class})
class ContentSectionView implements View { class ContentSectionView extends CustomComponent implements View {
private static final long serialVersionUID = 602851260519364741L; private static final long serialVersionUID = 602851260519364741L;
@ -58,10 +60,26 @@ class ContentSectionView implements View {
this.controller = controller; this.controller = controller;
final BrowseDocuments browseDocuments = new BrowseDocuments(controller);
tabSheet = new TabSheet(); tabSheet = new TabSheet();
tabSheet.addTab(browseDocuments, "Documents");
tabSheet.addTab(new Label("Search placeholder"), "Search");
tabSheet.addTab(new Label("Media & Records placeholder"),
"Media & Records");
tabSheet.addTab(new Label("Roles placeholder"), "Roles");
tabSheet.addTab(new Label("Workflows Placeholder"), "Workflows");
tabSheet.addTab(new Label("Lifecycles placeholder"), "Lifecycles");
tabSheet.addTab(new Label("Document types placeholder"),
"Documents types");
noSectionPanel = new Panel(); noSectionPanel = new Panel();
noSectionPanel.setVisible(false); noSectionPanel.setVisible(false);
final VerticalLayout layout = new VerticalLayout(tabSheet,
noSectionPanel);
super.setCompositionRoot(layout);
} }
@Override @Override
@ -71,18 +89,21 @@ class ContentSectionView implements View {
if (parameters == null || parameters.trim().isEmpty()) { if (parameters == null || parameters.trim().isEmpty()) {
tabSheet.setVisible(false); tabSheet.setVisible(false);
noSectionPanel.setCaption("No content section selected"); noSectionPanel.setCaption("No content section selected");
noSectionPanel.setContent(new Label("No content section selected")); noSectionPanel.setContent(new Label("No content section selected"));
noSectionPanel.setVisible(true); noSectionPanel.setVisible(true);
} else { } else {
final ContentSectionRepository sectionRepo = controller final ContentSectionRepository sectionRepo = controller
.getSectionRepo(); .getSectionRepository();
final Optional<ContentSection> contentSection = sectionRepo final Optional<ContentSection> contentSection = sectionRepo
.findByLabel(parameters); .findByLabel(parameters);
if (contentSection.isPresent()) { if (contentSection.isPresent()) {
selectedSection = contentSection.get(); selectedSection = contentSection.get();
controller
.getContentSectionViewState()
.setSelectedContentSection(selectedSection);
} else { } else {
tabSheet.setVisible(false); tabSheet.setVisible(false);
noSectionPanel.setCaption(String noSectionPanel.setCaption(String

View File

@ -21,7 +21,10 @@ package org.librecms.ui;
import com.vaadin.cdi.ViewScoped; import com.vaadin.cdi.ViewScoped;
import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.l10n.GlobalizationHelper;
import org.libreccm.security.PermissionChecker; import org.libreccm.security.PermissionChecker;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionRepository; import org.librecms.contentsection.ContentSectionRepository;
import org.librecms.contentsection.FolderRepository;
import org.librecms.contenttypes.ContentTypesManager;
import javax.inject.Inject; import javax.inject.Inject;
@ -30,7 +33,19 @@ import javax.inject.Inject;
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
@ViewScoped @ViewScoped
class ContentSectionViewController { public class ContentSectionViewController {
@Inject
private BrowseDocumentsDataProvider browseDocumentsDataProvider;
@Inject
private BrowseDocumentsFolderTreeDataProvider folderTreeDataProvider;
@Inject
private ContentTypesManager contentTypesManager;
@Inject
private FolderRepository folderRepository;
@Inject @Inject
private GlobalizationHelper globalizationHelper; private GlobalizationHelper globalizationHelper;
@ -39,18 +54,43 @@ class ContentSectionViewController {
private PermissionChecker permissionChecker; private PermissionChecker permissionChecker;
@Inject @Inject
private ContentSectionRepository sectionRepo; private ContentSectionRepository sectionRepository;
@Inject
private ContentSectionViewState contentSectionViewState;
protected BrowseDocumentsDataProvider getBrowseDocumentsDataProvider() {
return browseDocumentsDataProvider;
}
public GlobalizationHelper getGlobalizationHelper() { protected BrowseDocumentsFolderTreeDataProvider getFolderTreeDataProvider() {
return folderTreeDataProvider;
}
protected ContentTypesManager getContentTypesManager() {
return contentTypesManager;
}
protected FolderRepository getFolderRepository() {
return folderRepository;
}
protected GlobalizationHelper getGlobalizationHelper() {
return globalizationHelper; return globalizationHelper;
} }
public PermissionChecker getPermissionChecker() { protected PermissionChecker getPermissionChecker() {
return permissionChecker; return permissionChecker;
} }
public ContentSectionRepository getSectionRepo() { protected ContentSectionRepository getSectionRepository() {
return sectionRepo; return sectionRepository;
} }
protected ContentSectionViewState getContentSectionViewState() {
return contentSectionViewState;
}
} }

View File

@ -0,0 +1,44 @@
/*
* 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.ui;
import com.vaadin.cdi.ViewScoped;
import org.librecms.contentsection.ContentSection;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
@ViewScoped
class ContentSectionViewState {
private ContentSection selectedContentSection;
protected ContentSection getSelectedContentSection() {
return selectedContentSection;
}
protected void setSelectedContentSection(
final ContentSection selectedContentSection) {
this.selectedContentSection = selectedContentSection;
}
}

View File

@ -444,3 +444,5 @@ cms.ui.authoring.assets.related_info_step.attachment.move\ \t=Move
cms.ui.authoring.assets.related_info_step.add_internal_link=Add internal link cms.ui.authoring.assets.related_info_step.add_internal_link=Add internal link
cms.ui.authoring.assets.related_info_step.internal_link.title=Title cms.ui.authoring.assets.related_info_step.internal_link.title=Title
cms.ui.authoring.assets.related_info_step.internal_link.target_item=Target cms.ui.authoring.assets.related_info_step.internal_link.target_item=Target
item_category_step.label=Assigned categories
related_info_step.description=Assign this item to categories

View File

@ -441,3 +441,5 @@ cms.ui.authoring.assets.related_info_step.attachment.move\ \t=Verschieben
cms.ui.authoring.assets.related_info_step.add_internal_link=Internen Link hinzuf\u00fcgen cms.ui.authoring.assets.related_info_step.add_internal_link=Internen Link hinzuf\u00fcgen
cms.ui.authoring.assets.related_info_step.internal_link.title=Titel cms.ui.authoring.assets.related_info_step.internal_link.title=Titel
cms.ui.authoring.assets.related_info_step.internal_link.target_item=Ziel cms.ui.authoring.assets.related_info_step.internal_link.target_item=Ziel
item_category_step.label=Zugewiesene Kategorien
related_info_step.description=Dieses Dokument Kategorien zuweisen

View File

@ -400,3 +400,5 @@ cms.ui.authoring.assets.related_info_step.attachment.move\ \t=Move
cms.ui.authoring.assets.related_info_step.add_internal_link=Add internal link cms.ui.authoring.assets.related_info_step.add_internal_link=Add internal link
cms.ui.authoring.assets.related_info_step.internal_link.title=Title cms.ui.authoring.assets.related_info_step.internal_link.title=Title
cms.ui.authoring.assets.related_info_step.internal_link.target_item=Target cms.ui.authoring.assets.related_info_step.internal_link.target_item=Target
item_category_step.label=Assigned categories
related_info_step.description=Assign this item to categories

View File

@ -0,0 +1,23 @@
<jsp:root xmlns:jsp="http://java.sun.com/JSP/Page"
xmlns:define="/WEB-INF/bebop-define.tld"
xmlns:show="/WEB-INF/bebop-show.tld"
version="1.2">
<define:page name="childCategories"
pageClass="com.arsdigita.cms.ui.authoring.EmptyPage"
title="childCategories"
cache="true">
<!-- Class had been moved from ccm-ldn-aplaws to ccm-ldn-terms in
order to avoid dependencies between modules, ccm-forum-categorised
and a specific kind of the integration module ccm-???-aplaws.
<define:component name="catSubtree"
classname="com.arsdigita.aplaws.ui.CategorySubtree"/>
-->
<define:component name="catSubtree"
classname="com.arsdigita.london.terms.ui.CategorySubtree"/>
</define:page>
<show:all/>
</jsp:root>

View File

@ -230,7 +230,7 @@
<plugin> <plugin>
<groupId>de.jpdigital</groupId> <groupId>de.jpdigital</groupId>
<artifactId>hibernate50-ddl-maven-plugin</artifactId> <artifactId>hibernate50-ddl-maven-plugin</artifactId>
<version>2.0.4</version> <version>2.1.0-SNAPSHOT</version>
</plugin> </plugin>
<plugin> <plugin>
<groupId>org.jacoco</groupId> <groupId>org.jacoco</groupId>