diff --git a/ccm-bundle-devel-wildfly-web/src/main/resources/log4j2.xml b/ccm-bundle-devel-wildfly-web/src/main/resources/log4j2.xml index 37684c867..fb01e7b0f 100644 --- a/ccm-bundle-devel-wildfly-web/src/main/resources/log4j2.xml +++ b/ccm-bundle-devel-wildfly-web/src/main/resources/log4j2.xml @@ -45,6 +45,9 @@ + + diff --git a/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/web.xml b/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/web.xml index 524e50256..42fb40ecd 100644 --- a/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/web.xml +++ b/ccm-bundle-devel-wildfly-web/src/main/webapp/WEB-INF/web.xml @@ -42,4 +42,8 @@ javax.faces.PROJECT_STAGE Development + + javax.faces.FACELETS_SKIP_COMMENTS + true + diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ContentSectionServlet.java b/ccm-cms/src/main/java/com/arsdigita/cms/ContentSectionServlet.java index 0442fea9f..661cfc829 100755 --- a/ccm-cms/src/main/java/com/arsdigita/cms/ContentSectionServlet.java +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ContentSectionServlet.java @@ -211,11 +211,8 @@ public class ContentSectionServlet extends BaseApplicationServlet { getClass().getName()); } - // NEW STUFF here will be used to process the pages in this servlet - // Currently NOT working - // addPage("/admin", new MainPage()); // index page at address ~/cs - // addPage("/admin/index.jsp", new MainPage()); - // addPage("/admin/item.jsp", new MainPage()); + //ToDo addPage(CmsConstants.CONTENT_SECTION_PAGE, new ContentSectionPage()); // index page at address ~/cs + //ToDo addPage(CmsConstants.CONTENT_SECTION_ITEM_PAGE, new ContentSectionPage()); } /** diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ItemSelectionModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ItemSelectionModel.java new file mode 100755 index 000000000..28c223eca --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ItemSelectionModel.java @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2001-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; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.kernel.ui.ACSObjectSelectionModel; +import com.arsdigita.util.UncheckedWrapperException; + +import org.apache.log4j.Logger; +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.core.CcmObject; +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentType; +import org.librecms.contentsection.ContentTypeRepository; + +import javax.servlet.ServletException; + +import java.math.BigDecimal; + +/** + *

+ * Loads a subclass of a {@link com.arsdigita.cms.ContentItem} from the + * database. This model should be used as a parameter to the constructor of + * authoring kit components.

+ * + *

+ * It is possible to instantiate this model with a {@link + * com.arsdigita.cms.ContentType} as a constructor parameter. In this case, the + * model will only instantiate items that are of the specified content type, or + * one of it subclasses.

