CCM NG/ccm-cms: Next part of AssetPane

git-svn-id: https://svn.libreccm.org/ccm/ccm_ng@4654 8810af33-2d31-482b-a856-94f89814c4df
jensp 2017-03-30 10:44:53 +00:00
parent a78ab32db6
commit d1743342a6
10 changed files with 592 additions and 121 deletions

View File

@ -18,18 +18,38 @@
*/ */
package com.arsdigita.cms.ui.assets; package com.arsdigita.cms.ui.assets;
import com.arsdigita.bebop.Component;
import com.arsdigita.bebop.ControlLink;
import com.arsdigita.bebop.Image;
import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Link;
import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Paginator; import com.arsdigita.bebop.Paginator;
import com.arsdigita.bebop.SimpleContainer;
import com.arsdigita.bebop.Table; import com.arsdigita.bebop.Table;
import com.arsdigita.bebop.Text;
import com.arsdigita.bebop.event.TableActionAdapter;
import com.arsdigita.bebop.event.TableActionEvent;
import com.arsdigita.bebop.event.TableActionListener; import com.arsdigita.bebop.event.TableActionListener;
import com.arsdigita.bebop.parameters.StringParameter; import com.arsdigita.bebop.parameters.StringParameter;
import com.arsdigita.bebop.table.DefaultTableCellRenderer;
import com.arsdigita.bebop.table.DefaultTableColumnModel; import com.arsdigita.bebop.table.DefaultTableColumnModel;
import com.arsdigita.bebop.table.TableCellRenderer;
import com.arsdigita.bebop.table.TableColumn; import com.arsdigita.bebop.table.TableColumn;
import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ui.folder.FolderBrowser;
import com.arsdigita.cms.ui.folder.FolderSelectionModel; import com.arsdigita.cms.ui.folder.FolderSelectionModel;
import com.arsdigita.globalization.GlobalizedMessage; import com.arsdigita.globalization.GlobalizedMessage;
import java.util.Date;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.libreccm.cdi.utils.CdiUtil;
import javafx.scene.control.Pagination;
import org.librecms.CmsConstants; import org.librecms.CmsConstants;
import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.ContentSectionManager;
import org.librecms.dispatcher.ItemResolver;
/** /**
* Browse folder and assets. * Browse folder and assets.
@ -48,13 +68,13 @@ public class AssetFolderBrowser extends Table {
private final FolderSelectionModel folderSelectionModel; private final FolderSelectionModel folderSelectionModel;
private TableActionListener folderChanger; private TableActionListener folderChanger;
private TableActionListener tableDeleter; private TableActionListener folderDeleter;
private TableColumn nameColumn; private TableColumn nameColumn;
private TableColumn deleteColumn; private TableColumn deleteColumn;
private final StringParameter sortTypeParameter = new StringParameter( private final StringParameter sortTypeParameter = new StringParameter(
"sortType"); "sortType");
private final StringParameter sortDirectionParameter = new StringParameter( private final StringParameter sortDirectionParameter = new StringParameter(
"sortDir"); "sortDir");
private Paginator paginator; private Paginator paginator;
private long folderSize; private long folderSize;
@ -69,22 +89,6 @@ public class AssetFolderBrowser extends Table {
initComponents(); initComponents();
} }
protected FolderSelectionModel getFolderSelectionModel() {
return folderSelectionModel;
}
protected Paginator getPaginator() {
return paginator;
}
protected String getSortType(final PageState state) {
return (String) state.getValue(sortTypeParameter);
}
protected String getSortDirection(final PageState state) {
return (String) state.getValue(sortDirectionParameter);
}
private void initComponents() { private void initComponents() {
setModelBuilder(new AssetFolderBrowserTableModelBuilder()); setModelBuilder(new AssetFolderBrowserTableModelBuilder());
@ -96,6 +100,71 @@ public class AssetFolderBrowser extends Table {
globalize("cms.ui.folder.creation_date"), globalize("cms.ui.folder.creation_date"),
globalize("cms.ui.folder.last_modified"), globalize("cms.ui.folder.last_modified"),
globalize("cms.ui.folder.action")}; globalize("cms.ui.folder.action")};
setModelBuilder(new AssetFolderBrowserTableModelBuilder());
setColumnModel(new DefaultTableColumnModel(headers));
setClassAttr("dataTable");
getHeader().setDefaultRenderer(new DefaultTableCellRenderer());
nameColumn = getColumn(AssetFolderBrowserTableModel.COL_NAME);
nameColumn.setCellRenderer(new NameCellRenderer());
nameColumn.setHeaderRenderer(new HeaderCellRenderer(SORT_KEY_NAME));
getColumn(AssetFolderBrowserTableModel.COL_CREATION_DATE)
.setHeaderRenderer(
new HeaderCellRenderer(SORT_KEY_CREATION_DATE));
getColumn(AssetFolderBrowserTableModel.COL_CREATION_DATE)
.setCellRenderer(new DateCellRenderer());
getColumn(AssetFolderBrowserTableModel.COL_LAST_MODIFIED)
.setHeaderRenderer(new HeaderCellRenderer(
SORT_KEY_LAST_MODIFIED_DATE));
getColumn(AssetFolderBrowserTableModel.COL_LAST_MODIFIED)
.setCellRenderer(new DateCellRenderer());
deleteColumn = getColumn(AssetFolderBrowserTableModel.COL_ACTION);
deleteColumn.setCellRenderer(new ActionCellRenderer());
deleteColumn.setAlign("center");
folderChanger = new FolderChanger();
addTableActionListener(folderChanger);
folderDeleter = new ItemDeleter();
addTableActionListener(folderDeleter);
setEmptyView(new Label(globalize("cms.ui.folder.no_assets")));
}
@Override
public void register(final Page page) {
super.register(page);
page.addComponentStateParam(this, folderSelectionModel.
getStateParameter());
page.addComponentStateParam(this, sortTypeParameter);
page.addComponentStateParam(this, sortDirectionParameter);
}
protected FolderSelectionModel getFolderSelectionModel() {
return folderSelectionModel;
}
protected Paginator getPaginator() {
return paginator;
}
protected void setPaginator(final Paginator paginator) {
this.paginator = paginator;
}
protected String getSortType(final PageState state) {
return (String) state.getValue(sortTypeParameter);
}
protected String getSortDirection(final PageState state) {
return (String) state.getValue(sortDirectionParameter);
} }
/** /**
@ -108,4 +177,233 @@ public class AssetFolderBrowser extends Table {
} }
private class HeaderCellRenderer extends DefaultTableCellRenderer {
private final String headerKey;
public HeaderCellRenderer(final String headerKey) {
super(true);
this.headerKey = headerKey;
}
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
final GlobalizedMessage headerName = (GlobalizedMessage) value;
final String sortKey = (String) state.getValue(sortTypeParameter);
final boolean isCurrentKey = sortKey.equals(key);
final String currentSortDirection = (String) state
.getValue(sortDirectionParameter);
final String imageUrlStub;
if (SORT_ACTION_UP.equals(currentSortDirection)) {
imageUrlStub = "gray-triangle-up.gif";
} else {
imageUrlStub = "gray-triangle-down.gif";
}
final ControlLink link = new ControlLink(new Label(headerName)) {
@Override
public void setControlEvent(final PageState state) {
String sortDirectionAction;
// by default, everything sorts "up" unless it
// is the current key and it is already pointing up
if (SORT_ACTION_UP.equals(currentSortDirection)
&& isCurrentKey) {
sortDirectionAction = SORT_ACTION_DOWN;
} else {
sortDirectionAction = SORT_ACTION_UP;
}
state.setControlEvent(table,
sortDirectionAction,
headerKey);
}
};
final Label label = new Label();
label.setLabel(headerName);
label.setClassAttr("folderBrowserLink");
label.setOutputEscaping(false);
label.setFontWeight(Label.BOLD);
final SimpleContainer container = new SimpleContainer();
container.add(label);
if (isCurrentKey) {
Image image = new Image("/assets/" + imageUrlStub);
image.setBorder("0");
container.add(image);
}
link.setChild(container);
return link;
}
}
/**
* Produce links to view an item or control links for folders to change into
* the folder.
*/
private class NameCellRenderer extends DefaultTableCellRenderer {
public NameCellRenderer() {
super(true);
}
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
final String name = (String) value;
final ContentSection section = CMS.getContext().
getContentSection();
final ContentSectionManager sectionManager = CdiUtil.
createCdiUtil()
.findBean(ContentSectionManager.class);
final boolean isFolder = ((AssetFolderBrowserTableModel) table
.getTableModel(state))
.isFolder();
final long objectId = getObjectId(key);
if (isFolder) {
//return new ControlLink(new Text(name));
return super.getComponent(table,
state,
value,
isSelected,
objectId,
row,
column);
} else {
// return new Link(new Text(name),
// itemResolver.generateItemURL(state,
// objectId,
// name,
// section,
// "DRAFT"));
return new Text(name);
}
}
}
private class DateCellRenderer implements TableCellRenderer {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
if (value instanceof Date) {
final Date date = (Date) value;
return new Text(String.format("%1$TF %1$TT", date));
} else if (value == null) {
return new Text("");
} else {
return new Text(value.toString());
}
}
}
/**
* Produce delete links for items and non-empty folders.
*/
private class ActionCellRenderer implements TableCellRenderer {
@Override
public Component getComponent(final Table table,
final PageState state,
final Object value,
final boolean isSelected,
final Object key,
final int row,
final int column) {
if (((Boolean) value)) {
return new Label(" ", false);
} else {
final ControlLink link = new ControlLink(
new Label(new GlobalizedMessage("cms.ui.folder.delete",
CmsConstants.CMS_BUNDLE)));
link.setConfirmation(
new GlobalizedMessage(
"cms.ui.folder.delete_confirmation",
CmsConstants.CMS_BUNDLE));
return link;
}
}
}
// Deletes an item
private class ItemDeleter extends TableActionAdapter {
@Override
public void cellSelected(final TableActionEvent event) {
int col = event.getColumn();
if (deleteColumn != getColumn(col)) {
return;
}
final PageState state = event.getPageState();
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final AssetFolderBrowserController controller = cdiUtil.findBean(
AssetFolderBrowserController.class);
controller.deleteObject((String) event.getRowKey());
((Table) event.getSource()).clearSelection(state);
}
}
private class FolderChanger extends TableActionAdapter {
@Override
public void cellSelected(final TableActionEvent event) {
final PageState state = event.getPageState();
final int col = event.getColumn();
if (nameColumn != getColumn(col)) {
return;
}
clearSelection(state);
getFolderSelectionModel().setSelectedKey(
state,
getObjectId(event.getRowKey()));
}
}
private long getObjectId(final Object key) {
final String keyStr = (String) key;
if (keyStr.startsWith("folder-")) {
return Long.parseLong(keyStr.substring("folder-".length()));
} else if (keyStr.startsWith("asset-")) {
return Long.parseLong(keyStr.substring("asset-".length()));
} else {
return Long.parseLong(keyStr);
}
}
} }

