From 4e56c6cae947caae44f51a52b8a3490c5ab088a9 Mon Sep 17 00:00:00 2001 From: Gavin Cornwell Date: Mon, 21 Aug 2006 14:30:42 +0000 Subject: [PATCH] - Next checkpoint of workflow - Made the date picker renderer allow user to set date to "None" git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@3554 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- config/alfresco/messages/webclient.properties | 6 + .../alfresco/web-client-config-workflow.xml | 16 +- .../bean/generator/DatePickerGenerator.java | 24 +- .../bean/generator/TextFieldGenerator.java | 13 +- .../web/bean/repository/TransientNode.java | 7 + .../bean/workflow/ManageWorkItemDialog.java | 104 +++++++- .../bean/workflow/StartWorkflowWizard.java | 48 +++- .../web/bean/workflow/WorkflowBean.java | 6 +- .../common/renderer/DatePickerRenderer.java | 234 +++++++++++++----- .../jsp/workflow/manage-workitem-dialog.jsp | 59 ++++- 10 files changed, 428 insertions(+), 89 deletions(-) diff --git a/config/alfresco/messages/webclient.properties b/config/alfresco/messages/webclient.properties index a632b74acd..dd2c2b6c5c 100644 --- a/config/alfresco/messages/webclient.properties +++ b/config/alfresco/messages/webclient.properties @@ -182,6 +182,9 @@ lock=Lock unlock=Unlock items_per_page=Items Per Page raise_issue=Raise an Issue +click_to_set_date=Click to set a date +today=Today +reset=Reset # Properties username=User Name @@ -935,9 +938,11 @@ start_workflow_options_desc=Select options for the workflow start_workflow_finish_instruction=To start the workflow press Finish. To review or change your selections click Back. start_workflow_no_metadata=There is no metadata to collect for this particular workflow. users_and_roles=Users and their Roles +resources=Resources manage_workitem=Manage WorkItem manage_workitem_title=Manage WorkItem manage_workitem_desc=This dialog allows the work item to be managed +workitem_properties=Work Item Properties id=Id status=Status my_workitems_todo_title=My Work Items To Do @@ -949,6 +954,7 @@ completed_on=Completed on outcome=Outcome reassign=Reassign + # Admin Console messages title_admin_console=Administration Console admin_console=Administration Console diff --git a/config/alfresco/web-client-config-workflow.xml b/config/alfresco/web-client-config-workflow.xml index 2bb90ba827..6234f356fa 100644 --- a/config/alfresco/web-client-config-workflow.xml +++ b/config/alfresco/web-client-config-workflow.xml @@ -7,18 +7,18 @@ - + + + - - + + @@ -37,7 +37,7 @@ wizard:startWorkflow #{WizardManager.setupParameters} - #{actionContext.id} + #{actionContext.id} @@ -51,6 +51,10 @@ + + + + diff --git a/source/java/org/alfresco/web/bean/generator/DatePickerGenerator.java b/source/java/org/alfresco/web/bean/generator/DatePickerGenerator.java index 5a2e3badd5..a7f0463ddb 100644 --- a/source/java/org/alfresco/web/bean/generator/DatePickerGenerator.java +++ b/source/java/org/alfresco/web/bean/generator/DatePickerGenerator.java @@ -4,6 +4,7 @@ import java.util.Date; import javax.faces.component.UIComponent; import javax.faces.component.UIOutput; +import javax.faces.component.UISelectOne; import javax.faces.context.FacesContext; import javax.faces.convert.Converter; @@ -13,6 +14,7 @@ import org.alfresco.web.app.servlet.FacesHelper; import org.alfresco.web.ui.common.ComponentConstants; import org.alfresco.web.ui.common.converter.XMLDateConverter; import org.alfresco.web.ui.repo.RepoConstants; +import org.alfresco.web.ui.repo.component.UIMultiValueEditor; import org.alfresco.web.ui.repo.component.property.PropertySheetItem; import org.alfresco.web.ui.repo.component.property.UIPropertySheet; @@ -97,8 +99,26 @@ public class DatePickerGenerator extends BaseComponentGenerator UIPropertySheet propertySheet, PropertySheetItem item, UIComponent component, boolean realTimeChecking, String idSuffix) { - // a date picker will always have a date value so there - // is no need to create a mandatory validation rule + if (component instanceof UIMultiValueEditor) + { + // Override the setup of the mandatory validation + // so we can send the _current_value id suffix. + // We also enable real time so the page load + // check disables the ok button if necessary, as the user + // adds or removes items from the multi value list the + // page will be refreshed and therefore re-check the status. + + super.setupMandatoryValidation(context, propertySheet, item, + component, true, "_current_value"); + } + else + { + // setup the client validation rule with real time validation enabled + // so that the initial page load checks the state of the date + super.setupMandatoryValidation(context, propertySheet, item, + component, true, idSuffix); + } + } /** diff --git a/source/java/org/alfresco/web/bean/generator/TextFieldGenerator.java b/source/java/org/alfresco/web/bean/generator/TextFieldGenerator.java index 4a84e10f44..cdbe96d52e 100644 --- a/source/java/org/alfresco/web/bean/generator/TextFieldGenerator.java +++ b/source/java/org/alfresco/web/bean/generator/TextFieldGenerator.java @@ -84,12 +84,17 @@ public class TextFieldGenerator extends BaseComponentGenerator if (propertySheet.inEditMode()) { - // if the field has the list of values constraint a - // SelectOne component is required otherwise create - // the standard edit component + // if the field has the list of values constraint + // and it is editable a SelectOne component is + // required otherwise create the standard edit component ListOfValuesConstraint constraint = getListOfValuesConstraint( context, propertySheet, item); - if (constraint != null) + + PropertyDefinition propDef = this.getPropertyDefinition(context, + propertySheet.getNode(), item.getName()); + + if (constraint != null && item.isReadOnly() == false && + propDef != null && propDef.isProtected() == false) { component = context.getApplication().createComponent( UISelectOne.COMPONENT_TYPE); diff --git a/source/java/org/alfresco/web/bean/repository/TransientNode.java b/source/java/org/alfresco/web/bean/repository/TransientNode.java index 21dfbe340e..50a2c11e32 100644 --- a/source/java/org/alfresco/web/bean/repository/TransientNode.java +++ b/source/java/org/alfresco/web/bean/repository/TransientNode.java @@ -13,6 +13,8 @@ import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; import org.alfresco.util.GUID; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** * Represents a transient node i.e. it is not and will not be present in the repository. @@ -27,6 +29,8 @@ import org.alfresco.util.GUID; public class TransientNode extends Node { private static final long serialVersionUID = 2140554155948154106L; + + private static final Log logger = LogFactory.getLog(TransientNode.class); /** * Constructor. @@ -50,6 +54,9 @@ public class TransientNode extends Node // initialise the node initNode(data); + + if (logger.isDebugEnabled()) + logger.debug("Constructed transient node: " + this); } /** diff --git a/source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java b/source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java index e1453564e0..33d26071b7 100644 --- a/source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java +++ b/source/java/org/alfresco/web/bean/workflow/ManageWorkItemDialog.java @@ -1,20 +1,29 @@ package org.alfresco.web.bean.workflow; import java.io.Serializable; +import java.text.MessageFormat; import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.Map; import javax.faces.context.FacesContext; import javax.transaction.UserTransaction; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.workflow.WorkflowModel; +import org.alfresco.service.cmr.dictionary.TypeDefinition; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +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.WorkflowTransition; import org.alfresco.service.namespace.QName; +import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.web.app.Application; import org.alfresco.web.bean.dialog.BaseDialogBean; +import org.alfresco.web.bean.repository.MapNode; import org.alfresco.web.bean.repository.Node; import org.alfresco.web.bean.repository.Repository; import org.alfresco.web.bean.repository.TransientNode; @@ -34,6 +43,7 @@ public class ManageWorkItemDialog extends BaseDialogBean protected Node workItemNode; protected WorkflowTask workItem; protected WorkflowTransition[] transitions; + protected List resources; protected static final String ID_PREFIX = "transition_"; protected static final String CLIENT_ID_PREFIX = "dialog:" + ID_PREFIX; @@ -57,9 +67,6 @@ public class ManageWorkItemDialog extends BaseDialogBean 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); } } @@ -68,7 +75,7 @@ public class ManageWorkItemDialog extends BaseDialogBean throws Exception { if (logger.isDebugEnabled()) - logger.debug("Saving work item with params: " + this.workItemNode.getProperties()); + logger.debug("Saving work item: " + this.workItemNode.getId()); // prepare the edited parameters for saving Map params = WorkflowBean.prepareWorkItemParams(this.workItemNode); @@ -96,7 +103,7 @@ public class ManageWorkItemDialog extends BaseDialogBean for (WorkflowTransition trans : this.transitions) { - buttons.add(new DialogButtonConfig(ID_PREFIX + trans, trans.title, null, + buttons.add(new DialogButtonConfig(ID_PREFIX + trans.title, trans.title, null, "#{DialogManager.bean.transition}", "false", null)); } } @@ -125,6 +132,9 @@ public class ManageWorkItemDialog extends BaseDialogBean { String outcome = getDefaultFinishOutcome(); + if (logger.isDebugEnabled()) + logger.debug("Transitioning work item: " + this.workItemNode.getId()); + // 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. @@ -134,7 +144,7 @@ public class ManageWorkItemDialog extends BaseDialogBean String selectedTransition = null; for (WorkflowTransition trans : this.transitions) { - Object result = reqParams.get(CLIENT_ID_PREFIX + trans); + Object result = reqParams.get(CLIENT_ID_PREFIX + trans.title); if (result != null) { // this was the button that was pressed @@ -195,6 +205,88 @@ public class ManageWorkItemDialog extends BaseDialogBean return this.workItemNode; } + /** + * Returns a list of resources associated with this work item + * i.e. the children of the workflow package + * + * @return The list of nodes + */ + public List getResources() + { + NodeRef workflowPackage = (NodeRef)this.workItem.properties.get(WorkflowModel.ASSOC_PACKAGE); + + this.resources = new ArrayList(4); + + if (workflowPackage != null) + { + UserTransaction tx = null; + try + { + FacesContext context = FacesContext.getCurrentInstance(); + tx = Repository.getUserTransaction(context, true); + tx.begin(); + + if (logger.isDebugEnabled()) + logger.debug("Found workflow package for work item '" + + this.workItem.id + "': " + workflowPackage ); + + List childRefs = this.nodeService.getChildAssocs(workflowPackage, + ContentModel.ASSOC_CONTAINS, RegexQNamePattern.MATCH_ALL); + + for (ChildAssociationRef ref: childRefs) + { + // create our Node representation from the NodeRef + NodeRef nodeRef = ref.getChildRef(); + + if (this.nodeService.exists(nodeRef)) + { + // find it's type so we can see if it's a node we are interested in + QName type = this.nodeService.getType(nodeRef); + + // make sure the type is defined in the data dictionary + TypeDefinition typeDef = this.dictionaryService.getType(type); + + if (typeDef != null) + { + // look for content nodes or links to content + // NOTE: folders within workflow packages are ignored for now + 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); + + this.resources.add(node); + } + } + else + { + if (logger.isWarnEnabled()) + logger.warn("Found invalid object in database: id = " + nodeRef + ", type = " + type); + } + } + } + + // commit the transaction + tx.commit(); + } + catch (Throwable err) + { + Utils.addErrorMessage(MessageFormat.format(Application.getMessage( + FacesContext.getCurrentInstance(), Repository.ERROR_GENERIC), err.getMessage()), err); + this.resources = Collections.emptyList(); + try { if (tx != null) {tx.rollback();} } catch (Exception tex) {} + } + } + else if (logger.isDebugEnabled()) + { + logger.debug("Failed to find workflow package for work item: " + this.workItem.id); + } + + return this.resources; + } + /** * Sets the workflow service to use * diff --git a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java index c24639c83c..b0c3fc53c9 100644 --- a/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java +++ b/source/java/org/alfresco/web/bean/workflow/StartWorkflowWizard.java @@ -1,5 +1,6 @@ package org.alfresco.web.bean.workflow; +import java.io.Serializable; import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -9,14 +10,20 @@ import java.util.ResourceBundle; import javax.faces.context.FacesContext; import javax.faces.model.SelectItem; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.workflow.WorkflowModel; +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.NamespaceService; +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; @@ -66,11 +73,41 @@ public class StartWorkflowWizard extends BaseWizardBean // TODO: Deal with workflows that don't require any data if (logger.isDebugEnabled()) - logger.debug("Starting workflow with params: " + this.startTaskNode.getProperties()); + logger.debug("Starting workflow: " + this.selectedWorkflow); + + // prepare the parameters from the current state of the property sheet + Map params = WorkflowBean.prepareWorkItemParams(this.startTaskNode); + + // create a workflow package for the attached items and add them + String itemToWorkflowId = this.parameters.get("item-to-workflow"); + if (itemToWorkflowId != null && itemToWorkflowId.length() > 0) + { + // create the node ref for the item and determine its type + NodeRef itemToWorkflow = new NodeRef(Repository.getStoreRef(), itemToWorkflowId); + QName type = this.nodeService.getType(itemToWorkflow); + + NodeRef workflowPackage = null; + if (this.dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDER) || + this.dictionaryService.isSubClass(type, ContentModel.TYPE_FOLDERLINK)) + { + throw new UnsupportedOperationException("Workflow on a folder is not supported yet!"); + } + else + { + // create a workflow package and add the given item to workflow as a child + workflowPackage = this.workflowService.createPackage(null); + this.nodeService.addChild(workflowPackage, itemToWorkflow, + ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI, + QName.createValidLocalName((String)this.nodeService.getProperty( + itemToWorkflow, ContentModel.PROP_NAME)))); + } + + // add the workflow package to the parameter map + params.put(WorkflowModel.ASSOC_PACKAGE, workflowPackage); + } // start the workflow to get access to the start task - WorkflowPath path = this.workflowService.startWorkflow(this.selectedWorkflow, - WorkflowBean.prepareWorkItemParams(this.startTaskNode)); + WorkflowPath path = this.workflowService.startWorkflow(this.selectedWorkflow, params); if (path != null) { // extract the start task @@ -111,7 +148,7 @@ public class StartWorkflowWizard extends BaseWizardBean WorkflowDefinition flowDef = this.workflows.get(this.selectedWorkflow); if (logger.isDebugEnabled()) - logger.debug("Starting workflow: "+ flowDef); + logger.debug("Selected workflow: "+ flowDef); WorkflowTaskDefinition taskDef = flowDef.startTaskDefinition; if (taskDef != null) @@ -122,9 +159,6 @@ public class StartWorkflowWizard extends BaseWizardBean // create an instance of a task from the data dictionary this.startTaskNode = new TransientNode(taskDef.metadata.getName(), "task_" + System.currentTimeMillis(), null); - - if (logger.isDebugEnabled()) - logger.debug("Created node for task: " + this.startTaskNode); } } diff --git a/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java b/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java index 94c2bde380..f5f487e4b6 100644 --- a/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java +++ b/source/java/org/alfresco/web/bean/workflow/WorkflowBean.java @@ -143,6 +143,9 @@ public class WorkflowBean params.put(assocQName, (Serializable)targets); } + if (logger.isDebugEnabled()) + logger.debug("Prepared parameters: " + params); + return params; } @@ -166,9 +169,6 @@ public class WorkflowBean 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); - return node; } } diff --git a/source/java/org/alfresco/web/ui/common/renderer/DatePickerRenderer.java b/source/java/org/alfresco/web/ui/common/renderer/DatePickerRenderer.java index 4f85d1404f..6181461f69 100644 --- a/source/java/org/alfresco/web/ui/common/renderer/DatePickerRenderer.java +++ b/source/java/org/alfresco/web/ui/common/renderer/DatePickerRenderer.java @@ -36,6 +36,9 @@ import javax.faces.convert.ConverterException; import javax.faces.model.SelectItem; import org.alfresco.web.app.Application; +import org.alfresco.web.ui.common.Utils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** * @author kevinr @@ -51,6 +54,12 @@ public class DatePickerRenderer extends BaseRenderer private static final String FIELD_DAY = "_day"; private static final String FIELD_HOUR = "_hour"; private static final String FIELD_MINUTE = "_minute"; + private static final String FIELD_CMD = "_cmd"; + private static final int CMD_SET = 1; + private static final int CMD_RESET = 2; + private static final int CMD_TODAY = 3; + + private static final Log logger = LogFactory.getLog(DatePickerRenderer.class); /** * @see javax.faces.render.Renderer#decode(javax.faces.context.FacesContext, javax.faces.component.UIComponent) @@ -66,26 +75,68 @@ public class DatePickerRenderer extends BaseRenderer // TODO: should check for disabled/readonly here - no need to decode String clientId = component.getClientId(context); Map params = context.getExternalContext().getRequestParameterMap(); - String year = (String)params.get(clientId + FIELD_YEAR); - if (year != null) + + // see if a command was invoked + String cmd = (String)params.get(clientId + FIELD_CMD); + if (cmd != null && cmd.length() > 0) { - // found data for our component - String month = (String)params.get(clientId + FIELD_MONTH); - String day = (String)params.get(clientId + FIELD_DAY); - String hour = (String)params.get(clientId + FIELD_HOUR); - String minute = (String)params.get(clientId + FIELD_MINUTE); + int action = Integer.parseInt(cmd); - // we encode the values needed for the component as we see fit - int[] parts = new int[5]; - parts[0] = Integer.parseInt(year); - parts[1] = Integer.parseInt(month); - parts[2] = Integer.parseInt(day); - parts[3] = Integer.parseInt(hour); - parts[4] = Integer.parseInt(minute); - - // save the data in an object for our component as the "EditableValueHolder" - // all UI Input Components support this interface for the submitted value - ((EditableValueHolder)component).setSubmittedValue(parts); + switch (action) + { + case CMD_RESET: + { + // set the submitted value to be null + ((EditableValueHolder)component).setSubmittedValue(null); + + // set the component value to be null too + ((EditableValueHolder)component).setValue(null); + + break; + } + + default: + { + // the user is either trying to set the date for the first + // time or set it back to today's date, create the parts array + // to represent this and set as the submitted value + int[] parts = new int[5]; + + Calendar date = Calendar.getInstance(); + parts[0] = date.get(Calendar.YEAR); + parts[1] = date.get(Calendar.MONTH); + parts[2] = date.get(Calendar.DAY_OF_MONTH); + parts[3] = date.get(Calendar.HOUR_OF_DAY); + parts[4] = date.get(Calendar.MINUTE); + + ((EditableValueHolder)component).setSubmittedValue(parts); + } + } + } + else + { + // a command was not invoked so decode the date the user set (if present) + String year = (String)params.get(clientId + FIELD_YEAR); + if (year != null) + { + // found data for our component + String month = (String)params.get(clientId + FIELD_MONTH); + String day = (String)params.get(clientId + FIELD_DAY); + String hour = (String)params.get(clientId + FIELD_HOUR); + String minute = (String)params.get(clientId + FIELD_MINUTE); + + // we encode the values needed for the component as we see fit + int[] parts = new int[5]; + parts[0] = Integer.parseInt(year); + parts[1] = Integer.parseInt(month); + parts[2] = Integer.parseInt(day); + parts[3] = Integer.parseInt(hour); + parts[4] = Integer.parseInt(minute); + + // save the data in an object for our component as the "EditableValueHolder" + // all UI Input Components support this interface for the submitted value + ((EditableValueHolder)component).setSubmittedValue(parts); + } } } catch (NumberFormatException nfe) @@ -124,6 +175,9 @@ public class DatePickerRenderer extends BaseRenderer if (component.isRendered() == true) { Date date = null; + String clientId = component.getClientId(context); + ResponseWriter out = context.getResponseWriter(); + String cmdFieldName = clientId + FIELD_CMD; // this is part of the spec: // first you attempt to build the date from the submitted value @@ -136,57 +190,119 @@ public class DatePickerRenderer extends BaseRenderer { // second if no submitted value is found, default to the current value Object value = ((ValueHolder)component).getValue(); - // finally check for null value and create default if needed - date = value instanceof Date ? (Date)value : new Date(); + if (value instanceof Date) + { + date = (Date)value; + } } - // get the attributes from the component we need for rendering - int nStartYear; - Integer startYear = (Integer)component.getAttributes().get("startYear"); - if (startYear != null) + // create a flag to show if the component is disabled + Boolean disabled = (Boolean)component.getAttributes().get("disabled"); + if (disabled == null) { - nStartYear = startYear.intValue(); + disabled = Boolean.FALSE; + } + + if (date != null) + { + // get the attributes from the component we need for rendering + int nStartYear; + Integer startYear = (Integer)component.getAttributes().get("startYear"); + if (startYear != null) + { + nStartYear = startYear.intValue(); + } + else + { + nStartYear = new Date().getYear() + 1900 + 2; // for "effectivity date" searches + } + + int nYearCount = 25; + Integer yearCount = (Integer)component.getAttributes().get("yearCount"); + if (yearCount != null) + { + nYearCount = yearCount.intValue(); + } + + // now we render the output for our component + // we create 3 drop-down menus for day, month and year and + // two text fields for the hour and minute + + // note that we build a client id for our form elements that we are then + // able to decode() as above. + Calendar calendar = new GregorianCalendar(); + calendar.setTime(date); + renderMenu(out, component, getDays(), calendar.get(Calendar.DAY_OF_MONTH), clientId + FIELD_DAY); + renderMenu(out, component, getMonths(), calendar.get(Calendar.MONTH), clientId + FIELD_MONTH); + renderMenu(out, component, getYears(nStartYear, nYearCount), calendar.get(Calendar.YEAR), clientId + FIELD_YEAR); + + // make sure we have a flag to determine whether to show the time + Boolean showTime = (Boolean)component.getAttributes().get("showTime"); + if (showTime == null) + { + showTime = Boolean.FALSE; + } + + out.write(" "); + renderTimeElement(out, component, calendar.get(Calendar.HOUR_OF_DAY), clientId + FIELD_HOUR, showTime.booleanValue()); + if (showTime.booleanValue()) + { + out.write(" : "); + } + renderTimeElement(out, component, calendar.get(Calendar.MINUTE), clientId + FIELD_MINUTE, showTime.booleanValue()); + out.write(" "); + + // render 2 links (if the component is not disabled) to allow the user to reset the + // date back to null or to select today's date + if (disabled.booleanValue() == false) + { + out.write(" "); + } } else { - nStartYear = new Date().getYear() + 1900 + 2; // for "effectivity date" searches + // Render a link indicating there isn't a date set (unless the property is disabled) + out.write(""); } - int nYearCount = 25; - Integer yearCount = (Integer)component.getAttributes().get("yearCount"); - if (yearCount != null) + // also output a hidden field containing the current value of the date, this will + // allow JavaScript to determine if a value is set for validation purposes. + out.write(""); } } diff --git a/source/web/jsp/workflow/manage-workitem-dialog.jsp b/source/web/jsp/workflow/manage-workitem-dialog.jsp index fe9e556ed1..f23dc7bfb8 100644 --- a/source/web/jsp/workflow/manage-workitem-dialog.jsp +++ b/source/web/jsp/workflow/manage-workitem-dialog.jsp @@ -19,5 +19,60 @@ <%@ taglib uri="/WEB-INF/alfresco.tld" prefix="a" %> <%@ taglib uri="/WEB-INF/repo.tld" prefix="r" %> - \ No newline at end of file + + + + + + + + + + + + <%-- Primary column for details view mode --%> + + + + + + + + + + + <%-- Description column --%> + + + + + + + + <%-- Path column --%> + + + + + + + + <%-- Actions column --%> + + + + + + <%-- actions are configured in web-client-config-actions.xml --%> + + + + + + \ No newline at end of file