mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
- Resources can now be added and removed to and from workflow packages
- Added simple search based content selector component to support this git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3628 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -971,6 +971,7 @@ error_reassign_workitem=Unable to reassign the work item due to system error:
|
||||
part_of_workflow=Part of Workflow
|
||||
initiated_by=Initiated by
|
||||
start_date=Start date
|
||||
add_resource=Add Resource
|
||||
|
||||
# Admin Console messages
|
||||
title_admin_console=Administration Console
|
||||
|
@@ -111,9 +111,9 @@
|
||||
</action>
|
||||
|
||||
<action id="add_package_item">
|
||||
<label-id>add</label-id>
|
||||
<label-id>add_resource</label-id>
|
||||
<image>/images/icons/add_item.gif</image>
|
||||
<action>null</action>
|
||||
<action-listener>#{DialogManager.bean.prepareForAdd}</action-listener>
|
||||
</action>
|
||||
|
||||
<action id="remove_package_item">
|
||||
|
@@ -21,6 +21,7 @@ import org.alfresco.service.cmr.workflow.WorkflowService;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTask;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTaskDefinition;
|
||||
import org.alfresco.service.cmr.workflow.WorkflowTransition;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.service.namespace.RegexQNamePattern;
|
||||
import org.alfresco.web.app.Application;
|
||||
@@ -49,9 +50,14 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
protected WorkflowTask workItem;
|
||||
protected WorkflowInstance workflowInstance;
|
||||
protected WorkflowTransition[] transitions;
|
||||
protected NodeRef workflowPackage;
|
||||
protected List<Node> resources;
|
||||
protected WorkItemCompleteResolver completeResolver = new WorkItemCompleteResolver();
|
||||
protected UIRichList packageItemsRichList;
|
||||
protected List<String> packageItemsToAdd;
|
||||
protected List<String> packageItemsToRemove;
|
||||
protected String[] itemsToAdd;
|
||||
protected boolean isItemBeingAdded = false;
|
||||
|
||||
protected static final String ID_PREFIX = "transition_";
|
||||
protected static final String CLIENT_ID_PREFIX = "dialog:" + ID_PREFIX;
|
||||
@@ -66,6 +72,23 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
{
|
||||
super.init(parameters);
|
||||
|
||||
// reset variables
|
||||
this.workItem = null;
|
||||
this.workItemNode = null;
|
||||
this.workflowInstance = null;
|
||||
this.transitions = null;
|
||||
this.workflowPackage = null;
|
||||
this.resources = null;
|
||||
this.itemsToAdd = null;
|
||||
this.packageItemsToAdd = null;
|
||||
this.packageItemsToRemove = null;
|
||||
this.isItemBeingAdded = false;
|
||||
if (this.packageItemsRichList != null)
|
||||
{
|
||||
this.packageItemsRichList.setValue(null);
|
||||
}
|
||||
|
||||
// get the task details
|
||||
String taskId = this.parameters.get("id");
|
||||
this.workItem = this.workflowService.getTaskById(taskId);
|
||||
|
||||
@@ -78,6 +101,22 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
|
||||
// get access to the workflow instance for the work item
|
||||
this.workflowInstance = this.workItem.path.instance;
|
||||
|
||||
// setup the workflow package for the task
|
||||
Serializable obj = this.workItem.properties.get(WorkflowModel.ASSOC_PACKAGE);
|
||||
// TODO: remove this workaroud where JBPM may return a String and not the NodeRef
|
||||
if (obj instanceof NodeRef)
|
||||
{
|
||||
this.workflowPackage = (NodeRef)obj;
|
||||
}
|
||||
else if (obj instanceof String)
|
||||
{
|
||||
this.workflowPackage = new NodeRef((String)obj);
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found workflow package for work item '" +
|
||||
this.workItem.id + "': " + this.workflowPackage );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,11 +125,35 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
throws Exception
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Saving work item: " + this.workItemNode.getId());
|
||||
logger.debug("Saving task: " + this.workItem.id);
|
||||
|
||||
// prepare the edited parameters for saving
|
||||
Map<QName, Serializable> params = WorkflowBean.prepareWorkItemParams(this.workItemNode);
|
||||
|
||||
// remove any items the user selected to remove
|
||||
if (this.workflowPackage != null && this.packageItemsToRemove != null &&
|
||||
this.packageItemsToRemove.size() > 0)
|
||||
{
|
||||
for (String removedItem : this.packageItemsToRemove)
|
||||
{
|
||||
this.nodeService.removeChild(this.workflowPackage, new NodeRef(removedItem));
|
||||
}
|
||||
}
|
||||
|
||||
// add any items the user selected to add
|
||||
if (this.workflowPackage != null && this.packageItemsToAdd != null &&
|
||||
this.packageItemsToAdd.size() > 0)
|
||||
{
|
||||
for (String addedItem : this.packageItemsToAdd)
|
||||
{
|
||||
NodeRef addedNodeRef = new NodeRef(addedItem);
|
||||
this.nodeService.addChild(this.workflowPackage, addedNodeRef,
|
||||
ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI,
|
||||
QName.createValidLocalName((String)this.nodeService.getProperty(
|
||||
addedNodeRef, ContentModel.PROP_NAME))));
|
||||
}
|
||||
}
|
||||
|
||||
// update the task with the updated parameters
|
||||
this.workflowService.updateTask(this.workItem.id, params, null, null);
|
||||
|
||||
@@ -200,6 +263,70 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
return outcome;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepares the dialog to allow the user to add an item to the workflow package
|
||||
*
|
||||
* @param event The event
|
||||
*/
|
||||
public void prepareForAdd(ActionEvent event)
|
||||
{
|
||||
this.isItemBeingAdded = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancels the adding of an item to the workflow package
|
||||
*
|
||||
* @param event The event
|
||||
*/
|
||||
public void cancelAddPackageItems(ActionEvent event)
|
||||
{
|
||||
this.isItemBeingAdded = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an item to the workflow package
|
||||
*
|
||||
* @param event The event
|
||||
*/
|
||||
public void addPackageItems(ActionEvent event)
|
||||
{
|
||||
if (this.itemsToAdd != null)
|
||||
{
|
||||
if (this.packageItemsToAdd == null)
|
||||
{
|
||||
// create the list of items to add if necessary
|
||||
this.packageItemsToAdd = new ArrayList<String>(this.itemsToAdd.length);
|
||||
}
|
||||
|
||||
for (String item : this.itemsToAdd)
|
||||
{
|
||||
// if this item is in the remove list it means it was there originally
|
||||
// and has now been re-added, as a result we don't need to do anything
|
||||
// to the original workflow package, therefore remove from the remove list
|
||||
if (this.packageItemsToRemove != null && this.packageItemsToRemove.contains(item))
|
||||
{
|
||||
this.packageItemsToRemove.remove(item);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Removed item from the removed list: " + item);
|
||||
}
|
||||
else
|
||||
{
|
||||
this.packageItemsToAdd.add(item);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Added item to the added list: " + item);
|
||||
}
|
||||
}
|
||||
|
||||
// reset the rich list so it re-renders
|
||||
this.packageItemsRichList.setValue(null);
|
||||
}
|
||||
|
||||
this.isItemBeingAdded = false;
|
||||
this.itemsToAdd = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes an item from the workflow package
|
||||
*
|
||||
@@ -207,7 +334,34 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
*/
|
||||
public void removePackageItem(ActionEvent event)
|
||||
{
|
||||
logger.info("remove package item: " + event);
|
||||
UIActionLink link = (UIActionLink)event.getComponent();
|
||||
Map<String, String> params = link.getParameterMap();
|
||||
String nodeRef = new NodeRef(Repository.getStoreRef(), params.get("id")).toString();
|
||||
|
||||
if (this.packageItemsToAdd != null && this.packageItemsToAdd.contains(nodeRef))
|
||||
{
|
||||
// remove the item from the added list if it was added in this dialog session
|
||||
this.packageItemsToAdd.remove(nodeRef);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Removed item from the added list: " + nodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
// add the node to the list of items to remove
|
||||
if (this.packageItemsToRemove == null)
|
||||
{
|
||||
this.packageItemsToRemove = new ArrayList<String>(1);
|
||||
}
|
||||
|
||||
this.packageItemsToRemove.add(nodeRef);
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Added item to the removed list: " + nodeRef);
|
||||
}
|
||||
|
||||
// reset the rich list so it re-renders
|
||||
this.packageItemsRichList.setValue(null);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -217,77 +371,42 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
*/
|
||||
public void togglePackageItemComplete(ActionEvent event)
|
||||
{
|
||||
UserTransaction tx = null;
|
||||
try
|
||||
{
|
||||
FacesContext context = FacesContext.getCurrentInstance();
|
||||
tx = Repository.getUserTransaction(context);
|
||||
tx.begin();
|
||||
|
||||
UIActionLink link = (UIActionLink)event.getComponent();
|
||||
Map<String, String> params = link.getParameterMap();
|
||||
|
||||
// create the node ref for the item we are toggling
|
||||
NodeRef nodeRef = new NodeRef(Repository.getStoreRef(),
|
||||
(String)params.get("id"));
|
||||
|
||||
// get the existing list of completed items
|
||||
List<NodeRef> completedItems = (List<NodeRef>)this.workItem.properties.get(
|
||||
WorkflowModel.PROP_COMPLETED_ITEMS);
|
||||
|
||||
if (completedItems == null)
|
||||
{
|
||||
// if it doesn't exist yet create the list and add the noderef
|
||||
completedItems = new ArrayList<NodeRef>(1);
|
||||
completedItems.add(nodeRef);
|
||||
this.workItem.properties.put(WorkflowModel.PROP_COMPLETED_ITEMS,
|
||||
(Serializable)completedItems);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (completedItems.contains(nodeRef))
|
||||
{
|
||||
// the item is already in the list remove it
|
||||
completedItems.remove(nodeRef);
|
||||
|
||||
// NOTE: There is a bug somwehere which causes the list to be
|
||||
// returned as a byte array instead of a list if an empty
|
||||
// list is persisted, therefore if the list is now empty
|
||||
// set the completed items back to null
|
||||
if (completedItems.size() == 0)
|
||||
{
|
||||
this.workItem.properties.put(WorkflowModel.PROP_COMPLETED_ITEMS, null);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// the noderef is not in the list yet so just add it
|
||||
completedItems.add(nodeRef);
|
||||
}
|
||||
}
|
||||
|
||||
// update the task with the updated parameters
|
||||
this.workflowService.updateTask(this.workItem.id, this.workItem.properties,
|
||||
null, null);
|
||||
|
||||
// commit the transaction
|
||||
tx.commit();
|
||||
|
||||
// reset the rich list if the change was successful
|
||||
this.packageItemsRichList.setValue(null);
|
||||
}
|
||||
catch (Throwable err)
|
||||
{
|
||||
Utils.addErrorMessage(MessageFormat.format(Application.getMessage(
|
||||
FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err);
|
||||
this.resources = Collections.<Node>emptyList();
|
||||
try { if (tx != null) {tx.rollback();} } catch (Exception tex) {}
|
||||
}
|
||||
// TODO: implement this!
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Bean Getters and Setters
|
||||
|
||||
/**
|
||||
* Returns a String array of NodeRef's that are being added to the workflow package
|
||||
*
|
||||
* @return String array of NodeRef's
|
||||
*/
|
||||
public String[] getItemsToAdd()
|
||||
{
|
||||
return this.itemsToAdd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the NodeRef's to add as items to the workflow package
|
||||
*
|
||||
* @param itemsToAdd NodeRef's to add to the workflow package
|
||||
*/
|
||||
public void setItemsToAdd(String[] itemsToAdd)
|
||||
{
|
||||
this.itemsToAdd = itemsToAdd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether an item is currently being added to the workflow package
|
||||
*
|
||||
* @return true if an item is being added
|
||||
*/
|
||||
public boolean isItemBeingAdded()
|
||||
{
|
||||
return this.isItemBeingAdded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the rich list being used for the workflow package items
|
||||
*
|
||||
@@ -358,21 +477,9 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
*/
|
||||
public List<Node> getResources()
|
||||
{
|
||||
NodeRef workflowPackage = null;
|
||||
Serializable obj = this.workItem.properties.get(WorkflowModel.ASSOC_PACKAGE);
|
||||
// TODO: remove this workaroud where JBPM may return a String and not the NodeRef
|
||||
if (obj instanceof NodeRef)
|
||||
{
|
||||
workflowPackage = (NodeRef)obj;
|
||||
}
|
||||
else if (obj instanceof String)
|
||||
{
|
||||
workflowPackage = new NodeRef((String)obj);
|
||||
}
|
||||
|
||||
this.resources = new ArrayList<Node>(4);
|
||||
|
||||
if (workflowPackage != null)
|
||||
if (this.workflowPackage != null)
|
||||
{
|
||||
UserTransaction tx = null;
|
||||
try
|
||||
@@ -381,12 +488,10 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
tx = Repository.getUserTransaction(context, true);
|
||||
tx.begin();
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found workflow package for work item '" +
|
||||
this.workItem.id + "': " + workflowPackage );
|
||||
|
||||
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(workflowPackage,
|
||||
ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL);
|
||||
// get existing workflow package items
|
||||
List<ChildAssociationRef> childRefs = this.nodeService.getChildAssocs(
|
||||
this.workflowPackage, ContentModel.ASSOC_CONTAINS,
|
||||
RegexQNamePattern.MATCH_ALL);
|
||||
|
||||
for (ChildAssociationRef ref: childRefs)
|
||||
{
|
||||
@@ -408,18 +513,13 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_CONTENT) ||
|
||||
ContentModel.TYPE_FILELINK.equals(type))
|
||||
{
|
||||
// create our Node representation
|
||||
MapNode node = new MapNode(nodeRef, this.nodeService, true);
|
||||
this.browseBean.setupCommonBindingProperties(node);
|
||||
|
||||
// add property resolvers to show path information
|
||||
node.addPropertyResolver("path", this.browseBean.resolverPath);
|
||||
node.addPropertyResolver("displayPath", this.browseBean.resolverDisplayPath);
|
||||
|
||||
// add a property resolver to indicate whether the item has been completed or not
|
||||
node.addPropertyResolver("completed", this.completeResolver);
|
||||
|
||||
this.resources.add(node);
|
||||
// if the node is not in the removed list then add create the
|
||||
// client side representation and add to the list
|
||||
if (this.packageItemsToRemove == null ||
|
||||
this.packageItemsToRemove.contains(nodeRef.toString()) == false)
|
||||
{
|
||||
createAndAddNode(nodeRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -428,6 +528,31 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Ignoring " + nodeRef + " as it has been removed from the repository");
|
||||
}
|
||||
}
|
||||
|
||||
// now iterate through the items to add list and add them to the list of resources
|
||||
if (this.packageItemsToAdd != null)
|
||||
{
|
||||
for (String newItem : this.packageItemsToAdd)
|
||||
{
|
||||
NodeRef nodeRef = new NodeRef(newItem);
|
||||
if (this.nodeService.exists(nodeRef))
|
||||
{
|
||||
// we know the type is correct as this was added as a result of a query
|
||||
// for all content items so just add the item to the resources list
|
||||
createAndAddNode(nodeRef);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Ignoring " + nodeRef + " as it has been removed from the repository");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// commit the transaction
|
||||
@@ -463,6 +588,21 @@ public class ManageWorkItemDialog extends BaseDialogBean
|
||||
// ------------------------------------------------------------------------------
|
||||
// Helper methods
|
||||
|
||||
protected void createAndAddNode(NodeRef nodeRef)
|
||||
{
|
||||
// create our Node representation
|
||||
MapNode node = new MapNode(nodeRef, this.nodeService, true);
|
||||
this.browseBean.setupCommonBindingProperties(node);
|
||||
|
||||
// add property resolvers to show path information
|
||||
node.addPropertyResolver("path", this.browseBean.resolverPath);
|
||||
node.addPropertyResolver("displayPath", this.browseBean.resolverDisplayPath);
|
||||
|
||||
// add a property resolver to indicate whether the item has been completed or not
|
||||
// node.addPropertyResolver("completed", this.completeResolver);
|
||||
|
||||
this.resources.add(node);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Inner classes
|
||||
|
@@ -0,0 +1,401 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.gnu.org/licenses/lgpl.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.ui.repo.component;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.faces.component.UIInput;
|
||||
import javax.faces.context.FacesContext;
|
||||
import javax.faces.context.ResponseWriter;
|
||||
import javax.faces.el.ValueBinding;
|
||||
|
||||
import org.alfresco.model.ContentModel;
|
||||
import org.alfresco.service.cmr.repository.NodeRef;
|
||||
import org.alfresco.service.cmr.repository.NodeService;
|
||||
import org.alfresco.service.cmr.search.ResultSet;
|
||||
import org.alfresco.service.cmr.search.SearchService;
|
||||
import org.alfresco.service.namespace.NamespaceService;
|
||||
import org.alfresco.service.namespace.QName;
|
||||
import org.alfresco.web.app.Application;
|
||||
import org.alfresco.web.bean.repository.Repository;
|
||||
import org.alfresco.web.ui.common.Utils;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Component for selecting content from the repository
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public class UIContentSelector extends UIInput
|
||||
{
|
||||
private final static Log logger = LogFactory.getLog(UIContentSelector.class);
|
||||
|
||||
private final static String ACTION_SEPARATOR = ";";
|
||||
private final static String ACTION_SEARCH = "0";
|
||||
|
||||
private final static String FIELD_CONTAINS = "_contains";
|
||||
private final static String FIELD_AVAILABLE = "_available";
|
||||
private final static String MSG_SEARCH = "search";
|
||||
|
||||
protected String availableOptionsSize;
|
||||
protected Boolean disabled;
|
||||
private Boolean multiSelect;
|
||||
|
||||
/** List containing the currently available options */
|
||||
protected List<NodeRef> availableOptions;
|
||||
|
||||
// ------------------------------------------------------------------------------
|
||||
// Component implementation
|
||||
|
||||
/**
|
||||
* @see javax.faces.component.UIComponent#getFamily()
|
||||
*/
|
||||
public String getFamily()
|
||||
{
|
||||
return "org.alfresco.faces.ContentSelector";
|
||||
}
|
||||
|
||||
/**
|
||||
* Default constructor
|
||||
*/
|
||||
public UIContentSelector()
|
||||
{
|
||||
setRendererType(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.component.StateHolder#restoreState(javax.faces.context.FacesContext, java.lang.Object)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void restoreState(FacesContext context, Object state)
|
||||
{
|
||||
Object values[] = (Object[])state;
|
||||
// standard component attributes are restored by the super class
|
||||
super.restoreState(context, values[0]);
|
||||
this.availableOptions = (List<NodeRef>)values[1];
|
||||
this.availableOptionsSize = (String)values[2];
|
||||
this.disabled = (Boolean)values[3];
|
||||
this.multiSelect = (Boolean)values[4];
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.component.StateHolder#saveState(javax.faces.context.FacesContext)
|
||||
*/
|
||||
public Object saveState(FacesContext context)
|
||||
{
|
||||
Object values[] = new Object[10];
|
||||
// standard component attributes are saved by the super class
|
||||
values[0] = super.saveState(context);
|
||||
values[1] = this.availableOptions;
|
||||
values[2] = this.availableOptionsSize;
|
||||
values[3] = this.disabled;
|
||||
values[4] = this.multiSelect;
|
||||
|
||||
return (values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.component.UIComponent#decode(javax.faces.context.FacesContext)
|
||||
*/
|
||||
public void decode(FacesContext context)
|
||||
{
|
||||
Map requestMap = context.getExternalContext().getRequestParameterMap();
|
||||
Map valuesMap = context.getExternalContext().getRequestParameterValuesMap();
|
||||
String fieldId = getHiddenFieldName();
|
||||
String value = (String)requestMap.get(fieldId);
|
||||
|
||||
if (value != null && value.equals(ACTION_SEARCH))
|
||||
{
|
||||
// user has issued a search action, fill the list with options
|
||||
String contains = (String)requestMap.get(fieldId + FIELD_CONTAINS);
|
||||
this.availableOptions = new ArrayList<NodeRef>();
|
||||
getAvailableOptions(FacesContext.getCurrentInstance(), contains);
|
||||
}
|
||||
else
|
||||
{
|
||||
// set the submitted value (if there is one)
|
||||
String[] addedItems = (String[])valuesMap.get(fieldId + FIELD_AVAILABLE);
|
||||
this.setSubmittedValue(addedItems);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.component.UIComponent#encodeBegin(javax.faces.context.FacesContext)
|
||||
*/
|
||||
public void encodeBegin(FacesContext context) throws IOException
|
||||
{
|
||||
if (isRendered() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ResponseWriter out = context.getResponseWriter();
|
||||
|
||||
// get the child associations currently on the node and any that have been added
|
||||
NodeService nodeService = Repository.getServiceRegistry(context).getNodeService();
|
||||
|
||||
if (isDisabled())
|
||||
{
|
||||
// TODO: if the component is disabled just show the current value as text
|
||||
}
|
||||
else
|
||||
{
|
||||
// start outer table
|
||||
out.write("<table border='0' cellspacing='4' cellpadding='0' class='");
|
||||
if (this.getAttributes().get("styleClass") != null)
|
||||
{
|
||||
out.write((String)this.getAttributes().get("styleClass"));
|
||||
}
|
||||
else
|
||||
{
|
||||
out.write("selector");
|
||||
}
|
||||
out.write("'");
|
||||
|
||||
if (this.getAttributes().get("style") != null)
|
||||
{
|
||||
out.write(" style='");
|
||||
out.write((String)this.getAttributes().get("style"));
|
||||
out.write("'");
|
||||
}
|
||||
out.write(">");
|
||||
|
||||
// show the search field
|
||||
out.write("<tr><td colspan='2'><input type='text' maxlength='1024' size='32' name='");
|
||||
out.write(getClientId(context) + FIELD_CONTAINS);
|
||||
out.write("'/> <input type='submit' value='");
|
||||
out.write(Application.getMessage(context, MSG_SEARCH));
|
||||
out.write("' onclick=\"");
|
||||
out.write(generateFormSubmit(context, ACTION_SEARCH));
|
||||
out.write("\"/></td></tr>");
|
||||
|
||||
// show available options i.e. all content in repository
|
||||
renderAvailableOptions(context, out, nodeService);
|
||||
|
||||
// close table
|
||||
out.write("</table>");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the component should be rendered in a disabled state
|
||||
*
|
||||
* @return Returns whether the component is disabled
|
||||
*/
|
||||
public boolean isDisabled()
|
||||
{
|
||||
if (this.disabled == null)
|
||||
{
|
||||
ValueBinding vb = getValueBinding("disabled");
|
||||
if (vb != null)
|
||||
{
|
||||
this.disabled = (Boolean)vb.getValue(getFacesContext());
|
||||
}
|
||||
}
|
||||
|
||||
if (this.disabled == null)
|
||||
{
|
||||
this.disabled = Boolean.FALSE;
|
||||
}
|
||||
|
||||
return this.disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the component should be rendered in a disabled state
|
||||
*
|
||||
* @param disabled true to disable the component
|
||||
*/
|
||||
public void setDisabled(boolean disabled)
|
||||
{
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the select control when multiple items
|
||||
* can be selected
|
||||
*
|
||||
* @return The size of the select control
|
||||
*/
|
||||
public String getAvailableOptionsSize()
|
||||
{
|
||||
if (this.availableOptionsSize == null)
|
||||
{
|
||||
this.availableOptionsSize = "6";
|
||||
}
|
||||
|
||||
return this.availableOptionsSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the size of the select control used when multiple items can
|
||||
* be selected
|
||||
*
|
||||
* @param availableOptionsSize The size
|
||||
*/
|
||||
public void setAvailableOptionsSize(String availableOptionsSize)
|
||||
{
|
||||
this.availableOptionsSize = availableOptionsSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if multi select should be enabled.
|
||||
*/
|
||||
public boolean getMultiSelect()
|
||||
{
|
||||
ValueBinding vb = getValueBinding("multiSelect");
|
||||
if (vb != null)
|
||||
{
|
||||
this.multiSelect = (Boolean)vb.getValue(getFacesContext());
|
||||
}
|
||||
|
||||
return multiSelect != null ? multiSelect.booleanValue() : true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param multiSelect Flag to determine whether multi select is enabled
|
||||
*/
|
||||
public void setMultiSelect(boolean multiSelect)
|
||||
{
|
||||
this.multiSelect = Boolean.valueOf(multiSelect);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders the list of available options
|
||||
*
|
||||
* @param context FacesContext
|
||||
* @param out Writer to write output to
|
||||
* @param nodeService The NodeService
|
||||
* @throws IOException
|
||||
*/
|
||||
protected void renderAvailableOptions(FacesContext context, ResponseWriter out, NodeService nodeService)
|
||||
throws IOException
|
||||
{
|
||||
boolean itemsPresent = (this.availableOptions != null && this.availableOptions.size() > 0);
|
||||
|
||||
out.write("<tr><td colspan='2'><select ");
|
||||
if (itemsPresent == false)
|
||||
{
|
||||
// rather than having a very slim select box set the width if there are no results
|
||||
out.write("style='width:240px;' ");
|
||||
}
|
||||
out.write("name='");
|
||||
out.write(getClientId(context) + FIELD_AVAILABLE);
|
||||
out.write("' size='");
|
||||
if (getMultiSelect())
|
||||
{
|
||||
out.write(getAvailableOptionsSize());
|
||||
out.write("' multiple");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.write("1'");
|
||||
}
|
||||
out.write(">");
|
||||
|
||||
if (itemsPresent)
|
||||
{
|
||||
for (NodeRef item : this.availableOptions)
|
||||
{
|
||||
out.write("<option value='");
|
||||
out.write(item.toString());
|
||||
out.write("'>");
|
||||
out.write(Repository.getDisplayPath(nodeService.getPath(item)));
|
||||
out.write("/");
|
||||
out.write(Repository.getNameForNode(nodeService, item));
|
||||
out.write("</option>");
|
||||
}
|
||||
}
|
||||
|
||||
out.write("</select></td></tr>");
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the available options for the current association
|
||||
*
|
||||
* @param context Faces Context
|
||||
* @param contains The contains part of the query
|
||||
*/
|
||||
protected void getAvailableOptions(FacesContext context, String contains)
|
||||
{
|
||||
// query for all content in the current repository
|
||||
StringBuilder query = new StringBuilder("+TYPE:\"");
|
||||
query.append(ContentModel.TYPE_CONTENT);
|
||||
query.append("\"");
|
||||
|
||||
if (contains != null && contains.length() > 0)
|
||||
{
|
||||
String safeContains = Utils.remove(contains.trim(), "\"");
|
||||
query.append(" AND +@");
|
||||
|
||||
String nameAttr = Repository.escapeQName(QName.createQName(
|
||||
NamespaceService.CONTENT_MODEL_1_0_URI, "name"));
|
||||
query.append(nameAttr);
|
||||
|
||||
query.append(":*" + safeContains + "*");
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Query: " + query.toString());
|
||||
|
||||
ResultSet results = null;
|
||||
try
|
||||
{
|
||||
results = Repository.getServiceRegistry(context).getSearchService().query(
|
||||
Repository.getStoreRef(), SearchService.LANGUAGE_LUCENE, query.toString());
|
||||
this.availableOptions = results.getNodeRefs();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (results != null)
|
||||
{
|
||||
results.close();
|
||||
}
|
||||
}
|
||||
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Found " + this.availableOptions.size() + " available options");
|
||||
}
|
||||
|
||||
/**
|
||||
* We use a hidden field per picker instance on the page.
|
||||
*
|
||||
* @return hidden field name
|
||||
*/
|
||||
private String getHiddenFieldName()
|
||||
{
|
||||
return getClientId(getFacesContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate FORM submit JavaScript for the specified action
|
||||
*
|
||||
* @param context FacesContext
|
||||
* @param action Action string
|
||||
*
|
||||
* @return FORM submit JavaScript
|
||||
*/
|
||||
private String generateFormSubmit(FacesContext context, String action)
|
||||
{
|
||||
return Utils.generateFormSubmit(context, this, getHiddenFieldName(), action);
|
||||
}
|
||||
}
|
113
source/java/org/alfresco/web/ui/repo/tag/ContentSelectorTag.java
Normal file
113
source/java/org/alfresco/web/ui/repo/tag/ContentSelectorTag.java
Normal file
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright (C) 2005 Alfresco, Inc.
|
||||
*
|
||||
* Licensed under the Mozilla Public License version 1.1
|
||||
* with a permitted attribution clause. You may obtain a
|
||||
* copy of the License at
|
||||
*
|
||||
* http://www.alfresco.org/legal/license.txt
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
* either express or implied. See the License for the specific
|
||||
* language governing permissions and limitations under the
|
||||
* License.
|
||||
*/
|
||||
package org.alfresco.web.ui.repo.tag;
|
||||
|
||||
import javax.faces.component.UIComponent;
|
||||
|
||||
import org.alfresco.web.ui.common.tag.HtmlComponentTag;
|
||||
|
||||
/**
|
||||
* Tag class to allow the content selector component to be added to a JSP page
|
||||
*
|
||||
* @author gavinc
|
||||
*/
|
||||
public class ContentSelectorTag extends HtmlComponentTag
|
||||
{
|
||||
private String availableOptionsSize;
|
||||
private String disabled;
|
||||
private String value;
|
||||
private String multiSelect;
|
||||
|
||||
/**
|
||||
* @see javax.faces.webapp.UIComponentTag#getComponentType()
|
||||
*/
|
||||
public String getComponentType()
|
||||
{
|
||||
return "org.alfresco.faces.ContentSelector";
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.webapp.UIComponentTag#getRendererType()
|
||||
*/
|
||||
public String getRendererType()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.webapp.UIComponentTag#setProperties(javax.faces.component.UIComponent)
|
||||
*/
|
||||
protected void setProperties(UIComponent component)
|
||||
{
|
||||
super.setProperties(component);
|
||||
|
||||
setStringStaticProperty(component, "availableOptionsSize", this.availableOptionsSize);
|
||||
setStringProperty(component, "value", this.value);
|
||||
setBooleanProperty(component, "disabled", this.disabled);
|
||||
setBooleanProperty(component, "multiSelect", this.multiSelect);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value The value to set.
|
||||
*/
|
||||
public void setValue(String value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param availableOptionsSize Sets the size of the available options size when
|
||||
* multiple items can be selected
|
||||
*/
|
||||
public void setAvailableOptionsSize(String availableOptionsSize)
|
||||
{
|
||||
this.availableOptionsSize = availableOptionsSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the multiSelect
|
||||
*
|
||||
* @param mutliSelect the multiSelect
|
||||
*/
|
||||
public void setMultiSelect(String multiSelect)
|
||||
{
|
||||
this.multiSelect = multiSelect;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets whether the component should be rendered in a disabled state
|
||||
*
|
||||
* @param disabled true to render the component in a disabled state
|
||||
*/
|
||||
public void setDisabled(String disabled)
|
||||
{
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see javax.faces.webapp.UIComponentTag#release()
|
||||
*/
|
||||
public void release()
|
||||
{
|
||||
this.availableOptionsSize = null;
|
||||
this.disabled = null;
|
||||
this.value = null;
|
||||
this.multiSelect = null;
|
||||
|
||||
super.release();
|
||||
}
|
||||
}
|
@@ -34,6 +34,7 @@ public abstract class BaseAssociationEditorTag extends BaseComponentTag
|
||||
private String selectedItemsMsg;
|
||||
private String noSelectedItemsMsg;
|
||||
private String disabled;
|
||||
private String value;
|
||||
|
||||
/**
|
||||
* @see javax.faces.webapp.UIComponentTag#getRendererType()
|
||||
@@ -56,9 +57,18 @@ public abstract class BaseAssociationEditorTag extends BaseComponentTag
|
||||
setStringProperty(component, "selectItemsMsg", this.selectItemsMsg);
|
||||
setStringProperty(component, "selectedItemsMsg", this.selectedItemsMsg);
|
||||
setStringProperty(component, "noSelectedItemsMsg", this.noSelectedItemsMsg);
|
||||
setStringProperty(component, "value", this.value);
|
||||
setBooleanProperty(component, "disabled", this.disabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param value The value to set.
|
||||
*/
|
||||
public void setValue(String value)
|
||||
{
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the association name
|
||||
*
|
||||
@@ -140,6 +150,7 @@ public abstract class BaseAssociationEditorTag extends BaseComponentTag
|
||||
this.selectedItemsMsg = null;
|
||||
this.noSelectedItemsMsg = null;
|
||||
this.disabled = null;
|
||||
this.value = null;
|
||||
|
||||
super.release();
|
||||
}
|
||||
|
@@ -54,6 +54,11 @@
|
||||
<component-class>org.alfresco.web.ui.repo.component.UISpaceSelector</component-class>
|
||||
</component>
|
||||
|
||||
<component>
|
||||
<component-type>org.alfresco.faces.ContentSelector</component-type>
|
||||
<component-class>org.alfresco.web.ui.repo.component.UIContentSelector</component-class>
|
||||
</component>
|
||||
|
||||
<component>
|
||||
<component-type>org.alfresco.faces.CategorySelector</component-type>
|
||||
<component-class>org.alfresco.web.ui.repo.component.UICategorySelector</component-class>
|
||||
|
@@ -209,11 +209,17 @@
|
||||
|
||||
<tag>
|
||||
<name>associationEditor</name>
|
||||
<tag-class>org.alfresco.web.ui.repo.tag.AssociationEditorTag</tag-class>
|
||||
<tag-class>org.alfresco.web.ui.repo.tag.property.AssociationEditorTag</tag-class>
|
||||
<body-content>JSP</body-content>
|
||||
|
||||
<attribute>
|
||||
<name>assocationName</name>
|
||||
<name>value</name>
|
||||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>associationName</name>
|
||||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
@@ -329,11 +335,17 @@
|
||||
|
||||
<tag>
|
||||
<name>childAssociationEditor</name>
|
||||
<tag-class>org.alfresco.web.ui.repo.tag.ChildAssociationEditorTag</tag-class>
|
||||
<tag-class>org.alfresco.web.ui.repo.tag.property.ChildAssociationEditorTag</tag-class>
|
||||
<body-content>JSP</body-content>
|
||||
|
||||
<attribute>
|
||||
<name>assocationName</name>
|
||||
<name>value</name>
|
||||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>associationName</name>
|
||||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
@@ -721,6 +733,60 @@
|
||||
</attribute>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
<name>contentSelector</name>
|
||||
<tag-class>org.alfresco.web.ui.repo.tag.ContentSelectorTag</tag-class>
|
||||
<body-content>JSP</body-content>
|
||||
|
||||
<attribute>
|
||||
<name>value</name>
|
||||
<required>true</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>availableOptionsSize</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>multiSelect</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>id</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>binding</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>rendered</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>style</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
|
||||
<attribute>
|
||||
<name>styleClass</name>
|
||||
<required>false</required>
|
||||
<rtexprvalue>true</rtexprvalue>
|
||||
</attribute>
|
||||
</tag>
|
||||
|
||||
<tag>
|
||||
<name>categorySelector</name>
|
||||
<tag-class>org.alfresco.web.ui.repo.tag.CategorySelectorTag</tag-class>
|
||||
|
@@ -107,7 +107,17 @@
|
||||
--%>
|
||||
</a:richList>
|
||||
|
||||
<%-- Put the package actions here --%>
|
||||
<h:panelGrid columns="1" styleClass="paddingRow">
|
||||
<r:actions context="#{DialogManager.bean.workItemNode}" value="#{DialogManager.bean.packageActionGroup}" />
|
||||
</h:panelGrid>
|
||||
|
||||
<h:panelGrid columns="1" rendered="#{DialogManager.bean.itemBeingAdded}" styleClass="selector" style="margin-top: 6px;">
|
||||
<r:contentSelector value="#{DialogManager.bean.itemsToAdd}" styleClass="" />
|
||||
<h:panelGrid columns="2">
|
||||
<h:commandButton value="#{msg.add_to_list_button}" actionListener="#{DialogManager.bean.addPackageItems}" />
|
||||
<h:commandButton value="#{msg.cancel}" actionListener="#{DialogManager.bean.cancelAddPackageItems}" />
|
||||
</h:panelGrid>
|
||||
</h:panelGrid>
|
||||
|
||||
</a:panel>
|
||||
|
||||
|
Reference in New Issue
Block a user