=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/dataentry-controller.js' --- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/dataentry-controller.js 2015-07-14 19:05:51 +0000 +++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/dataentry-controller.js 2015-07-15 14:30:32 +0000 @@ -928,7 +928,12 @@ }, true); $scope.eventsByStage[key] = sortedEvents; - $scope.eventsByStageAsc[key] = angular.copy(angular.copy(sortedEvents).reverse()); + $scope.eventsByStageAsc[key] = []; + //Reverse the order of events, but keep the objects within the array. + //angular.copy and reverse did not work - this messed up databinding. + angular.forEach(sortedEvents, function(sortedEvent) { + $scope.eventsByStageAsc[key].splice(0,0,sortedEvent); + }); var periods = PeriodService.getPeriods(sortedEvents, stage, $scope.selectedEnrollment).occupiedPeriods; === modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js' --- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js 2015-07-13 07:37:11 +0000 +++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js 2015-07-15 14:30:32 +0000 @@ -834,7 +834,7 @@ if(!valueFound) { if(attribute.attribute === programVariable.trackedEntityAttribute.id) { valueFound = true; - variables = pushVariable(variables, programVariable.name, attribute.value, attribute.type, valueFound, '#' ); + variables = pushVariable(variables, programVariable.name, attribute.value, attribute.type, valueFound, 'A' ); } } }); @@ -868,7 +868,12 @@ variables = pushVariable(variables, programVariable.name, "", "string",false, '#' ); } } + else if (programVariable.trackedEntityAttribute) { + //The variable is an attribute, set correct prefix and a blank value + variables = pushVariable(variables, programVariable.name, "", "string",false, 'A' ); + } else { + //Fallback for calculated(assigned) values: variables = pushVariable(variables, programVariable.name, "", "string",false, '#' ); } } @@ -901,7 +906,7 @@ var replaceVariables = function(expression, variablesHash){ //replaces the variables in an expression with actual variable values. - //Check if the expression contains variables at all(any dollar signs): + //Check if the expression contains program rule variables at all(any dollar signs): if(expression.indexOf('#{') !== -1) { //Find every variable name in the expression; var variablespresent = expression.match(/#{\w+.?\w*}/g); @@ -923,7 +928,7 @@ }); } - //Check if the expression contains program variables + //Check if the expression contains environment variables if(expression.indexOf('V{') !== -1) { //Find every variable name in the expression; var variablespresent = expression.match(/V{\w+.?\w*}/g); @@ -944,6 +949,28 @@ } }); } + + //Check if the expression contains attribute variables: + if(expression.indexOf('A{') !== -1) { + //Find every attribute in the expression; + var variablespresent = expression.match(/A{\w+.?\w*}/g); + //Replace each matched variable: + angular.forEach(variablespresent, function(variablepresent) { + //First strip away any prefix and postfix signs from the variable name: + variablepresent = variablepresent.replace("A{","").replace("}",""); + + if(angular.isDefined(variablesHash[variablepresent]) && + variablesHash[variablepresent].variablePrefix === 'A') { + //Replace all occurrences of the variable name(hence using regex replacement): + expression = expression.replace(new RegExp("A{" + variablepresent + "}", 'g'), + variablesHash[variablepresent].variableValue); + } + else { + $log.warn("Expression " + expression + " conains attribute " + variablepresent + + " - but this attribute is not defined." ); + } + }); + } //Check if the expression contains constants if(expression.indexOf('C{') !== -1) { @@ -974,9 +1001,9 @@ //Called from "runExpression". Only proceed with this logic in case there seems to be dhis function calls: "dhis." is present. if(angular.isDefined(expression) && expression.indexOf("dhis.") !== -1){ var dhisFunctions = [{name:"dhis.daysbetween",parameters:2}, + {name:"dhis.yearsbetween",parameters:2}, {name:"dhis.floor",parameters:1}, {name:"dhis.modulus",parameters:2}, - {name:"dhis.hasValue",parameters:1}, {name:"dhis.concatenate"}]; angular.forEach(dhisFunctions, function(dhisFunction){ @@ -1016,6 +1043,15 @@ //Replace the end evaluation of the dhis function: expression = expression.replace(callToThisFunction, seconddate.diff(firstdate,'days')); } + else if(dhisFunction.name === "dhis.yearsbetween") + { + var firstdate = $filter('trimquotes')(parameters[0]); + var seconddate = $filter('trimquotes')(parameters[1]); + firstdate = moment(firstdate); + seconddate = moment(seconddate); + //Replace the end evaluation of the dhis function: + expression = expression.replace(callToThisFunction, seconddate.diff(firstdate,'years')); + } else if(dhisFunction.name === "dhis.floor") { var floored = Math.floor(parameters[0]); @@ -1030,15 +1066,6 @@ //Replace the end evaluation of the dhis function: expression = expression.replace(callToThisFunction, rest); } - else if(dhisFunction.name === "dhis.hasValue") - { - //"evaluate" hasvalue to true or false: - if(variablesHash[parameters[0]].hasValue){ - expression = expression.replace(callToThisFunction, 'true'); - } else { - expression = expression.replace(callToThisFunction, 'false'); - } - } else if(dhisFunction.name === "dhis.concatenate") { var returnString = "'"; @@ -1202,7 +1229,8 @@ } //Even if the variable is not defined: we assign it: - if(variablesHash[variabletoassign].variableValue !== $rootScope.ruleeffects[executingEvent.event][action.id].data){ + if(variablesHash[variabletoassign] && + variablesHash[variabletoassign].variableValue !== $rootScope.ruleeffects[executingEvent.event][action.id].data){ //If the variable was actually updated, we assume that there is an updated ruleeffect somewhere: updatedEffectsExits = true; //Then we assign the new value: