← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 19368: Merged the tracker capture rules engine and table-dataentry from folkehelsa branch.

 

Merge authors:
  Abyot Asalefew Gizaw (abyot)
  Abyot Asalefew Gizaw abyota@xxxxxxxxx
  Lars Helge Øverland (larshelge)
  Markus Bekken (markus-bekken)
  Øystein Gammersvik ogam@xxxxxxxxxxxx
------------------------------------------------------------
revno: 19368 [merge]
committer: Markus Bekken <markus.bekken@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2015-06-11 20:44:52 +0200
message:
  Merged the tracker capture rules engine and table-dataentry from folkehelsa branch.
added:
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/table-entry-form.html
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/rulebound/
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/rulebound/rulebound-controller.js
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/rulebound/rulebound.html
modified:
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java
  dhis-2/dhis-api/src/main/java/org/hisp/dhis/programrule/ProgramRuleVariableSourceType.java
  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.html
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/default-form.html
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/registration-controller.js
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/i18n/i18n_app.properties
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/i18n/i18n_app_ar.properties
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/index.html
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/services.js
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/tracker-capture.js
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/styles/style.css


--
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/program/Program.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java	2015-03-31 03:17:35 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/program/Program.java	2015-04-08 11:07:34 +0000
@@ -67,6 +67,8 @@
     extends BaseIdentifiableObject
     implements VersionedObject
 {
+    private static final long serialVersionUID = -2807997671779497354L;
+    
     public static final List<String> TYPE_LOOKUP = Arrays.asList( "", "MULTIPLE_EVENTS_WITH_REGISTRATION",
         "SINGLE_EVENT_WITH_REGISTRATION", "SINGLE_EVENT_WITHOUT_REGISTRATION" );
 

=== modified file 'dhis-2/dhis-api/src/main/java/org/hisp/dhis/programrule/ProgramRuleVariableSourceType.java'
--- dhis-2/dhis-api/src/main/java/org/hisp/dhis/programrule/ProgramRuleVariableSourceType.java	2015-03-13 08:24:36 +0000
+++ dhis-2/dhis-api/src/main/java/org/hisp/dhis/programrule/ProgramRuleVariableSourceType.java	2015-05-15 11:08:43 +0000
@@ -42,7 +42,8 @@
     DATAELEMENT_PREVIOUS_EVENT("dataelement_previous_event"), 
     CALCULATED_VALUE("calculated_value"), 
     TEI_ATTRIBUTE("tei_attribute"),
-    CONTEXT_VARIABLE("context_variable");
+    CONTEXT_VARIABLE("context_variable"),
+    NUMBEROFEVENTS_PROGRAMSTAGE("numberofevents_programstage");
     
     private final String value;
 

=== 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-06-10 11:58:22 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/dataentry-controller.js	2015-06-10 13:45:11 +0000
@@ -3,8 +3,9 @@
 trackerCapture.controller('DataEntryController',
         function($rootScope,
                 $scope,
-                $modal,
-                $filter,
+				$modal,
+				$filter,
+                $log,
                 $timeout,
                 Paginator,
                 DateUtils,
@@ -17,8 +18,10 @@
                 OptionSetService,
                 ModalService,
                 CurrentSelection,
-                CustomFormService,
-                PeriodService) {
+				TrackerRulesExecutionService,
+				CustomFormService,
+				PeriodService) {
+    
     //Data entry form
     $scope.outerForm = {};
     $scope.displayCustomForm = false;
@@ -27,7 +30,11 @@
     $scope.eventPeriods = [];
     $scope.currentPeriod = [];
     $scope.filterEvents = true;
+    $scope.showEventsAsTables = false;
+    //variable is set while looping through the program stages later.
+    $scope.stagesCanBeShownAsTable = false;
     $scope.showHelpText = {};
+	$scope.hiddenFields = {};
     
     var userProfile = SessionStorageService.get('USER_PROFILE');
     var storedBy = userProfile && userProfile.username ? userProfile.username : '';
@@ -46,21 +53,56 @@
                             {color: 'alert-danger', description: 'overdue'},
                             {color: 'alert-default', description: 'skipped'}
                          ];
-    $scope.showEventColors = false;    
-      
+    $scope.showEventColors = false;
+    
+    //listen for rule effect changes
+    $scope.$on('ruleeffectsupdated', function(event, args) {
+        angular.forEach($rootScope.ruleeffects, function(effect) {
+            if( effect.dataElement ) {
+                //in the data entry controller we only care about the "hidefield" actions
+                if(effect.action === "HIDEFIELD") {
+                    if(effect.dataElement) {
+                        //Hide the field if the hiding is in effect, and there is no data value in the field.
+                        var hide = effect.ineffect && !$scope.currentEvent[effect.dataElement.id];
+                        $scope.hiddenFields[effect.dataElement.id] = hide;
+                    }
+                    else {
+                        $log.warn("ProgramRuleAction " + effect.id + " is of type HIDEFIELD, bot does not have a dataelement defined");
+                    }
+                }
+            }
+        });
+    });
+    //check if field is hidden
+    $scope.isHidden = function(id) {
+        //In case the field contains a value, we cant hide it. 
+        //If we hid a field with a value, it would falsely seem the user was aware that the value was entered in the UI.
+        if($scope.currentEvent[id])
+        {
+           return false; 
+        }
+        else
+        {
+            return $scope.hiddenFields[id];
+        }
+    }; 
+    
+    
     //listen for the selected items
     $scope.$on('dashboardWidgets', function() {
         $scope.showDataEntryDiv = false;
         $scope.showEventCreationDiv = false;
         $scope.currentEvent = null;
         $scope.currentStage = null;
+        $scope.currentStageEvents = null;
         $scope.totalEvents = 0;
             
         $scope.allowEventCreation = false;
         $scope.repeatableStages = [];        
         $scope.eventsByStage = [];
-        $scope.programStages = [];        
-        $scope.prStDes = [];
+        $scope.programStages = [];
+        $rootScope.ruleeffects = {};
+		$scope.prStDes = [];
         
         var selections = CurrentSelection.get();          
         $scope.selectedOrgUnit = SessionStorageService.get('SELECTED_OU');
@@ -84,6 +126,11 @@
                     
                     $scope.stagesById[stage.id] = stage;
                     $scope.eventsByStage[stage.id] = [];
+                    
+                    //If one of the stages has less than 7 data elements, allow sorting as table:
+                    if(stage.programStageDataElements.length < 7) {
+                        $scope.stagesCanBeShownAsTable = true;
+                    }
                 });
                 
                 $scope.programStages = orderByFilter($scope.programStages, '-sortOrder').reverse();
@@ -147,8 +194,32 @@
         $scope.schedulingEnabled = !$scope.schedulingEnabled;
     };
     
+    $scope.stageCanBeShownAsTable = function(stage) {
+        if(stage.programStageDataElements && stage.programStageDataElements.length < 7) {
+            return true;
+        }
+        return false;
+    };
+    
+    $scope.toggleEventsTableDisplay = function() {
+        $scope.showEventsAsTables = !$scope.showEventsAsTables;
+        angular.forEach($scope.programStages, function(stage){
+            if(stage.programStageDataElements.length < 7) {
+                stage.displayEventsInTable = $scope.showEventsAsTables;
+                if($scope.currentStage === stage) {
+                    $scope.getDataEntryForm();
+                }
+            }
+        });
+    };
+    
     $scope.stageNeedsEvent = function(stage){  
-      
+        
+        //In case the event is a table, we sould always allow adding more events(rows)
+        if(stage.displayEventsInTable) {
+            return true;
+        }
+        
         if($scope.eventsByStage[stage.id].length < 1){                
             return true;
         }
@@ -180,6 +251,10 @@
                 },
                 eventPeriods: function(){
                     return $scope.eventPeriods;
+                },
+                autoCreate: function() {
+                    //In case the programstage is a table, autocreate
+                    return stage.displayEventsInTable;
                 }
             }
         });
@@ -200,9 +275,14 @@
                     newEvent.coordinate = {};
                 }
                 
+                //Have to make sure the event is preprocessed - this does not happen unless "Dashboardwidgets" is invoked.
+                newEvent = EventUtils.processEvent(newEvent, stage, $scope.optionSets, $scope.prStDes);
+                
+                
                 $scope.eventsByStage[newEvent.programStage].push(newEvent);
                 $scope.currentEvent = newEvent;
                 sortEventsByStage('ADD');
+
                 $scope.currentEvent = null;
                 $scope.showDataEntry(newEvent, false);
             }            
@@ -253,18 +333,31 @@
     $scope.getDataEntryForm = function(){
         
         $scope.currentStage = $scope.stagesById[$scope.currentEvent.programStage];
+        $scope.currentStageEvents = $scope.eventsByStage[$scope.currentEvent.programStage];
         
         angular.forEach($scope.currentStage.programStageSections, function(section){
             section.open = true;
         });
 
         $scope.customForm = CustomFormService.getForProgramStage($scope.currentStage, $scope.prStDes);
-        $scope.displayCustomForm = $scope.customForm ? true:false;        
+        $scope.displayCustomForm = "default";
+        if($scope.customForm){
+            $scope.displayCustomForm = "custom";
+        }
+        else if($scope.currentStage.displayEventsInTable) {
+            $scope.displayCustomForm = "table";
+        }
+        
+        $scope.currentEventOriginal = angular.copy($scope.currentEvent);
 
-        $scope.currentEventOriginal = angular.copy($scope.currentEvent); 
+        $scope.currentStageEventsOriginal = angular.copy($scope.currentStageEvents);
         
         var period = {event: $scope.currentEvent.event, stage: $scope.currentEvent.programStage, name: $scope.currentEvent.sortingDate};
         $scope.currentPeriod[$scope.currentEvent.programStage] = period;
+
+        //Execute rules for the first time, to make the initial page appear correctly.
+        //Subsequent calls will be made from the "saveDataValue" function.
+        TrackerRulesExecutionService.executeRules($scope);
     };
     
     function updateCurrentEventInStage(){
@@ -280,7 +373,14 @@
         }
         
     };