+ * + * @author Stanislav Freidin (stas@arsdigita.com) + * @version $Revision$ $DateTime: 2004/08/17 23:15:09 $ + * @see com.arsdigita.kernel.ui.ACSObjectSelectionModel + * @see com.arsdigita.bebop.SingleSelectionModel + */ +public class ItemSelectionModel extends ACSObjectSelectionModel { + + private Long m_typeId; + + private static final Logger s_log = Logger.getLogger( + ItemSelectionModel.class); + + /** + * Construct a new ItemSelectionModel. This model will produce + * instances of ContentItem by automatically instantiating the + * correct Java subclass using the + * {@link com.arsdigita.domain.DomainObjectFactory}. + * + * @param parameter The state parameter which should be used to store the + * object ID + */ + public ItemSelectionModel(BigDecimalParameter parameter) { + this(null, null, parameter); + } + + /** + * Construct a new ItemSelectionModel. This model will produce + * instances of ContentItem by automatically instantiating the + * correct Java subclass using the + * {@link com.arsdigita.domain.DomainObjectFactory}. + * + * @param parameterName The name of the state parameter which will be used + * to store the object ID. + */ + public ItemSelectionModel(String parameterName) { + this(null, null, new BigDecimalParameter(parameterName)); + } + + /** + * Construct a new ItemSelectionModel. This model will produce + * instances of ContentItem by automatically instantiating the + * correct Java subclass using the + * {@link com.arsdigita.domain.DomainObjectFactory}. + * + * @param model The {@link SingleSelectionModel} which will supply a + * {@link BigDecimal} ID of the currently selected item + */ + public ItemSelectionModel(SingleSelectionModel model) { + this(null, null, model); + } + + /** + * Construct a new ItemSelectionModel + * + * @param type The content type for the items this model will + * generate + * + * @param parameterName The name of the state parameter which will be used + * to store the item. + */ + public ItemSelectionModel(ContentType type, String parameterName) { + this(type, new BigDecimalParameter(parameterName)); + } + + /** + * Construct a new ItemSelectionModel + * + * @param type The content type for the items this model will generate + * + * @param parameter The state parameter which should be used by this item + * + */ + public ItemSelectionModel(ContentType type, BigDecimalParameter parameter) { + super(type.getContentItemClass(), type.getContentItemClass(), parameter); + m_typeId = type.getObjectId(); + } + + /** + * Construct a new ItemSelectionModel + * + * @param type The content type for the items this model will generate + * + * @param model The {@link SingleSelectionModel} which will supply a + * {@link BigDecimal} id of the currently selected object + * + */ + public ItemSelectionModel(ContentType type, SingleSelectionModel model) { + super(type.getContentItemClass(), type.getContentItemClass(), model); + m_typeId = type.getObjectId(); + } + + /** + * Construct a new ItemSelectionModel + * + * @param itemClass The name of the Java class which represents the + * content item. Must be a subclass of ContentItem. In + * addition, the class must have a constructor with a + * single OID parameter. + * @param objectType The name of the persistence metadata object type + * which represents the content item. In practice, will + * often be the same as the itemClass. + * @param parameterName The name of the state parameter which will be used + * to store the item. + */ + public ItemSelectionModel(String itemClass, + String objectType, + String parameterName) { + super(itemClass, objectType, new BigDecimalParameter(parameterName)); + } + + /** + * Construct a new ItemSelectionModel + * + * @param itemClass The name of the Java class which represents the content + * item. Must be a subclass of ContentItem. In addition, + * the class must have a constructor with a single OID + * parameter. + * @param objectType The name of the persistence metadata object type which + * represents the content item. In practice, will often be + * the same as the itemClass. + * @param parameter The state parameter which should be used by this item + */ + public ItemSelectionModel(String itemClass, String objectType, + BigDecimalParameter parameter) { + super(itemClass, objectType, parameter); + } + + /** + * Construct a new ItemSelectionModel + * + * @param itemClass The name of the Java class which represents the content + * item. Must be a subclass of ContentItem. In addition, + * the class must have a constructor with a single OID + * parameter. + * @param objectType The name of the persistence metadata object type which + * represents the content item. In practice, will often be + * the same as the itemClass. + * @param model The {@link SingleSelectionModel} which will supply a + * {@link BigDecimal} id of the currently selected object + * + */ + public ItemSelectionModel(String itemClass, + String objectType, + SingleSelectionModel model) { + super(itemClass, objectType, model); + } + + /** + * A utility function which creates a new item with the given ID. Uses + * reflection to create the instance of the class supplied in the + * constructor to this ItemSelectionModel. + * + * @param id The id of the new item -- this is now ignored + * + * @return The newly created item + * + * @deprecated use createItem() instead + */ + public ContentItem createItem(BigDecimal id) throws ServletException { + return (ContentItem) createACSObject(); + } + + /** + * A utility function which creates a new item. Uses reflection to create + * the instance of the class supplied in the constructor to this + * ItemSelectionModel. + * + * @return The newly created item + */ + public ContentItem createItem() throws ServletException { + return (ContentItem) createACSObject(); + } + + /** + * A convenience method that gets the currently selected object and casts it + * to a ContentItem + * + * @param s the current page state + * + * @return the currently selected ContentItem, or null if no + * item was selected. + */ + public final ContentItem getSelectedItem(PageState s) { + return (ContentItem) getSelectedObject(s); + } + + /** + * A utility function which creates a new item with the given ID. Uses + * reflection to create the instance of the class supplied in the + * constructor to this ItemSelectionModel. + * + * @param id The id of the new item -- this is now ignored + * + * @return The newly created item + * + * @deprecated Use createACSObject() instead + */ + public CcmObject createACSObject(BigDecimal id) throws ServletException { + return createACSObject(); + } + + /** + * A utility function which creates a new item. Uses reflection to create + * the instance of the class supplied in the constructor to this + * ItemSelectionModel. + * + * @return The newly created item + */ + public CcmObject createACSObject() throws ServletException { + ContentType type = getContentType(); + ContentItem item = (ContentItem) super.createACSObject(); + + if (type != null) { + item.setContentType(type); + } + return item; + } + + /** + * + * @return The content type of the items which are produced by this model, + * or null if the content type has not been specified in the + * constructor. + */ + public ContentType getContentType() { + + ContentType type = null; + + if (m_typeId != null) { + type = CdiUtil.createCdiUtil().findBean(ContentTypeRepository.class).findById(m_typeId); + } + + return type; + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/BaseTree.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/BaseTree.java new file mode 100755 index 000000000..6b7da2d54 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/BaseTree.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2003-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.ui; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Tree; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.event.TreeExpansionEvent; +import com.arsdigita.bebop.event.TreeExpansionListener; +import com.arsdigita.bebop.tree.TreeModelBuilder; +import org.apache.log4j.Logger; + +/** + * A convenience class for CMS trees. + * + * @author Justin Ross <jross@redhat.com> + * @version $Id$ + */ +public class BaseTree extends Tree { + + private static final Logger s_log = Logger.getLogger(BaseTree.class); + + public BaseTree(final TreeModelBuilder builder) { + super(builder); + + addChangeListener(new Change()); + addTreeExpansionListener(new TreeExpansion()); + } + + private class Change implements ChangeListener { + public final void stateChanged(final ChangeEvent e) { + final PageState state = e.getPageState(); + final Object key = BaseTree.this.getSelectedKey(state); + + if (key != null) { + expand(key.toString(), state); + } + } + } + + private class TreeExpansion implements TreeExpansionListener { + public final void treeExpanded(final TreeExpansionEvent e) { + //s_log.error("expanded"); + } + + public final void treeCollapsed(final TreeExpansionEvent e) { + //s_log.error("collapsed"); + } + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/BrowsePane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/BrowsePane.java.off new file mode 100755 index 000000000..357e89738 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/BrowsePane.java.off @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2001-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.ui; + +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Resettable; +import com.arsdigita.bebop.SegmentedPanel; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormSubmissionListener; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ui.folder.FolderRequestLocal; +import com.arsdigita.cms.ui.folder.FolderSelectionModel; +import com.arsdigita.cms.ui.folder.FolderTreeModelBuilder; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.toolbox.ui.LayoutPanel; +import com.arsdigita.util.Assert; +import com.arsdigita.web.Web; + +import java.math.BigDecimal; + +import org.apache.log4j.Logger; +import org.libreccm.categorization.Category; +import org.libreccm.core.CcmObject; +import org.librecms.CmsConstants; + +/** + * A pane that contains a folder tree on the left and a folder manipulator on + * the right. It is a part of the content section main page and is displayed as + * the "Browse" tab. + * + * @author David LutterKort <dlutter@redhat.com> + * @version $Id: BrowsePane.java 1325 2006-09-22 08:11:33Z sskracic $ + */ +public class BrowsePane extends LayoutPanel implements Resettable { + + private static final Logger s_log = Logger.getLogger(BrowsePane.class); + + private final BaseTree m_tree; + private final SingleSelectionModel m_model; + private final FolderSelectionModel m_folderModel; // To support legacy UI code + private final FolderRequestLocal m_folder; + private final FlatItemList m_fil; + + public BrowsePane() { + + /* The folder tree displayed on the left side / left column */ + m_tree = new BaseTree(new FolderTreeModelBuilder()); + m_model = m_tree.getSelectionModel(); + m_folderModel = new FolderSelectionModel(m_model); + m_folder = new FolderRequestLocal(m_folderModel); + + final SegmentedPanel left = new SegmentedPanel(); + setLeft(left); + + final Label heading = new Label( + new GlobalizedMessage("cms.ui.folder_browser", + CmsConstants.CMS_FOLDER_BUNDLE)); + left.addSegment(heading, m_tree); + + m_fil = new FlatItemList(m_folder, m_folderModel); + setBody(m_fil); + + m_fil.getManipulator().getItemView().addProcessListener( + new ProcessListener()); + m_fil.getManipulator().getTargetSelector().addProcessListener( + new ProcessListener()); + m_fil.getManipulator().getTargetSelector().addSubmissionListener( + new SubmissionListener()); + } + + @Override + public final void register(Page page) { + super.register(page); + + page.addActionListener(new FolderListener()); + page.addActionListener(new TreeListener()); + } + + @Override + public final void reset(PageState state) { + super.reset(state); + + m_fil.reset(state); + } + + // Private classes and methods + /** + * + */ + private final class ProcessListener implements FormProcessListener { + + /** + * + * @param e + */ + public final void process(final FormSectionEvent e) { + final PageState state = e.getPageState(); + + if (e.getSource() == m_fil.getManipulator().getItemView()) { + // Hide everything except for the flat item list + m_tree.setVisible(state, false); + } else if (e.getSource() == m_fil.getManipulator() + .getTargetSelector()) { + m_tree.setVisible(state, true); + } + } + + } + + private final class SubmissionListener implements FormSubmissionListener { + + public final void submitted(final FormSectionEvent e) { + final PageState s = e.getPageState(); + + if (e.getSource() == m_fil.getManipulator().getTargetSelector()) { + if (!m_fil.getManipulator().getTargetSelector().isVisible(s)) { + m_tree.setVisible(s, true); + } + } + } + + } + + private final class FolderListener implements ActionListener { + + public final void actionPerformed(final ActionEvent e) { + final PageState state = e.getPageState(); + + if (!m_model.isSelected(state)) { + final String folder = state.getRequest().getParameter( + ContentSectionPage.SET_FOLDER); + + if (folder == null) { + final Category root = CMS.getContext().getContentSection() + .getRootDocumentsFolder(); + Long folderID = root.getObjectId(); + + /* + ToDo + User user = Web.getWebContext().getUser(); + if (user != null) { + Folder homeFolder = Folder.getUserHomeFolder( + user, CMS.getContext().getContentSection()); + if (homeFolder != null) { + folderID = homeFolder.getID(); + } + + }*/ + m_model.setSelectedKey(state, folderID); + } else { + m_model.setSelectedKey(state, folder); + } + } + } + + } + + private final class TreeListener implements ActionListener { + + public final void actionPerformed(final ActionEvent e) { + final PageState state = e.getPageState(); + + if (Assert.isEnabled()) { + Assert.isTrue(m_model.isSelected(state)); + } + + final Category root = CMS.getContext().getContentSection() + .getRootDocumentsFolder(); + + if (!root.equals(m_folder.getFolder(state))) { + // Expand the ancestor nodes of the currently + // selected node. + + CcmObject object = m_folder.getFolder(state); + + while (object != null) { + if (object instanceof Category) { + final Category category = (Category) object; + + if (category.getParent().isPresent()) { + final CcmObject result = category.getParent().get(); + + if (result instanceof Category) { + object = result; + m_tree.expand( + ((Long) object.getObjectId()).toString(), + state); + } else { + object = null; + } + } else { + object = null; + } + + } else { + object = null; + } + } + } + } + + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/CcmObjectRequestLocal.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/CcmObjectRequestLocal.java new file mode 100755 index 000000000..db03a326c --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/CcmObjectRequestLocal.java @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2003-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.ui; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.RequestLocal; + +import org.apache.log4j.Logger; +import org.libreccm.core.CcmObject; + + +/** + * + * @version $Id$ + */ +public class CcmObjectRequestLocal extends RequestLocal { + + private static final Logger s_log = Logger.getLogger + (CcmObjectRequestLocal.class); + + public final CcmObject getACSObject(final PageState state) { + return (CcmObject) get(state); + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionContextBar.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionContextBar.java.off new file mode 100755 index 000000000..252c6df83 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionContextBar.java.off @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2003-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.ui; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ContentBundle; +import com.arsdigita.cms.ContentItem; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.ContentType; +import com.arsdigita.cms.Folder; +import com.arsdigita.cms.PageLocations; +import com.arsdigita.cms.Template; +import com.arsdigita.kernel.ACSObject; +import com.arsdigita.web.ParameterMap; +import com.arsdigita.web.URL; + +import java.math.BigDecimal; +import java.util.List; +import java.util.Stack; + +import org.apache.log4j.Logger; + +/** + * The context bar of the content section UI. + * + * @author Justin Ross <jross@redhat.com> + * @version $Id: ContentSectionContextBar.java 287 2005-02-22 00:29:02Z sskracic $ + */ +// class ContentSectionContextBar extends WorkspaceContextBar { +public class ContentSectionContextBar extends WorkspaceContextBar { + + private static final Logger s_log = Logger.getLogger + (ContentSectionContextBar.class); + + @Override + protected List entries(final PageState state) { + + /* Include breadcrumb entries already set by content-center (i.e. the + * URL of the content center itself */ + final List entries = super.entries(state); + + final ContentSection section = CMS.getContext().getContentSection(); + final Stack folderEntryStack = new Stack(); + String currentFolderLabel = null; + ParameterMap params = new ParameterMap(); + boolean isTemplate = false; + BigDecimal templateID = null; + + if (CMS.getContext().hasContentItem()) { + final ContentItem item = CMS.getContext().getContentItem(); + if (item == null) { + s_log.warn("item is null"); + } else if(item.getContentType() == null) { + s_log.warn("item.getContentType() returns null. item.class.getName(): " + + item.getClass().getName()); + } + isTemplate = + item.getContentType().equals(ContentType + .findByAssociatedObjectType(Template.BASE_DATA_OBJECT_TYPE)); + if (isTemplate) { + templateID = item.getID(); + } + ACSObject parent = item.getParent(); + + while (!isTemplate && parent != null && parent instanceof ContentItem) { + if (currentFolderLabel != null) { + final URL folderURL = URL.there + (state.getRequest(), + section.getPath() + "/" + PageLocations.SECTION_PAGE, + params); + folderEntryStack.push(new Entry(currentFolderLabel, folderURL)); + currentFolderLabel = null; + params = new ParameterMap(); + } + final ContentItem pitem = (ContentItem) parent; + + if (pitem instanceof Folder) { + final Folder folder = (Folder) pitem; + parent = folder.getParent(); + + currentFolderLabel = folder.getLabel(); + if (parent != null || folder.equals(section.getRootFolder())) { + params.setParameter + (ContentSectionPage.SET_FOLDER, folder.getID()); + } + } else if (pitem instanceof ContentBundle) { + final ACSObject ppitem = pitem.getParent(); + + if (ppitem != null && ppitem instanceof Folder) { + final Folder folder = (Folder) ppitem; + + parent = folder.getParent(); + currentFolderLabel = folder.getLabel(); + if (parent != null || folder.equals(section + .getRootFolder())) { + params.setParameter + (ContentSectionPage.SET_FOLDER, folder.getID()); + } + } else { + parent = null; + } + } else { + parent = null; + } + } + + } + + if (isTemplate) { + params.setParameter + ( ContentSectionPage.SET_TAB, + new BigDecimal(ContentSectionPage.CONTENTTYPES_TAB) ); + params.setParameter(ContentSectionPage.SET_TEMPLATE, templateID); + } + // add section-level entry. if this is for an item page, the URL + // will be for the root folder. + final URL url = URL.there + (state.getRequest(), + section.getPath() + "/" + PageLocations.SECTION_PAGE, + params); + + + final String sectionTitle = lz("cms.ui.content_section"); + final String title = sectionTitle + ": " + section.getName(); + + entries.add(new Entry(title, url)); + + // add any folders to the path now + while (!folderEntryStack.empty()) { + entries.add(folderEntryStack.pop()); + } + + return entries; + } + + private static String lz(final String key) { + return (String) ContentSectionPage.globalize(key).localize(); + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java.off new file mode 100755 index 000000000..6b708faf5 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ContentSectionPage.java.off @@ -0,0 +1,524 @@ +/* + * Copyright (C) 2001-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.ui; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SimpleComponent; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.TabbedPane; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.cms.CMS; + +import org.librecms.contentsection.ContentItem; +import org.librecms.contentsection.ContentSection; + +import com.arsdigita.cms.dispatcher.CMSPage; +import com.arsdigita.cms.ui.category.CategoryAdminPane; +import com.arsdigita.cms.ui.cse.ContentSoonExpiredPane; +import com.arsdigita.cms.ui.folder.FolderAdminPane; +import com.arsdigita.cms.ui.lifecycle.LifecycleAdminPane; +import com.arsdigita.cms.ui.role.RoleAdminPane; +import com.arsdigita.cms.ui.type.ContentTypeAdminPane; +import com.arsdigita.cms.ui.workflow.WorkflowAdminPane; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.toolbox.ui.LayoutPanel; +import com.arsdigita.util.Assert; +import com.arsdigita.web.Web; + +import javax.servlet.http.HttpServletRequest; + +import org.apache.log4j.Logger; +import org.arsdigita.cms.CMSConfig; +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.security.PermissionChecker; +import org.librecms.CmsConstants; +import org.librecms.contentsection.ContentItemVersion; +import org.librecms.contentsection.ContentSectionConfig; + +/** + * Contains the entire admin UI for a content section. + * + * Developers Note: It is based on the dispatcher model is is going to be + * replaced by the newer servlet based model. @see + * c.ad.cms.ui.contentsection.MainPage (currently not active). + * + * @author Jack Chung + * @author Michael Pih + * @author Xixi D'Moon <xdmoon@redhat.com> + * @author Justin Ross <jross@redhat.com> + * @version $Id: ContentSectionPage.java 2224 2011-08-01 07:45:23Z pboy $ + */ +public class ContentSectionPage extends CMSPage implements ActionListener { + + private static final Logger s_log = Logger.getLogger( + ContentSectionPage.class); + public static final String RESOURCE_BUNDLE + = "com.arsdigita.cms.CMSResources"; + /** + * The URL parameter that can be passed in in order to set the current + * folder. This is used in getting back to the correct level of folder + * expansion from content item page. + */ + public static final String SET_FOLDER = "set_folder"; + /** + * The URL parameter that can be passed in in order to set the current + * template (for setting the content type) + */ + public static final String SET_TEMPLATE = "set_template"; + /** + * The URL parameter that can be passed in in order to set the current tab. + * This is a KLUDGE right now because the TabbedDialog's current tab is + * selected with a local state parameter. + */ + public static final String SET_TAB = "set_tab"; + /** + * Index of the search tab + */ + public static final int SEARCH_TAB = 0; + /** + * Index of the browse tab + */ + public static final int BROWSE_TAB = 1; + /** + * Index of the roles tab + */ + public static final int ROLES_TAB = 2; + /** + * Index of the workflows tab + */ + public static final int WORKFLOW_TAB = 3; + /** + * Index of the lifecycles tab + */ + public static final int LIFECYCLES_TAB = 4; + /** + * Index of the categories tab + */ + public static final int CATEGORIES_TAB = 5; + /** + * Index of the content types tab + */ + public static final int CONTENTTYPES_TAB = 6; + public static final int USER_ADMIN_TAB = 7; + private TabbedPane m_tabbedPane; + private FolderAdminPane m_folderPane; + private BrowsePane m_browsePane; + private ItemSearch m_searchPane; + private ImagesPane m_imagesPane; + private RoleAdminPane m_rolePane; + private WorkflowAdminPane m_workflowPane; + private LifecycleAdminPane m_lifecyclePane; + private CategoryAdminPane m_categoryPane; + private ContentTypeAdminPane m_typePane; + //private LayoutPanel m_userAdminPane; + private LayoutPanel m_csePane; + private ReportPane m_reportPane; + + /** + * Creates the content section index page containing - a Navigaton bar for + * the various tasks (items, search, images, ....) - a breadcrumb - .... + * Contains the UI for administering a content section. + */ + public ContentSectionPage() { + super(new Label(new TitlePrinter()), new SimpleContainer()); + + setClassAttr("cms-admin"); + + add(new GlobalNavigation()); + add(new ContentSectionContextBar()); + + // Initialize the individual panes + m_folderPane = getFolderAdminPane(); + m_browsePane = getBrowsePane(); + m_searchPane = getSearchPane(); + m_imagesPane = getImagesPane(); + m_rolePane = getRoleAdminPane(); + m_workflowPane = getWorkflowAdminPane(); + m_lifecyclePane = getLifecycleAdminPane(); + m_categoryPane = getCategoryAdminPane(); + m_typePane = getContentTypeAdminPane(); + // userAdminPane removed, used to contain just one item (reset user + // folder) which moved to the FolderAdminPane + //m_userAdminPane = getUserAdminPane(); + m_csePane = getCSEPane(); + m_reportPane = getReportPane(); + + // The panes + m_tabbedPane = createTabbedPane(); + m_tabbedPane.setIdAttr("page-body"); + m_tabbedPane.addActionListener(this); + add(m_tabbedPane); + + addActionListener(new ActionListener() { + + @Override + public final void actionPerformed(ActionEvent e) { + final PageState state = e.getPageState(); + + final String tab = state.getRequest().getParameter(SET_TAB); + + if (tab != null) { + m_tabbedPane.setSelectedIndex(state, Integer.valueOf(tab) + .intValue()); + } + + final PermissionChecker permissionChecker = CdiUtil + .createCdiUtil().findBean(PermissionChecker.class); + + //m_tabbedPane.setTabVisible(state, m_userAdminPane, sm.canAccess(user, SecurityConstants.STAFF_ADMIN)); + if (CMSConfig.getConfig().isHideAdminTabs()) { + m_tabbedPane.setTabVisible( + state, + m_workflowPane, + permissionChecker.isPermitted( + CmsConstants.PRIVILEGE_ADMINISTER_WORKFLOW)); + m_tabbedPane.setTabVisible( + state, m_categoryPane, + permissionChecker.isPermitted( + CmsConstants.PRIVILEGE_ADMINISTER_CATEGORIES)); + m_tabbedPane.setTabVisible( + state, + m_lifecyclePane, + permissionChecker.isPermitted( + CmsConstants.PRIVILEGE_ADMINISTER_LIFECYLES)); + m_tabbedPane.setTabVisible( + state, + m_typePane, + permissionChecker.isPermitted( + CmsConstants.PRIVILEGE_ADMINISTER_CONTENT_TYPES)); + m_tabbedPane.setTabVisible( + state, + m_rolePane, + permissionChecker.isPermitted( + CmsConstants.PRIVILEGE_ADMINISTER_ROLES)); + // csePane: should check permission + m_tabbedPane.setTabVisible(state, m_csePane, true); + // TODO Check for reportPane as well + } + } + + }); + } + + /** + * Creates, and then caches, the browse pane. Overriding this method to + * return null will prevent this tab from appearing. + * @return + */ + protected FolderAdminPane getFolderAdminPane() { + if (m_folderPane == null) { + m_folderPane = new FolderAdminPane(); + } + return m_folderPane; + } + + /** + * Creates, and then caches, the browse pane. Overriding this method to + * return null will prevent this tab from appearing. + * + * @return + */ + protected BrowsePane getBrowsePane() { + if (m_browsePane == null) { + m_browsePane = new BrowsePane(); + } + return m_browsePane; + } + + /** + * Creates, and then caches, the search pane. Overriding this method to + * return null will prevent this tab from appearing. + * @return + */ + protected ItemSearch getSearchPane() { + if (m_searchPane == null) { + m_searchPane + = new ItemSearch( + ContentItemVersion.DRAFT.toString(), + CMSConfig.getConfig().isLimitItemSearchToContentSection()); + } + return m_searchPane; + } + + protected ImagesPane getImagesPane() { + if (m_imagesPane == null) { + m_imagesPane = new ImagesPane(); + } + return m_imagesPane; + } + + protected RoleAdminPane getRoleAdminPane() { + if (m_rolePane == null) { + m_rolePane = new RoleAdminPane(); + } + return m_rolePane; + } + + /** + * Creates, and then caches, the workflow administration pane. Overriding + * this method to return null will prevent this tab from appearing. + */ + protected WorkflowAdminPane getWorkflowAdminPane() { + if (m_workflowPane == null) { + m_workflowPane = new WorkflowAdminPane(); + } + return m_workflowPane; + } + + /** + * Creates, and then caches, the lifecycle administration pane. Overriding + * this method to return null will prevent this tab from appearing. + */ + protected LifecycleAdminPane getLifecycleAdminPane() { + if (m_lifecyclePane == null) { + m_lifecyclePane = new LifecycleAdminPane(); + } + return m_lifecyclePane; + } + + /** + * Creates, and then caches, the category administration pane. Overriding + * this method to return null will prevent this tab from appearing. + */ + protected CategoryAdminPane getCategoryAdminPane() { + if (m_categoryPane == null) { + m_categoryPane = new CategoryAdminPane(); + } + return m_categoryPane; + } + + /** + * Creates, and then caches, the content type administration pane. + * Overriding this method to return null will prevent this tab from + * appearing. + */ + protected ContentTypeAdminPane getContentTypeAdminPane() { + if (m_typePane == null) { + m_typePane = new ContentTypeAdminPane(); + } + return m_typePane; + } + +// protected LayoutPanel getUserAdminPane() { +// if (m_userAdminPane == null) { +// m_userAdminPane = new LayoutPanel(); +// m_userAdminPane.setLeft(new SimpleComponent()); +// m_userAdminPane.setBody(new UserAdminPane()); +// } +// return m_userAdminPane; +// } + protected LayoutPanel getCSEPane() { + if (m_csePane == null) { + m_csePane = new LayoutPanel(); + m_csePane.setLeft(new SimpleComponent()); + m_csePane.setBody(new ContentSoonExpiredPane()); + } + return m_csePane; + } + + protected ReportPane getReportPane() { + if (m_reportPane == null) { + m_reportPane = new ReportPane(); + } + return m_reportPane; + } + + /** + * Adds the specified component, with the specified tab name, to the tabbed + * pane only if it is not null. + * + * @param pane The pane to which to add the tab + * @param tabName The name of the tab if it's added + * @param comp The component to add to the pane + */ + protected void addToPane(TabbedPane pane, String tabName, Component comp) { + if (comp != null) { + pane.addTab(new Label(tabName), comp); + } + } + + private void tab(final TabbedPane pane, + final String key, + final Component tab) { + if (tab != null) { + pane.addTab(new Label(gz(key)), tab); + } + } + + /** + *

+ * Created the TabbedPane to use for this page. Adds the tabs to the pane. + * The default implementation uses a {@link + * com.arsdigita.bebop.TabbedPane}. This implementation also adds browse, + * search, staff admin, viewers admin, workflow admin, category admin, and + * content type panes.

+ * + *

+ * Developers can override this method to add only the tabs they want, or to + * add additional tabs after the default CMS tabs are added.

+ * + * @return + */ + protected TabbedPane createTabbedPane() { + final TabbedPane pane = new TabbedPane(); + + //tab(pane, "cms.ui.folders", getFolderAdminPane()); + tab(pane, "cms.ui.browse", getBrowsePane()); + tab(pane, "cms.ui.search", getSearchPane()); + tab(pane, "cms.ui.images", getImagesPane()); + tab(pane, "cms.ui.roles", getRoleAdminPane()); + tab(pane, "cms.ui.workflows", getWorkflowAdminPane()); + tab(pane, "cms.ui.lifecycles", getLifecycleAdminPane()); + tab(pane, "cms.ui.categories", getCategoryAdminPane()); + tab(pane, "cms.ui.content_types", getContentTypeAdminPane()); + // user admin tab removed from tab bar and the only one widget there + // (reset home folder) moved to folder browser + // tab(pane, "cms.ui.user_admin", getUserAdminPane()); + tab(pane, "cms.ui.cse", getCSEPane()); + //if (DbHelper.getDatabase() == DbHelper.DB_ORACLE) { + tab(pane, "cms.ui.reports", getReportPane()); + //} + + return pane; + } + + /** + * Fetch the request-local content section. + * + * @param request The HTTP request + * + * @return The current content section + */ + @Override + public ContentSection getContentSection(HttpServletRequest request) { + // Resets all content sections associations. + ContentSection section = super.getContentSection(request); + Assert.exists(section); + return section; + } + + /** + * When a new tab is selected, reset the state of the formerly-selected + * pane. + * + * @param event The event fired by selecting a tab + */ + @Override + public void actionPerformed(ActionEvent event) { + final PageState state = event.getPageState(); + + final Component pane = m_tabbedPane.getCurrentPane(state); + + if (pane == m_searchPane) { + m_searchPane.reset(state); + } else if (pane == m_imagesPane) { + m_imagesPane.reset(state); + } else if (pane == m_folderPane) { + m_folderPane.reset(state); + } else if (pane == m_browsePane) { + m_browsePane.reset(state); + } else if (pane == m_rolePane) { + m_rolePane.reset(state); + } else if (pane == m_workflowPane) { + m_workflowPane.reset(state); + } else if (pane == m_lifecyclePane) { + m_lifecyclePane.reset(state); + } else if (pane == m_categoryPane) { + m_categoryPane.reset(state); + } else if (pane == m_typePane) { + m_typePane.reset(state); +// } else if (pane == m_userAdminPane) { + //m_userAdminPane.reset(state); + } else if (pane == m_csePane) { + //m_csePane.reset(state); + } + } + + /** + * Construct a URL for displaying the tab + * + * @param item The item from which we get the corresponding content section + * @param tab The index of the tab to display + * + * @return + */ + public static String getSectionURL(ContentItem item, int tab) { + // Get the content section associated with the content item. + ContentSection section = ContentSection.getContentSection(item); + + String url = section.getURL() + PageLocations.SECTION_PAGE + + "?" + SET_TAB + "=" + tab; + + return url; + } + + private static GlobalizedMessage gz(final String key) { + return new GlobalizedMessage(key, RESOURCE_BUNDLE); + } + + /** + * Getting the GlobalizedMessage using a CMS Class targetBundle. + * + * @param key The resource key + * + * @return + * + * @pre key != null + */ + public static GlobalizedMessage globalize(final String key) { + return new GlobalizedMessage(key, RESOURCE_BUNDLE); + } + + /** + * + * @param key + * @param args + * + * @return + */ + public static GlobalizedMessage globalize(final String key, + final Object[] args) { + return new GlobalizedMessage(key, RESOURCE_BUNDLE, args); + } + + /** + * Helper class to be able to use a PrintListener to set the titel of the + * page. + */ + private static class TitlePrinter implements PrintListener { + + /** + * + * @param e + */ + @Override + public void prepare(PrintEvent e) { + final Label l = (Label) e.getTarget(); + + l.setLabel(CMS.getContext().getContentSection().getName()); + } + + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/FlatItemList.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/FlatItemList.java.off new file mode 100755 index 000000000..147b504e3 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/FlatItemList.java.off @@ -0,0 +1,604 @@ +/* + * Copyright (C) 2001-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.ui; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.Resettable; +import com.arsdigita.bebop.SegmentedPanel; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.FormSubmissionListener; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.cms.CMS; +import org.librecms.contentsection.ContentSection; +import com.arsdigita.cms.dispatcher.Utilities; +import com.arsdigita.cms.ui.authoring.CreationSelector; +import com.arsdigita.cms.ui.authoring.NewItemForm; +import com.arsdigita.cms.ui.folder.FolderCreator; +import com.arsdigita.cms.ui.folder.FolderEditor; +import com.arsdigita.cms.ui.folder.FolderManipulator; +import com.arsdigita.cms.ui.folder.FolderRequestLocal; +import com.arsdigita.cms.ui.folder.FolderSelectionModel; +import com.arsdigita.cms.ui.folder.ItemPath; +import com.arsdigita.cms.ui.permissions.CMSPermissionsPane; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.kernel.ACSObject; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.User; +import com.arsdigita.kernel.permissions.ObjectPermissionCollection; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.persistence.DataObject; +import com.arsdigita.persistence.DataQuery; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.util.Assert; +import com.arsdigita.web.Web; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * Encapsulates a {@link FolderManipulator} in order to create a flat item + * listing. Also contains a new item form. + * + * @author Stanislav Freidin + * @version $Id: FlatItemList.java 1538 2007-03-23 16:26:36Z apevec $ + */ +public class FlatItemList extends SegmentedPanel + implements FormProcessListener, ChangeListener, FormSubmissionListener, + Resettable, ActionListener { + + private static final String CONTENT_TYPE_ID = "ct"; + private static final String CMS_PRIVILEGES = "com.arsdigita.cms.getPrivileges"; + private static final String PRIVILEGE = "privilege"; + private static final String PRIVILEGE_NAME = "prettyName"; + // The folder selectors + private final FolderSelectionModel m_folderSel; + private FolderRequestLocal m_folder; + private final NewItemForm m_newItem; + private final SingleSelectionModel m_typeSel; + private final CreationSelector m_selector; + private final FolderManipulator m_folderManip; + private final FolderCreator m_folderCreator; + private final ActionLink m_setHomeFolderAction; + private final ActionLink m_removeHomeFolderAction; + private final ActionLink m_createFolderAction; + private final ActionLink m_togglePrivateAction; + private final Label m_homeFolderLabel; + private final Segment m_browseSeg; + private final Segment m_newItemSeg; + private final Segment m_newFolderSeg; + private final Segment m_editFolderSeg; + private final Segment m_permissionsSeg; + private final CMSPermissionsPane m_permPane; + // Folder edit/rename functionality. + private final ActionLink m_editFolderAction; + private final FolderEditor m_folderEditor; + private final Label m_contentLabel; + private final ItemPath m_itemPath; + private final Label m_chooseLabel; + + /** + * Construct a new item listing pane. The provided folder selection model + * is used to keep track of the currently displayed folder. + * + * @param folder + * @param model maintains the currently displayed folder. + */ + public FlatItemList(final FolderRequestLocal folder, + final FolderSelectionModel model) { + m_folder = folder; + m_folderSel = model; + m_folderSel.addChangeListener(new ChangeListener() { + @Override + public void stateChanged(ChangeEvent e) { + PageState s = e.getPageState(); + reset(s); + } + + }); + + setIdAttr("flat-item-list"); + + m_newItemSeg = addSegment(); + m_newItemSeg.setIdAttr("folder-new-item"); + + m_newFolderSeg = addSegment(); + m_newFolderSeg.setIdAttr("folder-new-folder"); + + m_editFolderSeg = addSegment(); + m_editFolderSeg.setIdAttr("folder-edit-folder"); + + m_browseSeg = addSegment(); + m_browseSeg.setIdAttr("folder-browse"); + + final ActionGroup browseActions = new ActionGroup(); + m_browseSeg.add(browseActions); + + // The top 'browse' segment + m_contentLabel = new Label(globalize("cms.ui.contents_of"), false); + m_browseSeg.addHeader(m_contentLabel); + m_chooseLabel = new Label(globalize("cms.ui.choose_target_folder"), false); + m_browseSeg.addHeader(m_chooseLabel); + m_itemPath = new ItemPath(m_folderSel); + //m_itemPath = new Label(new PrintListener() { + // public final void prepare(final PrintEvent e) { + // final Folder f = m_folder.getFolder(e.getPageState()); + // ((Label) e.getTarget()).setLabel(f.getDisplayName()); + // } + // }); + + m_browseSeg.addHeader(m_itemPath); + m_folderManip = new FolderManipulator(m_folderSel); + m_folderManip.getItemView().addProcessListener(this); + m_folderManip.getTargetSelector().addProcessListener(this); + m_folderManip.getTargetSelector().addSubmissionListener(this); + + browseActions.setSubject(m_folderManip); + + // The actions + + m_createFolderAction = new ActionLink(new Label(globalize("cms.ui.new_folder"))); + m_createFolderAction.addActionListener(this); + browseActions.addAction(m_createFolderAction); + + m_editFolderAction = new ActionLink(new Label(globalize("cms.ui.edit_folder"))); + m_editFolderAction.addActionListener(this); + browseActions.addAction(m_editFolderAction); + + m_setHomeFolderAction = new ActionLink(new Label(globalize("cms.ui.set_home_folder"))); + m_setHomeFolderAction.addActionListener(this); + browseActions.addAction(m_setHomeFolderAction); + + m_homeFolderLabel = new Label(new PrintListener() { + @Override + public final void prepare(final PrintEvent e) { + Label label = (Label) e.getTarget(); + User user = Web.getWebContext().getUser(); + + Folder folder = Folder.getUserHomeFolder(user, CMS.getContext().getContentSection()); + if (folder != null) { + String url = folder.getContentSection().getURL() + PageLocations.SECTION_PAGE + "?" + + ContentSectionPage.SET_FOLDER + "=" + folder.getID(); + //label.setLabel("Go to home folder: " + folder.getLabel() + ""); + String[] parts = new String[3]; + parts[0] = ""; + parts[1] = url; + parts[2] = folder.getLabel(); + // label.setLabel(String.format("%s: %s", + // (String) globalize("cms.ui.go_to_home_folder").localize(), + // url, + // folder.getLabel())); + label.setLabel( globalize("cms.ui.go_to_home_folder",parts) ); + } else { + //label.setLabel("No home folder selected"); + String[] parts = new String[3]; + parts[0] = ""; + parts[1] = ""; + //label.setLabel(String.format("%s", + // (String)globalize("cms.ui.no_home_folder_selected").localize())); + label.setLabel( globalize("cms.ui.no_home_folder_selected",parts) ); + } + label.setOutputEscaping(false); + } + + }); + browseActions.addAction(m_homeFolderLabel); + + m_removeHomeFolderAction = new ActionLink(new Label(globalize("cms.ui.remove_home_folder"))); + m_removeHomeFolderAction.addActionListener(this); + browseActions.addAction(m_removeHomeFolderAction); + + /* */ + m_newItem = new SectionNewItemForm("newItem"); + m_newItem.addProcessListener(this); + browseActions.addAction(m_newItem); + + /* permission */ + m_permissionsSeg = addSegment(); + m_permissionsSeg.setIdAttr("folder-permissions"); + + final ActionGroup permActions = new ActionGroup(); + m_permissionsSeg.add(permActions); + + // The permissions segment + m_permissionsSeg.addHeader(new Label(GlobalizationUtil.globalize("cms.ui.permissions"))); + + List privs = new ArrayList(); + Map privNameMap = new HashMap(); + DataQuery query = SessionManager.getSession().retrieveQuery(CMS_PRIVILEGES); + query.addFilter("scope != 'section'"); + query.addOrder("sortOrder"); + while (query.next()) { + String privilege = (String) query.get(PRIVILEGE); + String privilegeName = (String) query.get(PRIVILEGE_NAME); + privs.add(PrivilegeDescriptor.get(privilege)); + privNameMap.put(privilege, privilegeName); + } + query.close(); + + m_permPane = + new CMSPermissionsPane((PrivilegeDescriptor[]) privs.toArray(new PrivilegeDescriptor[privs.size()]), + privNameMap, + m_folderSel); + permActions.setSubject(m_permPane); + + // An action + + m_togglePrivateAction = new ActionLink(new Label(new PrintListener() { + public void prepare(PrintEvent e) { + PageState state = e.getPageState(); + Label target = (Label) e.getTarget(); + Folder currentFolder = m_folder.getFolder(state); + // ACSObject parent = currentFolder.getParent(); + DataObject context = PermissionService.getContext(currentFolder); + if (context == null) { + target.setLabel(GlobalizationUtil + .globalize("cms.ui.restore_default_permissions")); + } else { + target.setLabel(GlobalizationUtil + .globalize("cms.ui.use_custom_permissions")); + } + } + + })); + m_togglePrivateAction.addActionListener(this); + permActions.addAction(m_togglePrivateAction); + + // The 'new item' segment + m_newItemSeg.addHeader(new Label(globalize("cms.ui.new_item"))); + m_typeSel = new ParameterSingleSelectionModel(new BigDecimalParameter(CONTENT_TYPE_ID)); + m_typeSel.addChangeListener(this); + + m_selector = new CreationSelector(m_typeSel, m_folderSel); + m_newItemSeg.add(m_selector); + //m_newItemSeg.add(new Label("
", false)); + + // The 'new folder' segment + m_newFolderSeg.addHeader(new Label(globalize("cms.ui.new_folder"))); + Form folderCreate = new Form("fcreat"); + m_folderCreator = new FolderCreator("fcreat", m_folderSel); + m_folderCreator.addSubmissionListener(this); + m_folderCreator.addProcessListener(this); + folderCreate.add(m_folderCreator); + m_newFolderSeg.add(folderCreate); + m_newFolderSeg.add(new Label("
", false)); + + m_editFolderSeg.addHeader(new Label(globalize("cms.ui.edit_folder"))); + m_folderEditor = new FolderEditor("fedit", m_folderSel); + m_folderEditor.addSubmissionListener(this); + m_folderEditor.addProcessListener(this); + + Form folderEditorForm = new Form("fedit_form"); + folderEditorForm.add(m_folderEditor); + m_editFolderSeg.add(folderEditorForm); + m_editFolderSeg.add(new Label("
", false)); + } + + @Override + public void register(Page p) { + super.register(p); + + p.setVisibleDefault(m_chooseLabel, false); + p.setVisibleDefault(m_newItemSeg, false); + p.setVisibleDefault(m_newFolderSeg, false); + p.setVisibleDefault(m_editFolderSeg, false); + + p.addComponentStateParam(this, m_typeSel.getStateParameter()); + + p.addActionListener(new ActionListener() { + @Override + public void actionPerformed(ActionEvent e) { + final PageState state = e.getPageState(); + + if (state.isVisibleOnPage(FlatItemList.this)) { + showHideSegments(state); + } + } + + }); + } + + /** + * Show/hide segments based on access checks. + * + * @param state The page state + * @pre ( state != null ) + */ + private void showHideSegments(PageState state) { + SecurityManager sm = Utilities.getSecurityManager(state); + Folder folder = m_folder.getFolder(state); + Assert.exists(folder); + + // MP: This should be checked on the current folder instead of just + // the content section. + boolean newItem = + sm.canAccess(state.getRequest(), + SecurityManager.NEW_ITEM, + folder); + + if (!newItem) { + browseMode(state); + } + m_createFolderAction.setVisible(state, newItem); + m_newItem.setVisible(state, newItem); + + final boolean editItem = sm.canAccess(state.getRequest(), + SecurityManager.EDIT_ITEM, + folder); + + m_editFolderAction.setVisible(state, editItem); + + User user = (User) Kernel.getContext().getParty(); + PermissionDescriptor perm = + new PermissionDescriptor(PrivilegeDescriptor.ADMIN, + folder, + user); + + if (PermissionService.checkPermission(perm)) { + m_permissionsSeg.setVisible(state, true); + } else { + m_permissionsSeg.setVisible(state, false); + } + } + + private void browseMode(PageState s) { + m_browseSeg.setVisible(s, true); + m_permissionsSeg.setVisible(s, true); + m_chooseLabel.setVisible(s, false); + m_contentLabel.setVisible(s, true); + m_itemPath.setVisible(s, true); + m_newItemSeg.setVisible(s, false); + m_newFolderSeg.setVisible(s, false); + m_editFolderSeg.setVisible(s, false); + + m_typeSel.clearSelection(s); + } + + private void newItemMode(PageState s) { + m_permissionsSeg.setVisible(s, false); + m_newItemSeg.setVisible(s, true); + } + + private void newFolderMode(PageState s) { + m_permissionsSeg.setVisible(s, false); + m_newFolderSeg.setVisible(s, true); + } + + @Override + public void submitted(FormSectionEvent e) + throws FormProcessException { + PageState s = e.getPageState(); + if (e.getSource() == m_folderCreator + && m_folderCreator.isCancelled(s)) { + browseMode(s); + throw new FormProcessException(GlobalizationUtil.globalize("cms.ui.cancelled")); + } else if (e.getSource() == m_folderEditor && m_folderEditor.isCancelled(s)) { + browseMode(s); + throw new FormProcessException(GlobalizationUtil.globalize("cms.ui.cancelled")); + } else if (e.getSource() == m_folderManip.getTargetSelector()) { + // This only works if this submission listener is run + // after the target selector's one + if (!m_folderManip.getTargetSelector().isVisible(s)) { + browseMode(s); + } + } + } + + @Override + public void process(FormSectionEvent e) { + PageState s = e.getPageState(); + final Object source = e.getSource(); + if (source == m_newItem) { + BigDecimal typeID = m_newItem.getTypeID(s); + m_typeSel.setSelectedKey(s, typeID); + newItemMode(s); + } else if (source == m_folderCreator || source == m_folderEditor) { + browseMode(s); + } else if (source == m_folderManip.getItemView()) { + // Hide everything except for the browseSeg + m_permissionsSeg.setVisible(s, false); + m_chooseLabel.setVisible(s, true); + m_contentLabel.setVisible(s, false); + m_itemPath.setVisible(s, false); + } else if (source == m_folderManip.getTargetSelector()) { + browseMode(s); + } + } + + @Override + public void stateChanged(ChangeEvent e) { + PageState s = e.getPageState(); + if (e.getSource().equals(m_typeSel)) { + if (!m_typeSel.isSelected(s)) { + browseMode(s); + } + } + } + + @Override + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + Object source = e.getSource(); + if (source == m_createFolderAction) { + newFolderMode(s); + } else if (source == m_editFolderAction) { + m_permissionsSeg.setVisible(s, false); + m_editFolderSeg.setVisible(s, true); + } else if (source == m_togglePrivateAction) { + togglePermissions(s); + } else if (source == m_setHomeFolderAction) { + User user = Web.getWebContext().getUser(); + Folder folder = m_folder.getFolder(s); + user = (User) DomainObjectFactory.newInstance(user.getOID()); + Folder.setUserHomeFolder(user, folder); + } else if( source == m_removeHomeFolderAction) { + User user = Web.getWebContext().getUser(); + ContentSection section = CMS.getContext().getContentSection(); + UserHomeFolderMap map = UserHomeFolderMap.findUserHomeFolderMap(user, section); + if (map != null) { + map.delete(); + } + } + } + + private void togglePermissions(PageState state) { + Folder currentFolder = m_folder.getFolder(state); + if (!Utilities.getSecurityManager(state).canAccess(state.getRequest(), SecurityManager.STAFF_ADMIN)) { + throw new com.arsdigita.cms.dispatcher.AccessDeniedException(); + } + DataObject context = PermissionService.getContext(currentFolder); + if (context != null) { + PermissionService.clonePermissions(currentFolder); + Folder liveFolder = (Folder) currentFolder.getLiveVersion(); + if (liveFolder != null) { + PermissionService.setContext(liveFolder, currentFolder); + } + } else { + ACSObject parent = currentFolder.getParent(); + if (parent != null) { + PermissionService.setContext(currentFolder, parent); + } else { + // if the folder has no parent, it must be a root folder or template folder + // in this case, set it's context to the ContentSection + ContentSection section = currentFolder.getContentSection(); + if (section != null) { + PermissionService.setContext(currentFolder, section); + } else { + throw new IllegalStateException("Cannot set the context for a folder with " + + "no parent and no Content Section"); + } + } + + Folder liveVersion = (Folder) currentFolder.getLiveVersion(); + if (liveVersion != null) { + ACSObject liveParent = liveVersion.getParent(); + if (liveParent != null) { + PermissionService.setContext(liveVersion, liveParent); + } else { + ContentSection liveSection = liveVersion.getContentSection(); + if (liveSection != null) { + PermissionService.setContext(liveVersion, liveSection); + } else { + throw new IllegalStateException("Cannot set the context for a folder with " + + "no parent and no Content Section"); + } + } + } + + // revoke all direct permissions so folder will only have inherited permissions + ObjectPermissionCollection perms = PermissionService.getGrantedPermissions(currentFolder.getOID()); + while (perms.next()) { + if (!perms.isInherited() && !perms.getPrivilege().equals(PrivilegeDescriptor.ADMIN)) { + PermissionDescriptor desc = new PermissionDescriptor(perms.getPrivilege(), currentFolder.getOID(), + perms.getGranteeOID()); + PermissionService.revokePermission(desc); + } + } + + if (liveVersion != null) { + ObjectPermissionCollection livePerms = PermissionService.getGrantedPermissions(liveVersion.getOID()); + while (livePerms.next()) { + if (!livePerms.isInherited()) { + PermissionDescriptor desc2 = new PermissionDescriptor(livePerms.getPrivilege(), liveVersion. + getOID(), + livePerms.getGranteeOID()); + PermissionService.revokePermission(desc2); + } + } + } + + } + m_permPane.reset(state); + } + + @Override + public void reset(PageState s) { + browseMode(s); + m_folderManip.reset(s); + // switching between folders used to keep showing the permission pane + // in the same perm mode (direct or inherited) regardless + // of the folder status + m_permPane.reset(s); + } + + public final FolderManipulator getManipulator() { + return m_folderManip; + } + + public final CMSPermissionsPane getPermissionsPane() { + return m_permPane; + } + + public void setPermissionLinkVis(PageState state) { + if (!Utilities.getSecurityManager(state). + canAccess(state.getRequest(), SecurityManager.STAFF_ADMIN)) { + m_togglePrivateAction.setVisible(state, false); + } + } + + private static class SectionNewItemForm extends NewItemForm { + + public SectionNewItemForm(String name) { + super(name); + } + + @Override + public ContentSection getContentSection(PageState s) { + return CMS.getContext().getContentSection(); + } + + } + + /** + * Getting the GlobalizedMessage using a CMS Class targetBundle. + * + * @param key The resource key + * @pre ( key != null ) + */ + private static GlobalizedMessage globalize(String key) { + return ContentSectionPage.globalize(key); + } + + private static GlobalizedMessage globalize(final String key, + final Object[] args) { + return ContentSectionPage.globalize(key, args); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ImagesPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ImagesPane.java.off new file mode 100644 index 000000000..897899eb4 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ImagesPane.java.off @@ -0,0 +1,265 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package com.arsdigita.cms.ui; + +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.FormModel; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.MapComponentSelectionModel; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.Resettable; +import com.arsdigita.bebop.SegmentedPanel; +import com.arsdigita.bebop.SegmentedPanel.Segment; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.parameters.ParameterModel; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.toolbox.ui.LayoutPanel; +import com.arsdigita.toolbox.ui.Section; +import com.arsdigita.util.Assert; +import com.arsdigita.util.LockableImpl; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import org.apache.log4j.Logger; + +/** + * A {@link LayoutPanel} to insert into {@link ContentSectionPage}. + * + * @author Sören Bernstein + */ +public class ImagesPane extends LayoutPanel implements Resettable { + + public static final Logger S_LOG = Logger.getLogger(ImagesPane.class); + private final StringParameter m_imageComponentKey; + private final MapComponentSelectionModel m_imageComponent; + private final ImageComponentAdminListener m_adminListener; + final private SegmentedPanel m_body; + private HashMap m_bodySegments = new HashMap(); + private final ResettableParameterSingleSelectionModel m_model; + private final List m_links; + private final LinksSection m_modes; + + public ImagesPane() { + super(); + + m_model = new ResettableParameterSingleSelectionModel(new + StringParameter(List.SELECTED)); + m_model.setDefaultSelection(ImageComponent.LIBRARY); + m_model.addChangeListener(new ImageAdminSelectionListener()); + + m_links = new List(new ImageAdminListModelBuilder()); + m_links.setSelectionModel(m_model); + + final SimpleContainer left = new SimpleContainer(); + setLeft(left); + + m_modes = new LinksSection(); + left.add(m_modes); + + m_body = new SegmentedPanel(); + setBody(m_body); + + m_imageComponentKey = new StringParameter("imageComponent"); + + final ParameterSingleSelectionModel componentModel = new + ParameterSingleSelectionModel(m_imageComponentKey); + m_imageComponent = new MapComponentSelectionModel(componentModel, + new HashMap()); + + final Map selectors = m_imageComponent.getComponentsMap(); + m_adminListener = new ImageComponentAdminListener(m_imageComponent, this); + + // Image library component + final ImageLibraryComponent library = new + ImageLibraryComponent(ImageComponent.ADMIN_IMAGES); + library.getForm().addInitListener(m_adminListener); + library.getForm().addProcessListener(m_adminListener); + selectors.put(ImageComponent.LIBRARY, library); + m_bodySegments.put(ImageComponent.LIBRARY, m_body.addSegment( + new Label(GlobalizationUtil.globalize( + "cms.contentasset.image.ui.image_library")), + library)); + + // Image upload component + final ImageUploadComponent upload = new + ImageUploadComponent(ImageComponent.ADMIN_IMAGES); + upload.getForm().addInitListener(m_adminListener); + upload.getForm().addSubmissionListener(m_adminListener); + upload.getForm().addProcessListener(m_adminListener); + selectors.put(ImageComponent.UPLOAD, upload); + m_bodySegments.put(ImageComponent.UPLOAD, m_body.addSegment( + new Label(GlobalizationUtil.globalize( + "cms.contentasset.image.ui.image_upload")), + upload)); + + } + + @Override + public final void register(final Page page) { + super.register(page); + + Iterator keys = m_bodySegments.keySet().iterator(); + + while (keys.hasNext()) { + String key = keys.next(); + page.setVisibleDefault(m_bodySegments.get(key), + m_model.getDefaultSelection().equals(key)); + } + + page.addComponentStateParam(this, m_imageComponentKey); + } + + /** + * Resets this pane and all its resettable components. + * + * @param state Page state + */ + @Override + public final void reset(final PageState state) { + super.reset(state); + + m_model.reset(state); + this.setActiveImageComponent(state, m_model.getDefaultSelection()); + } + + public final void setActiveImageComponent(PageState state, String activeComp) { + + Iterator keys = m_bodySegments.keySet().iterator(); + m_imageComponent.setSelectedKey(state, activeComp); + + while (keys.hasNext()) { + + String key = keys.next(); + final boolean visibility = key.equals(activeComp); + state.setVisible(m_bodySegments.get(key), visibility); + + for (int index = 0; index < m_bodySegments.get(key).size(); index++) { + + Component component = m_bodySegments.get(key).get(index); + + // Reset all components if they are of type Resettable + if (component instanceof Resettable) { + ((Resettable) component).reset(state); + } + + // Set visibility + component.setVisible(state, visibility); + } + } + } + + /** + * + */ + private class ResettableParameterSingleSelectionModel + extends ParameterSingleSelectionModel + implements Resettable { + + private String defaultKey; + + public ResettableParameterSingleSelectionModel(ParameterModel m) { + super(m); + } + + public void setDefaultSelection(String selKey) { + this.defaultKey = selKey; + } + + public String getDefaultSelection() { + return defaultKey; + } + + public void reset(PageState state) { + + if (Assert.isEnabled()) { + final FormModel model = state.getPage().getStateModel(); + Assert.isTrue(model.containsFormParam(getStateParameter())); + } + + state.setValue(getStateParameter(), this.defaultKey); + } + } + + /** + * + */ + private class ImageAdminListModel implements ListModel { + + private ArrayList m_keys; + private int m_index = -1; + + public ImageAdminListModel(ArrayList keys) { + m_keys = keys; + } + + public boolean next() { + return (m_index++ < m_keys.size() - 1); + } + + public Object getElement() { + return GlobalizationUtil.globalize( + "cms.contentasset.image.ui.image_" + m_keys.get(m_index)).localize(); + } + + public String getKey() { + return m_keys.get(m_index); + } + } + + private class ImageAdminListModelBuilder extends LockableImpl + implements ListModelBuilder { + + public ListModel makeModel(final List list, final PageState state) { + ArrayList keys = new ArrayList(2); + keys.add(ImageComponent.LIBRARY); + keys.add(ImageComponent.UPLOAD); + return new ImageAdminListModel(keys); + } + } + + private class ImageAdminSelectionListener implements ChangeListener { + + public final void stateChanged(final ChangeEvent e) { + S_LOG.debug("Selection state changed; I may change " + +"the body's visible pane"); + + final PageState state = e.getPageState(); + +// ImagesPane.this.reset(state); + + if (m_model.isSelected(state)) { + S_LOG.debug("The selection model is selected; displaying " + +"the item pane"); + + ImagesPane.this.setActiveImageComponent( + state, + state.getControlEventValue()); + } + } + } + + private class LinksSection extends Section { + + LinksSection() { + setHeading(GlobalizationUtil.globalize( + "cms.contentasset.image.ui.images")); + + final ActionGroup group = new ActionGroup(); + setBody(group); + + group.setSubject(m_links); + } + } +} \ No newline at end of file diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/ReportPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ReportPane.java.off new file mode 100644 index 000000000..04de51549 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/ReportPane.java.off @@ -0,0 +1,158 @@ +/* + * Copyright (C) 2009 Permeance Technologies Pty Ltd. 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.ui; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; + +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.ui.report.ContentSectionSummaryTable; +import com.arsdigita.cms.ui.report.Report; +import com.arsdigita.cms.ui.report.ReportListModel; +import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.toolbox.ui.Section; +import com.arsdigita.util.LockableImpl; + +/** + * A pane that shows selectable reports and their results. + * A selectable list of reports is shown on the left-hand side, a selected report is shown as + * body. + * + * @author thomas-buckel + * @author tim-permeance + */ +public class ReportPane extends BaseAdminPane { + + private final SingleSelectionModel m_selectionModel; + private final java.util.List m_availableReports; + + public ReportPane() { + m_availableReports = getReports(); + + m_selectionModel = new ParameterSingleSelectionModel(new StringParameter(List.SELECTED)); + m_selectionModel.addChangeListener(new SelectionListener()); + setSelectionModel(m_selectionModel); + + List m_reports = new List(new ReportListModelBuilder(m_availableReports)); + m_reports.setSelectionModel(m_selectionModel); + + final ReportsListSection reportsListSection = new ReportsListSection(m_reports); + setLeft(reportsListSection); + + // Register the actual components of the reports for later usage + for (Report report : m_availableReports) { + getBody().add(report.getComponent()); + } + + setIntroPane(new Label(gz("cms.ui.reports.intro"))); + } + + /** + * @return List of available reports. + */ + private java.util.List getReports() { + java.util.List reports = new ArrayList(); + reports.add(new Report("cms.ui.reports.css.reportName", new ContentSectionSummaryTable())); + // Add other reports as required + + Collections.sort(reports, new Comparator() { + @Override + public int compare(Report r1, Report r2) { + return r1.getName().compareTo(r2.getName()); + } + }); + return reports; + } + + /** + * Get the report model that matches the given key. + * @param key Key to match. + * @return Report model that matches that given key, null if no matching report was found. + */ + private Report getReportByKey(String key) { + for (Report report : m_availableReports) { + if (report.getKey().equals(key)) { + return report; + } + } + return null; + } + + /** + * UI section for left-hand list of reports. + */ + private class ReportsListSection extends Section { + ReportsListSection(List reports) { + setHeading(gz("cms.ui.reports.header")); + ActionGroup group = new ActionGroup(); + setBody(group); + group.setSubject(reports); + } + } + + /** + * SelectionListener for selected report. It shows the selected report in the body of this + * component. + */ + private class SelectionListener implements ChangeListener { + + public final void stateChanged(final ChangeEvent e) { + + final PageState state = e.getPageState(); + + getBody().reset(state); + + if (m_selectionModel.isSelected(state)) { + Report selectedReport = getReportByKey(m_selectionModel.getSelectedKey(state).toString()); + if (selectedReport != null) { + getBody().push(state, selectedReport.getComponent()); + } + } + } + + } + + /** + * ListModelBuilder creating a ReportListModel for a list of reports. + */ + private static class ReportListModelBuilder extends LockableImpl implements ListModelBuilder { + + private java.util.List reports; + + private ReportListModelBuilder(java.util.List reports) { + this.reports = reports; + } + + public final ListModel makeModel(final List list, + final PageState state) { + return new ReportListModel(reports); + } + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/CreationSelector.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/CreationSelector.java.off new file mode 100755 index 000000000..74ea845b6 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/authoring/CreationSelector.java.off @@ -0,0 +1,258 @@ +/* + * Copyright (C) 2001-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.ui.authoring; + +import com.arsdigita.bebop.ColumnPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.MetaForm; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.form.FormErrorDisplay; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.cms.AuthoringKit; +import com.arsdigita.cms.ContentBundle; +import com.arsdigita.cms.ContentItem; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.ContentType; +import com.arsdigita.cms.Folder; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.ui.ContentItemPage; +import com.arsdigita.cms.ui.folder.FolderSelectionModel; +import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.util.UncheckedWrapperException; +import com.arsdigita.web.RedirectSignal; +import com.arsdigita.web.URL; +import org.apache.log4j.Logger; + +import java.lang.reflect.Constructor; +import java.math.BigDecimal; + +/** + * An invisible component which contains all the possible creation + * components. The components are loaded from the database at + * construction time. The selector uses a {@link SingleSelectionModel} + * in order to get the ID of the current content type. + * + * Important: This component is passed in the + * constructor to every authoring kit creation component (such as + * {@link PageCreate}). The creation component is supposed to follow + * the following pattern: + * + *
+ *   // The member variable m_parent points to the CreationSelector
+ *   SomeContentItem item = somehowCreateTheItem(state);
+ *   item.setParent(m_parent.getFolder(state));
+ *   m_parent.editItem(state, item);
+ * 
+ * + * If the creation component wishes to cancel the creation process, + * it should call + * + *
m_parent.redirectBack(state);
+ * + * The component may also call + * + *
m_parent.getContentSection(state);
+ * + * in order to get the current content section. + * + * @version $Id: CreationSelector.java 2185 2011-06-20 21:16:02Z pboy $ + */ +public class CreationSelector extends MetaForm { + + private static Logger s_log = Logger.getLogger(CreationSelector.class); + + private final FolderSelectionModel m_folderSel; + private final SingleSelectionModel m_typeSel; + + private static Class[] s_args = new Class[] { + ItemSelectionModel.class, + CreationSelector.class + }; + + private Object[] m_vals; + + private ItemSelectionModel m_itemSel; + private BigDecimalParameter m_itemId; + + private ItemSelectionModel m_bundleSel; + private BigDecimalParameter m_bundleId; + + public static final String ITEM_ID = "iid"; + public static final String BUNDLE_ID = "bid"; + + /** + * Constructs a new CreationSelector. Load all the + * possible creation components from the database and stick them + * in the Map. + * + * @param typeModel the {@link SingleSelectionModel} which will + * supply a BigDecimal ID of the content type to instantiate + * + * @param folderModel the {@link FolderSelectionModel} containing + * the folder in which new items are to be created + */ + public CreationSelector(final SingleSelectionModel typeModel, + final FolderSelectionModel folderModel) { + super("pageCreate"); + + m_typeSel = typeModel; + + m_folderSel = folderModel; + m_itemId = new BigDecimalParameter(ITEM_ID); + m_bundleId = new BigDecimalParameter(BUNDLE_ID); + m_bundleSel = new ItemSelectionModel(ContentBundle.class.getName(), + ContentBundle.BASE_DATA_OBJECT_TYPE, m_bundleId); + } + + + /** + * + * @param state + * @return + */ + @Override + public Form buildForm(PageState state) { + BigDecimal typeID = (BigDecimal)m_typeSel.getSelectedKey(state); + Component c = null; + Form returnForm = new Form("pageCreate"); + FormErrorDisplay fed = new FormErrorDisplay(this); + fed.setStateParamsAreRegistered(false); + returnForm.add(fed , ColumnPanel.FULL_WIDTH | ColumnPanel.LEFT); + if (typeID != null) { + try { + ContentType type = new ContentType(typeID); + AuthoringKit kit = type.getAuthoringKit(); + if(kit != null) { + c = instantiateKitComponent(kit, type); + if(c != null) { + returnForm.add(c); + returnForm.setMethod(Form.POST); + returnForm.setEncType("multipart/form-data"); + } + } + } catch (DataObjectNotFoundException e) { + // content type not found + } + } + return returnForm; + } + + /** + * Add the item_id parameter. + * + * @param p + */ + @Override + public void register(Page p) { + super.register(p); + p.addComponentStateParam(this, m_itemId); + p.addComponentStateParam(this, m_bundleId); + } + + /** + * Get the creation component. + * + * @param kit + * @param type + * @return + */ + protected Component instantiateKitComponent + (final AuthoringKit kit, final ContentType type) { + String creatorName = kit.getCreateComponent(); + Object[] vals; + + if(creatorName == null) { + return null; + } + + try { + Class createClass = Class.forName(creatorName); + ItemSelectionModel itemModel = new ItemSelectionModel(type, m_itemId); + vals = new Object[]{itemModel, this}; + Constructor constr = createClass.getConstructor(s_args); + Component c = (Component)constr.newInstance(vals); + return c; + } catch (Exception e) { + s_log.error("Instantiation failure", e); + throw new UncheckedWrapperException ( + "Failed to instantiate creation component " + + kit.getCreateComponent() + ": " + e.getMessage(), + e); + } + } + + /** + * Return the currently selected folder. Creation components will place + * new items in this folder. + * + * @param s represents the current request + * @return the currently selected folder, in which new items should be + * placed. + */ + public final Folder getFolder(PageState s) { + return (Folder) m_folderSel.getSelectedObject(s); + } + + /** + * Return the currently selected content section. New items created by + * creation components will belong to this section. This is the content + * section to which the folder returned by {@link #getFolder getFolder} + * belongs. + * + * @param s represents the current request + * @return the currently selected content section. + */ + public final ContentSection getContentSection(PageState s) { + final ContentSection section = (ContentSection) + getFolder(s).getContentSection(); + + return section; + } + + /** + * Forward to the item editing UI. The creation component of an authoring + * kit may call this method to indicate that the creation process is + * complete. + * + * @param s the page state + * @param item the newly created item + */ + public void editItem(PageState s, ContentItem item) { + ContentSection sec = getContentSection(s); + + String nodeURL = URL.getDispatcherPath() + sec.getPath() + "/"; + String target = ContentItemPage.getItemURL + (nodeURL, item.getID(), ContentItemPage.AUTHORING_TAB,true); + + throw new RedirectSignal(target, true); + } + + /** + * Cancel item editing and go back to where the user came from + * + * @param s the page state + */ + public void redirectBack(PageState state) { + m_typeSel.clearSelection(state); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/category/CategoryAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/category/CategoryAdminPane.java.off new file mode 100755 index 000000000..01ef79e25 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/category/CategoryAdminPane.java.off @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2003-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.ui.category; + +import com.arsdigita.bebop.*; +import com.arsdigita.bebop.event.*; +import com.arsdigita.bebop.parameters.ParameterModel; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.categorization.CategorizedCollection; +import com.arsdigita.categorization.Category; +import com.arsdigita.categorization.CategoryCollection; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.SecurityManager; +import com.arsdigita.cms.ui.BaseAdminPane; +import com.arsdigita.cms.ui.BaseDeleteForm; +import com.arsdigita.cms.ui.BaseTree; +import com.arsdigita.cms.ui.VisibilityComponent; +import com.arsdigita.kernel.Kernel; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.toolbox.ui.Section; +import com.arsdigita.xml.Element; +import java.math.BigDecimal; +import org.apache.log4j.Logger; + +/** + * A split pane for the Category Administration UI. + * + * @author Justin Ross <jross@redhat.com> + * @version $Id: CategoryAdminPane.java 2090 2010-04-17 08:04:14Z pboy $ + */ +public final class CategoryAdminPane extends BaseAdminPane { + + public static final String CONTEXT_SELECTED = "sel_context"; + private static final String DEFAULT_USE_CONTEXT = + CategoryUseContextModelBuilder.DEFAULT_USE_CONTEXT; + private static final Logger s_log = Logger.getLogger(CategoryAdminPane.class); + private final SingleSelectionModel m_contextModel; + private final Tree m_categoryTree; + private final SingleSelectionModel m_model; + private final CategoryRequestLocal m_parent; + private final CategoryRequestLocal m_category; + + public CategoryAdminPane() { + super(); + + m_contextModel = new UseContextSelectionModel(new StringParameter(CONTEXT_SELECTED)); + + /* Left column */ + /* Use context section */ + List list = new List(new CategoryUseContextModelBuilder()); + list.setSelectionModel(m_contextModel); + list.addChangeListener(new ContextSelectionListener()); + + /* Category tree section */ + m_categoryTree = new BaseTree(new CategoryTreeModelBuilder(m_contextModel)); + m_categoryTree.addChangeListener(new SelectionListener()); + m_model = m_categoryTree.getSelectionModel(); + + setSelectionModel(m_model); + setSelector(m_categoryTree); + + /* setup use context form */ + final Section contextSection = new Section(); + contextSection.setHeading(new Label(gz("cms.ui.category.use_contexts"))); + ActionGroup contextGroup = new ActionGroup(); + contextSection.setBody(contextGroup); + contextGroup.setSubject(list); + + if (CMS.getConfig().getAllowCategoryCreateUseContext()) { + ActionLink addContextAction = new ActionLink(new Label(gz( + "cms.ui.category.add_use_context"))); + Form addContextForm = new AddUseContextForm(m_contextModel); + getBody().add(addContextForm); + getBody().connect(addContextAction, addContextForm); + contextGroup.addAction(new VisibilityComponent(addContextAction, + SecurityManager.CATEGORY_ADMIN)); + } + + final Section categorySection = new Section(); + categorySection.setHeading(new Label(gz("cms.ui.categories"))); + ActionGroup categoryGroup = new ActionGroup(); + categorySection.setBody(categoryGroup); + categoryGroup.setSubject(m_categoryTree); + + final SimpleContainer leftContainer = new SimpleContainer(); + leftContainer.add(contextSection); + leftContainer.add(categorySection); + setLeft(leftContainer); + + m_parent = new ParentRequestLocal(); + m_category = new SelectionRequestLocal(); + + setAdd(gz("cms.ui.category.add"), + new CategoryAddForm(m_category, m_model)); + + setEdit(gz("cms.ui.category.edit"), + new CategoryEditForm(m_parent, m_category)); + + setDelete(new DeleteLink(new Label(gz("cms.ui.category.delete"))), new DeleteForm( + new SimpleContainer())); + + setIntroPane(new Label(gz("cms.ui.category.intro"))); + setItemPane(new CategoryItemPane(m_model, + m_contextModel, + m_category, + getAddLink(), + getEditLink(), + getDeleteLink())); + + //m_contextList = new List(new ContextListModelBuilder()); + //m_contextList.adChangeListener(new ContextListSelectionListener()); + //m_contextModel = m_contextList.getSelectionModel(); + + } + + @Override + public void register(final Page page) { + super.register(page); + + page.addActionListener(new RootListener()); + } + + private final class DeleteLink extends ActionLink { + + private final Label m_alternativeLabel; + + DeleteLink(Label label) { + super(label); + m_alternativeLabel = new Label(gz("cms.ui.category.undeletable")); + } + + @Override + public void generateXML(PageState state, Element parent) { + if (!isVisible(state)) { + return; + } + + Category cat = m_category.getCategory(state); + String context = getUseContext(state); + boolean isDefaultContext = + (context == null) || DEFAULT_USE_CONTEXT.equals(context); + + if (cat.isRoot() || !cat.getChildren().isEmpty()) { + m_alternativeLabel.generateXML(state, parent); + } else { + super.generateXML(state, parent); + } + } + + } + + private final class DeleteForm extends BaseDeleteForm { + + DeleteForm(SimpleContainer prompt) { + super(prompt); + prompt.add(new Label(gz("cms.ui.category.delete_prompt"))); + Label catLabel = new Label(); + catLabel.addPrintListener(new PrintListener() { + public void prepare(PrintEvent pe) { + Label label = (Label) pe.getTarget(); + Category cat = + m_category.getCategory(pe.getPageState()); + CategoryCollection descendants = cat.getDescendants(); + final long nDescendants = descendants.size() - 1; + descendants.close(); + CategorizedCollection descObjects = + cat.getDescendantObjects(); + final long nDescObjects = descObjects.size(); + descObjects.close(); + StringBuffer sb = new StringBuffer(" "); + if (nDescendants > 0) { + sb.append("This category has "); + sb.append(nDescendants); + sb.append(" descendant category(ies). "); + } + if (nDescObjects > 0) { + sb.append("It has ").append(nDescObjects); + sb.append(" descendant object(s). "); + } + if (nDescendants > 0 || nDescObjects > 0) { + sb.append("Descendants will be orphaned, if this category is removed."); + } + label.setLabel(sb.toString()); + } + + }); + prompt.add(catLabel); + } + + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + final Category category = m_category.getCategory(state); + if (category == null) { + return; + } + + PermissionService.assertPermission(new PermissionDescriptor(PrivilegeDescriptor.DELETE, + category, + Kernel.getContext(). + getParty())); + + if (category.isRoot()) { + Category root = + Category.getRootForObject(CMS.getContext().getContentSection(), + getUseContext(state)); + if (category.equals(root)) { + Category.clearRootForObject(CMS.getContext().getContentSection(), + getUseContext(state)); + } + m_contextModel.setSelectedKey(state, DEFAULT_USE_CONTEXT); + } else { + Category parent = category.getDefaultParentCategory(); + m_model.setSelectedKey(state, parent.getID()); + } + + category.deleteCategoryAndOrphan(); + } + + } + + private final class SelectionRequestLocal extends CategoryRequestLocal { + + @Override + protected final Object initialValue(final PageState state) { + final String id = m_model.getSelectedKey(state).toString(); + + if (id == null) { + return null; + } else { + return new Category(new BigDecimal(id)); + } + } + + } + + private final class ParentRequestLocal extends CategoryRequestLocal { + + @Override + protected final Object initialValue(final PageState state) { + return m_category.getCategory(state).getDefaultParentCategory(); + } + + } + + private final class RootListener implements ActionListener { + + public final void actionPerformed(final ActionEvent e) { + final PageState state = e.getPageState(); + + if (!m_model.isSelected(state)) { + final Category root = + Category.getRootForObject(CMS.getContext().getContentSection(), + getUseContext(state)); + if (root != null) { + m_model.setSelectedKey(state, root.getID()); + } + } + } + + } + + private class UseContextSelectionModel extends ParameterSingleSelectionModel { + + public UseContextSelectionModel(ParameterModel m) { + super(m); + } + + @Override + public Object getSelectedKey(PageState state) { + Object val = super.getSelectedKey(state); + if (val == null || ((String) val).length() == 0) { + val = DEFAULT_USE_CONTEXT; + state.setValue(getStateParameter(), val); + fireStateChanged(state); + } + return val; + } + + } + + public String getUseContext(PageState state) { + String selected = (String) m_contextModel.getSelectedKey(state); + return (DEFAULT_USE_CONTEXT).equals(selected) ? (String) null : selected; + } + + public class ContextSelectionListener implements ChangeListener { + + public final void stateChanged(final ChangeEvent e) { + s_log.debug("Selection state changed; I may change " + "the body's visible pane"); + + final PageState state = e.getPageState(); + + getBody().reset(state); + + if (m_contextModel.isSelected(state)) { + final Category root = + Category.getRootForObject(CMS.getContext().getContentSection(), + getUseContext(state)); + + if (root != null) { + m_model.setSelectedKey(state, root.getID()); + //m_categoryTree.reset(state); + } + + } + if (m_model.isSelected(state)) { + s_log.debug("The selection model is selected; displaying " + "the item pane"); + + getBody().push(state, getItemPane()); + } + } + + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/cse/ContentSoonExpiredPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/cse/ContentSoonExpiredPane.java.off new file mode 100755 index 000000000..f63223b88 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/cse/ContentSoonExpiredPane.java.off @@ -0,0 +1,296 @@ +/* + * Copyright (C) 2002-2005 Runtime Collective Ltd. 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.ui.cse; + +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Link; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ContentItem; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.SecurityManager; +import com.arsdigita.cms.ui.ContentItemPage; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.cms.util.SecurityConstants; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.kernel.User; +import com.arsdigita.kernel.permissions.PermissionDescriptor; +import com.arsdigita.kernel.permissions.PermissionService; +import com.arsdigita.kernel.permissions.PrivilegeDescriptor; +import com.arsdigita.persistence.DataQuery; +import com.arsdigita.persistence.Filter; +import com.arsdigita.persistence.FilterFactory; +import com.arsdigita.persistence.OID; +import com.arsdigita.persistence.Session; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.toolbox.ui.DataQueryBuilder; +import com.arsdigita.toolbox.ui.DataTable; +import com.arsdigita.ui.admin.Admin; +import com.arsdigita.web.Application; +import com.arsdigita.web.Web; +import com.arsdigita.xml.Element; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.Component; + +import java.math.BigDecimal; +import java.util.Calendar; +import java.util.Iterator; + +import org.apache.log4j.Logger; + +/** + * A pane that contains details to soon to be expired content. + * + * @version $Id: ContentSoonExpiredPane.java 775 2005-09-12 14:54:17Z fabrice $ + */ +public class ContentSoonExpiredPane extends SimpleContainer { + + private static final Logger log = Logger.getLogger(ContentSoonExpiredPane.class); + + private DataTable dataTable; + + public ContentSoonExpiredPane() { + add(getDataTable()); + } + + public final void generateXML(final PageState state, final Element parent) { + if (!isVisible(state)) { + return; + } + + SecurityManager sm = CMS.getContext().getSecurityManager(); + User user = Web.getWebContext().getUser(); + + DataTable dt = getDataTable(); + DataQuery dq = dt.getDataQuery(state); + dq.addFilter(getViewFilter(dq, user)); + + dt.generateXML(state, parent); + + } + + private static Filter getViewFilter(DataQuery query, User user) { + PrivilegeDescriptor privilege = new PrivilegeDescriptor(SecurityConstants.CMS_READ_ITEM); + FilterFactory ff = query.getFilterFactory(); + OID partyOID = user.getOID(); + return PermissionService.getFilterQuery(ff, "objectId", privilege, partyOID); + } + + protected DataTable getDataTable() { + if (dataTable == null) { + dataTable = new DataTable(new ContentSoonExpiredQueryBuilder()); + dataTable.addColumn(GlobalizationUtil.globalize("cms.ui.cse.authorName").localize() + .toString(), + "authorName", true); + dataTable.addColumn(GlobalizationUtil.globalize("cms.ui.cse.itemName").localize() + .toString(), + "objectId", true, new ItemTitleCellRender()); + dataTable + .addColumn(GlobalizationUtil.globalize("cms.ui.cse.view").localize().toString(), + "objectId", false, new ItemViewLinkCellRender()); + dataTable + .addColumn(GlobalizationUtil.globalize("cms.ui.cse.edit").localize().toString(), + "objectId", false, new ItemEditLinkCellRender()); + dataTable.addColumn(GlobalizationUtil.globalize("cms.ui.cse.endDateTime").localize() + .toString(), + "endDateTime", true); + + dataTable.setEmptyView(new Label(GlobalizationUtil.globalize("cms.ui.cse.none"))); + } + + return dataTable; + } + + private static boolean hasSiteWideAdmin(User user) { + Application adminApp = Admin.getInstance(); + if (adminApp == null) { + return false; + } + + PermissionDescriptor admin = new PermissionDescriptor(PrivilegeDescriptor.ADMIN, adminApp, + user); + return PermissionService.checkPermission(admin); + } + + private static GlobalizedMessage gz(final String key) { + return GlobalizationUtil.globalize(key); + } + + private static String lz(final String key) { + return (String) gz(key).localize(); + } + + private class ContentSoonExpiredQueryBuilder implements DataQueryBuilder { + + public String getKeyColumn() { + return "objectId"; + } + + public DataQuery makeDataQuery(DataTable t, PageState s) { + Session ses = SessionManager.getSession(); + DataQuery query = ses.retrieveQuery( + "com.arsdigita.cms.getContentItemExpiredBeforeInSection"); + + int months = ContentSection.getConfig().getSoonExpiredMonths(); + int days = ContentSection.getConfig().getSoonExpiredDays(); + + Calendar now = Calendar.getInstance(); + now.add(Calendar.DAY_OF_YEAR, days); + now.add(Calendar.MONTH, months); + query.setParameter("endDateTime", now.getTime()); + + ContentSection section = CMS.getContext().getContentSection(); + query.setParameter("sectionId", section.getID()); + + return query; + } + + public void lock() { + } + + public boolean isLocked() { + return false; + } + + } + + private class ItemTitleCellRender implements TableCellRenderer { + + private ThreadLocal threadLocal; + + public ItemTitleCellRender() { + threadLocal = new ThreadLocal() { + + protected Object initialValue() { + return new Label(""); + } + + }; + } + + public Component getComponent(Table table, PageState state, Object value, + boolean isSelected, Object key, + int row, int column) { + BigDecimal id = (BigDecimal) key; + Label l = (Label) threadLocal.get(); + l.setLabel(ContentSoonExpiredPane.getItemFromIdString(id.toString()).getDisplayName()); + return l; + } + + } + + private class ItemEditLinkCellRender implements TableCellRenderer { + + private ThreadLocal threadLocal; + + public ItemEditLinkCellRender() { + threadLocal = new ThreadLocal() { + + protected Object initialValue() { + return new Link(new Label(), ""); + } + + }; + } + + public Component getComponent(Table table, PageState state, Object value, + boolean isSelected, Object key, + int row, int column) { + boolean canEdit = false; + BigDecimal id = (BigDecimal) key; + User user = Web.getWebContext().getUser(); + ContentItem ci = getItemFromIdString(id.toString()); + Iterator permissions = PermissionService + .getImpliedPrivileges(ci.getOID(), user.getOID()); + while (permissions.hasNext()) { + PrivilegeDescriptor permission = (PrivilegeDescriptor) permissions.next(); + if (permission.equals(PrivilegeDescriptor.ADMIN) || permission.equals( + PrivilegeDescriptor.EDIT)) { + canEdit = true; + break; + } + } + + if (!canEdit) { + return new Label(""); + } + + Link l = (Link) threadLocal.get(); +// l.setTarget(ContentItemPage.getRelativeItemURL(ContentSoonExpiredPane.getItemDraft(id.toString()), ContentItemPage.AUTHORING_TAB)); + l.setTarget(ContentItemPage.getItemURL(ContentSoonExpiredPane.getItemFromIdString(id + .toString()), ContentItemPage.AUTHORING_TAB)); + ((Label) l.getChild()).setLabel(GlobalizationUtil.globalize("cms.ui.cse.editLink")); + + return l; + } + + } + + private class ItemViewLinkCellRender implements TableCellRenderer { + + private ThreadLocal threadLocal; + + public ItemViewLinkCellRender() { + threadLocal = new ThreadLocal() { + + protected Object initialValue() { + return new Link(new Label(), ""); + } + + }; + } + + public Component getComponent(Table table, PageState state, Object value, + boolean isSelected, Object key, + int row, int column) { + BigDecimal id = (BigDecimal) key; + Link l = (Link) threadLocal.get(); + + ContentItem item = getItemFromIdString(id.toString()); + String url = ".jsp"; + while (item.getParent() != null) { + if (item.getParent() instanceof ContentItem) { + item = (ContentItem) item.getParent(); + if (!"/".equals(item.getName())) { + url = "/" + item.getName() + url; + } else { + break; + } + } + } + ContentSection section = CMS.getContext().getContentSection(); + l.setTarget("/" + section.getName() + url); + + ((Label) l.getChild()).setLabel(GlobalizationUtil.globalize("cms.ui.cse.viewLink")); + return l; + } + + } + + private static ContentItem getItemFromIdString(String idString) { + return new ContentItem(new OID(ContentItem.class.getName(), Integer.parseInt(idString))); + } + + private static BigDecimal getItemDraft(String idString) { + ContentItem item = getItemFromIdString(idString); + return item.getDraftVersion().getID(); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderAdminPane.java.off new file mode 100755 index 000000000..15d0e79f3 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderAdminPane.java.off @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2003-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.ui.folder; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.ui.BaseDeleteForm; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.globalization.GlobalizedMessage; +import com.arsdigita.toolbox.ui.SelectionPanel; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; + +/** + * A pane that contains a folder tree on the left and a folder + * manipulator on the right. + * + * @author Justin Ross <jross@redhat.com> + * @version $Id: FolderAdminPane.java 1942 2009-05-29 07:53:23Z terry $ + */ +public class FolderAdminPane extends SelectionPanel { + + private static final Logger s_log = Logger.getLogger + (FolderAdminPane.class); + + private final FolderRequestLocal m_folder; + + private final BigDecimalParameter m_param; + + public static final String FOLDER_PARAMETER = "folder"; + + public FolderAdminPane() { + super(new Label(gz("cms.ui.folder.folders")), + new FolderTreeModelBuilder()); + + m_folder = new FolderRequestLocal(getSelectionModel()); + m_param = new BigDecimalParameter(FOLDER_PARAMETER); + + setAdd(new ActionLink(new Label(gz("cms.ui.folder.add"))), + new FolderAddForm(getSelectionModel(), m_folder)); + + setEdit(new ActionLink(new Label(gz("cms.ui.folder.edit"))), + new FolderEditForm(m_folder)); + + final BaseDeleteForm delete = new BaseDeleteForm + (new Label(gz("cms.ui.folder.delete_prompt"))) { + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + + m_folder.getFolder(state).delete(); + getSelectionModel().clearSelection(state); + } + }; + + setDelete(new ActionLink(new Label(gz("cms.ui.folder.delete"))), + delete); + + setIntroPane(new Label(gz("cms.ui.folder.intro"))); + setItemPane(new Label("item XXX")); + + addAction(getAddLink()); + addAction(getEditLink()); + addAction(getDeleteLink()); + } + + public void register(final Page page) { + super.register(page); + + page.addGlobalStateParam(m_param); + page.addActionListener(new PreselectListener()); + } + + private class PreselectListener implements ActionListener { + public final void actionPerformed(final ActionEvent e) { + final PageState state = e.getPageState(); + final SingleSelectionModel model = getSelectionModel(); + + if (!model.isSelected(state)) { + final BigDecimal value = (BigDecimal) state.getValue(m_param); + + if (value == null) { + final ContentSection section = + CMS.getContext().getContentSection(); + + model.setSelectedKey + (state, section.getRootFolder().getID()); + } else { + model.setSelectedKey(state, value); + } + } + } + } + + private static GlobalizedMessage gz(final String key) { + return GlobalizationUtil.globalize(key); + } + + private static String lz(final String key) { + return (String) gz(key).localize(); + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreator.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreator.java.off new file mode 100755 index 000000000..bfb1ad53b --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderCreator.java.off @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2001-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.ui.folder; + +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.cms.Folder; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.db.Sequences; +import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.persistence.OID; +import com.arsdigita.persistence.SessionManager; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; + +public class FolderCreator extends FolderForm { + + private static Logger s_log = + Logger.getLogger(FolderCreator.class.getName()); + + + public FolderCreator(String name, FolderSelectionModel parent) { + super(name, parent); + } + + public void init(FormSectionEvent e) throws FormProcessException { + PageState state = e.getPageState(); + ItemSelectionModel m = getItemSelectionModel(); + + // Create a new item_id and set it as the key + try { + m.setSelectedKey(state, Sequences.getNextValue()); + } catch (java.sql.SQLException ex) { + s_log.error("Error retrieving sequence.nextval", ex); + throw new FormProcessException(ex); + } + } + + + public void process(FormSectionEvent e) throws FormProcessException { + PageState s = e.getPageState(); + FormData data = e.getFormData(); + ItemSelectionModel m = getItemSelectionModel(); + BigDecimal id = (BigDecimal) m.getSelectedKey(s); + Folder parent = getCurrentFolder(s); + + Folder child = null; + try { + child = new Folder(id); + } catch (DataObjectNotFoundException ex) { + child = new Folder(SessionManager.getSession().create + (new OID(Folder.BASE_DATA_OBJECT_TYPE, id))); + } + + updateFolder(child, parent, (String)data.get(NAME), (String)data.get(TITLE)); + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditor.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditor.java.off new file mode 100755 index 000000000..afdf6aea9 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderEditor.java.off @@ -0,0 +1,64 @@ +/* + * 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.ui.folder; + +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.cms.Folder; + + +/** + * Implements functionality for renaming a folder. Most code taken from FolderCreator. Need to refactor out base + * functionality of FolderEditor & Creator. + * + * @author Jon Orris (jorris@arsdigita.com) + * + * @version $Revision: #9 $ $DateTime: 2004/08/17 23:15:09 $ + * @version $Id: FolderEditor.java 287 2005-02-22 00:29:02Z sskracic $ + */ + +public class FolderEditor extends FolderForm { + + public FolderEditor(String name, FolderSelectionModel folder) { + super(name, folder); + } + + + /** + * Initialize the form with name & label of folder being edited. + */ + public void init(FormSectionEvent e) throws FormProcessException { + PageState s = e.getPageState(); + FormData data = e.getFormData(); + Folder folder = getCurrentFolder(s); + data.put(NAME, folder.getName()); + data.put(TITLE, folder.getLabel()); + } + + + public void process(FormSectionEvent e) throws FormProcessException { + PageState s = e.getPageState(); + FormData data = e.getFormData(); + Folder folder = getCurrentFolder(s); + + updateFolder(folder, (String)data.get(NAME), (String)data.get(TITLE)); + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderManipulator.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderManipulator.java.off new file mode 100755 index 000000000..896819431 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderManipulator.java.off @@ -0,0 +1,1087 @@ +/* + * Copyright (C) 2001-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.ui.folder; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.BoxPanel; +import com.arsdigita.bebop.Component; +import com.arsdigita.bebop.Container; +import com.arsdigita.bebop.ControlLink; +import com.arsdigita.bebop.Form; +import com.arsdigita.bebop.FormData; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.PaginationModelBuilder; +import com.arsdigita.bebop.Paginator; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.Resettable; +import com.arsdigita.bebop.SaveCancelSection; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.Table; +import com.arsdigita.bebop.Tree; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +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.event.FormValidationListener; +import com.arsdigita.bebop.event.PrintEvent; +import com.arsdigita.bebop.event.PrintListener; +import com.arsdigita.bebop.form.CheckboxGroup; +import com.arsdigita.bebop.form.FormErrorDisplay; +import com.arsdigita.bebop.form.Option; +import com.arsdigita.bebop.form.OptionGroup; +import com.arsdigita.bebop.form.SingleSelect; +import com.arsdigita.bebop.form.Submit; +import com.arsdigita.bebop.form.TextField; +import com.arsdigita.bebop.parameters.ArrayParameter; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.bebop.table.TableCellRenderer; +import com.arsdigita.bebop.table.TableColumn; +import com.arsdigita.bebop.tree.TreeCellRenderer; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.CMSConfig; +import com.arsdigita.cms.ContentBundle; +import com.arsdigita.cms.ContentItem; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.ContentTypeLifecycleDefinition; +import com.arsdigita.cms.Folder; +import com.arsdigita.cms.ItemCollection; +import com.arsdigita.cms.SecurityManager; +import com.arsdigita.cms.lifecycle.LifecycleDefinition; +import com.arsdigita.cms.ui.lifecycle.PublishLock; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.domain.DataObjectNotFoundException; +import com.arsdigita.domain.DomainObjectFactory; +import com.arsdigita.kernel.ACSObject; +import com.arsdigita.kernel.Party; +import com.arsdigita.kernel.PartyCollection; +import com.arsdigita.kernel.User; +import com.arsdigita.notification.Notification; +import com.arsdigita.persistence.CompoundFilter; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.Filter; +import com.arsdigita.persistence.OID; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.toolbox.GlobalisationUtil; +import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.util.Assert; +import com.arsdigita.util.UncheckedWrapperException; +import com.arsdigita.web.Web; +import com.arsdigita.workflow.simple.TaskException; +import com.arsdigita.workflow.simple.Workflow; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Arrays; + +/** + * Browse folders and manipulate them with various actions (move/copy/delete). + * + * @author David Lutterkort + * @version $Id: FolderManipulator.java 1940 2009-05-29 07:15:05Z terry $ + */ +@SuppressWarnings("PMD.BeanMembersShouldSerialize") +public class FolderManipulator extends SimpleContainer implements + //FormProcessListener, + //FormValidationListener, + //FormSubmissionListener, + Resettable { + + //public static final String RESOURCE_BUNDLE = "com.arsdigita.cms.ui.folder.CMSFolderResources"; + private final GlobalisationUtil globalizationUtil = new com.arsdigita.toolbox.GlobalisationUtil( + "com.arsdigita.cms.ui.folder.CMSFolderResources"); + private static final Logger LOGGER = Logger.getLogger(FolderManipulator.class); + private static final String ATOZ_FILTER_PARAM = "aToZfilter"; + private static final String ACTION_PARAM = "act"; + private static final String FILTER_PARAM = "filter"; + + private static final String SOURCES_PARAM = "srcs"; + private static final String MOVE = "Move"; + private static final String COPY = "Copy"; + //private static final String PUBLISH = "Publish"; + //private static final String UNPUBLISH = "UnPublish"; + + private final ArrayParameter sourcesParam = new ArrayParameter( + new BigDecimalParameter(SOURCES_PARAM)); + private final StringParameter actionParam = new StringParameter(ACTION_PARAM); + ; + /** + * The folder in which the source items live. + */ + private final FolderSelectionModel sourceFolderModel; + private final ItemView itemView; + private final TargetSelector targetSelector = new TargetSelector(); + //private final PublishDialog publishDialog = new PublishDialog(); + + private FilterForm filterForm; + private final StringParameter atozFilterParam = new StringParameter(ATOZ_FILTER_PARAM); + private final StringParameter filterParam = new StringParameter(FILTER_PARAM); + + public FolderManipulator(final FolderSelectionModel folderModel) { + + super(); + + sourceFolderModel = folderModel; + itemView = new ItemView(); + itemView.addProcessListener(new ItemViewProcessListener()); + itemView.addValidationListener(new ItemViewValidationListener()); + add(itemView); + + targetSelector.addProcessListener(new TargetSelectorProcessListener()); + targetSelector.addValidationListener(new TargetSelectorValidationListener()); + targetSelector.addSubmissionListener(new TargetSelectorSubmissionListener()); + add(targetSelector); + + //publishDialog.addProcessListener(new PublishDialogProcessListener()); + + } + + @Override + public void register(final Page page) { + + super.register(page); + page.setVisibleDefault(targetSelector, false); + page.setVisibleDefault(filterForm, true); + page.addComponentStateParam(this, sourcesParam); + page.addComponentStateParam(this, actionParam); + page.addComponentStateParam(this, atozFilterParam); + page.addComponentStateParam(this, filterParam); + + } + + public final BigDecimal[] getSources(final PageState state) { + + final BigDecimal[] result = (BigDecimal[]) state.getValue(sourcesParam); + + //Return empty array instead of null. + if (result == null) { + return new BigDecimal[0]; + } else { + return result; + } + } + + public final FolderSelectionModel getSourceFolderModel() { + return sourceFolderModel; + } + + public final Folder getTarget(final PageState state) { + return targetSelector.getTarget(state); + } + + protected final boolean isMove(final PageState state) { + return MOVE.equals(getAction(state)); + } + + protected final boolean isCopy(final PageState state) { + return COPY.equals(getAction(state)); + } + +// protected final boolean isPublish(final PageState state) { +// return PUBLISH.equals(getAction(state)); +// } +// +// protected final boolean isUnPublish(final PageState state) { +// return UNPUBLISH.equals(getAction(state)); +// } + + private String getAction(final PageState state) { + return (String) state.getValue(actionParam); + } + + protected void moveItems(final Folder target, final BigDecimal[] itemIds) { + + for (BigDecimal itemId : itemIds) { + try { + changeItemParent(itemId, target); + } catch (DataObjectNotFoundException e) { + LOGGER.warn("object not found in content move", e); + throw new IllegalStateException(String.format("Item '%s' to move not found.", + itemId.toString())); + + } + } + + } + + private void changeItemParent(final BigDecimal itemId, final Folder newParent) + throws DataObjectNotFoundException { + + final ContentItem item = new ContentItem(itemId); + item.setParent(newParent); + item.save(); + + } + + protected void copyItems(final Folder target, + final BigDecimal[] itemIds) { + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Copying items " + Arrays.asList(itemIds) + " to " + target); + } + for (BigDecimal itemId : itemIds) { + +// ContentItem source = (ContentItem) DomainObjectFactory.newInstance( +// new OID(ContentItem.BASE_DATA_OBJECT_TYPE, itemId)); +// Assert.exists(source, ContentItem.class); +// +// final ACSObject parent = source.getParent(); +// if (parent instanceof ContentBundle) { +// source = (ContentBundle) parent; +// } +// +// if (LOGGER.isDebugEnabled()) { +// LOGGER.debug("Copying item " + source); +// } + final ContentItem source = retrieveSourceItem(itemId); + + final ContentItem newItem = source.copy(target, true); + Assert.isEqual(target, newItem.getParent()); + + } + } + +// protected void publishItems(final BigDecimal[] itemIds) { +// +// if (LOGGER.isDebugEnabled()) { +// LOGGER.debug("(Re-)Publishing items " + Arrays.asList(itemIds)); +// } +// +// for (BigDecimal itemId : itemIds) { +// +// final ContentItem item = retrieveSourceItem(itemId); +// +// if (item.isLive()) { +// //Republish +// //Ensure that we have the draft version +// //final ContentItem draftItem = item.getDraftVersion(); +// republish(itemId); +// } else { +// publish(itemId); +// } +// +// final LifecycleDefinition lifecycleDef = ContentTypeLifecycleDefinition +// .getLifecycleDefinition(item.getContentSection(), item.getContentType()); +// +// } +// } + +// private void publish(final BigDecimal itemId) { +// +// } +// +// private void republish(final BigDecimal itemId) { +// +// final User user = Web.getWebContext().getUser(); +// +// final Thread thread = new Thread(new Runnable() { +// +// @Override +// public void run() { +// final ContentItem item = retrieveSourceItem(itemId); +// +// PublishLock.getInstance().lock(item); +// item.republish(false); +// Workflow workflow = Workflow.getObjectWorkflow(item); +// ItemLifecycleSelectForm.finish(workflow, item, user); +// PublishLock.getInstance().unlock(item); +// } +// +// }); +// thread.setUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { +// +// @Override +// public void uncaughtException(final Thread thread, +// final Throwable ex) { +// final StringWriter strWriter = new StringWriter(); +// final PrintWriter writer = new PrintWriter(strWriter); +// ex.printStackTrace(writer); +// final ContentItem item = retrieveSourceItem(itemId); +// +// PublishLock.getInstance().setError(item, strWriter.toString()); +// LOGGER.error(String.format( +// "An error occurred while " +// + "publishing the item '%s': ", +// item.getOID().toString()), +// ex); +// +// if ((CMSConfig.getInstanceOf(). +// getPublicationFailureSender() +// == null) +// && (CMSConfig.getInstanceOf(). +// getPublicationFailureReceiver() == null)) { +// return; +// } +// +// final PartyCollection receiverParties = Party.retrieveAllParties(); +// Party receiver = null; +// receiverParties.addEqualsFilter("primaryEmail", +// CMSConfig.getInstanceOf(). +// getPublicationFailureReceiver()); +// if (receiverParties.next()) { +// receiver = receiverParties.getParty(); +// } +// receiverParties.close(); +// +// final PartyCollection senderParties = Party.retrieveAllParties(); +// Party sender = null; +// senderParties.addEqualsFilter("primaryEmail", +// CMSConfig.getInstanceOf(). +// getPublicationFailureReceiver()); +// if (senderParties.next()) { +// sender = senderParties.getParty(); +// } +// senderParties.close(); +// +// if ((sender != null) && (receiver != null)) { +// final Writer traceWriter = new StringWriter(); +// final PrintWriter printWriter = new PrintWriter( +// traceWriter); +// ex.printStackTrace(printWriter); +// +// final Notification notification = new Notification( +// sender, +// receiver, +// String.format( +// "Failed to publish item '%s'", +// item.getOID().toString()), +// String.format("Publishing item '%s' failed " +// + "with error message: %s.\n\n" +// + "Stacktrace:\n%s", +// item.getOID().toString(), +// ex.getMessage(), +// traceWriter.toString())); +// notification.save(); +// } +// } +// +// }); +// +// thread.start(); +// } + + private ContentItem retrieveSourceItem(final BigDecimal itemToCopyId) { + + ContentItem source = (ContentItem) DomainObjectFactory.newInstance( + new OID(ContentItem.BASE_DATA_OBJECT_TYPE, itemToCopyId)); + Assert.exists(source, ContentItem.class); + + final ACSObject parent = source.getParent(); + if (parent instanceof ContentBundle) { + source = (ContentBundle) parent; + } + + if (LOGGER.isDebugEnabled()) { + LOGGER.debug("Copying item " + source); + } + + return source; + } + + /** + * Returns the form that contains the folder browser and the move/copy dropdown. + * + * @return The form containing the folder browser and dropdown menu + */ + public final Form getItemView() { + return itemView; + } + + /** + * Returns the form to choose the target folder for move/copy + * + * @return + */ + public final Form getTargetSelector() { + return targetSelector; + } + + /** + * Return the browser contained in the ItemView form + * + * @return + */ + public final FolderBrowser getBrowser() { + return itemView.getBrowser(); + } + + private class ItemViewProcessListener implements FormProcessListener { + + public ItemViewProcessListener() { + //Nothing + } + + @Override + public void process(final FormSectionEvent event) throws FormProcessException { + final PageState state = event.getPageState(); + + itemView.setVisible(state, false); + targetSelector.setVisible(state, true); + targetSelector.expose(state); + } + + } + + private class TargetSelectorProcessListener implements FormProcessListener { + + public TargetSelectorProcessListener() { + //Nothing + } + + @Override + public void process(final FormSectionEvent event) throws FormProcessException { + + final PageState state = event.getPageState(); + + itemView.setVisible(state, true); + targetSelector.setVisible(state, false); + + final Folder folder = targetSelector.getTarget(state); + final BigDecimal[] itemIds = getSources(state); + + if (isCopy(state)) { + copyItems(folder, itemIds); + } else if (isMove(state)) { + moveItems(folder, itemIds); + } + + reset(state); + + } + + } + +// private class PublishDialogProcessListener implements FormProcessListener { +// +// public PublishDialogProcessListener() { +// //Nothing +// } +// +// @Override +// public void process(final FormSectionEvent event) throws FormProcessException { +// +// final PageState state = event.getPageState(); +// +// itemView.setVisible(state, true); +// publishDialog.setVisible(state, false); +// +// final BigDecimal[] itemIds = getSources(state); +// +// if (isPublish(state)) { +// publishItems(itemIds); +// } else if (isUnPublish(state)) { +// unpublishItems(itemIds); +// } +// +// reset(state); +// } +// +// } + + private class ItemViewValidationListener implements FormValidationListener { + + public ItemViewValidationListener() { + //Nothing + } + + @Override + public void validate(final FormSectionEvent event) throws FormProcessException { + + final PageState state = event.getPageState(); + final FormData data = event.getFormData(); + + if (getSources(state).length <= 0) { + data.addError(globalizationUtil.globalize("cms.ui.folder.must_select_item")); + } + } + + } + + private class TargetSelectorValidationListener implements FormValidationListener { + + public TargetSelectorValidationListener() { + //Nothing + } + + @Override + public void validate(final FormSectionEvent event) throws FormProcessException { + + final PageState state = event.getPageState(); + + if (getSources(state).length <= 0) { + throw new IllegalStateException("No source items specified"); + } + + final Folder target = targetSelector.getTarget(state); + final FormData data = event.getFormData(); + if (target == null) { + data.addError(globalizationUtil.globalize( + "cms.ui.folder.need_select_target_folder")); + //If the target is null, we can skip the rest of the checks + return; + } + + if (target.equals(sourceFolderModel.getSelectedObject(state))) { + data.addError(globalizationUtil.globalize("cms.ui.folder.not_within_same_folder")); + } + + // check create item permission + final User user = Web.getWebContext().getUser(); + final SecurityManager securityManager = CMS.getSecurityManager(state); + if (!securityManager.canAccess(user, SecurityManager.NEW_ITEM, target)) { + data.addError(globalizationUtil.globalize("cms.ui.folder.no_permission_for_item")); + } + + for (BigDecimal source : getSources(state)) { + try { + validateItem(source, target, state, data); + } catch (DataObjectNotFoundException ex) { + LOGGER.warn("Object not found in validation", ex); + throw new IllegalStateException(String.format( + "There is no item with the id '%s'", source.toString())); + } + } + + } + + private void validateItem(final BigDecimal itemId, + final Folder target, + final PageState state, + final FormData data) { + + final ContentItem item = new ContentItem(itemId); + final String name = item.getName(); + + final ItemCollection items = target.getItems(); + items.addNameFilter(name); + if (items.next()) { + // there is an item in the target folder that already has this name + addErrorMessage(data, "cms.ui.folder.item_already_exists", name); + } + items.close(); + + if (item.isLive() && isMove(state)) { + addErrorMessage(data, "cms.ui.folder.item_is_live", name); + } + + final SecurityManager securityManager = CMS.getSecurityManager(state); + final User user = Web.getWebContext().getUser(); + if ((!securityManager.canAccess(user, SecurityManager.DELETE_ITEM, item)) + && isMove(state)) { + addErrorMessage(data, "cms.ui.folder.no_permission_for_item", name); + } + } + + } + + private void addErrorMessage(final FormData data, final String message, final String itemName) { + data.addError(globalizationUtil.globalize(message, new Object[]{itemName})); + } + +// @Override +// public void submitted(final FormSectionEvent event) throws FormProcessException { +// +// final PageState state = event.getPageState(); +// +// if (targetSelector.isCancelled(state)) { +// reset(state); +// throw new FormProcessException("cms.ui.folder.cancelled"); +// +// } +// } + private class TargetSelectorSubmissionListener implements FormSubmissionListener { + + public TargetSelectorSubmissionListener() { + //Nothing + } + + @Override + public void submitted(final FormSectionEvent event) throws FormProcessException { + + final PageState state = event.getPageState(); + + if (targetSelector.isCancelled(state)) { + reset(state); + throw new FormProcessException(GlobalizationUtil.globalize("cms.ui.folder.cancelled")); + } + + } + + } + + @Override + public void reset(final PageState state) { + + itemView.setVisible(state, true); + itemView.reset(state); + targetSelector.setVisible(state, false); + targetSelector.reset(state); + //publishDialog.setVisible(state, false); + state.setValue(actionParam, null); + state.setValue(sourcesParam, null); + //s.setValue(m_aToZfilter, null); + state.setValue(filterParam, null); + + } + + // The form containing the tree to select the target folder from + private class TargetSelector extends Form implements Resettable { + + private final FolderSelectionModel targetModel; + private final FolderTree folderTree; + private final Submit cancelButton; + + public TargetSelector() { + super("targetSel", new BoxPanel()); + setMethod(GET); + targetModel = new FolderSelectionModel("target"); + folderTree = new FolderTree(targetModel); + folderTree.setCellRenderer(new FolderTreeCellRenderer()); + + final Label label = new Label(new PrintListener() { + + @Override + public void prepare(final PrintEvent event) { + final PageState state = event.getPageState(); + final Label label = (Label) event.getTarget(); + final int numberOfItems = getSources(state).length; + final Folder folder = (Folder) sourceFolderModel.getSelectedObject(state); + if (isMove(state)) { + label.setLabel(globalizationUtil.globalize( + "cms.ui.folder.move", new Object[]{numberOfItems, + folder.getPathNoJsp()})); + } else if (isCopy(state)) { + label.setLabel(globalizationUtil.globalize( + "cms.ui.folder.copy", new Object[]{numberOfItems, + folder.getPathNoJsp()})); + } + } + + }); + + label.setOutputEscaping(false); + add(label); + add(folderTree); + add(new FormErrorDisplay(this)); + final SaveCancelSection saveCancelSection = new SaveCancelSection(); + cancelButton = saveCancelSection.getCancelButton(); + add(saveCancelSection); + } + + @Override + public void register(final Page page) { + super.register(page); + page.addComponentStateParam(this, targetModel.getStateParameter()); + } + + // Set things up the first time the selector gets visible + public void expose(final PageState state) { + final Folder folder = (Folder) sourceFolderModel.getSelectedObject(state); + targetModel.clearSelection(state); + if (folder != null) { + final ItemCollection items = folder.getPathInfo(true); + while (items.next()) { + folderTree.expand(items.getID().toString(), state); + } + items.close(); + } + } + + @Override + public void reset(final PageState state) { + folderTree.clearSelection(state); + // FIXME: add a reset method to Tree and call that instead of this + // hack + state.setValue(folderTree.getSelectionModel().getStateParameter(), null); + } + + public Folder getTarget(final PageState state) { + return (Folder) targetModel.getSelectedObject(state); + } + + public boolean isCancelled(final PageState state) { + return cancelButton.isSelected(state); + } + + } + + //The form which is show for the publish and unpublish action +// private class PublishDialog extends Form { +// +// public PublishDialog() { +// super("PublishDialog", new BoxPanel()); +// +// final Label label = new Label(new PrintListener() { +// +// @Override +// public void prepare(final PrintEvent event) { +// +// final PageState state = event.getPageState(); +// final Label target = (Label) event.getTarget(); +// final int numberOfItems = getSources(state).length; +// final Folder folder = (Folder) sourceFolderModel.getSelectedObject(state); +// +// if (isPublish(state)) { +// target.setLabel(globalizationUtil.globalize( +// "cms.ui.folder.publish", +// new Object[]{numberOfItems, +// folder.getPathNoJsp()})); +// } else if (isUnPublish(state)) { +// target.setLabel(globalizationUtil.globalize( +// "cms.ui.folder.publish", +// new Object[]{numberOfItems, +// folder.getPathNoJsp()})); +// } +// } +// +// }); +// +// label.setOutputEscaping(false); +// add(label); +// add(new FormErrorDisplay(this)); +// add(new SaveCancelSection()); +// } +// +// } + + // The form containing the browser and the drop down for selecting an + // action + private class ItemView extends Form implements Resettable { + + private static final String ITEM_VIEW = "itemView"; + + private final FolderBrowser folderBrowser; + private final Paginator paginator; + private final OptionGroup checkboxGroup; + private final SingleSelect actionSelect; + private final Submit submit; + + public ItemView() { + + super(ITEM_VIEW, new SimpleContainer()); + setMethod(GET); + + final ActionGroup group = new ActionGroup(); + add(group); + + final GridPanel panel = new GridPanel(1); + group.setSubject(panel); + + folderBrowser = new FolderBrowser(sourceFolderModel); + folderBrowser.setAtoZfilterParameter(atozFilterParam); + folderBrowser.setFilterParameter(filterParam); + folderBrowser.setFilterForm(filterForm); + paginator = new Paginator((PaginationModelBuilder) folderBrowser.getModelBuilder(), + ContentSection.getConfig().getFolderBrowseListSize()); + panel.add(paginator); + panel.add(folderBrowser); + + LOGGER.debug("Adding filter form..."); + filterForm = new FilterForm((FilterFormModelBuilder) folderBrowser.getModelBuilder()); + FolderManipulator.this.add(filterForm); + + checkboxGroup = new CheckboxGroup(sourcesParam); + panel.add(checkboxGroup); + + panel.add(new FormErrorDisplay(this)); + + final Container container = new SimpleContainer(); + group.addAction(container); + + container.add(new Label(globalizationUtil.globalize("cms.ui.folder.edit_selection"))); + actionSelect = new SingleSelect(actionParam); + actionSelect.addOption(new Option(COPY, + new Label(globalizationUtil.globalize( + "cms.ui.folder.copy.action")))); + actionSelect.addOption(new Option(MOVE, + new Label(globalizationUtil.globalize( + "cms.ui.folder.move.action")))); + //Publishing in the folder browser only works if threaded publishing is active +// if (CMSConfig.getInstanceOf().getThreadedPublishing()) { +// actionSelect.addOption(new Option(PUBLISH, +// new Label(globalizationUtil.globalize( +// "cms.ui.folder.publish.action")))); +// actionSelect.addOption(new Option(UNPUBLISH, +// new Label(globalizationUtil.globalize( +// "cms.ui.folder.unpublish.action")))); +// } + container.add(actionSelect); + submit = new Submit("Go", globalizationUtil.globalize("cms.ui.folder.go")); + container.add(submit); + + // Add a new first column to the table + final TableColumn column = new TableColumn(); + column.setCellRenderer(new CheckboxRenderer()); + folderBrowser.getColumnModel().add(0, column); + } + + public final FolderBrowser getBrowser() { + return folderBrowser; + } + + @Override + public void reset(final PageState state) { + + checkboxGroup.setValue(state, null); + actionSelect.setValue(state, null); + paginator.reset(state); + //state.setValue(m_aToZfilter, null); + state.setValue(filterParam, null); + filterForm.getFilterField().setValue(state, null); + } + + // The renderer for the first column in the itemView table + private class CheckboxRenderer implements TableCellRenderer { + + public CheckboxRenderer() { + //Nothing to do + } + + @Override + public Component getComponent(final Table table, + final PageState state, + final Object value, + final boolean isSelected, + final Object key, + final int row, + final int column) { + final BigDecimal n = (BigDecimal) key; + Option result = new Option(sourcesParam.marshalElement(n.abs()), ""); + result.setGroup(checkboxGroup); + return result; + } + + } + + } + + protected class FilterForm extends Form implements FormProcessListener, + FormInitListener, + FormSubmissionListener { + + private final SimpleContainer panel; + private boolean visible; + private final FilterFormModelBuilder modelBuilder; + private final TextField filterField; + + public FilterForm(final FilterFormModelBuilder modelBuilder) { + super("folderFilterForm"); + + LOGGER.debug("Creating filter form..."); + + this.modelBuilder = modelBuilder; + + addProcessListener(this); + addInitListener(this); + addSubmissionListener(this); + + panel = new BoxPanel(BoxPanel.HORIZONTAL); + + final ActionLink allLink = new ActionLink( + globalizationUtil.globalize("cms.ui.folder.filter.all")); + allLink.addActionListener(new ActionListener() { + + @Override + public void actionPerformed(final ActionEvent event) { + //event.getPageState().setValue(m_aToZfilter, ""); + event.getPageState().setValue(filterParam, ""); + } + + }); + panel.add(allLink); + +// for (char c = 'A'; c <= 'Z'; c++) { +// final char lowerCaseChar = Character.toLowerCase(c); +// final ActionLink link = new ActionLink(Character.toString(c)); +// link.addActionListener(new ActionListener() { +// +// @Override +// public void actionPerformed(final ActionEvent event) { +// event.getPageState().setValue(m_aToZfilter, +// Character.toString(lowerCaseChar)); +// } +// }); +// panel.add(link); +// } + panel.add(new Label(globalizationUtil.globalize("cms.ui.folder.filter"))); + filterField = new TextField(filterParam); + panel.add(filterField); + panel.add(new Submit("filterFolderSubmit", + globalizationUtil.globalize("cms.ui.folder.filter_do"))); + + add(panel); + + } + + public TextField getFilterField() { + return filterField; + } + + @Override + public void process(final FormSectionEvent event) throws FormProcessException { + //Nothing + } + + @Override + public void init(final FormSectionEvent event) throws FormProcessException { + //fse.getPageState().setValue(FolderManipulator.this.m_filter, null); + //filterField.setValue(fse.getPageState(), null); + } + + @Override + public void submitted(final FormSectionEvent event) throws FormProcessException { + } + + @Override + public boolean isVisible(PageState state) { + if (super.isVisible(state) + && (modelBuilder.getFolderSize(state) + >= CMSConfig.getInstanceOf().getFolderAtoZShowLimit())) { + return true; + } else { + return false; + } + } + + } + + protected interface FilterFormModelBuilder { + + public long getFolderSize(PageState state); + + } + + /** + * Getting the GlobalizedMessage using a CMS Class targetBundle. + * + * @param key The resource key. May not null. + * + * @return The globalized message + */ +// public static GlobalizedMessage globalize(final String key) { +// return new GlobalizedMessage(key, RESOURCE_BUNDLE); +// } +// +// public static GlobalizedMessage globalize(final String key, final Object[] args) { +// return new GlobalizedMessage(key, RESOURCE_BUNDLE, args); +// } + private class FolderTreeCellRenderer implements TreeCellRenderer { + + private RequestLocal m_invalidFolders = new RequestLocal(); + + /** + * Render the folders appropriately. The selected folder is a bold label. Invalid folders + * are plain labels. Unselected, valid folders are control links. Invalid folders are: the + * parent folder of the sources, any of the sources, and any subfolders of the sources. + */ + @Override + public Component getComponent(final Tree tree, + final PageState state, + final Object value, + final boolean isSelected, + final boolean isExpanded, + final boolean isLeaf, + final Object key) { + + // Get the list of invalid folders once per request. + ArrayList invalidFolders = (ArrayList) m_invalidFolders.get(state); + + if (invalidFolders == null) { + // The list of invalid folders has not been set for this + // request. Setting now. + invalidFolders = new ArrayList(); + + final DataCollection collection = SessionManager.getSession().retrieve( + ContentItem.BASE_DATA_OBJECT_TYPE); + CompoundFilter filter = collection.getFilterFactory().or(); + // The sources themselves are not valid. + final BigDecimal[] sources = getSources(state); + + for (int i = 0; i < sources.length; i++) { + invalidFolders.add(sources[i].toString()); + + final Filter temp = filter.addFilter("id = :id" + i); + temp.set("id" + i, sources[i]); + } + collection.addFilter(filter); + + final DataCollection folders = SessionManager.getSession().retrieve( + Folder.BASE_DATA_OBJECT_TYPE); + folders.addEqualsFilter(Folder.IS_DELETED, Boolean.FALSE); + + filter = collection.getFilterFactory().or(); + int count = 0; + while (collection.next()) { + filter.addFilter(Folder.ANCESTORS + " like :ancestors" + + count + " || '%'"); + filter.set("ancestors" + count, + collection.get(ContentItem.ANCESTORS)); + count++; + } + folders.addFilter(filter); + + while (folders.next()) { + invalidFolders.add(folders.get(Folder.ID).toString()); + } + + // Get all subfolders of the sources. These are also not valid. + /* + DataQuery dq = SessionManager.getSession().retrieveQuery("com.arsdigita.cms.FoldersAndAllSubFolders"); + dq.setParameter("item_list", invalidFolders); + + while (dq.next()) { + invalidFolders.add (dq.get("folder_id").toString()); + } + */ + // The folder from which the sources are being moved/copied is + // not allowed. + invalidFolders.add(sourceFolderModel.getSelectedKey(state).toString()); + + // Save the invalid folder list + m_invalidFolders.set(state, invalidFolders); + } + + final Label label = new Label(value.toString()); + + if (invalidFolders.contains(key.toString())) { + return label; + } + + // Bold if selected + if (isSelected) { + label.setFontWeight(Label.BOLD); + return label; + } + + return new ControlLink(label); + } + + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderRequestLocal.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderRequestLocal.java new file mode 100755 index 000000000..f82279f1c --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderRequestLocal.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2003-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.ui.folder; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.cms.ui.CcmObjectRequestLocal; + +import org.apache.log4j.Logger; +import org.libreccm.categorization.Category; +import org.libreccm.categorization.CategoryRepository; +import org.libreccm.cdi.utils.CdiUtil; + + +public class FolderRequestLocal extends CcmObjectRequestLocal { + + private static final Logger s_log = Logger.getLogger( + FolderRequestLocal.class); + + private final SingleSelectionModel m_model; + + public FolderRequestLocal(final SingleSelectionModel model) { + m_model = model; + } + + public FolderRequestLocal() { + m_model = null; + } + + @Override + protected Object initialValue(final PageState state) { + if (m_model == null) { + return null; + } else { + final String id = m_model.getSelectedKey(state).toString(); + + return CdiUtil.createCdiUtil().findBean(CategoryRepository.class) + .findById(Long.parseLong(id)); + } + } + + public final Category getFolder(final PageState state) { + return (Category) get(state); + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderSelectionModel.java b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderSelectionModel.java new file mode 100755 index 000000000..3bc6e12ac --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderSelectionModel.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2001-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.ui.folder; + + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.cms.CMS; + +import com.arsdigita.cms.ItemSelectionModel; + +import org.apache.log4j.Category; +import org.librecms.contentsection.ContentSection; + +import java.math.BigDecimal; + +/** + * Keeps track of the selection of an item in a folder. The objects that + * are selected by this model are all subclasses of {@link + * com.arsdigita.cms.Folder}. + * + * @author David Lutterkort + * @version $Id$ + */ +public class FolderSelectionModel + extends ItemSelectionModel { + + public FolderSelectionModel(String name) { + super(Category.class.getName(), + Category.class.getName(), + name); + } + + public FolderSelectionModel(final SingleSelectionModel model) { + super(Category.class.getName(), + Category.class.getName(), + model); + } + + public Object getSelectedKey(PageState s) { + // FIXME: this code will go away once parameter models support init listeners + Object result = super.getSelectedKey(s); + if ( result == null ) { + result = getRootFolderID(s); + setSelectedKey(s, result); + } + return result; + } + + /** + * Clear the selection by resetting it to the root folder id. + * + * @param s represents the curent request. + */ + public void clearSelection(PageState s) { + setSelectedKey(s, getRootFolderID(s)); + } + + /** + * Return the ID of the root folder. By default, this is the root folder + * of the content section in which the current request is made. If this + * model is to be used outside a content section, this method has to be + * overriden appropriately. + * + * @param s represents the current request + * @return the ID of the root folder + * + * @pre s != null + * @post return != null + */ + protected Long getRootFolderID(PageState s) { + ContentSection sec = CMS.getContext().getContentSection(); + return sec.getRootDocumentsFolder().getObjectId(); + } + + /** + * Return true, since this selection model will always have + * a folder selected in it + */ + public boolean isSelected(PageState s) { + return true; + } + +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java.off new file mode 100755 index 000000000..f0d777d39 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/FolderTreeModelBuilder.java.off @@ -0,0 +1,204 @@ +/* + * Copyright (C) 2001-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.ui.folder; + +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.Tree; +import com.arsdigita.bebop.tree.TreeModelBuilder; +import com.arsdigita.bebop.tree.TreeNode; +import com.arsdigita.cms.CMS; +import org.librecms.contentsection.ContentSection; +import com.arsdigita.util.LockableImpl; +import java.math.BigDecimal; +import java.util.Collections; +import java.util.Iterator; +import org.apache.log4j.Logger; + +/** + * A {@link com.arsdigita.bebop.tree.TreeModelBuilder} that produces trees + * containing the folder structure underneath a root folder. The root + * folder can be changed by overriding {@link #getRoot getRoot}. + * + * @author Tri Tran + * @author David Lutterkort + * + * @version $Id: FolderTreeModelBuilder.java 2183 2011-06-20 00:57:18Z pboy $ + */ +public class FolderTreeModelBuilder extends LockableImpl + implements TreeModelBuilder { + + private static final Logger s_log = Logger.getLogger(FolderTreeModelBuilder.class); + + /** + * Make a tree model that lists the hierarchy of folders underneath the + * folder returned by {@link #getRoot getRoot}. + * + * @param t the tree in which the model is used + * @param s represents the current request + * @return a tree model that lists the hierarchy of folders underneath the + * folder returnedby {@link #getRoot getRoot}. + */ + @Override + public com.arsdigita.bebop.tree.TreeModel makeModel(final Tree t, + PageState s) { + return new DataQueryTreeModel(getRoot(s).getID(), + "com.arsdigita.cms.getRootFolder", + "com.arsdigita.cms.getSubFolders") { + + @Override + public Iterator getChildren(TreeNode node, PageState data) { + String nodeKey = node.getKey().toString(); + + // Always expand root node + if (nodeKey.equals(getRoot(data).getKey().toString()) && t.isCollapsed(nodeKey, data)) { + t.expand(nodeKey, data); + } + + if (t.isCollapsed(nodeKey, data)) { + return Collections.EMPTY_LIST.iterator(); + } + Party party = Kernel.getContext().getParty(); + OID partyOID = null; + if (party == null) { + partyOID = new OID(User.BASE_DATA_OBJECT_TYPE, + PermissionManager.VIRTUAL_PUBLIC_ID); + } else { + partyOID = party.getOID(); + } + UniversalPermissionDescriptor universalPermission = + new UniversalPermissionDescriptor(SecurityManager.CMS_PREVIEW_ITEM_DESCRIPTOR, partyOID); + if (PermissionService.checkPermission(universalPermission)) { + // the person is an admin so we just pass in the + // standard, non filtered query + return getDataQueryTreeIterator( + (DataQueryTreeNode) node, + "com.arsdigita.cms.getSubFolders"); + } else { + // now we need to set the parameters + return new NewFolderBrowserIterator( + (DataQueryTreeNode) node, + partyOID); + } + } + }; + } + + /** + * Retrn the root folder for the tree model in the current + * request. + * @param s represents the current request + * @return the root folder for the tree + * @post return != null + */ + protected Folder getRoot(PageState s) + throws IllegalStateException { + ContentSection sec = CMS.getContext().getContentSection(); + return sec.getRootFolder(); + } + + private class NewFolderBrowserIterator implements Iterator { + + private DataQuery m_nodes; + + public NewFolderBrowserIterator(DataQueryTreeNode node, OID partyOID) { + + BigDecimal userID = (BigDecimal) partyOID.get("id"); + + String sql = "" + + "\n select f.folder_id as id," + + "\n f.label as name," + + "\n count(sub.item_id) as nchild" + + "\n from cms_folders f," + + "\n cms_items i" + + "\n left join" + + "\n (select i2.item_id, f2.label as name, i2.parent_id" + + "\n from cms_folders f2," + + "\n cms_items i2" + + "\n where f2.folder_id = i2.item_id) sub" + + "\n on (sub.parent_id = i.item_id" + + "\n and" + + "\n exists (select 1" + + "\n from dnm_object_1_granted_context dogc," + + "\n dnm_granted_context dgc," + + "\n dnm_permissions dp," + + "\n dnm_group_membership dgm" + + "\n where dogc.pd_object_id = sub.item_id" + + "\n and dogc.pd_context_id = dgc.pd_object_id" + + "\n and dgc.pd_context_id = dp.pd_object_id" + + "\n and dp.pd_grantee_id = dgm.pd_group_id" + + "\n and dgm.pd_member_id in (-200," + userID + ",-202)" + + "\n and dp." + TREE_DESCRIPTOR.getColumnName() + " = '1'" + + "\n ) )" + + "\n where i.parent_id = " + node.getID() + + "\n and f.folder_id = i.item_id" + + "\n and exists (" + + "\n select 1 as permission_p" + + "\n from dnm_object_1_granted_context dogc," + + "\n dnm_granted_context dgc," + + "\n dnm_permissions dp," + + "\n dnm_group_membership dgm" + + "\n where dogc.pd_context_id = dgc.pd_object_id" + + "\n and dgc.pd_context_id = dp.pd_object_id" + + "\n and dgm.pd_member_id in (-200," + userID + ",-202)" + + "\n and dp.pd_grantee_id = dgm.pd_group_id" + + "\n and dogc.pd_object_id = f.folder_id" + + "\n and dp." + TREE_DESCRIPTOR.getColumnName() + " = '1' )" + + "\n group by f.label, f.folder_id" + + "\n order by lower(f.label)"; + + if (s_log.isDebugEnabled()) { + s_log.debug("Custom SQL: \n" + sql); + } + + m_nodes = new GenericDataQuery( + SessionManager.getSession(), + sql, + new String[]{"id", "name", "nchild"}); + } + + @Override + public Object next() { + BigDecimal id = new BigDecimal(0); + try { + // this appears to be the only portable way to dig numbers out + // of the result set + id = new BigDecimal(m_nodes.get("id").toString()); + } catch (NumberFormatException nfe) { + } + String name = m_nodes.get("name").toString(); + BigDecimal count = new BigDecimal(0); + try { + count = new BigDecimal(m_nodes.get("nchild").toString()); + } catch (NumberFormatException nfe) { + } + + return new DataQueryTreeNode(id, name, count.intValue() > 0); + } + + @Override + public void remove() { + throw new UnsupportedOperationException("cannot remove nodes via iterator"); + } + + @Override + public boolean hasNext() { + return m_nodes.next(); + } + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/ItemPath.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/ItemPath.java.off new file mode 100755 index 000000000..01057a6aa --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/folder/ItemPath.java.off @@ -0,0 +1,77 @@ +/* + * Copyright (C) 2001-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.ui.folder; + +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.PageState; +import com.arsdigita.cms.ContentItem; +import com.arsdigita.cms.ItemCollection; +import com.arsdigita.cms.ItemSelectionModel; +import com.arsdigita.util.LockableImpl; + +/** + * Produce a list of the items starting from the selected item's root down + * to the item itself. + * + * @author David Lutterkort + * @version $Id: ItemPath.java 1940 2009-05-29 07:15:05Z terry $ + */ +public class ItemPath extends List { + + public ItemPath(ItemSelectionModel folderSel) { + super(new ListModelBuilder(folderSel)); + setAttribute("type", "item-path"); + setSelectionModel(folderSel); + } + + public static class ListModel + implements com.arsdigita.bebop.list.ListModel { + ItemCollection m_coll; + + public ListModel(ContentItem i) { + m_coll = i.getPathInfo(true); + } + + public boolean next() { + return m_coll.next(); + } + + public Object getElement() { + return m_coll.getName(); + } + + public String getKey() { + return m_coll.getID().toString(); + } + } + + public static class ListModelBuilder extends LockableImpl + implements com.arsdigita.bebop.list.ListModelBuilder { + + ItemSelectionModel m_itemSel; + + public ListModelBuilder(ItemSelectionModel itemSel) { + m_itemSel = itemSel; + } + + public com.arsdigita.bebop.list.ListModel makeModel(List l, final PageState s) { + return new ListModel((ContentItem) m_itemSel.getSelectedObject(s)); + } + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleAdminPane.java.off new file mode 100755 index 000000000..a375e8f39 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/lifecycle/LifecycleAdminPane.java.off @@ -0,0 +1,110 @@ +/* + * Copyright (C) 2003-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.ui.lifecycle; + +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.SecurityManager; +import com.arsdigita.cms.lifecycle.LifecycleDefinition; +import com.arsdigita.cms.ui.BaseAdminPane; +import com.arsdigita.cms.ui.BaseDeleteForm; +import com.arsdigita.cms.ui.FormSecurityListener; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; + +/** + *

This class contains the split pane for the lifecycle administration + * interface.

+ * + * @author Michael Pih + * @author Jack Chung + * @author Justin Ross <jross@redhat.com> + * @version $Id: LifecycleAdminPane.java 1942 2009-05-29 07:53:23Z terry $ + */ +public class LifecycleAdminPane extends BaseAdminPane { + + private static Logger s_log = Logger.getLogger(LifecycleAdminPane.class); + + private final SingleSelectionModel m_model; + private final LifecycleDefinitionRequestLocal m_definition; + + public LifecycleAdminPane() { + super(new Label(gz("cms.ui.lifecycles")), + new LifecycleListModelBuilder()); + + m_model = getSelectionModel(); + m_definition = new SelectionRequestLocal(); + + // XXX secvis + //add(new LifecycleAdminContainer(m_addLink)); + + setAdd(gz("cms.ui.lifecycle.add"), + new LifecycleAddForm(m_model)); + setEdit(gz("cms.ui.lifecycle.edit"), + new LifecycleEditForm(m_definition)); + setDelete(gz("cms.ui.lifecycle.delete"), new DeleteForm()); + + setIntroPane(new Label(gz("cms.ui.lifecycle.intro"))); + setItemPane(new LifecycleItemPane(m_definition, + getEditLink(), + getDeleteLink())); + + addAction(new LifecycleAdminContainer(getAddLink())); + } + + private class SelectionRequestLocal + extends LifecycleDefinitionRequestLocal { + protected final Object initialValue(final PageState state) { + final String id = m_model.getSelectedKey(state).toString(); + + return new LifecycleDefinition(new BigDecimal(id)); + } + } + + private final class DeleteForm extends BaseDeleteForm { + DeleteForm() { + super(new Label(gz("cms.ui.lifecycle.delete_prompt"))); + + addSubmissionListener + (new FormSecurityListener(SecurityManager.LIFECYCLE_ADMIN)); + } + + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + final ContentSection section = + CMS.getContext().getContentSection(); + final LifecycleDefinition definition = + m_definition.getLifecycleDefinition(state); + + section.removeLifecycleDefinition(definition); + section.save(); + + definition.delete(); + + m_model.clearSelection(state); + } + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/role/RoleAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/role/RoleAdminPane.java.off new file mode 100755 index 000000000..a85df6ba5 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/role/RoleAdminPane.java.off @@ -0,0 +1,208 @@ +/* + * Copyright (C) 2003-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.ui.role; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.List; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.SimpleContainer; +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.event.ChangeEvent; +import com.arsdigita.bebop.event.ChangeListener; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.list.ListModel; +import com.arsdigita.bebop.list.ListModelBuilder; +import com.arsdigita.bebop.parameters.StringParameter; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.ui.BaseAdminPane; +import com.arsdigita.cms.ui.BaseDeleteForm; +import com.arsdigita.cms.ui.VisibilityComponent; +import com.arsdigita.kernel.Role; +import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.toolbox.ui.Section; +import com.arsdigita.util.LockableImpl; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; + +/** + * @author Justin Ross <jross@redhat.com> + * @version $Id: RoleAdminPane.java 287 2005-02-22 00:29:02Z sskracic $ + */ +public class RoleAdminPane extends BaseAdminPane { + + private static final Logger s_log = Logger.getLogger(RoleAdminPane.class); + + private final SingleSelectionModel m_model; + private final RoleRequestLocal m_role; + + private final List m_staff; + private final List m_viewers; + + public RoleAdminPane() { + m_model = new ParameterSingleSelectionModel + (new StringParameter(List.SELECTED)); + setSelectionModel(m_model); + + m_model.addChangeListener(new SelectionListener()); + + m_role = new SelectionRequestLocal(); + + m_staff = new List(new StaffListModelBuilder()); + m_staff.setSelectionModel(m_model); + + m_viewers = new List(new ViewerListModelBuilder()); + m_viewers.setSelectionModel(m_model); + + final SimpleContainer left = new SimpleContainer(); + setLeft(left); + + final StaffSection staff = new StaffSection(); + left.add(staff); + + final ViewerSection viewers = new ViewerSection(); + left.add(viewers); + + // XXX there need to be two edit forms with different boolean + // args. this is broken + setEdit(gz("cms.ui.role.edit"), new RoleEditForm(m_role, false)); + setDelete(gz("cms.ui.role.delete"), new DeleteForm()); + + setIntroPane(new Label(gz("cms.ui.role.intro"))); + setItemPane(new BaseRoleItemPane(m_model, m_role, + getEditLink(), getDeleteLink())); + } + + private class StaffSection extends Section { + StaffSection() { + setHeading(gz("cms.ui.role.staff")); + + final ActionGroup group = new ActionGroup(); + setBody(group); + + group.setSubject(m_staff); + + final ActionLink link = new ActionLink + (new Label(gz("cms.ui.role.staff.add"))); + + group.addAction(new VisibilityComponent(link, STAFF_ADMIN), + ActionGroup.ADD); + + final RoleAddForm form = new RoleAddForm(m_model, false); + getBody().add(form); + getBody().connect(link, form); + } + } + + private class ViewerSection extends Section { + ViewerSection() { + setHeading(gz("cms.ui.role.viewers")); + + final ActionGroup group = new ActionGroup(); + setBody(group); + + group.setSubject(m_viewers); + + final ActionLink link = new ActionLink + (new Label(gz("cms.ui.role.viewer.add"))); + + group.addAction(new VisibilityComponent(link, STAFF_ADMIN), + ActionGroup.ADD); + + final RoleAddForm form = new RoleAddForm(m_model, true); + getBody().add(form); + getBody().connect(link, form); + } + } + + private class SelectionListener implements ChangeListener { + public final void stateChanged(final ChangeEvent e) { + s_log.debug("Selection state changed; I may change " + + "the body's visible pane"); + + final PageState state = e.getPageState(); + + getBody().reset(state); + + if (m_model.isSelected(state)) { + s_log.debug("The selection model is selected; displaying " + + "the item pane"); + + getBody().push(state, getItemPane()); + } + } + } + + private class SelectionRequestLocal extends RoleRequestLocal { + protected final Object initialValue(final PageState state) { + final String id = m_model.getSelectedKey(state).toString(); + + return new Role(new BigDecimal(id)); + } + } + + private static class StaffListModelBuilder extends LockableImpl + implements ListModelBuilder { + public StaffListModelBuilder() { + super(); + } + + public final ListModel makeModel(final List list, + final PageState state) { + final ContentSection section = + CMS.getContext().getContentSection(); + + return new RoleListModel + (section.getStaffGroup().getOrderedRoles()); + } + } + + private static class ViewerListModelBuilder extends LockableImpl + implements ListModelBuilder { + public final ListModel makeModel(final List list, + final PageState state) { + final ContentSection section = + CMS.getContext().getContentSection(); + + return new RoleListModel + (section.getViewersGroup().getOrderedRoles()); + } + } + + private class DeleteForm extends BaseDeleteForm { + DeleteForm() { + super(gz("cms.ui.role.delete_prompt")); + + addSecurityListener(STAFF_ADMIN); + } + + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + + m_role.getRole(state).delete(); + + m_model.clearSelection(state); + } + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/type/ContentTypeAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/type/ContentTypeAdminPane.java.off new file mode 100755 index 000000000..97a8aaacd --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/type/ContentTypeAdminPane.java.off @@ -0,0 +1,292 @@ +/* + * Copyright (C) 2003-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.ui.type; + +import com.arsdigita.bebop.ActionLink; +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.Page; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.GridPanel; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.bebop.event.ActionEvent; +import com.arsdigita.bebop.event.ActionListener; +import com.arsdigita.bebop.event.FormProcessListener; +import com.arsdigita.bebop.event.FormSubmissionListener; +import com.arsdigita.cms.CMS; +import com.arsdigita.cms.ContentSection; +import com.arsdigita.cms.ContentType; +import com.arsdigita.cms.ContentTypeCollection; +import com.arsdigita.cms.SectionTemplateMapping; +import com.arsdigita.cms.ui.BaseAdminPane; +import com.arsdigita.cms.ui.BaseDeleteForm; +import com.arsdigita.cms.ui.ContentSectionPage; +import com.arsdigita.cms.util.GlobalizationUtil; +import com.arsdigita.kernel.ACSObject; +import com.arsdigita.domain.DomainCollection; +import com.arsdigita.persistence.DataCollection; +import com.arsdigita.persistence.SessionManager; +import com.arsdigita.kernel.ui.ACSObjectSelectionModel; +import com.arsdigita.toolbox.ui.ActionGroup; +import com.arsdigita.toolbox.ui.Section; +import com.arsdigita.toolbox.ui.Cancellable; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; + +/** + * This class contains the split pane for the ContentType + * administration interface. + * + * @author Jack Chung + * @author Michael Pih + * @author Stanislav Freidin + * @author Justin Ross <jross@redhat.com> + * @version $Id: ContentTypeAdminPane.java 1942 2009-05-29 07:53:23Z terry $ + */ +public final class ContentTypeAdminPane extends BaseAdminPane { + + private static final Logger s_log = Logger.getLogger(ContentTypeAdminPane.class); + private final ACSObjectSelectionModel m_model; + private final ContentTypeRequestLocal m_type; + + /** + * Constructs an admin pane. It is containing + * (a) + * a list of available content types in a + * given content section and adds a link to make additional content types + * available (out of a list of installed, but available in a given content + * section). + */ + public ContentTypeAdminPane() { + + // + super(new Label(gz("cms.ui.types")), + new ContentTypeListModelBuilder() ); //list with all Types avail. + + m_model = new ACSObjectSelectionModel(getSelectionModel()); + m_type = new SelectionRequestLocal(); + + ActionLink addTypeLink = new ActionLink(new Label(gz("cms.ui.type.add"))); + + AddTypeContainer addTypeContainer = new AddTypeContainer(); + getBody().add(addTypeContainer); + getBody().connect(addTypeLink, addTypeContainer); + addTypeLink.addActionListener(addTypeContainer); + + setEdit(new ActionLink(new Label(gz("cms.ui.type.edit"))), + new EditType(m_model)); + + setDelete(new ActionLink(new Label(gz("cms.ui.type.delete"))), + new DeleteForm()); + + setIntroPane(new Label(gz("cms.ui.type.intro"))); + setItemPane(new ContentTypeItemPane(m_model, + m_type, + getEditLink(), + getDeleteLink())); + + addAction(new TypeSecurityContainer(addTypeLink), ActionGroup.ADD); + } + + @Override + public void register(Page p) { + super.register(p); + + p.addActionListener(new ActionListener() { + + /** + * + * @param e + */ + @Override + public void actionPerformed(ActionEvent e) { + final PageState state = e.getPageState(); + ContentType contentType = (ContentType) m_model.getSelectedObject(state); + ContentSection section = CMS.getContext().getContentSection(); + if (contentType == null) { + final String template = state.getRequest() + .getParameter(ContentSectionPage + .SET_TEMPLATE); + if (template != null) { + DataCollection da = SessionManager.getSession().retrieve(SectionTemplateMapping.BASE_DATA_OBJECT_TYPE); + DomainCollection c = new DomainCollection(da); + c.addEqualsFilter(SectionTemplateMapping.SECTION + "." + ACSObject.ID, + section.getID()); + c.addEqualsFilter(SectionTemplateMapping.TEMPLATE + "." + ACSObject.ID, + new BigDecimal(template)); + c.addOrder(SectionTemplateMapping.CONTENT_TYPE + "." + ContentType.LABEL); + if (c.next()) { + SectionTemplateMapping mapping = + (SectionTemplateMapping) c.getDomainObject(); + contentType = mapping.getContentType(); + } + c.close(); + } + if (contentType == null) { + ContentTypeCollection contentTypes = section.getContentTypes(); + contentTypes.addOrder("label asc"); + try { + if (contentTypes.next()) { + contentType = contentTypes.getContentType(); + } + } finally { + contentTypes.close(); + } + } + if (contentType != null) { + m_model.setSelectedObject(state, contentType); + getBody().push(state, getItemPane()); + } + + + } + } + }); + } + + /** + * + */ + private class AddTypeContainer extends GridPanel implements ActionListener, + FormProcessListener { + + private Label m_noTypesAvailable = + new Label(gz("cms.ui.type.select.none")); + private SelectType m_selectType; + private CreateType m_createType; + + /** + * + */ + AddTypeContainer() { + super(1); + Section selectSection = new Section(); + selectSection.setHeading(new Label(gz("cms.ui.type.select"))); + add(selectSection); + + GridPanel container = new GridPanel(1); + container.add(m_noTypesAvailable); + m_selectType = new SelectType(); + m_selectType.addSubmissionListener(new CancelListener(m_selectType)); + m_selectType.addProcessListener(this); + container.add(m_selectType); + selectSection.setBody(container); + + Section addSection = new Section() { + + @Override + public final boolean isVisible(final PageState state) { + return super.isVisible(state) + && !ContentSection.getConfig().getHideUDCTUI(); + } + }; + addSection.setHeading(new Label(gz("cms.ui.type.define"))); + m_createType = new CreateType(m_model); + m_createType.addSubmissionListener(new CancelListener(m_createType)); + m_createType.addProcessListener(this); + addSection.setBody(m_createType); + add(addSection); + } + + /** + * + * @param e + */ + @Override + public void actionPerformed(ActionEvent e) { + PageState s = e.getPageState(); + ContentSection section = CMS.getContext().getContentSection(); + ContentTypeCollection contentTypes = + section.getNotAssociatedContentTypes(); + boolean hasAvailableTypes = !contentTypes.isEmpty(); + m_selectType.setVisible(s, hasAvailableTypes); + m_noTypesAvailable.setVisible(s, !hasAvailableTypes); + } + + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + resetPane(state); + } + } + + /** + * This class is essentially a copy of the CancelListener inside of + * ModalPanel. We could not use the one in ModalPanel because it was + * protected + */ + private final class CancelListener implements FormSubmissionListener { + + Cancellable m_form; + + CancelListener(Cancellable form) { + m_form = form; + } + + @Override + public void submitted(FormSectionEvent event) + throws FormProcessException { + PageState state = event.getPageState(); + if (m_form.isCancelled(state)) { + getBody().pop(state); + throw new FormProcessException(GlobalizationUtil.globalize( + "cms.ui.type.cancelled")); + } + } + } // end private class + + private void resetPane(PageState state) { + getBody().reset(state); + if (getSelectionModel().isSelected(state)) { + s_log.debug("The selection model is selected; displaying " + + "the item pane"); + getBody().push(state, getItemPane()); + } + } + + private class SelectionRequestLocal extends ContentTypeRequestLocal { + + protected final Object initialValue(final PageState state) { + ContentType contentType = (ContentType) m_model.getSelectedObject(state); + return contentType; + } + } + + private class DeleteForm extends BaseDeleteForm { + + DeleteForm() { + super(new Label(gz("cms.ui.type.delete_prompt"))); + + addSubmissionListener(new TypeSecurityListener()); + } + + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + final ContentSection section = + CMS.getContext().getContentSection(); + + section.removeContentType(m_type.getContentType(state)); + section.save(); + + getSelectionModel().clearSelection(state); + } + } +} diff --git a/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/WorkflowAdminPane.java.off b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/WorkflowAdminPane.java.off new file mode 100755 index 000000000..cb251c487 --- /dev/null +++ b/ccm-cms/src/main/java/com/arsdigita/cms/ui/workflow/WorkflowAdminPane.java.off @@ -0,0 +1,89 @@ +/* + * Copyright (C) 2001-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.ui.workflow; + +import com.arsdigita.bebop.FormProcessException; +import com.arsdigita.bebop.Label; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.event.FormSectionEvent; +import com.arsdigita.cms.SecurityManager; +import com.arsdigita.cms.ui.BaseAdminPane; +import com.arsdigita.cms.ui.BaseDeleteForm; +import com.arsdigita.cms.ui.VisibilityComponent; +import com.arsdigita.workflow.simple.WorkflowTemplate; +import org.apache.log4j.Logger; + +import java.math.BigDecimal; + +/** + * @author Justin Ross <jross@redhat.com> + * @version $Id: WorkflowAdminPane.java 287 2005-02-22 00:29:02Z sskracic $ + */ +public final class WorkflowAdminPane extends BaseAdminPane { + + private static final Logger s_log = Logger.getLogger + (WorkflowAdminPane.class); + + private final WorkflowRequestLocal m_workflow; + + public WorkflowAdminPane() { + super(gz("cms.ui.workflows"), new WorkflowListModelBuilder()); + + m_workflow = new SelectionRequestLocal(); + + setAdd(gz("cms.ui.workflow.add"), + new WorkflowAddForm(getSelectionModel())); + setEdit(gz("cms.ui.workflow.edit"), new WorkflowEditForm(m_workflow)); + setDelete(gz("cms.ui.workflow.delete"), new DeleteForm()); + + setIntroPane(new Label(gz("cms.ui.workflow.intro"))); + setItemPane(new WorkflowItemPane(m_workflow, + getEditLink(), + getDeleteLink())); + + addAction(new VisibilityComponent(getAddLink(), + SecurityManager.WORKFLOW_ADMIN)); + } + + private class DeleteForm extends BaseDeleteForm { + DeleteForm() { + super(gz("cms.ui.workflow.delete_prompt")); + + addSecurityListener(SecurityManager.WORKFLOW_ADMIN); + } + + public final void process(final FormSectionEvent e) + throws FormProcessException { + final PageState state = e.getPageState(); + + m_workflow.getWorkflow(state).delete(); + + getSelectionModel().clearSelection(state); + } + } + + private class SelectionRequestLocal extends WorkflowRequestLocal { + protected final Object initialValue(final PageState state) { + final String id = getSelectionModel().getSelectedKey + (state).toString(); + + return new WorkflowTemplate(new BigDecimal(id)); + } + } +} diff --git a/ccm-cms/src/main/java/org/librecms/CmsConstants.java b/ccm-cms/src/main/java/org/librecms/CmsConstants.java index 75a3397c5..a911fa08e 100644 --- a/ccm-cms/src/main/java/org/librecms/CmsConstants.java +++ b/ccm-cms/src/main/java/org/librecms/CmsConstants.java @@ -29,6 +29,7 @@ public class CmsConstants { public static final String DB_SCHEMA = "CCM_CMS"; public static final String CMS_BUNDLE = "org.librecms.CmsResources"; + public static final String CMS_FOLDER_BUNDLE = "com.arsdigita.cms.ui.folder.CMSFolderResources"; public static final String CONTENT_CENTER_APP_TYPE = "com.arsdigita.cms.ContentCenter"; public static final String CONTENT_CENTER_URL = "/content-center/"; @@ -40,6 +41,9 @@ public class CmsConstants { = "/templates/servlet/content-section/*"; public static final String CONTENT_SECTION_DESC_BUNDLE = "org.librecms.contentsection.ContentSectionResources"; + + public static final String CONTENT_SECTION_PAGE = "/admin"; + public static final String CONTENT_SECTION_ITEM_PAGE = "/item"; public static final String CATEGORIZATION_TYPE_FOLDER = "folder"; diff --git a/ccm-cms/src/main/java/org/librecms/contentsection/ContentTypeRepository.java b/ccm-cms/src/main/java/org/librecms/contentsection/ContentTypeRepository.java new file mode 100644 index 000000000..a39638840 --- /dev/null +++ b/ccm-cms/src/main/java/org/librecms/contentsection/ContentTypeRepository.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2016 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.contentsection; + +import org.libreccm.core.AbstractEntityRepository; + +import javax.enterprise.context.RequestScoped; + +/** + * + * @author Jens Pelzetter + */ +@RequestScoped +public class ContentTypeRepository + extends AbstractEntityRepository{ + + @Override + public Class getEntityClass() { + return ContentType.class; + } + + @Override + public boolean isNew(final ContentType type) { + return type.getObjectId() == 0; + } + +} diff --git a/ccm-cms/src/main/resources/com/arsdigita/cms/ui/folder/CMSFolderResources.properties b/ccm-cms/src/main/resources/com/arsdigita/cms/ui/folder/CMSFolderResources.properties new file mode 100755 index 000000000..3889c119a --- /dev/null +++ b/ccm-cms/src/main/resources/com/arsdigita/cms/ui/folder/CMSFolderResources.properties @@ -0,0 +1,79 @@ +COMMENT.00=BUTTONS/LINKS/LABELS +cms.ui.folder.edit_selection=What to do with checked items +cms.ui.folder.save=Save +cms.ui.folder.cancel=Cancel +cms.ui.folder.edit=Edit +cms.ui.folder.delete=Delete +cms.ui.folder.move=Move {0} items from {1} to {2}. +cms.ui.folder.copy=Copy {0} items from {1} +cms.ui.folder.go=Go +cms.ui.folder.name=Name +cms.ui.folder.type=Type +cms.ui.folder.creation_date=Creation Date +cms.ui.folder.last_modified=Last Modified +cms.ui.folder.action=Action +cms.ui.folder.title=Title +cms.ui.folder.index=Index +cms.ui.folder.preview=Preview +cms.ui.folder.lock=Lock +cms.ui.folder.unlock=Unlock +cms.ui.folder.external_lock=External lock +cms.ui.folder.left=Left +cms.ui.folder.right=Right +cms.ui.folder.items=item(s) +cms.ui.folder.from=from +cms.ui.folder.to=to +cms.ui.folder.no_items=No Items +cms.ui.folder.no_image=No image +cms.ui.folder.hide_metadata=Hide metadata +cms.ui.folder.show_metadata=Show metadata +cms.ui.folder.edit_subject_classes=Edit subject classes +cms.ui.folder.add_paragraph=Add a paragraph +cms.ui.folder.edit_in_applet=Edit In EoPro +cms.ui.folder.edit_in_browser=Edit In Browser + +cms.ui.folder.edit_current_folder=Edit Current Folder +cms.ui.folder.preview_current_folder=Preview Current Folder +cms.ui.folder.contents_for=Contents for  +cms.ui.folder.choose_target_folder=Choose target folder +cms.ui.foldr.new_wcms_doc=New WCMS Documents + +COMMENT.05=INPUTS +cms.ui.folder.left=Left +cms.ui.folder.right=Right + +COMMENT.10=FOLDER METADATA + +cms.ui.folder.headline=Headline +cms.ui.folder.heading=Heading +cms.ui.folder.body=Body +cms.ui.folder.add_image=Add an Image +cms.ui.folder.replace_image=Replace this Image +cms.ui.folder.align=Align +cms.ui.folder.add_download=Add a Download +cms.ui.folder.alt=Alt +cms.ui.folder.caption=Caption +cms.ui.folder.remove_asset_link=Remove + +COMMENT.20=ERROR MESSAGES +cms.ui.folder.column_index_not_in_table_model=Column index not in table model: +cms.ui.folder.cannot_find_root_folder=Cannot find a root folder. +cms.ui.folder.must_select_item=You must select at least one item to move/copy +cms.ui.folder.no_source_items_specified=No source items specified. +cms.ui.folder.need_select_target_folder=You need to select a folder to which the items should be copied/moved. +cms.ui.folder.not_within_same_folder=Cannot move/copy items within the same folder. +cms.ui.folder.no_permission=You do not have permission to create, copy, or move items. +cms.ui.folder.item_already_exists=There is already an item in the target folder named: {0} +cms.ui.folder.item_is_live= {0} is live; you must unpublish it before moving it. +cms.ui.folder.no_permission_for_item=You do not have permission to delete or move {0}. +cms.ui.folder.no_such_item=Item ID supplied does not match an existing Content Item. +cms.ui.folder.filter.all=All +cms.ui.folder.filter=Filter for work +cms.ui.folder.filter_do=Filter +cms.ui.folder.languages=Languages +cms.ui.folder.delete_confirmation=Permanently delete this item? +cms.ui.folder.additionalInfo=Info +cms.ui.folder.move.action=Move +cms.ui.folder.copy.action=Copy +cms.ui.folder.publish.action=(Re-)publish +cms.ui.folder.unpublish.action=Unpublish diff --git a/ccm-cms/src/main/resources/com/arsdigita/cms/ui/folder/CMSFolderResources_de.properties b/ccm-cms/src/main/resources/com/arsdigita/cms/ui/folder/CMSFolderResources_de.properties new file mode 100755 index 000000000..28ee56db9 --- /dev/null +++ b/ccm-cms/src/main/resources/com/arsdigita/cms/ui/folder/CMSFolderResources_de.properties @@ -0,0 +1,79 @@ +COMMENT.00=BUTTONS/LINKS/LABELS +cms.ui.folder.save=Speichern +cms.ui.folder.cancel=Abbrechen +cms.ui.folder.edit=Editieren +cms.ui.folder.delete=L\u00f6schen +cms.ui.folder.move=Verschiebe {0} Dokumente von {1} nach {2}. +cms.ui.folder.copy=Kopiere {0} Dokumente von {1} nach +cms.ui.folder.go=Los +cms.ui.folder.name=Name +cms.ui.folder.type=Typ +cms.ui.folder.action=Aktion +cms.ui.folder.title=Titel +cms.ui.folder.preview=Voransicht +cms.ui.folder.lock=Sperren +cms.ui.folder.unlock=Entsperren +cms.ui.folder.external_lock=Externe Sperrung +cms.ui.folder.left=Links +cms.ui.folder.right=Rechts +cms.ui.folder.items=Eintrag/Eintr\u00e4ge +cms.ui.folder.from=von +cms.ui.folder.to=an +cms.ui.folder.no_items=Keine Eintr\u00e4ge +cms.ui.folder.no_image=Kein Bild +cms.ui.folder.hide_metadata=Metadaten verbergen +cms.ui.folder.show_metadata=Zeige die Metadaten +cms.ui.folder.edit_subject_classes=Themenklassen editieren +cms.ui.folder.add_paragraph=Abschnitt hinzuf\u00fcgen +cms.ui.folder.edit_in_applet=In EoPro editieren +cms.ui.folder.edit_in_browser=Im Browser editieren + +cms.ui.folder.edit_current_folder=Bearbeiten des aktuellen Verzeichnisses +cms.ui.folder.preview_current_folder=Vorschau des aktuellen Verzeichnisses +cms.ui.folder.contents_for=Inhalt f\u00fcr +cms.ui.folder.choose_target_folder=Zielverzeichnis ausw\u00e4hlen +cms.ui.foldr.new_wcms_doc=Neue WCMS Documente + +COMMENT.05=INPUTS +cms.ui.folder.left=Links +cms.ui.folder.right=Rechts + +COMMENT.10=FOLDER METADATA +cms.ui.folder.headline=Titelzeile +cms.ui.folder.heading=\u00dcberschrift +cms.ui.folder.body=Hauptbereich +cms.ui.folder.add_image=Bild hinzuf\u00fcgen +cms.ui.folder.replace_image=Ersetze dieses Bild +cms.ui.folder.align=Ausrichten +cms.ui.folder.add_download=Download hinzuf\u00fcgen +cms.ui.folder.alt=Alt +cms.ui.folder.caption=\u00dcberschrift + +COMMENT.20=ERROR MESSAGES +cms.ui.folder.column_index_not_in_table_model=Spaltenindex befindet sich nicht im Datenbankmodell: +cms.ui.folder.cannot_find_root_folder=Oberster Ordner kann nicht gefunden werden. +cms.ui.folder.must_select_item=Es mu\u00df mindestens ein Eintrag zum Verschieben/Kopieren ausgew\u00e4hlt werden +cms.ui.folder.no_source_items_specified=Es wurden keine Ursprungseintr\u00e4ge gew\u00e4hlt +cms.ui.folder.need_select_target_folder=Es mu\u00df ein Ordner ausgew\u00e4hlt werden, in den die Eintr\u00e4ge verschoben oder kopiert werden sollen. +cms.ui.folder.not_within_same_folder=Kopieren/Verschieben im gleichen Ordner nicht m\u00f6glich +cms.ui.folder.no_permission=Sie haben nicht die Berechtigung Eintr\u00e4ge zu erzeugen, zu kopieren oder zu verschieben. +cms.ui.folder.item_already_exists=Es gibt schon einen Eintrag im Zielordner mit Namen: {0} +cms.ui.folder.item_is_live={0} ist ver\u00f6ffentlicht. Sie m\u00fcssen ihn zum Verschieben depublizieren. +cms.ui.folder.no_permission_for_item=Sie haben nicht die Berechtigung {0} zum L\u00f6schen oder Verschieben. +cms.ui.folder.no_such_item=Die verwendete Eintrags-ID pa\u00dft zu keinem Eintrag. + +cms.ui.folder.remove_asset_link=Entfernen +cms.ui.folder.filter.all=Alle +cms.ui.folder.filter=Nach Begriff filtern +cms.ui.folder.filter_do=Filtern +cms.ui.folder.languages=Sprachen +cms.ui.folder.delete_confirmation=Wollen Sie dieses Content-Item l\u00f6schen? +cms.ui.folder.edit_selection=Ausgew\u00e4hlte Items +cms.ui.folder.creation_date=Erstellungsdatum +cms.ui.folder.last_modified=Letzte \u00c4nderung +cms.ui.folder.index=Index +cms.ui.folder.additionalInfo=Info +cms.ui.folder.move.action=Verschieben +cms.ui.folder.copy.action=Kopieren +cms.ui.folder.publish.action=(Re-)Publizieren +cms.ui.folder.unpublish.action=Depublizieren diff --git a/ccm-cms/src/main/resources/com/arsdigita/cms/ui/folder/CMSFolderResources_fr.properties b/ccm-cms/src/main/resources/com/arsdigita/cms/ui/folder/CMSFolderResources_fr.properties new file mode 100755 index 000000000..094cf3b85 --- /dev/null +++ b/ccm-cms/src/main/resources/com/arsdigita/cms/ui/folder/CMSFolderResources_fr.properties @@ -0,0 +1,74 @@ +COMMENT.00=BOUTONS/LIENS/LIBELLE +cms.ui.folder.save=Sauver +cms.ui.folder.cancel=Annuler +cms.ui.folder.edit=Modifier +cms.ui.folder.delete=Effacer +cms.ui.folder.move= +cms.ui.folder.copy= +cms.ui.folder.go=Go +cms.ui.folder.name=Nom +cms.ui.folder.type=Type +cms.ui.folder.action=Action +cms.ui.folder.title=Titre +cms.ui.folder.index=Index +cms.ui.folder.preview=Pr\u00e9-visualisation +cms.ui.folder.lock=Verrouiller +cms.ui.folder.unlock=D\u00e9-v\u00e9rrouiller +cms.ui.folder.external_lock=Verrou externe +cms.ui.folder.left=Gauche +cms.ui.folder.right=Droite +cms.ui.folder.items=\u00e9l\u00e9ment(s) +cms.ui.folder.from=de +cms.ui.folder.to=\u00e0 +cms.ui.folder.no_items=Pas d'\u00e9l\u00e9ments +cms.ui.folder.no_image=Pas d'image +cms.ui.folder.hide_metadata=Cacher les m\u00e9ta-donn\u00e9es +cms.ui.folder.show_metadata=Montrer les m\u00e9ta-donn\u00e9es +cms.ui.folder.edit_subject_classes=Modifier les classes objet +cms.ui.folder.add_paragraph=Ajouter un paragraphe +cms.ui.folder.edit_in_applet=Modifier dans EoPro +cms.ui.folder.edit_in_browser=Modifier dans un navigateur + +cms.ui.folder.edit_current_folder=Modifier le dossier courant +cms.ui.folder.preview_current_folder=Pr\u00e9-visualiser le dossier courant +cms.ui.folder.contents_for=Contenu de  +cms.ui.folder.choose_target_folder=Choisir le dossier de destination +cms.ui.foldr.new_wcms_doc=Nouveau document WCMS + +COMMENT.05=ENTREES +cms.ui.folder.left=Gauche +cms.ui.folder.right=Droite + +COMMENT.10=DOSSIER DES META DONNEES + +cms.ui.folder.headline=Ent\u00eate +cms.ui.folder.heading=Chapeau +cms.ui.folder.body=Corps +cms.ui.folder.add_image=Ajouter une image +cms.ui.folder.replace_image=Remplacer cette image +cms.ui.folder.align=Aligner +cms.ui.folder.add_download=Ajouter un t\u00e9l\u00e9chargement +cms.ui.folder.alt=Alt +cms.ui.folder.caption=L\u00e9gende +cms.ui.folder.remove_asset_link=Retirer + +COMMENT.20=MESSAGES D'ERREURS +cms.ui.folder.column_index_not_in_table_model=Index de la colonne absent du mod\u00e8le de table: +cms.ui.folder.cannot_find_root_folder=Impossible de trouver le dossier racine. +cms.ui.folder.must_select_item=Vous devez s\u00e9lectionner au moins \u00e9l\u00e9ment pour le d\u00e9placer ou le copier +cms.ui.folder.no_source_items_specified=Pas d'\u00e9l\u00e9ment source sp\u00e9cifi\u00e9. +cms.ui.folder.need_select_target_folder=Vous devez s\u00e9lectionner un dossier dans lequel les \u00e9l\u00e9ments seront d\u00e9plac\u00e9s ou copi\u00e9s. +cms.ui.folder.not_within_same_folder=Impossible de d\u00e9placer ou de copier des \u00e9l\u00e9ments \u00e0 l'int\u00e9rieur d'un m\u00eame dossier. +cms.ui.folder.no_permission=Vous n'avez pas l'autorisation de cr\u00e9er, de copier, ou de d\u00e9placer des \u00e9l\u00e9ments. +cms.ui.folder.item_already_exists=Il y a d\u00e9j\u00e0 un \u00e9l\u00e9ment dans le dossier destination appel\u00e9: {0} +cms.ui.folder.item_is_live={0} est en ligne ; Vous devez le d\u00e9-publier avant de le d\u00e9placer. +cms.ui.folder.no_permission_for_item=Vous n'avez pas l'autorisation de supprimer ou de d\u00e9placer {0}. +cms.ui.folder.no_such_item=L'identifiant fourni pour l'\u00e9l\u00e9ment ne correspond pas \u00e0 un contenu existant. +cms.ui.folder.filter.all= +cms.ui.folder.languages= +cms.ui.folder.delete_confirmation= +cms.ui.folder.additionalInfo= +cms.ui.folder.move.action= +cms.ui.folder.copy.action= +cms.ui.folder.publish.action= +cms.ui.folder.unpublish.action= diff --git a/ccm-core/src/main/java/com/arsdigita/kernel/ui/ACSObjectSelectionModel.java b/ccm-core/src/main/java/com/arsdigita/kernel/ui/ACSObjectSelectionModel.java new file mode 100755 index 000000000..9a8cdc6a5 --- /dev/null +++ b/ccm-core/src/main/java/com/arsdigita/kernel/ui/ACSObjectSelectionModel.java @@ -0,0 +1,487 @@ +/* + * Copyright (C) 2001-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.kernel.ui; + +import com.arsdigita.bebop.SingleSelectionModel; +import com.arsdigita.bebop.ParameterSingleSelectionModel; +import com.arsdigita.bebop.RequestLocal; +import com.arsdigita.bebop.PageState; +import com.arsdigita.bebop.parameters.ParameterModel; +import com.arsdigita.bebop.parameters.BigDecimalParameter; +import com.arsdigita.bebop.event.ChangeListener; + +import com.arsdigita.util.Assert; +import com.arsdigita.util.UncheckedWrapperException; + +import java.math.BigDecimal; +import java.lang.reflect.Constructor; + +import javax.servlet.ServletException; + +import org.apache.log4j.Logger; +import org.libreccm.cdi.utils.CdiUtil; +import org.libreccm.core.CcmObject; +import org.libreccm.core.CcmObjectRepository; + +/** + * Loads a subclass of an ACSObject from the database. + * By default, uses a BigDecimal state parameter in order to + * store and retrieve the item id. + * + *

+ * The getSelectedKey(PageState state) method will return the + * BigDecimal id of the currently selected object. This method + * will return the id even if the object with this id does not + * actually exist. + * + *

+ * The getSelectedObject(PageState state) method will return the + * object whose id is getSelectedKey(PageState state). If the + * object does not actually exist, the method will return null + * + *

+ * Thus, it is possible to implement the following pattern: + *

class MyComponent extends SimpleComponent {
+ *  ACSObjectSelectionModel m_model;
+ *
+ *  public MyComponent() {
+ *    super();
+ *    m_model = new ACSObjectSelectionModel("item_id");
+ *  }
+ *
+ *  public void register(Page p) {
+ *    super.register(p);
+ *    p.addComponentStateParam(this, p.getStateParameter());
+ *  }
+ *
+ *  public void doSomethingUseful(PageState s) {
+ *    if (m_model.isSelected(s)) {
+ *      CusomACSObject obj = (CustomACSObject)m_model.getSelectedObject(state);
+ *      // Do something with obj..
+ *    }
+ *  }
+ *}
+ * + * Naturally, the ACSObjectSelectionModel could also be passed + * in as a parameter in the MyComponent constructor. In this + * case, it should be up to the parent of MyComponent to + * register the model's state parameter. + *

+ * Advanced Usage: The ACSObjectSelectionModel + * is actually just a wrapper for a {@link SingleSelectionModel} + * which maintains the currently selected object's ID as a + * {@link BigDecimal}. By default, a new + * {@link ParameterSingleSelectionModel} is wrapped in this way; + * however, any {@link SingleSelectionModel} may be wrapped. + * Thus, it becomes possible to use the ACSObjectSelectionModel + * even if the currently selected ID is not stored in a state parameter. + *

+ * Persistence Details: The default constructor of + * ACSObjectSelectionModel will attempt to use the + * {@link DomainObjectFactory} to automatically instantiate the correct Java + * subclass of {@link ACSObject}. However, it is also possible to use an + * alternate constructor in order to force the ACSObjectSelectionModel + * to manually instantiate the objects: + * + *


+ * ACSObjectSelectionModel model = 
+ *     new ACSObjectSelectionModel("com.arsdigita.cms.Article", 
+ *                                 "com.arsdigita.cms.Article", "item_id");
+ * 
+ * + * In this case, the model will attempt to use reflection to instantiate the + * correct subclass of ACSObject. In addition, the supplementary + * constructor makes it possible to create new objects in the database + * using the {@link #createACSObject(BigDecimal)} method. + * + * @see com.arsdigita.bebop.SingleSelectionModel + * @see com.arsdigita.bebop.ParameterSingleSelectionModel + * + * @author Stanislav Freidin + * @version $Id$ + */ +public class ACSObjectSelectionModel implements SingleSelectionModel { + + private static final Logger s_log = + Logger.getLogger(ACSObjectSelectionModel.class); + + private RequestLocal m_loaded; + private Class m_javaClass; + private Constructor m_constructor; + private String m_objectType; + private SingleSelectionModel m_model; + + /** + * Construct a new ACSObjectSelectionModel. + * This model will produce instances of ACSObject + * by automatically instantiating the correct Java subclass using + * the {@link DomainObjectFactory}. + * + * @param parameter The state parameter which should be used to store + * the object ID + */ + public ACSObjectSelectionModel(BigDecimalParameter parameter) { + this(null, null, parameter); + } + + /** + * Construct a new ACSObjectSelectionModel. + * This model will produce instances of ACSObject + * by automatically instantiating the correct Java subclass using + * the {@link DomainObjectFactory}. + * + * @param parameterName The name of the state parameter which will + * be used to store the object ID. + */ + public ACSObjectSelectionModel(String parameterName) { + this(null, null, new BigDecimalParameter(parameterName)); + } + + /** + * Construct a new ACSObjectSelectionModel. + * This model will produce instances of ACSObject + * by automatically instantiating the correct Java subclass using + * the {@link DomainObjectFactory}. + * + * @param model The {@link SingleSelectionModel} which will supply + * a {@link BigDecimal} ID of the currently selected object + */ + public ACSObjectSelectionModel(SingleSelectionModel model) { + this(null, null, model); + } + + /** + * Construct a new ACSObjectSelectionModel + * + * @param javaClass The name of the Java class which represents + * the object. Must be a subclass of {@link ACSObject}. In + * addition, the class must have a constructor with a single + * {@link OID} parameter. + * @param objectType The name of the persistence metadata object type + * which represents the ACS object. In practice, will often be + * the same as the javaClass. + * @param parameterName The name of the state parameter which will + * be used to store the object ID. + */ + public ACSObjectSelectionModel( String javaClass, + String objectType, + String parameterName ) { + this(javaClass, objectType, new BigDecimalParameter(parameterName)); + } + + /** + * Construct a new ACSObjectSelectionModel + * + * @param javaClass The name of the Java class which represents + * the object. Must be a subclass of {@link ACSObject}. In + * addition, the class must have a constructor with a single + * {@link OID} parameter. + * @param objectType The name of the persistence metadata object type + * which represents the ACS object. In practice, will often be + * the same as the javaClass. + * @param parameter The state parameter which should be used to store + * the object ID + */ + public ACSObjectSelectionModel( String javaClass, + String objectType, + BigDecimalParameter parameter ) { + this(javaClass, objectType, + new ParameterSingleSelectionModel(parameter)); + } + + /** + * Construct a new ACSObjectSelectionModel + * + * @param javaClass The name of the Java class which represents + * the object. Must be a subclass of {@link ACSObject}. In + * addition, the class must have a constructor with a single + * {@link OID} parameter. + * @param objectType The name of the persistence metadata object type + * which represents the ACS object. In practice, will often be + * the same as the javaClass. + * @param model The {@link SingleSelectionModel} which will supply + * a {@link BigDecimal} ID of the currently selected object + */ + public ACSObjectSelectionModel( String javaClass, + String objectType, + SingleSelectionModel model ) { + m_loaded = new RequestLocal() { + protected Object initialValue(PageState state) { + return Boolean.FALSE; + } + }; + + if (javaClass != null) { + // Cache the Class object and the constructor for further use + try { + m_javaClass = Class.forName(javaClass); + m_constructor = m_javaClass.getConstructor(); + } catch (Exception e) { + throw new UncheckedWrapperException( "Problem loading class " + + javaClass, e ); + } + } + + m_objectType = objectType; + m_model = model; + } + + /** + * Set the ID of the current object. The next time + * {@link #getSelectedObject(PageState)} is called, the object + * with the specified ID will be loaded from the database. + * + * @param state The page state + * @param key A {@link BigDecimal} primary key for the object, + * or a String representation of a BigDecimal, such as "42". + */ + public void setSelectedKey(PageState state, Object key) { + //BigDecimal newKey = convertToBigDecimal(key); + + m_loaded.set(state, Boolean.FALSE); + m_model.setSelectedKey(state, key); + } + + /** + * Return the object which was selected and loaded from the database, + * using the values supplied in the page state. May return null + * if isSelected(state) == false, or if the object was not found. + * + * @param state The page state + * @return The currently selected domain object, or null if no object is + * selected. + */ + public CcmObject getSelectedObject(PageState state) { + + Long id = convertToLong(getSelectedKey(state)); + if (id == null) { + return null; + } + + return loadACSObject(state, id); + } + + /** + * Load the selected object for the first time. Child classes + * may choose to override this method in order to load the object + * in nonstandard ways. The default implementation merely + * instantiates an {@link ACSObject} whose ID is the passed-in key. + * + * @param state the current page state + * @param key the currently selected key; guaranteed to be non-null + * @return the object identified by the specified key + * @pre key != null + */ + protected CcmObject loadACSObject(PageState state, Object key) { + CcmObject item = null; + + // Cheesy back-and-forth conversion to ensure that + // the result will be a BigDecimal, not a String or + // something else. Should go away when ListModel.getKey is + // changed to return an Object. + Long id = convertToLong(key); + + return CdiUtil.createCdiUtil().findBean(CcmObjectRepository.class).findById(id); + + } + + /** + * Select the specified object. + * + * @param state The page state + * @param object The content item to set + */ + public void setSelectedObject(PageState state, CcmObject object) { + CcmObject item = object; + + if (item == null) { + m_loaded.set(state, Boolean.FALSE); + m_model.setSelectedKey(state, null); + } else { + m_loaded.set(state, Boolean.TRUE); + m_model.setSelectedKey(state, item.getObjectId()); + } + } + + /** + * Determine if the attempt to load the selected object has + * been made yet. Child classes may use this method to + * perform request-local initialization. + * + * @param state the page state + * @return true if the attempt to load the selected object has + * already been made, false otherwise + */ + public boolean isInitialized(PageState state) { + return ((Boolean)m_loaded.get(state)).booleanValue(); + } + + /** + * A utility function which creates a new object with the given ID. + * Uses reflection to create the instance of the class supplied + * in the constructor to this ACSObjectSelectionModel. + * If no classname was supplied in the constructor, an assertion + * failure will occur. + * + * @param id The id of the new item - this is ignored and the object + * will have a different id + * @return The newly created item + * @post return != null + * @deprecated This ignores the ID since ACSObject.setID is a no-op + */ + public CcmObject createACSObject(Long id) throws ServletException { + return createACSObject(); + } + + + /** + * A utility function which creates a new object with the given ID. + * Uses reflection to create the instance of the class supplied + * in the constructor to this ACSObjectSelectionModel. + * If no classname was supplied in the constructor, an assertion + * failure will occur. + * + * @param id The id of the new item + * @return The newly created item + * @post return != null + */ + public CcmObject createACSObject() throws ServletException { + Assert.exists(m_javaClass, Class.class); + + try { + CcmObject item = (CcmObject)m_javaClass.newInstance(); + return item; + } catch (InstantiationException e) { + throw new ServletException(e); + } catch (IllegalAccessException e) { + throw new ServletException(e); + } + } + + + /** + * @return the Class of the content items which are produced + * by this model + */ + public Class getJavaClass() { + return m_javaClass; + } + + /** + * @return The name of the object type of the + * content items which are produced by this model + */ + public String getObjectType() { + return m_objectType; + } + + /** + * @return the underlying {@link SingleSelectionModel} which + * maintains the ID of the selected object + */ + public SingleSelectionModel getSingleSelectionModel() { + return m_model; + } + + //////////////////////// + // + // Passthrough methods + + /** + * Return true if there is a selected object. + * + * @param state represents the state of the current request + * @return true if there is a selected component. + */ + public boolean isSelected(PageState state) { + return m_model.isSelected(state); + } + + /** + * Return the key that identifies the selected object. + * + * @param state the current page state + * @return the {@link BigDecimal} ID of the currently selected + * object, or null if no object is selected. + * @post return instanceof BigDecimal + * + */ + public Object getSelectedKey(PageState state) { + Object key = m_model.getSelectedKey(state); + return key; + } + + + /** + * Clear the selection. + * + * @param state the current page state. + * @post ! isSelected(state) + * @post ! isInitialized(state) + */ + public void clearSelection(PageState state) { + m_model.clearSelection(state); + m_loaded.set(state, Boolean.FALSE); + } + + /** + * Add a change listener to the model. The listener's + * stateChanged is called whenever the selected key changes. + * + * @param l a listener to notify when the selected key changes + */ + public void addChangeListener(ChangeListener l) { + m_model.addChangeListener(l); + } + + /** + * Remove a change listener from the model. + * + * @param l the listener to remove. + */ + public void removeChangeListener(ChangeListener l) { + m_model.removeChangeListener(l); + } + + /** + * Return the state parameter which will be used to keep track + * of the currently selected key. Most likely, the parameter will + * be a {@link BigDecimalParameter}. + * + * @return The state parameter which should be used to keep + * track of the ID of the currently selected object, or null + * if the ID is computed in some other way + * @see SingleSelectionModel#getStateParameter() + */ + public ParameterModel getStateParameter() { + return m_model.getStateParameter(); + } + + private static Long convertToLong(Object value) { + Long newValue = null; + + if ( value instanceof Long ) { + newValue = (Long) value; + } else if ( value != null ) { + newValue = Long.parseLong(value.toString()); + } + + return newValue; + } +} diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/UserContextController.java b/ccm-core/src/main/java/org/libreccm/ui/admin/UserContextController.java index 8627e84ee..6de01bce1 100644 --- a/ccm-core/src/main/java/org/libreccm/ui/admin/UserContextController.java +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/UserContextController.java @@ -21,17 +21,23 @@ package org.libreccm.ui.admin; import javax.enterprise.context.RequestScoped; import javax.inject.Inject; import javax.inject.Named; + import org.apache.shiro.subject.Subject; import org.libreccm.security.Shiro; import org.libreccm.security.User; +import java.io.Serializable; + + /** * * @author Jens Pelzetter */ -@RequestScoped @Named -public class UserContextController { +@RequestScoped +public class UserContextController implements Serializable { + + private static final long serialVersionUID = 2046117182808198398L; @Inject private Shiro shiro; @@ -42,14 +48,14 @@ public class UserContextController { public boolean isLoggedIn() { return subject.isAuthenticated(); } - + public String getCurrentUserName() { final User user = shiro.getUser(); if (user == null) { return ""; } else { - return String.format("%s %s", + return String.format("%s %s", user.getGivenName(), user.getFamilyName()); } diff --git a/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java b/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java index 2cb5961b1..5e494dea4 100644 --- a/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java +++ b/ccm-core/src/main/java/org/libreccm/ui/admin/usersgroupsroles/RolesController.java @@ -18,55 +18,105 @@ */ package org.libreccm.ui.admin.usersgroupsroles; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.libreccm.security.Permission; import org.libreccm.security.Role; +import org.libreccm.security.RoleMembership; import org.libreccm.security.RoleRepository; import org.primefaces.model.LazyDataModel; import org.primefaces.model.SortOrder; +import java.io.Serializable; +import java.util.ArrayList; import java.util.List; import java.util.Map; -import javax.enterprise.context.RequestScoped; +import java.util.Set; + +import javax.faces.view.ViewScoped; import javax.inject.Inject; import javax.inject.Named; +import javax.transaction.Transactional; /** * * @author Jens Pelzetter */ -@RequestScoped @Named -public class RolesController { +@ViewScoped +public class RolesController implements Serializable { + private static final long serialVersionUID = 9092665507680111584L; + private static final Logger LOGGER = LogManager.getLogger( + RolesController.class); + @Inject private RoleRepository roleRepo; private final LazyDataModel tableModel; private Role selectedRole; - + private String selectedRoleName; + public RolesController() { + LOGGER.debug("Intializing RolesController and creating table model..."); tableModel = new RolesTableModel(); } public LazyDataModel getTableModel() { + LOGGER.debug("getTableModel invoked..."); return tableModel; } public List getRoles() { + LOGGER.debug("getRoles invoked..."); return roleRepo.findAll(); } - + public Role getSelectedRole() { + LOGGER.debug("getSelectedRole invoked..."); return selectedRole; } public void setSelectedRole(final Role selectedRole) { + LOGGER.debug("Setting selected role to \"{}\"...", selectedRole); this.selectedRole = selectedRole; + selectedRoleName = selectedRole.getName(); } + public String getSelectedRoleName() { + return selectedRoleName; + } + public void setSelectedRoleName(final String name) { + selectedRoleName = name; + } + + @Transactional(Transactional.TxType.REQUIRED) + public Set getSelectedRoleMemberships() { + final Role role = roleRepo.findById(selectedRole.getRoleId()); + return role.getMemberships(); + } + + @Transactional(Transactional.TxType.REQUIRED) + public List getSelectedRolePermissions() { + final Role role = roleRepo.findById(selectedRole.getRoleId(), + Role.ENTITY_GRPAH_WITH_PERMISSIONS); + return role.getPermissions(); + } + public void renameSelectedRole() { + selectedRole.setName(selectedRoleName); + roleRepo.save(selectedRole); + } + + public void renameSelectedRoleCancel() { + selectedRoleName = selectedRole.getName(); + } + + + private class RolesTableModel extends LazyDataModel { private static final long serialVersionUID = 8878060757439667086L; diff --git a/ccm-core/src/main/resources/META-INF/resources/admin-jsf/admin.xhtml b/ccm-core/src/main/resources/META-INF/resources/admin-jsf/admin.xhtml index 17c008002..a0efa8d9d 100644 --- a/ccm-core/src/main/resources/META-INF/resources/admin-jsf/admin.xhtml +++ b/ccm-core/src/main/resources/META-INF/resources/admin-jsf/admin.xhtml @@ -14,6 +14,7 @@ + @@ -29,9 +30,6 @@ library="admin-jsf" name="libreccm.png" /> - @@ -62,8 +60,6 @@ - - @@ -82,16 +79,20 @@ id="role-name"> - + - - - + update=":admin-tabs:user-groups-roles-tabs:rolesForm:roleDetails"> + + + + + @@ -100,15 +101,52 @@ widgetVar="roleDialog" modal="true" showEffect="fade" - hideEffect="fade"> - - + hideEffect="fade" + style="font-size: 1.2em;"> + + + + +
+ + +
+ +
+ + + + + + + + + + + + + + + + + +
-
diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties index a1f8e802d..910fc3f90 100644 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources.properties @@ -547,3 +547,8 @@ ui.admin.applications.instance_table.heading=Instances ui.admin.applications.new_instance.primary_url=Primary URL ui.admin.applications.new_instance.primary_url.error.not_empty=The primary URL of an application instance can't be empty. ui.admin.tab.users_groups_roles.edit=Edit role +ui.admin.tab.users_groups_roles.role_details=Details +ui.admin.tab.users_groups_roles.role_members=Members +ui.admin.tab.users_groups_roles.role_permissions=Permissions +ui.admin.tab.users_groups_roles.role_details.save=Save +ui.admin.tab.users_groups_roles.role_details.cancel=Cancel diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties index fdb4a3cdb..c876208ca 100644 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_de.properties @@ -551,3 +551,8 @@ ui.admin.applications.instance_table.heading=Instanzen ui.admin.applications.new_instance.primary_url=Prim\u00e4re URL ui.admin.applications.new_instance.primary_url.error.not_empty=Die prim\u00e4re URL einer Applikations-Instanz kann nicht leer sein. ui.admin.tab.users_groups_roles.edit=Rolle bearbeiten +ui.admin.tab.users_groups_roles.role_details=Details +ui.admin.tab.users_groups_roles.role_members=Mitglieder +ui.admin.tab.users_groups_roles.role_permissions=Berechtigungen +ui.admin.tab.users_groups_roles.role_details.save=Speichern +ui.admin.tab.users_groups_roles.role_details.cancel=Abbrechen diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties index 4aa255b0d..1f8579efe 100755 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_en.properties @@ -544,3 +544,8 @@ ui.admin.applications.instance_table.heading=Instances ui.admin.applications.new_instance.primary_url=Primary URL ui.admin.applications.new_instance.primary_url.error.not_empty=The primary URL of an application instance can't be empty. ui.admin.tab.users_groups_roles.edit=Edit role +ui.admin.tab.users_groups_roles.role_details=Details\t +ui.admin.tab.users_groups_roles.role_members=Members +ui.admin.tab.users_groups_roles.role_permissions=Permissions +ui.admin.tab.users_groups_roles.role_details.save=Save +ui.admin.tab.users_groups_roles.role_details.cancel=Cancel diff --git a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties index a2ff3b59a..0cb6be9ec 100755 --- a/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties +++ b/ccm-core/src/main/resources/com/arsdigita/ui/admin/AdminResources_fr.properties @@ -535,3 +535,8 @@ ui.admin.applications.instance_table.heading=Instances ui.admin.applications.new_instance.primary_url=Primary URL ui.admin.applications.new_instance.primary_url.error.not_empty=The primary URL of an application instance can't be empty. ui.admin.tab.users_groups_roles.edit=Edit role +ui.admin.tab.users_groups_roles.role_details=Details +ui.admin.tab.users_groups_roles.role_members=Members +ui.admin.tab.users_groups_roles.role_permissions=Permissions +ui.admin.tab.users_groups_roles.role_details.save=Save +ui.admin.tab.users_groups_roles.role_details.cancel=Cancel