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("