View File

@ -38,6 +38,7 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Locale; import java.util.Locale;
import java.util.Objects;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
@ -52,6 +53,9 @@ import javax.persistence.criteria.Order;
import javax.persistence.criteria.Path; import javax.persistence.criteria.Path;
import javax.persistence.criteria.Root; import javax.persistence.criteria.Root;
import javax.transaction.Transactional; import javax.transaction.Transactional;
import org.libreccm.core.CcmObject;
import org.librecms.contentsection.AssetRepository;
import org.librecms.contentsection.FolderRepository;
/** /**
* *
@ -72,6 +76,12 @@ public class AssetFolderBrowserController {
@Inject @Inject
private AssetTypesManager typesManager; private AssetTypesManager typesManager;
@Inject
private FolderRepository folderRepo;
@Inject
private AssetRepository assetRepo;
@Inject @Inject
private GlobalizationHelper globalizationHelper; private GlobalizationHelper globalizationHelper;
@ -86,7 +96,7 @@ public class AssetFolderBrowserController {
@PostConstruct @PostConstruct
private void init() { private void init() {
final KernelConfig kernelConfig = confManager.findConfiguration( final KernelConfig kernelConfig = confManager.findConfiguration(
KernelConfig.class); KernelConfig.class);
defaultLocale = kernelConfig.getDefaultLocale(); defaultLocale = kernelConfig.getDefaultLocale();
} }
@ -102,25 +112,25 @@ public class AssetFolderBrowserController {
firstResult, firstResult,
maxResults); maxResults);
final List<AssetFolderBrowserTableRow> subFolderRows = subFolders final List<AssetFolderBrowserTableRow> subFolderRows = subFolders
.stream() .stream()
.map(subFolder -> buildRow(subFolder)) .map(subFolder -> buildRow(subFolder))
.collect(Collectors.toList()); .collect(Collectors.toList());
if (subFolders.size() > maxResults) { if (subFolders.size() > maxResults) {
return subFolderRows; return subFolderRows;
} else { } else {
final int maxAssets = maxResults - subFolders.size(); final int maxAssets = maxResults - subFolders.size();
final int firstItem = firstResult - subFolders.size(); final int firstAsset = firstResult - subFolders.size();
final List<Asset> assets = findAssetsInFolder(folder, final List<Asset> assets = findAssetsInFolder(folder,
orderBy, orderBy,
orderDirection, orderDirection,
firstResult, firstAsset,
maxResults); maxAssets);
final List<AssetFolderBrowserTableRow> assetRows = assets final List<AssetFolderBrowserTableRow> assetRows = assets
.stream() .stream()
.map(asset -> buildRow(asset)) .map(asset -> buildRow(asset))
.collect(Collectors.toList()); .collect(Collectors.toList());
final List<AssetFolderBrowserTableRow> rows = new ArrayList<>(); final List<AssetFolderBrowserTableRow> rows = new ArrayList<>();
rows.addAll(subFolderRows); rows.addAll(subFolderRows);
@ -130,6 +140,76 @@ public class AssetFolderBrowserController {
} }
} }
@Transactional(Transactional.TxType.REQUIRED)
protected long countObjects(final Folder folder) {
Objects.requireNonNull(folder);
final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<Long> criteriaQuery = builder.createQuery(Long.class);
final Root<CcmObject> from = criteriaQuery.from(CcmObject.class);
criteriaQuery = criteriaQuery.select(builder.count(from));
final List<Folder> subFolders = findSubFolders(
folder,
AssetFolderBrowser.SORT_KEY_NAME,
AssetFolderBrowser.SORT_ACTION_UP,
-1,
-1);
final List<Asset> assets = findAssetsInFolder(
folder,
AssetFolderBrowser.SORT_KEY_NAME,
AssetFolderBrowser.SORT_ACTION_UP,
-1,
-1);
if (subFolders.isEmpty() && assets.isEmpty()) {
return 0;
} else if(subFolders.isEmpty() && !assets.isEmpty()) {
criteriaQuery = criteriaQuery.where(from.in(assets));
} else if (!subFolders.isEmpty() && assets.isEmpty()) {
criteriaQuery = criteriaQuery.where(from.in(subFolders));
} else {
criteriaQuery = criteriaQuery.where(builder.or(
from.in(subFolders),
from.in(assets)));
}
return entityManager.createQuery(criteriaQuery).getSingleResult();
}
/**
* Called by the {@link AssetFolderBrowser} to delete an object.
*
* @param objectId
*/
@Transactional(Transactional.TxType.REQUIRED)
protected void deleteObject(final String objectId) {
Objects.requireNonNull(objectId);
if (objectId.startsWith("folder-")) {
final long folderId = Long.parseLong(
objectId.substring("folder-".length()));
folderRepo
.findById(folderId)
.ifPresent(folderRepo::delete);
} else if (objectId.startsWith("asset-")) {
final long assetId = Long.parseLong(
objectId.substring("asset-".length()));
assetRepo
.findById(assetId)
.ifPresent(assetRepo::delete);
} else {
throw new IllegalArgumentException(
"The objectId is expected to start with 'folder-' or 'item.'.");
}
}
private AssetFolderBrowserTableRow buildRow(final Folder folder) { private AssetFolderBrowserTableRow buildRow(final Folder folder) {
final AssetFolderBrowserTableRow row = new AssetFolderBrowserTableRow(); final AssetFolderBrowserTableRow row = new AssetFolderBrowserTableRow();
@ -138,15 +218,15 @@ public class AssetFolderBrowserController {
row.setObjectUuid(folder.getUuid()); row.setObjectUuid(folder.getUuid());
row.setName(folder.getName()); row.setName(folder.getName());
if (folder.getTitle().hasValue(globalizationHelper if (folder.getTitle().hasValue(globalizationHelper
.getNegotiatedLocale())) { .getNegotiatedLocale())) {
row.setTitle(folder.getTitle().getValue(globalizationHelper row.setTitle(folder.getTitle().getValue(globalizationHelper
.getNegotiatedLocale())); .getNegotiatedLocale()));
} else { } else {
row.setTitle(folder.getTitle().getValue(defaultLocale)); row.setTitle(folder.getTitle().getValue(defaultLocale));
} }
row.setFolder(true); row.setFolder(true);
row.setDeletable(!categoryManager.hasSubCategories(folder) row.setDeletable(!categoryManager.hasSubCategories(folder)
&& !categoryManager.hasObjects(folder)); && !categoryManager.hasObjects(folder));
return row; return row;
} }
@ -159,14 +239,14 @@ public class AssetFolderBrowserController {
row.setObjectUuid(asset.getUuid()); row.setObjectUuid(asset.getUuid());
row.setName(asset.getDisplayName()); row.setName(asset.getDisplayName());
if (asset.getTitle().hasValue(globalizationHelper if (asset.getTitle().hasValue(globalizationHelper
.getNegotiatedLocale())) { .getNegotiatedLocale())) {
row.setTitle(asset.getTitle().getValue(globalizationHelper row.setTitle(asset.getTitle().getValue(globalizationHelper
.getNegotiatedLocale())); .getNegotiatedLocale()));
} else { } else {
row.setTitle(asset.getTitle().getValue(defaultLocale)); row.setTitle(asset.getTitle().getValue(defaultLocale));
} }
final AssetTypeInfo typeInfo = typesManager final AssetTypeInfo typeInfo = typesManager
.getAssetTypeInfo(asset.getClass()); .getAssetTypeInfo(asset.getClass());
row.setTypeLabelBundle(typeInfo.getLabelBundle()); row.setTypeLabelBundle(typeInfo.getLabelBundle());
row.setTypeLabelKey(typeInfo.getLabelKey()); row.setTypeLabelKey(typeInfo.getLabelKey());
@ -184,24 +264,26 @@ public class AssetFolderBrowserController {
final CriteriaBuilder builder = entityManager.getCriteriaBuilder(); final CriteriaBuilder builder = entityManager.getCriteriaBuilder();
final CriteriaQuery<Folder> criteria = builder final CriteriaQuery<Folder> criteria = builder
.createQuery(Folder.class); .createQuery(Folder.class);
final Root<Folder> from = criteria.from(Folder.class); final Root<Folder> from = criteria.from(Folder.class);
final Order order; final Order order;
if (AssetFolderBrowser.SORT_KEY_NAME.equals(orderBy) if (AssetFolderBrowser.SORT_KEY_NAME.equals(orderBy)
&& AssetFolderBrowser.SORT_ACTION_DOWN.equals(orderDirection)) { && AssetFolderBrowser.SORT_ACTION_DOWN.
equals(orderDirection)) {
order = builder.desc(from.get("name")); order = builder.desc(from.get("name"));
} else { } else {
order = builder.asc(from.get("name")); order = builder.asc(from.get("name"));
} }
final TypedQuery<Folder> query = entityManager final TypedQuery<Folder> query = entityManager
.createQuery( .createQuery(
criteria.where( criteria.where(
builder.equal(from.get("parentCategory"), folder) builder.
) equal(from.get("parentCategory"), folder)
.orderBy(order) )
); .orderBy(order)
);
if (firstResult >= 0) { if (firstResult >= 0) {
query.setFirstResult(firstResult); query.setFirstResult(firstResult);
@ -250,17 +332,18 @@ public class AssetFolderBrowserController {
} }
final TypedQuery<Asset> query = entityManager final TypedQuery<Asset> query = entityManager
.createQuery( .createQuery(
criteria.select(fromAsset) criteria.select(fromAsset)
.where( .where(
builder.and( builder.and(
builder.equal(join.get("category"), folder), builder.equal(join.get(
builder.equal(join.get("type"), "category"), folder),
CmsConstants.CATEGORIZATION_TYPE_FOLDER) builder.equal(join.get("type"),
) CmsConstants.CATEGORIZATION_TYPE_FOLDER)
) )
.orderBy(order) )
); .orderBy(order)
);
if (firstResult >= 0) { if (firstResult >= 0) {
query.setFirstResult(firstResult); query.setFirstResult(firstResult);

View File

@ -0,0 +1,65 @@
/*
* 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 com.arsdigita.cms.ui.assets;
import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.PaginationModelBuilder;
import com.arsdigita.bebop.Paginator;
import com.arsdigita.cms.ui.folder.FolderSelectionModel;
import org.libreccm.cdi.utils.CdiUtil;
import org.librecms.contentsection.Folder;
/**
*
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/
class AssetFolderBrowserPaginationModelBuilder implements PaginationModelBuilder {
private final AssetFolderBrowser folderBrowser;
public AssetFolderBrowserPaginationModelBuilder(
final AssetFolderBrowser folderBrowser) {
this.folderBrowser = folderBrowser;
}
@Override
public int getTotalSize(final Paginator paginator, final PageState state) {
final FolderSelectionModel folderSelectionModel = folderBrowser
.getFolderSelectionModel();
final Folder folder = folderSelectionModel.getSelectedObject(state);
if (folder == null) {
return 0;
} else {
final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final AssetFolderBrowserController controller = cdiUtil.findBean(
AssetFolderBrowserController.class);
return (int) controller.countObjects(folder);
}
}
@Override
public boolean isVisible(final PageState state) {
return folderBrowser != null && folderBrowser.isVisible(state);
}
}

View File

@ -30,14 +30,15 @@ import java.util.List;
* *
* @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a> * @author <a href="mailto:jens.pelzetter@googlemail.com">Jens Pelzetter</a>
*/ */
public class AssetFolderBrowserTableModel implements TableModel { class AssetFolderBrowserTableModel implements TableModel {
private static final int COL_NAME = 0; protected static final int COL_NAME = 0;
private static final int COL_TITLE = 1; protected static final int COL_TITLE = 1;
private static final int COL_TYPE = 2; protected static final int COL_TYPE = 2;
private static final int COL_CREATION_DATE = 3; protected static final int COL_CREATION_DATE = 3;
private static final int COL_LAST_MODIFIED = 4; protected static final int COL_LAST_MODIFIED = 4;
private static final int COL_DELETEABLE = 5; protected static final int COL_DELETEABLE = 5;
protected static final int COL_ACTION = 6;
private final Iterator<AssetFolderBrowserTableRow> iterator; private final Iterator<AssetFolderBrowserTableRow> iterator;
private AssetFolderBrowserTableRow currentRow; private AssetFolderBrowserTableRow currentRow;

View File

@ -23,6 +23,7 @@ import com.arsdigita.bebop.FormProcessException;
import com.arsdigita.bebop.Label; import com.arsdigita.bebop.Label;
import com.arsdigita.bebop.Page; import com.arsdigita.bebop.Page;
import com.arsdigita.bebop.PageState; import com.arsdigita.bebop.PageState;
import com.arsdigita.bebop.Paginator;
import com.arsdigita.bebop.Resettable; import com.arsdigita.bebop.Resettable;
import com.arsdigita.bebop.SegmentedPanel; import com.arsdigita.bebop.SegmentedPanel;
import com.arsdigita.bebop.SimpleContainer; import com.arsdigita.bebop.SimpleContainer;
@ -37,7 +38,6 @@ import com.arsdigita.bebop.event.PrintEvent;
import com.arsdigita.bebop.event.PrintListener; import com.arsdigita.bebop.event.PrintListener;
import com.arsdigita.cms.CMS; import com.arsdigita.cms.CMS;
import com.arsdigita.cms.ui.BaseTree; import com.arsdigita.cms.ui.BaseTree;
import com.arsdigita.cms.ui.folder.FolderBrowser;
import com.arsdigita.cms.ui.folder.FolderCreateForm; import com.arsdigita.cms.ui.folder.FolderCreateForm;
import com.arsdigita.cms.ui.folder.FolderEditorForm; import com.arsdigita.cms.ui.folder.FolderEditorForm;
import com.arsdigita.cms.ui.folder.FolderRequestLocal; import com.arsdigita.cms.ui.folder.FolderRequestLocal;
@ -55,6 +55,7 @@ import org.librecms.contentsection.ContentSection;
import org.librecms.contentsection.Folder; import org.librecms.contentsection.Folder;
import java.util.List; import java.util.List;
import org.arsdigita.cms.CMSConfig;
/** /**
* *
@ -69,8 +70,11 @@ public class AssetPane extends LayoutPanel implements Resettable {
private final FolderSelectionModel folderSelectionModel; private final FolderSelectionModel folderSelectionModel;
private final FolderRequestLocal folderRequestLocal; private final FolderRequestLocal folderRequestLocal;
private SegmentedPanel.Segment currentFolderSegment; private AssetFolderBrowser folderBrowser;
private SegmentedPanel.Segment browseSegment; private SegmentedPanel.Segment browseSegment;
private SegmentedPanel.Segment currentFolderSegment;
private SegmentedPanel.Segment actionsSegment;
private SegmentedPanel.Segment newFolderSegment; private SegmentedPanel.Segment newFolderSegment;
private SegmentedPanel.Segment editFolderSegment; private SegmentedPanel.Segment editFolderSegment;
@ -81,8 +85,8 @@ public class AssetPane extends LayoutPanel implements Resettable {
@Override @Override
protected Folder getRootFolder(final PageState state) { protected Folder getRootFolder(final PageState state) {
final ContentSection section = CMS final ContentSection section = CMS
.getContext() .getContext()
.getContentSection(); .getContentSection();
return section.getRootAssetsFolder(); return section.getRootAssetsFolder();
} }
@ -93,8 +97,8 @@ public class AssetPane extends LayoutPanel implements Resettable {
@Override @Override
protected Long getRootFolderID(final PageState state) { protected Long getRootFolderID(final PageState state) {
final ContentSection section = CMS final ContentSection section = CMS
.getContext() .getContext()
.getContentSection(); .getContentSection();
return section.getRootAssetsFolder().getObjectId(); return section.getRootAssetsFolder().getObjectId();
} }
@ -105,8 +109,8 @@ public class AssetPane extends LayoutPanel implements Resettable {
setLeft(left); setLeft(left);
final Label heading = new Label( final Label heading = new Label(
new GlobalizedMessage("cms.ui.folder_browser", new GlobalizedMessage("cms.ui.folder_browser",
CmsConstants.CMS_BUNDLE)); CmsConstants.CMS_BUNDLE));
left.addSegment(heading, tree); left.addSegment(heading, tree);
// final Text placeholder = new Text("Placeholder"); // final Text placeholder = new Text("Placeholder");
@ -118,6 +122,15 @@ public class AssetPane extends LayoutPanel implements Resettable {
final SegmentedPanel panel = new SegmentedPanel(); final SegmentedPanel panel = new SegmentedPanel();
browseSegment = panel.addSegment();
folderBrowser = new AssetFolderBrowser(folderSelectionModel);
final Paginator paginator = new Paginator(
new AssetFolderBrowserPaginationModelBuilder(folderBrowser),
CMSConfig.getConfig().getFolderBrowseListSize());
folderBrowser.setPaginator(paginator);
browseSegment.add(paginator);
browseSegment.add(folderBrowser);
currentFolderSegment = panel.addSegment(); currentFolderSegment = panel.addSegment();
currentFolderSegment.addHeader(new Text("Current folder")); currentFolderSegment.addHeader(new Text("Current folder"));
final Label currentFolderLabel = new Label(); final Label currentFolderLabel = new Label();
@ -129,39 +142,38 @@ public class AssetPane extends LayoutPanel implements Resettable {
final Label target = (Label) event.getTarget(); final Label target = (Label) event.getTarget();
final long selectedId = Long.parseLong(selectionModel final long selectedId = Long.parseLong(selectionModel
.getSelectedKey(state).toString()); .getSelectedKey(state).toString());
final long currentFolderId = folderSelectionModel final long currentFolderId = folderSelectionModel
.getSelectedObject(state).getObjectId(); .getSelectedObject(state).getObjectId();
target.setLabel(String.format( target.setLabel(String.format(
"selectedId = %d; currentFolderId = %d", "selectedId = %d; currentFolderId = %d",
selectedId, selectedId,
currentFolderId)); currentFolderId));
} }
}); });
currentFolderSegment.add(currentFolderLabel); currentFolderSegment.add(currentFolderLabel);
browseSegment = panel.addSegment(); actionsSegment = panel.addSegment();
browseSegment.setIdAttr("folder-browse"); actionsSegment.setIdAttr("folder-browse");
final ActionGroup actions = new ActionGroup(); final ActionGroup actions = new ActionGroup();
browseSegment.add(actions); actionsSegment.add(actions);
final FolderCreateForm folderCreateForm = new FolderCreateForm( final FolderCreateForm folderCreateForm = new FolderCreateForm(
"fcreat", folderSelectionModel); "fcreat", folderSelectionModel);
folderCreateForm.addSubmissionListener(new FormSubmissionListener() { folderCreateForm.addSubmissionListener(new FormSubmissionListener() {
@Override @Override
public void submitted(final FormSectionEvent event) public void submitted(final FormSectionEvent event)
throws FormProcessException { throws FormProcessException {
final PageState state = event.getPageState(); final PageState state = event.getPageState();
if (event.getSource() == folderCreateForm if (event.getSource() == folderCreateForm
&& folderCreateForm.isCancelled(state)) { && folderCreateForm.isCancelled(state)) {
browseMode(state); browseMode(state);
throw new FormProcessException(new GlobalizedMessage( throw new FormProcessException(new GlobalizedMessage(
"cms.ui.cancelled", CmsConstants.CMS_BUNDLE)); "cms.ui.cancelled", CmsConstants.CMS_BUNDLE));
} }
} }
@ -171,7 +183,7 @@ public class AssetPane extends LayoutPanel implements Resettable {
@Override @Override
public void process(final FormSectionEvent event) public void process(final FormSectionEvent event)
throws FormProcessException { throws FormProcessException {
final PageState state = event.getPageState(); final PageState state = event.getPageState();
final Object source = event.getSource(); final Object source = event.getSource();
@ -182,24 +194,24 @@ public class AssetPane extends LayoutPanel implements Resettable {
}); });
newFolderSegment = panel.addSegment( newFolderSegment = panel.addSegment(
new Label(new GlobalizedMessage("cms.ui.new_folder", new Label(new GlobalizedMessage("cms.ui.new_folder",
CmsConstants.CMS_BUNDLE)), CmsConstants.CMS_BUNDLE)),
folderCreateForm); folderCreateForm);
final FolderEditorForm folderEditorForm = new FolderEditorForm( final FolderEditorForm folderEditorForm = new FolderEditorForm(
"fedit", folderSelectionModel); "fedit", folderSelectionModel);
folderEditorForm.addSubmissionListener(new FormSubmissionListener() { folderEditorForm.addSubmissionListener(new FormSubmissionListener() {
@Override @Override
public void submitted(final FormSectionEvent event) public void submitted(final FormSectionEvent event)
throws FormProcessException { throws FormProcessException {
final PageState state = event.getPageState(); final PageState state = event.getPageState();
if (event.getSource() == folderEditorForm if (event.getSource() == folderEditorForm
&& folderEditorForm.isCancelled(state)) { && folderEditorForm.isCancelled(state)) {
browseMode(state); browseMode(state);
throw new FormProcessException(new GlobalizedMessage( throw new FormProcessException(new GlobalizedMessage(
"cms.ui.cancelled", CmsConstants.CMS_BUNDLE)); "cms.ui.cancelled", CmsConstants.CMS_BUNDLE));
} }
} }
@ -208,7 +220,7 @@ public class AssetPane extends LayoutPanel implements Resettable {
@Override @Override
public void process(final FormSectionEvent event) public void process(final FormSectionEvent event)
throws FormProcessException { throws FormProcessException {
final PageState state = event.getPageState(); final PageState state = event.getPageState();
final Object source = event.getSource(); final Object source = event.getSource();
@ -219,13 +231,13 @@ public class AssetPane extends LayoutPanel implements Resettable {
}); });
editFolderSegment = panel.addSegment( editFolderSegment = panel.addSegment(
new Label(new GlobalizedMessage("cms.ui.edit_folder", new Label(new GlobalizedMessage("cms.ui.edit_folder",
CmsConstants.CMS_BUNDLE)), CmsConstants.CMS_BUNDLE)),
folderEditorForm); folderEditorForm);
final ActionLink createFolderAction = new ActionLink( final ActionLink createFolderAction = new ActionLink(
new Label(new GlobalizedMessage("cms.ui.new_folder", new Label(new GlobalizedMessage("cms.ui.new_folder",
CmsConstants.CMS_BUNDLE))); CmsConstants.CMS_BUNDLE)));
createFolderAction.addActionListener(new ActionListener() { createFolderAction.addActionListener(new ActionListener() {
@Override @Override
@ -241,8 +253,8 @@ public class AssetPane extends LayoutPanel implements Resettable {
actions.addAction(createFolderAction); actions.addAction(createFolderAction);
final ActionLink editFolderAction = new ActionLink( final ActionLink editFolderAction = new ActionLink(
new Label(new GlobalizedMessage("cms.ui.edit_folder", new Label(new GlobalizedMessage("cms.ui.edit_folder",
CmsConstants.CMS_BUNDLE))); CmsConstants.CMS_BUNDLE)));
editFolderAction.addActionListener(new ActionListener() { editFolderAction.addActionListener(new ActionListener() {
@Override @Override
@ -262,6 +274,7 @@ public class AssetPane extends LayoutPanel implements Resettable {
protected void browseMode(final PageState state) { protected void browseMode(final PageState state) {
browseSegment.setVisible(state, true); browseSegment.setVisible(state, true);
actionsSegment.setVisible(state, true);
newFolderSegment.setVisible(state, false); newFolderSegment.setVisible(state, false);
editFolderSegment.setVisible(state, false); editFolderSegment.setVisible(state, false);
@ -269,12 +282,14 @@ public class AssetPane extends LayoutPanel implements Resettable {
protected void newFolderMode(final PageState state) { protected void newFolderMode(final PageState state) {
browseSegment.setVisible(state, false); browseSegment.setVisible(state, false);
actionsSegment.setVisible(state, false);
newFolderSegment.setVisible(state, true); newFolderSegment.setVisible(state, true);
editFolderSegment.setVisible(state, false); editFolderSegment.setVisible(state, false);
} }
protected void editFolderMode(final PageState state) { protected void editFolderMode(final PageState state) {
browseSegment.setVisible(state, false); browseSegment.setVisible(state, false);
actionsSegment.setVisible(state, false);
newFolderSegment.setVisible(state, false); newFolderSegment.setVisible(state, false);
editFolderSegment.setVisible(state, true); editFolderSegment.setVisible(state, true);
} }
@ -288,6 +303,7 @@ public class AssetPane extends LayoutPanel implements Resettable {
page.addActionListener(new FolderListener()); page.addActionListener(new FolderListener());
page.setVisibleDefault(browseSegment, true); page.setVisibleDefault(browseSegment, true);
page.setVisibleDefault(actionsSegment, true);
page.setVisibleDefault(newFolderSegment, false); page.setVisibleDefault(newFolderSegment, false);
page.setVisibleDefault(editFolderSegment, false); page.setVisibleDefault(editFolderSegment, false);
} }
@ -297,6 +313,8 @@ public class AssetPane extends LayoutPanel implements Resettable {
super.reset(state); super.reset(state);
folderBrowser.getPaginator().reset(state);
} }
private final class FolderListener implements ActionListener { private final class FolderListener implements ActionListener {
@ -309,14 +327,14 @@ public class AssetPane extends LayoutPanel implements Resettable {
if (!selectionModel.isSelected(state)) { if (!selectionModel.isSelected(state)) {
final String folder = state final String folder = state
.getRequest() .getRequest()
.getParameter(SET_FOLDER); .getParameter(SET_FOLDER);
if (folder == null) { if (folder == null) {
final Category root = CMS final Category root = CMS
.getContext() .getContext()
.getContentSection() .getContentSection()
.getRootAssetsFolder(); .getRootAssetsFolder();
final Long folderId = root.getObjectId(); final Long folderId = root.getObjectId();
selectionModel.setSelectedKey(state, folderId); selectionModel.setSelectedKey(state, folderId);
@ -336,18 +354,18 @@ public class AssetPane extends LayoutPanel implements Resettable {
final PageState state = event.getPageState(); final PageState state = event.getPageState();
final Category root = CMS final Category root = CMS
.getContext() .getContext()
.getContentSection() .getContentSection()
.getRootAssetsFolder(); .getRootAssetsFolder();
if (!root.equals(folderRequestLocal.getFolder(state))) { if (!root.equals(folderRequestLocal.getFolder(state))) {
// Expand the ancestor nodes of the currently // Expand the ancestor nodes of the currently
// selected node. // selected node.
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final FolderTreeModelController controller = cdiUtil.findBean( final FolderTreeModelController controller = cdiUtil.findBean(
FolderTreeModelController.class); FolderTreeModelController.class);
final List<Long> ancestorIds = controller.findAncestorIds( final List<Long> ancestorIds = controller.findAncestorIds(
folderRequestLocal.getFolder(state)); folderRequestLocal.getFolder(state));
ancestorIds.forEach(id -> tree.expand(id.toString(), state)); ancestorIds.forEach(id -> tree.expand(id.toString(), state));
} }

View File

@ -38,10 +38,10 @@ class FolderBrowserPaginationModelBuilder implements PaginationModelBuilder {
} }
@Override @Override
public int getTotalSize(final Paginator paginator, public int getTotalSize(final Paginator paginator, final PageState state) {
final PageState state) {
final FolderSelectionModel folderSelectionModel = folderBrowser final FolderSelectionModel folderSelectionModel = folderBrowser
.getFolderSelectionModel(); .getFolderSelectionModel();
final Folder folder = folderSelectionModel.getSelectedObject(state); final Folder folder = folderSelectionModel.getSelectedObject(state);
if (folder == null) { if (folder == null) {
return 0; return 0;
@ -49,7 +49,7 @@ class FolderBrowserPaginationModelBuilder implements PaginationModelBuilder {
folderBrowser.getRowSelectionModel().clearSelection(state); folderBrowser.getRowSelectionModel().clearSelection(state);
final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); final CdiUtil cdiUtil = CdiUtil.createCdiUtil();
final FolderBrowserController controller = cdiUtil.findBean( final FolderBrowserController controller = cdiUtil.findBean(
FolderBrowserController.class); FolderBrowserController.class);
final String filter = folderBrowser.getFilter(state); final String filter = folderBrowser.getFilter(state);
final String atozFilter = folderBrowser.getAtoZfilter(state); final String atozFilter = folderBrowser.getAtoZfilter(state);
final int first = paginator.getFirst(state); final int first = paginator.getFirst(state);

View File

@ -245,3 +245,4 @@ cms.ui.type.workflow.select=Select default workflow
cms.ui.type.select=Select Content Type cms.ui.type.select=Select Content Type
cms.ui.type.select.none=There are no available content types to select cms.ui.type.select.none=There are no available content types to select
cms.ui.assets=Assets cms.ui.assets=Assets
cms.ui.folder.no_assets=No assets

View File

@ -244,3 +244,4 @@ cms.ui.type.workflow.select=Voreingestellten Arbeitsablauf ausw\u00e4hlen
cms.ui.type.select=Dolkumententype ausw\u00e4hlen cms.ui.type.select=Dolkumententype ausw\u00e4hlen
cms.ui.type.select.none=Keine verf\u00fcgbaren Dokumententypen cms.ui.type.select.none=Keine verf\u00fcgbaren Dokumententypen
cms.ui.assets=Medien & Daten cms.ui.assets=Medien & Daten
cms.ui.folder.no_assets=Keine Medien oder Datens\u00e4tze vorhanden

View File

@ -203,3 +203,4 @@ cms.ui.type.workflow.select=Select default workflow
cms.ui.type.select=Select Content Type cms.ui.type.select=Select Content Type
cms.ui.type.select.none=There are no available content types to select cms.ui.type.select.none=There are no available content types to select
cms.ui.assets=Assets cms.ui.assets=Assets
cms.ui.folder.no_assets=No assets

View File

@ -52,7 +52,7 @@ import com.arsdigita.util.Assert;
* *
*/ */
public class ParameterSingleSelectionModel<T> public class ParameterSingleSelectionModel<T>
extends AbstractSingleSelectionModel<T> { extends AbstractSingleSelectionModel<T> {
private final ParameterModel m_parameter; private final ParameterModel m_parameter;
@ -60,7 +60,7 @@ public class ParameterSingleSelectionModel<T>
* Constructs a new ParameterSingleSelectionModel. * Constructs a new ParameterSingleSelectionModel.
* *
* @param m the parameter model that will be used to keep track of the * @param m the parameter model that will be used to keep track of the
* currently selected key * currently selected key
*/ */
public ParameterSingleSelectionModel(ParameterModel m) { public ParameterSingleSelectionModel(ParameterModel m) {
super(); super();
@ -94,7 +94,7 @@ public class ParameterSingleSelectionModel<T>
/** /**
* Set the selected key. * Set the selected key.
* *
* @param state represents the state of the current request * @param state represents the state of the current request
* @param newKey the new selected key * @param newKey the new selected key
*/ */
@Override @Override
@ -103,7 +103,10 @@ public class ParameterSingleSelectionModel<T>
if (Assert.isEnabled()) { if (Assert.isEnabled()) {
final FormModel model = state.getPage().getStateModel(); final FormModel model = state.getPage().getStateModel();
Assert.isTrue(model.containsFormParam(m_parameter)); Assert.isTrue(model.containsFormParam(m_parameter),
String.format(
"Parameter %s is not part of the FormModel.",
m_parameter.getName()));
} }
state.setValue(m_parameter, newKey); state.setValue(m_parameter, newKey);