← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 8124: Finished dynamic fields in cde. Impl option for validation requiring all category options to be f...

 

Merge authors:
  Lars Helge Øverland (larshelge)
------------------------------------------------------------
revno: 8124 [merge]
committer: Lars Helge Øverland <larshelge@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2012-09-18 18:20:20 +0200
message:
  Finished dynamic fields in cde. Impl option for validation requiring all category options to be filled for a data element in a form.
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/DataSet.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataentryform/DefaultDataEntryFormService.java
  dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java
  dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataset/hibernate/DataSet.hbm.xml
  dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/widgets.css
  dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/org/hisp/dhis/de/i18n_module.properties
  dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/customForm.vm
  dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/entry.js
  dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/form.js
  dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/responseMetaData.vm
  dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/select.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/AddDataSetAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/UpdateDataSetAction.java
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/addDataSet.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/editDataSet.vm
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/javascript/viewDataEntryForm.js
  dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/viewDataEntryForm.vm


--
lp:dhis2
https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk

Your team DHIS 2 developers is subscribed to branch lp:dhis2.
To unsubscribe from this branch go to https://code.launchpad.net/~dhis2-devs-core/dhis2/trunk/+edit-subscription
=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/DataSet.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/DataSet.java	2012-07-12 09:32:15 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/dataset/DataSet.java	2012-09-18 16:20:20 +0000
@@ -120,11 +120,6 @@
     private boolean mobile;
 
     /**
-     * Property indicating whether it should allow to enter data for future periods.
-     */
-    private boolean allowFuturePeriods;
-    
-    /**
      * Indicating custom data entry form.
      */
     private DataEntryForm dataEntryForm;
@@ -143,6 +138,20 @@
      * Property indicating whether aggregation should be skipped.
      */
     private boolean skipAggregation;
+
+    // -------------------------------------------------------------------------
+    // Form properties
+    // -------------------------------------------------------------------------
+
+    /**
+     * Property indicating whether it should allow to enter data for future periods.
+     */
+    private boolean allowFuturePeriods;
+    
+    /**
+     * Property indicating that all fields for a data element must be filled.
+     */
+    private boolean fieldCombinationRequired;
     
     // -------------------------------------------------------------------------
     // Contructors
@@ -496,19 +505,6 @@
     @JsonProperty
     @JsonView( {DetailedView.class, ExportView.class} )
     @JacksonXmlProperty( namespace = Dxf2Namespace.NAMESPACE )
-    public boolean isAllowFuturePeriods()
-    {
-        return allowFuturePeriods;
-    }
-
-    public void setAllowFuturePeriods( boolean allowFuturePeriods )
-    {
-        this.allowFuturePeriods = allowFuturePeriods;
-    }
-
-    @JsonProperty
-    @JsonView( {DetailedView.class, ExportView.class} )
-    @JacksonXmlProperty( namespace = Dxf2Namespace.NAMESPACE )
     public Integer getVersion()
     {
         return version;
@@ -545,6 +541,32 @@
         this.skipAggregation = skipAggregation;
     }
 
+    @JsonProperty
+    @JsonView( {DetailedView.class, ExportView.class} )
+    @JacksonXmlProperty( namespace = Dxf2Namespace.NAMESPACE )
+    public boolean isAllowFuturePeriods()
+    {
+        return allowFuturePeriods;
+    }
+
+    public void setAllowFuturePeriods( boolean allowFuturePeriods )
+    {
+        this.allowFuturePeriods = allowFuturePeriods;
+    }
+
+    @JsonProperty
+    @JsonView( {DetailedView.class, ExportView.class} )
+    @JacksonXmlProperty( namespace = Dxf2Namespace.NAMESPACE )
+    public boolean isFieldCombinationRequired()
+    {
+        return fieldCombinationRequired;
+    }
+
+    public void setFieldCombinationRequired( boolean fieldCombinationRequired )
+    {
+        this.fieldCombinationRequired = fieldCombinationRequired;
+    }
+
     @Override
     public void mergeWith( IdentifiableObject other )
     {

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataentryform/DefaultDataEntryFormService.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataentryform/DefaultDataEntryFormService.java	2012-09-16 14:44:45 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/dataentryform/DefaultDataEntryFormService.java	2012-09-18 09:17:06 +0000
@@ -333,8 +333,7 @@
             {
                 int optionComboId = Integer.parseInt( dynamicInputMather.group( 2 ) );
 
-                DataElementCategoryOptionCombo categoryOptionCombo = categoryService
-                    .getDataElementCategoryOptionCombo( optionComboId );
+                DataElementCategoryOptionCombo categoryOptionCombo = categoryService.getDataElementCategoryOptionCombo( optionComboId );
 
                 if ( categoryOptionCombo == null )
                 {

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java'
--- dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2012-08-29 15:41:35 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/java/org/hisp/dhis/startup/TableAlteror.java	2012-09-18 16:20:20 +0000
@@ -377,6 +377,7 @@
         
         // replace null with false for boolean fields
         
+        executeSql( "update dataset set fieldcombinationrequired = false where fieldcombinationrequired is null" );
         executeSql( "update chart set hidelegend = false where hidelegend is null" );
         executeSql( "update chart set regression = false where regression is null" );
         executeSql( "update chart set targetline = false where targetline is null" );

=== modified file 'dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataset/hibernate/DataSet.hbm.xml'
--- dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataset/hibernate/DataSet.hbm.xml	2012-07-12 09:32:15 +0000
+++ dhis-2/dhis-services/dhis-service-core/src/main/resources/org/hisp/dhis/dataset/hibernate/DataSet.hbm.xml	2012-09-18 16:20:20 +0000
@@ -61,13 +61,17 @@
 
     <property name="mobile" not-null="true" />
 	
-	<property name="allowFuturePeriods" />
-
     <property name="version" />
 
     <property name="expiryDays" />
 	
 	<property name="skipAggregation" />
 
+	<!-- Form properties -->
+
+	<property name="allowFuturePeriods" />
+
+	<property name="fieldCombinationRequired" />
+
   </class>
 </hibernate-mapping>

=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/widgets.css'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/widgets.css	2012-08-01 17:32:01 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/widgets.css	2012-09-18 11:06:27 +0000
@@ -495,17 +495,24 @@
 
 div.paging 
 {
-	width:300px;float:right; margin-right:5em; text-align: center; height:16px; 
+	width:300px;
+	float:right; 
+	margin-right:5em; 
+	text-align: center; 
+	height:16px; 
 }
 
 div.paging span, div.paging a 
 {
-	padding: 0 5px;font-weight: bold; font-size: 11px;
+	font-family: LiberationSansBold, arial;
+	padding: 0 5px;
+	font-size: 11px;
 }
 
 div.paging a
 {
-	text-decoration: none; color: #FF9900;
+	text-decoration: none; 
+	color: #FF9900;
 }
 
 div.paging a:hover
@@ -525,7 +532,11 @@
 
 ul.pageSizeSelection 
 {
-	list-style:none; float:left; width: 300px; margin: 0; padding: 0;
+	list-style:none; 
+	float:left; 
+	width: 300px; 
+	margin: 0; 
+	padding: 0;
 }
 
 ul.pageSizeSelection span 

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/org/hisp/dhis/de/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/org/hisp/dhis/de/i18n_module.properties	2012-09-16 00:11:12 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/resources/org/hisp/dhis/de/i18n_module.properties	2012-09-18 13:32:54 +0000
@@ -102,4 +102,5 @@
 category_option_combo_with_id=Category option combination identifier
 does_not_exist=does not exist
 insert_input_fields_into_the_form=Insert input fields into the form
-select_data_element=Select data element
\ No newline at end of file
+select_data_element=Select data element
+all_values_for_data_element_must_be_filled=This form requires that all fields for a data element must be filled, please correct this before continuing.
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/customForm.vm'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/customForm.vm	2012-09-16 00:11:12 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/customForm.vm	2012-09-18 09:17:06 +0000
@@ -5,7 +5,7 @@
 </div>
 
 <select id="dynselect" class="hidden">
-<option value="">[ $i18n.getString( "select_data_element" ) ]</option>
+<option value="-1">[ $i18n.getString( "select_data_element" ) ]</option>
 #foreach( $element in $dataElementsNotInForm )
 <option value="${element.id}">$encoder.htmlEncode( ${element.displayName} )</option>
 #end

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/entry.js'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/entry.js	2012-09-16 15:21:25 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/entry.js	2012-09-18 09:17:06 +0000
@@ -117,13 +117,13 @@
 {
     var dataElementId = $( '#' + code + '-dynselect option:selected' ).val();
     
-    if ( isDefined( dataElementId ) && dataElementId != '' )
-    {    
-    	saveVal( dataElementId, optionComboId, fieldId );
+    if ( !isDefined( dataElementId ) || dataElementId == -1 )
+    {
+    	log( 'There is no select list in form or no option selected for code: ' + code );
     	return;
     }
     
-    log( 'There is no select list in form or no option selected for code: ' + code );
+    saveVal( dataElementId, optionComboId, fieldId );
 }
 
 function saveVal( dataElementId, optionComboId, fieldId )

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/form.js'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/form.js	2012-09-17 09:06:22 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/javascript/form.js	2012-09-18 16:20:20 +0000
@@ -367,14 +367,27 @@
         $( this ).css( 'width', '100%' );
     } );
     
-    $( '[name="dyninput"]' ).each( function( i ) // Custom only
+    $( '[name="dynselect"]' ).each( function( i )
+    {
+    	var id = $( this ).attr( 'id' );
+    	var code = id.split( '-' )[0];
+    	
+    	$( this ).unbind( 'change' );
+    	
+    	$( this ).change( function()
+    	{
+            dynamicSelectChanged( id, code );
+    	} );
+    } );
+    
+    $( '[name="dyninput"]' ).each( function( i )
     {
     	var id = $( this ).attr( 'id' );
     	var code = id.split( '-' )[0];
         var optionComboId = id.split( '-' )[1];
         
-        $( this ).unbind( 'focus' );
         $( this ).unbind( 'change' );
+        $( this ).unbind( 'keyup' );
 
         $( this ).change( function()
         {
@@ -394,21 +407,6 @@
     clearEntryForm();
 }
 
-function insertDynamicOptions()
-{
-	var optionMarkup = $( '#dynselect' ).html();
-	
-	if ( !isDefined( optionMarkup ) )
-	{
-		return;
-	}
-	
-    $( '[name="dynselect"]' ).each( function( i )
-    {
-    	$( this ).append( optionMarkup );
-    } );
-}
-
 function clearEntryForm()
 {
     $( '#contentDiv' ).html( '' );
@@ -452,6 +450,72 @@
     }
 }
 
+//------------------------------------------------------------------------------
+// Dynamic input
+//------------------------------------------------------------------------------
+
+function insertDynamicOptions()
+{
+	var optionMarkup = $( '#dynselect' ).html();
+	
+	if ( !isDefined( optionMarkup ) )
+	{
+		return; // Custom form only
+	}
+	
+    $( '[name="dynselect"]' ).each( function( i )
+    {
+    	$( this ).append( optionMarkup );
+    } );
+}
+
+function dynamicSelectChanged( id, code )
+{
+	var validSelection = $( '#' + id ).val() != -1;
+	var color = validSelection ? COLOR_WHITE : COLOR_GREY;
+	
+	$( 'input[code="' + code + '"]' ).prop( 'disabled', !validSelection );
+	$( 'input[code="' + code + '"]' ).css( 'background-color', color );
+}
+
+function getDynamicSelectElementId( dataElementId )
+{
+	// Search for element where data element is already selected
+	
+	var id = null;
+	
+	$( '[name="dynselect"]' ).each( function( i )
+	{
+		if ( $( this ).val() == dataElementId )
+		{
+			id = $( this ).attr( 'id' );
+			return false;
+		}
+	} );
+
+	if ( id != null )
+	{
+		return id;
+	}
+	
+	// Search for unselected element
+	
+	$( '[name="dynselect"]' ).each( function( i )
+	{
+		if ( $( this ).val() == -1 )
+		{
+			id = $( this ).attr( 'id' );
+			return false;
+		}
+	} );
+	
+	return id;
+}
+
+//------------------------------------------------------------------------------
+// Section filter
+//------------------------------------------------------------------------------
+
 function enableSectionFilter()
 {
     var $sectionsHeaders = $( '.formSection .cent h3' );
@@ -492,7 +556,7 @@
     }
 }
 
-function filterInSection($this)
+function filterInSection( $this )
 {
     var $tbody = $this.parent().parent().parent();
     var $trTarget = $tbody.find( 'tr:not([colspan])' );
@@ -524,10 +588,14 @@
     refreshZebraStripes( $tbody );
 }
 
+//------------------------------------------------------------------------------
+// Supportive methods
+//------------------------------------------------------------------------------
+
 function refreshZebraStripes( $tbody )
 {
-    $tbody.find( 'tr:not([colspan]):visible:even' ).find( 'td:first-child' ).removeClass( 'reg alt' ).addClass('alt' );
-    $tbody.find( 'tr:not([colspan]):visible:odd' ).find( 'td:first-child' ).removeClass( 'reg alt' ).addClass('reg' );
+    $tbody.find( 'tr:not([colspan]):visible:even' ).find( 'td:first-child' ).removeClass( 'reg alt' ).addClass( 'alt' );
+    $tbody.find( 'tr:not([colspan]):visible:odd' ).find( 'td:first-child' ).removeClass( 'reg alt' ).addClass( 'reg' );
 }
 
 function getDataElementType( dataElementId )
@@ -679,7 +747,7 @@
     var periods = periodTypeFactory.get( periodType ).generatePeriods( currentPeriodOffset );
     periods = periodTypeFactory.reverse( periods );
     
-    if ( allowFuturePeriods == "false" )
+    if ( allowFuturePeriods == false )
     {
     	periods = periodTypeFactory.filterFuturePeriods( periods );
     }
@@ -711,7 +779,7 @@
     var periods = periodTypeFactory.get( periodType ).generatePeriods( currentPeriodOffset );
     periods = periodTypeFactory.reverse( periods );
     
-    if ( allowFuturePeriods == "false" )
+    if ( allowFuturePeriods == false )
     {
     	periods = periodTypeFactory.filterFuturePeriods( periods );
     }
@@ -798,15 +866,23 @@
 
     $( '[name="entryfield"]' ).val( '' );
     $( '[name="entryselect"]' ).val( '' );
+    $( '[name="dyninput"]' ).val( '' );
+    $( '[name="dynselect"]' ).val( '' );
 
     $( '[name="entryfield"]' ).css( 'background-color', COLOR_WHITE );
     $( '[name="entryselect"]' ).css( 'background-color', COLOR_WHITE );
+    $( '[name="dyninput"]' ).css( 'background-color', COLOR_WHITE );
 
     $( '[name="min"]' ).html( '' );
     $( '[name="max"]' ).html( '' );
 
     $( '[name="entryfield"]' ).filter( ':disabled' ).css( 'background-color', COLOR_GREY );
+    
+    // Disable and grey dynamic fields to start with and enable later
 
+    $( '[name="dyninput"]' ).prop( 'disabled', true );    
+    $( '[name="dyninput"]' ).css( 'background-color', COLOR_GREY );
+    
     $.ajax( {
     	url: 'getDataValues.action',
     	data:
@@ -843,10 +919,50 @@
 	        {
 	            var fieldId = '#' + value.id + '-val';
 
-	            if ( $( fieldId ) )
+	            if ( $( fieldId ).length > 0 ) // Insert for fixed input fields
 	            {
 	                $( fieldId ).val( value.val );
 	            }
+	            else // Insert for potential dynamic input fields
+	            {
+	                var dataElementId = value.id.split( '-' )[0];
+	                var optionComboId = value.id.split( '-' )[1];
+	                
+	                var selectElementId = '#' + getDynamicSelectElementId( dataElementId );
+	                
+	                if ( $( selectElementId ).length == 0 )
+	                {
+	                	log( 'Could not find dynamic select element for data element: ' + dataElementId );
+	                	return true;
+	                }
+
+                	var code = $( selectElementId ).attr( 'id' ).split( '-' )[0];
+        			
+        			if ( !isDefined( code ) )
+        			{
+        				log( 'Could not find code on select element: ' + selectElementId );
+        				return true;
+        			}
+
+    				var dynamicInputId = '#' + code + '-' + optionComboId + '-dyninput';
+    				
+        			if ( $( dynamicInputId ).length == 0 )
+    				{
+        				log( 'Could not find find dynamic input element for option combo: ' + optionComboId );
+        				return true;
+    				}
+
+        			// Set data element in select list
+        			    		    
+        			$( selectElementId ).val( dataElementId );
+
+        			// Enable input fields and set value
+        			
+        		    $( 'input[code="' + code + '"]' ).prop( 'disabled', false );    
+        		    $( 'input[code="' + code + '"]' ).css( 'background-color', COLOR_WHITE );
+        		    
+    				$( dynamicInputId ).val( value.val );
+	            }
 
 	            dataValueMap[value.id] = value.val;
 	        } );
@@ -998,6 +1114,11 @@
 {
     var confirmed = confirm( i18n_confirm_complete );
 
+	if ( !validateCompulsoryCombinations() )
+	{
+		return false;
+	}
+	
     if ( confirmed )
     {
         var params = storageManager.getCurrentCompleteDataSetParams();
@@ -1067,9 +1188,9 @@
         	dataType: 'json',
         	success: function(data)
 	        {
-                if( data.status == 2 )
+                if ( data.status == 2 )
                 {
-                    log( 'DataSet is locked' );
+                    log( 'Data set is locked' );
                     setHeaderMessage( i18n_unregister_complete_failed_dataset_is_locked );
                 }
                 else
@@ -1139,6 +1260,11 @@
 
 function validate()
 {
+	if ( !validateCompulsoryCombinations() )
+	{
+		return false;
+	}
+	
     var periodId = $( '#selectedPeriodId' ).val();
     var dataSetId = $( '#selectedDataSetId' ).val();
 
@@ -1146,7 +1272,8 @@
         periodId : periodId,
         dataSetId : dataSetId,
         organisationUnitId : currentOrganisationUnitId
-    }, function( response, status, xhr )
+    }, 
+    function( response, status, xhr )
     {
         if ( status == 'error' )
         {
@@ -1159,6 +1286,53 @@
     } );
 }
 
+function validateCompulsoryCombinations()
+{
+	var validationRequired = dataSets[currentDataSetId].fieldCombinationRequired;
+	
+    if ( validationRequired )
+    {
+        var violations = false;
+		
+        $( '[name="entryfield"]' ).add( '[name="entryselect"]' ).each( function( i )
+        {
+            var id = $( this ).attr( 'id' );
+            var dataElementId = id.split( '-' )[0];		
+            var hasValue = $.trim( $( this ).val() ).length > 0;
+            
+            if ( hasValue )
+            {
+            	$selector = $( '[name="entryfield"][id^="' + dataElementId + '-"]' ).
+            		add( '[name="entryselect"][id^="' + dataElementId + '-"]' );
+				
+                $selector.each( function( i )
+                {
+                    if ( $.trim( $( this ).val() ).length == 0 )
+                    {
+                        violations = true;
+						
+                        $selector.css( 'background-color', COLOR_RED );
+						
+                        return false;
+                    }
+                } );
+            }
+        } );
+		
+        if ( violations )
+        {
+        	$( '#validationDiv' ).html( '<h3>' + i18n_validation_result + '</h3>' +
+                '<p class="bold">' + i18n_all_values_for_data_element_must_be_filled + '</p>' );
+				
+            displayValidationDialog();
+			
+            return false;
+		}
+    }
+	
+	return true;
+}
+
 // -----------------------------------------------------------------------------
 // History
 // -----------------------------------------------------------------------------
@@ -1186,7 +1360,8 @@
         optionComboId : optionComboId,
         periodId : periodId,
         organisationUnitId : currentOrganisationUnitId
-    }, function( response, status, xhr )
+    }, 
+    function( response, status, xhr )
     {
         if ( status == 'error' )
         {
@@ -1359,7 +1534,8 @@
             localStorage[id] = html;
 
             log( 'Successfully stored form: ' + dataSetId );
-        } catch ( e )
+        } 
+        catch ( e )
         {
             log( 'Max local storage quota reached, ignored form: ' + dataSetId );
             return false;

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/responseMetaData.vm'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/responseMetaData.vm	2012-06-25 20:39:32 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/responseMetaData.vm	2012-09-18 16:20:20 +0000
@@ -24,7 +24,8 @@
 #set( $size = $dataSets.size() )
 #foreach( $dataSet in $dataSets )
 "${dataSet.id}":{"name":"$encoder.jsonEncode( ${dataSet.displayName} )","periodType":"$encoder.jsonEncode( ${dataSet.periodType.name} )",
-"allowFuturePeriods":"${dataSet.allowFuturePeriods}","version":"${dataSet.version}","type":"${dataSet.getDataSetType()}","expiryDays":"${dataSet.expiryDays}"
+"version":"${dataSet.version}","type":"${dataSet.getDataSetType()}","expiryDays":"${dataSet.expiryDays}",
+"allowFuturePeriods":${dataSet.allowFuturePeriods},"fieldCombinationRequired":${dataSet.fieldCombinationRequired}
 }#if( $velocityCount < $size ),#end
 #end },
 

=== modified file 'dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/select.vm'
--- dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/select.vm	2012-09-17 09:23:34 +0000
+++ dhis-2/dhis-web/dhis-web-dataentry/src/main/webapp/dhis-web-dataentry/select.vm	2012-09-18 16:20:20 +0000
@@ -37,6 +37,8 @@
 var i18n_register_complete_failed_dataset_is_locked = '$encoder.jsEscape( $i18n.getString( "register_complete_failed_dataset_is_locked" ) , "'")';
 var i18n_unregister_complete_failed_dataset_is_locked = '$encoder.jsEscape( $i18n.getString( "unregister_complete_failed_dataset_is_locked" ) , "'")';
 var i18n_show_all_sections = '$encoder.jsEscape( $i18n.getString( "show_all_sections" ) , "'")';
+var i18n_all_values_for_data_element_must_be_filled = '$encoder.jsEscape( $i18n.getString( "all_values_for_data_element_must_be_filled" ) , "'")';
+var i18n_validation_result = '$encoder.jsEscape( $i18n.getString( "validation_result" ) , "'")';
 </script>
 
 <h3>$i18n.getString( "data_entry" ) #openHelp( "dataEntry" )</h3>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/AddDataSetAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/AddDataSetAction.java	2012-07-18 07:37:01 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/AddDataSetAction.java	2012-09-18 16:20:20 +0000
@@ -114,13 +114,6 @@
         this.description = description;
     }
 
-    private boolean allowFuturePeriods;
-
-    public void setAllowFuturePeriods( boolean allowFuturePeriods )
-    {
-        this.allowFuturePeriods = allowFuturePeriods;
-    }
-
     private int expiryDays;
 
     public void setExpiryDays( int expiryDays )
@@ -142,6 +135,20 @@
         this.frequencySelect = frequencySelect;
     }
 
+    private boolean allowFuturePeriods;
+
+    public void setAllowFuturePeriods( boolean allowFuturePeriods )
+    {
+        this.allowFuturePeriods = allowFuturePeriods;
+    }
+
+    private boolean fieldCombinationRequired;
+    
+    public void setFieldCombinationRequired( boolean fieldCombinationRequired )
+    {
+        this.fieldCombinationRequired = fieldCombinationRequired;
+    }
+
     private Collection<String> dataElementsSelectedList = new HashSet<String>();
 
     public void setDataElementsSelectedList( Collection<String> dataElementsSelectedList )
@@ -191,10 +198,11 @@
         }
 
         dataSet.setDescription( description );
-        dataSet.setAllowFuturePeriods( allowFuturePeriods );
         dataSet.setVersion( 1 );
         dataSet.setMobile( false );
         dataSet.setIndicators( indicators );
+        dataSet.setAllowFuturePeriods( allowFuturePeriods );
+        dataSet.setFieldCombinationRequired( fieldCombinationRequired );
 
         dataSetService.addDataSet( dataSet );
 

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/UpdateDataSetAction.java'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/UpdateDataSetAction.java	2012-07-12 09:32:15 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/java/org/hisp/dhis/dataset/action/UpdateDataSetAction.java	2012-09-18 16:20:20 +0000
@@ -125,13 +125,6 @@
         this.description = description;
     }
 
-    private boolean allowFuturePeriods;
-
-    public void setAllowFuturePeriods( boolean allowFuturePeriods )
-    {
-        this.allowFuturePeriods = allowFuturePeriods;
-    }
-    
     private int expiryDays;
 
     public void setExpiryDays( int expiryDays )
@@ -160,6 +153,20 @@
         this.dataSetId = dataSetId;
     }
 
+    private boolean allowFuturePeriods;
+
+    public void setAllowFuturePeriods( boolean allowFuturePeriods )
+    {
+        this.allowFuturePeriods = allowFuturePeriods;
+    }
+    
+    private boolean fieldCombinationRequired;
+    
+    public void setFieldCombinationRequired( boolean fieldCombinationRequired )
+    {
+        this.fieldCombinationRequired = fieldCombinationRequired;
+    }
+
     private Collection<String> dataElementsSelectedList = new HashSet<String>();
 
     public void setDataElementsSelectedList( Collection<String> dataElementsSelectedList )
@@ -219,11 +226,12 @@
         dataSet.setName( name );
         dataSet.setShortName( shortName );
         dataSet.setDescription( description );
-        dataSet.setAllowFuturePeriods( allowFuturePeriods );
         dataSet.setCode( code );
         dataSet.setPeriodType( periodService.getPeriodTypeByClass( periodType.getClass() ) );
         dataSet.updateDataElements( dataElements );
         dataSet.setIndicators( indicators );
+        dataSet.setAllowFuturePeriods( allowFuturePeriods );
+        dataSet.setFieldCombinationRequired( fieldCombinationRequired );
 
         dataSetService.updateDataSet( dataSet );
 

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties	2012-09-15 11:19:46 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/resources/org/hisp/dhis/dataset/i18n_module.properties	2012-09-18 16:20:20 +0000
@@ -99,4 +99,6 @@
 cat_option_combo_not_exist=Category option combo does not exist
 data_element_not_exist=Data element does not exist
 indicator_not_exist=Indicator does not exist
