diff --git a/config/alfresco/web-client-config-wcm-actions.xml b/config/alfresco/web-client-config-wcm-actions.xml index e77da049b2..c4b46d0f87 100644 --- a/config/alfresco/web-client-config-wcm-actions.xml +++ b/config/alfresco/web-client-config-wcm-actions.xml @@ -364,8 +364,9 @@ false - - + + @@ -385,5 +386,19 @@ + + + + + + + false + + + + + + + diff --git a/source/java/org/alfresco/web/action/evaluator/EditFormEvaluator.java b/source/java/org/alfresco/web/action/evaluator/EditFormEvaluator.java index b3d0d52430..2613974642 100644 --- a/source/java/org/alfresco/web/action/evaluator/EditFormEvaluator.java +++ b/source/java/org/alfresco/web/action/evaluator/EditFormEvaluator.java @@ -17,10 +17,18 @@ */ package org.alfresco.web.action.evaluator; +import javax.faces.context.FacesContext; + import org.alfresco.model.WCMAppModel; +import org.alfresco.service.ServiceRegistry; +import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.web.action.ActionEvaluator; +import org.alfresco.web.app.Application; +import org.alfresco.web.app.servlet.FacesHelper; +import org.alfresco.web.bean.NavigationBean; import org.alfresco.web.bean.repository.Node; +import org.alfresco.web.bean.repository.Repository; /** * UI Action Evaluator - Edit Web Form in the Forms DataDictionary folder @@ -34,7 +42,23 @@ public class EditFormEvaluator implements ActionEvaluator */ public boolean evaluate(final Node node) { - return (node.hasAspect(WCMAppModel.ASPECT_FORM) && - node.hasPermission(PermissionService.ADD_CHILDREN)); + if (node.hasAspect(WCMAppModel.ASPECT_FORM) && node.hasPermission(PermissionService.ADD_CHILDREN)) + { + final FacesContext fc = FacesContext.getCurrentInstance(); + final ServiceRegistry services = Repository.getServiceRegistry(fc); + final NavigationBean navigator = (NavigationBean)FacesHelper.getManagedBean(fc, NavigationBean.BEAN_NAME); + + // get the path to the current name - compare last element with the Website folder assoc name + final Path path = navigator.getCurrentNode().getNodePath(); + final Path.Element element = path.get(path.size() - 1); + final String endPath = element.getPrefixedString(services.getNamespaceService()); + + // check we have the permission to create nodes in that Website folder + return (Application.getContentFormsFolderName(fc).equals(endPath)); + } + else + { + return false; + } } } diff --git a/source/java/org/alfresco/web/config/ActionsConfigElement.java b/source/java/org/alfresco/web/config/ActionsConfigElement.java index 96672efb53..3b8498b5ef 100644 --- a/source/java/org/alfresco/web/config/ActionsConfigElement.java +++ b/source/java/org/alfresco/web/config/ActionsConfigElement.java @@ -29,6 +29,7 @@ import java.util.Set; import org.alfresco.config.ConfigElement; import org.alfresco.config.ConfigException; import org.alfresco.config.element.ConfigElementAdapter; +import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.web.action.ActionEvaluator; import org.alfresco.web.bean.repository.Repository; @@ -83,15 +84,26 @@ public class ActionsConfigElement extends ConfigElementAdapter combinedElement.actionDefs.putAll(newElement.actionDefs); // add the existing action groups - combinedElement.actionGroups.putAll(this.actionGroups); + Map combinedActionGroups = new HashMap(this.actionGroups.size()); + try + { + for (ActionGroup group : this.actionGroups.values()) + { + combinedActionGroups.put(group.getId(), (ActionGroup)group.clone()); + } + } + catch (CloneNotSupportedException e) + { + throw new AlfrescoRuntimeException("clone() required on ActionGroup class.", e); + } + combinedElement.actionGroups = combinedActionGroups; // any new action groups with the same name must be combined for (ActionGroup newGroup : newElement.actionGroups.values()) { if (combinedElement.actionGroups.containsKey(newGroup.getId())) { - // there is already a group with this id, combine it - // with the new one + // there is already a group with this id, combine it with the new one ActionGroup combinedGroup = combinedElement.actionGroups.get(newGroup.getId()); if (newGroup.ShowLink != combinedGroup.ShowLink) { @@ -240,7 +252,7 @@ public class ActionsConfigElement extends ConfigElementAdapter * * @author Kevin Roast */ - public static class ActionGroup implements Iterable + public static class ActionGroup implements Iterable, Cloneable { public ActionGroup(String id) { @@ -251,6 +263,18 @@ public class ActionsConfigElement extends ConfigElementAdapter this.id = id; } + @Override + protected Object clone() throws CloneNotSupportedException + { + ActionGroup clone = new ActionGroup(id); + clone.actions = (Set)((LinkedHashSet)actions).clone(); + clone.hiddenActions = (Set)((HashSet)hiddenActions).clone(); + clone.ShowLink = ShowLink; + clone.Style = Style; + clone.StyleClass = StyleClass; + return clone; + } + public String getId() { return id; diff --git a/source/java/org/alfresco/web/ui/common/ComponentConstants.java b/source/java/org/alfresco/web/ui/common/ComponentConstants.java index 3a267a9273..d0cbb80393 100644 --- a/source/java/org/alfresco/web/ui/common/ComponentConstants.java +++ b/source/java/org/alfresco/web/ui/common/ComponentConstants.java @@ -28,6 +28,7 @@ public final class ComponentConstants public static final String JAVAX_FACES_OUTPUT = "javax.faces.Output"; public static final String JAVAX_FACES_GRID = "javax.faces.Grid"; public static final String JAVAX_FACES_PANEL = "javax.faces.Panel"; + public static final String JAVAX_FACES_PANELGROUP = "javax.faces.HtmlPanelGroup"; public static final String JAVAX_FACES_CHECKBOX = "javax.faces.Checkbox"; public static final String JAVAX_FACES_SELECT_BOOLEAN = "javax.faces.SelectBoolean"; public static final String JAVAX_FACES_GRAPHIC = "javax.faces.Graphic"; diff --git a/source/java/org/alfresco/web/ui/repo/component/UIActions.java b/source/java/org/alfresco/web/ui/repo/component/UIActions.java index 71c0611916..5ed027b6d8 100644 --- a/source/java/org/alfresco/web/ui/repo/component/UIActions.java +++ b/source/java/org/alfresco/web/ui/repo/component/UIActions.java @@ -19,13 +19,16 @@ package org.alfresco.web.ui.repo.component; import java.io.IOException; import java.net.URLEncoder; +import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.ResourceBundle; +import java.util.Set; import javax.faces.component.UIComponent; import javax.faces.component.UIParameter; +import javax.faces.component.html.HtmlPanelGroup; import javax.faces.context.FacesContext; import javax.faces.context.ResponseWriter; import javax.faces.el.ValueBinding; @@ -34,6 +37,7 @@ import org.alfresco.config.Config; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.web.app.Application; +import org.alfresco.web.bean.repository.Node; import org.alfresco.web.config.ActionsConfigElement; import org.alfresco.web.config.ActionsConfigElement.ActionDefinition; import org.alfresco.web.config.ActionsConfigElement.ActionGroup; @@ -71,6 +75,9 @@ public class UIActions extends SelfRenderingComponent public static final String COMPONENT_ACTIONEVAL = "org.alfresco.faces.ActionInstanceEvaluator"; public final static Class ACTION_CLASS_ARGS[] = {javax.faces.event.ActionEvent.class}; + + private Set groups = new HashSet(4); + private final static String CONTEXTID_DEFAULT = "_default"; /** * @see javax.faces.component.UIComponent#getFamily() @@ -91,6 +98,7 @@ public class UIActions extends SelfRenderingComponent this.value = (String)values[1]; this.showLink = (Boolean)values[2]; this.verticalSpacing = (Integer)values[3]; + this.groups = (HashSet)values[4]; } /** @@ -98,14 +106,10 @@ public class UIActions extends SelfRenderingComponent */ public Object saveState(FacesContext context) { - Object values[] = new Object[4]; - // standard component attributes are saved by the super class - values[0] = super.saveState(context); - values[1] = this.value; - values[2] = this.showLink; - values[3] = this.verticalSpacing; + Object values[] = new Object[] { + super.saveState(context), this.value, this.showLink, this.verticalSpacing, this.groups}; return (values); - } + } /** * @see javax.faces.component.UIComponentBase#encodeBegin(javax.faces.context.FacesContext) @@ -123,20 +127,44 @@ public class UIActions extends SelfRenderingComponent // put the context object into the requestMap so it is accessable // by any child component value binding expressions + Object actionContext = getContext(); Map requestMap = getFacesContext().getExternalContext().getRequestMap(); - requestMap.put(ACTION_CONTEXT, getContext()); + requestMap.put(ACTION_CONTEXT, actionContext); - if (getChildCount() != 0) + String contextId; + if (actionContext instanceof Node) { - if (logger.isDebugEnabled()) - logger.debug("---already built component tree for actions."); - return; + contextId = ((Node)actionContext).getType().toString(); + if (groups.contains(contextId)) + { + if (logger.isDebugEnabled()) + logger.debug("---already built component tree for actions contextId: " + contextId); + return; + } + } + else + { + contextId = CONTEXTID_DEFAULT; + if (groups.contains(contextId)) + { + if (logger.isDebugEnabled()) + logger.debug("---already built component tree for default actions."); + return; + } } String groupId = getValue(); if (groupId != null && groupId.length() != 0) { - Config config = Application.getConfigService(context).getGlobalConfig(); + Config config; + if (actionContext instanceof Node) + { + config = Application.getConfigService(context).getConfig(actionContext); + } + else + { + config = Application.getConfigService(context).getGlobalConfig(); + } if (config != null) { // find the Actions specific config element @@ -150,8 +178,8 @@ public class UIActions extends SelfRenderingComponent { // render the action group component tree if (logger.isDebugEnabled()) - logger.debug("-constructing ActionGroup: " + groupId); - buildActionGroup(context, actionConfig, actionGroup); + logger.debug("-constructing ActionGroup: " + groupId + " for ContextId: " + contextId); + buildActionGroup(context, actionConfig, actionGroup, contextId); } else { @@ -193,10 +221,25 @@ public class UIActions extends SelfRenderingComponent out.write(">"); } + // use the current context Id to find the correct component group to render + Map requestMap = getFacesContext().getExternalContext().getRequestMap(); + Object actionContext = requestMap.get(ACTION_CONTEXT); + String contextId = CONTEXTID_DEFAULT; + if (actionContext instanceof Node) + { + contextId = ((Node)actionContext).getType().toString(); + } + for (Iterator i=getChildren().iterator(); i.hasNext(); /**/) { UIComponent child = (UIComponent)i.next(); - Utils.encodeRecursive(context, child); + if (contextId.equals(child.getAttributes().get("contextId"))) + { + if (logger.isDebugEnabled()) + logger.debug("Rendering actions group for contextId: " + contextId); + Utils.encodeRecursive(context, child); + break; + } } if (verticalSpacing != 0) @@ -224,7 +267,8 @@ public class UIActions extends SelfRenderingComponent * @param actionGroup */ @SuppressWarnings("unchecked") - private void buildActionGroup(FacesContext context, ActionsConfigElement config, ActionGroup actionGroup) + private void buildActionGroup( + FacesContext context, ActionsConfigElement config, ActionGroup actionGroup, String contextId) throws IOException { javax.faces.application.Application facesApp = context.getApplication(); @@ -239,6 +283,13 @@ public class UIActions extends SelfRenderingComponent showLink = (Boolean)getAttributes().get(ATTR_SHOWLINK); } + // build parent wrapper component + HtmlPanelGroup wrapper = (HtmlPanelGroup)facesApp.createComponent(ComponentConstants.JAVAX_FACES_PANELGROUP); + wrapper.setId(createUniqueId()); + wrapper.getAttributes().put("contextId", contextId); + this.getChildren().add(wrapper); + this.groups.add(contextId); + // process each ActionDefinition in the order they were defined for (String actionId : actionGroup) { @@ -251,7 +302,7 @@ public class UIActions extends SelfRenderingComponent throw new AlfrescoRuntimeException("Unable to find configured ActionDefinition Id: " + actionId); } - UIComponent currentParent = this; + UIComponent currentParent = wrapper; // build a permissions evaluator component to wrap the actionlink PermissionEvaluator permEval = null;