diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/ResettableContainer.java b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/ResettableContainer.java new file mode 100755 index 000000000..a0cb49645 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/ResettableContainer.java @@ -0,0 +1,209 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.cms.contenttypes.ui; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Resettable; +import com.arsdigita.bebop.SimpleContainer; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +/** + * A container which implements the {@link Resettable} interface and provides + * other useful methods. + * + * @author Phong Nguyen + * @author Jens Pelzetter + */ +public class ResettableContainer extends SimpleContainer implements Resettable { + + /** + * A list of all resettable components in this container + */ + private final List resettableComponents = new ArrayList<>(); + + /** + * A list of all components that are not visible by default + */ + private final List componentsNotVisibleByDefault + = new ArrayList<>(); + + /** + * Constructs a new, empty {@code RessetableContainer}. + * + */ + public ResettableContainer() { + super(); + } + + /** + * Constructs a new, empty {@code ResettableContainer}. + * + * @param key The key for this container. + * + */ + public ResettableContainer(final String key) { + super(); + setKey(key); + } + + /** + * Constructs a new, empty {@code RessetableContainer}. The container will + * wrap its children in the specified tag. + * + * @param tag The name of the XML element that will be used to wrap + * the children of this container. + * @param namespace The namespace for the tag. + * + */ + public ResettableContainer(final String tag, final String namespace) { + super(tag, namespace); + } + + /** + * Adds a component to container. + * + * @param component The component to be added. + * + */ + @Override + public void add(final Component component) { + add(component, true); + } + + /** + * Add a component to this container + * + * @param component The component to be added. + * @param constraints This parameter is ignored. Child classes should + * override the add method if they wish to provide + * special handling of constraints. + * + */ + @Override + public void add(final Component component, final int constraints) { + add(component); + } + + /** + * Adds the component to this pane with the specified default visibility. + * + * @param component + * @param defaultVisibility The default visibility of this component + * + * + */ + public void add(final Component component, + final boolean defaultVisibility) { + + super.add(component); + if (component instanceof Resettable) { + resettableComponents.add(component); + } + if (!defaultVisibility) { + componentsNotVisibleByDefault.add(component); + } + } + + /** + * Sets the visibility of all child components to false, except for the + * component with the specified key. + * + * @param state The state of the current request. + * @param key The key of the component. There will be no visibility + * changes if key is null. + * + */ + public void onlyShowComponent(final PageState state, + final String key) { + + if (key == null) { + return; + } + + @SuppressWarnings("unchecked") + final Iterator iter = children(); + Component child; + while (iter.hasNext()) { + child = iter.next(); + child.setVisible(state, key.equals(child.getKey())); + } + } + + /** + * Sets the visibility of all child components to false, except for the + * specified component. + * + * @param state The state of the current request. + * @param component The key of the component. There will be no visibility + * changes if {@code component} is null. + * + */ + public void onlyShowComponent(final PageState state, + final Component component) { + + if (component == null) { + return; + } + + @SuppressWarnings("unchecked") + final Iterator iter = children(); + Component child; + while (iter.hasNext()) { + child = iter.next(); + child.setVisible(state, child.equals(component)); + } + } + + /** + * Resets all resettable components added to this container. + * + * @param state The state of the current request. + * + */ + @Override + public void reset(final PageState state) { + // Reset all resettable components automatically + final Iterator iter = resettableComponents.iterator(); + while (iter.hasNext()) { + ((Resettable) iter.next()).reset(state); + } + } + + /** + * Registers with page that this container belongs to and sets the default + * visibility of child components. + * + * @param page The page this container belongs to. + * + */ + @Override + public void register(final Page page) { + final Iterator iter = componentsNotVisibleByDefault + .iterator(); + while (iter.hasNext()) { + page.setVisibleDefault(iter.next(), false); + } + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/MultiPartArticleSectionStepController.java b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/MultiPartArticleSectionStepController.java new file mode 100644 index 000000000..3b8fa6a5d --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/MultiPartArticleSectionStepController.java @@ -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.contenttypes.ui.mparticle; + +import org.librecms.contentsection.ContentItemRepository; +import org.librecms.contenttypes.MultiPartArticle; +import org.librecms.contenttypes.MultiPartArticleSection; +import org.librecms.contenttypes.MultiPartArticleSectionManager; +import org.librecms.contenttypes.MultiPartArticleSectionRepository; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class MultiPartArticleSectionStepController { + + @Inject + private ContentItemRepository itemRepo; + + @Inject + private MultiPartArticleSectionRepository sectionRepo; + + @Inject + private MultiPartArticleSectionManager sectionManager; + + public void moveToFirst(final MultiPartArticle article, + final MultiPartArticleSection section) { + + final MultiPartArticle theArticle = itemRepo + .findById(article.getObjectId(), + MultiPartArticle.class) + .orElseThrow(() -> new IllegalArgumentException(String.format( + "No MultiPartArticle with ID %d in the database.", + article.getObjectId()))); + + final MultiPartArticleSection theSection = sectionRepo + .findById(section.getSectionId()) + .orElseThrow(() -> new IllegalArgumentException(String.format( + "No MultiPartArticleSection with ID %d in the database.", + section.getSectionId()))); + + sectionManager.moveToFirst(article, section); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/MultiPartArticleSectionsStep.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/MultiPartArticleSectionsStep.java.todo new file mode 100644 index 000000000..e5b22e040 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/MultiPartArticleSectionsStep.java.todo @@ -0,0 +1,165 @@ +/* + * 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.contenttypes.ui.mparticle; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.ColumnPanel; +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.DefaultSingleSelectionModel; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.parameters.LongParameter; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.contenttypes.ui.ResettableContainer; +import com.arsdigita.cms.ui.GlobalNavigation; +import com.arsdigita.cms.ui.authoring.AuthoringKitWizard; +import com.arsdigita.globalization.GlobalizedMessage; + +import org.libreccm.cdi.utils.CdiUtil; +import org.librecms.CmsConstants; +import org.librecms.contenttypes.MultiPartArticle; +import org.librecms.contenttypes.MultiPartArticleSection; +import org.librecms.contenttypes.MultiPartArticleSectionManager; + +/** + * Authoring kit step to manage the sections of a MultiPartArticle. Process is + * implemented with three main components that manipulate the currently selected + * MultiPartArticle and sections. The visibility of these components is managed + * by this class. + * + * Note: This class was originally called {@code MultiPartArticleViewSections}. + * Starting with version 7.0.0 all authoring step classes should end with + * {@code Step} to make them easily identifiable. + * + * @author Dave Turner + * * @author Jens Pelzetter + */ +public class MultiPartArticleSectionsStep extends ResettableContainer { + + /* id keys for each editing panel */ + public static final String SECTION_TABLE = "sec_tbl"; + public static final String SECTION_EDIT = "sec_edt"; + public static final String SECTION_PREVIEW = "sec_prv"; + public static final String SECTION_DELETE = "sec_del"; + + public static final String DATA_TABLE = "dataTable"; + public static final String ACTION_LINK = "actionLink"; + + private final AuthoringKitWizard authoringKitWizard; + private final ItemSelectionModel selectedArticleModel; + private final StringParameter selectedLanguageParam; + private SectionSelectionModel selectedSectionModel; + private SectionSelectionModel moveSectionModel; + private LongParameter moveSectionParam; + + private SectionTable sectionTable; + private SectionEditForm sectionEditForm; + private SectionPreviewPanel sectionPreviewPanel; + private SectionDeleteForm sectionDeleteForm; + + private ActionLink beginLink; + private Label moveSectionLabel; + + private final String typeIdStr; + + public MultiPartArticleSectionsStep( + final ItemSelectionModel selectedArticleModel, + final AuthoringKitWizard authoringKitWizard, + final StringParameter selectedLanguageParam) { + + super(); + this.selectedArticleModel = selectedArticleModel; + this.authoringKitWizard = authoringKitWizard; + this.selectedLanguageParam = selectedLanguageParam; + + typeIdStr = authoringKitWizard + .getContentType() + .getContentItemClass() + .getName(); + + addWidgets(); + } + + private void addWidgets() { + // create the components and set default visibility + add(buildSectionTable(), true); + add(buildSectionEdit(), false); + add(buildSectionDelete(), false); + } + + /** + * Builds a {@link Container} to hold a {@link SectionTable} and a link to + * add a new {@link MultiPartArticleSection}. + * + * @return A {@link Container} for the table of sections. + */ + protected Container buildSectionTable() { + + final ColumnPanel panel = new ColumnPanel(1); + panel.setKey(SECTION_TABLE + typeIdStr); + panel.setBorderColor("#FFFFFF"); + panel.setPadColor("#FFFFFF"); + + moveSectionParam = new LongParameter("moveSection"); + moveSectionModel = new SectionSelectionModel<>(moveSectionParam); + + sectionTable = new SectionTable(selectedArticleModel, + moveSectionModel); + sectionTable.setClassAttr(DATA_TABLE); + + // selected section is based on the selection in the SectionTable + selectedSectionModel = new SectionSelectionModel<>(sectionTable + .getRowSelectionModel()); + + sectionTable.setSectionModel(selectedSectionModel); + + final Label emptyView = new Label(new GlobalizedMessage( + "cms.contenttypes.ui.mparticle.no_sections_yet", + CmsConstants.CMS_BUNDLE)); + sectionTable.setEmptyView(this); + + moveSectionLabel = new Label(new GlobalizedMessage( + "cms.contenttypes.ui.mparticle.section.title", + CmsConstants.CMS_BUNDLE)); + panel.add(moveSectionLabel, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT); + + beginLink = new ActionLink(new GlobalizedMessage( + "cms.contenttypes.ui.mparticle.move_to_beginning", + CmsConstants.CMS_BUNDLE)); + panel.add(beginLink); + + beginLink.addActionListener(event -> { + final PageState state = event.getPageState(); + final MultiPartArticle article + = (MultiPartArticle) selectedArticleModel + .getSelectedObject(state); + final MultiPartArticleSection section = moveSectionModel + .getSelectedSection(state); + + final MultiPartArticleSectionStepController controller = CdiUtil + .createCdiUtil() + .findBean(MultiPartArticleSectionStepController.class); + + controller.moveToFirst(article, section); + }); + + + } diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionDeleteForm.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionDeleteForm.java.todo new file mode 100755 index 000000000..3fe19a903 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionDeleteForm.java.todo @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.cms.contenttypes.ui.mparticle; + + +import com.arsdigita.bebop.ColumnPanel; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SaveCancelSection; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormSubmissionListener; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.contenttypes.ArticleSection; +import com.arsdigita.cms.contenttypes.MultiPartArticle; +import com.arsdigita.cms.contenttypes.util.MPArticleGlobalizationUtil; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.util.Assert; +import org.apache.log4j.Logger; + +/** + * A form to confirm deletion of a single section of a MultiPartArticle. + * + * @author Dave Turner + * @version $Id: SectionDeleteForm.java 287 2005-02-22 00:29:02Z sskracic $ + */ +public class SectionDeleteForm extends Form + implements FormInitListener, FormSubmissionListener, FormProcessListener +{ + private final static Logger log = Logger.getLogger(SectionDeleteForm.class.getName()); + + protected ItemSelectionModel m_selArticle; + protected ItemSelectionModel m_selSection; + protected SaveCancelSection m_saveCancelSection; + private Label m_sectionNameLabel; + + + /** + * + * @param selArticle + * @param selSection + */ + public SectionDeleteForm + ( ItemSelectionModel selArticle, + ItemSelectionModel selSection) { + super("SectionDeleteForm", new ColumnPanel(2)); + m_selArticle = selArticle; + m_selSection = selSection; + + ColumnPanel panel = (ColumnPanel)getPanel(); + panel.setBorder(false); + panel.setPadColor("#FFFFFF"); + panel.setColumnWidth(1, "20%"); + panel.setColumnWidth(2, "80%"); + panel.setWidth("100%"); + + m_sectionNameLabel = new Label ("Section Name"); + add(m_sectionNameLabel, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT); + addSaveCancelSection(); + + addInitListener(this); + addSubmissionListener(this); + addProcessListener(this); + } + + /** + * + * @return + */ + protected SaveCancelSection addSaveCancelSection () { + m_saveCancelSection = new SaveCancelSection(); + m_saveCancelSection.getSaveButton().setButtonLabel( + GlobalizationUtil.globalize("cms.ui.delete")); + add(m_saveCancelSection, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT); + return m_saveCancelSection; + } + + @Override + public void init ( FormSectionEvent event ) throws FormProcessException { + PageState state = event.getPageState(); + + ArticleSection section = (ArticleSection)m_selSection.getSelectedObject(state); + + if ( section == null ) { + log.error("No section selected"); + } else { + m_sectionNameLabel.setLabel(section.getTitle(),state); + } + } + + @Override + public void submitted ( FormSectionEvent event ) throws FormProcessException { + PageState state = event.getPageState(); + + if ( m_saveCancelSection.getCancelButton().isSelected(state) ) { + throw new FormProcessException( + "Submission cancelled", + MPArticleGlobalizationUtil.globalize( + "cms.contenttypes.ui.mparticle.submission_cancelled") + ); + } + } + + @Override + public void process ( FormSectionEvent event ) throws FormProcessException { + PageState state = event.getPageState(); + + MultiPartArticle article = (MultiPartArticle)m_selArticle.getSelectedObject(state); + ArticleSection section = (ArticleSection)m_selSection.getSelectedObject(state); + + Assert.exists(article, MultiPartArticle.class); + Assert.exists(section, ArticleSection.class); + + article.removeSection(section); + + log.info("section " + m_selSection.getSelectedKey(state) + " delete"); + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionEditForm.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionEditForm.java.todo new file mode 100755 index 000000000..0e42c1733 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionEditForm.java.todo @@ -0,0 +1,399 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.cms.contenttypes.ui.mparticle; + + +import com.arsdigita.bebop.ColumnPanel; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SaveCancelSection; +import com.arsdigita.bebop.event.FormInitListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormSubmissionListener; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.form.CheckboxGroup; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.NotNullValidationListener; +import com.arsdigita.bebop.parameters.TrimmedStringParameter; +import com.arsdigita.cms.ReusableImageAsset; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.TextAsset; +import com.arsdigita.cms.contenttypes.ArticleSection; +import com.arsdigita.cms.contenttypes.MultiPartArticle; +import com.arsdigita.cms.ui.CMSDHTMLEditor; +import com.arsdigita.cms.contenttypes.util.MPArticleGlobalizationUtil; +import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.util.UncheckedWrapperException; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; + + +/** + * Form to edit an ArticleSection for a MultiPartArticle. + * + * @author Dave Turner + * @version $Id: SectionEditForm.java 1423 2006-12-19 22:08:04Z apevec $ + */ +public class SectionEditForm extends Form { + + private final static Logger log = Logger.getLogger(SectionEditForm.class); + + private ItemSelectionModel m_selArticle; + private ItemSelectionModel m_selSection; + + private BigDecimalParameter m_imageParam; + private ItemSelectionModel m_selImage; + + private BigDecimalParameter m_textParam; + private ItemSelectionModel m_selText; + private MultiPartArticleViewSections m_container; + + private SaveCancelSection m_saveCancelSection; + private ImageUploadSection m_imageUpload; + + + public static final String TITLE = "title"; + public static final String TEXT = "text"; + public static final String IMAGE = "image"; + public static final String PAGE_BREAK = "pageBreak"; + + private static final String TEXT_PARAM = "textParam"; + private static final String IMAGE_PARAM = "imageParam"; + + /** + * Constructor. + * + * @param selArticle the current article + * @param selSection the current section + */ + public SectionEditForm(ItemSelectionModel selArticle, + ItemSelectionModel selSection) { + this(selArticle, selSection, null); + } + /** + * Constructor. + * + * @param selArticle the current article + * @param selSection the current section + * @param container container which this form is added to + */ + public SectionEditForm(ItemSelectionModel selArticle, + ItemSelectionModel selSection, + MultiPartArticleViewSections container) { + super("SectionEditForm", new ColumnPanel(2)); + m_selArticle = selArticle; + m_selSection = selSection; + m_container = container; + + m_imageParam = new BigDecimalParameter(IMAGE_PARAM); + m_selImage = new ItemSelectionModel(ReusableImageAsset.class.getName(), + ReusableImageAsset.BASE_DATA_OBJECT_TYPE, + m_imageParam); + + m_textParam = new BigDecimalParameter(TEXT_PARAM); + m_selText = new ItemSelectionModel(TextAsset.class.getName(), + TextAsset.BASE_DATA_OBJECT_TYPE, + m_textParam); + + setMethod(Form.POST); + setEncType("multipart/form-data"); + + ColumnPanel panel = (ColumnPanel)getPanel(); + panel.setBorder(false); + panel.setPadColor("#FFFFFF"); + panel.setColumnWidth(1, "20%"); + panel.setColumnWidth(2, "80%"); + panel.setWidth("100%"); + + addWidgets(); + addSaveCancelSection(); + + addInitListener(new SectionInitListener()); + addSubmissionListener(new SectionSubmissionListener()); + addProcessListener(new SectionProcessListener()); + } + + /** + * Instantiate and add a save/cancel section to the form. + * + * @return the SaveCancelSection that was added + */ + protected SaveCancelSection addSaveCancelSection() { + m_saveCancelSection = new SaveCancelSection(); + add(m_saveCancelSection, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT); + return m_saveCancelSection; + } + + /** + * Returns the save/cancel section from this form. + */ + public SaveCancelSection getSaveCancelSection() { + return m_saveCancelSection; + } + + /** + * Add form widgets for a Section. + */ + protected void addWidgets() { + + //add(new Label(MPArticleGlobalizationUtil + // .globalize("cms.contenttypes.ui.mparticle.section.title"))); + TextField titleWidget = new TextField( + new TrimmedStringParameter(TITLE)); + titleWidget.addValidationListener(new NotNullValidationListener()); + titleWidget.setLabel(MPArticleGlobalizationUtil + .globalize("cms.contenttypes.ui.mparticle.section.title")); + add(titleWidget); + + //add(new Label(MPArticleGlobalizationUtil + // .globalize("cms.contenttypes.ui.mparticle.section.text")), + // ColumnPanel.LEFT | ColumnPanel.FULL_WIDTH); + CMSDHTMLEditor textWidget = + new CMSDHTMLEditor(new TrimmedStringParameter(TEXT)); + textWidget.setLabel(MPArticleGlobalizationUtil + .globalize("cms.contenttypes.ui.mparticle.section.text")); + textWidget.setRows(40); + textWidget.setCols(70); + textWidget.setWrap(CMSDHTMLEditor.SOFT); + add(textWidget, + ColumnPanel.LEFT | ColumnPanel.FULL_WIDTH); + + //add(new Label(MPArticleGlobalizationUtil + // .globalize("cms.contenttypes.ui.mparticle.section.image")), + // ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT); + m_imageUpload = new ImageUploadSection("image", m_selImage); + m_imageUpload.setLabel(MPArticleGlobalizationUtil + .globalize("cms.contenttypes.ui.mparticle.section.image")); + add(m_imageUpload, ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT); + + //add(new Label()); + CheckboxGroup pageBreak = new CheckboxGroup(PAGE_BREAK); + pageBreak.addOption(new Option("true", + new Label(MPArticleGlobalizationUtil + .globalize("cms.contenttypes.ui.mparticle.section.create_break")) )); + add(pageBreak); + } + + /** + * Utility method to create a Section from the form data supplied. + * + * @param event + * @param article + * @return + */ + protected ArticleSection createSection(FormSectionEvent event, + MultiPartArticle article) { + + PageState state = event.getPageState(); + FormData data = event.getFormData(); + + ArticleSection section = new ArticleSection(); + + section.setTitle((String)data.get(TITLE)); + section.setName(article.getName() + ": " + (String)data.get(TITLE)); + section.setContentSection(article.getContentSection()); + + return section; + } + + /** + * + * @param p + */ + @Override + public void register(Page p) { + super.register(p); + p.addGlobalStateParam(m_imageParam); + p.addGlobalStateParam(m_textParam); + } + + + /** + * Initialize the form. If there is a selected section, ie. this + * is an 'edit' step rather than a 'create new' step, load the data + * into the form fields. + */ + private class SectionInitListener implements FormInitListener { + + @Override + public void init( FormSectionEvent event ) + throws FormProcessException { + PageState state = event.getPageState(); + FormData data = event.getFormData(); + m_selImage.setSelectedObject(state, null); + m_selText.setSelectedObject(state,null); + + + if ( m_selSection.getSelectedKey(state) != null ) { + BigDecimal id = new BigDecimal(m_selSection + .getSelectedKey(state).toString()); + try { + // retrieve the selected Section from the persistence layer + ArticleSection section = new ArticleSection(id); + + data.put(TITLE, section.getTitle()); + + TextAsset t = section.getText(); + if ( t != null ) { + m_selText.setSelectedObject(state, t); + data.put(TEXT, t.getText()); + } + + ReusableImageAsset img = section.getImage(); + if (img != null) { + m_selImage.setSelectedObject(state, img); + } + + if (section.isPageBreak()) { + data.put(PAGE_BREAK, new Object[] { "true" }); + } + + } catch ( DataObjectNotFoundException ex ) { + log.error("Section(" + id + ") could not be found"); + } + } + + // Wait until the image selection model is updated before + // initializing the image section + m_imageUpload.initImageUpload(event); + } + } + + + /** + * Called on form submission. Check to see if the user clicked the + * cancel button. If they did, don't continue with the form. + */ + private class SectionSubmissionListener implements FormSubmissionListener { + + @Override + public void submitted( FormSectionEvent event ) + throws FormProcessException { + PageState state = event.getPageState(); + + if ( m_saveCancelSection.getCancelButton() + .isSelected(state) && m_container != null) { + m_container.onlyShowComponent( + state, MultiPartArticleViewSections.SECTION_TABLE+ + m_container.getTypeIDStr()); + throw new FormProcessException( + "Submission cancelled", + MPArticleGlobalizationUtil.globalize( + "cms.contenttypes.ui.mparticle.submission_cancelled") + ); + } else if ( m_imageUpload.getDeleteImageButton().isSelected(state) ) { + BigDecimal id = new BigDecimal(m_selSection + .getSelectedKey(state).toString()); + log.debug("deleting image for MPA section " + id); + try { + ArticleSection section = new ArticleSection(id); + section.setImage(null); + } catch ( DataObjectNotFoundException ex ) { + log.error("Section(" + id + ") could not be found"); + } + + } + } + } + + /** + * Called after form has been validated. Create the new ArticleSection and + * assign it to the current MultiPartArticle. + */ + private class SectionProcessListener implements FormProcessListener { + + @Override + public void process( FormSectionEvent event ) + throws FormProcessException { + PageState state = event.getPageState(); + FormData data = event.getFormData(); + + // retrieve the current MultiPartArticle + BigDecimal id = new BigDecimal( + m_selArticle.getSelectedKey(state).toString()); + MultiPartArticle article = null; + + try { + article = new MultiPartArticle(id); + } catch ( DataObjectNotFoundException ex ) { + throw new UncheckedWrapperException(ex); + } + + // get the selected section to update or create a new one + ArticleSection section = (ArticleSection) + m_selSection.getSelectedObject(state); + if ( section == null ) { + section = createSection(event, article); + article.addSection(section); + } + + section.setTitle((String)data.get(TITLE)); + + Object[] pageBreakVal = (Object[])data.get(PAGE_BREAK); + boolean pageBreak; + if (pageBreakVal == null || + pageBreakVal.length == 0 || + !"true".equals(pageBreakVal[0])) { + pageBreak = false; + } else { + pageBreak = true; + } + section.setPageBreak(pageBreak); + + // get the image asset + ReusableImageAsset reusableImageAsset = + m_imageUpload.processImageUpload(event); + if ( reusableImageAsset != null ) { + section.setImage(reusableImageAsset); + m_selImage.setSelectedObject(state, reusableImageAsset); + } + + + // get the text asset + TextAsset textAsset = (TextAsset)m_selText.getSelectedObject(state); + if ( textAsset == null ) { + textAsset = new TextAsset(); + textAsset.setName(section.getName() + " text"); + m_selText.setSelectedObject(state, textAsset); + section.setText(textAsset); + } + + String text = (String)data.get(TEXT); + if ( text == null ) { + text = ""; + } + + textAsset.setText(text); + if ( m_container != null) { + m_container.onlyShowComponent( + state, + MultiPartArticleViewSections.SECTION_TABLE+ + m_container.getTypeIDStr()); + } + } + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionPreviewPanel.java b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionPreviewPanel.java new file mode 100755 index 000000000..90dc0883b --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionPreviewPanel.java @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.cms.contenttypes.ui.mparticle; + +import com.arsdigita.bebop.BoxPanel; + +public class SectionPreviewPanel extends BoxPanel +{ + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionSelectionModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionSelectionModel.java new file mode 100644 index 000000000..099bb29ad --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionSelectionModel.java @@ -0,0 +1,168 @@ +/* + * 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.contenttypes.ui.mparticle; + +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.libreccm.core.UnexpectedErrorException; +import org.librecms.contenttypes.MultiPartArticleSection; +import org.librecms.contenttypes.MultiPartArticleSectionRepository; + +/** + * A {@link SingleSelectionModel} implementation for + * {@link MultiPartArticleSection}s. + * + * @param + * + * @author Jens Pelzetter + */ +class SectionSelectionModel + implements SingleSelectionModel { + + private final Class clazz; + private final SingleSelectionModel model; + + public SectionSelectionModel(final LongParameter parameter) { + this(MultiPartArticleSection.class.getName(), parameter); + } + + public SectionSelectionModel(final String parameterName) { + this(MultiPartArticleSection.class.getName(), + new LongParameter(parameterName)); + } + + public SectionSelectionModel(final Class clazz, + final String parameterName) { + this(clazz, new LongParameter(parameterName)); + } + + @SuppressWarnings("unchecked") + public SectionSelectionModel(final String className, + final String parameterName) { + + try { + clazz = (Class) Class.forName(className); + } catch (ClassNotFoundException ex) { + throw new UnexpectedErrorException(ex); + } + + model = new ParameterSingleSelectionModel<>( + new LongParameter(parameterName)); + } + + public SectionSelectionModel(final Class clazz, + final LongParameter parameter) { + this(clazz, new ParameterSingleSelectionModel<>(parameter)); + } + + @SuppressWarnings("unchecked") + public SectionSelectionModel(final String className, + final LongParameter parameter) { + + try { + clazz = (Class) Class.forName(className); + } catch (ClassNotFoundException ex) { + throw new UnexpectedErrorException(ex); + } + model = new ParameterSingleSelectionModel<>(parameter); + } + + public SectionSelectionModel(final Class clazz, + final SingleSelectionModel model) { + this.clazz = clazz; + this.model = model; + } + + @SuppressWarnings("unchecked") + public SectionSelectionModel(final String className, + final SingleSelectionModel model) { + + try { + clazz = (Class) Class.forName(className); + } catch (ClassNotFoundException ex) { + throw new UnexpectedErrorException(ex); + } + this.model = model; + } + + @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 T getSelectedSection(final PageState state) { + final Long key = getSelectedKey(state); + final MultiPartArticleSectionRepository sectionRepo = CdiUtil + .createCdiUtil() + .findBean(MultiPartArticleSectionRepository.class); + @SuppressWarnings("unchecked") + final T object = (T) sectionRepo.findById(key).get(); + return object; + } + + @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/contenttypes/ui/mparticle/SectionTable.java.todo b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionTable.java.todo new file mode 100755 index 000000000..243243a8b --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/contenttypes/ui/mparticle/SectionTable.java.todo @@ -0,0 +1,350 @@ +/* + * Copyright (C) 2002-2004 Red Hat Inc. All Rights Reserved. + * + * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * + */ +package com.arsdigita.cms.contenttypes.ui.mparticle; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.event.TableActionEvent; +import com.arsdigita.bebop.event.TableActionListener; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableColumn; +import com.arsdigita.bebop.table.TableColumnModel; +import com.arsdigita.bebop.table.TableModel; +import com.arsdigita.bebop.table.TableModelBuilder; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ContentItem; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.SecurityManager; +import com.arsdigita.cms.contenttypes.ArticleSection; +import com.arsdigita.cms.contenttypes.ArticleSectionCollection; +import com.arsdigita.cms.contenttypes.MultiPartArticle; +import com.arsdigita.cms.contenttypes.util.MPArticleGlobalizationUtil; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.persistence.OID; +import com.arsdigita.util.LockableImpl; + +import org.apache.log4j.Logger; + +import java.math.BigDecimal; + +/** + * A table that displays the sections for the currently + * selected MultiPartArticle. + * + * @author Dave Turner + * @version $Id: SectionTable.java 2099 2010-04-17 15:35:14Z pboy $ + */ +public class SectionTable extends Table { + + private static final Logger s_log = Logger.getLogger(SectionTable.class); + // match columns by (symbolic) index, makes for easier reordering + public static final int COL_INDEX_TITLE = 0; // "Section"; + public static final int COL_INDEX_EDIT = 1; // "Edit"; + public static final int COL_INDEX_MOVE = 2; // "Move"; + public static final int COL_INDEX_DELETE = 3; // "Delete"; + private ItemSelectionModel m_selArticle; + private ItemSelectionModel m_selSection; + private ItemSelectionModel m_moveSection; + + /** + * Constructor. Create an instance of this class. + * + * @param selArticle a selection model that returns the MultiPartArticle + * which holds the sections to display. + * @param moveSection + */ + public SectionTable(ItemSelectionModel selArticle, + ItemSelectionModel moveSection) { + + super(); + m_selArticle = selArticle; + m_moveSection = moveSection; + + TableColumnModel model = getColumnModel(); + model.add(new TableColumn( + COL_INDEX_TITLE, + new Label(MPArticleGlobalizationUtil.globalize( + "cms.contenttypes.ui.mparticle.section_table.header_section")))); + model.add(new TableColumn( + COL_INDEX_EDIT, + new Label(MPArticleGlobalizationUtil.globalize( + "cms.contenttypes.ui.mparticle.section_table.header_edit")))); + model.add(new TableColumn( + COL_INDEX_MOVE, + new Label(MPArticleGlobalizationUtil.globalize( + "cms.contenttypes.ui.mparticle.section_table.header_move")))); + model.add(new TableColumn( + COL_INDEX_DELETE, + new Label(MPArticleGlobalizationUtil.globalize( + "cms.contenttypes.ui.mparticle.section_table.header_delete")))); + + model.get(1).setCellRenderer(new SectionTableCellRenderer(true)); + model.get(2).setCellRenderer(new SectionTableCellRenderer(true)); + model.get(3).setCellRenderer(new SectionTableCellRenderer(true)); + + + setModelBuilder(new SectionTableModelBuilder(m_selArticle, m_moveSection)); + + addTableActionListener(new TableActionListener() { + + @Override + public void cellSelected(TableActionEvent event) { + PageState state = event.getPageState(); + + TableColumn col = getColumnModel().get(event.getColumn() + .intValue()); + + if (col.getModelIndex() == COL_INDEX_MOVE) { + if (m_moveSection.getSelectedKey(state) == null) { + m_moveSection.setSelectedKey(state, + m_selSection + .getSelectedKey(state)); + } else { + MultiPartArticle article = (MultiPartArticle) m_selArticle. + getSelectedObject(state); + + BigDecimal id = (BigDecimal) m_moveSection.getSelectedKey(state); + ArticleSection sect = (ArticleSection) DomainObjectFactory.newInstance( + new OID(ArticleSection.BASE_DATA_OBJECT_TYPE, id)); + + BigDecimal dest = + new BigDecimal((String) event.getRowKey()); + ArticleSection destSect = (ArticleSection) DomainObjectFactory.newInstance( + new OID(ArticleSection.BASE_DATA_OBJECT_TYPE, dest)); + + // if sect is lower in rank than the dest + // then move below is default behavior + int rank = destSect.getRank().intValue(); + if (sect.getRank().intValue() > rank) { + // otherwise, add one to get "move below" + rank++; + } + + article.changeSectionRank(sect, rank); + m_moveSection.setSelectedKey(state, null); + } + } + } + + @Override + public void headSelected(TableActionEvent event) { + // do nothing + } + + }); + } + + public void setSectionModel(ItemSelectionModel selSection) { + if (selSection == null) { + s_log.warn("null item model"); + } + m_selSection = selSection; + } + + /** + * The model builder to generate a suitable model for the SectionTable + */ + protected class SectionTableModelBuilder extends LockableImpl + implements TableModelBuilder { + + protected ItemSelectionModel m_selArticle; + protected ItemSelectionModel m_moveSection; + + /** + * Private class constructor. + * @param selArticle + * @param moveSection + */ + public SectionTableModelBuilder(ItemSelectionModel selArticle, + ItemSelectionModel moveSection) { + m_selArticle = selArticle; + m_moveSection = moveSection; + } + + /** + * + * @param table + * @param state + * @return + */ + @Override + public TableModel makeModel(Table table, PageState state) { + table.getRowSelectionModel().clearSelection(state); + + MultiPartArticle article = (MultiPartArticle) m_selArticle + .getSelectedObject(state); + + return new SectionTableModel(table, state, article, m_moveSection); + } + + } + + /** + * Internal class + */ + protected class SectionTableModel implements TableModel { + + private TableColumnModel m_colModel; + private SectionTable m_table; + private PageState m_state; + private ArticleSectionCollection m_sections; + private ItemSelectionModel m_moveSection; + private ArticleSection m_section; + + /** Constructor. + * @param table + * @param state + * @param article + * @param moveSection + */ + public SectionTableModel(Table table, PageState state, + MultiPartArticle article, + ItemSelectionModel moveSection) { + m_colModel = table.getColumnModel(); + m_state = state; + m_sections = article.getSections(); + m_table = (SectionTable) table; + m_moveSection = moveSection; + } + + /** Return the number of columsn this TableModel has. */ + @Override + public int getColumnCount() { + return m_colModel.size(); + } + + /** Move to the next row and return true if the model is now positioned + * on a valid row. + */ + @Override + public boolean nextRow() { + if (m_sections.next()) { + m_section = (ArticleSection) m_sections.getArticleSection(); + return true; + } + return false; + } + + /** + * Return the data element for the given column and the current row. + */ + @Override + public Object getElementAt(int columnIndex) { + + if (m_colModel == null) { + return null; + } + + // match columns by (symbolic) index, makes for easier reordering + if (columnIndex == COL_INDEX_TITLE) { + return m_section.getTitle(); + } else if (columnIndex == COL_INDEX_EDIT) { + //return "edit"; + return new Label( + MPArticleGlobalizationUtil.globalize( + "cms.contenttypes.ui.mparticle.section_table.link_edit")); + } else if (columnIndex == COL_INDEX_DELETE) { + // return "delete"; + return new Label( + MPArticleGlobalizationUtil.globalize( + "cms.contenttypes.ui.mparticle.section_table.link_delete")); + } else if (columnIndex == COL_INDEX_MOVE) { + if (m_moveSection.getSelectedKey(m_state) == null) { + // return "move"; + return new Label( + MPArticleGlobalizationUtil.globalize( + "cms.contenttypes.ui.mparticle.section_table.link_move")); + } else { + // return "move below here"; + return new Label( + MPArticleGlobalizationUtil.globalize( + "cms.contenttypes.ui.mparticle.section_table.link_move_below")); + } + } + + return null; + } + + /** + * Return the key for the given column and the current row. + */ + @Override + public Object getKeyAt(int columnIndex) { + return m_section.getID(); + } + + } + + /** + * + */ + public class SectionTableCellRenderer extends LockableImpl + implements TableCellRenderer { + + private boolean m_active; + + public SectionTableCellRenderer() { + this(false); + } + + public SectionTableCellRenderer(boolean active) { + m_active = active; + } + + @Override + public Component getComponent(Table table, PageState state, + Object value, boolean isSelected, + Object key, int row, int column) { + + Component ret; + SecurityManager sm = CMS.getSecurityManager(state); + ContentItem item = (ContentItem) m_selArticle.getSelectedObject(state); + + boolean active = m_active && sm.canAccess(state.getRequest(), + SecurityManager.EDIT_ITEM, + item); + + if (value instanceof Label) { + if (active) { + ret = new ControlLink((Component) value); + } else { + ret = (Component) value; + } + + } else if (value instanceof String) { + // Backwards compatibility, should be removed asap! + if (active) { + ret = new ControlLink(value.toString()); + } else { + ret = new Label(value.toString()); + } + } else { + ret = new Label(MPArticleGlobalizationUtil.globalize( + "cms.contenttypes.ui.mparticle.section_table.link_not_defined"), + false); + } + + return ret; + } + + } +} diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticle.java b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticle.java index 9ae7137dc..7e6478399 100644 --- a/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticle.java +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticle.java @@ -37,6 +37,7 @@ import javax.persistence.Entity; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; import javax.persistence.OneToMany; +import javax.persistence.OrderBy; import javax.persistence.Table; import static org.librecms.CmsConstants.*; diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSection.java b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSection.java index 52b0064ca..f7512b853 100644 --- a/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSection.java +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSection.java @@ -33,6 +33,8 @@ import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.JoinTable; +import javax.persistence.NamedQueries; +import javax.persistence.NamedQuery; import javax.persistence.Table; import static org.librecms.CmsConstants.*; @@ -45,6 +47,17 @@ import static org.librecms.CmsConstants.*; @Entity @Audited @Table(name = "MULTIPART_ARTICLE_SECTIONS", schema = DB_SCHEMA) +@NamedQueries({ + @NamedQuery( + name = "MultiPartArticleSection.findById", + query = "SELECT s FROM MultiPartArticleSection s " + + "WHERE s.sectionId = :sectionId") + , + @NamedQuery( + name = "MultiPartArticleSection.findArticleOfSection", + query = "SELECT a FROM MultiPartArticle a " + + "WHERE :section MEMBER OF a.sections") +}) public class MultiPartArticleSection implements Serializable { private static final long serialVersionUID = 1109186628988745920L; @@ -53,7 +66,7 @@ public class MultiPartArticleSection implements Serializable { @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "SECTION_ID") private long sectionId; - + @Embedded @AssociationOverride( name = "values", @@ -83,11 +96,11 @@ public class MultiPartArticleSection implements Serializable { public long getSectionId() { return sectionId; } - + protected void setSectionId(final long sectionId) { this.sectionId = sectionId; } - + public LocalizedString getTitle() { return title; } @@ -121,7 +134,6 @@ public class MultiPartArticleSection implements Serializable { } //ToDo: Add image property - @Override public int hashCode() { int hash = 5; diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSectionManager.java b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSectionManager.java new file mode 100644 index 000000000..78a56c8cb --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSectionManager.java @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2017 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.contenttypes; + +import org.librecms.contentsection.ContentItemRepository; + +import java.util.List; +import java.util.stream.Collectors; + +import javax.enterprise.context.RequestScoped; +import javax.inject.Inject; +import javax.persistence.EntityManager; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class MultiPartArticleSectionManager { + + @Inject + private ContentItemRepository itemRepo; + + @Inject + private MultiPartArticleSectionRepository sectionRepo; + + + @Transactional(Transactional.TxType.REQUIRED) + public void addSectionToMultiPartArticle( + final MultiPartArticleSection section, + final MultiPartArticle article) { + + article.addSection(section); + itemRepo.save(article); + sectionRepo.save(section); + } + + @Transactional(Transactional.TxType.REQUIRED) + public void removeSectionFromMultiPartArticle( + final MultiPartArticleSection section, + final MultiPartArticle article) { + + article.removeSection(section); + itemRepo.save(article); + sectionRepo.delete(section); + } + + @Transactional(Transactional.TxType.REQUIRED) + public void moveToFirst(final MultiPartArticle article, + final MultiPartArticleSection section) { + + final List sections = article + .getSections() + .stream() + .sorted((section1, section2) -> Integer.compare(section1.getRank(), + section2.getRank())) + .collect(Collectors.toList()); + + final int oldRank = section.getRank(); + + section.setRank(1); + sections + .stream() + .filter(current -> !current.equals(section)) + .forEach(current -> current.setRank(current.getRank() + 1)); + + sections + .forEach(current -> sectionRepo.save(section)); + } + + +} diff --git a/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSectionRepository.java b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSectionRepository.java new file mode 100644 index 000000000..312f2bfe7 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contenttypes/MultiPartArticleSectionRepository.java @@ -0,0 +1,81 @@ +/* + * Copyright (C) 2017 LibreCCM Foundation. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, + * MA 02110-1301 USA + */ +package org.librecms.contenttypes; + +import org.libreccm.auditing.AbstractAuditedEntityRepository; + +import java.util.Optional; + +import javax.enterprise.context.RequestScoped; +import javax.persistence.NoResultException; +import javax.persistence.TypedQuery; +import javax.transaction.Transactional; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class MultiPartArticleSectionRepository + extends AbstractAuditedEntityRepository { + + @Override + public Long getEntityId(final MultiPartArticleSection entity) { + return entity.getSectionId(); + } + + @Override + public Class getEntityClass() { + return MultiPartArticleSection.class; + } + + @Override + public boolean isNew(final MultiPartArticleSection entity) { + return entity.getSectionId() == 0; + } + + @Transactional(Transactional.TxType.REQUIRED) + public Optional findById( + final long sectionId) { + + final TypedQuery query = getEntityManager() + .createNamedQuery("MultiPartArticleSection.findById", + MultiPartArticleSection.class); + query.setParameter("sectionId", sectionId); + + try { + return Optional.of(query.getSingleResult()); + } catch (NoResultException ex) { + return Optional.empty(); + } + } + + @Transactional(Transactional.TxType.REQUIRED) + public MultiPartArticle findArticleOfSection( + final MultiPartArticleSection section) { + + final TypedQuery query = getEntityManager() + .createNamedQuery("MultiPartArticleSection.findArticleOfSection", + MultiPartArticle.class); + query.setParameter("section", section); + + return query.getSingleResult(); + } + +} diff --git a/ccm-core/src/main/java/com/arsdigita/ui/CcmObjectSelectionModel.java b/ccm-core/src/main/java/com/arsdigita/ui/CcmObjectSelectionModel.java index eefa97493..2867fa148 100644 --- a/ccm-core/src/main/java/com/arsdigita/ui/CcmObjectSelectionModel.java +++ b/ccm-core/src/main/java/com/arsdigita/ui/CcmObjectSelectionModel.java @@ -135,7 +135,8 @@ public class CcmObjectSelectionModel @Override public void clearSelection(final PageState state) { - throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates. + + model.clearSelection(state); } @Override @@ -145,7 +146,7 @@ public class CcmObjectSelectionModel @Override public void removeChangeListener(final ChangeListener changeListener) { - model.addChangeListener(changeListener);; + model.removeChangeListener(changeListener);; } @Override diff --git a/ccm-core/src/main/java/org/libreccm/admin/ui/AdminUIVaadin.java b/ccm-core/src/main/java/org/libreccm/admin/ui/AdminUIVaadin.java index 4bb157e73..aade93f75 100644 --- a/ccm-core/src/main/java/org/libreccm/admin/ui/AdminUIVaadin.java +++ b/ccm-core/src/main/java/org/libreccm/admin/ui/AdminUIVaadin.java @@ -31,8 +31,6 @@ import org.apache.shiro.subject.Subject; import org.libreccm.l10n.GlobalizationHelper; import org.libreccm.security.PermissionChecker; -import java.util.Locale; - import javax.inject.Inject; /**