-    $scope.saveDatavalue = function(prStDe, field){
+
+    $scope.saveDatavalue = function(prStDe,field){
+        $scope.saveDatavalueForEvent(prStDe,field,$scope.currentEvent);
+    };
+
+    $scope.saveDatavalueForEvent = function(prStDe,field,eventToSave,object){
+        //Blank out the input-saved class on the last saved due date:
+        $scope.eventDateSaved = false;
         
         //console.log('the field:  ', field);
         $scope.currentElement = {};
@@ -294,12 +394,17 @@
             return false;
         }
         
-        //input is valid        
-        var value = $scope.currentEvent[prStDe.dataElement.id];
-        //var value = inputField.$viewValue;
-        
-        if($scope.currentEventOriginal[prStDe.dataElement.id] !== value){
-            
+        //input is valid
+        var value = eventToSave[prStDe.dataElement.id];
+        
+        var oldValue = null;
+        angular.forEach($scope.currentStageEventsOriginal, function (eventOriginal) {
+            if(eventOriginal.event === eventToSave.event) {
+               oldValue = eventOriginal[prStDe.dataElement.id];
+            }
+        });
+        
+        if(oldValue !== value){
             if(value){
                 if(prStDe.dataElement.type === 'date'){                    
                     value = DateUtils.formatFromUserToApi(value);
@@ -311,19 +416,21 @@
                 }
             }
 
-            $scope.currentElement = {id: prStDe.dataElement.id, saved: false};
-
-            var ev = {  event: $scope.currentEvent.event,
-                        orgUnit: $scope.currentEvent.orgUnit,
-                        program: $scope.currentEvent.program,
-                        programStage: $scope.currentEvent.programStage,
-                        status: $scope.currentEvent.status,
-                        trackedEntityInstance: $scope.currentEvent.trackedEntityInstance,
+            $scope.updateSuccess = false;
+
+            $scope.currentElement = {id: prStDe.dataElement.id, event:eventToSave.event, saved: false};
+
+            var ev = {  event: eventToSave.event,
+                        orgUnit: eventToSave.orgUnit,
+                        program: eventToSave.program,
+                        programStage: eventToSave.programStage,
+                        status: eventToSave.status,
+                        trackedEntityInstance: eventToSave.trackedEntityInstance,
                         dataValues: [
                                         {
                                             dataElement: prStDe.dataElement.id, 
                                             value: value, 
-                                            providedElsewhere: $scope.currentEvent.providedElsewhere[prStDe.dataElement.id] ? true : false
+                                            providedElsewhere: eventToSave.providedElsewhere[prStDe.dataElement.id] ? true : false
                                         }
                                     ]
                      };
@@ -332,7 +439,12 @@
                 sortEventsByStage('UPDATE');
                 
                 $scope.currentElement.saved = true;
-                $scope.currentEventOriginal = angular.copy($scope.currentEvent);                
+                
+                $scope.currentEventOriginal = angular.copy($scope.currentEvent);
+                
+                $scope.currentStageEventsOriginal = angular.copy($scope.currentStageEvents);
+
+				TrackerRulesExecutionService.executeRules($scope);
             });
             
         }
@@ -365,44 +477,46 @@
                 sortEventsByStage('UPDATE');
                 
                 $scope.updateSuccess = true;
-            });            
-        }        
-    };
-    
-    $scope.saveEventDate = function(){
-        
+            });
+        }
+    };
+    
+    $scope.saveEventDate = function () {
+        $scope.saveEventDateForEvent($scope.currentEvent);
+    };
+    
+    $scope.saveEventDateForEvent = function(eventToSave){
         $scope.eventDateSaved = false;
-        if($scope.currentEvent.eventDate === ''){            
-            $scope.invalidDate = true;
+        if(eventToSave.eventDate === ''){            
+            $scope.invalidDate = eventToSave.event;
             return false;
         }
         
-        var rawDate = angular.copy($scope.currentEvent.eventDate);
-        var convertedDate = DateUtils.format($scope.currentEvent.eventDate);
+        var rawDate = angular.copy(eventToSave.eventDate);
+        var convertedDate = DateUtils.format(eventToSave.eventDate);
         
         if(rawDate !== convertedDate){
             $scope.invalidDate = true;
             return false;
         }
         
-        var e = {event: $scope.currentEvent.event,
-             enrollment: $scope.currentEvent.enrollment,
-             dueDate: DateUtils.formatFromUserToApi($scope.currentEvent.dueDate),
-             status: $scope.currentEvent.status === 'SCHEDULE' ? 'ACTIVE' : $scope.currentEvent.status,
-             program: $scope.currentEvent.program,
-             programStage: $scope.currentEvent.programStage,
-             orgUnit: $scope.currentEvent.dataValues && $scope.currentEvent.dataValues.length > 0 ? $scope.currentEvent.orgUnit : $scope.selectedOrgUnit.id,
-             eventDate: DateUtils.formatFromUserToApi($scope.currentEvent.eventDate),
-             trackedEntityInstance: $scope.currentEvent.trackedEntityInstance
+        var e = {event: eventToSave.event,
+             enrollment: eventToSave.enrollment,
+             dueDate: DateUtils.formatFromUserToApi(eventToSave.dueDate),
+             status: eventToSave.status === 'SCHEDULE' ? 'ACTIVE' : eventToSave.status,
+             program: eventToSave.program,
+             programStage: eventToSave.programStage,
+             orgUnit: eventToSave.dataValues && eventToSave.length > 0 ? eventToSave.orgUnit : $scope.selectedOrgUnit.id,
+             eventDate: DateUtils.formatFromUserToApi(eventToSave.eventDate),
+             trackedEntityInstance: eventToSave.trackedEntityInstance
             };
 
         DHIS2EventFactory.updateForEventDate(e).then(function(data){
-            $scope.currentEvent.sortingDate = $scope.currentEvent.eventDate;
+            eventToSave.sortingDate = eventToSave.eventDate;
             $scope.invalidDate = false;
-            $scope.eventDateSaved = true;
-            $scope.currentEvent.statusColor = EventUtils.getEventStatusColor($scope.currentEvent);
-            $scope.currentEvent.visited = true;
-            
+            $scope.eventDateSaved = eventToSave.event;
+            eventToSave.statusColor = EventUtils.getEventStatusColor(eventToSave);
+            sortEventsByStage();
             updateCurrentEventInStage();
             sortEventsByStage('UPDATE');
         });
@@ -485,6 +599,8 @@
         
         DHIS2EventFactory.update(dhis2Event).then(function(response){            
             $scope.currentEventOriginal = angular.copy($scope.currentEvent);
+            $scope.currentStageEventsOriginal = angular.copy($scope.currentStageEvents);
+
             if(type === 'LAT' || type === 'LATLNG' ){
                 $scope.latitudeSaved = true;
             }
@@ -529,15 +645,29 @@
          $scope.note = '';           
     };
     
-    $scope.getInputNotifcationClass = function(id, custom){
-        if($scope.currentElement.id){
-            if($scope.currentElement.saved && ($scope.currentElement.id === id)){
+    $scope.getInputDueDateClass = function(event) {
+        if(event.event === $scope.eventDateSaved) {
+            return 'input-success';
+        }
+        else {
+            return '';
+        }
+            
+    };
+    
+    $scope.getInputNotifcationClass = function(id, custom, event){
+        if(!event) {
+            event = $scope.currentEvent;
+        }
+        if($scope.currentElement.id && $scope.currentElement.event){
+            if($scope.currentElement.saved && ($scope.currentElement.id === id && $scope.currentElement.event === event.event)){
+                
                 if(custom){
                     return 'input-success';
                 }
                 return 'form-control input-success';
             }            
-            if(!$scope.currentElement.saved && ($scope.currentElement.id === id)){
+            if(!$scope.currentElement.saved && ($scope.currentElement.id === id && $scope.currentElement.event === event.event)){
                 if(custom){
                     return 'input-error';
                 }
@@ -859,7 +989,8 @@
             DialogService,
             stagesById,
             dummyEvent,
-            eventPeriods){
+            eventPeriods,
+            autoCreate){
     $scope.stagesById = stagesById;
     $scope.programStageId = dummyEvent.programStage;
     $scope.eventPeriods = eventPeriods;
@@ -944,6 +1075,12 @@
             }
         });
         
+        
+    };
+    
+    //If the caller wants to create right away, go ahead and save.
+    if(autoCreate) {
+        $scope.save();
     };
     
     $scope.cancel = function(){

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/dataentry.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/dataentry.html	2015-06-02 12:25:03 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/dataentry.html	2015-06-10 11:55:41 +0000
@@ -3,6 +3,8 @@
         {{dataentryWidget.title| translate}}        
 
         <span class="pull-right widget-link">
+            
+            <a href ng-click="toggleEventsTableDisplay()" title="{{showEventsAsTables ? 'toggle_table_view_off' : 'toggle_table_view_on'| translate}}" ng-show="stagesCanBeShownAsTable"><span ng-if="!showEventsAsTables"><i class="fa fa-bars vertical-center"></i></span><span ng-if="showEventsAsTables"><i class="fa fa-square vertical-center"></i></span></a>
             <a href ng-click="filterEvents = !filterEvents" title="{{filterEvents ? 'list_events' : 'filter_events'| translate}}" ng-show="eventFilteringRequired"><span ng-if="!filterEvents"><i class="fa fa-filter vertical-center"></i></span><span ng-if="filterEvents"><i class="fa fa-list vertical-center"></i></span></a>
             <a href ng-click="toggleLegend()" title="{{'event_color_legend'| translate}}" class="small-horizonal-spacing"><i class="fa fa-info-circle vertical-center"></i></a>
             <a class="small-horizonal-spacing" href ng-click="expandCollapse(dataentryWidget)">
@@ -34,6 +36,7 @@
                             
                             <!-- event add/filter icon begins -->
                             <span class='pull-right'>
+
                                 <span ng-if="stageNeedsEvent(stage)">
                                     <a href title="{{'create_new_event'| translate}}" ng-click="showCreateEvent(stage)" style="vertical-align:middle"><i class="fa fa-plus"></i></a>
                                 </span>
@@ -76,7 +79,8 @@
             <div ng-if="currentEvent">
 
                 <!-- event dates/scheduling begin -->
-                <div class="row" ng-if="!currentStage.periodType">
+                <div class="row" ng-if="(displayCustomForm !== 'table') && !currentStage.periodType">
+
                     <div class="col-md-6">
                         {{currentEvent.reportDateDescription}}
                         <input type="text"
@@ -145,9 +149,12 @@
 
                 <!-- data entry form begins -->
                 <div ng-if="currentEvent.eventDate">                            
-                    <div class="clear vertical-spacing" ng-if="displayCustomForm" ng-include="'../dhis-web-commons/angular-forms/custom-form.html'"></div>  
-                    <div class="clear vertical-spacing" ng-if="!displayCustomForm" ng-include="'components/dataentry/default-form.html'"></div>
-                </div>            
+                    <div class="clear vertical-spacing" ng-if="displayCustomForm === 'custom'" ng-include="'../dhis-web-commons/customform/custom-form.html'"></div>  
+                    <div class="clear vertical-spacing" ng-if="displayCustomForm === 'default'" ng-include="'components/dataentry/default-form.html'"></div>
+                </div>    
+                <!-- the table form is insensitive to the event date being present. In this situation the eventdate is set inside the table form -->
+                <div class="clear vertical-spacing" ng-if="displayCustomForm === 'table'" ng-include="'components/dataentry/table-entry-form.html'"></div>
+
                 <!-- data entry form ends -->
 
                 <!-- data entry/event buttons begins -->

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/default-form.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/default-form.html	2015-06-03 12:18:22 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/default-form.html	2015-06-10 11:55:41 +0000
@@ -14,7 +14,7 @@
                 </th>
             </tr>
         </thead>
-        <tr class="col-md-12" ng-repeat="prStDe in currentStage.programStageDataElements">
+        <tr class="col-md-12" ng-repeat="prStDe in currentStage.programStageDataElements" ng-if="!isHidden(prStDe.dataElement.id)">
             <td class="col-md-5">
                 {{prStDe.dataElement.formName ? prStDe.dataElement.formName : prStDe.dataElement.name}}
                 <a ng-if="prStDes[prStDe.dataElement.id].dataElement.description" Title="{{prStDes[prStDe.dataElement.id].dataElement.description}}" ng-init="showHelpText[prStDe.dataElement.id] = false;" ng-click="showHelpText[prStDe.dataElement.id] = !showHelpText[prStDe.dataElement.id]">
@@ -158,7 +158,8 @@
     
     <div ng-if='currentEvent && currentStage.programStageSections.length'>
         <accordion close-others='false'>
-            <accordion-group heading="{{section.name}}" is-open="section.open" ng-repeat='section in currentStage.programStageSections'>
+			<!-- The inline style was needed to override overflow:hidden in the css. Can possibly be replaced with a CSS update. --> 
+            <accordion-group heading="{{section.name}}" is-open="section.open" ng-repeat='section in currentStage.programStageSections' style="overflow:visible">
                 <table class="dhis2-list-table-striped">                    
                     <thead>                        
                         <tr class="col-md-12">
@@ -174,7 +175,7 @@
                         </tr>                        
                     </thead>
                     <tbody id="list">       
-                        <tr class="col-md-12" ng-repeat="de in section.programStageDataElements">
+                        <tr class="col-md-12" ng-repeat="de in section.programStageDataElements" ng-if="!isHidden(de.dataElement.id)">
                             <td class="col-md-5">
                                 {{prStDes[de.dataElement.id].dataElement.formName ? prStDes[de.dataElement.id].dataElement.formName : prStDes[de.dataElement.id].dataElement.name}}
                                 <a ng-if="prStDes[de.dataElement.id].dataElement.description" Title="{{prStDes[de.dataElement.id].dataElement.description}}" ng-init="showHelpText[de.dataElement.id] = false;" ng-click="showHelpText[de.dataElement.id] = !showHelpText[de.dataElement.id]">

=== added file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/table-entry-form.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/table-entry-form.html	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/dataentry/table-entry-form.html	2015-06-11 18:44:52 +0000
@@ -0,0 +1,153 @@
+<form name="tableEntryOuterForm" novalidate>          
+    <table class="table-borderless table-striped" ng-if='currentEvent'>
+        <thead>
+            <tr class="col-md-12">
+                <th class="col-md-2" >
+                    {{currentEvent.reportDateDescription}}
+                </th>
+                <th class="col-md-2" ng-repeat="prStDe in currentStage.programStageDataElements" ng-if="!isHidden(prStDe.dataElement.id)">
+                    {{prStDe.dataElement.formName ? prStDe.dataElement.formName : prStDe.dataElement.name}}
+                </th>
+            </tr>
+        </thead>
+        <tr class="col-md-12" ng-repeat="eventRow in currentStageEvents" ng-if="currentStageEvents">
+            <td>
+                <input type="text"
+                       placeholder="{{dhis2CalendarFormat.keyDateFormat}}"
+                       class="form-control" 
+                       ng-class="getInputDueDateClass(eventRow)"
+                       d2-date 
+                       ng-model="eventRow.eventDate"
+                       ng-disabled="eventRow.status === 'SKIPPED' || eventRow.enrollmentStatus !== 'ACTIVE' || eventRow.editingNotAllowed"    
+                       ng-required="true"
+                       blur-or-change="saveEventDateForEvent(eventRow)"/>
+                <span ng-if="invalidDate === eventRow.event" class="error">{{'date_required'| translate}}</span>
+            </td>
+            <td class="col-md-2" ng-repeat="prStDe in currentStage.programStageDataElements" ng-if="!isHidden(prStDe.dataElement.id)">
+                <ng-form name="innerform">
+                    <div ng-switch="prStDe.dataElement.type">
+                        <div ng-switch-when="int">
+                            <input type="number"
+                                   number-type={{prStDe.dataElement.numberType}}
+                                   ng-class='getInputNotifcationClass(prStDe.dataElement.id,false,eventRow)'
+                                   ng-model="eventRow[prStDe.dataElement.id]" 
+                                   d2-number-validator
+                                   ng-required={{prStDe.compulsory}}
+                                   ng-disabled="selectedEnrollment.status !== 'ACTIVE' || eventRow.editingNotAllowed" 
+                                   ng-blur="saveDatavalueForEvent(prStDe,innerform.foo,eventRow)" 
+                                   name="foo"/>
+                            <span ng-show="dataEntryOuterForm.submitted && innerform.foo.$invalid" class="error">{{'number_required'| translate}}</span>
+                        </div>
+                        <div ng-switch-when="string">
+                            <div ng-if="prStDe.dataElement.optionSet">
+                                <div ng-if="!selectedProgram.dataEntryMethod || optionSets[prStDe.dataElement.optionSet.id].options.length >= 7">
+                                    <input type="text"
+                                        ng-class='getInputNotifcationClass(prStDe.dataElement.id,false,eventRow)'
+                                        ng-model="eventRow[prStDe.dataElement.id]"
+                                        ng-required={{prStDe.compulsory}} 
+                                        ng-disabled="selectedEnrollment.status !== 'ACTIVE' || eventRow.editingNotAllowed"
+                                        typeahead="option.name as option.name for option in optionSets[prStDe.dataElement.optionSet.id].options | filter:$viewValue | limitTo:20" 
+                                        typeahead-open-on-focus
+                                        typeahead-editable="false"
+                                        ng-blur="saveDatavalueForEvent(prStDe,innerform.foo,eventRow)"
+                                        name="foo"/>
+                                    <span ng-show="dataEntryOuterForm.submitted && innerform.foo.$invalid || !eventRow[prStDe.dataElement.id] && currentElement.id === prStDe.dataElement.id" class="error">{{'invalid'| translate}}</span>
+                                </div>
+                                <div ng-if="selectedProgram.dataEntryMethod && optionSets[prStDe.dataElement.optionSet.id].options.length < 7">
+                                    <label>
+                                        <input type="radio"
+                                            ng-class='getInputNotifcationClass(prStDe.dataElement.id,true,eventRow)'
+                                            name={{eventRow[prStDe.dataElement.id]}}
+                                            ng-required={{prStDe.compulsory}} 
+                                            ng-disabled="selectedEnrollment.status !== 'ACTIVE' || eventRow.editingNotAllowed" 
+                                            ng-model="eventRow[prStDe.dataElement.id]"
+                                            ng-change="saveDatavalueForEvent(prStDe,null,eventRow)" 
+                                            value=""> {{'no_value' | translate}}<br>                                       
+                                    </label><br>
+                                    <span ng-repeat="option in optionSets[prStDe.dataElement.optionSet.id].options">
+                                        <label>
+                                            <input type="radio"
+                                                ng-class='getInputNotifcationClass(prStDe.dataElement.id,true,eventRow)'
+                                                name={{eventRow[prStDe.dataElement.id]}}
+                                                ng-required={{prStDe.compulsory}} 
+                                                ng-disabled="selectedEnrollment.status !== 'ACTIVE' || eventRow.editingNotAllowed" 
+                                                ng-model="eventRow[prStDe.dataElement.id]"
+                                                ng-change="saveDatavalueForEvent(prStDe,null,eventRow)" 
+                                                value={{option.name}}> {{option.name}}
+                                        </label><br>
+                                    </span>
+                                </div>                                    
+                            </div>
+                            <div ng-if="!prStDe.dataElement.optionSet">
+                                <input type="text"
+                                    ng-class='getInputNotifcationClass(prStDe.dataElement.id,false,eventRow)'
+                                    ng-model="eventRow[prStDe.dataElement.id]" 
+                                    ng-required={{prStDe.compulsory}} 
+                                    ng-disabled="selectedEnrollment.status !== 'ACTIVE' || eventRow.editingNotAllowed" 
+                                    ng-blur="saveDatavalueForEvent(prStDe,innerform.foo,eventRow)" 
+                                    name="foo"/>
+                            </div>
+                        </div>
+                        <div ng-switch-when="bool">
+                            <select ng-class='getInputNotifcationClass(prStDe.dataElement.id,false,eventRow)'
+                                    ng-model="eventRow[prStDe.dataElement.id]" 
+                                    ng-required={{prStDe.compulsory}} 
+                                    ng-disabled="selectedEnrollment.status !== 'ACTIVE' || eventRow.editingNotAllowed" 
+                                    ng-change="saveDatavalueForEvent(prStDe,innerform.foo,eventRow)" 
+                                    name="foo">
+                                <option value="">{{'please_select'| translate}}</option>                        
+                                <option value="false">{{'no'| translate}}</option>
+                                <option value="true">{{'yes'| translate}}</option>
+                            </select>
+                        </div>
+                        <div ng-switch-when="date">
+                            <input type="text" 
+                                   placeholder="{{dhis2CalendarFormat.keyDateFormat}}" 
+                                   d2-date
+                                   max-date="prStDe.allowFutureDate ? '' : 0"
+                                   ng-class='getInputNotifcationClass(prStDe.dataElement.id,false,eventRow)'
+                                   ng-model="eventRow[prStDe.dataElement.id]"
+                                   ng-required={{prStDe.compulsory}}  
+                                   ng-disabled="selectedEnrollment.status !== 'ACTIVE' || eventRow.editingNotAllowed" 
+                                   blur-or-change="saveDatavalueForEvent(prStDe,innerform.foo,eventRow)"
+                                   name="foo"/>
+                        </div>
+                        <div ng-switch-when="trueOnly">
+                            <input type="checkbox"                         
+                                   ng-class='getInputNotifcationClass(prStDe.dataElement.id,false,eventRow)'
+                                   ng-model="eventRow[prStDe.dataElement.id]"                                                               
+                                   ng-required={{prStDe.compulsory}} 
+                                   ng-disabled="selectedEnrollment.status !== 'ACTIVE' || eventRow.editingNotAllowed" 
+                                   ng-change="saveDatavalueForEvent(prStDe,innerform.foo,eventRow)" 
+                                   name="foo"/>
+                        </div>
+                    </div>
+                    <div class="alert alert-warning alert-dismissible" role="alert" ng-if="warningMessages[prStDe.dataElement.id]">
+                        <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                        {{warningMessages[prStDe.dataElement.id]}}
+                    </div>
+                    <div class="alert alert-danger alert-dismissible" role="alert" ng-if="errorMessages[prStDe.dataElement.id]">
+                        <button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>
+                        {{errorMessages[prStDe.dataElement.id]}}
+                    </div>
+                </ng-form>
+                <span ng-show="dataEntryOuterForm.submitted && innerform.foo.$invalid" class="error">{{'required'| translate}}</span>
+            </td>
+            <!--<td class="col-md-2" ng-if="allowProvidedElsewhereExists">                
+                <div class="align-center" ng-show="prStDe.allowProvidedElsewhere">
+                    <input type="checkbox" 
+                           ng-model="eventRow.providedElsewhere[prStDe.dataElement.id]" 
+                           ng-disabled="selectedEnrollment.status !== 'ACTIVE' || eventRow.editingNotAllowed" 
+                           ng-change="saveDatavalueLocation(prStDe)"/>                
+                </div>
+            </td>-->
+        </tr>
+    </table>
+    <div class="col-md-12"style="text-align: right"> 
+        <button type="button" 
+                class="btn btn-default"
+                ng-click="showCreateEvent(currentStage)">
+            {{'add'| translate}}
+        </button>
+    </div>
+</form>

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/registration-controller.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/registration-controller.js	2015-06-02 12:25:03 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/registration-controller.js	2015-06-10 11:55:41 +0000
@@ -51,7 +51,7 @@
     }
     
     $scope.selectedOrgUnit = SessionStorageService.get('SELECTED_OU');
-    $scope.selectedEnrollment = {dateOfEnrollment: '', dateOfIncident: ''};   
+    $scope.selectedEnrollment = {dateOfEnrollment: $scope.today, dateOfIncident: $scope.today};   
             
     $scope.trackedEntities = {available: []};
     TEService.getAll().then(function(entities){

=== added directory 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/rulebound'
=== added file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/rulebound/rulebound-controller.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/rulebound/rulebound-controller.js	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/rulebound/rulebound-controller.js	2015-06-02 05:55:14 +0000
@@ -0,0 +1,58 @@
+trackerCapture.controller('RuleBoundController',
+        function(
+                $rootScope,
+                $scope,
+                $log) {
+
+    
+    $scope.widget = $scope.$parent.$parent.biggerWidget ? $scope.$parent.$parent.biggerWidget
+    : $scope.$parent.$parent.smallerWidget ? $scope.$parent.$parent.smallerWidget : null;
+    $scope.widgetTitle = $scope.widget.title;
+    $scope.widgetCode = $scope.widget.code;
+    
+    
+    $scope.displayTextEffects = {};
+    $scope.displayKeyDataEffects = {};
+    
+    //listen for updated rule effects
+    $scope.$on('ruleeffectsupdated', function(event, args) {
+        var textInEffect = false;
+        var keyDataInEffect = false;
+        
+        //Bind non-bound rule effects, if any.
+        angular.forEach($rootScope.ruleeffects, function(effect) {
+            if(effect.location == $scope.widgetCode){
+                //This effect is affecting the local widget
+                
+                if(effect.action == "DISPLAYTEXT") {
+                    //this action is display text. Make sure the displaytext is
+                    //added to the local list of displayed texts
+                    if(!angular.isObject($scope.displayTextEffects[effect.id])){
+                        $scope.displayTextEffects[effect.id] = effect;
+                    }
+                    if(effect.ineffect)
+                    {
+                        textInEffect = true;
+                    }
+                }
+                else if(effect.action == "DISPLAYKEYVALUEPAIR") {
+                    //this action is display text. Make sure the displaytext is
+                    //added to the local list of displayed texts
+                    if(!angular.isObject($scope.displayTextEffects[effect.id])){
+                        $scope.displayKeyDataEffects[effect.id] = effect;
+                    }
+                    if(effect.ineffect)
+                    {
+                        keyDataInEffect = true;
+                    }
+                } else {
+                    $log.warn("action: '" + effect.action + "' not supported by rulebound-controller.js")
+                }
+            }
+        });
+        
+        $scope.showKeyDataSection = keyDataInEffect;
+        $scope.showTextSection = textInEffect;
+        
+    });     
+});
\ No newline at end of file

=== added file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/rulebound/rulebound.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/rulebound/rulebound.html	1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/rulebound/rulebound.html	2015-06-02 05:55:14 +0000
@@ -0,0 +1,29 @@
+<div class="panel panel-info" ng-controller="RuleBoundController">
+    <div class="panel-heading handle bold">
+        {{widgetTitle | translate}}
+        <span class="pull-right">
+            <a class="small-horizonal-spacing" href ng-click="expandCollapse(this.widget)">
+                <span ng-show="this.widget.expand"><i class="fa fa-chevron-up" title="{{'collapse' | translate}}"></i></span>
+                <span ng-show="!this.widget.expand"><i class="fa fa-chevron-down" title="{{'expand' | translate}}"></i></span>
+            </a>
+            <a class="small-horizonal-spacing" href ng-click="removeWidget(this.widget)" title="{{'remove' | translate}}"><i class="fa fa-times-circle"></i></a>            
+        </span>        
+    </div>    
+    <div ng-show="this.widget.expand" class="dashboard-element-container">
+        <div class="panel-body" ng-if="showKeyDataSection">
+            <div ng-repeat="(key,item) in displayKeyDataEffects" ng-show="item.ineffect"  class="info-container">
+                <div class="info-container-heading">{{item.content | trimquotes }}</div>
+                <div class="info-container-text">{{item.data | trimquotes}}</div>          
+            </div>
+        </div>   
+        <table class="table table-striped dashboard-element-container" ng-if="showTextSection">
+            <tr ng-repeat="(key,item) in displayTextEffects" ng-if="item.ineffect">
+                <td>
+                    <div>
+                        {{item.content | trimquotes}}{{item.data | trimquotes}}
+                    </div>
+                </td>
+            </tr>
+        </table>
+    </div>
+</div>

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/i18n/i18n_app.properties'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/i18n/i18n_app.properties	2015-06-02 12:25:03 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/i18n/i18n_app.properties	2015-06-10 11:55:41 +0000
@@ -106,6 +106,8 @@
 new_event=New event
 create_new_event=Create new event
 create_new_event_repeatable=Create new event from a repeatable stage
+toggle_table_view_on=Show events as tables where possible
+toggle_table_view_off=Show data entry forms for each event
 event_recorded_on=Event recorded on
 at=at
 show_more=Click for more

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/i18n/i18n_app_ar.properties'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/i18n/i18n_app_ar.properties	2015-01-20 11:51:34 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/i18n/i18n_app_ar.properties	2015-06-08 08:54:37 +0000
@@ -1,261 +1,263 @@
-tracked_entity_management=\u0627\u062F\u0631\u0627\u0629 \u0627\u0644\u0643\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0645\u062A\u062A\u0628\u0639\u0629
-registering_unit=\u0648\u062D\u062F\u0629 \u062A\u0633\u062C\u064A\u0644
-program=\u0628\u0631\u0646\u0627\u0645\u062C
-please_select=\u0631\u062C\u0627\u0621\u064B \u0627\u062E\u062A\u0631
-please_select_a_program=\u0631\u062C\u0627\u0621\u064B \u0627\u062E\u062A\u0631 \u0628\u0631\u0646\u0627\u0645\u062C\u0627\u064B
-no_program_exists=\u0644\u0627\u064A\u0648\u062C\u062F \u0628\u0631\u0646\u0627\u0645\u062C
-please_select_a_program_for_enrollment=\u0631\u062C\u0627\u0621\u064B \u0627\u062E\u062A\u0631 \u0628\u0631\u0646\u0627\u0645\u062C\u0627\u064B \u0644\u0644\u062A\u0633\u062C\u064A\u0644
-please_select_program_report=\u0631\u062C\u0627\u0621\u064B \u0627\u062E\u062A\u0631 \u0628\u0631\u0646\u0627\u0645\u062C\u0627\u064B \u0644\u0644\u0625\u0639\u062F\u0627\u062F
-please_select_a_relationship=\u0631\u062C\u0627\u0621\u064B \u0627\u062E\u062A\u0631 \u0639\u0644\u0627\u0642\u0629
-no_relationship=\u0644\u0627\u062A\u0648\u062C\u062F \u0639\u0644\u0627\u0642\u0629
-relationship_not_possible=\u0644\u0627 \u064A\u0648\u062C\u062F \u0645\u062B\u0627\u0644 \u0644\u0643\u064A\u0627\u0646 \u0645\u062A\u0628\u0639 . \u0627\u0644\u0639\u0644\u0627\u0642\u0629 \u063A\u064A\u0631 \u0645\u0645\u0643\u0646\u0629
-no_program_exists_enrollment=\u0644\u0627\u064A\u0648\u062C\u062F \u0628\u0631\u0646\u0627\u0645\u062C \u0644\u0639\u0644\u0627\u0642\u0629 \u0627\u0644\u062A\u0646\u0638\u064A\u0645 \u0627\u0644\u0645\u062E\u062A\u0627\u0631\u0629 . \u0627\u0644\u062A\u0633\u062C\u064A\u0644 \u063A\u064A\u0631 \u0645\u0645\u0643\u0646
-no_program_exists_report=\u0644\u0627\u064A\u0648\u062C\u062F \u0628\u0631\u0646\u0627\u0645\u062C \u0644\u0639\u0644\u0627\u0642\u0629 \u0627\u0644\u062A\u0646\u0638\u064A\u0645 \u0627\u0644\u0645\u062E\u062A\u0627\u0631\u0629 . \u0627\u0644\u0627\u0639\u062F\u0627\u062F \u063A\u064A\u0631 \u0645\u0645\u0643\u0646
-not_yet_enrolled_data_entry=\u063A\u064A\u0631 \u0645\u0633\u062C\u0644 \u062D\u062A\u0649 \u0627\u0644\u0644\u0622\u0646 . \u0627\u062F\u062E\u0627\u0644 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u063A\u064A\u0631 \u0645\u0645\u0643\u0646
-not_yet_enrolled_enrollment=\u063A\u064A\u0631 \u0645\u0633\u062C\u0644 \u062D\u062A\u0649 \u0627\u0644\u0644\u0622\u0646 . \u0631\u062C\u0627\u0621\u064B \u0633\u062C\u0644
-not_active_enrollment_exists=\u0644\u0627\u064A\u0648\u062C\u062F \u062A\u0633\u062C\u064A\u0644 \u0641\u0639\u0627\u0644 \u0644\u0644\u0628\u0631\u0646\u0627\u0645\u062C \u0627\u0644\u0645\u062E\u062A\u0627\u0631
-not_yet_enrolled_note=\u063A\u064A\u0631 \u0645\u0633\u062C\u0644 \u062D\u062A\u0649 \u0627\u0644\u0622\u0646 . \u062A\u0633\u062C\u064A\u0644 \u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0629 \u063A\u064A\u0631 \u0645\u0645\u0643\u0646
-not_yet_enrolled_report=\u063A\u064A\u0631 \u0645\u0633\u062C\u0644 \u062D\u062A\u0649 \u0627\u0644\u0622\u0646 . \u0627\u0644\u0627\u0639\u062F\u0627\u062F \u063A\u064A\u0631 \u0645\u0645\u0643\u0646
-no_data_report=\u0644\u0627\u064A\u0648\u062C\u062F \u062A\u0633\u062C\u064A\u0644 \u0644\u064A\u062A\u0645 \u0627\u0644\u0627\u0639\u062F\u0627\u062F
-empty_notes=\u0644\u0627\u0626\u062D\u0629 \u0627\u0644\u0645\u0644\u0627\u062D\u0638\u0627\u062A \u0627\u0644\u0641\u0627\u0631\u063A\u0629
-no_event_is_yet_created=\u0644\u0627\u064A\u0648\u062C\u062F \u062D\u062F\u062B \u0645\u062A\u0648\u0641\u0631 \u0644\u0627\u062F\u062E\u0627\u0644 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A . \u0631\u062C\u0627\u0621\u064B \u0627\u0646\u0634\u0626 \u0648\u0627\u062D\u062F\u0627\u064B
-event_creation=\u0631\u062C\u0627\u0621\u064B \u0627\u0646\u0634\u0626 \u0648\u0627\u062D\u062F\u0627\u064B \u0645\u0646 \u0627\u0644\u0623\u0633\u0641\u0644
-not_selected=\u063A\u064A\u0631 \u0645\u062E\u062A\u0627\u0631
+tracked_entity_management=\u0627\u062f\u0631\u0627\u0629 \u0627\u0644\u0643\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0645\u062a\u062a\u0628\u0639\u0629
+registering_unit=\u0648\u062d\u062f\u0629 \u062a\u0633\u062c\u064a\u0644
+program=\u0628\u0631\u0646\u0627\u0645\u062c
+please_select=\u0631\u062c\u0627\u0621\u064b \u0627\u062e\u062a\u0631
+please_select_a_program=\u0631\u062c\u0627\u0621\u064b \u0627\u062e\u062a\u0631 \u0628\u0631\u0646\u0627\u0645\u062c\u0627\u064b
+no_program_exists=\u0644\u0627\u064a\u0648\u062c\u062f \u0628\u0631\u0646\u0627\u0645\u062c
+please_select_a_program_for_enrollment=\u0631\u062c\u0627\u0621\u064b \u0627\u062e\u062a\u0631 \u0628\u0631\u0646\u0627\u0645\u062c\u0627\u064b \u0644\u0644\u062a\u0633\u062c\u064a\u0644
+please_select_program_report=\u0631\u062c\u0627\u0621\u064b \u0627\u062e\u062a\u0631 \u0628\u0631\u0646\u0627\u0645\u062c\u0627\u064b \u0644\u0644\u0625\u0639\u062f\u0627\u062f
+please_select_a_relationship=\u0631\u062c\u0627\u0621\u064b \u0627\u062e\u062a\u0631 \u0639\u0644\u0627\u0642\u0629
+no_relationship=\u0644\u0627\u062a\u0648\u062c\u062f \u0639\u0644\u0627\u0642\u0629
+relationship_not_possible=\u0644\u0627 \u064a\u0648\u062c\u062f \u0645\u062b\u0627\u0644 \u0644\u0643\u064a\u0627\u0646 \u0645\u062a\u0628\u0639 . \u0627\u0644\u0639\u0644\u0627\u0642\u0629 \u063a\u064a\u0631 \u0645\u0645\u0643\u0646\u0629
+no_program_exists_enrollment=\u0644\u0627\u064a\u0648\u062c\u062f \u0628\u0631\u0646\u0627\u0645\u062c \u0644\u0639\u0644\u0627\u0642\u0629 \u0627\u0644\u062a\u0646\u0638\u064a\u0645 \u0627\u0644\u0645\u062e\u062a\u0627\u0631\u0629 . \u0627\u0644\u062a\u0633\u062c\u064a\u0644 \u063a\u064a\u0631 \u0645\u0645\u0643\u0646
+no_program_exists_report=\u0644\u0627\u064a\u0648\u062c\u062f \u0628\u0631\u0646\u0627\u0645\u062c \u0644\u0639\u0644\u0627\u0642\u0629 \u0627\u0644\u062a\u0646\u0638\u064a\u0645 \u0627\u0644\u0645\u062e\u062a\u0627\u0631\u0629 . \u0627\u0644\u0627\u0639\u062f\u0627\u062f \u063a\u064a\u0631 \u0645\u0645\u0643\u0646
+not_yet_enrolled_data_entry=\u063a\u064a\u0631 \u0645\u0633\u062c\u0644 \u062d\u062a\u0649 \u0627\u0644\u0644\u0622\u0646 . \u0627\u062f\u062e\u0627\u0644 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u063a\u064a\u0631 \u0645\u0645\u0643\u0646
+not_yet_enrolled_enrollment=\u063a\u064a\u0631 \u0645\u0633\u062c\u0644 \u062d\u062a\u0649 \u0627\u0644\u0644\u0622\u0646 . \u0631\u062c\u0627\u0621\u064b \u0633\u062c\u0644
+not_active_enrollment_exists=\u0644\u0627\u064a\u0648\u062c\u062f \u062a\u0633\u062c\u064a\u0644 \u0641\u0639\u0627\u0644 \u0644\u0644\u0628\u0631\u0646\u0627\u0645\u062c \u0627\u0644\u0645\u062e\u062a\u0627\u0631
+not_yet_enrolled_note=\u063a\u064a\u0631 \u0645\u0633\u062c\u0644 \u062d\u062a\u0649 \u0627\u0644\u0622\u0646 . \u062a\u0633\u062c\u064a\u0644 \u0627\u0644\u0645\u0644\u0627\u062d\u0638\u0629 \u063a\u064a\u0631 \u0645\u0645\u0643\u0646
+not_yet_enrolled_report=\u063a\u064a\u0631 \u0645\u0633\u062c\u0644 \u062d\u062a\u0649 \u0627\u0644\u0622\u0646 . \u0627\u0644\u0627\u0639\u062f\u0627\u062f \u063a\u064a\u0631 \u0645\u0645\u0643\u0646
+no_data_report=\u0644\u0627\u064a\u0648\u062c\u062f \u062a\u0633\u062c\u064a\u0644 \u0644\u064a\u062a\u0645 \u0627\u0644\u0627\u0639\u062f\u0627\u062f
+empty_notes=\u0644\u0627\u0626\u062d\u0629 \u0627\u0644\u0645\u0644\u0627\u062d\u0638\u0627\u062a \u0627\u0644\u0641\u0627\u0631\u063a\u0629
+no_event_is_yet_created=\u0644\u0627\u064a\u0648\u062c\u062f \u062d\u062f\u062b \u0645\u062a\u0648\u0641\u0631 \u0644\u0627\u062f\u062e\u0627\u0644 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a . \u0631\u062c\u0627\u0621\u064b \u0627\u0646\u0634\u0626 \u0648\u0627\u062d\u062f\u0627\u064b
+event_creation=\u0631\u062c\u0627\u0621\u064b \u0627\u0646\u0634\u0626 \u0648\u0627\u062d\u062f\u0627\u064b \u0645\u0646 \u0627\u0644\u0623\u0633\u0641\u0644
+not_selected=\u063a\u064a\u0631 \u0645\u062e\u062a\u0627\u0631
 create=\u0627\u0646\u0634\u0626
 view_all=\u0627\u0639\u0631\u0636 \u0627\u0644\u0643\u0644
-list_all_entities=\u0627\u062F\u0631\u062C \u0643\u0644 \u0627\u0644\u0643\u064A\u0627\u0646\u0627\u062A
-list_all=\u0627\u062F\u0631\u062C \u0627\u0644\u0643\u0644
-list=\u0627\u062F\u0631\u062C
-invalid=\u063A\u064A\u0631 \u0635\u0627\u0644\u062D
+list_all_entities=\u0627\u062f\u0631\u062c \u0643\u0644 \u0627\u0644\u0643\u064a\u0627\u0646\u0627\u062a
+list_all=\u0627\u062f\u0631\u062c \u0627\u0644\u0643\u0644
+list=\u0627\u062f\u0631\u062c
+invalid=\u063a\u064a\u0631 \u0635\u0627\u0644\u062d
 required=\u0645\u0637\u0644\u0648\u0628
 number_required=\u0631\u0642\u0645 \u0645\u0637\u0644\u0648\u0628
-date_required=\u0628\u064A\u0627\u0646\u0627\u062A \u0645\u0637\u0644\u0648\u0628\u0629
-filter=\u062A\u0635\u0641\u064A\u0629
-search=\u0628\u062D\u062B
-_search=\u0627\u0628\u062D\u062B
-advanced_search=\u0628\u062D\u062B \u0645\u062A\u0642\u062F\u0645
-search_for=\u0627\u0628\u062D\u062B \u0639\u0646
-type_your_search_criteria_here=\u062F\u0648\u0650\u0646 \u0645\u0639\u0627\u064A\u064A\u0631 \u0627\u0644\u0628\u062D\u062B \u0647\u0646\u0627
-search_input_required=\u0631\u062C\u0627\u0621\u064B \u062D\u062F\u062F \u0645\u0639\u0627\u064A\u064A\u0631 \u0627\u0644\u0628\u062D\u062B
-in_progress=\u0642\u064A\u062F \u0627\u0644\u0639\u0645\u0644
-registered_entities=\u0643\u064A\u0627\u0646\u0627\u062A \u0645\u0633\u062C\u0644\u0629
-empty_entity_list=\u0644\u0627\u062A\u0648\u062C\u062F \u0643\u064A\u0627\u0646\u0627\u062A \u0645\u0633\u062C\u0644\u0629
-empty=\u0641\u0627\u0631\u063A
-form_is_empty_fill_at_least_one=\u0627\u0644\u0627\u0633\u062A\u0645\u0627\u0631\u0629 \u0641\u0627\u0631\u063A\u0629 . \u0631\u062C\u0627\u0621\u064B \u0627\u0645\u0644\u0623 \u0648\u0627\u062D\u062F\u0629 \u0639\u0644\u0649 \u0627\u0644\u0623\u0642\u0644
-total_number_of_pages=\u0639\u062F\u062F \u0627\u0644\u0635\u0641\u062D\u0627\u062A
-rows_per_page=\u0639\u062F\u062F \u0627\u0644\u0635\u0641\u0648\u0641 \u0641\u064A \u0643\u0644 \u0635\u0641\u062D\u0629
-jump_to_page=\u0627\u0646\u062A\u0642\u0644 \u0627\u0644\u0649 \u0635\u0641\u062D\u0629
-page=\u0635\u0641\u062D\u0629
-first=\u0623\u0648\u0644\u0627\u064B
+date_required=\u0628\u064a\u0627\u0646\u0627\u062a \u0645\u0637\u0644\u0648\u0628\u0629
+filter=\u062a\u0635\u0641\u064a\u0629
+search=\u0628\u062d\u062b
+_search=\u0627\u0628\u062d\u062b
+advanced_search=\u0628\u062d\u062b \u0645\u062a\u0642\u062f\u0645
+search_for=\u0627\u0628\u062d\u062b \u0639\u0646
+type_your_search_criteria_here=\u062f\u0648\u0650\u0646 \u0645\u0639\u0627\u064a\u064a\u0631 \u0627\u0644\u0628\u062d\u062b \u0647\u0646\u0627
+search_input_required=\u0631\u062c\u0627\u0621\u064b \u062d\u062f\u062f \u0645\u0639\u0627\u064a\u064a\u0631 \u0627\u0644\u0628\u062d\u062b
+in_progress=\u0642\u064a\u062f \u0627\u0644\u0639\u0645\u0644
+registered_entities=\u0643\u064a\u0627\u0646\u0627\u062a \u0645\u0633\u062c\u0644\u0629
+empty_entity_list=\u0644\u0627\u062a\u0648\u062c\u062f \u0643\u064a\u0627\u0646\u0627\u062a \u0645\u0633\u062c\u0644\u0629
+empty=\u0641\u0627\u0631\u063a
+form_is_empty_fill_at_least_one=\u0627\u0644\u0627\u0633\u062a\u0645\u0627\u0631\u0629 \u0641\u0627\u0631\u063a\u0629 . \u0631\u062c\u0627\u0621\u064b \u0627\u0645\u0644\u0623 \u0648\u0627\u062d\u062f\u0629 \u0639\u0644\u0649 \u0627\u0644\u0623\u0642\u0644
+total_number_of_pages=\u0639\u062f\u062f \u0627\u0644\u0635\u0641\u062d\u0627\u062a
+rows_per_page=\u0639\u062f\u062f \u0627\u0644\u0635\u0641\u0648\u0641 \u0641\u064a \u0643\u0644 \u0635\u0641\u062d\u0629
+jump_to_page=\u0627\u0646\u062a\u0642\u0644 \u0627\u0644\u0649 \u0635\u0641\u062d\u0629
+page=\u0635\u0641\u062d\u0629
+first=\u0623\u0648\u0644\u0627\u064b
 previous=\u0627\u0644\u0633\u0627\u0628\u0642
-next=\u0627\u0644\u062A\u0627\u0644\u064A
-last=\u0627\u062E\u064A\u0631
-go_to_dashboard=\u0627\u0630\u0647\u0628 \u0627\u0644\u0649 \u0644\u0648\u062D\u0629 \u0627\u0644\u0639\u062F\u0627\u062F\u0627\u062A
+next=\u0627\u0644\u062a\u0627\u0644\u064a
+last=\u0627\u062e\u064a\u0631
+go_to_dashboard=\u0627\u0630\u0647\u0628 \u0627\u0644\u0649 \u0644\u0648\u062d\u0629 \u0627\u0644\u0639\u062f\u0627\u062f\u0627\u062a
 go=\u0627\u0630\u0647\u0628
-edit=\u062A\u062D\u0631\u064A\u0631
-edit_profile=\u062D\u0631\u0631 \u0627\u0644\u062A\u0634\u0643\u064A\u0644 \u0627\u0644\u062C\u0627\u0646\u0628\u064A
-association=\u0646\u0638\u0650\u0645 \u0627\u0644\u0645\u0634\u0627\u0631\u0643\u0627\u062A
+edit=\u062a\u062d\u0631\u064a\u0631
+edit_profile=\u062d\u0631\u0631 \u0627\u0644\u062a\u0634\u0643\u064a\u0644 \u0627\u0644\u062c\u0627\u0646\u0628\u064a
+association=\u0646\u0638\u0650\u0645 \u0627\u0644\u0645\u0634\u0627\u0631\u0643\u0627\u062a
 change_location=\u0646\u0638\u0650\u0645 \u0627\u0644\u0645\u0648\u0642\u0639
-details_history=\u062A\u0641\u0627\u0635\u064A\u0644/\u062A\u0627\u0631\u064A\u062E
-history=\u062A\u0627\u0631\u064A\u062E
+details_history=\u062a\u0641\u0627\u0635\u064a\u0644/\u062a\u0627\u0631\u064a\u062e
+history=\u062a\u0627\u0631\u064a\u062e
 complete=\u0627\u0643\u0645\u0644
 terminate=\u0627\u0646\u0647\u0627\u0621
-completed=\u0645\u0643\u062A\u0645\u0644
-terminated=\u0645\u0646\u062A\u0647\u064A
-delete=\u0627\u062D\u0630\u0641
+completed=\u0645\u0643\u062a\u0645\u0644
+terminated=\u0645\u0646\u062a\u0647\u064a
+delete=\u0627\u062d\u0630\u0641
 remove=\u0627\u0632\u0644
-entity=\u0643\u064A\u0627\u0646
-clear=\u0627\u0645\u0633\u062D
+entity=\u0643\u064a\u0627\u0646
+clear=\u0627\u0645\u0633\u062d
 add=\u0623\u0636\u0641
-add_note=\u0623\u0636\u0641 \u0645\u0644\u0627\u062D\u0638\u0629
-search_note=\u0627\u0628\u062D\u062B \u0639\u0646 \u0645\u0644\u0627\u062D\u0638\u0627\u062A
-add_new_note_here=\u0627\u0636\u0641 \u0645\u0644\u0627\u062D\u0638\u0629 \u062C\u062F\u064A\u062F\u0629 \u0647\u0646\u0627
-skipped=\u0645\u062A\u062E\u0637\u0649
-skip=\u062A\u062E\u0637\u0649
-unskip=\u062C\u062F\u0648\u0644\u0629 \u0633\u0627\u0628\u0642\u0629
-complete=\u0645\u0643\u062A\u0645\u0644
-incomplete=\u063A\u064A\u0631 \u0645\u0643\u062A\u0645\u0644
-validate=\u062A\u062D\u0642\u0642 \u0645\u0646 \u0627\u0644\u0635\u062D\u0629
-status=\u062D\u0627\u0644\u0629
-details=\u062A\u0641\u0627\u0635\u064A\u0644
-_details=\u062A\u0641\u0627\u0635\u064A\u0644
-created_by=\u0645\u0633\u062C\u0644 \u0628\u0648\u0627\u0633\u0637\u0629
-date=\u062A\u0627\u0631\u064A\u062E
-_date=\u062A\u0627\u0631\u064A\u062E
-add_new=\u0623\u0635\u0641 \u062C\u062F\u064A\u062F\u0627\u064B
-event_name=\u0627\u0633\u0645 \u0627\u0644\u062D\u062F\u062B
-new_event=\u062D\u062F\u062B \u062C\u062F\u064A\u062F
-create_new_event=\u0627\u0646\u0634\u0626 \u062D\u062F\u062B\u0627\u064B \u062C\u062F\u064A\u062F\u0627\u064B
-create_new_event_repeatable=\u0627\u0646\u0634\u0626 \u062D\u062F\u062B\u0627\u064B \u062C\u062F\u064A\u062F\u0627\u064B \u0645\u0646 \u0645\u0631\u062D\u0644\u0629 \u0645\u0645\u0643\u0646 \u0627\u0639\u0627\u062F\u062A\u0647\u0627
-close_search=\u0627\u063A\u0644\u0642 \u0627\u0644\u0628\u062D\u062B
-search_attributes=\u062E\u0635\u0627\u0626\u0635 \u0627\u0644\u0628\u062D\u062B
-available_search_attributes=\u062E\u0635\u0627\u0626\u0635 \u0627\u0644\u0628\u062D\u062B \u0627\u0644\u0645\u062A\u0648\u0641\u0631\u0629
-selected_search_attributes=\u062E\u0635\u0627\u0626\u0635 \u0627\u0644\u0628\u062D\u062B \u0627\u0644\u0645\u062E\u062A\u0627\u0631\u0629
-search_for_dashboard=\u0627\u0628\u062D\u062B \u0639\u0646 \u0639\u0646\u0627\u0635\u0631 \u0644\u0648\u062D\u0629 \u0627\u0644\u0639\u062F\u0627\u062F\u0627\u062A
-dashboard=\u0644\u0648\u062D\u0629 \u0627\u0644\u0639\u062F\u0627\u062F\u0627\u062A
-home=\u0627\u0644\u0635\u0641\u062D\u0629 \u0627\u0644\u0631\u0626\u0633\u064A\u0629
-back=\u0644\u0644\u062E\u0644\u0641
-profile=\u062A\u0634\u0643\u064A\u0644 \u062C\u0627\u0646\u0628\u064A
-enrollment=\u062A\u0633\u062C\u064A\u0644
-delete_enrollment=\u0627\u0644\u063A\u0650 \u0627\u0644\u062A\u0633\u062C\u064A\u0644
-terminate_enrollment=\u0627\u0646\u0647\u0650 \u0627\u0644\u062A\u0633\u062C\u064A\u0644
-complete_enrollment=\u0627\u0643\u0645\u0644 \u0627\u0644\u062A\u0633\u062C\u0628\u0644
-enrollment_date=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u062A\u0633\u062C\u064A\u0644
-notes=\u0645\u0644\u0627\u062D\u0638\u0627\u062A
+add_note=\u0623\u0636\u0641 \u0645\u0644\u0627\u062d\u0638\u0629
+search_note=\u0627\u0628\u062d\u062b \u0639\u0646 \u0645\u0644\u0627\u062d\u0638\u0627\u062a
+add_new_note_here=\u0627\u0636\u0641 \u0645\u0644\u0627\u062d\u0638\u0629 \u062c\u062f\u064a\u062f\u0629 \u0647\u0646\u0627
+skipped=\u0645\u062a\u062e\u0637\u0649
+skip=\u062a\u062e\u0637\u0649
+unskip=\u062c\u062f\u0648\u0644\u0629 \u0633\u0627\u0628\u0642\u0629
+complete=\u0645\u0643\u062a\u0645\u0644
+incomplete=\u063a\u064a\u0631 \u0645\u0643\u062a\u0645\u0644
+validate=\u062a\u062d\u0642\u0642 \u0645\u0646 \u0627\u0644\u0635\u062d\u0629
+status=\u062d\u0627\u0644\u0629
+details=\u062a\u0641\u0627\u0635\u064a\u0644
+_details=\u062a\u0641\u0627\u0635\u064a\u0644
+created_by=\u0645\u0633\u062c\u0644 \u0628\u0648\u0627\u0633\u0637\u0629
+date=\u062a\u0627\u0631\u064a\u062e
+_date=\u062a\u0627\u0631\u064a\u062e
+add_new=\u0623\u0635\u0641 \u062c\u062f\u064a\u062f\u0627\u064b
+event_name=\u0627\u0633\u0645 \u0627\u0644\u062d\u062f\u062b
+new_event=\u062d\u062f\u062b \u062c\u062f\u064a\u062f
+create_new_event=\u0627\u0646\u0634\u0626 \u062d\u062f\u062b\u0627\u064b \u062c\u062f\u064a\u062f\u0627\u064b
+create_new_event_repeatable=\u0627\u0646\u0634\u0626 \u062d\u062f\u062b\u0627\u064b \u062c\u062f\u064a\u062f\u0627\u064b \u0645\u0646 \u0645\u0631\u062d\u0644\u0629 \u0645\u0645\u0643\u0646 \u0627\u0639\u0627\u062f\u062a\u0647\u0627
+toggle_table_view_on=\u0645\u0634\u0627\u0647\u062f\u0629 \u0623\u062d\u062f\u0627\u062b \u0643\u062c\u062f\u0627\u0648\u0644 \u062d\u064a\u062b\u0645\u0627 \u0623\u0645\u0643\u0646(\u062c\u0648\u062c\u0644 \u062a\u0631\u062c\u0645\u0629)
+toggle_table_view_off=\u0646\u0645\u0627\u0630\u062c \u0625\u062f\u062e\u0627\u0644 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u062a\u0638\u0647\u0631 \u0644\u0643\u0644 \u062d\u062f\u062b(\u062c\u0648\u062c\u0644 \u062a\u0631\u062c\u0645\u0629)
+close_search=\u0627\u063a\u0644\u0642 \u0627\u0644\u0628\u062d\u062b
+search_attributes=\u062e\u0635\u0627\u0626\u0635 \u0627\u0644\u0628\u062d\u062b
+available_search_attributes=\u062e\u0635\u0627\u0626\u0635 \u0627\u0644\u0628\u062d\u062b \u0627\u0644\u0645\u062a\u0648\u0641\u0631\u0629
+selected_search_attributes=\u062e\u0635\u0627\u0626\u0635 \u0627\u0644\u0628\u062d\u062b \u0627\u0644\u0645\u062e\u062a\u0627\u0631\u0629
+search_for_dashboard=\u0627\u0628\u062d\u062b \u0639\u0646 \u0639\u0646\u0627\u0635\u0631 \u0644\u0648\u062d\u0629 \u0627\u0644\u0639\u062f\u0627\u062f\u0627\u062a
+dashboard=\u0644\u0648\u062d\u0629 \u0627\u0644\u0639\u062f\u0627\u062f\u0627\u062a
+home=\u0627\u0644\u0635\u0641\u062d\u0629 \u0627\u0644\u0631\u0626\u0633\u064a\u0629
+back=\u0644\u0644\u062e\u0644\u0641
+profile=\u062a\u0634\u0643\u064a\u0644 \u062c\u0627\u0646\u0628\u064a
+enrollment=\u062a\u0633\u062c\u064a\u0644
+delete_enrollment=\u0627\u0644\u063a\u0650 \u0627\u0644\u062a\u0633\u062c\u064a\u0644
+terminate_enrollment=\u0627\u0646\u0647\u0650 \u0627\u0644\u062a\u0633\u062c\u064a\u0644
+complete_enrollment=\u0627\u0643\u0645\u0644 \u0627\u0644\u062a\u0633\u062c\u0628\u0644
+enrollment_date=\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u062a\u0633\u062c\u064a\u0644
+notes=\u0645\u0644\u0627\u062d\u0638\u0627\u062a
 relationship=\u0639\u0644\u0627\u0642\u0629
-relationships=\u0639\u0644\u0627\u0642\u0627\u062A
+relationships=\u0639\u0644\u0627\u0642\u0627\u062a
 add_relationship=\u0627\u0636\u0641 \u0639\u0644\u0627\u0642\u0629
 a_is_to_b=\u0639\u0644\u0627\u0642\u0629 (\u0623) \u0644\u0640\u0640 (\u0628)
 b_is_to_a=\u0639\u0644\u0627\u0642\u0629 (\u0628) \u0644\u0640\u0640 (\u0623)
-please_select_source=\u0631\u062C\u0627\u0621\u064B \u0627\u062E\u062A\u0631 \u0645\u0635\u062F\u0631\u0627\u064B
-register_new=\u0633\u062C\u0644 \u062C\u062F\u064A\u062F\u0627\u064B
-search_from_existing=\u0627\u0628\u062D\u062B \u0628\u0645\u0639\u064A\u0627\u0631 \u0645\u062A\u0649 \u062A\u0645 \u0627\u0644\u0627\u0646\u0634\u0627\u0621
+please_select_source=\u0631\u062c\u0627\u0621\u064b \u0627\u062e\u062a\u0631 \u0645\u0635\u062f\u0631\u0627\u064b
+register_new=\u0633\u062c\u0644 \u062c\u062f\u064a\u062f\u0627\u064b
+search_from_existing=\u0627\u0628\u062d\u062b \u0628\u0645\u0639\u064a\u0627\u0631 \u0645\u062a\u0649 \u062a\u0645 \u0627\u0644\u0627\u0646\u0634\u0627\u0621
 name=\u0627\u0633\u0645
-dataentry=\u0627\u062F\u062E\u0627\u0644 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A
-custom_form=\u0627\u0633\u062A\u0645\u0627\u0631\u0629 \u0645\u062E\u0635\u0635\u0629
-default_form=\u0627\u0633\u062A\u0645\u0627\u0631\u0629 \u0627\u0641\u062A\u0631\u0627\u0636\u064A\u0629
+dataentry=\u0627\u062f\u062e\u0627\u0644 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a
+custom_form=\u0627\u0633\u062a\u0645\u0627\u0631\u0629 \u0645\u062e\u0635\u0635\u0629
+default_form=\u0627\u0633\u062a\u0645\u0627\u0631\u0629 \u0627\u0641\u062a\u0631\u0627\u0636\u064a\u0629
 menu=\u0642\u0627\u0626\u0645\u0629
-tracker_reports=\u062A\u0642\u0627\u0631\u064A\u0631 \u0645\u064F\u062A\u064E\u062A\u064E\u0628\u0650\u0639\u064E\u0629
-reports=\u062A\u0642\u0627\u0631\u064A\u0631
-registration_and_data_entry=\u0627\u0644\u062A\u0633\u062C\u064A\u0644 \u0648 \u0627\u062F\u062E\u0627\u0644 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A
-program_summary_report=\u062A\u0642\u0631\u064A\u0631 \u0645\u0644\u062E\u0635 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C
-program_summary=\u0645\u0644\u062E\u0635 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C
-program_summary_description=\u0627\u0635\u062F\u0631 \u062A\u0642\u0631\u064A\u0631\u0627\u064B \u0645\u0644\u062E\u0635\u0627\u064B \u0644\u0648\u062D\u062F\u0629 \u062A\u0646\u0638\u064A\u0645 \u0628\u0631\u0646\u0627\u0645\u062C \u0645\u062E\u0635\u0635\u0629 \u0648 \u0627\u0637\u0627\u0631\u0627\u064B \u0632\u0645\u0646\u064A\u0627\u064B . \u064A\u0642\u062F\u0645 \u0627\u0644\u062A\u0642\u0631\u064A\u0631 \u0644\u0627\u0626\u062D\u0629\u064B \u0628\u0623\u0645\u062B\u0644\u0629 \u0627\u0644\u0643\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0645\u062A\u0628\u0639\u0629 \u0628\u0627\u0644\u0627\u0636\u0627\u0641\u0629 \u0627\u0644\u0649 \u062E\u064A\u0627\u0631 \u0627\u0644\u062A\u0639\u0645\u0642 \u0648 \u0631\u0624\u064A\u0629 \u0627\u0644\u0642\u064A\u0645 \u0627\u0644\u0641\u0639\u0644\u064A\u0629
-program_statistics_report=\u062A\u0642\u0631\u064A\u0631 \u0627\u062D\u0635\u0627\u0626\u064A\u0627\u062A \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C
-program_statistics=\u0627\u062D\u0635\u0627\u0626\u064A\u0627\u062A \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C
-program_statistics_description= \u0627\u0635\u062F\u0631 \u062A\u0642\u0631\u064A\u0631\u0627\u064B\u0627\u062D\u0635\u0627\u0626\u064A\u0627\u064B \u0644\u0628\u0631\u0646\u0627\u0645\u062C \u0645\u0639\u064A\u0646 . \u064A\u062D\u0648\u064A \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C \u0639\u0644\u0649 \u0633\u0628\u064A\u0644 \u0627\u0644\u0645\u062B\u0627\u0644 \u0648\u0635\u0641\u0627\u064B \u0639\u0627\u0645\u0627\u064B \u0639\u0646 \u0627\u0644\u0627\u0646\u0642\u0637\u0627\u0639\u0627\u062A \u0627\u0648 \u0646\u0633\u0628 \u0627\u0644\u0627\u0643\u0645\u0627\u0644 \u0641\u064A \u0627\u0637\u0627\u0631 \u0632\u0645\u0646\u064A \u0645\u0623\u062E\u0648\u0630 \u0628\u0639\u064A\u0646 \u0627\u0644\u0627\u0639\u062A\u0628\u0627\u0631 \u0641\u064A \u0648\u062D\u062F\u0629 \u062A\u0646\u0638\u064A\u0645 \u0645\u062E\u0635\u0635\u0629
-upcoming_events=\u0627\u062D\u062F\u0627\u062B \u062A\u0627\u0644\u064A\u0629
-upcoming_events_description=\u0627\u0635\u062F\u0631 \u062A\u0642\u0631\u064A\u0631\u0627\u064B \u062C\u062F\u0648\u0644\u064A\u0627\u064B \u064A\u0638\u0647\u0631 \u0641\u064A\u0647 \u0623\u0645\u062B\u0644\u0629 \u0639\u0646 \u0643\u064A\u0627\u0646\u0627\u062A \u0645\u062A\u0628\u0639\u0629 \u0648 \u0623\u062D\u062F\u0627\u062B\u0647\u0645 \u0627\u0644\u0645\u0631\u062A\u0642\u0628\u0629 \u0644\u0628\u0631\u0646\u0627\u0645\u062C \u0648 \u0648\u0642\u062A \u0645\u062D\u062F\u062F\u064A\u0646 . \u062A\u0635\u0646\u064A\u0641 \u0627\u0644\u0628\u062D\u062B \u0648 \u0627\u0638\u0647\u0627\u0631\\u0627\u062E\u0641\u0627\u0621 \u0627\u0644\u0639\u0645\u0644\u064A\u0627\u062A \u0645\u0645\u0643\u0646\u0627\u062A \u0641\u064A \u0627\u0644\u0623\u0639\u0645\u062F\u0629
-overdue_events=\u0627\u062D\u062F\u0627\u062B \u063A\u064A\u0631 \u0645\u0646\u062C\u0632\u0629
-overdue_events_description=\u0627\u0635\u062F\u0631 \u0644\u0627\u0626\u062D\u0629 \u0645\u0646 \u0623\u062D\u062F\u0627\u062B \u0644\u0628\u0631\u0646\u0627\u0645\u062C \u0645\u062E\u062A\u0627\u0631 . \u064A\u0638\u0647\u0631 \u0627\u0644\u062A\u0642\u0631\u064A\u0631 \u0642\u0627\u0626\u0645\u0629\u064B \u0645\u0646 \u0623\u0645\u062B\u0644\u0629 \u0627\u0644\u0643\u064A\u0627\u0646\u0627\u062A \u0627\u0644\u0645\u062A\u0628\u0639\u0629 \u0648 \u0623\u062D\u062F\u0627\u062B\u0647\u0645 \u0627\u0644\u062A\u064A \u0644\u0645 \u062A\u062A\u0645 \u0641\u064A \u0648\u0642\u062A\u0647\u0627 . \u0627\u0644\u062A\u0635\u0641\u064A\u0629 \u0648 \u0627\u0644\u0628\u062D\u062B \u0623\u064A\u0636\u0627\u064B \u0645\u0645\u0643\u0646\u0627\u0646 .
-enrollment_stats=\u0627\u062D\u0635\u0627\u0626\u064A\u0627\u062A \u0627\u0644\u062A\u0633\u062C\u064A\u0644
-event_stats=\u0627\u062D\u0635\u0627\u0626\u064A\u0627\u062A \u0627\u0644\u062D\u062F\u062B
-upcoming_event=\u0627\u0644\u062D\u062F\u062B \u0627\u0644\u062A\u0627\u0644\u064A
-legend=\u0634\u0631\u0648\u062D\u0627\u062A
-event_color_legend=\u0645\u0627\u0630\u0627 \u062A\u0639\u0646\u064A \u0627\u0644\u0623\u0644\u0648\u0627\u0646
-completed=\u0645\u0643\u062A\u0645\u0644
-executed=\u0645\u064F\u0646\u064E\u0641\u064E\u0630
-ontime=\u0641\u064A \u0648\u0642\u062A\u0647
-overdue=\u063A\u064A\u0631 \u0645\u0646\u062C\u0632
-skipped=\u0645\u062A\u062E\u0637\u0649
-report=\u062A\u0642\u0631\u064A\u0631
-_report=\u062A\u0642\u0631\u064A\u0631
-visit_schedule=\u062C\u062F\u0648\u0644 \u0632\u064A\u0627\u0631\u0629
-mark_for_followup=\u0627\u0634\u0631 \u0645\u0646 \u0623\u062C\u0644 \u0627\u0644\u0645\u0644\u062D\u0642
-unmark_for_followup=\u0627\u062D\u0630\u0641 \u0645\u0646 \u0627\u0644\u0645\u0644\u062D\u0642
-only_marked_for_followup=\u0641\u0642\u0637 \u0627\u0634\u0650\u0631 \u0639\u0644\u064A\u0647 \u0645\u0646 \u0623\u062C\u0644 \u0627\u0644\u0645\u0644\u062D\u0642
-registered_data=\u0642\u064A\u0645\u0629 \u0645\u0633\u062C\u0644\u0629
-no_value=\u0644\u0627 \u0642\u064A\u0645\u0629
-no_data_found=\u0644\u0645 \u062A\u0648\u062C\u062F \u0628\u064A\u0627\u0646\u0627\u062A
-no_data=\u0644\u0627 \u062A\u0648\u062C\u062F \u0628\u064A\u0627\u0646\u0627\u062A
-data_exists=\u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A \u0645\u062A\u0648\u0627\u062C\u062F\u0629
-data_registerd=\u0644\u0627 \u062A\u0648\u062C\u062F \u0628\u064A\u0627\u0646\u0627\u062A \u0645\u0633\u062C\u0644\u0629
-no_visit_made=\u0644\u0627 \u062A\u0648\u062C\u062F \u0632\u064A\u0627\u0631\u0627\u062A \u062A\u0627\u0645\u0629
-visit_not_made=\u0644\u0645 \u062A\u062A\u0645 \u0627\u0644\u0632\u064A\u0627\u0631\u0629
-_visit=\u0632\u064C\u0631
-visit=\u0632\u064A\u0627\u0631\u0629
-visits=\u0632\u064A\u0627\u0631\u0627\u062A
-current_selections=\u0627\u0644\u0627\u062E\u062A\u064A\u0627\u0631\u0627\u062A \u0627\u0644\u062D\u0627\u0644\u064A\u0629
-org_unit=\u0648\u062D\u062F\u0629 \u0627\u0644\u062A\u0646\u0638\u064A\u0645
-org_unit_scope=\u0645\u062F\u0649 \u0648\u062D\u062F\u0629 \u0627\u0644\u062A\u0646\u0638\u064A\u0645
-SELECTED=\u0645\u062E\u062A\u0627\u0631\\u0629
-CHILDREN=\u0627\u0644\u0623\u0637\u0641\u0627\u0644 \u0627\u0644\u0645\u062A\u0648\u0633\u0637\u0648\u0646
+tracker_reports=\u062a\u0642\u0627\u0631\u064a\u0631 \u0645\u064f\u062a\u064e\u062a\u064e\u0628\u0650\u0639\u064e\u0629
+reports=\u062a\u0642\u0627\u0631\u064a\u0631
+registration_and_data_entry=\u0627\u0644\u062a\u0633\u062c\u064a\u0644 \u0648 \u0627\u062f\u062e\u0627\u0644 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a
+program_summary_report=\u062a\u0642\u0631\u064a\u0631 \u0645\u0644\u062e\u0635 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c
+program_summary=\u0645\u0644\u062e\u0635 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c
+program_summary_description=\u0627\u0635\u062f\u0631 \u062a\u0642\u0631\u064a\u0631\u0627\u064b \u0645\u0644\u062e\u0635\u0627\u064b \u0644\u0648\u062d\u062f\u0629 \u062a\u0646\u0638\u064a\u0645 \u0628\u0631\u0646\u0627\u0645\u062c \u0645\u062e\u0635\u0635\u0629 \u0648 \u0627\u0637\u0627\u0631\u0627\u064b \u0632\u0645\u0646\u064a\u0627\u064b . \u064a\u0642\u062f\u0645 \u0627\u0644\u062a\u0642\u0631\u064a\u0631 \u0644\u0627\u0626\u062d\u0629\u064b \u0628\u0623\u0645\u062b\u0644\u0629 \u0627\u0644\u0643\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0645\u062a\u0628\u0639\u0629 \u0628\u0627\u0644\u0627\u0636\u0627\u0641\u0629 \u0627\u0644\u0649 \u062e\u064a\u0627\u0631 \u0627\u0644\u062a\u0639\u0645\u0642 \u0648 \u0631\u0624\u064a\u0629 \u0627\u0644\u0642\u064a\u0645 \u0627\u0644\u0641\u0639\u0644\u064a\u0629
+program_statistics_report=\u062a\u0642\u0631\u064a\u0631 \u0627\u062d\u0635\u0627\u0626\u064a\u0627\u062a \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c
+program_statistics=\u0627\u062d\u0635\u0627\u0626\u064a\u0627\u062a \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c
+program_statistics_description= \u0627\u0635\u062f\u0631 \u062a\u0642\u0631\u064a\u0631\u0627\u064b\u0627\u062d\u0635\u0627\u0626\u064a\u0627\u064b \u0644\u0628\u0631\u0646\u0627\u0645\u062c \u0645\u0639\u064a\u0646 . \u064a\u062d\u0648\u064a \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c \u0639\u0644\u0649 \u0633\u0628\u064a\u0644 \u0627\u0644\u0645\u062b\u0627\u0644 \u0648\u0635\u0641\u0627\u064b \u0639\u0627\u0645\u0627\u064b \u0639\u0646 \u0627\u0644\u0627\u0646\u0642\u0637\u0627\u0639\u0627\u062a \u0627\u0648 \u0646\u0633\u0628 \u0627\u0644\u0627\u0643\u0645\u0627\u0644 \u0641\u064a \u0627\u0637\u0627\u0631 \u0632\u0645\u0646\u064a \u0645\u0623\u062e\u0648\u0630 \u0628\u0639\u064a\u0646 \u0627\u0644\u0627\u0639\u062a\u0628\u0627\u0631 \u0641\u064a \u0648\u062d\u062f\u0629 \u062a\u0646\u0638\u064a\u0645 \u0645\u062e\u0635\u0635\u0629
+upcoming_events=\u0627\u062d\u062f\u0627\u062b \u062a\u0627\u0644\u064a\u0629
+upcoming_events_description=\u0627\u0635\u062f\u0631 \u062a\u0642\u0631\u064a\u0631\u0627\u064b \u062c\u062f\u0648\u0644\u064a\u0627\u064b \u064a\u0638\u0647\u0631 \u0641\u064a\u0647 \u0623\u0645\u062b\u0644\u0629 \u0639\u0646 \u0643\u064a\u0627\u0646\u0627\u062a \u0645\u062a\u0628\u0639\u0629 \u0648 \u0623\u062d\u062f\u0627\u062b\u0647\u0645 \u0627\u0644\u0645\u0631\u062a\u0642\u0628\u0629 \u0644\u0628\u0631\u0646\u0627\u0645\u062c \u0648 \u0648\u0642\u062a \u0645\u062d\u062f\u062f\u064a\u0646 . \u062a\u0635\u0646\u064a\u0641 \u0627\u0644\u0628\u062d\u062b \u0648 \u0627\u0638\u0647\u0627\u0631\\u0627\u062e\u0641\u0627\u0621 \u0627\u0644\u0639\u0645\u0644\u064a\u0627\u062a \u0645\u0645\u0643\u0646\u0627\u062a \u0641\u064a \u0627\u0644\u0623\u0639\u0645\u062f\u0629
+overdue_events=\u0627\u062d\u062f\u0627\u062b \u063a\u064a\u0631 \u0645\u0646\u062c\u0632\u0629
+overdue_events_description=\u0627\u0635\u062f\u0631 \u0644\u0627\u0626\u062d\u0629 \u0645\u0646 \u0623\u062d\u062f\u0627\u062b \u0644\u0628\u0631\u0646\u0627\u0645\u062c \u0645\u062e\u062a\u0627\u0631 . \u064a\u0638\u0647\u0631 \u0627\u0644\u062a\u0642\u0631\u064a\u0631 \u0642\u0627\u0626\u0645\u0629\u064b \u0645\u0646 \u0623\u0645\u062b\u0644\u0629 \u0627\u0644\u0643\u064a\u0627\u0646\u0627\u062a \u0627\u0644\u0645\u062a\u0628\u0639\u0629 \u0648 \u0623\u062d\u062f\u0627\u062b\u0647\u0645 \u0627\u0644\u062a\u064a \u0644\u0645 \u062a\u062a\u0645 \u0641\u064a \u0648\u0642\u062a\u0647\u0627 . \u0627\u0644\u062a\u0635\u0641\u064a\u0629 \u0648 \u0627\u0644\u0628\u062d\u062b \u0623\u064a\u0636\u0627\u064b \u0645\u0645\u0643\u0646\u0627\u0646 .
+enrollment_stats=\u0627\u062d\u0635\u0627\u0626\u064a\u0627\u062a \u0627\u0644\u062a\u0633\u062c\u064a\u0644
+event_stats=\u0627\u062d\u0635\u0627\u0626\u064a\u0627\u062a \u0627\u0644\u062d\u062f\u062b
+upcoming_event=\u0627\u0644\u062d\u062f\u062b \u0627\u0644\u062a\u0627\u0644\u064a
+legend=\u0634\u0631\u0648\u062d\u0627\u062a
+event_color_legend=\u0645\u0627\u0630\u0627 \u062a\u0639\u0646\u064a \u0627\u0644\u0623\u0644\u0648\u0627\u0646
+completed=\u0645\u0643\u062a\u0645\u0644
+executed=\u0645\u064f\u0646\u064e\u0641\u064e\u0630
+ontime=\u0641\u064a \u0648\u0642\u062a\u0647
+overdue=\u063a\u064a\u0631 \u0645\u0646\u062c\u0632
+skipped=\u0645\u062a\u062e\u0637\u0649
+report=\u062a\u0642\u0631\u064a\u0631
+_report=\u062a\u0642\u0631\u064a\u0631
+visit_schedule=\u062c\u062f\u0648\u0644 \u0632\u064a\u0627\u0631\u0629
+mark_for_followup=\u0627\u0634\u0631 \u0645\u0646 \u0623\u062c\u0644 \u0627\u0644\u0645\u0644\u062d\u0642
+unmark_for_followup=\u0627\u062d\u0630\u0641 \u0645\u0646 \u0627\u0644\u0645\u0644\u062d\u0642
+only_marked_for_followup=\u0641\u0642\u0637 \u0627\u0634\u0650\u0631 \u0639\u0644\u064a\u0647 \u0645\u0646 \u0623\u062c\u0644 \u0627\u0644\u0645\u0644\u062d\u0642
+registered_data=\u0642\u064a\u0645\u0629 \u0645\u0633\u062c\u0644\u0629
+no_value=\u0644\u0627 \u0642\u064a\u0645\u0629
+no_data_found=\u0644\u0645 \u062a\u0648\u062c\u062f \u0628\u064a\u0627\u0646\u0627\u062a
+no_data=\u0644\u0627 \u062a\u0648\u062c\u062f \u0628\u064a\u0627\u0646\u0627\u062a
+data_exists=\u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a \u0645\u062a\u0648\u0627\u062c\u062f\u0629
+data_registerd=\u0644\u0627 \u062a\u0648\u062c\u062f \u0628\u064a\u0627\u0646\u0627\u062a \u0645\u0633\u062c\u0644\u0629
+no_visit_made=\u0644\u0627 \u062a\u0648\u062c\u062f \u0632\u064a\u0627\u0631\u0627\u062a \u062a\u0627\u0645\u0629
+visit_not_made=\u0644\u0645 \u062a\u062a\u0645 \u0627\u0644\u0632\u064a\u0627\u0631\u0629
+_visit=\u0632\u064c\u0631
+visit=\u0632\u064a\u0627\u0631\u0629
+visits=\u0632\u064a\u0627\u0631\u0627\u062a
+current_selections=\u0627\u0644\u0627\u062e\u062a\u064a\u0627\u0631\u0627\u062a \u0627\u0644\u062d\u0627\u0644\u064a\u0629
+org_unit=\u0648\u062d\u062f\u0629 \u0627\u0644\u062a\u0646\u0638\u064a\u0645
+org_unit_scope=\u0645\u062f\u0649 \u0648\u062d\u062f\u0629 \u0627\u0644\u062a\u0646\u0638\u064a\u0645
+SELECTED=\u0645\u062e\u062a\u0627\u0631\\u0629
+CHILDREN=\u0627\u0644\u0623\u0637\u0641\u0627\u0644 \u0627\u0644\u0645\u062a\u0648\u0633\u0637\u0648\u0646
 DESCENDANTS=\u0643\u0644 \u0627\u0644\u0623\u0637\u0641\u0627\u0644
-ACCESSIBLE=\u0627\u0644\u0643\u0644 \u064A\u0645\u0643\u0646 \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u064A\u0647
-data_element=\u0639\u0646\u0635\u0631 \u0627\u0644\u0628\u064A\u0627\u0646\u0627\u062A
-value=\u0642\u064A\u0645\u0629
-provided_elsewhere=\u0645\u0632\u0648\u062F\u0629 \u0628\u0645\u0643\u0627\u0646 \u0622\u062E\u0631
-expand=\u0648\u0633\u0650\u0639\\u0645\u062F\u0650\u062F
-collapse=\u0627\u0646\u0647\u064A\u0627\u0631
-show_hide_columns=\u0627\u0638\u0647\u0631\\u0627\u062E\u0641\u0650 \u0623\u0639\u0645\u062F\u0629
-select_columns_to_show=\u0627\u062E\u062A\u0631 \u0623\u0639\u0645\u062F\u0629 \u0644\u064A\u062A\u0645 \u0627\u0638\u0647\u0627\u0631\u0647\u0627
-show_hide_widgets=\u0627\u0638\u0647\u0631\\u0627\u062E\u0641\u0650 \u0627\u0644\u062A\u0637\u0628\u064A\u0642\u0627\u062A \u0627\u0644\u0645\u0635\u063A\u0631\u0629
-select_widgets_to_show=\u0627\u062E\u062A\u0631 \u0627\u0644\u062A\u0637\u0628\u064A\u0642\u0627\u062A \u0627\u0644\u0645\u0635\u063A\u0631\u0629 \u0644\u064A\u062A\u0645 \u0625\u0638\u0647\u0627\u0631\u0647\u0627
-close=\u0627\u063A\u0644\u0627\u0642
+ACCESSIBLE=\u0627\u0644\u0643\u0644 \u064a\u0645\u0643\u0646 \u0627\u0644\u0648\u0635\u0648\u0644 \u0627\u0644\u064a\u0647
+data_element=\u0639\u0646\u0635\u0631 \u0627\u0644\u0628\u064a\u0627\u0646\u0627\u062a
+value=\u0642\u064a\u0645\u0629
+provided_elsewhere=\u0645\u0632\u0648\u062f\u0629 \u0628\u0645\u0643\u0627\u0646 \u0622\u062e\u0631
+expand=\u0648\u0633\u0650\u0639\\u0645\u062f\u0650\u062f
+collapse=\u0627\u0646\u0647\u064a\u0627\u0631
+show_hide_columns=\u0627\u0638\u0647\u0631\\u0627\u062e\u0641\u0650 \u0623\u0639\u0645\u062f\u0629
+select_columns_to_show=\u0627\u062e\u062a\u0631 \u0623\u0639\u0645\u062f\u0629 \u0644\u064a\u062a\u0645 \u0627\u0638\u0647\u0627\u0631\u0647\u0627
+show_hide_widgets=\u0627\u0638\u0647\u0631\\u0627\u062e\u0641\u0650 \u0627\u0644\u062a\u0637\u0628\u064a\u0642\u0627\u062a \u0627\u0644\u0645\u0635\u063a\u0631\u0629
+select_widgets_to_show=\u0627\u062e\u062a\u0631 \u0627\u0644\u062a\u0637\u0628\u064a\u0642\u0627\u062a \u0627\u0644\u0645\u0635\u063a\u0631\u0629 \u0644\u064a\u062a\u0645 \u0625\u0638\u0647\u0627\u0631\u0647\u0627
+close=\u0627\u063a\u0644\u0627\u0642
 generate=\u0627\u0646\u0634\u0627\u0621
 print=\u0637\u0628\u0627\u0639\u0629
-excel_export=\u062A\u0635\u062F\u064A\u0631 \u0627\u0643\u0633\u0644
-list_programs=\u0627\u062F\u0631\u062C \u0627\u0644\u0628\u0631\u0627\u0645\u062C
-program_stage=\u0645\u0631\u062D\u0644\u0629 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062C
-due_date=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u0627\u0633\u062A\u062D\u0642\u0627\u0642
-event_date=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u062D\u062F\u062B
-enable_rescheduling=\u062A\u0645\u0643\u064A\u0646 \u0627\u0639\u0627\u062F\u0629 \u0627\u0644\u062C\u062F\u0648\u0644\u0629
-disable_rescheduling=\u0639\u062F\u0645 \u062A\u0645\u0643\u064A\u0646 \u0627\u0639\u0627\u062F\u0629 \u0627\u0644\u062C\u062F\u0648\u0644\u0629
-show_hide_scheduling=\u0627\u0638\u0647\u0631\\u0627\u062E\u0641\u0650 \u0627\u0633\u062A\u0645\u0627\u0631\u0629 \u0627\u0644\u062C\u062F\u0648\u0644\u0629
-show_hide_messaging=\u0627\u0638\u0647\u0631\\u0627\u062E\u0641\u0650 \u0627\u0633\u062A\u0645\u0627\u0631\u0629 \u0627\u0644\u0631\u0633\u0627\u0626\u0644
+excel_export=\u062a\u0635\u062f\u064a\u0631 \u0627\u0643\u0633\u0644
+list_programs=\u0627\u062f\u0631\u062c \u0627\u0644\u0628\u0631\u0627\u0645\u062c
+program_stage=\u0645\u0631\u062d\u0644\u0629 \u0627\u0644\u0628\u0631\u0646\u0627\u0645\u062c
+due_date=\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0627\u0633\u062a\u062d\u0642\u0627\u0642
+event_date=\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u062d\u062f\u062b
+enable_rescheduling=\u062a\u0645\u0643\u064a\u0646 \u0627\u0639\u0627\u062f\u0629 \u0627\u0644\u062c\u062f\u0648\u0644\u0629
+disable_rescheduling=\u0639\u062f\u0645 \u062a\u0645\u0643\u064a\u0646 \u0627\u0639\u0627\u062f\u0629 \u0627\u0644\u062c\u062f\u0648\u0644\u0629
+show_hide_scheduling=\u0627\u0638\u0647\u0631\\u0627\u062e\u0641\u0650 \u0627\u0633\u062a\u0645\u0627\u0631\u0629 \u0627\u0644\u062c\u062f\u0648\u0644\u0629
+show_hide_messaging=\u0627\u0638\u0647\u0631\\u0627\u062e\u0641\u0650 \u0627\u0633\u062a\u0645\u0627\u0631\u0629 \u0627\u0644\u0631\u0633\u0627\u0626\u0644
 messaging=\u0631\u0633\u0627\u0626\u0644
-scheduling=\u062C\u062F\u0648\u0644\u0629
-reschedule=\u0627\u0639\u0627\u062F\u0629 \u062C\u062F\u0648\u0644\u0629
-rescheduling=\u0627\u0639\u062F \u062C\u062F\u0648\u0644\u0629
-scheduling_messaging=\u0627\u0644\u062C\u062F\u0648\u0644\u0629 \u0648 \u0627\u0644\u0631\u0633\u0627\u0626\u0644
-not_yet_enrolled_scheduling=\u063A\u064A\u0631 \u0645\u0633\u062C\u0644 \u0627\u0644\u0649 \u0627\u0644\u0644\u0622\u0646 . \u0627\u0644\u062C\u062F\u0648\u0644\u0629 \u063A\u064A\u0631 \u0645\u0645\u0643\u0646\u0629
-schedule_details=\u062A\u0641\u0627\u0635\u064A\u0644 \u0627\u0644\u062C\u062F\u0648\u0644
-no_event_to_schedule=\u0644\u0627 \u062A\u0648\u062C\u062F \u0623\u062D\u062F\u0627\u062B \u0644\u062C\u062F\u0648\u0644\u062A\u0647\u0627
-enroll=\u0633\u062C\u064D\u0644
-new_enrollment=\u062A\u0633\u062C\u0628\u0644 \u062C\u062F\u064A\u062F
-start_date=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u062A\u0633\u062C\u064A\u0644
-end_date=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u0627\u0646\u062A\u0647\u0627\u0621
+scheduling=\u062c\u062f\u0648\u0644\u0629
+reschedule=\u0627\u0639\u0627\u062f\u0629 \u062c\u062f\u0648\u0644\u0629
+rescheduling=\u0627\u0639\u062f \u062c\u062f\u0648\u0644\u0629
+scheduling_messaging=\u0627\u0644\u062c\u062f\u0648\u0644\u0629 \u0648 \u0627\u0644\u0631\u0633\u0627\u0626\u0644
+not_yet_enrolled_scheduling=\u063a\u064a\u0631 \u0645\u0633\u062c\u0644 \u0627\u0644\u0649 \u0627\u0644\u0644\u0622\u0646 . \u0627\u0644\u062c\u062f\u0648\u0644\u0629 \u063a\u064a\u0631 \u0645\u0645\u0643\u0646\u0629
+schedule_details=\u062a\u0641\u0627\u0635\u064a\u0644 \u0627\u0644\u062c\u062f\u0648\u0644
+no_event_to_schedule=\u0644\u0627 \u062a\u0648\u062c\u062f \u0623\u062d\u062f\u0627\u062b \u0644\u062c\u062f\u0648\u0644\u062a\u0647\u0627
+enroll=\u0633\u062c\u064d\u0644
+new_enrollment=\u062a\u0633\u062c\u0628\u0644 \u062c\u062f\u064a\u062f
+start_date=\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u062a\u0633\u062c\u064a\u0644
+end_date=\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u0627\u0646\u062a\u0647\u0627\u0621
 from=\u0645\u0646
 to=\u0627\u0644\u0649
-exact_date=\u0627\u0644\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u062F\u0642\u064A\u0642
-exact_value=\u0627\u0644\u0642\u064A\u0645\u0629 \u0627\u0644\u062F\u0642\u064A\u0642\u0629
-EQ=\u0645\u062A\u0633\u0627\u0648\u064A\u0627\u0646 \ \u0645\u062A\u0633\u0627\u0648\u064A\u0648\u0646
-GT=\u0623\u0643\u062B\u0631 \u0645\u0646
-GE=\u0623\u0643\u062B\u0631 \u0645\u0646 \u0627\u0644\u0645\u0633\u0627\u0648\u064A
+exact_date=\u0627\u0644\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u062f\u0642\u064a\u0642
+exact_value=\u0627\u0644\u0642\u064a\u0645\u0629 \u0627\u0644\u062f\u0642\u064a\u0642\u0629
+EQ=\u0645\u062a\u0633\u0627\u0648\u064a\u0627\u0646 \ \u0645\u062a\u0633\u0627\u0648\u064a\u0648\u0646
+GT=\u0623\u0643\u062b\u0631 \u0645\u0646
+GE=\u0623\u0643\u062b\u0631 \u0645\u0646 \u0627\u0644\u0645\u0633\u0627\u0648\u064a
 LT=\u0623\u0642\u0644 \u0645\u0646
-LE=\u0623\u0642\u0644 \u0645\u0646 \u0627\u0644\u0645\u0633\u0627\u0648\u064A
-NE=\u063A\u064A\u0631 \u0645\u0633\u0627\u0648\u064D
-IS=\u064A\u0643\u0648\u0646
+LE=\u0623\u0642\u0644 \u0645\u0646 \u0627\u0644\u0645\u0633\u0627\u0648\u064a
+NE=\u063a\u064a\u0631 \u0645\u0633\u0627\u0648\u064d
+IS=\u064a\u0643\u0648\u0646
 RANGE=\u0646\u0637\u0627\u0642
-like=\u064A\u0634\u0628\u0647
-not_like=\u0644\u0627 \u064A\u0634\u0628\u0647
-boolean=\u0646\u0638\u0627\u0645 \u0627\u0644\u0639\u062F \u0627\u0644\u062B\u0646\u0627\u0626\u064A
+like=\u064a\u0634\u0628\u0647
+not_like=\u0644\u0627 \u064a\u0634\u0628\u0647
+boolean=\u0646\u0638\u0627\u0645 \u0627\u0644\u0639\u062f \u0627\u0644\u062b\u0646\u0627\u0626\u064a
 yes=\u0645\u0648\u0627\u0641\u0642
-no=\u063A\u064A\u0631 \u0645\u0648\u0627\u0641\u0642
-records=\u0633\u062C\u0644\u0627\u062A
-record=\u0633\u062C\u0644
-_record=\u0633\u062C\u0650\u0644
-_records=\u0633\u062C\u0644\u0627\u062A
+no=\u063a\u064a\u0631 \u0645\u0648\u0627\u0641\u0642
+records=\u0633\u062c\u0644\u0627\u062a
+record=\u0633\u062c\u0644
+_record=\u0633\u062c\u0650\u0644
+_records=\u0633\u062c\u0644\u0627\u062a
 found=\u0623\u0633\u0650\u0633
-move_to_selected=\u0627\u0646\u0642\u0644 \u0644\u0644\u0645\u062E\u062A\u0627\u0631/\u0629
-move_all_to_selected=\u0627\u0646\u0642\u0644 \u0627\u0644\u062C\u0645\u064A\u0639 \u0644\u0644\u0645\u062E\u062A\u0627\u0631/\u0629
-new=\u062C\u062F\u064A\u062F
-add_new=\u0627\u0636\u0641 \u062C\u062F\u064A\u062F\u0627\u064B
-register_new=\u0633\u062C\u0650\u0644 \u062C\u062F\u064A\u062F\u0627\u064B
-registration=\u0627\u0644\u062A\u0633\u062C\u064A\u0644
-registration_date=\u062A\u0627\u0631\u064A\u062E \u0627\u0644\u062A\u0633\u062C\u064A\u0644
-register=\u062A\u0633\u062C\u064A\u0644
-_register=\u0633\u062C\u0650\u0644
-registration_error=\u062E\u0637\u0623 \u0641\u064A \u0627\u0644\u062A\u0633\u062C\u064A\u0644
-update_error=\u062E\u0637\u0627\u064B \u0641\u064A \u0627\u0644\u062A\u062D\u062F\u064A\u062B
-event_creation_error=\u062E\u0637\u0623 \u0641\u064A \u0627\u0646\u0634\u0627\u0621 \u0627\u0644\u062D\u062F\u062B
-relationship_error=\u062E\u0637\u0627\u064B \u0641\u064A \u0645\u0647\u0645\u0629 / \u0648\u0638\u064A\u0641\u0629 \u0627\u0644\u0639\u0644\u0627\u0642\u0629
-event_orgunit_name=\u0648\u062D\u062F\u0629 \u0627\u0644\u062A\u0646\u0638\u064A\u0645
+move_to_selected=\u0627\u0646\u0642\u0644 \u0644\u0644\u0645\u062e\u062a\u0627\u0631/\u0629
+move_all_to_selected=\u0627\u0646\u0642\u0644 \u0627\u0644\u062c\u0645\u064a\u0639 \u0644\u0644\u0645\u062e\u062a\u0627\u0631/\u0629
+new=\u062c\u062f\u064a\u062f
+add_new=\u0627\u0636\u0641 \u062c\u062f\u064a\u062f\u0627\u064b
+register_new=\u0633\u062c\u0650\u0644 \u062c\u062f\u064a\u062f\u0627\u064b
+registration=\u0627\u0644\u062a\u0633\u062c\u064a\u0644
+registration_date=\u062a\u0627\u0631\u064a\u062e \u0627\u0644\u062a\u0633\u062c\u064a\u0644
+register=\u062a\u0633\u062c\u064a\u0644
+_register=\u0633\u062c\u0650\u0644
+registration_error=\u062e\u0637\u0623 \u0641\u064a \u0627\u0644\u062a\u0633\u062c\u064a\u0644
+update_error=\u062e\u0637\u0627\u064b \u0641\u064a \u0627\u0644\u062a\u062d\u062f\u064a\u062b
+event_creation_error=\u062e\u0637\u0623 \u0641\u064a \u0627\u0646\u0634\u0627\u0621 \u0627\u0644\u062d\u062f\u062b
+relationship_error=\u062e\u0637\u0627\u064b \u0641\u064a \u0645\u0647\u0645\u0629 / \u0648\u0638\u064a\u0641\u0629 \u0627\u0644\u0639\u0644\u0627\u0642\u0629
+event_orgunit_name=\u0648\u062d\u062f\u0629 \u0627\u0644\u062a\u0646\u0638\u064a\u0645
 category=\u0641\u0626\u0629
-entity_type=\u0646\u0648\u0639 \u0627\u0644\u0643\u064A\u0627\u0646
-save=\u0627\u062D\u0641\u0638
-save_and_add_new=\u0627\u062D\u0641\u0638 \u0648 \u0627\u0636\u0641 \u062C\u062F\u064A\u062F\u0627\u064B
-save_and_go_back=\u0627\u062D\u0641\u0638 \u0648 \u0627\u0631\u062C\u0639 \u0644\u0644\u062E\u0644\u0641
-save_and_continue=\u0627\u062D\u0641\u0638 \u0648 \u0623\u0643\u0645\u0644
-save_relationship=\u0627\u062D\u0641\u0638 \u0627\u0644\u0639\u0644\u0627\u0642\u0629
-go_back=\u0627\u0631\u062C\u0639 \u0644\u0644\u062E\u0644\u0641
-cancel=\u0627\u0644\u063A\u0650
-are_you_sure_to_delete_enrollment=\u0647\u0644 \u0623\u0646\u062A \u0645\u062A\u0623\u0643\u062F \u0645\u0646 \u0623\u0646\u0643 \u062A\u0631\u063A\u0628 \u0641\u064A \u062D\u0630\u0641 \u0639\u0645\u0644\u064A\u0629 \u0627\u0644\u062A\u0633\u062C\u064A\u0644 \u0627\u0644\u0645\u062E\u062A\u0627\u0631\u0629 \u061F
-are_you_sure_to_complete_enrollment=\u0647\u0644 \u0623\u0646\u062A \u0645\u062A\u0623\u0643\u062F \u0645\u0646 \u0623\u0646\u0643 \u062A\u0631\u063A\u0628 \u0641\u064A \u0627\u0643\u0645\u0627\u0644 \u0639\u0645\u0644\u064A\u0629 \u0627\u0644\u062A\u0633\u062C\u064A\u0644 \u0627\u0644\u0645\u062E\u062A\u0627\u0631\u0629 \u061F
-are_you_sure_to_terminate_enrollment=\u0647\u0644 \u0627\u0646\u062A \u0645\u062A\u0623\u0643\u062F \u0645\u0646 \u0623\u0646\u0643 \u062A\u0631\u063A\u0628 \u0641\u064A \u0627\u0646\u0647\u0627\u0621 \u0639\u0645\u0644\u064A\u0629 \u0627\u0644\u062A\u0633\u062C\u064A\u0644 \u0627\u0644\u0645\u062E\u062A\u0627\u0631\u0629 \u061F
-are_you_sure_to_delete_event=\u0647\u0644 \u0623\u0646\u062A \u0645\u062A\u0623\u0643\u062F \u0645\u0646 \u0623\u0646\u0643 \u062A\u0631\u063A\u0628 \u0641\u064A \u062D\u0630\u0641 \u0627\u0644\u062D\u062F\u062B \u0627\u0644\u0645\u062E\u062A\u0627\u0631 \u061F
-are_you_sure_to_complete_event=\u0647\u0644 \u0623\u0646\u062A \u0645\u062A\u0623\u0643\u062F \u0645\u0646 \u0623\u0646\u0643 \u062A\u0631\u063A\u0628 \u0641\u064A \u0627\u0643\u0645\u0627\u0644 \u0627\u0644\u062D\u062F\u062B \u0627\u0644\u0645\u062E\u062A\u0627\u0631 \u061F
-are_you_sure_to_incomplete_event=\u0647\u0644 \u0623\u0646\u062A \u0645\u062A\u0623\u0643\u062F \u0645\u0646 \u0623\u0646\u0643 \u062A\u0631\u063A\u0628 \u0641\u064A \u0639\u062F\u0645 \u0627\u0643\u0645\u0627\u0644 \u0627\u0644\u062D\u062F\u062B \u0627\u0644\u0645\u062E\u062A\u0627\u0631 \u061F
-are_you_sure_to_skip_event=\u0647\u0644 \u0623\u0646\u062A \u0645\u062A\u0623\u0643\u062F \u0645\u0646 \u0623\u0646\u0643 \u062A\u0631\u063A\u0628 \u0641\u064A \u062A\u062E\u0637\u064A \u0627\u0644\u062D\u062F\u062B \u0627\u0644\u0645\u062E\u062A\u0627\u0631 \u061F
-are_you_sure_to_unskip_event=\u0647\u0644 \u0623\u0646\u062A \u0645\u062A\u0623\u0643\u062F \u0645\u0646 \u0623\u0646\u0643 \u062A\u0631\u063A\u0628 \u0641\u064A \u062C\u062F\u0648\u0644\u0629 \u0627\u0644\u062D\u062F\u062B \u0627\u0644\u0645\u062E\u062A\u0627\u0631 \u0644\u0644\u0633\u0627\u0628\u0642 \u061F
-more=\u0645\u0632\u064A\u062F
-under_construction=\u0645\u0627\u0632\u0627\u0644 \u0642\u064A\u062F \u0627\u0644\u0627\u0646\u0634\u0627\u0621
-advanced_search=\u0628\u062D\u062B \u0645\u062A\u0642\u062F\u0645
-profile=\u062A\u0634\u0643\u064A\u0644 \u062C\u0627\u0646\u0628\u064A
-applications=\u0628\u0631\u0627\u0645\u062C
-more_applications=\u0645\u0632\u064A\u062F \u0645\u0646 \u0627\u0644\u0628\u0631\u0627\u0645\u062C
+entity_type=\u0646\u0648\u0639 \u0627\u0644\u0643\u064a\u0627\u0646
+save=\u0627\u062d\u0641\u0638
+save_and_add_new=\u0627\u062d\u0641\u0638 \u0648 \u0627\u0636\u0641 \u062c\u062f\u064a\u062f\u0627\u064b
+save_and_go_back=\u0627\u062d\u0641\u0638 \u0648 \u0627\u0631\u062c\u0639 \u0644\u0644\u062e\u0644\u0641
+save_and_continue=\u0627\u062d\u0641\u0638 \u0648 \u0623\u0643\u0645\u0644
+save_relationship=\u0627\u062d\u0641\u0638 \u0627\u0644\u0639\u0644\u0627\u0642\u0629
+go_back=\u0627\u0631\u062c\u0639 \u0644\u0644\u062e\u0644\u0641
+cancel=\u0627\u0644\u063a\u0650
+are_you_sure_to_delete_enrollment=\u0647\u0644 \u0623\u0646\u062a \u0645\u062a\u0623\u0643\u062f \u0645\u0646 \u0623\u0646\u0643 \u062a\u0631\u063a\u0628 \u0641\u064a \u062d\u0630\u0641 \u0639\u0645\u0644\u064a\u0629 \u0627\u0644\u062a\u0633\u062c\u064a\u0644 \u0627\u0644\u0645\u062e\u062a\u0627\u0631\u0629 \u061f
+are_you_sure_to_complete_enrollment=\u0647\u0644 \u0623\u0646\u062a \u0645\u062a\u0623\u0643\u062f \u0645\u0646 \u0623\u0646\u0643 \u062a\u0631\u063a\u0628 \u0641\u064a \u0627\u0643\u0645\u0627\u0644 \u0639\u0645\u0644\u064a\u0629 \u0627\u0644\u062a\u0633\u062c\u064a\u0644 \u0627\u0644\u0645\u062e\u062a\u0627\u0631\u0629 \u061f
+are_you_sure_to_terminate_enrollment=\u0647\u0644 \u0627\u0646\u062a \u0645\u062a\u0623\u0643\u062f \u0645\u0646 \u0623\u0646\u0643 \u062a\u0631\u063a\u0628 \u0641\u064a \u0627\u0646\u0647\u0627\u0621 \u0639\u0645\u0644\u064a\u0629 \u0627\u0644\u062a\u0633\u062c\u064a\u0644 \u0627\u0644\u0645\u062e\u062a\u0627\u0631\u0629 \u061f
+are_you_sure_to_delete_event=\u0647\u0644 \u0623\u0646\u062a \u0645\u062a\u0623\u0643\u062f \u0645\u0646 \u0623\u0646\u0643 \u062a\u0631\u063a\u0628 \u0641\u064a \u062d\u0630\u0641 \u0627\u0644\u062d\u062f\u062b \u0627\u0644\u0645\u062e\u062a\u0627\u0631 \u061f
+are_you_sure_to_complete_event=\u0647\u0644 \u0623\u0646\u062a \u0645\u062a\u0623\u0643\u062f \u0645\u0646 \u0623\u0646\u0643 \u062a\u0631\u063a\u0628 \u0641\u064a \u0627\u0643\u0645\u0627\u0644 \u0627\u0644\u062d\u062f\u062b \u0627\u0644\u0645\u062e\u062a\u0627\u0631 \u061f
+are_you_sure_to_incomplete_event=\u0647\u0644 \u0623\u0646\u062a \u0645\u062a\u0623\u0643\u062f \u0645\u0646 \u0623\u0646\u0643 \u062a\u0631\u063a\u0628 \u0641\u064a \u0639\u062f\u0645 \u0627\u0643\u0645\u0627\u0644 \u0627\u0644\u062d\u062f\u062b \u0627\u0644\u0645\u062e\u062a\u0627\u0631 \u061f
+are_you_sure_to_skip_event=\u0647\u0644 \u0623\u0646\u062a \u0645\u062a\u0623\u0643\u062f \u0645\u0646 \u0623\u0646\u0643 \u062a\u0631\u063a\u0628 \u0641\u064a \u062a\u062e\u0637\u064a \u0627\u0644\u062d\u062f\u062b \u0627\u0644\u0645\u062e\u062a\u0627\u0631 \u061f
+are_you_sure_to_unskip_event=\u0647\u0644 \u0623\u0646\u062a \u0645\u062a\u0623\u0643\u062f \u0645\u0646 \u0623\u0646\u0643 \u062a\u0631\u063a\u0628 \u0641\u064a \u062c\u062f\u0648\u0644\u0629 \u0627\u0644\u062d\u062f\u062b \u0627\u0644\u0645\u062e\u062a\u0627\u0631 \u0644\u0644\u0633\u0627\u0628\u0642 \u061f
+more=\u0645\u0632\u064a\u062f
+under_construction=\u0645\u0627\u0632\u0627\u0644 \u0642\u064a\u062f \u0627\u0644\u0627\u0646\u0634\u0627\u0621
+advanced_search=\u0628\u062d\u062b \u0645\u062a\u0642\u062f\u0645
+profile=\u062a\u0634\u0643\u064a\u0644 \u062c\u0627\u0646\u0628\u064a
+applications=\u0628\u0631\u0627\u0645\u062c
+more_applications=\u0645\u0632\u064a\u062f \u0645\u0646 \u0627\u0644\u0628\u0631\u0627\u0645\u062c
 settings=\u0636\u0628\u0637
-account=\u062D\u0633\u0627\u0628
-help=\u0645\u0633\u0627\u0639\u062F\u0629
-log_out=\u062A\u0633\u062C\u064A\u0644 \u062E\u0631\u0648\u062C
-about_dhis2=\u062D\u0648\u0644 DHIS 2
+account=\u062d\u0633\u0627\u0628
+help=\u0645\u0633\u0627\u0639\u062f\u0629
+log_out=\u062a\u0633\u062c\u064a\u0644 \u062e\u0631\u0648\u062c
+about_dhis2=\u062d\u0648\u0644 DHIS 2

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/index.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/index.html	2015-06-02 12:25:03 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/index.html	2015-06-10 11:55:41 +0000
@@ -114,6 +114,7 @@
         <script type="text/javascript" src="components/relationship/relationship-controller.js"></script>        
         <script type="text/javascript" src="components/profile/profile-controller.js"></script>        
         <script type="text/javascript" src="components/notes/notes-controller.js"></script>
+        <script type="text/javascript" src="components/rulebound/rulebound-controller.js"></script>
 
         <!-- Menu scripts -->
         <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.translate.js"></script>

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/services.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/services.js	2015-06-10 11:58:22 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/services.js	2015-06-10 13:45:11 +0000
@@ -10,7 +10,7 @@
     var store = new dhis2.storage.Store({
         name: "dhis2tc",
         adapters: [dhis2.storage.IndexedDBAdapter, dhis2.storage.DomSessionStorageAdapter, dhis2.storage.InMemoryAdapter],
-        objectStores: ['programs', 'programStages', 'trackedEntities', 'trackedEntityForms', 'attributes', 'relationshipTypes', 'optionSets', 'programValidations', 'ouLevels']
+        objectStores: ['programs', 'programStages', 'trackedEntities', 'trackedEntityForms', 'attributes', 'relationshipTypes', 'optionSets', 'programValidations', 'ouLevels', 'programRuleVariables', 'programRules', 'programRuleActions']
     });
     return{
         currentStore: store
@@ -1065,6 +1065,128 @@
     };  
 })
 
+    /* Returns a function for getting rules for a specific program */
+.factory('TrackerRulesFactory', function($q,$rootScope,TCStorageService){
+    return{
+        getOldProgramStageRules :function(programUid, programstageUid) {
+            var rules = this.getProgramRules(programUid);
+            
+            //Only keep the rules actually matching the program stage we are in, or rules with no program stage defined.
+            var programStageRules = [];
+            angular.forEach(rules, function(rule) {
+                if(rule.programstage_uid == null || rule.programstage_uid == "" || rule.programstage_uid == programstageUid) {
+                   programStageRules.push(rule);
+                }
+            });
+            
+            return programStageRules;
+        },
+        
+        getProgramStageRules : function(programUid, programStageUid){
+            var def = $q.defer();
+            
+            TCStorageService.currentStore.open().done(function(){
+                TCStorageService.currentStore.getAll('programRules').done(function(rules){ 
+                    TCStorageService.currentStore.getAll('programRuleActions').done(function(actions){
+                        //The hash will serve as a direct-lookup for linking the actions to rules later.
+                        var programRulesHash = {};
+                        //The array will ultimately be returned to the caller.
+                        var programRulesArray = [];
+                        //Loop through and add the rules belonging to this program and program stage
+                        angular.forEach(rules, function(rule){
+                           if(rule.program.id == programUid) {
+                               if(!rule.programStage || !rule.programStage.id || rule.programStage.id == programStageUid) {
+                                    rule.actions = [];
+                                    programRulesHash[rule.id] = rule;
+                                    programRulesArray.push(rule);
+                                }
+                           }
+                        });
+                        
+                        //Loop through and attach all actions to the correct rules:
+                        angular.forEach(actions, function(action){
+                           if(programRulesHash[action.programRule.id])
+                           {
+                               programRulesHash[action.programRule.id].actions.push(action);
+                           }
+                        });
+                        
+                        $rootScope.$apply(function(){
+                            def.resolve(programRulesArray);
+                        });
+                    });
+                });     
+            });
+                        
+            return def.promise;
+        }
+    };  
+})
+
+/* Returns user defined variable names and their corresponding UIDs and types for a specific program */
+.factory('TrackerRuleVariableFactory', function($rootScope, $q, TCStorageService){
+    return{
+        getProgramRuleVariables : function(programUid){
+            var def = $q.defer();
+            
+            TCStorageService.currentStore.open().done(function(){
+                
+                TCStorageService.currentStore.getAll('programRuleVariables').done(function(variables){
+                    
+                    //The array will ultimately be returned to the caller.
+                    var programRuleVariablesArray = [];
+                    //Loop through and add the variables belonging to this program
+                    angular.forEach(variables, function(variable){
+                       if(variable.program.id == programUid) {
+                            programRuleVariablesArray.push(variable);
+                       }
+                    });
+
+                    $rootScope.$apply(function(){
+                        def.resolve(programRuleVariablesArray);
+                    });
+                });
+            });
+                        
+            return def.promise;
+        }
+    };
+})
+
+/* Returns user defined variable names and their corresponding UIDs and types for a specific program */
+.factory('TrackerWidgetsConfigurationFactory', function(){
+    return{
+        getWidgetConfiguration : function(programUid){
+            //If no config exists, return default config
+            
+            return [
+                {title: 'Details', type: 'rulebound', code:"det", show: true, expand: true, horizontalplacement:"left", index:0},
+                {title: 'enrollment', type:'enrollment', show: false, expand: true, horizontalplacement:"left", index:1},
+                {title: 'dataentry', type: 'dataentry', show: true, expand: true, horizontalplacement:"left", index:2},
+                {title: 'report', type: 'report', show: false, expand: true, horizontalplacement:"left", index:3},
+                {title: 'current_selections', type: 'current_selections', show: false, expand: true, horizontalplacement:"right", index:0},
+                {title: 'profile', type: 'profile', show: false, expand: true, horizontalplacement:"right", index:1},
+                {title: 'Conditions/Complications',  type:'rulebound', code:"con", show: true, expand: true, horizontalplacement:"right", index:2},
+                {title: 'relationships', type: 'relationships', show: false, expand: true, horizontalplacement:"right", index:3},
+                {title: 'notes', type: 'notes', show: true, expand: true, horizontalplacement:"right", index:4},
+                {title: 'Summary', type: 'rulebound', code:"sum", show: true, expand: true, horizontalplacement:"left", index:4}
+            ];
+        },
+        getDefaultWidgetConfiguration: function() {
+            return [
+                {title: 'enrollment', type:'enrollment', show: true, expand: true, horizontalplacement:"left", index:0},
+                {title: 'dataentry', type: 'dataentry', show: true, expand: true, horizontalplacement:"left", index:1},
+                {title: 'report', type: 'report', show: true, expand: true, horizontalplacement:"left", index:2},
+                {title: 'current_selections', type: 'current_selections', show: false, expand: true, horizontalplacement:"right", index:0},
+                {title: 'profile', type: 'profile', show: true, expand: true, horizontalplacement:"right", index:1},
+                {title: 'relationships', type: 'relationships', show: true, expand: true, horizontalplacement:"right", index:2},
+                {title: 'notes', type: 'notes', show: true, expand: true, horizontalplacement:"right", index:3}
+            ];
+        }
+    };
+            
+})
+
 .service('EntityQueryFactory', function(OperatorFactory, DateUtils){  
     
     this.getAttributesQuery = function(attributes, enrollment){
@@ -1650,5 +1772,476 @@
             }
             return event;
         }
+    }; 
+})
+
+/* service for building variables based on the data in users fields */
+.service('VariableService', function($rootScope,$q,TrackerRuleVariableFactory,$filter,orderByFilter,$log){
+    return {
+        getVariables: function($scope) {
+            var thePromisedVariables = $q.defer();
+            var variables = [];
+            
+            $scope.pushVariable = function(variablename, variablevalue, variabletype, variablefound) {
+                //First clean away single or double quotation marks at the start and end of the variable name.
+                variablevalue = $filter('trimquotes')(variablevalue);
+                
+                //Append single quotation marks in case the variable is of text type:
+                if(variabletype === 'string') {
+                    variablevalue = "'" + variablevalue + "'";
+                }
+                else if(variabletype === 'date') {
+                    variablevalue = "'" + variablevalue + "'";
+                }
+                else if(variabletype === 'bool' || variabletype === 'trueOnly') {
+                    if(eval(variablevalue)) {
+                        variablevalue = true;
+                    }
+                    else {    
+                        variablevalue = false;
+                    }
+                }
+                else if(variabletype === "int" || variabletype === "number") {
+                    variablevalue = Number(variablevalue);
+                }
+                else{
+                    $log.warn("unknown datatype:" + variabletype);
+                }
+                 
+                
+                //Make sure that the variablevalue does not contain a dollar sign anywhere 
+                //- this would potentially mess up later use of the variable:
+//                if(angular.isDefined(variablevalue) 
+//                        && variablevalue !== null
+//                        && variablevalue.indexOf("$") !== -1 ) {
+//                    variablevalue = variablevalue.replace(/\\$/,"");
+//                }
+                
+                //TODO:
+                //Also clean away instructions that might be erroneusly evalutated in javascript
+
+                variables.push({variablename:variablename,
+                                variablevalue:variablevalue,
+                                variabletype:variabletype,
+                                hasValue:variablefound
+                            });
+            };
+            
+            TrackerRuleVariableFactory.getProgramRuleVariables($scope.currentEvent.program).then(function(programVariables){
+
+                // The following section will need a different implementation for event capture:
+                var allEventsSorted = [];
+                var currentEvent = $scope.currentEvent;
+                var eventsSortedPerProgramStage = [];
+                
+                for(var key in $scope.eventsByStage){
+                    if($scope.eventsByStage.hasOwnProperty(key)){
+                        eventsSortedPerProgramStage[key] = [];
+                        angular.forEach($scope.eventsByStage[key], function(event){
+                            allEventsSorted.push(event);
+                            eventsSortedPerProgramStage[key].push(event);
+                        });
+                        eventsSortedPerProgramStage[key] = orderByFilter(eventsSortedPerProgramStage[key], '-sortingDate').reverse(); 
+                    }
+                }
+                allEventsSorted = orderByFilter(allEventsSorted, '-sortingDate').reverse(); 
+                
+                var allDes = {};
+                angular.forEach($scope.programStages, function(programStage){
+                    angular.forEach(programStage.programStageDataElements, function(dataElement) {
+                        allDes[dataElement.dataElement.id] = dataElement;
+                    });
+                });
+                //End of region that neeeds specific implementation for event capture
+                
+                angular.forEach(programVariables, function(programVariable) {
+                    var valueFound = false;
+                    if(programVariable.programRuleVariableSourceType === "DATAELEMENT_NEWEST_EVENT_PROGRAM_STAGE"){
+                        if(programVariable.programStage) {
+                            angular.forEach(eventsSortedPerProgramStage[programVariable.programStage.id], function(event) {
+                                if(angular.isDefined(event[programVariable.dataElement.id])
+                                        && event[programVariable.dataElement.id] !== null ){
+                                    valueFound = true;
+                                    $scope.pushVariable(programVariable.name, event[programVariable.dataElement.id], allDes[programVariable.dataElement.id].dataElement.type, valueFound );
+                                }
+                            });
+                        } else {
+                            $log.warn("Variable id:'" + programVariable.id + "' name:'" + programVariable.name 
+                                    + "' does not have a programstage defined,"
+                                    + " despite that the variable has sourcetype DATAELEMENT_NEWEST_EVENT_PROGRAM_STAGE" );
+                        }
+                        
+                    }
+                    else if(programVariable.programRuleVariableSourceType === "DATAELEMENT_NEWEST_EVENT_PROGRAM"){
+                        angular.forEach(allEventsSorted, function(event) {
+                            if(angular.isDefined(event[programVariable.dataElement.id])
+                                    && event[programVariable.dataElement.id] !== null ){
+                                valueFound = true;
+                                 $scope.pushVariable(programVariable.name, event[programVariable.dataElement.id], allDes[programVariable.dataElement.id].dataElement.type, valueFound );
+                             }
+                        });
+                    }
+                    else if(programVariable.programRuleVariableSourceType === "DATAELEMENT_CURRENT_EVENT"){
+                        if(angular.isDefined(currentEvent[programVariable.dataElement.id])
+                                && currentEvent[programVariable.dataElement.id] !== null ){
+                            valueFound = true;
+                            $scope.pushVariable(programVariable.name, currentEvent[programVariable.dataElement.id], allDes[programVariable.dataElement.id].dataElement.type, valueFound );
+                        }      
+                    }
+                    else if(programVariable.programRuleVariableSourceType === "DATAELEMENT_PREVIOUS_EVENT"){
+                        //Only continue checking for a value if there is more than one event.
+                        if(allEventsSorted && allEventsSorted.length > 1) {
+                            var previousvalue = null;
+                            var currentEventPassed = false;
+                            for(var i = 0; i < allEventsSorted.length; i++) {
+                                //Store the values as we iterate through the stages
+                                //If the event[i] is not the current event, it is older(previous). Store the previous value if it exists
+                                if(!currentEventPassed && allEventsSorted[i] !== currentEvent && 
+                                        angular.isDefined(allEventsSorted[i][programVariable.dataElement.id])) {
+                                    previousvalue = allEventsSorted[i][programVariable.dataElement.id];
+                                    valueFound = true;
+                                }
+                                else if(allEventsSorted[i] === currentEvent) {
+                                    //We have iterated to the newest event - store the last collected variable value - if any is found:
+                                    if(valueFound) {
+                                        $scope.pushVariable(programVariable.name, previousvalue, allDes[programVariable.dataElement.id].dataElement.type, valueFound );
+                                    }
+                                    //Set currentEventPassed, ending the iteration:
+                                    currentEventPassed = true;
+                                }
+                                
+                            }
+                        }
+                    }
+                    else if(programVariable.programRuleVariableSourceType === "TEI_ATTRIBUTE"){
+                        angular.forEach($scope.selectedEntity.attributes , function(attribute) {
+                            if(!valueFound) {
+                                if(attribute.attribute === programVariable.trackedEntityAttribute.id) {
+                                    valueFound = true;
+                                    $scope.pushVariable(programVariable.name, attribute.value, attribute.type, valueFound );
+                                }
+                            }
+                        });
+                    }
+                    else if(programVariable.programRuleVariableSourceType === "CALCULATED_VALUE"){
+                        //We won't assign the calculated variables at this step. The rules execution will calculate and assign the variable.
+                    }
+                    else if(programVariable.programRuleVariableSourceType === "NUMBEROFEVENTS_PROGRAMSTAGE"){
+                        var numberOfEvents = 0;
+                        if( programVariable.programStage && eventsSortedPerProgramStage[programVariable.programStage.id] ) {
+                            numberOfEvents = eventsSortedPerProgramStage[programVariable.programStage.id].length;
+                        }
+                        valueFound = true;
+                        $scope.pushVariable(programVariable.name, numberOfEvents, 'int', valueFound );
+                    }
+                    else {
+                        //Missing handing of ruletype
+                        $log.warn("Unknown programRuleVariableSourceType:" + programVariable.programRuleVariableSourceType);
+                    }
+
+                   
+                    if(!valueFound){
+                        //If there is still no value found, assign default value:
+                        if(programVariable.dataElement) {
+                            var dataElement = allDes[programVariable.dataElement.id];
+                            if( dataElement ) {
+                                $scope.pushVariable(programVariable.name, "", dataElement.dataElement.type );
+                            } 
+                            else {
+                                $log.warn("Variable #{" + programVariable.name + "} is linked to a dataelement that is not part of the program");
+                                $scope.pushVariable(programVariable.name, "", "string" );
+                            }
+                        }
+                        else {
+                            $scope.pushVariable(programVariable.name, "", "string" );
+                        }
+                    }
+                });
+
+                //add context variables:
+                //last parameter "valuefound" is always true for event date
+                $scope.pushVariable('eventdate', currentEvent.eventDate, 'date', true );
+                
+                thePromisedVariables.resolve(variables);
+            });
+            
+            return thePromisedVariables.promise;
+        }
+    };
+})
+       
+
+
+/* service for executing tracker rules and broadcasting results */
+.service('TrackerRulesExecutionService', function(TrackerRulesFactory,VariableService, $rootScope, $log, $filter, orderByFilter){
+    return {
+        executeRules: function($scope) {
+            //When debugging rules, the caller should provide a variable for wether or not the rules is being debugged.
+            //hard coding this for now:
+            var debug = true;
+            var verbose = true;
+            
+            var variablesHash = {};
+            var variablesWithValueHash = {};
+                    
+            $scope.replaceVariables = function(expression) {
+                //replaces the variables in an expression with actual variable values.
+                //First check if the expression contains variables at all(any dollar signs):
+                if(expression.indexOf('#') !== -1) {
+                    //Find every variable name in the expression;
+                    var variablespresent = expression.match(/#{\w+}/g);
+                    //Replace each matched variable:
+                    angular.forEach(variablespresent, function(variablepresent) {
+                        //First strip away any dollar signs from the variable name:
+                        variablepresent = variablepresent.replace("#{","").replace("}","");
+                        
+                        if(angular.isDefined(variablesHash[variablepresent])) {
+                            //Replace all occurrences of the variable name(hence using regex replacement):
+                            expression = expression.replace(new RegExp("#{" + variablepresent + "}", 'g'),
+                                variablesHash[variablepresent]);
+                        }
+                        else {
+                            $log.warn("Expression " + expression + " conains variable " + variablepresent 
+                                    + " - but this variable is not defined." );
+                        }
+                            
+                    });
+                }
+                return expression;
+            };
+            
+            $scope.runDhisFunctions = function(expression) {
+                //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.floor",parameters:1},
+                                        {name:"dhis.modulus",parameters:2},
+                                        {name:"dhis.hasValue",parameters:1},
+                                        {name:"dhis.concatenate"}];
+                    
+                    angular.forEach(dhisFunctions, function(dhisFunction){
+                        //Replace each * with a regex that matches each parameter, allowing commas only inside single quotation marks.
+                        var regularExFunctionCall = new RegExp(dhisFunction.name.replace(".","\\.") + "\\([^\\)]*\\)",'g');
+                        var callsToThisFunction = expression.match(regularExFunctionCall);
+                        angular.forEach(callsToThisFunction, function(callToThisFunction){
+                            //Remove the function name and paranthesis:
+                            var justparameters = callToThisFunction.replace(/(^[^\(]+\()|\)$/g,"");
+                            //Then split into single parameters:
+                            var parameters = justparameters.match(/(('[^']+')|([^,]+))/g);
+                            
+                            //Show error if no parameters is given and the function requires parameters,
+                            //or if the number of parameters is wrong.
+                            if(angular.isDefined(dhisFunction.parameters)){
+                                //But we are only checking parameters where the dhisFunction actually has a defined set of parameters(concatenate, for example, does not have a fixed number);
+                                if((!angular.isDefined(parameters) && dhisFunction.parameters > 0)
+                                        || parameters.length !== dhisFunction.parameters){
+                                    $log.warn(dhisFunction.name + " was called with the incorrect number of parameters");
+                                }
+                            }
+
+                            //In case the function call is nested, the parameter itself contains an expression, run the expression.
+                            if(angular.isDefined(parameters)) {
+                                for (var i = 0; i < parameters.length; i++) {
+                                    parameters[i] = $scope.runExpression(parameters[i],dhisFunction.name,"parameter:" + i);
+                                }
+                            }
+
+                            //Special block for dhis.weeksBetween(*,*) - add such a block for all other dhis functions.
+                            if(dhisFunction.name === "dhis.daysbetween")
+                            {
+                                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,'days'));
+                            }
+                            else if(dhisFunction.name === "dhis.floor")
+                            {
+                                var floored = Math.floor(parameters[0]);
+                                //Replace the end evaluation of the dhis function:
+                                expression = expression.replace(callToThisFunction, floored);
+                            }
+                            else if(dhisFunction.name === "dhis.modulus")
+                            {
+                                var dividend = Number(parameters[0]);
+                                var divisor = Number(parameters[1]);
+                                var rest = dividend % divisor;
+                                //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(variablesWithValueHash[parameters[0]]){
+                                    expression = expression.replace(callToThisFunction, 'true');
+                                } else {
+                                    expression = expression.replace(callToThisFunction, 'false');
+                                }
+                            }
+                            else if(dhisFunction.name === "dhis.concatenate")
+                            {
+                                var returnString = "'";
+                                for (var i = 0; i < parameters.length; i++) {
+                                    returnString += parameters[i];
+                                }
+                                returnString += "'";
+                                expression = expression.replace(callToThisFunction, returnString);
+                            }
+                        });
+                    });
+                }
+                
+                return expression;
+            };
+            
+            $scope.runExpression = function(expression, beforereplacement, identifier ){
+                //determine if expression is true, and actions should be effectuated
+                //If DEBUG mode, use try catch and report errors. If not, omit the heavy try-catch loop.:
+                var answer = false;
+                if(debug) {
+                    try{
+                        
+                        var dhisfunctionsevaluated = $scope.runDhisFunctions(expression);
+                        answer = eval(dhisfunctionsevaluated);
+
+                        if(verbose)
+                        {
+                            $log.info("Expression with id " + identifier + " was successfully run. Original condition was: " + beforereplacement + " - Evaluation ended up as:" + expression + " - Result of evaluation was:" + answer);
+                        }
+                    }
+                    catch(e)
+                    {
+                        $log.warn("Expression with id " + identifier + " could not be run. Original condition was: " + beforereplacement + " - Evaluation ended up as:" + expression + " - error message:" + e);
+                    }
+                }
+                else {
+                    //Just run the expression. This is much faster than the debug route: http://jsperf.com/try-catch-block-loop-performance-comparison
+                    var dhisfunctionsevaluated = $scope.runDhisFunctions(expression);
+                    answer = eval(dhisfunctionsevaluated);
+                }
+                return answer;
+            };
+            
+            
+            VariableService.getVariables($scope).then(function(variables){
+                TrackerRulesFactory.getProgramStageRules($scope.selectedProgram.id, $scope.currentStage.id).then(function(rules){
+                    //But run rules in priority - lowest number first(priority null is last)
+                    rules = orderByFilter(rules, 'priority');
+
+                    //Make a variables hash to allow direct lookup:
+                    angular.forEach(variables, function(variable) {
+                        variablesHash[variable.variablename] = variable.variablevalue;
+                    });
+                    
+                    //Make a variables-exists/hasvalue hash to allow direct lookup:
+                    angular.forEach(variables, function(variable) {
+                        variablesWithValueHash[variable.variablename] = variable.hasValue;
+                    });
+
+                    if(angular.isObject(rules) && angular.isArray(rules)){
+                        //The program has rules, and we want to run them.
+                        //Prepare repository unless it is already prepared:
+                        if(angular.isUndefined( $rootScope.ruleeffects )){
+                            $rootScope.ruleeffects = {};
+                        }
+
+                        var updatedEffectsExits = false;
+
+                        angular.forEach(rules, function(rule) {
+                            var ruleEffective = false;
+
+                            var expression = rule.condition;
+                            //Go through and populate variables with actual values, but only if there actually is any replacements to be made(one or more "$" is present)
+                            if(expression) {
+                                if(expression.indexOf('#') !== -1) {
+                                    expression = $scope.replaceVariables(expression);
+                                }
+                                //run expression:
+                                ruleEffective = $scope.runExpression(expression, rule.condition, "rule:" + rule.id);
+                            } else {
+                                $log.warn("Rule id:'" + rule.id + "'' and name:'" + rule.name + "' had no condition specified. Please check rule configuration.");
+                            }
+                            
+                            angular.forEach(rule.actions, function(action){
+                                //In case the effect-hash is not populated, add entries
+                                if(angular.isUndefined( $rootScope.ruleeffects[action.id] )){
+                                    $rootScope.ruleeffects[action.id] =  {
+                                        id:action.id,
+                                        location:action.location, 
+                                        action:action.programRuleActionType,
+                                        dataElement:action.dataElement,
+                                        content:action.content,
+                                        data:action.data,
+                                        ineffect:false
+                                    };
+                                }
+
+                                //In case the rule is effective and contains specific data, 
+                                //the effect be refreshed from the variables list.
+                                //If the rule is not effective we can skip this step
+                                if(ruleEffective && action.data)
+                                {
+                                    //The key data might be containing a dollar sign denoting that the key data is a variable.
+                                    //To make a lookup in variables hash, we must make a lookup without the dollar sign in the variable name
+                                    //The first strategy is to make a direct lookup. In case the "data" expression is more complex, we have to do more replacement and evaluation.
+
+                                    var nameWithoutDollarSign = action.data.replace('#{','').replace('}','');
+                                    if(angular.isDefined(variablesHash[nameWithoutDollarSign]))
+                                    {
+                                        //The variable exists, and is replaced with its corresponding value
+                                        $rootScope.ruleeffects[action.id].data =
+                                            variablesHash[nameWithoutDollarSign];
+                                    }
+                                    else if(action.data.indexOf('#') !== -1)
+                                    {
+                                        //Since the value couldnt be looked up directly, and contains a dollar sign, the expression was more complex
+                                        //Now we will have to make a thorough replacement and separate evaluation to find the correct value:
+                                        $rootScope.ruleeffects[action.id].data = $scope.replaceVariables(action.data);
+                                        //In a scenario where the data contains a complex expression, evaluate the expression to compile(calculate) the result:
+                                        $rootScope.ruleeffects[action.id].data = $scope.runExpression($rootScope.ruleeffects[action.id].data, action.data, "action:" + action.id);
+                                    }
+                                }
+
+                                //Update the rule effectiveness if it changed in this evaluation;
+                                if($rootScope.ruleeffects[action.id].ineffect != ruleEffective)
+                                {
+                                    //There is a change in the rule outcome, we need to update the effect object.
+                                    updatedEffectsExits = true;
+                                    $rootScope.ruleeffects[action.id].ineffect = ruleEffective;
+                                }
+
+                                //In case the rule is of type "assign variable" and the rule is effective,
+                                //the variable data result needs to be applied to the correct variable:
+                                if($rootScope.ruleeffects[action.id].action === "ASSIGNVARIABLE" && $rootScope.ruleeffects[action.id].ineffect){
+                                    //from earlier evaluation, the data portion of the ruleeffect now contains the value of the variable to be assign.
+                                    //the content portion of the ruleeffect defines the name for the variable, when dollar is removed:
+                                    var variabletoassign = $rootScope.ruleeffects[action.id].content.replace("#{","").replace("}","");
+
+                                    if(!angular.isDefined(variablesHash[variabletoassign])){
+                                        $log.warn("Variable " + variabletoassign + " was not defined.");
+                                    }
+
+                                    //Even if the variable is not defined: we assign it:
+                                    if(variablesHash[variabletoassign] !== $rootScope.ruleeffects[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:
+                                        variablesHash[variabletoassign] = $rootScope.ruleeffects[action.id].data;
+                                    }
+                                }
+                            });
+                        });
+
+                        //Broadcast rules finished if there was any actual changes.
+                        if(updatedEffectsExits){
+                            $rootScope.$broadcast("ruleeffectsupdated");
+                        }
+                    }
+
+                    return true;
+                });
+            });
+        }
     };
 });

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/tracker-capture.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/tracker-capture.js	2015-06-11 09:09:20 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/tracker-capture.js	2015-06-11 18:44:52 +0000
@@ -29,7 +29,7 @@
 dhis2.tc.store = new dhis2.storage.Store({
     name: 'dhis2tc',
     adapters: [dhis2.storage.IndexedDBAdapter, dhis2.storage.DomSessionStorageAdapter, dhis2.storage.InMemoryAdapter],
-    objectStores: ['programs', 'programStages', 'trackedEntities', 'trackedEntityForms', 'attributes', 'relationshipTypes', 'optionSets', 'programValidations', 'ouLevels']      
+    objectStores: ['programs', 'programStages', 'trackedEntities', 'trackedEntityForms', 'attributes', 'relationshipTypes', 'optionSets', 'programValidations', 'ouLevels', 'programRuleVariables', 'programRules', 'programRuleActions']      
 });
 
 (function($) {
@@ -141,6 +141,12 @@
     promise = promise.then( getMetaTrackeEntityAttributes );
     promise = promise.then( getTrackedEntityAttributes );
     promise = promise.then( getOptionSetsForAttributes );
+    promise = promise.then( getMetaProgramRuleVariables );
+    promise = promise.then( getProgramRuleVariables );
+    promise = promise.then( getMetaProgramRules );
+    promise = promise.then( getProgramRules );
+    promise = promise.then( getMetaProgramRuleActions );
+    promise = promise.then( getProgramRuleActions );
     promise = promise.then( getMetaProgramValidations );
     promise = promise.then( getProgramValidations );    
     promise = promise.then( getTrackedEntityForms );
@@ -490,6 +496,335 @@
     };
 }
 
+function getMetaProgramRuleActions( data )
+{
+    if( !data ){
+        return;
+    }
+    
+    var def = $.Deferred();
+    
+    var programRuleIds = [];
+    _.each( _.values( data.programRules ), function ( programRule ) { 
+        if( programRule.id ) {
+            programRuleIds.push( programRule.id );
+        }
+    });
+    
+    $.ajax({
+        url: '../api/programRuleActions.json',
+        type: 'GET',
+        data:'paging=false&fields=id,programRule[id]'
+    }).done( function(response) {          
+        var programRuleActions = [];
+        _.each( _.values( response.programRuleActions ), function ( programRuleAction ) { 
+            if( programRuleAction &&
+                programRuleAction.id &&
+                programRuleAction.programRule &&
+                programRuleAction.programRule.id &&
+                programRuleIds.indexOf( programRuleAction.programRule.id ) !== -1) {
+                
+                programRuleActions.push( programRuleAction );
+            }
+        });
+        
+        def.resolve( {programRuleActions: programRuleActions, programs: data.programs} );
+        
+    }).fail(function(){
+        def.resolve( null );
+    });
+    
+    return def.promise();    
+}
+
+function getProgramRuleActions( data )
+{
+    if( !data || !data.programRuleActions ){
+        return;
+    }
+    
+    var mainDef = $.Deferred();
+    var mainPromise = mainDef.promise();
+
+    var def = $.Deferred();
+    var promise = def.promise();
+
+    var builder = $.Deferred();
+    var build = builder.promise();
+
+    _.each( _.values( data.programRuleActions ), function ( programRuleAction ) {
+        build = build.then(function() {
+            var d = $.Deferred();
+            var p = d.promise();
+            dhis2.tc.store.get('programRuleActions', programRuleAction.id).done(function(obj) {
+                if(!obj) {
+                    promise = promise.then( getProgramRuleAction( programRuleAction.id ) );
+                }
+                d.resolve();
+            });
+
+            return p;
+        });
+    });
+
+    build.done(function() {
+        def.resolve();
+
+        promise = promise.done( function () {
+            mainDef.resolve( data.programs );
+        } );
+    }).fail(function(){
+        mainDef.resolve( null );
+    });
+
+    builder.resolve();
+
+    return mainPromise;
+}
+
+function getProgramRuleAction( id )
+{
+    return function() {
+        return $.ajax( {
+            url: '../api/programRuleActions.json',
+            type: 'GET',
+            data: 'paging=false&filter=id:eq:' + id +'&fields=id,programRule[id],programRuleActionType,dataElement[id],location,content,data,'
+        }).done( function( response ){
+            
+            _.each( _.values( response.programRuleActions ), function ( programRuleAction ) { 
+                
+                if( programRuleAction &&
+                    programRuleAction.id &&
+                    programRuleAction.programRule &&
+                    programRuleAction.programRule.id ) {
+                
+                    dhis2.tc.store.set( 'programRuleActions', programRuleAction );
+                }
+            });
+        });
+    };
+}
+
+function getMetaProgramRuleVariables( programs )
+{
+    if( !programs ){
+        return;
+    }
+    
+    var def = $.Deferred();
+    
+    var programIds = [];
+    _.each( _.values( programs ), function ( program ) { 
+        if( program.id ) {
+            programIds.push( program.id );
+        }
+    });
+    
+    $.ajax({
+        url: '../api/programRuleVariables.json',
+        type: 'GET',
+        data:'paging=false&fields=id,program[id]'
+    }).done( function(response) {          
+        var programRuleVariables = [];
+        _.each( _.values( response.programRuleVariables ), function ( programRuleVariable ) { 
+            if( programRuleVariable &&
+                programRuleVariable.id &&
+                programRuleVariable.program &&
+                programRuleVariable.program.id &&
+                programIds.indexOf( programRuleVariable.program.id ) !== -1) {
+            
+                programRuleVariables.push( programRuleVariable );
+            }  
+            
+        });
+        
+        def.resolve( {programRuleVariables: programRuleVariables, programs: programs} );
+        
+    }).fail(function(){
+        def.resolve( null );
+    });
+    
+    return def.promise();    
+}
+
+function getProgramRuleVariables( data )
+{
+    if( !data || !data.programRuleVariables ){
+        return;
+    }
+    
+    var mainDef = $.Deferred();
+    var mainPromise = mainDef.promise();
+
+    var def = $.Deferred();
+    var promise = def.promise();
+
+    var builder = $.Deferred();
+    var build = builder.promise();
+
+    _.each( _.values( data.programRuleVariables ), function ( programRuleVariable ) {
+        build = build.then(function() {
+            var d = $.Deferred();
+            var p = d.promise();
+            dhis2.tc.store.get('programRuleVariables', programRuleVariable.id).done(function(obj) {
+                if(!obj) {
+                    promise = promise.then( getProgramRuleVariable( programRuleVariable.id ) );
+                }
+                d.resolve();
+            });
+
+            return p;
+        });
+    });
+
+    build.done(function() {
+        def.resolve();
+
+        promise = promise.done( function () {
+            mainDef.resolve( data.programs );
+        } );
+    }).fail(function(){
+        mainDef.resolve( null );
+    });
+
+    builder.resolve();
+
+    return mainPromise;
+}
+
+function getProgramRuleVariable( id )
+{
+    return function() {
+        return $.ajax( {
+            url: '../api/programRuleVariables.json',
+            type: 'GET',
+            data: 'paging=false&filter=id:eq:' + id +'&fields=id,program[id],name,programRuleVariableSourceType,trackedEntityAttribute[id],dataElement[id],programStage[id]'
+        }).done( function( response ){
+            
+            _.each( _.values( response.programRuleVariables ), function ( programRuleVariable ) { 
+                
+                if( programRuleVariable &&
+                    programRuleVariable.id &&
+                    programRuleVariable.program &&
+                    programRuleVariable.program.id ) {
+                
+                    dhis2.tc.store.set( 'programRuleVariables', programRuleVariable );
+                }
+            });
+        });
+    };
+}
+
+function getMetaProgramRules( programs )
+{
+    if( !programs ){
+        return;
+    }
+    
+    var def = $.Deferred();
+    
+    var programIds = [];
+    _.each( _.values( programs ), function ( program ) { 
+        if( program.id ) {
+            programIds.push( program.id );
+        }
+    });
+    
+    $.ajax({
+        url: '../api/programRules.json',
+        type: 'GET',
+        data:'paging=false&fields=id,program[id]'
+    }).done( function(response) {          
+        var programRules = [];
+        _.each( _.values( response.programRules ), function ( programRule ) { 
+            if( programRule &&
+                programRule.id &&
+                programRule.program &&
+                programRule.program.id &&
+                programIds.indexOf( programRule.program.id ) !== -1) {
+            
+                programRules.push( programRule );
+            }  
+            
+        });
+        
+        def.resolve( {programRules: programRules, programs: programs} );
+        
+    }).fail(function(){
+        def.resolve( null );
+    });
+    
+    return def.promise();    
+}
+
+function getProgramRules( data )
+{
+    if( !data || !data.programRules ){
+        return;
+    }
+    
+    var mainDef = $.Deferred();
+    var mainPromise = mainDef.promise();
+
+    var def = $.Deferred();
+    var promise = def.promise();
+
+    var builder = $.Deferred();
+    var build = builder.promise();
+
+    _.each( _.values( data.programRules ), function ( programRule ) {
+        build = build.then(function() {
+            var d = $.Deferred();
+            var p = d.promise();
+            dhis2.tc.store.get('programRules', programRule.id).done(function(obj) {
+                if(!obj) {
+                    promise = promise.then( getProgramRule( programRule.id ) );
+                }
+                d.resolve();
+            });
+
+            return p;
+        });
+    });
+
+    build.done(function() {
+        def.resolve();
+
+        promise = promise.done( function () {
+            mainDef.resolve( data );
+        } );
+    }).fail(function(){
+        mainDef.resolve( null );
+    });
+
+    builder.resolve();
+
+    return mainPromise;
+}
+
+function getProgramRule( id )
+{
+    return function() {
+        return $.ajax( {
+            url: '../api/programRules.json',
+            type: 'GET',
+            data: 'paging=false&filter=id:eq:' + id +'&fields=id,name,description,condition,program[id],programstage[id],priority'
+        }).done( function( response ){
+            
+            _.each( _.values( response.programRules ), function ( programRule ) { 
+                
+                if( programRule &&
+                    programRule.id &&
+                    programRule.program &&
+                    programRule.program.id ) {
+                
+                    dhis2.tc.store.set( 'programRules', programRule );
+                }
+            });
+        });
+    };
+}
+
 function getMetaProgramValidations( programs )
 {
     if( !programs ){

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/styles/style.css'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/styles/style.css	2015-06-02 12:25:03 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/styles/style.css	2015-06-10 11:55:41 +0000
@@ -384,6 +384,33 @@
     margin-left: 5px;
 }
 
+.info-container {
+    display: inline-block;
+    height:60px;
+    opacity: 1.0;
+    white-space: normal;
+    text-align: center;
+    border: 1px solid #aaa;
+    border-radius: 4px;
+    padding:0px;
+    margin-right: 10px
+}
+.info-container-text{
+    font-weight: bold;
+    padding: 5px 10px;
+    margin:0px;
+}
+.info-container-heading {
+    font-weight: normal;
+    padding: 5px 10px;
+    margin:0px;
+    background-color: #f5f5f5;
+    border-bottom: 1px solid transparent;
+    border-top-right-radius: 3px;
+    border-top-left-radius: 3px;
+}
+
+
 /*----------------------------------------------------------------------------*/
 /* Tracked entity
 /*----------------------------------------------------------------------------*/
@@ -426,8 +453,6 @@
 
 .dashboard-widget-container {
     height: auto;
-    overflow-x:auto;
-    overflow-y:auto;
 }
 
 .widget-link {