+ * NOTE: The name is NOT automatically added to the map of properties,
+ * if you need the name of this node to be in the map then add it to
+ * the map passed in to this constructor.
+ *
+ *
+ * @param type The type this node will represent
+ * @param name The name of the node
+ * @param data The properties and associations this node will have
+ */
+ public TransientMapNode(QName type, String name, Map data)
+ {
+ super(type, name, data);
+ }
+
+ @Override
+ public String toString()
+ {
+ return "Transient map node of type: " + getType() +
+ "\nProperties: " + this.getProperties().toString();
+ }
+
+ // ------------------------------------------------------------------------------
+ // Map implementation - allows the Node bean to be accessed using JSF expression syntax
+
+ /**
+ * @see java.util.Map#clear()
+ */
+ public void clear()
+ {
+ getProperties().clear();
+ }
+
+ /**
+ * @see java.util.Map#containsKey(java.lang.Object)
+ */
+ public boolean containsKey(Object key)
+ {
+ return getProperties().containsKey(key);
+ }
+
+ /**
+ * @see java.util.Map#containsValue(java.lang.Object)
+ */
+ public boolean containsValue(Object value)
+ {
+ return getProperties().containsKey(value);
+ }
+
+ /**
+ * @see java.util.Map#entrySet()
+ */
+ @SuppressWarnings("unchecked")
+ public Set entrySet()
+ {
+ return getProperties().entrySet();
+ }
+
+ /**
+ * @see java.util.Map#get(java.lang.Object)
+ */
+ public Object get(Object key)
+ {
+ return getProperties().get(key);
+ }
+
+ /**
+ * @see java.util.Map#isEmpty()
+ */
+ public boolean isEmpty()
+ {
+ return getProperties().isEmpty();
+ }
+
+ /**
+ * @see java.util.Map#keySet()
+ */
+ @SuppressWarnings("unchecked")
+ public Set keySet()
+ {
+ return getProperties().keySet();
+ }
+
+ /**
+ * @see java.util.Map#put(K, V)
+ */
+ public Object put(String key, Object value)
+ {
+ return getProperties().put(key, value);
+ }
+
+ /**
+ * @see java.util.Map#putAll(java.util.Map)
+ */
+ @SuppressWarnings("unchecked")
+ public void putAll(Map t)
+ {
+ getProperties().putAll(t);
+ }
+
+ /**
+ * @see java.util.Map#remove(java.lang.Object)
+ */
+ public Object remove(Object key)
+ {
+ return getProperties().remove(key);
+ }
+
+ /**
+ * @see java.util.Map#size()
+ */
+ public int size()
+ {
+ return getProperties().size();
+ }
+
+ /**
+ * @see java.util.Map#values()
+ */
+ @SuppressWarnings("unchecked")
+ public Collection values()
+ {
+ return getProperties().values();
+ }
+}
diff --git a/source/java/org/alfresco/web/bean/repository/TransientNode.java b/source/java/org/alfresco/web/bean/repository/TransientNode.java
index 8ef05da567..21dfbe340e 100644
--- a/source/java/org/alfresco/web/bean/repository/TransientNode.java
+++ b/source/java/org/alfresco/web/bean/repository/TransientNode.java
@@ -20,6 +20,7 @@ import org.alfresco.util.GUID;
* This type of node is typically used to drive the property sheet when data collection
* is required for a type but the node does not need to be stored in the repository. An
* example use is the workflow, transient nodes are used to collect workitem metadata.
+ *
*
* @author gavinc
*/
@@ -33,6 +34,7 @@ public class TransientNode extends Node
* NOTE: The name is NOT automatically added to the map of properties,
* if you need the name of this node to be in the map then add it to
* the map passed in to this constructor.
+ *
*
* @param type The type this node will represent
* @param name The name of the node
diff --git a/source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java b/source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java
index a25eea0e9b..75241e0144 100644
--- a/source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java
+++ b/source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java
@@ -1,12 +1,24 @@
package org.alfresco.web.bean.workflow;
+import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
+import java.util.Map;
import javax.faces.context.FacesContext;
+import javax.transaction.UserTransaction;
+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.namespace.QName;
+import org.alfresco.web.app.Application;
import org.alfresco.web.bean.dialog.BaseDialogBean;
+import org.alfresco.web.bean.repository.Node;
+import org.alfresco.web.bean.repository.Repository;
+import org.alfresco.web.bean.repository.TransientNode;
import org.alfresco.web.config.DialogsConfigElement.DialogButtonConfig;
+import org.alfresco.web.ui.common.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -17,51 +29,186 @@ import org.apache.commons.logging.LogFactory;
*/
public class ManageWorkItemDialog extends BaseDialogBean
{
- private static final Log logger = LogFactory.getLog(ManageWorkItemDialog.class);
+ protected WorkflowService workflowService;
+ protected Node workItemNode;
+ protected WorkflowTask workItem;
+ protected String[] transitions;
+
+ protected static final String ID_PREFIX = "transition_";
+ protected static final String CLIENT_ID_PREFIX = "dialog:" + ID_PREFIX;
+ private static final Log logger = LogFactory.getLog(ManageWorkItemDialog.class);
+
// ------------------------------------------------------------------------------
// Dialog implementation
+
+ @Override
+ public void init(Map parameters)
+ {
+ super.init(parameters);
+
+ String taskId = this.parameters.get("id");
+ this.workItem = this.workflowService.getTaskById(taskId);
+
+ if (this.workItem != null)
+ {
+ // setup a transient node to represent the work item we're managing
+ WorkflowTaskDefinition taskDef = this.workItem.definition;
+ this.workItemNode = new TransientNode(taskDef.metadata.getName(),
+ "task_" + System.currentTimeMillis(), this.workItem.properties);
+
+ if (logger.isDebugEnabled())
+ logger.debug("Created node for work item: " + this.workItemNode);
+ }
+ }
@Override
protected String finishImpl(FacesContext context, String outcome)
throws Exception
{
- return null;
+ if (logger.isDebugEnabled())
+ logger.debug("Saving work item with params: " + this.workItemNode.getProperties());
+
+ // prepare the edited parameters for saving
+ Map params = WorkflowBean.prepareWorkItemParams(this.workItemNode);
+
+ // update the task with the updated parameters
+ this.workflowService.updateTask(this.workItem.id, params, null, null);
+
+ return outcome;
}
-
+
@Override
public List getAdditionalButtons()
{
- List buttons = new ArrayList(1);
- buttons.add(new DialogButtonConfig("reassign-button",
- "Reassign", null, "#{ManageWorkItemDialog.reassign}", "false", null));
+ List buttons = null;
+
+ if (this.workItem != null)
+ {
+ // get the transitions available from this work item and
+ // show them in the dialog as additional buttons
+ this.transitions = this.workItem.path.node.transitions;
+
+ if (this.transitions != null)
+ {
+ buttons = new ArrayList(this.transitions.length);
+
+ for (String trans : this.transitions)
+ {
+ // TODO: Tidy this up when the service returns the list of labels
+ String label = trans;
+ if (label.length() == 0)
+ {
+ label = "Done";
+ }
+
+ buttons.add(new DialogButtonConfig(ID_PREFIX + trans, label, null,
+ "#{DialogManager.bean.transition}", "false", null));
+ }
+ }
+ }
- return buttons;
+ return buttons;
+ }
+
+ @Override
+ public String getFinishButtonLabel()
+ {
+ return Application.getMessage(FacesContext.getCurrentInstance(), "save");
}
+ @Override
+ public boolean getFinishButtonDisabled()
+ {
+ return false;
+ }
+
// ------------------------------------------------------------------------------
// Event handlers
-
- public void approve()
+
+ @SuppressWarnings("unused")
+ public String transition()
{
- logger.info("approve button was pressed");
- }
-
- public void reject()
- {
- logger.info("reject button was pressed");
- }
-
- public void reassign()
- {
- logger.info("reassign button was pressed");
+ String outcome = getDefaultFinishOutcome();
+
+ // to find out which transition button was pressed we need
+ // to look for the button's id in the request parameters,
+ // the first non-null result is the button that was pressed.
+ FacesContext context = FacesContext.getCurrentInstance();
+ Map reqParams = context.getExternalContext().getRequestParameterMap();
+
+ String selectedTransition = null;
+ for (String trans : this.transitions)
+ {
+ Object result = reqParams.get(CLIENT_ID_PREFIX + trans);
+ if (result != null)
+ {
+ // this was the button that was pressed
+ selectedTransition = trans;
+ break;
+ }
+ }
+
+ if (selectedTransition != null)
+ {
+ UserTransaction tx = null;
+
+ try
+ {
+ tx = Repository.getUserTransaction(context);
+ tx.begin();
+
+ // prepare the edited parameters for saving
+ Map params = WorkflowBean.prepareWorkItemParams(this.workItemNode);
+
+ // update the task with the updated parameters
+ this.workflowService.updateTask(this.workItem.id, params, null, null);
+
+ // signal the selected transition to the workflow task
+ this.workflowService.endTask(this.workItem.id, selectedTransition);
+
+ // commit the changes
+ tx.commit();
+
+ if (logger.isDebugEnabled())
+ logger.debug("Ended work item with transition: " + selectedTransition);
+ }
+ catch (Throwable e)
+ {
+ // reset the flag so we can re-attempt the operation
+ isFinished = false;
+
+ // rollback the transaction
+ try { if (tx != null) {tx.rollback();} } catch (Exception ex) {}
+ Utils.addErrorMessage(formatErrorMessage(e));
+ outcome = this.getErrorOutcome(e);
+ }
+ }
+
+ return outcome;
}
// ------------------------------------------------------------------------------
// Bean Getters and Setters
-
- public boolean getApproveDisabled()
+
+ /**
+ * Returns the Node representing the work item
+ *
+ * @return The node
+ */
+ public Node getWorkItemNode()
{
- return true;
+ return this.workItemNode;
+ }
+
+ /**
+ * Sets the workflow service to use
+ *
+ * @param workflowService
+ * WorkflowService instance
+ */
+ public void setWorkflowService(WorkflowService workflowService)
+ {
+ this.workflowService = workflowService;
}
}
diff --git a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java
index 6393ebd320..9a1300c250 100644
--- a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java
+++ b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java
@@ -1,6 +1,5 @@
package org.alfresco.web.bean.workflow;
-import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -10,18 +9,14 @@ import java.util.ResourceBundle;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
-import org.alfresco.service.cmr.repository.AssociationRef;
-import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.workflow.WorkflowDefinition;
import org.alfresco.service.cmr.workflow.WorkflowPath;
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.WorkflowTaskState;
-import org.alfresco.service.namespace.QName;
import org.alfresco.web.app.Application;
import org.alfresco.web.bean.repository.Node;
-import org.alfresco.web.bean.repository.Repository;
import org.alfresco.web.bean.repository.TransientNode;
import org.alfresco.web.bean.wizard.BaseWizardBean;
import org.apache.commons.logging.Log;
@@ -74,7 +69,8 @@ public class StartWorkflowWizard extends BaseWizardBean
logger.debug("Starting workflow with params: " + this.startTaskNode.getProperties());
// start the workflow to get access to the start task
- WorkflowPath path = this.workflowService.startWorkflow(this.selectedWorkflow, prepareTaskParams());
+ WorkflowPath path = this.workflowService.startWorkflow(this.selectedWorkflow,
+ WorkflowBean.prepareWorkItemParams(this.startTaskNode));
if (path != null)
{
// extract the start task
@@ -239,48 +235,4 @@ public class StartWorkflowWizard extends BaseWizardBean
{
this.workflowService = workflowService;
}
-
- protected Map prepareTaskParams()
- {
- Map params = new HashMap();
-
- // marshal the properties and associations captured by the property sheet
- // back into a Map to pass to the workflow service
-
- // go through all the properties in the transient node and add them to
- // params map
- Map props = this.startTaskNode.getProperties();
- for (String propName : props.keySet())
- {
- QName propQName = Repository.resolveToQName(propName);
- params.put(propQName, (Serializable)props.get(propName));
- }
-
- // go through any associations that have been added to the start task
- // and build a list of NodeRefs representing the targets
- Map> assocs = this.startTaskNode.getAddedAssociations();
- for (String assocName : assocs.keySet())
- {
- QName assocQName = Repository.resolveToQName(assocName);
-
- // get the associations added and create list of targets
- Map addedAssocs = assocs.get(assocName);
- List targets = new ArrayList(addedAssocs.size());
- for (AssociationRef assoc : addedAssocs.values())
- {
- targets.add(assoc.getTargetRef());
- }
-
- // add the targets for this particular association
- params.put(assocQName, (Serializable)targets);
- }
-
- // String reviewer = (String)this.startTaskNode.getProperties().get(
-// ContentModel.PROP_NAME);
-// Map params = new HashMap(1);
-// params.put(QName.createQName(NamespaceService.DEFAULT_URI, "reviewer"), reviewer);
-
-
- return params;
- }
}
diff --git a/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java b/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java
new file mode 100644
index 0000000000..cafb7e1e79
--- /dev/null
+++ b/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java
@@ -0,0 +1,140 @@
+package org.alfresco.web.bean.workflow;
+
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.faces.context.FacesContext;
+
+import org.alfresco.model.ContentModel;
+import org.alfresco.service.cmr.repository.AssociationRef;
+import org.alfresco.service.cmr.repository.NodeRef;
+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.WorkflowTaskState;
+import org.alfresco.service.namespace.QName;
+import org.alfresco.util.ISO9075;
+import org.alfresco.web.app.Application;
+import org.alfresco.web.bean.repository.Node;
+import org.alfresco.web.bean.repository.Repository;
+import org.alfresco.web.bean.repository.TransientMapNode;
+import org.alfresco.web.bean.repository.User;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+/**
+ * Managed bean used for handling workflow related features
+ *
+ * @author gavinc
+ */
+public class WorkflowBean
+{
+ protected WorkflowService workflowService;
+ protected List workItems;
+
+ private static final Log logger = LogFactory.getLog(WorkflowBean.class);
+
+ // ------------------------------------------------------------------------------
+ // Bean Getters and Setters
+
+ public List getWorkItemsToDo()
+ {
+ // get the current username
+ FacesContext fc = FacesContext.getCurrentInstance();
+ User user = Application.getCurrentUser(fc);
+ String userName = ISO9075.encode(user.getUserName());
+
+ // get the current in progress tasks for the current user
+ List tasks = this.workflowService.getAssignedTasks(
+ userName, WorkflowTaskState.IN_PROGRESS);
+
+ // create a list of transient nodes to represent
+ this.workItems = new ArrayList(tasks.size());
+ for (WorkflowTask task : tasks)
+ {
+ createWorkItem(task);
+ }
+
+ return this.workItems;
+ }
+
+ /**
+ * Sets the workflow service to use
+ *
+ * @param workflowService WorkflowService instance
+ */
+ public void setWorkflowService(WorkflowService workflowService)
+ {
+ this.workflowService = workflowService;
+ }
+
+ // ------------------------------------------------------------------------------
+ // Helper methods
+
+ public static Map prepareWorkItemParams(Node node)
+ {
+ Map params = new HashMap();
+
+ // marshal the properties and associations captured by the property sheet
+ // back into a Map to pass to the workflow service
+
+ // go through all the properties in the transient node and add them to
+ // params map
+ Map props = node.getProperties();
+ for (String propName : props.keySet())
+ {
+ QName propQName = Repository.resolveToQName(propName);
+ params.put(propQName, (Serializable)props.get(propName));
+ }
+
+ // go through any associations that have been added to the start task
+ // and build a list of NodeRefs representing the targets
+ Map> assocs = node.getAddedAssociations();
+ for (String assocName : assocs.keySet())
+ {
+ QName assocQName = Repository.resolveToQName(assocName);
+
+ // get the associations added and create list of targets
+ Map addedAssocs = assocs.get(assocName);
+ List targets = new ArrayList(addedAssocs.size());
+ for (AssociationRef assoc : addedAssocs.values())
+ {
+ targets.add(assoc.getTargetRef());
+ }
+
+ // add the targets for this particular association
+ params.put(assocQName, (Serializable)targets);
+ }
+
+ return params;
+ }
+
+ /**
+ * Creates and populates a TransientNode to represent the given
+ * workflow task from the repository workflow engine
+ *
+ * @param task The task to create a representation of
+ */
+ protected void createWorkItem(WorkflowTask task)
+ {
+ // get the type of the task
+ WorkflowTaskDefinition taskDef = task.definition;
+
+ // create the basic transient node
+ TransientMapNode node = new TransientMapNode(taskDef.metadata.getName(),
+ task.name, task.properties);
+
+ // add properties for the other useful metadata
+ node.getProperties().put(ContentModel.PROP_NAME.toString(), task.name);
+ node.getProperties().put("type", taskDef.metadata.getTitle());
+ node.getProperties().put("id", task.id);
+
+ if (logger.isDebugEnabled())
+ logger.debug("Created node for work item with id '" + task.id + "' " + node);
+
+ this.workItems.add(node);
+ }
+}
diff --git a/source/web/WEB-INF/faces-config-beans.xml b/source/web/WEB-INF/faces-config-beans.xml
index d79b3e25bc..4f0504bcb6 100644
--- a/source/web/WEB-INF/faces-config-beans.xml
+++ b/source/web/WEB-INF/faces-config-beans.xml
@@ -1737,6 +1737,10 @@
namespaceService#{NamespaceService}
+
+ workflowService
+ #{WorkflowService}
+
@@ -1777,6 +1781,16 @@
+
+ WorkflowBean
+ org.alfresco.web.bean.workflow.WorkflowBean
+ session
+
+ workflowService
+ #{WorkflowService}
+
+
+
diff --git a/source/web/jsp/dashboards/dashlets/my-tasks-todo.png b/source/web/jsp/dashboards/dashlets/my-tasks-todo.png
deleted file mode 100644
index e34ceee2aa..0000000000
Binary files a/source/web/jsp/dashboards/dashlets/my-tasks-todo.png and /dev/null differ
diff --git a/source/web/jsp/dashboards/dashlets/tasklist-todo.jsp b/source/web/jsp/workflow/manage-workitem-dialog.jsp
similarity index 78%
rename from source/web/jsp/dashboards/dashlets/tasklist-todo.jsp
rename to source/web/jsp/workflow/manage-workitem-dialog.jsp
index 22d7f0c020..fe9e556ed1 100644
--- a/source/web/jsp/dashboards/dashlets/tasklist-todo.jsp
+++ b/source/web/jsp/workflow/manage-workitem-dialog.jsp
@@ -1,5 +1,5 @@
<%--
- Copyright (C) 2006 Alfresco, Inc.
+ Copyright (C) 2005 Alfresco, Inc.
Licensed under the Mozilla Public License version 1.1
with a permitted attribution clause. You may obtain a
@@ -19,4 +19,5 @@
<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
-
+
\ No newline at end of file
diff --git a/source/web/jsp/workflow/manage-workitem.jsp b/source/web/jsp/workflow/manage-workitem.jsp
deleted file mode 100644
index b518813ad9..0000000000
--- a/source/web/jsp/workflow/manage-workitem.jsp
+++ /dev/null
@@ -1,28 +0,0 @@
-<%--
- 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.
---%>
-<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
-<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
-<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
-<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
-
-<%--
-
---%>
-
-
\ No newline at end of file
diff --git a/source/web/jsp/workflow/start-workflow-wizard/choose-workflow.jsp b/source/web/jsp/workflow/start-workflow-wizard/choose-workflow.jsp
index d57f91f593..a3799bbefb 100644
--- a/source/web/jsp/workflow/start-workflow-wizard/choose-workflow.jsp
+++ b/source/web/jsp/workflow/start-workflow-wizard/choose-workflow.jsp
@@ -19,7 +19,7 @@
<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
-
+
diff --git a/source/web/jsp/workflow/workitems-todo-dashlet.jsp b/source/web/jsp/workflow/workitems-todo-dashlet.jsp
new file mode 100644
index 0000000000..59ec036ddb
--- /dev/null
+++ b/source/web/jsp/workflow/workitems-todo-dashlet.jsp
@@ -0,0 +1,88 @@
+<%@ taglib uri="http://java.sun.com/jsf/html" prefix="h" %>
+<%@ taglib uri="http://java.sun.com/jsf/core" prefix="f" %>
+<%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %>
+<%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %>
+
+
+
+ <%-- Primary column for details view mode --%>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ <%-- Description column --%>
+
+
+
+
+
+
+
+ <%-- Type column --%>
+
+
+
+
+
+
+
+ <%-- Due date column --%>
+
+
+
+
+
+
+
+
+
+ <%-- Status column --%>
+
+
+
+
+
+
+
+ <%-- Actions column --%>
+ <%--
+
+
+
+
+
+
+
+
+
+
+
+
+
+ --%>
+
+
+
+
+
\ No newline at end of file