-cat_combo_not_exist=Category combo does not exist
\ No newline at end of file
+cat_combo_not_exist=Category combo does not exist
+all_fields_for_data_element_required=All fields for data elements required
+form_details=Form details
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/addDataSet.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/addDataSet.vm	2012-08-26 01:18:39 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/addDataSet.vm	2012-09-18 16:20:20 +0000
@@ -76,15 +76,6 @@
         <td><input type="text" id="description" name="description" style="width:20em"/></td>
       </tr>
       <tr>
-      	<td><label>$i18n.getString( "allow_future_periods" )</label></td>
-      	<td>
-      	  <select id="allowFuturePeriods" name="allowFuturePeriods" style="min-width:20em; margin:0;">
-      	  	<option value="false">$i18n.getString( "no" )</option>
-      	  	<option value="true">$i18n.getString( "yes" )</option>
-  	      </select>
-	    </td>
-      </tr>
-      <tr>
         <td><label>$i18n.getString( "expiry_days" )</label></td>
         <td><input type="text" id="expiryDays" name="expiryDays" value="0" style="width:20em"/></td>
       </tr>
@@ -107,10 +98,34 @@
   	      </select>
 	    </td>
       </tr>
-	   
+    </tbody>
+    <thead>
+      <tr>
+        <th colspan="2">$i18n.getString( "form_details" )</th>
+      </tr>
+    </thead>
+    <tbody>
+      <tr>
+      	<td><label>$i18n.getString( "allow_future_periods" )</label></td>
+      	<td>
+      	  <select id="allowFuturePeriods" name="allowFuturePeriods" style="min-width:20em; margin:0;">
+      	  	<option value="false">$i18n.getString( "no" )</option>
+      	  	<option value="true">$i18n.getString( "yes" )</option>
+  	      </select>
+	    </td>
+      </tr>
+      <tr>
+      	<td><label>$i18n.getString( "all_fields_for_data_element_required" )</label></td>
+      	<td>
+      	  <select id="fieldCombinationRequired" name="fieldCombinationRequired" style="min-width:20em; margin:0;">
+      	  	<option value="false">$i18n.getString( "no" )</option>
+      	  	<option value="true">$i18n.getString( "yes" )</option>
+  	      </select>
+	    </td>
+      </tr>	   
     </tbody>
   </table>
