diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/ImageStep.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/ImageStep.java deleted file mode 100644 index 87479f3e6..000000000 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/ImageStep.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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.authoring.assets; - -import com.arsdigita.bebop.Text; -import com.arsdigita.bebop.parameters.StringParameter; -import com.arsdigita.cms.ItemSelectionModel; -import com.arsdigita.cms.ui.authoring.AuthoringKitWizard; -import com.arsdigita.cms.ui.authoring.ResettableContainer; - -import org.librecms.CmsConstants; -import org.librecms.ui.authoring.ContentItemAuthoringStep; - -/** - * - * @author Jens Pelzetter - */ -@ContentItemAuthoringStep( - labelBundle = CmsConstants.CMS_BUNDLE, - labelKey = "image_step.label", - descriptionBundle = CmsConstants.CMS_BUNDLE, - descriptionKey = "image_step.description") -public class ImageStep extends ResettableContainer { - - public ImageStep(final ItemSelectionModel itemSelectionModel, - final AuthoringKitWizard authoringKitWizard, - final StringParameter selectedLanguage) { - - super(); - - super.add(new Text("Image Step placeholder")); - } - -} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/ItemAttachmentSelectionModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/ItemAttachmentSelectionModel.java new file mode 100644 index 000000000..6ce4cfef7 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/ItemAttachmentSelectionModel.java @@ -0,0 +1,100 @@ +/* + * 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.authoring.assets; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.parameters.LongParameter; +import com.arsdigita.bebop.parameters.ParameterModel; + +import org.libreccm.cdi.utils.CdiUtil; +import org.librecms.contentsection.ItemAttachment; +import org.librecms.contentsection.ItemAttachmentManager; + +/** + * + * @author Jens Pelzetter + */ +public class ItemAttachmentSelectionModel implements SingleSelectionModel{ + + private final SingleSelectionModel model; + + public ItemAttachmentSelectionModel(final LongParameter parameter) { + this.model = new ParameterSingleSelectionModel<>(parameter); + } + + public ItemAttachmentSelectionModel(final String parameterName) { + this(new LongParameter(parameterName)); + } + + @Override + public boolean isSelected(final PageState state) { + return model.isSelected(state); + } + + @Override + public Long getSelectedKey(final PageState state) { + final Object key = model.getSelectedKey(state); + if (key == null) { + return null; + } else if (key instanceof Long) { + return (Long) key; + } else if (key instanceof String) { + return Long.parseLong((String) key); + } else { + return Long.parseLong(key.toString()); + } + } + + @Override + public void setSelectedKey(final PageState state, final Long key) { + model.setSelectedKey(state, key); + } + + public ItemAttachment getSelectedAttachment(final PageState state) { + final Long key = getSelectedKey(state); + final ItemAttachmentManager manager = CdiUtil + .createCdiUtil() + .findBean(ItemAttachmentManager.class); + return manager.findById(key).get(); + } + + @Override + public void clearSelection(final PageState state) { + model.clearSelection(state); + } + + @Override + public void addChangeListener(final ChangeListener changeListener) { + model.addChangeListener(changeListener); + } + + @Override + public void removeChangeListener(final ChangeListener changeListener) { + model.removeChangeListener(changeListener); + } + + @Override + public ParameterModel getStateParameter() { + return model.getStateParameter(); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImageTableRow.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImageTableRow.java new file mode 100644 index 000000000..1ec8e477b --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImageTableRow.java @@ -0,0 +1,94 @@ +/* + * 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.authoring.assets.images; + +/** + * A container for the data shown in the table of assigned images. + * + * @author Jens Pelzetter + */ +class AssignedImageTableRow { + + private long attachmentId; + private String imageUuid; + private String filename; + private long width; + private long height; + private String type; + private String caption; + + public long getAttachmentId() { + return attachmentId; + } + + public void setAttachmentId(final long attachmentId) { + this.attachmentId = attachmentId; + } + + public String getImageUuid() { + return imageUuid; + } + + public void setImageUuid(final String imageUuid) { + this.imageUuid = imageUuid; + } + + public String getFilename() { + return filename; + } + + public void setFilename(final String filename) { + this.filename = filename; + } + + public long getWidth() { + return width; + } + + public void setWidth(final long width) { + this.width = width; + } + + public long getHeight() { + return height; + } + + public void setHeight(final long height) { + this.height = height; + } + + public String getType() { + return type; + } + + public void setType(final String type) { + this.type = type; + } + + public String getCaption() { + return caption; + } + + public void setCaption(final String caption) { + this.caption = caption; + } + + + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImagesTable.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImagesTable.java new file mode 100644 index 000000000..6a179b11d --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImagesTable.java @@ -0,0 +1,255 @@ +/* + * 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.authoring.assets.images; + +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Image; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.Text; +import com.arsdigita.bebop.event.TableActionEvent; +import com.arsdigita.bebop.event.TableActionListener; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableColumn; +import com.arsdigita.bebop.table.TableColumnModel; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.ui.authoring.assets.ItemAttachmentSelectionModel; +import com.arsdigita.globalization.GlobalizedMessage; + +import org.libreccm.cdi.utils.CdiUtil; +import org.librecms.CmsConstants; +import org.librecms.contentsection.ItemAttachment; + +/** + * + * @author Jens Pelzetter + */ +class AssignedImagesTable extends Table { + + protected static final int COL_PREVIEW = 0; + protected static final int COL_IMAGE_DATA = 1; + protected static final int COL_CAPTION = 2; + protected static final int COL_MOVE = 3; + protected static final int COL_REMOVE = 4; + + private final ItemSelectionModel itemSelectionModel; + private final ItemAttachmentSelectionModel moveAttachmentModel; + private final StringParameter selectedLanguageParam; + + public AssignedImagesTable( + final ItemSelectionModel itemSelectionModel, + final ItemAttachmentSelectionModel moveAttachmentModel, + final StringParameter selectedLanguageParam) { + + super(); + this.itemSelectionModel = itemSelectionModel; + this.moveAttachmentModel = moveAttachmentModel; + this.selectedLanguageParam = selectedLanguageParam; + + final TableColumnModel columnModel = super.getColumnModel(); + columnModel.add(new TableColumn( + COL_PREVIEW, + new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.preview_header", + CmsConstants.CMS_BUNDLE)))); + columnModel.add(new TableColumn( + COL_IMAGE_DATA, + new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.properties_header", + CmsConstants.CMS_BUNDLE)))); + columnModel.add(new TableColumn( + COL_IMAGE_DATA, + new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.caption_header", + CmsConstants.CMS_BUNDLE)))); + columnModel.add(new TableColumn( + COL_MOVE, + new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.move_header", + CmsConstants.CMS_BUNDLE)))); + columnModel.add(new TableColumn( + COL_IMAGE_DATA, + new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.remove_header", + CmsConstants.CMS_BUNDLE)))); + + super + .setModelBuilder(new AssignedImagesTableModelBuilder( + itemSelectionModel, + moveAttachmentModel, + selectedLanguageParam)); + + super + .getColumn(COL_PREVIEW) + .setCellRenderer(new ThumbnailCellRenderer()); + super + .getColumn(COL_IMAGE_DATA) + .setCellRenderer(new PropertiesCellRenderer()); + super + .getColumn(COL_MOVE) + .setCellRenderer(new MoveCellRenderer()); + super + .getColumn(COL_REMOVE) + .setCellRenderer(new RemoveCellRenderer()); + + super.addTableActionListener(new TableActionListener() { + + @Override + public void cellSelected(final TableActionEvent event) + throws FormProcessException { + + final PageState state = event.getPageState(); + + final TableColumn column = getColumnModel() + .get(event.getColumn()); + + switch (column.getModelIndex()) { + case COL_MOVE: + if (moveAttachmentModel + .getSelectedAttachment(state) == null) { + + moveAttachmentModel + .setSelectedKey(state, + Long.parseLong(column.getKey())); + } else { + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ImageStepController controller = cdiUtil + .findBean(ImageStepController.class); + + final ItemAttachment selectedAttachment + = moveAttachmentModel + .getSelectedAttachment(state); + + final Long destId = Long + .parseLong((String) event.getRowKey()); + + controller.moveAfter(selectedAttachment, destId); + + } + break; + case COL_REMOVE: + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ImageStepController controller = cdiUtil + .findBean(ImageStepController.class); + controller.deleteAttachment(moveAttachmentModel + .getSelectedAttachment(state)); + break; + } + } + + @Override + public void headSelected(final TableActionEvent event) { + //Nothing + } + + }); + + } + + private class ThumbnailCellRenderer 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 == null) { + return new Text(""); + } else { + final Image image = new Image((String) value, ""); + return image; + } + } + + } + + private class PropertiesCellRenderer 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) { + + @SuppressWarnings("unchecked") + final ImageProperties properties = (ImageProperties) value; + final BoxPanel panel = new BoxPanel(BoxPanel.VERTICAL); + + panel.add(new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.properties.filename", + CmsConstants.CMS_BUNDLE, + new Object[]{properties.getFilename()}))); + panel.add(new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.properties.size", + CmsConstants.CMS_BUNDLE, + new Object[]{properties.getWidth(), properties.getHeight()}))); + panel.add(new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.properties.type", + CmsConstants.CMS_BUNDLE, + new String[]{properties.getType()}))); + + return panel; + } + + } + + private class MoveCellRenderer 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) { + + return new ControlLink((Component) value); + } + + } + + private class RemoveCellRenderer 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) { + + return new ControlLink((Component) value); + } + + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImagesTableModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImagesTableModel.java new file mode 100644 index 000000000..6fe788566 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImagesTableModel.java @@ -0,0 +1,117 @@ +/* + * 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.authoring.assets.images; + +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ui.authoring.assets.ItemAttachmentSelectionModel; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.web.CCMDispatcherServlet; + +import org.librecms.CmsConstants; + +import java.util.Iterator; +import java.util.List; + +/** + * + * @author Jens Pelzetter + */ +class AssignedImagesTableModel implements TableModel { + + private final PageState state; + private final ItemAttachmentSelectionModel moveAttachmentModel; + + private final Iterator iterator; + private AssignedImageTableRow currentRow; + + public AssignedImagesTableModel( + final List rows, + final PageState state, + final ItemAttachmentSelectionModel moveAttachmentModel) { + + this.iterator = rows.iterator(); + this.state = state; + this.moveAttachmentModel = moveAttachmentModel; + } + + @Override + public int getColumnCount() { + return 4; + } + + @Override + public boolean nextRow() { + if (iterator.hasNext()) { + currentRow = iterator.next(); + return true; + } else { + return false; + } + } + + @Override + public Object getElementAt(final int columnIndex) { + switch (columnIndex) { + case AssignedImagesTable.COL_PREVIEW: + return String + .format("%s/content-.sections/%s/images/" + + "uuid-%s?width=150&height=100", + CCMDispatcherServlet.getContextPath(), + CMS.getContext().getContentSection().getLabel(), + currentRow.getImageUuid()); + case AssignedImagesTable.COL_IMAGE_DATA: { + final ImageProperties imageProperties = new ImageProperties(); + imageProperties.setFilename(currentRow.getFilename()); + imageProperties.setWidth(currentRow.getWidth()); + imageProperties.setHeight(currentRow.getHeight()); + imageProperties.setType(currentRow.getType()); + + return imageProperties; + } + case AssignedImagesTable.COL_CAPTION: + return currentRow.getCaption(); + case AssignedImagesTable.COL_MOVE: + if (moveAttachmentModel.getSelectedKey(state) == null) { + return new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_image.link_move", + CmsConstants.CMS_BUNDLE)); + } else { + return new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_image.link_move_below_here", + CmsConstants.CMS_BUNDLE)); + } + case AssignedImagesTable.COL_REMOVE: + return new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.remove", + CmsConstants.CMS_BUNDLE)); + default: + throw new IllegalArgumentException(String.format( + "Illegal column index %d.", columnIndex)); + } + } + + @Override + public Object getKeyAt(final int columnIndex) { + return currentRow.getAttachmentId(); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImagesTableModelBuilder.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImagesTableModelBuilder.java new file mode 100644 index 000000000..66f9c1464 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AssignedImagesTableModelBuilder.java @@ -0,0 +1,94 @@ +/* + * 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.authoring.assets.images; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.TableModelBuilder; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.ui.authoring.assets.ItemAttachmentSelectionModel; +import com.arsdigita.util.LockableImpl; + +import org.libreccm.cdi.utils.CdiUtil; +import org.librecms.contentsection.ContentItem; + +import java.util.List; +import java.util.Locale; + +/** + * Creates the {@link AssignedImagesTableModel} which is used in + * {@link ImageStep} for the table of assigned images. This + * {@link TableModelBuilder} takes the selected item and retrieves all retrieved + * images from the item. For each assigned image an instance + * {@link AssignedImageTableRow} is created. The resulting list (which might be + * empty) is than used to create the image model. This also means that all + * interaction with the database is done by this {@link TableModelBuilder}. + * + * @author Jens Pelzetter + */ +class AssignedImagesTableModelBuilder extends LockableImpl implements + TableModelBuilder { + + private final ItemSelectionModel itemSelectionModel; + private final ItemAttachmentSelectionModel moveAttachmentModel; + private final StringParameter selectedLanguageParam; + + /** + * Constructor for this {@link TableModelBuilder}. + * + * @param itemSelectionModel The model used to determine the selected + * {@link ContentItem}. + * @param selectedLanguageParam Parameter used to determine the selected + * language variant of the selected + * {@link ContentItem}. + */ + protected AssignedImagesTableModelBuilder( + final ItemSelectionModel itemSelectionModel, + final ItemAttachmentSelectionModel moveAttachmentModel, + final StringParameter selectedLanguageParam) { + + this.itemSelectionModel = itemSelectionModel; + this.moveAttachmentModel = moveAttachmentModel; + this.selectedLanguageParam = selectedLanguageParam; + } + + @Override + public TableModel makeModel(final Table table, final PageState state) { + + final ContentItem selectedItem = itemSelectionModel + .getSelectedItem(state); + final String selectedLanguage = (String) state + .getValue(selectedLanguageParam); + final Locale selectedLocale = new Locale(selectedLanguage); + + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ImageStepController controller = cdiUtil + .findBean(ImageStepController.class); + + final List rows = controller + .retrieveAssignedImages(selectedItem, selectedLocale); + + return new AssignedImagesTableModel(rows, + state, + moveAttachmentModel); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImageTableRow.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImageTableRow.java new file mode 100644 index 000000000..d5d4e44d5 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImageTableRow.java @@ -0,0 +1,94 @@ +/* + * 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.authoring.assets.images; + +/** + * A container for the data shown in the table of assigned images. + * + * @author Jens Pelzetter + */ +class AvailableImageTableRow { + + private long imageId; + private String imageUuid; + private String filename; + private long width; + private long height; + private String type; + private String caption; + + public long getImageId() { + return imageId; + } + + public void setImageId(final long imageId) { + this.imageId = imageId; + } + + public String getImageUuid() { + return imageUuid; + } + + public void setImageUuid(final String imageUuid) { + this.imageUuid = imageUuid; + } + + public String getFilename() { + return filename; + } + + public void setFilename(final String filename) { + this.filename = filename; + } + + public long getWidth() { + return width; + } + + public void setWidth(final long width) { + this.width = width; + } + + public long getHeight() { + return height; + } + + public void setHeight(final long height) { + this.height = height; + } + + public String getType() { + return type; + } + + public void setType(final String type) { + this.type = type; + } + + public String getCaption() { + return caption; + } + + public void setCaption(final String caption) { + this.caption = caption; + } + + + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImages.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImages.java new file mode 100644 index 000000000..ac557099d --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImages.java @@ -0,0 +1,231 @@ +/* + * 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.authoring.assets.images; + +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.PaginationModelBuilder; +import com.arsdigita.bebop.Paginator; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.Text; +import com.arsdigita.bebop.event.TableActionEvent; +import com.arsdigita.bebop.event.TableActionListener; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableColumn; +import com.arsdigita.bebop.table.TableColumnModel; +import com.arsdigita.globalization.GlobalizedMessage; + +import org.libreccm.cdi.utils.CdiUtil; +import org.librecms.CmsConstants; +import org.librecms.assets.Image; +import org.librecms.contentsection.AttachmentList; + +import java.util.List; + +/** + * + * @author Jens Pelzetter + */ +class AvailableImages extends BoxPanel { + + protected static final int COL_PREVIEW = 0; + protected static final int COL_PROPERTIES = 1; + protected static final int COL_CAPTION = 2; + protected static final int COL_ADD = 3; + + public AvailableImages(final AttachmentList imagesList, + final List assignedImages) { + + super(BoxPanel.VERTICAL); + + final Form filterForm = new Form("filter_available_images_form", + new BoxPanel(BoxPanel.HORIZONTAL)); + final TextField filterField = new TextField("filter_available_images"); + filterField.setLabel(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.available_images.filter_label")); + final Submit submitFilter = new Submit(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.available_images.submit_filter")); + filterForm.add(filterField); + filterForm.add(submitFilter); + + super.add(filterForm); + + final Paginator paginator = new Paginator(new PaginationModelBuilder() { + + @Override + public int getTotalSize(final Paginator paginator, + final PageState state) { + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ImageStepController controller = cdiUtil + .findBean(ImageStepController.class); + + return (int) controller + .getNumberOfAvailableImages( + assignedImages, + (String) filterField.getValue(state)); + } + + @Override + public boolean isVisible(final PageState state) { + return true; + } + + }, + 30); + + super.add(paginator); + + final Table table = new Table(); + final TableColumnModel columnModel = table.getColumnModel(); + columnModel.add(new TableColumn( + COL_PREVIEW, + new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.available_images.preview_header", + CmsConstants.CMS_BUNDLE)))); + columnModel.add(new TableColumn( + COL_PROPERTIES, + new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.available_images.properties_header", + CmsConstants.CMS_BUNDLE)))); + columnModel.add(new TableColumn( + COL_CAPTION, + new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.available_images.caption_header", + CmsConstants.CMS_BUNDLE)))); + columnModel.add(new TableColumn( + COL_ADD, + new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.available_images.select_header", + CmsConstants.CMS_BUNDLE)))); + + table.setModelBuilder(new AvailableImagesTableModelBuilder(imagesList, + filterField, + paginator)); + + table + .getColumn(COL_PREVIEW) + .setCellRenderer(new ThumbnailCellRenderer()); + table + .getColumn(COL_PROPERTIES) + .setCellRenderer(new PropertiesCellRenderer()); + table + .getColumn(COL_ADD) + .setCellRenderer(new AddCellRenderer()); + + table.addTableActionListener(new TableActionListener() { + + @Override + public void cellSelected(final TableActionEvent event) + throws FormProcessException { + + final long imageId = (long) event.getRowKey(); + + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ImageStepController controller = cdiUtil + .findBean(ImageStepController.class); + controller.attachImage(imagesList, imageId); + } + + @Override + public void headSelected(final TableActionEvent event) { + //Nothing + } + + }); + } + + private class ThumbnailCellRenderer 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 == null) { + return new Text(""); + } else { + final com.arsdigita.bebop.Image image + = new com.arsdigita.bebop.Image( + (String) value, ""); + return image; + } + } + + } + + private class PropertiesCellRenderer 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) { + + @SuppressWarnings("unchecked") + final ImageProperties properties = (ImageProperties) value; + final BoxPanel panel = new BoxPanel(BoxPanel.VERTICAL); + + panel.add(new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.properties.filename", + CmsConstants.CMS_BUNDLE, + new Object[]{properties.getFilename()}))); + panel.add(new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.properties.size", + CmsConstants.CMS_BUNDLE, + new Object[]{properties.getWidth(), properties.getHeight()}))); + panel.add(new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.properties.type", + CmsConstants.CMS_BUNDLE, + new String[]{properties.getType()}))); + + return panel; + } + + } + + private class AddCellRenderer 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) { + + return new ControlLink((Component) value); + } + + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImagesTableModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImagesTableModel.java new file mode 100644 index 000000000..8036a455b --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImagesTableModel.java @@ -0,0 +1,97 @@ +/* + * 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.authoring.assets.images; + +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.cms.CMS; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.web.CCMDispatcherServlet; + +import org.librecms.CmsConstants; + +import java.util.Iterator; +import java.util.List; + +/** + * + * @author Jens Pelzetter + */ +class AvailableImagesTableModel implements TableModel { + + private final Iterator iterator; + private AvailableImageTableRow currentRow; + + public AvailableImagesTableModel(final List rows) { + iterator = rows.iterator(); + } + + @Override + public int getColumnCount() { + return 4; + } + + @Override + public boolean nextRow() { + if (iterator.hasNext()) { + currentRow = iterator.next(); + return true; + } else { + return false; + } + } + + @Override + public Object getElementAt(final int columnIndex) { + + switch (columnIndex) { + case AvailableImages.COL_PREVIEW: + return String + .format("%s/content-.sections/%s/images/" + + "uuid-%s?width=150&height=100", + CCMDispatcherServlet.getContextPath(), + CMS.getContext().getContentSection().getLabel(), + currentRow.getImageUuid()); + case AvailableImages.COL_PROPERTIES: + final ImageProperties imageProperties = new ImageProperties(); + imageProperties.setFilename(currentRow.getFilename()); + imageProperties.setWidth(currentRow.getWidth()); + imageProperties.setHeight(currentRow.getHeight()); + imageProperties.setType(currentRow.getType()); + + return imageProperties; + case AvailableImages.COL_CAPTION: + return currentRow.getCaption(); + case AvailableImages.COL_ADD: + return new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.available_images.add", + CmsConstants.CMS_BUNDLE)); + default: + throw new IllegalArgumentException(String.format( + "Illegal column index %d.", columnIndex)); + } + + } + + @Override + public Object getKeyAt(final int columnIndex) { + return currentRow.getImageId(); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImagesTableModelBuilder.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImagesTableModelBuilder.java new file mode 100644 index 000000000..313d1b555 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/AvailableImagesTableModelBuilder.java @@ -0,0 +1,85 @@ +/* + * 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.authoring.assets.images; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Paginator; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.TableModelBuilder; +import com.arsdigita.util.LockableImpl; + +import org.libreccm.cdi.utils.CdiUtil; +import org.librecms.assets.Image; +import org.librecms.contentsection.AttachmentList; + +import java.util.List; +import java.util.stream.Collectors; + +/** + * + * @author Jens Pelzetter + */ +public class AvailableImagesTableModelBuilder + extends LockableImpl + implements TableModelBuilder { + + private final AttachmentList imageList; + private final TextField filterField; + private final Paginator paginator; + + public AvailableImagesTableModelBuilder(final AttachmentList imageList, + final TextField filterField, + final Paginator paginator) { + this.imageList = imageList; + this.filterField = filterField; + this.paginator = paginator; + } + + @Override + public TableModel makeModel(final Table table, + final PageState state) { + + final List excludedImages = imageList + .getAttachments() + .stream() + .map(attachment -> attachment.getAsset()) + .filter(asset -> asset instanceof Image) + .map(asset -> (Image) asset) + .collect(Collectors.toList()); + + //Paginator count from 1, JPA from 0 + final int firstResult = paginator.getFirst(state) - 1; + final int maxResults = paginator.getPageSize(state); + + final CdiUtil cdiUtil = CdiUtil.createCdiUtil(); + final ImageStepController controller = cdiUtil + .findBean(ImageStepController.class); + + final List rows = controller + .getAvailableImageRows(excludedImages, + (String) filterField.getValue(state), + firstResult, + maxResults); + + return new AvailableImagesTableModel(rows); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/ImageProperties.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/ImageProperties.java new file mode 100644 index 000000000..a8b8581ea --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/ImageProperties.java @@ -0,0 +1,72 @@ +/* + * 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.authoring.assets.images; + +/** + * + * @author Jens Pelzetter + */ +class ImageProperties { + + protected static final String IMAGE_DATA_FILE_NAME = "filename"; + protected static final String IMAGE_DATA_WIDTH = "width"; + protected static final String IMAGE_DATA_HEIGHT = "height"; + protected static final String IMAGE_DATA_TYPE = "type"; + + private String filename; + + private long width; + + private long height; + + private String type; + + public String getFilename() { + return filename; + } + + public void setFilename(final String filename) { + this.filename = filename; + } + + public long getWidth() { + return width; + } + + public void setWidth(final long width) { + this.width = width; + } + + public long getHeight() { + return height; + } + + public void setHeight(final long height) { + this.height = height; + } + + public String getType() { + return type; + } + + public void setType(final String type) { + this.type = type; + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/ImageStep.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/ImageStep.java new file mode 100644 index 000000000..862c7b478 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/ImageStep.java @@ -0,0 +1,156 @@ +/* + * 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.authoring.assets.images; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.Text; +import com.arsdigita.bebop.parameters.LongParameter; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.ui.GlobalNavigation; +import com.arsdigita.cms.ui.authoring.AuthoringKitWizard; +import com.arsdigita.cms.ui.authoring.ResettableContainer; +import com.arsdigita.cms.ui.authoring.assets.ItemAttachmentSelectionModel; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.kernel.KernelConfig; + +import org.libreccm.cdi.utils.CdiUtil; +import org.librecms.CmsConstants; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ItemAttachment; +import org.librecms.ui.authoring.ContentItemAuthoringStep; + +import java.util.Locale; + +/** + * + * @author Jens Pelzetter + */ +@ContentItemAuthoringStep( + labelBundle = CmsConstants.CMS_BUNDLE, + labelKey = "image_step.label", + descriptionBundle = CmsConstants.CMS_BUNDLE, + descriptionKey = "image_step.description") +public class ImageStep extends ResettableContainer { + + private final LongParameter moveAttachmentParam; + private final ItemAttachmentSelectionModel moveAttachmentModel; + + private final Label assignedImagesHeader; + private final ControlLink addImageLink; + private final ActionLink beginLink; + private final Table assignedImagesTable; + + public ImageStep(final ItemSelectionModel itemSelectionModel, + final AuthoringKitWizard authoringKitWizard, + final StringParameter selectedLanguageParam) { + + super(); + + moveAttachmentParam = new LongParameter("moveAttachment"); + moveAttachmentModel = new ItemAttachmentSelectionModel( + moveAttachmentParam); + + assignedImagesHeader = new Label(event -> { + final PageState state = event.getPageState(); + final Label target = (Label) event.getTarget(); + + final ContentItem selectedItem = itemSelectionModel + .getSelectedItem(state); + final String selectedLanguage = (String) state + .getValue(selectedLanguageParam); + final Locale selectedLocale = new Locale(selectedLanguage); + final String title; + if (selectedItem.getTitle().hasValue(selectedLocale)) { + title = selectedItem.getTitle().getValue(selectedLocale); + } else { + title = selectedItem.getTitle().getValue(KernelConfig + .getConfig() + .getDefaultLocale()); + } + + target.setLabel(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.heading", + CmsConstants.CMS_BUNDLE, + new String[]{title})); + }); + super.add(assignedImagesHeader); + + addImageLink = new ControlLink(new Label(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.add_image", + CmsConstants.CMS_BUNDLE))); + addImageLink.addActionListener(event -> { + //ToDo + }); + super.add(addImageLink); + + beginLink = new ActionLink(new GlobalizedMessage( + "cms.ui.authoring.assets.imagestep.assigned_images.move_to_beginning", + CmsConstants.CMS_BUNDLE)); + add(beginLink); + + beginLink.addActionListener(event -> { + final PageState state = event.getPageState(); + final ItemAttachment toMove = moveAttachmentModel + .getSelectedAttachment(state); + + final ImageStepController controller = CdiUtil + .createCdiUtil() + .findBean(ImageStepController.class); + + controller.moveToFirst(toMove); + }); + + assignedImagesTable = new AssignedImagesTable(itemSelectionModel, + moveAttachmentModel, + selectedLanguageParam); + super.add(assignedImagesTable); + + super.add(new Text("Image Step placeholder")); + + moveAttachmentModel.addChangeListener(event -> { + + final PageState state = event.getPageState(); + + if (moveAttachmentModel.getSelectedKey(state) == null) { + addImageLink.setVisible(state, true); + beginLink.setVisible(state, false); + } else { + addImageLink.setVisible(state, false); + beginLink.setVisible(state, true); + } + }); + } + + @Override + public void register(final Page page) { + super.register(page); + + page.setVisibleDefault(assignedImagesHeader, true); + page.setVisibleDefault(addImageLink, true); + page.setVisibleDefault(beginLink, false); + page.setVisibleDefault(assignedImagesTable, true); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/ImageStepController.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/ImageStepController.java new file mode 100644 index 000000000..259cffa68 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/assets/images/ImageStepController.java @@ -0,0 +1,329 @@ +/* + * 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.authoring.assets.images; + +import org.libreccm.l10n.LocalizedString; +import org.librecms.assets.Image; +import org.librecms.contentsection.AssetRepository; +import org.librecms.contentsection.AttachmentList; +import org.librecms.contentsection.AttachmentListManager; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentItemRepository; +import org.librecms.contentsection.ItemAttachment; +import org.librecms.contentsection.ItemAttachmentManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Locale; +import java.util.Objects; +import java.util.stream.Collectors; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.persistence.TypedQuery; +import javax.persistence.criteria.CriteriaBuilder; +import javax.persistence.criteria.CriteriaQuery; +import javax.persistence.criteria.Join; +import javax.persistence.criteria.Root; +import javax.transaction.Transactional; + +/** + * Encapsulates all interaction between the {@link ImageStep} and associated + * classes like the {@link ImageStepTableModelBuilder} and CDI beans. + * + * @author Jens Pelzetter + */ +@RequestScoped +class ImageStepController { + + @Inject + private EntityManager entityManager; + + @Inject + private ContentItemRepository itemRepo; + + @Inject + private AssetRepository assetRepo; + + @Inject + private AttachmentListManager attachmentListManager; + + @Inject + private ItemAttachmentManager attachmentManager; + + @Transactional(Transactional.TxType.REQUIRED) + protected List retrieveAssignedImages( + final ContentItem fromContentItem, final Locale selectedLocale) { + + Objects.requireNonNull(fromContentItem); + Objects.requireNonNull(selectedLocale); + + final ContentItem item = itemRepo + .findById(fromContentItem.getObjectId()) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No ContentItem with id %d in the database.", + fromContentItem.getObjectId()))); + + final List imageLists = attachmentListManager + .getAttachmentList(item, ".images"); + + if (imageLists.isEmpty()) { + return Collections.emptyList(); + } + + final List> attachments = new ArrayList<>(); + for (final AttachmentList imageList : imageLists) { + for (final ItemAttachment attachment : imageList.getAttachments()) { + attachments.add(attachment); + } + } + + @SuppressWarnings("unchecked") + final List rows = attachments + .stream() + .sorted((attachment1, attachment2) -> { + return attachment1.compareTo(attachment2); + }) + .filter(attachment -> attachment.getAsset() instanceof Image) + .map(attachment -> (ItemAttachment) attachment) + .map(imageAttachment -> buildAssignedImageTableRow(imageAttachment, + selectedLocale)) + .collect(Collectors.toList()); + + return rows; + } + + @Transactional(Transactional.TxType.REQUIRED) + protected void moveToFirst(final ItemAttachment attachmentToMove) { + + Objects.requireNonNull(attachmentToMove); + + final ItemAttachment toMove = attachmentManager + .findById(attachmentToMove.getAttachmentId()) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No ItemAttachment with ID %d in the database.", + attachmentToMove.getAttachmentId()))); + + final AttachmentList attachmentList = toMove.getAttachmentList(); + final List> attachments = attachmentList + .getAttachments() + .stream() + .sorted((attachment1, attachment2) -> { + return attachment1.compareTo(attachment2); + }) + .collect(Collectors.toList()); + + toMove.setSortKey(0); + attachments + .stream() + .filter(current -> !current.equals(toMove)) + .forEach(current -> current.setSortKey(current.getSortKey() + 1)); + + attachments + .forEach(current -> entityManager.merge(current)); + } + + @Transactional(Transactional.TxType.REQUIRED) + protected void moveAfter(final ItemAttachment attachmentToMove, + final long destId) { + + Objects.requireNonNull(attachmentToMove); + + final ItemAttachment toMove = attachmentManager + .findById(attachmentToMove.getAttachmentId()) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No ItemAttachment with ID %d in the database.", + attachmentToMove.getAttachmentId()))); + + final ItemAttachment after = attachmentManager + .findById(destId) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No ItemAttachment with ID %d in the database.", + attachmentToMove.getAttachmentId()))); + + final AttachmentList attachmentList = toMove.getAttachmentList(); + final List> attachments = attachmentList + .getAttachments() + .stream() + .sorted((attachment1, attachment2) -> { + return attachment1.compareTo(attachment2); + }) + .collect(Collectors.toList()); + + if (!attachments.contains(toMove)) { + throw new IllegalArgumentException(String.format( + "ItemAttachment %d is not part of AttachmentList %d.", + toMove.getAttachmentId(), + attachmentList.getListId())); + } + + if (!attachments.contains(after)) { + throw new IllegalArgumentException(String.format( + "ItemAttachment %d is not part of AttachmentList %d.", + after.getAttachmentId(), + attachmentList.getListId())); + } + + final int afterIndex = attachments.indexOf(after); + for (int i = afterIndex + 1; i < attachments.size(); i++) { + final ItemAttachment current = attachments.get(i); + current.setSortKey(current.getSortKey() + 1); + entityManager.merge(current); + } + + toMove.setSortKey(afterIndex + 1); + entityManager.merge(toMove); + } + + @Transactional(Transactional.TxType.REQUIRED) + protected void deleteAttachment(final ItemAttachment attachment) { + + Objects.requireNonNull(attachment); + + final ItemAttachment toRemove = attachmentManager + .findById(attachment.getAttachmentId()) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No ItemAttachment with ID %d in the database.", + attachment.getAttachmentId()))); + + entityManager.remove(toRemove); + } + + @Transactional(Transactional.TxType.REQUIRED) + protected long getNumberOfAvailableImages(final List excluededImages, + final String filter) { + + final CriteriaBuilder criteriaBuilder = entityManager + .getCriteriaBuilder(); + + final CriteriaQuery query = criteriaBuilder + .createQuery(Long.class); + final Root from = query.from(Image.class); + final Join titleJoin = from.join("title.values"); + + query + .select(criteriaBuilder.count(from)); + if (filter == null || filter.trim().isEmpty()) { + query.where(criteriaBuilder.and( + criteriaBuilder.not(from.in(excluededImages)), + criteriaBuilder.like(titleJoin, String.format("&s%%", filter)))); + } else { + query.where(criteriaBuilder.not(from.in(excluededImages))); + } + + return entityManager.createQuery(query).getSingleResult(); + } + + @Transactional(Transactional.TxType.REQUIRED) + protected List getAvailableImages(final List excludedImages, + final String filter, + final long firstImage, + final long maxImages) { + final CriteriaBuilder criteriaBuilder = entityManager + .getCriteriaBuilder(); + + final CriteriaQuery criteriaQuery = criteriaBuilder + .createQuery(Image.class); + final Root from = criteriaQuery.from(Image.class); + final Join titleJoin = from.join("title.values"); + + if (filter == null || filter.trim().isEmpty()) { + criteriaQuery.where(criteriaBuilder.and( + criteriaBuilder.not(from.in(excludedImages)), + criteriaBuilder.like(titleJoin, String.format("&s%%", filter)))); + } else { + criteriaQuery.where(criteriaBuilder.not(from.in(excludedImages))); + } + + final TypedQuery query = entityManager + .createQuery(criteriaQuery); + query.setFirstResult((int) firstImage); + query.setMaxResults((int) maxImages); + + return query.getResultList(); + + } + + @Transactional(Transactional.TxType.REQUIRED) + protected List getAvailableImageRows( + final List excludedImages, + final String filter, + final long firstImage, + final long lastImage) { + + return getAvailableImages(excludedImages, filter, firstImage, lastImage) + .stream() + .map(this::buildAvailableImageRow) + .collect(Collectors.toList()); + + } + + private AvailableImageTableRow buildAvailableImageRow(final Image image) { + final AvailableImageTableRow row = new AvailableImageTableRow(); + row.setImageId(image.getObjectId()); + row.setImageUuid(image.getUuid()); + row.setFilename(image.getFileName()); + row.setWidth(image.getWidth()); + row.setHeight(row.getHeight()); + row.setType(image.getMimeType().toString()); + + return row; + } + + @Transactional(Transactional.TxType.REQUIRED) + protected void attachImage(final AttachmentList attachmentList, + final long imageId) { + + final AttachmentList addTo = attachmentListManager + .getAttachmentList(attachmentList.getListId()) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No AttachmentList with ID %d in the database.", + attachmentList.getListId()))); + + final Image image = assetRepo + .findById(imageId, Image.class) + .orElseThrow(() -> new IllegalArgumentException(String + .format("No Image with ID %d in the database.", + imageId))); + + attachmentManager.attachAsset(image, attachmentList); + } + + private AssignedImageTableRow buildAssignedImageTableRow( + final ItemAttachment imageAttachment, + final Locale selectedLocale) { + + final AssignedImageTableRow row = new AssignedImageTableRow(); + + row.setAttachmentId(imageAttachment.getAttachmentId()); + + final Image image = imageAttachment.getAsset(); + row.setImageUuid(image.getUuid()); + row.setFilename(image.getFileName()); + row.setWidth(image.getWidth()); + row.setHeight(image.getHeight()); + row.setType(image.getMimeType().toString()); + row.setCaption(image.getDescription().getValue(selectedLocale)); + + return row; + } + +} diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentList.java b/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentList.java index a59b76157..f260541d8 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentList.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentList.java @@ -59,6 +59,11 @@ import static org.librecms.CmsConstants.*; @Table(name = "ATTACHMENT_LISTS", schema = DB_SCHEMA) @Audited @NamedQueries({ + @NamedQuery( + name = "AttachmentList.findById", + query = "SELECT l FROM AttachmentList l WHERE l.listId = :listId" + ) + , @NamedQuery( name = "AttachmentList.findForItemAndName", query = "SELECT l FROM AttachmentList l " diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentListManager.java b/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentListManager.java index 6ab9cff31..61d9da9d6 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentListManager.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/AttachmentListManager.java @@ -32,6 +32,7 @@ import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.persistence.EntityManager; +import javax.persistence.NoResultException; import javax.persistence.TypedQuery; import javax.transaction.Transactional; @@ -109,6 +110,20 @@ public class AttachmentListManager { return names; } + @Transactional(Transactional.TxType.REQUIRED) + public Optional getAttachmentList(final long listId) { + + final TypedQuery query = entityManager + .createNamedQuery("AttachmentList.findById", AttachmentList.class); + query.setParameter("listId", listId); + + try { + return Optional.of(query.getSingleResult()); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + /** * Retrieves all {@link AttachmentList}s of a {@link ContentItem} with a * specific name. @@ -382,5 +397,4 @@ public class AttachmentListManager { entityManager.merge(list2.get()); } - } diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ItemAttachment.java b/ccm-cms/src/main/java/org/librecms/contentsection/ItemAttachment.java index 629c79219..36e13e80c 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ItemAttachment.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ItemAttachment.java @@ -19,9 +19,7 @@ package org.librecms.contentsection; import org.hibernate.envers.Audited; -import org.libreccm.core.CcmObject; import org.libreccm.core.Identifiable; -import org.libreccm.security.Relation; import java.io.Serializable; import java.util.Objects; @@ -52,22 +50,27 @@ import static org.librecms.CmsConstants.*; @Audited @NamedQueries({ @NamedQuery( - name = "ItemAttachment.countByAssetIdAndList", - query = "SELECT COUNT(i) FROM ItemAttachment i " - + "WHERE i.asset = :asset " - + "AND i.attachmentList = :attachmentList") + name = "ItemAttachment.findById", + query = "SELECT i FROM ItemAttachment i " + + "WHERE i.attachmentId = :attachmentId") , @NamedQuery( - name = "ItemAttachment.findByAssetByAndList", - query = "SELECT i FROM ItemAttachment i " - + "WHERE i.asset = :asset " - + "AND i.attachmentList = :attachmentList" + name = "ItemAttachment.countByAssetIdAndList", + query = "SELECT COUNT(i) FROM ItemAttachment i " + + "WHERE i.asset = :asset " + + "AND i.attachmentList = :attachmentList") + , + @NamedQuery( + name = "ItemAttachment.findByAssetByAndList", + query = "SELECT i FROM ItemAttachment i " + + "WHERE i.asset = :asset " + + "AND i.attachmentList = :attachmentList" ) }) public class ItemAttachment - implements Comparable>, - Identifiable, - Serializable { + implements Comparable>, + Identifiable, + Serializable { private static final long serialVersionUID = -9005379413315191984L; @@ -96,7 +99,7 @@ public class ItemAttachment * The {@link Asset} which is linked by this attachment to the * {@link #attachmentList}. */ - @ManyToOne(targetEntity = Asset.class, + @ManyToOne(targetEntity = Asset.class, cascade = {CascadeType.PERSIST}) @JoinColumn(name = "ASSET_ID") private T asset; @@ -161,7 +164,7 @@ public class ItemAttachment public int hashCode() { int hash = 3; hash - = 71 * hash + (int) (attachmentId ^ (attachmentId >>> 32)); + = 71 * hash + (int) (attachmentId ^ (attachmentId >>> 32)); hash = 71 * hash + Objects.hashCode(uuid); hash = 71 * hash + Objects.hashCode(asset); hash = 71 * hash + (int) (sortKey ^ (sortKey >>> 32)); @@ -206,11 +209,11 @@ public class ItemAttachment public String toString(final String data) { return String.format("%s{ " - + "attachmentId = %d, " - + "uuid = %s, " - + "asset = { %s }, " - + "sortKey = %d%s" - + " }", + + "attachmentId = %d, " + + "uuid = %s, " + + "asset = { %s }, " + + "sortKey = %d%s" + + " }", super.toString(), attachmentId, uuid, diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ItemAttachmentManager.java b/ccm-cms/src/main/java/org/librecms/contentsection/ItemAttachmentManager.java index 249d31562..8df51dc34 100644 --- a/ccm-cms/src/main/java/org/librecms/contentsection/ItemAttachmentManager.java +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ItemAttachmentManager.java @@ -32,6 +32,7 @@ import java.util.stream.Collectors; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.persistence.EntityManager; +import javax.persistence.NoResultException; import javax.persistence.TypedQuery; import javax.transaction.Transactional; @@ -52,6 +53,17 @@ public class ItemAttachmentManager { @Inject private AssetManager assetManager; + public Optional> findById(final long attachmentId) { + + final TypedQuery query = entityManager + .createNamedQuery("ItemAttachment.findById", ItemAttachment.class); + try { + return Optional.of(query.getSingleResult()); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + /** * Adds the provided {@link Asset} to the provided {@link AttachmentList}. * diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSectionManager.java b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSectionManager.java index cd1f968a8..af9269f07 100644 --- a/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSectionManager.java +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSectionManager.java @@ -73,8 +73,6 @@ public class MultiPartArticleSectionManager { section2.getRank())) .collect(Collectors.toList()); - final int oldRank = section.getRank(); - section.setRank(0); sections .stream() diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties index 9a4b26dff..e62f9c3a4 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources.properties @@ -387,3 +387,21 @@ cms.ui.authoring.file_upload.auto_detect=(Auto-Detect) cms.ui.upload_new_content=Upload new content cms.ui.asset.name=Name cms.ui.asset.thumbnail=Preview +cms.ui.authoring.assets.imagestep.heading=Images assigned to document {0} +cms.ui.authoring.assets.imagestep.assigned_images.preview_header=Preview +cms.ui.authoring.assets.imagestep.assigned_images.properties_header=Properties +cms.ui.authoring.assets.imagestep.assigned_images.caption_header=Caption +cms.ui.authoring.assets.imagestep.assigned_images.remove_header=Remove +cms.ui.authoring.assets.imagestep.assigned_images.properties.filename=File name: {0} +cms.ui.authoring.assets.imagestep.assigned_images.properties.size=Size: {0}x{1} +cms.ui.authoring.assets.imagestep.assigned_images.properties.type=Type: {0} +cms.ui.authoring.assets.imagestep.assigned_image.link_move=Move +cms.ui.authoring.assets.imagestep.assigned_image.link_move_below_here=Move below here +cms.ui.authoring.assets.imagestep.assigned_images.move_header=Move +cms.ui.authoring.assets.imagestep.assigned_images.move_to_beginning=Move to first position +cms.ui.authoring.assets.imagestep.available_images.submit_filter=Submit +cms.ui.authoring.assets.imagestep.available_images.filter_label=Filter images +cms.ui.authoring.assets.imagestep.available_images.preview_header=Preview +cms.ui.authoring.assets.imagestep.available_images.properties_header=Properties +cms.ui.authoring.assets.imagestep.available_images.select_header=Add image +cms.ui.authoring.assets.imagestep.available_images.caption_header=Caption diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties index 3efb7d039..981e641d1 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_de.properties @@ -384,3 +384,21 @@ cms.ui.authoring.file_upload.auto_detect=(Automatisch erkennen) cms.ui.upload_new_content=Neuen Inhalt hochladen cms.ui.asset.name=Name cms.ui.asset.thumbnail=Vorschau +cms.ui.authoring.assets.imagestep.heading=Dokument {0} zugeordnete Bilder +cms.ui.authoring.assets.imagestep.assigned_images.preview_header=Vorschau +cms.ui.authoring.assets.imagestep.assigned_images.properties_header=Eigenschaften +cms.ui.authoring.assets.imagestep.assigned_images.caption_header=Bildunterschrift +cms.ui.authoring.assets.imagestep.assigned_images.remove_header=Entfernen +cms.ui.authoring.assets.imagestep.assigned_images.properties.filename=Dateiname: {0} +cms.ui.authoring.assets.imagestep.assigned_images.properties.size=Gr\u00f6\u00dfe: {0}x{1} +cms.ui.authoring.assets.imagestep.assigned_images.properties.type=Typ: {0} +cms.ui.authoring.assets.imagestep.assigned_image.link_move=Verschieben +cms.ui.authoring.assets.imagestep.assigned_image.link_move_below_here=Hierher verschieben +cms.ui.authoring.assets.imagestep.assigned_images.move_header=Verschieben +cms.ui.authoring.assets.imagestep.assigned_images.move_to_beginning=An die erste Position verschieben +cms.ui.authoring.assets.imagestep.available_images.submit_filter=Anwenden +cms.ui.authoring.assets.imagestep.available_images.filter_label=Bilder filtern +cms.ui.authoring.assets.imagestep.available_images.preview_header=Vorschau +cms.ui.authoring.assets.imagestep.available_images.properties_header=Eigenschaften +cms.ui.authoring.assets.imagestep.available_images.select_header=Hinzuf\u00fcgen +cms.ui.authoring.assets.imagestep.available_images.caption_header=Bildunterschrift diff --git a/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties index 38ab5b61d..eae852522 100644 --- a/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties +++ b/ccm-cms/src/main/resources/org/librecms/CmsResources_fr.properties @@ -343,3 +343,21 @@ cms.ui.authoring.file_upload.auto_detect=(Auto-Detect) cms.ui.upload_new_content=Upload new content cms.ui.asset.name=Name cms.ui.asset.thumbnail=Preview +cms.ui.authoring.assets.imagestep.heading=Images assigned to ContentItem {0} +cms.ui.authoring.assets.imagestep.assigned_images.preview_header=Preview +cms.ui.authoring.assets.imagestep.assigned_images.properties_header=Properties +cms.ui.authoring.assets.imagestep.assigned_images.caption_header=Caption +cms.ui.authoring.assets.imagestep.assigned_images.remove_header=Remove +cms.ui.authoring.assets.imagestep.assigned_images.properties.filename=File name: {0} +cms.ui.authoring.assets.imagestep.assigned_images.properties.size=Size: {0}x{1} +cms.ui.authoring.assets.imagestep.assigned_images.properties.type=Type: {0} +cms.ui.authoring.assets.imagestep.assigned_image.link_move=Move +cms.ui.authoring.assets.imagestep.assigned_image.link_move_below_here=Move below here +cms.ui.authoring.assets.imagestep.assigned_images.move_header=Move +cms.ui.authoring.assets.imagestep.assigned_images.move_to_beginning=Move to first position +cms.ui.authoring.assets.imagestep.available_images.submit_filter=Submit +cms.ui.authoring.assets.imagestep.available_images.filter_label=Filter images +cms.ui.authoring.assets.imagestep.available_images.preview_header=Preview +cms.ui.authoring.assets.imagestep.available_images.properties_header=Properties +cms.ui.authoring.assets.imagestep.available_images.select_header=Add image +cms.ui.authoring.assets.imagestep.available_images.caption_header=Caption