-	<br/>&nbsp;
+  <br/>&nbsp;
 
   <table id="dataElementSelectionArea">
     <col style="width: 450px"/>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/editDataSet.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/editDataSet.vm	2012-07-12 09:32:15 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/editDataSet.vm	2012-09-18 16:20:20 +0000
@@ -76,15 +76,6 @@
         <td><input type="text" id="description" name="description" style="width:20em" value="$!encoder.htmlEncode( $dataSet.description )"/></td>
       </tr>
       <tr>
-      	<td><label>$i18n.getString( "allow_future_periods" )</label></td>
-      	<td>
-      	  <select id="allowFuturePeriods" name="allowFuturePeriods" style="min-width:20em; margin:0;">
-      	  	<option value="false">$i18n.getString( "no" )</option>
-      	  	<option value="true"#if( $dataSet.allowFuturePeriods == true ) selected="selected"#end>$i18n.getString( "yes" )</option>
-  	      </select>
-	    </td>
-      </tr>
-      <tr>
         <td><label>$i18n.getString( "expiry_days" )</label></td>
         <td><input type="text" id="expiryDays" name="expiryDays" style="width:20em" value="$!encoder.htmlEncode( $dataSet.expiryDays )"/></td>
       </tr>
@@ -107,6 +98,31 @@
   	      </select>
 	    </td>
       </tr>
+    </tbody>
+    <thead>
+      <tr>
+        <th colspan="2">$i18n.getString( "form_details" )</th>
+      </tr>
+    </thead>
+    <tobd
+      <tr>
+      	<td><label>$i18n.getString( "allow_future_periods" )</label></td>
+      	<td>
+      	  <select id="allowFuturePeriods" name="allowFuturePeriods" style="min-width:20em; margin:0;">
+      	  	<option value="false">$i18n.getString( "no" )</option>
+      	  	<option value="true"#if( $dataSet.allowFuturePeriods == true ) selected="selected"#end>$i18n.getString( "yes" )</option>
+  	      </select>
+	    </td>
+      </tr>
+      <tr>
+      	<td><label>$i18n.getString( "all_fields_for_data_element_required" )</label></td>
+      	<td>
+      	  <select id="fieldCombinationRequired" name="fieldCombinationRequired" style="min-width:20em; margin:0;">
+      	  	<option value="false">$i18n.getString( "no" )</option>
+      	  	<option value="true"#if( $dataSet.fieldCombinationRequired == true ) selected="selected"#end>$i18n.getString( "yes" )</option>
+  	      </select>
+	    </td>
+      </tr>
       <tr><td>&nbsp;</td><td>&nbsp;</td></tr>
     </tbody>
   </table>

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/javascript/viewDataEntryForm.js'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/javascript/viewDataEntryForm.js	2012-09-16 14:44:45 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/javascript/viewDataEntryForm.js	2012-09-18 11:29:01 +0000
@@ -399,7 +399,7 @@
 		var categoryOptionComboName = $option.text();
 		var id = currentDynamicElementCode + "-" + categoryOptionComboId + "-dyninput";
 		
-		var template = '<input id="' + id + '" value="[ ' + categoryOptionComboName + ' ]" title="' + categoryOptionComboName + '" style="width:7em;text-align:center;" />';
+		var template = '<input id="' + id + '" code="' + currentDynamicElementCode + '" value="[ ' + categoryOptionComboName + ' ]" title="' + categoryOptionComboName + '" style="width:7em;text-align:center;" />';
 		oEditor.insertHtml( template );
 	}
 }

=== modified file 'dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/viewDataEntryForm.vm'
--- dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/viewDataEntryForm.vm	2012-09-15 22:53:29 +0000
+++ dhis-2/dhis-web/dhis-web-maintenance/dhis-web-maintenance-dataset/src/main/webapp/dhis-web-maintenance-dataset/viewDataEntryForm.vm	2012-09-18 12:10:07 +0000
@@ -138,6 +138,7 @@
 							#end
 						</select><br>
 						<button type="button" id="startButton">$i18n.getString( "start" )</button>
+						<div style="height:155px"></div>
 					</div>
 					<div id="dynamicElementInsert" style="margin-bottom: 10px; display:none;">
 						<div style="color:#666; margin-top:5px; margin-bottom:5px;">$i18n.getString( "insert_input_fields_into_the_form" )</div>