dhis2-devs team mailing list archive
-
dhis2-devs team
-
Mailing list archive
-
Message #35462
[Branch ~dhis2-devs-core/dhis2/trunk] Rev 18151: minor refactoring to adjust conventional naming; custom registration form - WIP
------------------------------------------------------------
revno: 18151
committer: Abyot Asalefew Gizaw <abyota@xxxxxxxxx>
branch nick: dhis2
timestamp: Mon 2015-02-02 14:42:37 +0100
message:
minor refactoring to adjust conventional naming; custom registration form - WIP
removed:
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/controllers.js
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/directives.js
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/filters.js
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/services.js
added:
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/custom-form.html
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/default-form.html
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/d2Directives.js
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/d2Services.js
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.controllers.js
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.filters.js
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js
modified:
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-cache-cleaner/index.html
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/event-capture.appcache
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/index.html
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/controllers.js
dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/profile/profile-controller.js
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.html
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/tracker-capture.appcache
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/green/green.css
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/india/india.css
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/light_blue/light_blue.css
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/myanmar/myanmar.css
dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/vietnam/vietnam.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-web/dhis-web-apps/src/main/webapp/dhis-web-cache-cleaner/index.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-cache-cleaner/index.html 2015-01-28 19:03:29 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-cache-cleaner/index.html 2015-02-02 13:42:37 +0000
@@ -49,8 +49,8 @@
<script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/angularLocalStorage.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/angular-translate.min.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/dhis2/services.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/dhis2/controllers.js"></script>
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js"></script>
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.controllers.js"></script>
<script type="text/javascript" src="scripts/app.js"></script>
<script type="text/javascript" src="scripts/services.js"></script>
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/event-capture.appcache'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/event-capture.appcache 2015-01-23 14:07:46 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/event-capture.appcache 2015-02-02 13:42:37 +0000
@@ -56,16 +56,14 @@
../dhis-web-commons/javascripts/angular/angular-animate.js
../dhis-web-commons/javascripts/angular/ui-bootstrap-tpls-0.10.0-draggable-modal.js
-
-#scripts/angular-translate.min.js
../dhis-web-commons/javascripts/angular/plugins/angularLocalStorage.js
../dhis-web-commons/javascripts/angular/plugins/angular-translate.min.js
../dhis-web-commons/javascripts/angular/plugins/angular-translate-loader-static-files.min.js
../dhis-web-commons/javascripts/angular/plugins/angular-translate-loader-url.min.js
-../dhis-web-commons/javascripts/angular/plugins/dhis2/directives.js
-../dhis-web-commons/javascripts/angular/plugins/dhis2/filters.js
-../dhis-web-commons/javascripts/angular/plugins/dhis2/services.js
-../dhis-web-commons/javascripts/angular/plugins/dhis2/controllers.js
+../dhis-web-commons/javascripts/dhis2/angular.directives.js
+../dhis-web-commons/javascripts/dhis2/angular.filters.js
+../dhis-web-commons/javascripts/dhis2/angular.services.js
+../dhis-web-commons/javascripts/dhis2/angular.controllers.js
../dhis-web-commons/javascripts/moment/moment-with-langs.min.js
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/index.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/index.html 2015-01-29 17:13:36 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/index.html 2015-02-02 13:42:37 +0000
@@ -66,10 +66,10 @@
<script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/angularLocalStorage.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/angular-translate.min.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/dhis2/directives.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/dhis2/filters.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/dhis2/services.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/dhis2/controllers.js"></script>
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js"></script>
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.filters.js"></script>
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js"></script>
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.controllers.js"></script>
<script type="text/javascript" src="scripts/app.js"></script>
<script type="text/javascript" src="scripts/services.js"></script>
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/controllers.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/controllers.js 2015-01-29 17:13:36 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/controllers.js 2015-02-02 13:42:37 +0000
@@ -196,11 +196,7 @@
ErrorMessageService.setErrorMessages(errorMessages);
ProgramValidationService.getByProgram($scope.selectedProgram.id).then(function(pvs){
-
$scope.programValidations = pvs;
-
- console.log('the validations: ', $scope.programValidations);
-
$scope.loadEvents();
});
});
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/profile/profile-controller.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/profile/profile-controller.js 2015-01-14 11:21:15 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/profile/profile-controller.js 2015-02-02 13:42:37 +0000
@@ -2,7 +2,8 @@
function($rootScope,
$scope,
CurrentSelection,
- DateUtils,
+ CustomFormService,
+ TEFormService,
TEIService,
DialogService,
AttributesFactory) {
@@ -31,6 +32,24 @@
//if no program, display attributesInNoProgram
TEIService.processAttributes($scope.selectedTei, $scope.selectedProgram, $scope.selectedEnrollment).then(function(tei){
$scope.selectedTei = tei;
+ if($scope.selectedProgram && $scope.selectedProgram.id){
+ AttributesFactory.getByProgram($scope.selectedProgram).then(function(atts){
+ $scope.attributesById = [];
+ angular.forEach(atts, function(att){
+ $scope.attributesById[att.id] = att;
+ });
+
+ $scope.selectedProgram.hasCustomForm = false;
+ TEFormService.getByProgram($scope.selectedProgram, atts).then(function(teForm){
+ if(angular.isObject(teForm)){
+ $scope.selectedProgram.hasCustomForm = true;
+ $scope.selectedProgram.displayCustomForm = $scope.selectedProgram.hasCustomForm ? true:false;
+ $scope.trackedEntityForm = teForm;
+ $scope.customForm = CustomFormService.getForTrackedEntity($scope.trackedEntityForm, 'PROFILE');
+ }
+ });
+ });
+ }
});
});
=== added file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/custom-form.html'
=== added file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/default-form.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/default-form.html 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/default-form.html 2015-02-02 13:42:37 +0000
@@ -0,0 +1,138 @@
+<div ng-if='!selectedProgram'>
+ <h3>{{'category'| translate}}</h3>
+ <table class="table-borderless table-striped">
+ <tr>
+ <td>
+ {{'entity_type'| translate}}
+ </td>
+ <td>
+ <select class="form-control" ng-model="trackedEntities.selected" ng-options="trackedEntity.name for trackedEntity in trackedEntities.available | orderBy: 'name'">
+ </select>
+ </td>
+ </tr>
+ </table>
+ <hr>
+</div>
+<h3>{{'profile'| translate}}</h3>
+<table class="table-borderless table-striped">
+ <tr ng-repeat="attribute in attributes">
+ <td>
+ {{attribute.name}}
+ </td>
+ <td>
+ <ng-form name="innerForm">
+ <div ng-switch="attribute.valueType">
+ <div ng-switch-when="date">
+ <input type="text" placeholder="{{dhis2CalendarFormat.keyDateFormat}}" name="foo" class="form-control" d2-date ng-model="attribute.value" ng-required="attribute.mandatory" />
+ <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
+ </div>
+ <div ng-switch-when="trueOnly">
+ <input type="checkbox" name="foo" class="form-control" ng-model="attribute.value" ng-required="attribute.mandatory" />
+ <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
+ </div>
+ <div ng-switch-when="bool">
+ <select name="foo" ng-model="attribute.value" class="form-control" ng-required="attribute.mandatory">
+ <option value="">{{'please_select'| translate}}</option>
+ <option value="false">{{'no'| translate}}</option>
+ <option value="true">{{'yes'| translate}}</option>
+ </select>
+ <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
+ </div>
+ <div ng-switch-when="optionSet">
+ <div ng-if="!selectedProgram">
+ <input type="text"
+ name="foo"
+ class="form-control"
+ ng-model="attribute.value"
+ typeahead="option.name as option.name for option in optionSets[attribute.optionSet.id].options | filter:$viewValue | limitTo:20"
+ typeahead-open-on-focus
+ ng-required="attribute.mandatory"/>
+ </div>
+ <div ng-if="selectedProgram">
+ <div ng-if="!selectedProgram.dataEntryMethod || optionSets[attribute.optionSet.id].options.length >= 7">
+ <input type="text"
+ name="foo"
+ class="form-control"
+ ng-model="attribute.value"
+ typeahead="option.name as option.name for option in optionSets[attribute.optionSet.id].options | filter:$viewValue | limitTo:20"
+ typeahead-open-on-focus
+ typeahead-editable=false
+ ng-required="attribute.mandatory"/>
+ </div>
+ <div ng-if="selectedProgram.dataEntryMethod && optionSets.optionSet[attribute.optionSet.id].options.length < 7">
+ <label>
+ <input type="radio"
+ name={{attribute.id}}
+ ng-required="attribute.mandatory"
+ ng-model="attribute.value"
+ value=""> {{'no_value'| translate}}<br>
+ </label><br>
+ <span ng-repeat="option in optionSets[attribute.optionSet.id].options">
+ <label>
+ <input type="radio"
+ name={{attribute.id}}
+ ng-required="attribute.mandatory"
+ ng-model="attribute.value"
+ value={{option.name}}> {{option.name}}
+ </label><br>
+ </span>
+ </div>
+ </div>
+ <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
+ </div>
+ <div ng-switch-when="number">
+ <input type="number" name="foo" class="form-control" ng-model="attribute.value" ng-required="attribute.mandatory"/>
+ <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
+ </div>
+ <div ng-switch-when="email">
+ <input type="email" name="foo" class="form-control" ng-model="attribute.value" ng-required="attribute.mandatory"/>
+ <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
+ </div>
+ <div ng-switch-default>
+ <input type="text" name="foo" class="form-control" ng-model="attribute.value" ng-required="attribute.mandatory"/>
+ <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
+ </div>
+ </div>
+ </ng-form>
+ </td>
+ </tr>
+</table>
+
+<div ng-if='selectedProgram'>
+ <hr>
+ <h3>{{'enrollment'| translate}}</h3>
+ <table class="dhis2-list-table-striped dhis2-table-hover">
+ <tr>
+ <td>
+ {{selectedProgram.dateOfEnrollmentDescription}}
+ </td>
+ <td>
+ <input type="text"
+ placeholder="{{dhis2CalendarFormat.keyDateFormat}}"
+ name="dateOfEnrollment"
+ class="form-control"
+ d2-date
+ ng-model="enrollment.dateOfEnrollment"
+ max-date="selectedProgram.selectEnrollmentDatesInFuture ? '' : 0"
+ min-date=""
+ ng-required="true"/>
+ <span ng-show="outerForm.submitted && outerForm.dateOfEnrollment.$invalid" class="error">{{'required'| translate}}</span>
+ </td>
+ </tr>
+ <tr ng-if="selectedProgram.displayIncidentDate">
+ <td>
+ {{selectedProgram.dateOfIncidentDescription}}
+ </td>
+ <td>
+ <input type="text"
+ placeholder="{{dhis2CalendarFormat.keyDateFormat}}"
+ name="dateOfIncident"
+ class="form-control"
+ d2-date
+ max-date="selectedProgram.selectIncidentDatesInFuture ? '' : 0"
+ min-date=""
+ ng-model="enrollment.dateOfIncident"/>
+ </td>
+ </tr>
+ </table>
+</div>
\ No newline at end of file
=== 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-01-05 15:31:59 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/registration-controller.js 2015-02-02 13:42:37 +0000
@@ -7,6 +7,8 @@
DHIS2EventFactory,
TEService,
TEIService,
+ TEFormService,
+ CustomFormService,
EnrollmentService,
DialogService,
CurrentSelection,
@@ -16,7 +18,8 @@
storage) {
$scope.today = DateUtils.getToday();
-
+ $scope.trackedEntityForm = null;
+ $scope.customForm = null;
$scope.optionSets = CurrentSelection.getOptionSets();
if(!$scope.optionSets){
@@ -45,19 +48,30 @@
//watch for selection of program
$scope.$watch('selectedProgram', function() {
+ $scope.trackedEntityForm = null;
+ $scope.customForm = null;
$scope.getAttributes();
});
$scope.getAttributes = function(){
-
- if($scope.selectedProgram){
+ if($scope.selectedProgram && $scope.selectedProgram.id){
AttributesFactory.getByProgram($scope.selectedProgram).then(function(atts){
$scope.attributes = atts;
$scope.attributesById = [];
angular.forEach(atts, function(att){
$scope.attributesById[att.id] = att;
});
- });
+
+ $scope.selectedProgram.hasCustomForm = false;
+ TEFormService.getByProgram($scope.selectedProgram, $scope.attributes).then(function(teForm){
+ if(angular.isObject(teForm)){
+ $scope.selectedProgram.hasCustomForm = true;
+ $scope.selectedProgram.displayCustomForm = $scope.selectedProgram.hasCustomForm ? true:false;
+ $scope.trackedEntityForm = teForm;
+ $scope.customForm = CustomFormService.getForTrackedEntity($scope.trackedEntityForm, 'ENROLLMENT');
+ }
+ });
+ });
}
else{
AttributesFactory.getWithoutProgram().then(function(atts){
@@ -70,8 +84,7 @@
}
};
- $scope.registerEntity = function(destination){
-
+ $scope.registerEntity = function(destination){
//check for form validity
$scope.outerForm.submitted = true;
if( $scope.outerForm.$invalid ){
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/registration.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/registration.html 2015-01-05 15:31:59 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/registration/registration.html 2015-02-02 13:42:37 +0000
@@ -1,147 +1,50 @@
<div class="bordered-div col-md-12" ng-controller="RegistrationController">
- <form name="outerForm" novalidate>
-
- <div ng-if='!selectedProgram'>
- <h3>{{'category' | translate}}</h3>
- <table class="table-borderless table-striped">
- <tr>
- <td>
- {{'entity_type' | translate}}
- </td>
- <td>
- <select class="form-control" ng-model="trackedEntities.selected" ng-options="trackedEntity.name for trackedEntity in trackedEntities.available | orderBy: 'name'">
- </select>
- </td>
- </tr>
- </table>
- <hr>
- </div>
-
- <h3>{{'profile' | translate}}</h3>
- <table class="table-borderless table-striped">
- <tr ng-repeat="attribute in attributes">
- <td>
- {{attribute.name}}
- </td>
- <td>
- <ng-form name="innerForm">
- <div ng-switch="attribute.valueType">
- <div ng-switch-when="date">
- <input type="text" placeholder="{{dhis2CalendarFormat.keyDateFormat}}" name="foo" class="form-control" d2-date ng-model="attribute.value" ng-required="attribute.mandatory" />
- <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
- </div>
- <div ng-switch-when="trueOnly">
- <input type="checkbox" name="foo" class="form-control" ng-model="attribute.value" ng-required="attribute.mandatory" />
- <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
- </div>
- <div ng-switch-when="bool">
- <select name="foo" ng-model="attribute.value" class="form-control" ng-required="attribute.mandatory">
- <option value="">{{'please_select'| translate}}</option>
- <option value="false">{{'no'| translate}}</option>
- <option value="true">{{'yes'| translate}}</option>
- </select>
- <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
- </div>
- <div ng-switch-when="optionSet">
- <div ng-if="!selectedProgram">
- <input type="text"
- name="foo"
- class="form-control"
- ng-model="attribute.value"
- typeahead="option.name as option.name for option in optionSets[attribute.optionSet.id].options | filter:$viewValue | limitTo:20"
- typeahead-open-on-focus
- ng-required="attribute.mandatory"/>
- </div>
- <div ng-if="selectedProgram">
- <div ng-if="!selectedProgram.dataEntryMethod || optionSets[attribute.optionSet.id].options.length >= 7">
- <input type="text"
- name="foo"
- class="form-control"
- ng-model="attribute.value"
- typeahead="option.name as option.name for option in optionSets[attribute.optionSet.id].options | filter:$viewValue | limitTo:20"
- typeahead-open-on-focus
- typeahead-editable=false
- ng-required="attribute.mandatory"/>
- </div>
- <div ng-if="selectedProgram.dataEntryMethod && optionSets.optionSet[attribute.optionSet.id].options.length < 7">
- <label>
- <input type="radio"
- name={{attribute.id}}
- ng-required="attribute.mandatory"
- ng-model="attribute.value"
- value=""> {{'no_value' | translate}}<br>
- </label><br>
- <span ng-repeat="option in optionSets[attribute.optionSet.id].options">
- <label>
- <input type="radio"
- name={{attribute.id}}
- ng-required="attribute.mandatory"
- ng-model="attribute.value"
- value={{option.name}}> {{option.name}}
- </label><br>
- </span>
- </div>
- </div>
- <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
- </div>
- <div ng-switch-when="number">
- <input type="number" name="foo" class="form-control" ng-model="attribute.value" ng-required="attribute.mandatory"/>
- <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
- </div>
- <div ng-switch-when="email">
- <input type="email" name="foo" class="form-control" ng-model="attribute.value" ng-required="attribute.mandatory"/>
- <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
- </div>
- <div ng-switch-default>
- <input type="text" name="foo" class="form-control" ng-model="attribute.value" ng-required="attribute.mandatory"/>
- <span ng-show="outerForm.submitted && innerForm.foo.$invalid" class="error">{{'required'| translate}}</span>
- </div>
- </div>
- </ng-form>
- </td>
- </tr>
- </table>
-
- <div ng-if='selectedProgram'>
- <hr>
- <h3>{{'enrollment' | translate}}</h3>
- <table class="dhis2-list-table-striped dhis2-table-hover">
- <tr>
- <td>
- {{selectedProgram.dateOfEnrollmentDescription}}
- </td>
- <td>
- <input type="text"
- placeholder="{{dhis2CalendarFormat.keyDateFormat}}"
- name="dateOfEnrollment"
- class="form-control"
- d2-date
- ng-model="enrollment.dateOfEnrollment"
- max-date="selectedProgram.selectEnrollmentDatesInFuture ? '' : 0"
- min-date=""
- ng-required="true"/>
- <span ng-show="outerForm.submitted && outerForm.dateOfEnrollment.$invalid" class="error">{{'required'| translate}}</span>
- </td>
- </tr>
- <tr ng-if="selectedProgram.displayIncidentDate">
- <td>
- {{selectedProgram.dateOfIncidentDescription}}
- </td>
- <td>
- <input type="text"
- placeholder="{{dhis2CalendarFormat.keyDateFormat}}"
- name="dateOfIncident"
- class="form-control"
- d2-date
- max-date="selectedProgram.selectIncidentDatesInFuture ? '' : 0"
- min-date=""
- ng-model="enrollment.dateOfIncident"/>
- </td>
- </tr>
- </table>
- </div>
-
- <div ng-if="formEmpty && outerForm.submitted">
+ <form name="outerForm" novalidate>
+ <div class="row col-sm-12 vertical-spacing" ng-if="selectedProgram && selectedProgram.displayCustomForm">
+ <div ng-if="!customForm.hasProgramDate">
+ <table>
+ <table class="dhis2-list-table-striped dhis2-table-hover">
+ <tr>
+ <td>
+ {{selectedProgram.dateOfEnrollmentDescription}}
+ </td>
+ <td>
+ <input type="text"
+ placeholder="{{dhis2CalendarFormat.keyDateFormat}}"
+ name="dateOfEnrollment"
+ class="form-control"
+ d2-date
+ ng-model="enrollment.dateOfEnrollment"
+ max-date="selectedProgram.selectEnrollmentDatesInFuture ? '' : 0"
+ min-date=""
+ ng-required="true"/>
+ <span ng-show="outerForm.submitted && outerForm.dateOfEnrollment.$invalid" class="error">{{'required'| translate}}</span>
+ </td>
+ </tr>
+ <tr ng-if="selectedProgram.displayIncidentDate">
+ <td>
+ {{selectedProgram.dateOfIncidentDescription}}
+ </td>
+ <td>
+ <input type="text"
+ placeholder="{{dhis2CalendarFormat.keyDateFormat}}"
+ name="dateOfIncident"
+ class="form-control"
+ d2-date
+ max-date="selectedProgram.selectIncidentDatesInFuture ? '' : 0"
+ min-date=""
+ ng-model="enrollment.dateOfIncident"/>
+ </td>
+ </tr>
+ </table>
+ </div>
+ <div ng-include="'../dhis-web-commons/customform/custom-form.html'"></div>
+ </div>
+ <div class="row col-sm-12 vertical-spacing" ng-if="!selectedProgram.displayCustomForm">
+ <div ng-include="'components/registration/default-form.html'"></div>
+ </div>
+
+ <div ng-if="formEmpty && outerForm.submitted">
<div class="alert alert-warning">{{'form_is_empty_fill_at_least_one'| translate}}</div>
</div>
=== 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-01-28 19:03:29 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/index.html 2015-02-02 13:42:37 +0000
@@ -79,10 +79,12 @@
<script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/angularjs-nvd3-directives.min.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/angularLocalStorage.js"></script>
<script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/angular-translate.min.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/dhis2/directives.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/dhis2/filters.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/dhis2/services.js"></script>
- <script type="text/javascript" src="../dhis-web-commons/javascripts/angular/plugins/dhis2/controllers.js"></script>
+ <!--<script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js"></script>-->
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.filters.js"></script>
+ <!--<script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js"></script>-->
+ <script type="text/javascript" src="../dhis-web-commons/javascripts/dhis2/dhis2.angular.controllers.js"></script>
+ <script type="text/javascript" src="scripts/d2Services.js"></script>
+ <script type="text/javascript" src="scripts/d2Directives.js"></script>
<script type="text/javascript" src="scripts/app.js"></script>
<script type="text/javascript" src="scripts/services.js"></script>
=== added file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/d2Directives.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/d2Directives.js 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/d2Directives.js 2015-02-02 13:42:37 +0000
@@ -0,0 +1,582 @@
+'use strict';
+
+/* Directives */
+
+var d2Directives = angular.module('d2Directives', [])
+
+
+.directive('d2OuSearch', function() {
+
+ return {
+ restrict: 'E',
+ template: '<div style="margin-top:20px">\n\
+ <img id="searchIcon" src="../images/search.png" style="cursor: pointer" title="{{ \'locate_organisation_unit_by_name\' | translate}}">\n\
+ <span id="searchSpan" style="width:100%;display:none;">\n\
+ <input type="text" id="searchField" name="key"/>\n\
+ <input type="button" value="{{\'find\' | translate}}" onclick="selection.findByName()"/>\n\
+ </span>\n\
+ </div>',
+ link: function (scope, element, attrs) {
+
+ $("#searchIcon").click(function() {
+ $("#searchSpan").toggle();
+ $("#searchField").focus();
+ });
+
+ $("#searchField").autocomplete({
+ source: "../dhis-web-commons/ouwt/getOrganisationUnitsByName.action",
+ select: function(event, ui) {
+ $("#searchField").val(ui.item.value);
+ selection.findByName();
+ }
+ });
+ }
+ };
+})
+
+.directive('inputValidator', function() {
+
+ return {
+ require: 'ngModel',
+ link: function (scope, element, attrs, ctrl) {
+
+ ctrl.$parsers.push(function (value) {
+ return parseFloat(value || '');
+ });
+ }
+ };
+})
+
+.directive('selectedOrgUnit', function($timeout, storage) {
+
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs){
+
+ //once ou tree is loaded, start meta-data download
+ $(function() {
+ dhis2.ou.store.open().done( function() {
+ selection.load();
+ $( "#orgUnitTree" ).one( "ouwtLoaded", function(event, ids, names) {
+ console.log('Finished loading orgunit tree');
+
+ //Disable ou selection until meta-data has downloaded
+ $( "#orgUnitTree" ).addClass( "disable-clicks" );
+
+ $timeout(function() {
+ scope.treeLoaded = true;
+ scope.$apply();
+ });
+
+ downloadMetaData();
+ });
+ });
+ });
+
+ //listen to user selection, and inform angular
+ selection.setListenerFunction( setSelectedOu, true );
+
+ function setSelectedOu( ids, names ) {
+ var ou = {id: ids[0], name: names[0]};
+ $timeout(function() {
+ scope.selectedOrgUnit = ou;
+ scope.$apply();
+ });
+ }
+ }
+ };
+})
+
+.directive('blurOrChange', function() {
+
+ return function( scope, elem, attrs) {
+ elem.calendarsPicker({
+ onSelect: function() {
+ scope.$apply(attrs.blurOrChange);
+ $(this).change();
+ }
+ }).change(function() {
+ scope.$apply(attrs.blurOrChange);
+ });
+ };
+})
+
+.directive('d2Enter', function () {
+ return function (scope, element, attrs) {
+ element.bind("keydown keypress", function (event) {
+ if(event.which === 13) {
+ scope.$apply(function (){
+ scope.$eval(attrs.d2Enter);
+ });
+ event.preventDefault();
+ }
+ });
+ };
+})
+
+.directive('d2NumberValidation', function(ErrorMessageService, $translate) {
+
+ return {
+ require: 'ngModel',
+ restrict: 'A',
+ link: function (scope, element, attrs, ctrl) {
+
+ function checkValidity(numberType, value){
+ var isValid = false;
+ switch(numberType){
+ case "number":
+ isValid = dhis2.validation.isNumber(value);
+ break;
+ case "posInt":
+ isValid = dhis2.validation.isPositiveInt(value);
+ break;
+ case "negInt":
+ isValid = dhis2.validation.isNegativeInt(value);
+ break;
+ case "zeroPositiveInt":
+ isValid = dhis2.validation.isZeroOrPositiveInt(value);
+ break;
+ case "int":
+ isValid = dhis2.validation.isInt(value);
+ break;
+ default:
+ isValid = true;
+ }
+ return isValid;
+ }
+
+ var errorMessages = ErrorMessageService.getErrorMessages();
+ var fieldName = attrs.inputFieldId;
+ var numberType = attrs.numberType;
+ var isRequired = attrs.ngRequired === 'true';
+ var msg = $translate(numberType)+ ' ' + $translate('required');
+
+ ctrl.$parsers.unshift(function(value) {
+ if(value){
+ var isValid = checkValidity(numberType, value);
+ if(!isValid){
+ errorMessages[fieldName] = $translate('value_must_be_' + numberType);
+ }
+ else{
+ if(isRequired){
+ errorMessages[fieldName] = msg;
+ }
+ else{
+ errorMessages[fieldName] = "";
+ }
+ }
+
+ ErrorMessageService.setErrorMessages(errorMessages);
+ ctrl.$setValidity(fieldName, isValid);
+ return value;
+ }
+
+ if(value === ''){
+ if(isRequired){
+ errorMessages[fieldName] = msg;
+ }
+ else{
+ ctrl.$setValidity(fieldName, true);
+ errorMessages[fieldName] = "";
+ }
+
+ ErrorMessageService.setErrorMessages(errorMessages);
+ return undefined;
+ }
+ });
+
+ ctrl.$formatters.unshift(function(value) {
+ if(value){
+ var isValid = checkValidity(numberType, value);
+ ctrl.$setValidity(fieldName, isValid);
+ return value;
+ }
+ });
+ }
+ };
+})
+
+.directive('typeaheadOpenOnFocus', function () {
+
+ return {
+ require: ['typeahead', 'ngModel'],
+ link: function (scope, element, attr, ctrls) {
+ element.bind('focus', function () {
+ ctrls[0].getMatchesAsync(ctrls[1].$viewValue);
+ scope.$watch(attr.ngModel, function(value) {
+ if(value === '' || angular.isUndefined(value)){
+ ctrls[0].getMatchesAsync(ctrls[1].$viewValue);
+ }
+ });
+ });
+ }
+ };
+})
+
+.directive('d2TypeaheadValidation', function() {
+
+ return {
+ require: ['typeahead', 'ngModel'],
+ restrict: 'A',
+ link: function (scope, element, attrs, ctrls) {
+ element.bind('blur', function () {
+ if(ctrls[1].$viewValue && !ctrls[1].$modelValue && ctrls[0].active === -1){
+ ctrls[1].$setViewValue();
+ ctrls[1].$render();
+ }
+ });
+ }
+ };
+})
+
+.directive('d2PopOver', function($compile, $templateCache){
+
+ return {
+ restrict: 'EA',
+ link: function(scope, element, attrs){
+ var content = $templateCache.get("popover.html");
+ content = $compile(content)(scope);
+ var options = {
+ content: content,
+ placement: 'bottom',
+ trigger: 'hover',
+ html: true,
+ title: scope.title
+ };
+ $(element).popover(options);
+ },
+ scope: {
+ content: '=',
+ title: '@details',
+ template: "@template"
+ }
+ };
+})
+
+.directive('sortable', function() {
+
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs){
+ element.sortable({
+ connectWith: ".connectedSortable",
+ placeholder: "ui-state-highlight",
+ tolerance: "pointer",
+ handle: '.handle'
+ });
+ }
+ };
+})
+
+.directive('serversidePaginator', function factory() {
+
+ return {
+ restrict: 'E',
+ controller: function ($scope, Paginator) {
+ $scope.paginator = Paginator;
+ },
+ templateUrl: '../dhis-web-commons/paging/serverside-pagination.html'
+ };
+})
+
+.directive('draggableModal', function(){
+
+ return {
+ restrict: 'EA',
+ link: function(scope, element) {
+ element.draggable();
+ }
+ };
+})
+
+.directive('d2GoogleMap', function ($parse, $compile, storage) {
+ return {
+ restrict: 'E',
+ replace: true,
+ template: '<div></div>',
+ link: function(scope, element, attrs){
+
+ //remove angular bootstrap ui modal draggable
+ $(".modal-content").draggable({ disabled: true });
+
+ //get a default center
+ var latCenter = 12.31, lngCenter = 51.48;
+
+ //if there is any marker already - use it as center
+ if(angular.isObject(scope.location)){
+ if(scope.location.lat && scope.location.lng){
+ latCenter = scope.location.lat;
+ lngCenter = scope.location.lng;
+ }
+ }
+
+ //default map configurations
+ var mapOptions = {
+ zoom: 3,
+ center: new google.maps.LatLng(latCenter, lngCenter),
+ mapTypeId: google.maps.MapTypeId.ROADMAP
+ },featureStyle = {
+ strokeWeight: 2,
+ strokeOpacity: 0.4,
+ fillOpacity: 0.4,
+ fillColor: 'green'
+ };
+
+ var geojsons = $parse(attrs.geojsons)(scope);
+ var currentLayer = 0, currentGeojson = geojsons[0];
+
+ var map = new google.maps.Map(document.getElementById(attrs.id), mapOptions);
+ var currentGeojsonFeatures = map.data.addGeoJson(currentGeojson);
+
+ var marker = new google.maps.Marker({
+ map: map
+ });
+
+ if(angular.isObject(scope.location)){
+ if(scope.location.lat && scope.location.lng){
+ addMarker({lat: scope.location.lat, lng: scope.location.lng});
+ }
+ }
+
+ function addMarker(loc){
+ var latLng = new google.maps.LatLng(loc.lat, loc.lng);
+ marker.setPosition(latLng);
+ }
+
+ function centerMap(){
+
+ if(currentGeojson && currentGeojson.features){
+ var latLngBounds = new google.maps.LatLngBounds();
+ angular.forEach(currentGeojson.features, function(feature){
+ if(feature.geometry.type === 'MultiPolygon'){
+ angular.forEach(feature.geometry.coordinates[0][0], function(coordinate){
+ latLngBounds.extend(new google.maps.LatLng(coordinate[1],coordinate[0]));
+ });
+ }
+ else if(feature.geometry.type === 'Point'){
+ latLngBounds.extend(new google.maps.LatLng(feature.geometry.coordinates[1],feature.geometry.coordinates[0]));
+ }
+ });
+
+ map.fitBounds(latLngBounds);
+ map.panToBounds(latLngBounds);
+ }
+ }
+
+ function initializeMap(){
+ google.maps.event.addListenerOnce(map, 'idle', function(){
+ google.maps.event.trigger(map, 'resize');
+ map.data.setStyle(featureStyle);
+ centerMap();
+ });
+ }
+
+ map.data.addListener('mouseover', function(e) {
+ $("#polygon-label").text( e.feature.k.name );
+ map.data.revertStyle();
+ map.data.overrideStyle(e.feature, {fillOpacity: 0.8});
+ });
+
+ map.data.addListener('mouseout', function() {
+ $("#polygon-label").text( '' );
+ map.data.revertStyle();
+ });
+
+ //drill-down based on polygons assigned to orgunits
+ map.data.addListener('rightclick', function(e){
+ for (var i = 0; i < currentGeojsonFeatures.length; i++){
+ map.data.remove(currentGeojsonFeatures[i]);
+ }
+
+ if(currentLayer >= geojsons.length-1){
+ currentLayer = 0;
+ currentGeojson = angular.copy(geojsons[currentLayer]);
+ }
+ else{
+ currentLayer++;
+ currentGeojson = angular.copy(geojsons[currentLayer]);
+ currentGeojson.features = [];
+ var selectedFeatures = [];
+ angular.forEach(geojsons[currentLayer].features, function(feature){
+ if(feature.properties.parent === e.feature.B){
+ selectedFeatures.push(feature);
+ }
+ });
+
+ if(selectedFeatures.length){
+ currentGeojson.features = selectedFeatures;
+ }
+ }
+ currentGeojsonFeatures = map.data.addGeoJson(currentGeojson);
+ centerMap();
+ });
+
+ //capturing coordinate from defined polygons
+ map.data.addListener('click', function(e) {
+ scope.$apply(function(){
+ addMarker({
+ lat: e.latLng.lat(),
+ lng: e.latLng.lng()
+ });
+ $parse(attrs.location).assign(scope.$parent, {lat: e.latLng.lat(), lng: e.latLng.lng()});
+ });
+ });
+
+ //capturing coordinate from anywhere in the map - incase no polygons are defined
+ google.maps.event.addListener(map, 'click', function(e){
+ scope.$apply(function(){
+ addMarker({
+ lat: e.latLng.lat(),
+ lng: e.latLng.lng()
+ });
+ $parse(attrs.location).assign(scope.$parent, {lat: e.latLng.lat(), lng: e.latLng.lng()});
+ });
+ });
+
+ initializeMap();
+ }
+ };
+})
+
+.directive('d2CustomForm', function($compile) {
+ return{
+ restrict: 'E',
+ link: function(scope, elm, attrs){
+ scope.$watch('customForm', function(){
+ elm.html(scope.customForm.htmlCode);
+ $compile(elm.contents())(scope);
+ });
+ }
+ };
+})
+
+.directive('d2ContextMenu', function(ContextMenuSelectedItem) {
+
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs){
+ var contextMenu = $("#contextMenu");
+
+ element.click(function (e) {
+ var selectedItem = $.parseJSON(attrs.selectedItem);
+ ContextMenuSelectedItem.setSelectedItem(selectedItem);
+
+ var menuHeight = contextMenu.height();
+ var menuWidth = contextMenu.width();
+ var winHeight = $(window).height();
+ var winWidth = $(window).width();
+
+ var pageX = e.pageX;
+ var pageY = e.pageY;
+
+ contextMenu.show();
+
+ if( (menuWidth + pageX) > winWidth ) {
+ pageX -= menuWidth;
+ }
+
+ if( (menuHeight + pageY) > winHeight ) {
+ pageY -= menuHeight;
+
+ if( pageY < 0 ) {
+ pageY = e.pageY;
+ }
+ }
+
+ contextMenu.css({
+ left: pageX,
+ top: pageY
+ });
+
+ return false;
+ });
+
+ contextMenu.on("click", "a", function () {
+ contextMenu.hide();
+ });
+
+ $(document).click(function () {
+ contextMenu.hide();
+ });
+ }
+ };
+})
+
+.directive('d2Date', function(DateUtils, CalendarService, ErrorMessageService, $translate, $parse) {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function(scope, element, attrs, ctrl) {
+
+ var errorMessages = ErrorMessageService.getErrorMessages();
+ var fieldName = attrs.inputFieldId;
+ var isRequired = attrs.ngRequired === 'true';
+ var calendarSetting = CalendarService.getSetting();
+ var dateFormat = 'yyyy-mm-dd';
+ if(calendarSetting.keyDateFormat === 'dd-MM-yyyy'){
+ dateFormat = 'dd-mm-yyyy';
+ }
+
+ var minDate = $parse(attrs.minDate)(scope),
+ maxDate = $parse(attrs.maxDate)(scope),
+ calendar = $.calendars.instance(calendarSetting.keyCalendar);
+
+ element.calendarsPicker({
+ changeMonth: true,
+ dateFormat: dateFormat,
+ yearRange: '-120:+30',
+ minDate: minDate,
+ maxDate: maxDate,
+ calendar: calendar,
+ duration: "fast",
+ showAnim: "",
+ renderer: $.calendars.picker.themeRollerRenderer,
+ onSelect: function(date) {
+ $(this).change();
+ }
+ })
+ .change(function() {
+ if(this.value){
+ var rawDate = this.value;
+ var convertedDate = DateUtils.format(this.value);
+
+ var isValid = rawDate == convertedDate;
+
+ if(!isValid){
+ errorMessages[fieldName] = $translate('date_required');
+ }
+ else{
+ if(isRequired){
+ errorMessages[fieldName] = $translate('required');
+ }
+ else{
+ errorMessages[fieldName] = "";
+ }
+ if(maxDate === 0){
+ isValid = !moment(convertedDate, calendarSetting.momentFormat).isAfter(DateUtils.getToday());
+ if(!isValid){
+ errorMessages[fieldName] = $translate('future_date_not_allowed');
+ }
+ }
+ }
+ ctrl.$setViewValue(this.value);
+ ctrl.$setValidity(fieldName, isValid);
+ }
+ else{
+ if(!isRequired){
+ ctrl.$setViewValue(this.value);
+ ctrl.$setValidity(fieldName, !isRequired);
+ errorMessages[fieldName] = "";
+ }
+ else{
+ errorMessages[fieldName] = $translate('required');
+ }
+ }
+
+ ErrorMessageService.setErrorMessages(errorMessages);
+ this.focus();
+ scope.$apply();
+ });
+ }
+ };
+});
\ No newline at end of file
=== added file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/d2Services.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/d2Services.js 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/d2Services.js 2015-02-02 13:42:37 +0000
@@ -0,0 +1,743 @@
+/* Pagination service */
+var d2Services = angular.module('d2Services', ['ngResource'])
+
+/* Factory for loading translation strings */
+.factory('i18nLoader', function ($q, $http, storage, DialogService) {
+
+ var getTranslationStrings = function(locale){
+ var defaultUrl = 'i18n/i18n_app.properties';
+ var url = '';
+ if(locale === 'en' || !locale){
+ url = defaultUrl;
+ }
+ else{
+ url = 'i18n/i18n_app_' + locale + '.properties';
+ }
+
+ var tx = {locale: locale};
+
+ var promise = $http.get(url).then(function(response){
+ tx= {locale: locale, keys: dhis2.util.parseJavaProperties(response.data)};
+ return tx;
+ }, function(){
+ var dialogOptions = {
+ headerText: 'missing_translation_file',
+ bodyText: 'missing_translation_using_default'
+ };
+
+ DialogService.showDialog({}, dialogOptions);
+ var p = $http.get(defaultUrl).then(function(response){
+ tx= {locale: locale, keys: dhis2.util.parseJavaProperties(response.data)};
+ return tx;
+ });
+ return p;
+ });
+ return promise;
+ };
+
+ var getLocale = function(){
+ var locale = 'en';
+
+ var promise = $http.get('../api/me/profile.json').then(function(response){
+ storage.set('USER_PROFILE', response.data);
+ if(response.data && response.data.settings && response.data.settings.keyUiLocale){
+ locale = response.data.settings.keyUiLocale;
+ }
+ return locale;
+ }, function(){
+ return locale;
+ });
+
+ return promise;
+ };
+ return function () {
+ var deferred = $q.defer(), translations;
+ var userProfile = storage.get('USER_PROFILE');
+ if(userProfile && userProfile.settings && userProfile.settings.keyUiLocale){
+ getTranslationStrings(userProfile.settings.keyUiLocale).then(function(response){
+ translations = response.keys;
+ deferred.resolve(translations);
+ });
+ return deferred.promise;
+ }
+ else{
+ getLocale().then(function(locale){
+ getTranslationStrings(locale).then(function(response){
+ translations = response.keys;
+ deferred.resolve(translations);
+ });
+ });
+ return deferred.promise;
+ }
+ };
+})
+
+/* Factory for loading external data */
+.factory('ExternalDataFactory', function($http) {
+
+ return {
+ get: function(fileName) {
+ var promise = $http.get( fileName ).then(function(response){
+ return response.data;
+ });
+ return promise;
+ }
+ };
+})
+
+/* service for getting calendar setting */
+.service('CalendarService', function(storage, $rootScope){
+
+ return {
+ getSetting: function() {
+
+ var dhis2CalendarFormat = {keyDateFormat: 'yyyy-MM-dd', keyCalendar: 'gregorian', momentFormat: 'YYYY-MM-DD'};
+ var storedFormat = storage.get('CALENDAR_SETTING');
+ if(angular.isObject(storedFormat) && storedFormat.keyDateFormat && storedFormat.keyCalendar){
+ if(storedFormat.keyCalendar === 'iso8601'){
+ storedFormat.keyCalendar = 'gregorian';
+ }
+
+ if(storedFormat.keyDateFormat === 'dd-MM-yyyy'){
+ dhis2CalendarFormat.momentFormat = 'DD-MM-YYYY';
+ }
+
+ dhis2CalendarFormat.keyCalendar = storedFormat.keyCalendar;
+ dhis2CalendarFormat.keyDateFormat = storedFormat.keyDateFormat;
+ }
+ $rootScope.dhis2CalendarFormat = dhis2CalendarFormat;
+ return dhis2CalendarFormat;
+ }
+ };
+})
+
+/* service for dealing with dates */
+.service('DateUtils', function($filter, CalendarService){
+
+ return {
+ getDate: function(dateValue){
+ if(!dateValue){
+ return;
+ }
+ var calendarSetting = CalendarService.getSetting();
+ dateValue = moment(dateValue, calendarSetting.momentFormat)._d;
+ return Date.parse(dateValue);
+ },
+ format: function(dateValue) {
+ if(!dateValue){
+ return;
+ }
+
+ var calendarSetting = CalendarService.getSetting();
+ dateValue = moment(dateValue, calendarSetting.momentFormat)._d;
+ dateValue = $filter('date')(dateValue, calendarSetting.keyDateFormat);
+ return dateValue;
+ },
+ formatToHrsMins: function(dateValue) {
+ var calendarSetting = CalendarService.getSetting();
+ var dateFormat = 'YYYY-MM-DD @ hh:mm A';
+ if(calendarSetting.keyDateFormat === 'dd-MM-yyyy'){
+ dateFormat = 'DD-MM-YYYY @ hh:mm A';
+ }
+ return moment(dateValue).format(dateFormat);
+ },
+ getToday: function(){
+ var calendarSetting = CalendarService.getSetting();
+ var tdy = $.calendars.instance(calendarSetting.keyCalendar).newDate();
+ var today = moment(tdy._year + '-' + tdy._month + '-' + tdy._day, 'YYYY-MM-DD')._d;
+ today = Date.parse(today);
+ today = $filter('date')(today, calendarSetting.keyDateFormat);
+ return today;
+ },
+ formatFromUserToApi: function(dateValue){
+ if(!dateValue){
+ return;
+ }
+ var calendarSetting = CalendarService.getSetting();
+ dateValue = moment(dateValue, calendarSetting.momentFormat)._d;
+ dateValue = Date.parse(dateValue);
+ dateValue = $filter('date')(dateValue, 'yyyy-MM-dd');
+ return dateValue;
+ },
+ formatFromApiToUser: function(dateValue){
+ if(!dateValue){
+ return;
+ }
+ var calendarSetting = CalendarService.getSetting();
+ dateValue = moment(dateValue, 'YYYY-MM-DD')._d;
+ return $filter('date')(dateValue, calendarSetting.keyDateFormat);
+ }
+ };
+})
+
+/* service for dealing with custom form */
+.service('CustomFormService', function(){
+
+ return {
+ getForProgramStage: function(programStage){
+
+ var htmlCode = programStage.dataEntryForm ? programStage.dataEntryForm.htmlCode : null;
+
+ if(htmlCode){
+
+ var programStageDataElements = [];
+
+ angular.forEach(programStage.programStageDataElements, function(prStDe){
+ programStageDataElements[prStDe.dataElement.id] = prStDe;
+ });
+
+ var inputRegex = /<input.*?\/>/g,
+ match,
+ inputFields = [],
+ hasEventDate = false;
+
+ while (match = inputRegex.exec(htmlCode)) {
+ inputFields.push(match[0]);
+ }
+
+ for(var i=0; i<inputFields.length; i++){
+ var inputField = inputFields[i];
+ var inputElement = $.parseHTML( inputField );
+ var attributes = {};
+
+ $(inputElement[0].attributes).each(function() {
+ attributes[this.nodeName] = this.value;
+ });
+
+ var fieldId = '', errorMessageId = '', newInputField;
+ if(attributes.hasOwnProperty('id')){
+
+ if(attributes['id'] === 'executionDate'){
+ fieldId = 'eventDate';
+ errorMessageId = '"' + 'eventDate' + '"';
+ hasEventDate = true;
+
+ //name needs to be unique so that it can be used for validation in angularjs
+ if(attributes.hasOwnProperty('name')){
+ attributes['name'] = fieldId;
+ }
+
+ newInputField = '<input type="text" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '"' +
+ ' input-field-id="' + fieldId + '"' +
+ ' d2-date ' +
+ ' max-date="' + 0 + '"' +
+ ' placeholder="{{dhis2CalendarFormat.keyDateFormat}}" ' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' blur-or-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="{{true}}">';
+ }
+ else{
+ fieldId = attributes['id'].substring(4, attributes['id'].length-1).split("-")[1];
+ errorMessageId = 'prStDes.' + fieldId + '.dataElement.id';
+
+ //name needs to be unique so that it can be used for validation in angularjs
+ if(attributes.hasOwnProperty('name')){
+ attributes['name'] = fieldId;
+ }
+
+ //check data element type and generate corresponding angular input field
+ if(programStageDataElements[fieldId].dataElement.type === "int"){
+ newInputField = '<input type="text" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' d2-number-validation ' +
+ ' number-type="' + programStageDataElements[fieldId].dataElement.numberType + '" ' +
+ ' ng-model="currentEvent.' + fieldId + '"' +
+ ' input-field-id="' + fieldId + '"' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
+ ' ng-blur="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="{{prStDes.' + fieldId + '.compulsory}}">';
+ }
+ if(programStageDataElements[fieldId].dataElement.type === "string"){
+ if(programStageDataElements[fieldId].dataElement.optionSet){
+ var optionSetId = programStageDataElements[fieldId].dataElement.optionSet.id;
+ newInputField = '<input type="text" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '" ' +
+ ' input-field-id="' + fieldId + '"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\' || currentEvent[uid]==\'uid\'"' +
+ ' ng-required="{{prStDes.' + fieldId + '.compulsory}}"' +
+ ' typeahead="option.name as option.name for option in optionSets.'+optionSetId+'.options | filter:$viewValue | limitTo:20"' +
+ ' typeahead-editable="false" ' +
+ ' d2-typeahead-validation ' +
+ ' class="typeahead" ' +
+ ' placeholder=" " ' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-blur="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' typeahead-open-on-focus ng-required="prStDes.'+fieldId+'.compulsory"> ';
+ }
+ else{
+ newInputField = '<input type="text" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '" ' +
+ ' input-field-id="' + fieldId + '"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\' || currentEvent[uid]==\'uid\'"' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-blur="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="prStDes.' + fieldId + '.compulsory"> ';
+ }
+ }
+ if(programStageDataElements[fieldId].dataElement.type === "bool"){
+ newInputField = '<select ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '" ' +
+ ' input-field-id="' + fieldId + '"' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
+ ' ng-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="{{prStDes.' + fieldId + '.compulsory}}">' +
+ '<option value="">{{\'please_select\'| translate}}</option>' +
+ '<option value="false">{{\'no\'| translate}}</option>' +
+ '<option value="true">{{\'yes\'| translate}}</option>' +
+ '</select> ';
+ }
+ if(programStageDataElements[fieldId].dataElement.type === "date"){
+ var maxDate = programStageDataElements[fieldId].allowFutureDate ? '' : 0;
+ newInputField = '<input type="text" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '"' +
+ ' input-field-id="' + fieldId + '"' +
+ ' placeholder="{{dhis2CalendarFormat.keyDateFormat}}" ' +
+ ' d2-date ' +
+ ' max-date="' + maxDate + '"' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
+ ' blur-or-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="{{prStDes.' + fieldId + '.compulsory}}"> ';
+ }
+ if(programStageDataElements[fieldId].dataElement.type === "trueOnly"){
+ newInputField = '<input type="checkbox" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '"' +
+ ' input-field-id="' + fieldId + '"' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
+ ' ng-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="{{prStDes.' + fieldId + '.compulsory}}"> ';
+ }
+ }
+
+ newInputField = newInputField + ' <span ng-show="(outerForm.'+ fieldId +'.$dirty && outerForm.'+ fieldId +'.$invalid) || (outerForm.submitted && outerForm.'+ fieldId +'.$invalid) || (currentEvent.' + fieldId + ' && outerForm.' + fieldId + '.$invalid)" class="required">{{getErrorMessage(' + errorMessageId + ')}}</span> ';
+
+ htmlCode = htmlCode.replace(inputField, newInputField);
+ }
+ }
+ return {htmlCode: htmlCode, hasEventDate: hasEventDate};
+ }
+ return null;
+ },
+ getForTrackedEntity: function(trackedEntity, target){
+ if(!trackedEntity ){
+ return null;
+ }
+
+ var htmlCode = trackedEntity.dataEntryForm ? trackedEntity.dataEntryForm.htmlCode : null;
+ if(htmlCode){
+
+ var trackedEntityFormAttributes = [];
+ angular.forEach(trackedEntity.attributes, function(att){
+ trackedEntityFormAttributes[att.id] = att;
+ });
+
+
+ var inputRegex = /<input.*?\/>/g, match, inputFields = [];
+ var hasProgramDate = false;
+ while (match = inputRegex.exec(htmlCode)) {
+ inputFields.push(match[0]);
+ }
+
+ for(var i=0; i<inputFields.length; i++){
+ var inputField = inputFields[i];
+ var inputElement = $.parseHTML( inputField );
+ var attributes = {};
+
+ $(inputElement[0].attributes).each(function() {
+ attributes[this.nodeName] = this.value;
+ });
+
+ var attId = '', newInputField, programId;
+ if(attributes.hasOwnProperty('attributeid')){
+ attId = attributes['attributeid'];
+
+ var fieldName = attId;
+ var attMaxDate = trackedEntityFormAttributes[attId].allowFutureDate ? '' : 0;
+
+ //check attribute type and generate corresponding angular input field
+ if(trackedEntityFormAttributes[attId].valueType === "number"){
+ newInputField = '<input type="text" ' +
+ ' name="' + fieldName + '"' +
+ ' element-id="' + i + '"' +
+ ' element-code="' + trackedEntityFormAttributes[attId].code + '"' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' d2-number-validation ' +
+ ' d2-focus-next-on-enter' +
+ ' ng-model="registeredTei.' + attId + '" ' +
+ ' ng-blur="validationAndSkipLogic(registeredTei,\'' + attId + '\')" ' +
+ ' ng-required=" ' + trackedEntityFormAttributes[attId].mandatory + '"> ';
+ }
+ else if(trackedEntityFormAttributes[attId].valueType === "optionSet"){
+ var optionSetId = trackedEntityFormAttributes[attId].optionSet.id;
+ newInputField = '<input type="text" ' +
+ ' name="' + fieldName + '"' +
+ ' element-id="' + i + '"' +
+ ' element-code="' + trackedEntityFormAttributes[attId].code + '"' +
+ this.getAttributesAsString(attributes) +
+ ' d2-focus-next-on-enter' +
+ ' ng-model="registeredTei.' + attId + '" ' +
+ ' d2-validation ' +
+ ' d2-typeahead-validation ' +
+ ' class="typeahead" ' +
+ ' placeholder=" " ' +
+ ' typeahead-editable="false" ' +
+ ' typeahead="option.name as option.name for option in optionSets.' + optionSetId + '.options | filter:$viewValue | limitTo:50"' +
+ ' typeahead-open-on-focus ' +
+ ' ng-blur="validationAndSkipLogic(registeredTei,\'' + attId + '\')" ' +
+ ' ng-required=" ' + trackedEntityFormAttributes[attId].mandatory + '"> ';
+ }
+ else if(trackedEntityFormAttributes[attId].valueType === "bool"){
+ newInputField = '<select ' +
+ ' name="' + fieldName + '"' +
+ ' element-id="' + i + '"' +
+ ' element-code="' + trackedEntityFormAttributes[attId].code + '"' +
+ this.getAttributesAsString(attributes) +
+ ' d2-focus-next-on-enter' +
+ ' ng-model="registeredTei.' + attId + '" ' +
+ ' ng-change="validationAndSkipLogic(registeredTei,\'' + attId + '\')" ' +
+ ' ng-required=" ' + trackedEntityFormAttributes[attId].mandatory + '"> ' +
+ ' <option value="">{{\'please_select\'| translate}}</option>' +
+ ' <option value="false">{{\'no\'| translate}}</option>' +
+ ' <option value="true">{{\'yes\'| translate}}</option>' +
+ '</select> ';
+ }
+ else if(trackedEntityFormAttributes[attId].valueType === "date"){
+ newInputField = '<input type="text" ' +
+ ' name="' + fieldName + '"' +
+ ' element-id="' + i + '"' +
+ ' element-code="' + trackedEntityFormAttributes[attId].code + '"' +
+ this.getAttributesAsString(attributes) +
+ ' d2-focus-next-on-enter' +
+ ' placeholder="{{dhis2CalendarFormat.keyDateFormat}}" ' +
+ ' ng-model="registeredTei.' + attId + '" ' +
+ ' max-date="' + attMaxDate + '"' + '\'' +
+ ' d2-date' +
+ ' d2-validation ' +
+ ' blur-or-change="validationAndSkipLogic(registeredTei,\'' + attId + '\')" ' +
+ ' ng-required=" ' + trackedEntityFormAttributes[attId].mandatory + '"> ';
+ }
+ else if(trackedEntityFormAttributes[attId].valueType === "trueOnly"){
+ newInputField = '<input type="checkbox" ' +
+ ' name="' + fieldName + '"' +
+ ' element-id="' + i + '"' +
+ ' element-code="' + trackedEntityFormAttributes[attId].code + '"' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' d2-focus-next-on-enter' +
+ ' ng-model="registeredTei.' + attId + '" ' +
+ ' ng-change="validationAndSkipLogic(registeredTei,\'' + attId + '\')" ' +
+ ' ng-required=" ' + trackedEntityFormAttributes[attId].mandatory + '"> ';
+ }
+ else if(trackedEntityFormAttributes[attId].valueType === "email"){
+ newInputField = '<input type="email" ' +
+ ' name="' + fieldName + '"' +
+ ' element-id="' + i + '"' +
+ ' element-code="' + trackedEntityFormAttributes[attId].code + '"' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' d2-focus-next-on-enter' +
+ ' ng-model="registeredTei.' + attId + '" ' +
+ ' ng-blur="validationAndSkipLogic(registeredTei,\'' + attId + '\')" ' +
+ ' ng-required=" ' + trackedEntityFormAttributes[attId].mandatory + '"> ';
+ }
+ else {
+ newInputField = '<input type="text" ' +
+ ' name="' + fieldName + '"' +
+ ' element-id="' + i + '"' +
+ ' element-code="' + trackedEntityFormAttributes[attId].code + '"' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' d2-focus-next-on-enter' +
+ ' ng-model="registeredTei.' + attId + '" ' +
+ ' ng-blur="validationAndSkipLogic(registeredTei,\'' + attId + '\')" ' +
+ ' ng-required=" ' + trackedEntityFormAttributes[attId].mandatory + '"> ';
+ }
+ }
+
+ if(target === 'ENROLLMENT' && attributes.hasOwnProperty('programid')){
+ hasProgramDate = true;
+ programId = attributes['programid'];
+ if(programId === 'enrollmentDate'){
+ fieldName = 'dateOfEnrollment';
+ var enMaxDate = trackedEntity.selectEnrollmentDatesInFuture ? '' : 0;
+ newInputField = '<input type="text" ' +
+ ' name="' + fieldName + '"' +
+ ' element-id="' + i + '"' +
+ this.getAttributesAsString(attributes) +
+ ' d2-focus-next-on-enter' +
+ ' placeholder="{{dhis2CalendarFormat.keyDateFormat}}" ' +
+ ' ng-model="enrollment.dateOfEnrollment" ' +
+ ' d2-date' +
+ ' max-date="' + enMaxDate + '"' + '\'' +
+ ' ng-required="true"> ';
+ }
+ if(programId === 'dateOfIncident'){
+ fieldName = 'dateOfEnrollment';
+ var inMaxDate = trackedEntity.selectIncidentDatesInFuture ? '' : 0;
+ newInputField = '<input type="text" ' +
+ ' name="' + fieldName + '"' +
+ ' element-id="' + i + '"' +
+ this.getAttributesAsString(attributes) +
+ ' d2-focus-next-on-enter' +
+ ' placeholder="{{dhis2CalendarFormat.keyDateFormat}}" ' +
+ ' ng-model="enrollment.dateOfIncident" ' +
+ ' d2-date ' +
+ ' max-date="' + inMaxDate + '"' + + '\'' +
+ ' ng-required="true"> ';
+ }
+ }
+
+ newInputField = //'<ng-form name="innerForm">' +
+ newInputField +
+ ' <span ng-show="outerForm.submitted && outerForm.'+ fieldName +'.$invalid" class="required">{{required}}</span> ' +
+ ' <span ng-show="invalidInputs.' + fieldName + '"" class="required">{{invalidInputLabel}}</span> ';
+ //'</ng-form>';
+
+ htmlCode = htmlCode.replace(inputField, newInputField);
+ }
+ return {htmlCode: htmlCode, hasProgramDate: hasProgramDate};
+ }
+ return null;
+ },
+ getAttributesAsString: function(attributes){
+ if(attributes){
+ var attributesAsString = '';
+ for(var prop in attributes){
+ if(prop !== 'value'){
+ attributesAsString += prop + '="' + attributes[prop] + '" ';
+ }
+ }
+ return attributesAsString;
+ }
+ return null;
+ }
+ };
+})
+
+/* Context menu for grid*/
+.service('ContextMenuSelectedItem', function(){
+ this.selectedItem = '';
+
+ this.setSelectedItem = function(selectedItem){
+ this.selectedItem = selectedItem;
+ };
+
+ this.getSelectedItem = function(){
+ return this.selectedItem;
+ };
+})
+
+/* Error messages*/
+.service('ErrorMessageService', function(){
+ this.errorMessages = {};
+
+ this.setErrorMessages = function(errorMessages){
+ this.errorMessages = errorMessages;
+ };
+
+ this.getErrorMessages = function(){
+ return this.errorMessages;
+ };
+
+ this.get = function(id){
+ return this.errorMessages[id];
+ };
+})
+
+/* Modal service for user interaction */
+.service('ModalService', ['$modal', function($modal) {
+
+ var modalDefaults = {
+ backdrop: true,
+ keyboard: true,
+ modalFade: true,
+ templateUrl: 'views/modal.html'
+ };
+
+ var modalOptions = {
+ closeButtonText: 'Close',
+ actionButtonText: 'OK',
+ headerText: 'Proceed?',
+ bodyText: 'Perform this action?'
+ };
+
+ this.showModal = function(customModalDefaults, customModalOptions) {
+ if (!customModalDefaults)
+ customModalDefaults = {};
+ customModalDefaults.backdrop = 'static';
+ return this.show(customModalDefaults, customModalOptions);
+ };
+
+ this.show = function(customModalDefaults, customModalOptions) {
+ //Create temp objects to work with since we're in a singleton service
+ var tempModalDefaults = {};
+ var tempModalOptions = {};
+
+ //Map angular-ui modal custom defaults to modal defaults defined in service
+ angular.extend(tempModalDefaults, modalDefaults, customModalDefaults);
+
+ //Map modal.html $scope custom properties to defaults defined in service
+ angular.extend(tempModalOptions, modalOptions, customModalOptions);
+
+ if (!tempModalDefaults.controller) {
+ tempModalDefaults.controller = function($scope, $modalInstance) {
+ $scope.modalOptions = tempModalOptions;
+ $scope.modalOptions.ok = function(result) {
+ $modalInstance.close(result);
+ };
+ $scope.modalOptions.close = function(result) {
+ $modalInstance.dismiss('cancel');
+ };
+ };
+ }
+
+ return $modal.open(tempModalDefaults).result;
+ };
+
+}])
+
+/* Dialog service for user interaction */
+.service('DialogService', ['$modal', function($modal) {
+
+ var dialogDefaults = {
+ backdrop: true,
+ keyboard: true,
+ backdropClick: true,
+ modalFade: true,
+ templateUrl: 'views/dialog.html'
+ };
+
+ var dialogOptions = {
+ closeButtonText: 'close',
+ actionButtonText: 'ok',
+ headerText: 'dhis2_tracker',
+ bodyText: 'Perform this action?'
+ };
+
+ this.showDialog = function(customDialogDefaults, customDialogOptions) {
+ if (!customDialogDefaults)
+ customDialogDefaults = {};
+ customDialogDefaults.backdropClick = false;
+ return this.show(customDialogDefaults, customDialogOptions);
+ };
+
+ this.show = function(customDialogDefaults, customDialogOptions) {
+ //Create temp objects to work with since we're in a singleton service
+ var tempDialogDefaults = {};
+ var tempDialogOptions = {};
+
+ //Map angular-ui modal custom defaults to modal defaults defined in service
+ angular.extend(tempDialogDefaults, dialogDefaults, customDialogDefaults);
+
+ //Map modal.html $scope custom properties to defaults defined in service
+ angular.extend(tempDialogOptions, dialogOptions, customDialogOptions);
+
+ if (!tempDialogDefaults.controller) {
+ tempDialogDefaults.controller = function($scope, $modalInstance) {
+ $scope.dialogOptions = tempDialogOptions;
+ $scope.dialogOptions.ok = function(result) {
+ $modalInstance.close(result);
+ };
+ };
+ }
+
+ return $modal.open(tempDialogDefaults).result;
+ };
+
+}])
+
+.service('Paginator', function () {
+ this.page = 1;
+ this.pageSize = 50;
+ this.itemCount = 0;
+ this.pageCount = 0;
+ this.toolBarDisplay = 5;
+
+ this.setPage = function (page) {
+ if (page > this.getPageCount()) {
+ return;
+ }
+
+ this.page = page;
+ };
+
+ this.getPage = function(){
+ return this.page;
+ };
+
+ this.setPageSize = function(pageSize){
+ this.pageSize = pageSize;
+ };
+
+ this.getPageSize = function(){
+ return this.pageSize;
+ };
+
+ this.setItemCount = function(itemCount){
+ this.itemCount = itemCount;
+ };
+
+ this.getItemCount = function(){
+ return this.itemCount;
+ };
+
+ this.setPageCount = function(pageCount){
+ this.pageCount = pageCount;
+ };
+
+ this.getPageCount = function () {
+ return this.pageCount;
+ };
+
+ this.lowerLimit = function() {
+ var pageCountLimitPerPageDiff = this.getPageCount() - this.toolBarDisplay;
+
+ if (pageCountLimitPerPageDiff < 0) {
+ return 0;
+ }
+
+ if (this.getPage() > pageCountLimitPerPageDiff + 1) {
+ return pageCountLimitPerPageDiff;
+ }
+
+ var low = this.getPage() - (Math.ceil(this.toolBarDisplay/2) - 1);
+
+ return Math.max(low, 0);
+ };
+})
+
+.service('GridColumnService', function(){
+ return {
+ columnExists: function(cols, id) {
+ var colExists = false;
+ if(!angular.isObject(cols) || !id || angular.isObject(cols) && !cols.length){
+ return colExists;
+ }
+
+ for(var i=0; i<cols.length && !colExists; i++){
+ if(cols[i].id === id){
+ colExists = true;
+ }
+ }
+ return colExists;
+ }
+ };
+});
=== 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-01-29 17:13:36 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/scripts/services.js 2015-02-02 13:42:37 +0000
@@ -390,13 +390,17 @@
.factory('TEFormService', function(TCStorageService, $q, $rootScope) {
return {
- getByProgram: function(programUid){
+ getByProgram: function(program, attributes){
var def = $q.defer();
TCStorageService.currentStore.open().done(function(){
- TCStorageService.currentStore.get('trackedEntityForms', programUid).done(function(te){
+ TCStorageService.currentStore.get('trackedEntityForms', program.id).done(function(teForm){
$rootScope.$apply(function(){
- def.resolve(te);
+ var trackedEntityForm = teForm;
+ trackedEntityForm.attributes = attributes;
+ trackedEntityForm.selectIncidentDatesInFuture = program.selectIncidentDatesInFuture;
+ trackedEntityForm.selectEnrollmentDatesInFuture = program.selectEnrollmentDatesInFuture;
+ def.resolve(trackedEntityForm);
});
});
});
=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/tracker-capture.appcache'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/tracker-capture.appcache 2015-01-23 14:07:46 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/tracker-capture.appcache 2015-02-02 13:42:37 +0000
@@ -39,6 +39,10 @@
../dhis-web-commons/javascripts/angular/plugins/angular-translate.min.js
../dhis-web-commons/javascripts/angular/plugins/angular-translate-loader-static-files.min.js
../dhis-web-commons/javascripts/angular/plugins/angular-translate-loader-url.min.js
+../dhis-web-commons/javascripts/dhis2/angular.directives.js
+../dhis-web-commons/javascripts/dhis2/angular.filters.js
+../dhis-web-commons/javascripts/dhis2/angular.services.js
+../dhis-web-commons/javascripts/dhis2/angular.controllers.js
../dhis-web-commons/javascripts/moment/moment-with-langs.min.js
=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/green/green.css'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/green/green.css 2014-11-26 13:33:14 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/green/green.css 2015-02-02 13:42:37 +0000
@@ -42,7 +42,7 @@
text-decoration: underline;
}
-input[type=text],input[type=password],textarea
+input[type=text],input[type=password],input[type=email],textarea
{
border: 1px solid #aaa;
padding: 4px 1px;
=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/india/india.css'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/india/india.css 2014-07-23 06:59:30 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/india/india.css 2015-02-02 13:42:37 +0000
@@ -42,7 +42,7 @@
text-decoration: underline;
}
-input[type=text],input[type=password],textarea
+input[type=text],input[type=password],input[type=email],textarea
{
border: 1px solid #aaa;
padding: 4px 1px;
=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/light_blue/light_blue.css'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/light_blue/light_blue.css 2014-11-26 13:33:14 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/light_blue/light_blue.css 2015-02-02 13:42:37 +0000
@@ -42,7 +42,7 @@
text-decoration: underline;
}
-input[type=text],input[type=password],textarea
+input[type=text],input[type=password],input[type=email],textarea
{
border: 1px solid #aaa;
padding: 4px 1px;
=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/myanmar/myanmar.css'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/myanmar/myanmar.css 2014-11-26 13:33:14 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/myanmar/myanmar.css 2015-02-02 13:42:37 +0000
@@ -42,7 +42,7 @@
text-decoration: underline;
}
-input[type=text],input[type=password],textarea
+input[type=text],input[type=password],input[type=email],textarea
{
border: 1px solid #aaa;
padding: 4px 1px;
=== modified file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/vietnam/vietnam.css'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/vietnam/vietnam.css 2014-11-26 13:33:14 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/css/vietnam/vietnam.css 2015-02-02 13:42:37 +0000
@@ -42,7 +42,7 @@
text-decoration: underline;
}
-input[type=text],input[type=password],textarea
+input[type=text],input[type=password],input[type=email],textarea
{
border: 1px solid #aaa;
padding: 4px 1px;
=== removed directory 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2'
=== removed file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/controllers.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/controllers.js 2015-01-29 17:13:36 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/controllers.js 1970-01-01 00:00:00 +0000
@@ -1,53 +0,0 @@
-'use strict';
-
-/* Controllers */
-var d2Controllers = angular.module('d2Controllers', [])
-
-//Controller for column show/hide
-.controller('ColumnDisplayController',
- function($scope,
- $modalInstance,
- hiddenGridColumns,
- gridColumns){
-
- $scope.gridColumns = gridColumns;
- $scope.hiddenGridColumns = hiddenGridColumns;
-
- $scope.close = function () {
- $modalInstance.close($scope.gridColumns);
- };
-
- $scope.showHideColumns = function(gridColumn){
-
- if(gridColumn.show){
- $scope.hiddenGridColumns--;
- }
- else{
- $scope.hiddenGridColumns++;
- }
- };
-})
-
-//controller for dealing with google map
-.controller('MapController',
- function($scope,
- $modalInstance,
- DHIS2URL,
- geoJsons,
- location) {
-
- $scope.home = function(){
- window.location = DHIS2URL;
- };
-
- $scope.location = location;
- $scope.geoJsons = geoJsons;
-
- $scope.close = function () {
- $modalInstance.close();
- };
-
- $scope.captureCoordinate = function(){
- $modalInstance.close($scope.location);
- };
-});
\ No newline at end of file
=== removed file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/directives.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/directives.js 2015-01-27 22:51:17 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/directives.js 1970-01-01 00:00:00 +0000
@@ -1,582 +0,0 @@
-'use strict';
-
-/* Directives */
-
-var d2Directives = angular.module('d2Directives', [])
-
-
-.directive('d2OuSearch', function() {
-
- return {
- restrict: 'E',
- template: '<div style="margin-top:20px">\n\
- <img id="searchIcon" src="../images/search.png" style="cursor: pointer" title="{{ \'locate_organisation_unit_by_name\' | translate}}">\n\
- <span id="searchSpan" style="width:100%;display:none;">\n\
- <input type="text" id="searchField" name="key"/>\n\
- <input type="button" value="{{\'find\' | translate}}" onclick="selection.findByName()"/>\n\
- </span>\n\
- </div>',
- link: function (scope, element, attrs) {
-
- $("#searchIcon").click(function() {
- $("#searchSpan").toggle();
- $("#searchField").focus();
- });
-
- $("#searchField").autocomplete({
- source: "../dhis-web-commons/ouwt/getOrganisationUnitsByName.action",
- select: function(event, ui) {
- $("#searchField").val(ui.item.value);
- selection.findByName();
- }
- });
- }
- };
-})
-
-.directive('inputValidator', function() {
-
- return {
- require: 'ngModel',
- link: function (scope, element, attrs, ctrl) {
-
- ctrl.$parsers.push(function (value) {
- return parseFloat(value || '');
- });
- }
- };
-})
-
-.directive('selectedOrgUnit', function($timeout, storage) {
-
- return {
- restrict: 'A',
- link: function(scope, element, attrs){
-
- //once ou tree is loaded, start meta-data download
- $(function() {
- dhis2.ou.store.open().done( function() {
- selection.load();
- $( "#orgUnitTree" ).one( "ouwtLoaded", function(event, ids, names) {
- console.log('Finished loading orgunit tree');
-
- //Disable ou selection until meta-data has downloaded
- $( "#orgUnitTree" ).addClass( "disable-clicks" );
-
- $timeout(function() {
- scope.treeLoaded = true;
- scope.$apply();
- });
-
- downloadMetaData();
- });
- });
- });
-
- //listen to user selection, and inform angular
- selection.setListenerFunction( setSelectedOu, true );
-
- function setSelectedOu( ids, names ) {
- var ou = {id: ids[0], name: names[0]};
- $timeout(function() {
- scope.selectedOrgUnit = ou;
- scope.$apply();
- });
- }
- }
- };
-})
-
-.directive('blurOrChange', function() {
-
- return function( scope, elem, attrs) {
- elem.calendarsPicker({
- onSelect: function() {
- scope.$apply(attrs.blurOrChange);
- $(this).change();
- }
- }).change(function() {
- scope.$apply(attrs.blurOrChange);
- });
- };
-})
-
-.directive('d2Enter', function () {
- return function (scope, element, attrs) {
- element.bind("keydown keypress", function (event) {
- if(event.which === 13) {
- scope.$apply(function (){
- scope.$eval(attrs.d2Enter);
- });
- event.preventDefault();
- }
- });
- };
-})
-
-.directive('d2NumberValidation', function(ErrorMessageService, $translate) {
-
- return {
- require: 'ngModel',
- restrict: 'A',
- link: function (scope, element, attrs, ctrl) {
-
- function checkValidity(numberType, value){
- var isValid = false;
- switch(numberType){
- case "number":
- isValid = dhis2.validation.isNumber(value);
- break;
- case "posInt":
- isValid = dhis2.validation.isPositiveInt(value);
- break;
- case "negInt":
- isValid = dhis2.validation.isNegativeInt(value);
- break;
- case "zeroPositiveInt":
- isValid = dhis2.validation.isZeroOrPositiveInt(value);
- break;
- case "int":
- isValid = dhis2.validation.isInt(value);
- break;
- default:
- isValid = true;
- }
- return isValid;
- }
-
- var errorMessages = ErrorMessageService.getErrorMessages();
- var fieldName = attrs.inputFieldId;
- var numberType = attrs.numberType;
- var isRequired = attrs.ngRequired === 'true';
- var msg = $translate(numberType)+ ' ' + $translate('required');
-
- ctrl.$parsers.unshift(function(value) {
- if(value){
- var isValid = checkValidity(numberType, value);
- if(!isValid){
- errorMessages[fieldName] = $translate('value_must_be_' + numberType);
- }
- else{
- if(isRequired){
- errorMessages[fieldName] = msg;
- }
- else{
- errorMessages[fieldName] = "";
- }
- }
-
- ErrorMessageService.setErrorMessages(errorMessages);
- ctrl.$setValidity(fieldName, isValid);
- return value;
- }
-
- if(value === ''){
- if(isRequired){
- errorMessages[fieldName] = msg;
- }
- else{
- ctrl.$setValidity(fieldName, true);
- errorMessages[fieldName] = "";
- }
-
- ErrorMessageService.setErrorMessages(errorMessages);
- return undefined;
- }
- });
-
- ctrl.$formatters.unshift(function(value) {
- if(value){
- var isValid = checkValidity(numberType, value);
- ctrl.$setValidity(fieldName, isValid);
- return value;
- }
- });
- }
- };
-})
-
-.directive('typeaheadOpenOnFocus', function () {
-
- return {
- require: ['typeahead', 'ngModel'],
- link: function (scope, element, attr, ctrls) {
- element.bind('focus', function () {
- ctrls[0].getMatchesAsync(ctrls[1].$viewValue);
- scope.$watch(attr.ngModel, function(value) {
- if(value === '' || angular.isUndefined(value)){
- ctrls[0].getMatchesAsync(ctrls[1].$viewValue);
- }
- });
- });
- }
- };
-})
-
-.directive('d2TypeaheadValidation', function() {
-
- return {
- require: ['typeahead', 'ngModel'],
- restrict: 'A',
- link: function (scope, element, attrs, ctrls) {
- element.bind('blur', function () {
- if(ctrls[1].$viewValue && !ctrls[1].$modelValue && ctrls[0].active === -1){
- ctrls[1].$setViewValue();
- ctrls[1].$render();
- }
- });
- }
- };
-})
-
-.directive('d2PopOver', function($compile, $templateCache){
-
- return {
- restrict: 'EA',
- link: function(scope, element, attrs){
- var content = $templateCache.get("popover.html");
- content = $compile(content)(scope);
- var options = {
- content: content,
- placement: 'bottom',
- trigger: 'hover',
- html: true,
- title: scope.title
- };
- $(element).popover(options);
- },
- scope: {
- content: '=',
- title: '@details',
- template: "@template"
- }
- };
-})
-
-.directive('sortable', function() {
-
- return {
- restrict: 'A',
- link: function(scope, element, attrs){
- element.sortable({
- connectWith: ".connectedSortable",
- placeholder: "ui-state-highlight",
- tolerance: "pointer",
- handle: '.handle'
- });
- }
- };
-})
-
-.directive('serversidePaginator', function factory() {
-
- return {
- restrict: 'E',
- controller: function ($scope, Paginator) {
- $scope.paginator = Paginator;
- },
- templateUrl: '../dhis-web-commons/paging/serverside-pagination.html'
- };
-})
-
-.directive('draggableModal', function(){
-
- return {
- restrict: 'EA',
- link: function(scope, element) {
- element.draggable();
- }
- };
-})
-
-.directive('d2GoogleMap', function ($parse, $compile, storage) {
- return {
- restrict: 'E',
- replace: true,
- template: '<div></div>',
- link: function(scope, element, attrs){
-
- //remove angular bootstrap ui modal draggable
- $(".modal-content").draggable({ disabled: true });
-
- //get a default center
- var latCenter = 12.31, lngCenter = 51.48;
-
- //if there is any marker already - use it as center
- if(angular.isObject(scope.location)){
- if(scope.location.lat && scope.location.lng){
- latCenter = scope.location.lat;
- lngCenter = scope.location.lng;
- }
- }
-
- //default map configurations
- var mapOptions = {
- zoom: 3,
- center: new google.maps.LatLng(latCenter, lngCenter),
- mapTypeId: google.maps.MapTypeId.ROADMAP
- },featureStyle = {
- strokeWeight: 2,
- strokeOpacity: 0.4,
- fillOpacity: 0.4,
- fillColor: 'green'
- };
-
- var geojsons = $parse(attrs.geojsons)(scope);
- var currentLayer = 0, currentGeojson = geojsons[0];
-
- var map = new google.maps.Map(document.getElementById(attrs.id), mapOptions);
- var currentGeojsonFeatures = map.data.addGeoJson(currentGeojson);
-
- var marker = new google.maps.Marker({
- map: map
- });
-
- if(angular.isObject(scope.location)){
- if(scope.location.lat && scope.location.lng){
- addMarker({lat: scope.location.lat, lng: scope.location.lng});
- }
- }
-
- function addMarker(loc){
- var latLng = new google.maps.LatLng(loc.lat, loc.lng);
- marker.setPosition(latLng);
- }
-
- function centerMap(){
-
- if(currentGeojson && currentGeojson.features){
- var latLngBounds = new google.maps.LatLngBounds();
- angular.forEach(currentGeojson.features, function(feature){
- if(feature.geometry.type === 'MultiPolygon'){
- angular.forEach(feature.geometry.coordinates[0][0], function(coordinate){
- latLngBounds.extend(new google.maps.LatLng(coordinate[1],coordinate[0]));
- });
- }
- else if(feature.geometry.type === 'Point'){
- latLngBounds.extend(new google.maps.LatLng(feature.geometry.coordinates[1],feature.geometry.coordinates[0]));
- }
- });
-
- map.fitBounds(latLngBounds);
- map.panToBounds(latLngBounds);
- }
- }
-
- function initializeMap(){
- google.maps.event.addListenerOnce(map, 'idle', function(){
- google.maps.event.trigger(map, 'resize');
- map.data.setStyle(featureStyle);
- centerMap();
- });
- }
-
- map.data.addListener('mouseover', function(e) {
- $("#polygon-label").text( e.feature.k.name );
- map.data.revertStyle();
- map.data.overrideStyle(e.feature, {fillOpacity: 0.8});
- });
-
- map.data.addListener('mouseout', function() {
- $("#polygon-label").text( '' );
- map.data.revertStyle();
- });
-
- //drill-down based on polygons assigned to orgunits
- map.data.addListener('rightclick', function(e){
- for (var i = 0; i < currentGeojsonFeatures.length; i++){
- map.data.remove(currentGeojsonFeatures[i]);
- }
-
- if(currentLayer >= geojsons.length-1){
- currentLayer = 0;
- currentGeojson = angular.copy(geojsons[currentLayer]);
- }
- else{
- currentLayer++;
- currentGeojson = angular.copy(geojsons[currentLayer]);
- currentGeojson.features = [];
- var selectedFeatures = [];
- angular.forEach(geojsons[currentLayer].features, function(feature){
- if(feature.properties.parent === e.feature.B){
- selectedFeatures.push(feature);
- }
- });
-
- if(selectedFeatures.length){
- currentGeojson.features = selectedFeatures;
- }
- }
- currentGeojsonFeatures = map.data.addGeoJson(currentGeojson);
- centerMap();
- });
-
- //capturing coordinate from defined polygons
- map.data.addListener('click', function(e) {
- scope.$apply(function(){
- addMarker({
- lat: e.latLng.lat(),
- lng: e.latLng.lng()
- });
- $parse(attrs.location).assign(scope.$parent, {lat: e.latLng.lat(), lng: e.latLng.lng()});
- });
- });
-
- //capturing coordinate from anywhere in the map - incase no polygons are defined
- google.maps.event.addListener(map, 'click', function(e){
- scope.$apply(function(){
- addMarker({
- lat: e.latLng.lat(),
- lng: e.latLng.lng()
- });
- $parse(attrs.location).assign(scope.$parent, {lat: e.latLng.lat(), lng: e.latLng.lng()});
- });
- });
-
- initializeMap();
- }
- };
-})
-
-.directive('d2CustomForm', function($compile, $parse, CustomFormService) {
- return{
- restrict: 'E',
- link: function(scope, elm, attrs){
- scope.$watch('customForm', function(){
- elm.html(scope.customForm.htmlCode);
- $compile(elm.contents())(scope);
- });
- }
- };
-})
-
-.directive('d2ContextMenu', function(ContextMenuSelectedItem) {
-
- return {
- restrict: 'A',
- link: function(scope, element, attrs){
- var contextMenu = $("#contextMenu");
-
- element.click(function (e) {
- var selectedItem = $.parseJSON(attrs.selectedItem);
- ContextMenuSelectedItem.setSelectedItem(selectedItem);
-
- var menuHeight = contextMenu.height();
- var menuWidth = contextMenu.width();
- var winHeight = $(window).height();
- var winWidth = $(window).width();
-
- var pageX = e.pageX;
- var pageY = e.pageY;
-
- contextMenu.show();
-
- if( (menuWidth + pageX) > winWidth ) {
- pageX -= menuWidth;
- }
-
- if( (menuHeight + pageY) > winHeight ) {
- pageY -= menuHeight;
-
- if( pageY < 0 ) {
- pageY = e.pageY;
- }
- }
-
- contextMenu.css({
- left: pageX,
- top: pageY
- });
-
- return false;
- });
-
- contextMenu.on("click", "a", function () {
- contextMenu.hide();
- });
-
- $(document).click(function () {
- contextMenu.hide();
- });
- }
- };
-})
-
-.directive('d2Date', function(DateUtils, CalendarService, ErrorMessageService, $translate, $parse) {
- return {
- restrict: 'A',
- require: 'ngModel',
- link: function(scope, element, attrs, ctrl) {
-
- var errorMessages = ErrorMessageService.getErrorMessages();
- var fieldName = attrs.inputFieldId;
- var isRequired = attrs.ngRequired === 'true';
- var calendarSetting = CalendarService.getSetting();
- var dateFormat = 'yyyy-mm-dd';
- if(calendarSetting.keyDateFormat === 'dd-MM-yyyy'){
- dateFormat = 'dd-mm-yyyy';
- }
-
- var minDate = $parse(attrs.minDate)(scope),
- maxDate = $parse(attrs.maxDate)(scope),
- calendar = $.calendars.instance(calendarSetting.keyCalendar);
-
- element.calendarsPicker({
- changeMonth: true,
- dateFormat: dateFormat,
- yearRange: '-120:+30',
- minDate: minDate,
- maxDate: maxDate,
- calendar: calendar,
- duration: "fast",
- showAnim: "",
- renderer: $.calendars.picker.themeRollerRenderer,
- onSelect: function(date) {
- $(this).change();
- }
- })
- .change(function() {
- if(this.value){
- var rawDate = this.value;
- var convertedDate = DateUtils.format(this.value);
-
- var isValid = rawDate == convertedDate;
-
- if(!isValid){
- errorMessages[fieldName] = $translate('date_required');
- }
- else{
- if(isRequired){
- errorMessages[fieldName] = $translate('required');
- }
- else{
- errorMessages[fieldName] = "";
- }
- if(maxDate === 0){
- isValid = !moment(convertedDate, calendarSetting.momentFormat).isAfter(DateUtils.getToday());
- if(!isValid){
- errorMessages[fieldName] = $translate('future_date_not_allowed');
- }
- }
- }
- ctrl.$setViewValue(this.value);
- ctrl.$setValidity(fieldName, isValid);
- }
- else{
- if(!isRequired){
- ctrl.$setViewValue(this.value);
- ctrl.$setValidity(fieldName, !isRequired);
- errorMessages[fieldName] = "";
- }
- else{
- errorMessages[fieldName] = $translate('required');
- }
- }
-
- ErrorMessageService.setErrorMessages(errorMessages);
- this.focus();
- scope.$apply();
- });
- }
- };
-});
\ No newline at end of file
=== removed file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/filters.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/filters.js 2014-12-04 13:04:31 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/filters.js 1970-01-01 00:00:00 +0000
@@ -1,97 +0,0 @@
-'use strict';
-
-/* Filters */
-
-var d2Filters = angular.module('d2Filters', [])
-
-.filter('gridFilter', function($filter, CalendarService){
-
- return function(data, filters, filterTypes){
-
- if(!data ){
- return;
- }
-
- if(!filters){
- return data;
- }
- else{
-
- var dateFilter = {},
- textFilter = {},
- numberFilter = {},
- filteredData = data;
-
- for(var key in filters){
-
- if(filterTypes[key] === 'date'){
- if(filters[key].start || filters[key].end){
- dateFilter[key] = filters[key];
- }
- }
- else if(filterTypes[key] === 'int'){
- if(filters[key].start || filters[key].end){
- numberFilter[key] = filters[key];
- }
- }
- else{
- textFilter[key] = filters[key];
- }
- }
-
- filteredData = $filter('filter')(filteredData, textFilter);
- filteredData = $filter('filter')(filteredData, dateFilter, dateComparator);
- filteredData = $filter('filter')(filteredData, numberFilter, numberComparator);
-
- return filteredData;
- }
- };
-
- function dateComparator(data,filter){
- var calendarSetting = CalendarService.getSetting();
- var start = moment(filter.start, calendarSetting.momentFormat);
- var end = moment(filter.end, calendarSetting.momentFormat);
- var date = moment(data, calendarSetting.momentFormat);
-
- if(filter.start && filter.end){
- return ( Date.parse(date) <= Date.parse(end) ) && (Date.parse(date) >= Date.parse(start));
- }
- return ( Date.parse(date) <= Date.parse(end) ) || (Date.parse(date) >= Date.parse(start));
- }
-
- function numberComparator(data,filter){
- var start = filter.start;
- var end = filter.end;
-
- if(filter.start && filter.end){
- return ( data <= end ) && ( data >= start );
- }
- return ( data <= end ) || ( data >= start );
- }
-})
-
-.filter('paginate', function(Paginator) {
- return function(input, rowsPerPage) {
- if (!input) {
- return input;
- }
-
- if (rowsPerPage) {
- Paginator.rowsPerPage = rowsPerPage;
- }
-
- Paginator.itemCount = input.length;
-
- return input.slice(parseInt(Paginator.page * Paginator.rowsPerPage), parseInt((Paginator.page + 1) * Paginator.rowsPerPage + 1) - 1);
- };
-})
-
-.filter('forLoop', function() {
- return function(input, start, end) {
- input = new Array(end - start);
- for (var i = 0; start < end; start++, i++) {
- input[i] = start;
- }
- return input;
- };
-});
\ No newline at end of file
=== removed file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/services.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/services.js 2015-01-26 17:47:09 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/angular/plugins/dhis2/services.js 1970-01-01 00:00:00 +0000
@@ -1,560 +0,0 @@
-/* Pagination service */
-var d2Services = angular.module('d2Services', ['ngResource'])
-
-/* Factory for loading translation strings */
-.factory('i18nLoader', function ($q, $http, storage, DialogService) {
-
- var getTranslationStrings = function(locale){
- var defaultUrl = 'i18n/i18n_app.properties';
- var url = '';
- if(locale === 'en' || !locale){
- url = defaultUrl;
- }
- else{
- url = 'i18n/i18n_app_' + locale + '.properties';
- }
-
- var tx = {locale: locale};
-
- var promise = $http.get(url).then(function(response){
- tx= {locale: locale, keys: dhis2.util.parseJavaProperties(response.data)};
- return tx;
- }, function(){
- var dialogOptions = {
- headerText: 'missing_translation_file',
- bodyText: 'missing_translation_using_default'
- };
-
- DialogService.showDialog({}, dialogOptions);
- var p = $http.get(defaultUrl).then(function(response){
- tx= {locale: locale, keys: dhis2.util.parseJavaProperties(response.data)};
- return tx;
- });
- return p;
- });
- return promise;
- };
-
- var getLocale = function(){
- var locale = 'en';
-
- var promise = $http.get('../api/me/profile.json').then(function(response){
- storage.set('USER_PROFILE', response.data);
- if(response.data && response.data.settings && response.data.settings.keyUiLocale){
- locale = response.data.settings.keyUiLocale;
- }
- return locale;
- }, function(){
- return locale;
- });
-
- return promise;
- };
- return function () {
- var deferred = $q.defer(), translations;
- var userProfile = storage.get('USER_PROFILE');
- if(userProfile && userProfile.settings && userProfile.settings.keyUiLocale){
- getTranslationStrings(userProfile.settings.keyUiLocale).then(function(response){
- translations = response.keys;
- deferred.resolve(translations);
- });
- return deferred.promise;
- }
- else{
- getLocale().then(function(locale){
- getTranslationStrings(locale).then(function(response){
- translations = response.keys;
- deferred.resolve(translations);
- });
- });
- return deferred.promise;
- }
- };
-})
-
-/* Factory for loading external data */
-.factory('ExternalDataFactory', function($http) {
-
- return {
- get: function(fileName) {
- var promise = $http.get( fileName ).then(function(response){
- return response.data;
- });
- return promise;
- }
- };
-})
-
-/* service for getting calendar setting */
-.service('CalendarService', function(storage, $rootScope){
-
- return {
- getSetting: function() {
-
- var dhis2CalendarFormat = {keyDateFormat: 'yyyy-MM-dd', keyCalendar: 'gregorian', momentFormat: 'YYYY-MM-DD'};
- var storedFormat = storage.get('CALENDAR_SETTING');
- if(angular.isObject(storedFormat) && storedFormat.keyDateFormat && storedFormat.keyCalendar){
- if(storedFormat.keyCalendar === 'iso8601'){
- storedFormat.keyCalendar = 'gregorian';
- }
-
- if(storedFormat.keyDateFormat === 'dd-MM-yyyy'){
- dhis2CalendarFormat.momentFormat = 'DD-MM-YYYY';
- }
-
- dhis2CalendarFormat.keyCalendar = storedFormat.keyCalendar;
- dhis2CalendarFormat.keyDateFormat = storedFormat.keyDateFormat;
- }
- $rootScope.dhis2CalendarFormat = dhis2CalendarFormat;
- return dhis2CalendarFormat;
- }
- };
-})
-
-/* service for dealing with dates */
-.service('DateUtils', function($filter, CalendarService){
-
- return {
- getDate: function(dateValue){
- if(!dateValue){
- return;
- }
- var calendarSetting = CalendarService.getSetting();
- dateValue = moment(dateValue, calendarSetting.momentFormat)._d;
- return Date.parse(dateValue);
- },
- format: function(dateValue) {
- if(!dateValue){
- return;
- }
-
- var calendarSetting = CalendarService.getSetting();
- dateValue = moment(dateValue, calendarSetting.momentFormat)._d;
- dateValue = $filter('date')(dateValue, calendarSetting.keyDateFormat);
- return dateValue;
- },
- formatToHrsMins: function(dateValue) {
- var calendarSetting = CalendarService.getSetting();
- var dateFormat = 'YYYY-MM-DD @ hh:mm A';
- if(calendarSetting.keyDateFormat === 'dd-MM-yyyy'){
- dateFormat = 'DD-MM-YYYY @ hh:mm A';
- }
- return moment(dateValue).format(dateFormat);
- },
- getToday: function(){
- var calendarSetting = CalendarService.getSetting();
- var tdy = $.calendars.instance(calendarSetting.keyCalendar).newDate();
- var today = moment(tdy._year + '-' + tdy._month + '-' + tdy._day, 'YYYY-MM-DD')._d;
- today = Date.parse(today);
- today = $filter('date')(today, calendarSetting.keyDateFormat);
- return today;
- },
- formatFromUserToApi: function(dateValue){
- if(!dateValue){
- return;
- }
- var calendarSetting = CalendarService.getSetting();
- dateValue = moment(dateValue, calendarSetting.momentFormat)._d;
- dateValue = Date.parse(dateValue);
- dateValue = $filter('date')(dateValue, 'yyyy-MM-dd');
- return dateValue;
- },
- formatFromApiToUser: function(dateValue){
- if(!dateValue){
- return;
- }
- var calendarSetting = CalendarService.getSetting();
- dateValue = moment(dateValue, 'YYYY-MM-DD')._d;
- return $filter('date')(dateValue, calendarSetting.keyDateFormat);
- }
- };
-})
-
-/* service for dealing with custom form */
-.service('CustomFormService', function(){
-
- return {
- getForProgramStage: function(programStage){
-
- var htmlCode = programStage.dataEntryForm ? programStage.dataEntryForm.htmlCode : null;
-
- if(htmlCode){
-
- var programStageDataElements = [];
-
- angular.forEach(programStage.programStageDataElements, function(prStDe){
- programStageDataElements[prStDe.dataElement.id] = prStDe;
- });
-
- var inputRegex = /<input.*?\/>/g,
- match,
- inputFields = [];
-
- while (match = inputRegex.exec(htmlCode)) {
- inputFields.push(match[0]);
- }
-
- for(var i=0; i<inputFields.length; i++){
- var inputField = inputFields[i];
- var inputElement = $.parseHTML( inputField );
- var attributes = {};
-
- $(inputElement[0].attributes).each(function() {
- attributes[this.nodeName] = this.value;
- });
-
- var fieldId = '', errorMessageId = '', newInputField, hasEventDate = false;
- if(attributes.hasOwnProperty('id')){
-
- if(attributes['id'] === 'executionDate'){
- fieldId = 'eventDate';
- errorMessageId = '"' + 'eventDate' + '"';
- hasEventDate = true;
-
- //name needs to be unique so that it can be used for validation in angularjs
- if(attributes.hasOwnProperty('name')){
- attributes['name'] = fieldId;
- }
-
- newInputField = '<input type="text" ' +
- this.getAttributesAsString(attributes) +
- ' d2-validation ' +
- ' ng-model="currentEvent.' + fieldId + '"' +
- ' input-field-id="' + fieldId + '"' +
- ' d2-date ' +
- ' max-date="' + 0 + '"' +
- ' placeholder="{{dhis2CalendarFormat.keyDateFormat}}" ' +
- ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
- ' blur-or-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
- ' ng-required="{{true}}">';
- }
- else{
- fieldId = attributes['id'].substring(4, attributes['id'].length-1).split("-")[1];
- errorMessageId = 'prStDes.' + fieldId + '.dataElement.id';
-
- //name needs to be unique so that it can be used for validation in angularjs
- if(attributes.hasOwnProperty('name')){
- attributes['name'] = fieldId;
- }
-
- //check data element type and generate corresponding angular input field
- if(programStageDataElements[fieldId].dataElement.type === "int"){
- newInputField = '<input type="text" ' +
- this.getAttributesAsString(attributes) +
- ' d2-validation ' +
- ' d2-number-validation ' +
- ' number-type="' + programStageDataElements[fieldId].dataElement.numberType + '" ' +
- ' ng-model="currentEvent.' + fieldId + '"' +
- ' input-field-id="' + fieldId + '"' +
- ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
- ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
- ' ng-blur="saveDatavalue(prStDes.'+ fieldId + ')"' +
- ' ng-required="{{prStDes.' + fieldId + '.compulsory}}">';
- }
- if(programStageDataElements[fieldId].dataElement.type === "string"){
- if(programStageDataElements[fieldId].dataElement.optionSet){
- var optionSetId = programStageDataElements[fieldId].dataElement.optionSet.id;
- newInputField = '<input type="text" ' +
- this.getAttributesAsString(attributes) +
- ' d2-validation ' +
- ' ng-model="currentEvent.' + fieldId + '" ' +
- ' input-field-id="' + fieldId + '"' +
- ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\' || currentEvent[uid]==\'uid\'"' +
- ' ng-required="{{prStDes.' + fieldId + '.compulsory}}"' +
- ' typeahead="option.name as option.name for option in optionSets.'+optionSetId+'.options | filter:$viewValue | limitTo:20"' +
- ' typeahead-editable="false" ' +
- ' d2-typeahead-validation ' +
- ' class="typeahead" ' +
- ' placeholder=" " ' +
- ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
- ' ng-blur="saveDatavalue(prStDes.'+ fieldId + ')"' +
- ' typeahead-open-on-focus ng-required="prStDes.'+fieldId+'.compulsory"> ';
- }
- else{
- newInputField = '<input type="text" ' +
- this.getAttributesAsString(attributes) +
- ' d2-validation ' +
- ' ng-model="currentEvent.' + fieldId + '" ' +
- ' input-field-id="' + fieldId + '"' +
- ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\' || currentEvent[uid]==\'uid\'"' +
- ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
- ' ng-blur="saveDatavalue(prStDes.'+ fieldId + ')"' +
- ' ng-required="prStDes.' + fieldId + '.compulsory"> ';
- }
- }
- if(programStageDataElements[fieldId].dataElement.type === "bool"){
- newInputField = '<select ' +
- this.getAttributesAsString(attributes) +
- ' d2-validation ' +
- ' ng-model="currentEvent.' + fieldId + '" ' +
- ' input-field-id="' + fieldId + '"' +
- ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
- ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
- ' ng-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
- ' ng-required="{{prStDes.' + fieldId + '.compulsory}}">' +
- '<option value="">{{\'please_select\'| translate}}</option>' +
- '<option value="false">{{\'no\'| translate}}</option>' +
- '<option value="true">{{\'yes\'| translate}}</option>' +
- '</select> ';
- }
- if(programStageDataElements[fieldId].dataElement.type === "date"){
- var maxDate = programStageDataElements[fieldId].allowFutureDate ? '' : 0;
- newInputField = '<input type="text" ' +
- this.getAttributesAsString(attributes) +
- ' d2-validation ' +
- ' ng-model="currentEvent.' + fieldId + '"' +
- ' input-field-id="' + fieldId + '"' +
- ' placeholder="{{dhis2CalendarFormat.keyDateFormat}}" ' +
- ' d2-date ' +
- ' max-date="' + maxDate + '"' +
- ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
- ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
- ' blur-or-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
- ' ng-required="{{prStDes.' + fieldId + '.compulsory}}"> ';
- }
- if(programStageDataElements[fieldId].dataElement.type === "trueOnly"){
- newInputField = '<input type="checkbox" ' +
- this.getAttributesAsString(attributes) +
- ' d2-validation ' +
- ' ng-model="currentEvent.' + fieldId + '"' +
- ' input-field-id="' + fieldId + '"' +
- ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
- ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
- ' ng-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
- ' ng-required="{{prStDes.' + fieldId + '.compulsory}}"> ';
- }
- }
-
- newInputField = newInputField + ' <span ng-show="(outerForm.'+ fieldId +'.$dirty && outerForm.'+ fieldId +'.$invalid) || (outerForm.submitted && outerForm.'+ fieldId +'.$invalid) || (currentEvent.' + fieldId + ' && outerForm.' + fieldId + '.$invalid)" class="required">{{getErrorMessage(' + errorMessageId + ')}}</span> ';
-
- htmlCode = htmlCode.replace(inputField, newInputField);
- }
- }
- return {htmlCode: htmlCode, hasEventDate: hasEventDate};
- }
- return null;
- },
- getAttributesAsString: function(attributes){
- if(attributes){
- var attributesAsString = '';
- for(var prop in attributes){
- if(prop !== 'value'){
- attributesAsString += prop + '="' + attributes[prop] + '" ';
- }
- }
- return attributesAsString;
- }
- return null;
- }
- };
-})
-
-/* Context menu for grid*/
-.service('ContextMenuSelectedItem', function(){
- this.selectedItem = '';
-
- this.setSelectedItem = function(selectedItem){
- this.selectedItem = selectedItem;
- };
-
- this.getSelectedItem = function(){
- return this.selectedItem;
- };
-})
-
-/* Error messages*/
-.service('ErrorMessageService', function(){
- this.errorMessages = {};
-
- this.setErrorMessages = function(errorMessages){
- this.errorMessages = errorMessages;
- };
-
- this.getErrorMessages = function(){
- return this.errorMessages;
- };
-
- this.get = function(id){
- return this.errorMessages[id];
- };
-})
-
-/* Modal service for user interaction */
-.service('ModalService', ['$modal', function($modal) {
-
- var modalDefaults = {
- backdrop: true,
- keyboard: true,
- modalFade: true,
- templateUrl: 'views/modal.html'
- };
-
- var modalOptions = {
- closeButtonText: 'Close',
- actionButtonText: 'OK',
- headerText: 'Proceed?',
- bodyText: 'Perform this action?'
- };
-
- this.showModal = function(customModalDefaults, customModalOptions) {
- if (!customModalDefaults)
- customModalDefaults = {};
- customModalDefaults.backdrop = 'static';
- return this.show(customModalDefaults, customModalOptions);
- };
-
- this.show = function(customModalDefaults, customModalOptions) {
- //Create temp objects to work with since we're in a singleton service
- var tempModalDefaults = {};
- var tempModalOptions = {};
-
- //Map angular-ui modal custom defaults to modal defaults defined in service
- angular.extend(tempModalDefaults, modalDefaults, customModalDefaults);
-
- //Map modal.html $scope custom properties to defaults defined in service
- angular.extend(tempModalOptions, modalOptions, customModalOptions);
-
- if (!tempModalDefaults.controller) {
- tempModalDefaults.controller = function($scope, $modalInstance) {
- $scope.modalOptions = tempModalOptions;
- $scope.modalOptions.ok = function(result) {
- $modalInstance.close(result);
- };
- $scope.modalOptions.close = function(result) {
- $modalInstance.dismiss('cancel');
- };
- };
- }
-
- return $modal.open(tempModalDefaults).result;
- };
-
-}])
-
-/* Dialog service for user interaction */
-.service('DialogService', ['$modal', function($modal) {
-
- var dialogDefaults = {
- backdrop: true,
- keyboard: true,
- backdropClick: true,
- modalFade: true,
- templateUrl: 'views/dialog.html'
- };
-
- var dialogOptions = {
- closeButtonText: 'close',
- actionButtonText: 'ok',
- headerText: 'dhis2_tracker',
- bodyText: 'Perform this action?'
- };
-
- this.showDialog = function(customDialogDefaults, customDialogOptions) {
- if (!customDialogDefaults)
- customDialogDefaults = {};
- customDialogDefaults.backdropClick = false;
- return this.show(customDialogDefaults, customDialogOptions);
- };
-
- this.show = function(customDialogDefaults, customDialogOptions) {
- //Create temp objects to work with since we're in a singleton service
- var tempDialogDefaults = {};
- var tempDialogOptions = {};
-
- //Map angular-ui modal custom defaults to modal defaults defined in service
- angular.extend(tempDialogDefaults, dialogDefaults, customDialogDefaults);
-
- //Map modal.html $scope custom properties to defaults defined in service
- angular.extend(tempDialogOptions, dialogOptions, customDialogOptions);
-
- if (!tempDialogDefaults.controller) {
- tempDialogDefaults.controller = function($scope, $modalInstance) {
- $scope.dialogOptions = tempDialogOptions;
- $scope.dialogOptions.ok = function(result) {
- $modalInstance.close(result);
- };
- };
- }
-
- return $modal.open(tempDialogDefaults).result;
- };
-
-}])
-
-.service('Paginator', function () {
- this.page = 1;
- this.pageSize = 50;
- this.itemCount = 0;
- this.pageCount = 0;
- this.toolBarDisplay = 5;
-
- this.setPage = function (page) {
- if (page > this.getPageCount()) {
- return;
- }
-
- this.page = page;
- };
-
- this.getPage = function(){
- return this.page;
- };
-
- this.setPageSize = function(pageSize){
- this.pageSize = pageSize;
- };
-
- this.getPageSize = function(){
- return this.pageSize;
- };
-
- this.setItemCount = function(itemCount){
- this.itemCount = itemCount;
- };
-
- this.getItemCount = function(){
- return this.itemCount;
- };
-
- this.setPageCount = function(pageCount){
- this.pageCount = pageCount;
- };
-
- this.getPageCount = function () {
- return this.pageCount;
- };
-
- this.lowerLimit = function() {
- var pageCountLimitPerPageDiff = this.getPageCount() - this.toolBarDisplay;
-
- if (pageCountLimitPerPageDiff < 0) {
- return 0;
- }
-
- if (this.getPage() > pageCountLimitPerPageDiff + 1) {
- return pageCountLimitPerPageDiff;
- }
-
- var low = this.getPage() - (Math.ceil(this.toolBarDisplay/2) - 1);
-
- return Math.max(low, 0);
- };
-})
-
-.service('GridColumnService', function(){
- return {
- columnExists: function(cols, id) {
- var colExists = false;
- if(!angular.isObject(cols) || !id || angular.isObject(cols) && !cols.length){
- return colExists;
- }
-
- for(var i=0; i<cols.length && !colExists; i++){
- if(cols[i].id === id){
- colExists = true;
- }
- }
- return colExists;
- }
- };
-});
=== added file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.controllers.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.controllers.js 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.controllers.js 2015-02-02 13:42:37 +0000
@@ -0,0 +1,53 @@
+'use strict';
+
+/* Controllers */
+var d2Controllers = angular.module('d2Controllers', [])
+
+//Controller for column show/hide
+.controller('ColumnDisplayController',
+ function($scope,
+ $modalInstance,
+ hiddenGridColumns,
+ gridColumns){
+
+ $scope.gridColumns = gridColumns;
+ $scope.hiddenGridColumns = hiddenGridColumns;
+
+ $scope.close = function () {
+ $modalInstance.close($scope.gridColumns);
+ };
+
+ $scope.showHideColumns = function(gridColumn){
+
+ if(gridColumn.show){
+ $scope.hiddenGridColumns--;
+ }
+ else{
+ $scope.hiddenGridColumns++;
+ }
+ };
+})
+
+//controller for dealing with google map
+.controller('MapController',
+ function($scope,
+ $modalInstance,
+ DHIS2URL,
+ geoJsons,
+ location) {
+
+ $scope.home = function(){
+ window.location = DHIS2URL;
+ };
+
+ $scope.location = location;
+ $scope.geoJsons = geoJsons;
+
+ $scope.close = function () {
+ $modalInstance.close();
+ };
+
+ $scope.captureCoordinate = function(){
+ $modalInstance.close($scope.location);
+ };
+});
\ No newline at end of file
=== added file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.directives.js 2015-02-02 13:42:37 +0000
@@ -0,0 +1,582 @@
+'use strict';
+
+/* Directives */
+
+var d2Directives = angular.module('d2Directives', [])
+
+
+.directive('d2OuSearch', function() {
+
+ return {
+ restrict: 'E',
+ template: '<div style="margin-top:20px">\n\
+ <img id="searchIcon" src="../images/search.png" style="cursor: pointer" title="{{ \'locate_organisation_unit_by_name\' | translate}}">\n\
+ <span id="searchSpan" style="width:100%;display:none;">\n\
+ <input type="text" id="searchField" name="key"/>\n\
+ <input type="button" value="{{\'find\' | translate}}" onclick="selection.findByName()"/>\n\
+ </span>\n\
+ </div>',
+ link: function (scope, element, attrs) {
+
+ $("#searchIcon").click(function() {
+ $("#searchSpan").toggle();
+ $("#searchField").focus();
+ });
+
+ $("#searchField").autocomplete({
+ source: "../dhis-web-commons/ouwt/getOrganisationUnitsByName.action",
+ select: function(event, ui) {
+ $("#searchField").val(ui.item.value);
+ selection.findByName();
+ }
+ });
+ }
+ };
+})
+
+.directive('inputValidator', function() {
+
+ return {
+ require: 'ngModel',
+ link: function (scope, element, attrs, ctrl) {
+
+ ctrl.$parsers.push(function (value) {
+ return parseFloat(value || '');
+ });
+ }
+ };
+})
+
+.directive('selectedOrgUnit', function($timeout, storage) {
+
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs){
+
+ //once ou tree is loaded, start meta-data download
+ $(function() {
+ dhis2.ou.store.open().done( function() {
+ selection.load();
+ $( "#orgUnitTree" ).one( "ouwtLoaded", function(event, ids, names) {
+ console.log('Finished loading orgunit tree');
+
+ //Disable ou selection until meta-data has downloaded
+ $( "#orgUnitTree" ).addClass( "disable-clicks" );
+
+ $timeout(function() {
+ scope.treeLoaded = true;
+ scope.$apply();
+ });
+
+ downloadMetaData();
+ });
+ });
+ });
+
+ //listen to user selection, and inform angular
+ selection.setListenerFunction( setSelectedOu, true );
+
+ function setSelectedOu( ids, names ) {
+ var ou = {id: ids[0], name: names[0]};
+ $timeout(function() {
+ scope.selectedOrgUnit = ou;
+ scope.$apply();
+ });
+ }
+ }
+ };
+})
+
+.directive('blurOrChange', function() {
+
+ return function( scope, elem, attrs) {
+ elem.calendarsPicker({
+ onSelect: function() {
+ scope.$apply(attrs.blurOrChange);
+ $(this).change();
+ }
+ }).change(function() {
+ scope.$apply(attrs.blurOrChange);
+ });
+ };
+})
+
+.directive('d2Enter', function () {
+ return function (scope, element, attrs) {
+ element.bind("keydown keypress", function (event) {
+ if(event.which === 13) {
+ scope.$apply(function (){
+ scope.$eval(attrs.d2Enter);
+ });
+ event.preventDefault();
+ }
+ });
+ };
+})
+
+.directive('d2NumberValidation', function(ErrorMessageService, $translate) {
+
+ return {
+ require: 'ngModel',
+ restrict: 'A',
+ link: function (scope, element, attrs, ctrl) {
+
+ function checkValidity(numberType, value){
+ var isValid = false;
+ switch(numberType){
+ case "number":
+ isValid = dhis2.validation.isNumber(value);
+ break;
+ case "posInt":
+ isValid = dhis2.validation.isPositiveInt(value);
+ break;
+ case "negInt":
+ isValid = dhis2.validation.isNegativeInt(value);
+ break;
+ case "zeroPositiveInt":
+ isValid = dhis2.validation.isZeroOrPositiveInt(value);
+ break;
+ case "int":
+ isValid = dhis2.validation.isInt(value);
+ break;
+ default:
+ isValid = true;
+ }
+ return isValid;
+ }
+
+ var errorMessages = ErrorMessageService.getErrorMessages();
+ var fieldName = attrs.inputFieldId;
+ var numberType = attrs.numberType;
+ var isRequired = attrs.ngRequired === 'true';
+ var msg = $translate(numberType)+ ' ' + $translate('required');
+
+ ctrl.$parsers.unshift(function(value) {
+ if(value){
+ var isValid = checkValidity(numberType, value);
+ if(!isValid){
+ errorMessages[fieldName] = $translate('value_must_be_' + numberType);
+ }
+ else{
+ if(isRequired){
+ errorMessages[fieldName] = msg;
+ }
+ else{
+ errorMessages[fieldName] = "";
+ }
+ }
+
+ ErrorMessageService.setErrorMessages(errorMessages);
+ ctrl.$setValidity(fieldName, isValid);
+ return value;
+ }
+
+ if(value === ''){
+ if(isRequired){
+ errorMessages[fieldName] = msg;
+ }
+ else{
+ ctrl.$setValidity(fieldName, true);
+ errorMessages[fieldName] = "";
+ }
+
+ ErrorMessageService.setErrorMessages(errorMessages);
+ return undefined;
+ }
+ });
+
+ ctrl.$formatters.unshift(function(value) {
+ if(value){
+ var isValid = checkValidity(numberType, value);
+ ctrl.$setValidity(fieldName, isValid);
+ return value;
+ }
+ });
+ }
+ };
+})
+
+.directive('typeaheadOpenOnFocus', function () {
+
+ return {
+ require: ['typeahead', 'ngModel'],
+ link: function (scope, element, attr, ctrls) {
+ element.bind('focus', function () {
+ ctrls[0].getMatchesAsync(ctrls[1].$viewValue);
+ scope.$watch(attr.ngModel, function(value) {
+ if(value === '' || angular.isUndefined(value)){
+ ctrls[0].getMatchesAsync(ctrls[1].$viewValue);
+ }
+ });
+ });
+ }
+ };
+})
+
+.directive('d2TypeaheadValidation', function() {
+
+ return {
+ require: ['typeahead', 'ngModel'],
+ restrict: 'A',
+ link: function (scope, element, attrs, ctrls) {
+ element.bind('blur', function () {
+ if(ctrls[1].$viewValue && !ctrls[1].$modelValue && ctrls[0].active === -1){
+ ctrls[1].$setViewValue();
+ ctrls[1].$render();
+ }
+ });
+ }
+ };
+})
+
+.directive('d2PopOver', function($compile, $templateCache){
+
+ return {
+ restrict: 'EA',
+ link: function(scope, element, attrs){
+ var content = $templateCache.get("popover.html");
+ content = $compile(content)(scope);
+ var options = {
+ content: content,
+ placement: 'bottom',
+ trigger: 'hover',
+ html: true,
+ title: scope.title
+ };
+ $(element).popover(options);
+ },
+ scope: {
+ content: '=',
+ title: '@details',
+ template: "@template"
+ }
+ };
+})
+
+.directive('sortable', function() {
+
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs){
+ element.sortable({
+ connectWith: ".connectedSortable",
+ placeholder: "ui-state-highlight",
+ tolerance: "pointer",
+ handle: '.handle'
+ });
+ }
+ };
+})
+
+.directive('serversidePaginator', function factory() {
+
+ return {
+ restrict: 'E',
+ controller: function ($scope, Paginator) {
+ $scope.paginator = Paginator;
+ },
+ templateUrl: '../dhis-web-commons/paging/serverside-pagination.html'
+ };
+})
+
+.directive('draggableModal', function(){
+
+ return {
+ restrict: 'EA',
+ link: function(scope, element) {
+ element.draggable();
+ }
+ };
+})
+
+.directive('d2GoogleMap', function ($parse, $compile, storage) {
+ return {
+ restrict: 'E',
+ replace: true,
+ template: '<div></div>',
+ link: function(scope, element, attrs){
+
+ //remove angular bootstrap ui modal draggable
+ $(".modal-content").draggable({ disabled: true });
+
+ //get a default center
+ var latCenter = 12.31, lngCenter = 51.48;
+
+ //if there is any marker already - use it as center
+ if(angular.isObject(scope.location)){
+ if(scope.location.lat && scope.location.lng){
+ latCenter = scope.location.lat;
+ lngCenter = scope.location.lng;
+ }
+ }
+
+ //default map configurations
+ var mapOptions = {
+ zoom: 3,
+ center: new google.maps.LatLng(latCenter, lngCenter),
+ mapTypeId: google.maps.MapTypeId.ROADMAP
+ },featureStyle = {
+ strokeWeight: 2,
+ strokeOpacity: 0.4,
+ fillOpacity: 0.4,
+ fillColor: 'green'
+ };
+
+ var geojsons = $parse(attrs.geojsons)(scope);
+ var currentLayer = 0, currentGeojson = geojsons[0];
+
+ var map = new google.maps.Map(document.getElementById(attrs.id), mapOptions);
+ var currentGeojsonFeatures = map.data.addGeoJson(currentGeojson);
+
+ var marker = new google.maps.Marker({
+ map: map
+ });
+
+ if(angular.isObject(scope.location)){
+ if(scope.location.lat && scope.location.lng){
+ addMarker({lat: scope.location.lat, lng: scope.location.lng});
+ }
+ }
+
+ function addMarker(loc){
+ var latLng = new google.maps.LatLng(loc.lat, loc.lng);
+ marker.setPosition(latLng);
+ }
+
+ function centerMap(){
+
+ if(currentGeojson && currentGeojson.features){
+ var latLngBounds = new google.maps.LatLngBounds();
+ angular.forEach(currentGeojson.features, function(feature){
+ if(feature.geometry.type === 'MultiPolygon'){
+ angular.forEach(feature.geometry.coordinates[0][0], function(coordinate){
+ latLngBounds.extend(new google.maps.LatLng(coordinate[1],coordinate[0]));
+ });
+ }
+ else if(feature.geometry.type === 'Point'){
+ latLngBounds.extend(new google.maps.LatLng(feature.geometry.coordinates[1],feature.geometry.coordinates[0]));
+ }
+ });
+
+ map.fitBounds(latLngBounds);
+ map.panToBounds(latLngBounds);
+ }
+ }
+
+ function initializeMap(){
+ google.maps.event.addListenerOnce(map, 'idle', function(){
+ google.maps.event.trigger(map, 'resize');
+ map.data.setStyle(featureStyle);
+ centerMap();
+ });
+ }
+
+ map.data.addListener('mouseover', function(e) {
+ $("#polygon-label").text( e.feature.k.name );
+ map.data.revertStyle();
+ map.data.overrideStyle(e.feature, {fillOpacity: 0.8});
+ });
+
+ map.data.addListener('mouseout', function() {
+ $("#polygon-label").text( '' );
+ map.data.revertStyle();
+ });
+
+ //drill-down based on polygons assigned to orgunits
+ map.data.addListener('rightclick', function(e){
+ for (var i = 0; i < currentGeojsonFeatures.length; i++){
+ map.data.remove(currentGeojsonFeatures[i]);
+ }
+
+ if(currentLayer >= geojsons.length-1){
+ currentLayer = 0;
+ currentGeojson = angular.copy(geojsons[currentLayer]);
+ }
+ else{
+ currentLayer++;
+ currentGeojson = angular.copy(geojsons[currentLayer]);
+ currentGeojson.features = [];
+ var selectedFeatures = [];
+ angular.forEach(geojsons[currentLayer].features, function(feature){
+ if(feature.properties.parent === e.feature.B){
+ selectedFeatures.push(feature);
+ }
+ });
+
+ if(selectedFeatures.length){
+ currentGeojson.features = selectedFeatures;
+ }
+ }
+ currentGeojsonFeatures = map.data.addGeoJson(currentGeojson);
+ centerMap();
+ });
+
+ //capturing coordinate from defined polygons
+ map.data.addListener('click', function(e) {
+ scope.$apply(function(){
+ addMarker({
+ lat: e.latLng.lat(),
+ lng: e.latLng.lng()
+ });
+ $parse(attrs.location).assign(scope.$parent, {lat: e.latLng.lat(), lng: e.latLng.lng()});
+ });
+ });
+
+ //capturing coordinate from anywhere in the map - incase no polygons are defined
+ google.maps.event.addListener(map, 'click', function(e){
+ scope.$apply(function(){
+ addMarker({
+ lat: e.latLng.lat(),
+ lng: e.latLng.lng()
+ });
+ $parse(attrs.location).assign(scope.$parent, {lat: e.latLng.lat(), lng: e.latLng.lng()});
+ });
+ });
+
+ initializeMap();
+ }
+ };
+})
+
+.directive('d2CustomForm', function($compile, $parse, CustomFormService) {
+ return{
+ restrict: 'E',
+ link: function(scope, elm, attrs){
+ scope.$watch('customForm', function(){
+ elm.html(scope.customForm.htmlCode);
+ $compile(elm.contents())(scope);
+ });
+ }
+ };
+})
+
+.directive('d2ContextMenu', function(ContextMenuSelectedItem) {
+
+ return {
+ restrict: 'A',
+ link: function(scope, element, attrs){
+ var contextMenu = $("#contextMenu");
+
+ element.click(function (e) {
+ var selectedItem = $.parseJSON(attrs.selectedItem);
+ ContextMenuSelectedItem.setSelectedItem(selectedItem);
+
+ var menuHeight = contextMenu.height();
+ var menuWidth = contextMenu.width();
+ var winHeight = $(window).height();
+ var winWidth = $(window).width();
+
+ var pageX = e.pageX;
+ var pageY = e.pageY;
+
+ contextMenu.show();
+
+ if( (menuWidth + pageX) > winWidth ) {
+ pageX -= menuWidth;
+ }
+
+ if( (menuHeight + pageY) > winHeight ) {
+ pageY -= menuHeight;
+
+ if( pageY < 0 ) {
+ pageY = e.pageY;
+ }
+ }
+
+ contextMenu.css({
+ left: pageX,
+ top: pageY
+ });
+
+ return false;
+ });
+
+ contextMenu.on("click", "a", function () {
+ contextMenu.hide();
+ });
+
+ $(document).click(function () {
+ contextMenu.hide();
+ });
+ }
+ };
+})
+
+.directive('d2Date', function(DateUtils, CalendarService, ErrorMessageService, $translate, $parse) {
+ return {
+ restrict: 'A',
+ require: 'ngModel',
+ link: function(scope, element, attrs, ctrl) {
+
+ var errorMessages = ErrorMessageService.getErrorMessages();
+ var fieldName = attrs.inputFieldId;
+ var isRequired = attrs.ngRequired === 'true';
+ var calendarSetting = CalendarService.getSetting();
+ var dateFormat = 'yyyy-mm-dd';
+ if(calendarSetting.keyDateFormat === 'dd-MM-yyyy'){
+ dateFormat = 'dd-mm-yyyy';
+ }
+
+ var minDate = $parse(attrs.minDate)(scope),
+ maxDate = $parse(attrs.maxDate)(scope),
+ calendar = $.calendars.instance(calendarSetting.keyCalendar);
+
+ element.calendarsPicker({
+ changeMonth: true,
+ dateFormat: dateFormat,
+ yearRange: '-120:+30',
+ minDate: minDate,
+ maxDate: maxDate,
+ calendar: calendar,
+ duration: "fast",
+ showAnim: "",
+ renderer: $.calendars.picker.themeRollerRenderer,
+ onSelect: function(date) {
+ $(this).change();
+ }
+ })
+ .change(function() {
+ if(this.value){
+ var rawDate = this.value;
+ var convertedDate = DateUtils.format(this.value);
+
+ var isValid = rawDate == convertedDate;
+
+ if(!isValid){
+ errorMessages[fieldName] = $translate('date_required');
+ }
+ else{
+ if(isRequired){
+ errorMessages[fieldName] = $translate('required');
+ }
+ else{
+ errorMessages[fieldName] = "";
+ }
+ if(maxDate === 0){
+ isValid = !moment(convertedDate, calendarSetting.momentFormat).isAfter(DateUtils.getToday());
+ if(!isValid){
+ errorMessages[fieldName] = $translate('future_date_not_allowed');
+ }
+ }
+ }
+ ctrl.$setViewValue(this.value);
+ ctrl.$setValidity(fieldName, isValid);
+ }
+ else{
+ if(!isRequired){
+ ctrl.$setViewValue(this.value);
+ ctrl.$setValidity(fieldName, !isRequired);
+ errorMessages[fieldName] = "";
+ }
+ else{
+ errorMessages[fieldName] = $translate('required');
+ }
+ }
+
+ ErrorMessageService.setErrorMessages(errorMessages);
+ this.focus();
+ scope.$apply();
+ });
+ }
+ };
+});
\ No newline at end of file
=== added file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.filters.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.filters.js 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.filters.js 2015-02-02 13:42:37 +0000
@@ -0,0 +1,97 @@
+'use strict';
+
+/* Filters */
+
+var d2Filters = angular.module('d2Filters', [])
+
+.filter('gridFilter', function($filter, CalendarService){
+
+ return function(data, filters, filterTypes){
+
+ if(!data ){
+ return;
+ }
+
+ if(!filters){
+ return data;
+ }
+ else{
+
+ var dateFilter = {},
+ textFilter = {},
+ numberFilter = {},
+ filteredData = data;
+
+ for(var key in filters){
+
+ if(filterTypes[key] === 'date'){
+ if(filters[key].start || filters[key].end){
+ dateFilter[key] = filters[key];
+ }
+ }
+ else if(filterTypes[key] === 'int'){
+ if(filters[key].start || filters[key].end){
+ numberFilter[key] = filters[key];
+ }
+ }
+ else{
+ textFilter[key] = filters[key];
+ }
+ }
+
+ filteredData = $filter('filter')(filteredData, textFilter);
+ filteredData = $filter('filter')(filteredData, dateFilter, dateComparator);
+ filteredData = $filter('filter')(filteredData, numberFilter, numberComparator);
+
+ return filteredData;
+ }
+ };
+
+ function dateComparator(data,filter){
+ var calendarSetting = CalendarService.getSetting();
+ var start = moment(filter.start, calendarSetting.momentFormat);
+ var end = moment(filter.end, calendarSetting.momentFormat);
+ var date = moment(data, calendarSetting.momentFormat);
+
+ if(filter.start && filter.end){
+ return ( Date.parse(date) <= Date.parse(end) ) && (Date.parse(date) >= Date.parse(start));
+ }
+ return ( Date.parse(date) <= Date.parse(end) ) || (Date.parse(date) >= Date.parse(start));
+ }
+
+ function numberComparator(data,filter){
+ var start = filter.start;
+ var end = filter.end;
+
+ if(filter.start && filter.end){
+ return ( data <= end ) && ( data >= start );
+ }
+ return ( data <= end ) || ( data >= start );
+ }
+})
+
+.filter('paginate', function(Paginator) {
+ return function(input, rowsPerPage) {
+ if (!input) {
+ return input;
+ }
+
+ if (rowsPerPage) {
+ Paginator.rowsPerPage = rowsPerPage;
+ }
+
+ Paginator.itemCount = input.length;
+
+ return input.slice(parseInt(Paginator.page * Paginator.rowsPerPage), parseInt((Paginator.page + 1) * Paginator.rowsPerPage + 1) - 1);
+ };
+})
+
+.filter('forLoop', function() {
+ return function(input, start, end) {
+ input = new Array(end - start);
+ for (var i = 0; start < end; start++, i++) {
+ input[i] = start;
+ }
+ return input;
+ };
+});
\ No newline at end of file
=== added file 'dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js'
--- dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js 1970-01-01 00:00:00 +0000
+++ dhis-2/dhis-web/dhis-web-commons-resources/src/main/webapp/dhis-web-commons/javascripts/dhis2/dhis2.angular.services.js 2015-02-02 13:42:37 +0000
@@ -0,0 +1,560 @@
+/* Pagination service */
+var d2Services = angular.module('d2Services', ['ngResource'])
+
+/* Factory for loading translation strings */
+.factory('i18nLoader', function ($q, $http, storage, DialogService) {
+
+ var getTranslationStrings = function(locale){
+ var defaultUrl = 'i18n/i18n_app.properties';
+ var url = '';
+ if(locale === 'en' || !locale){
+ url = defaultUrl;
+ }
+ else{
+ url = 'i18n/i18n_app_' + locale + '.properties';
+ }
+
+ var tx = {locale: locale};
+
+ var promise = $http.get(url).then(function(response){
+ tx= {locale: locale, keys: dhis2.util.parseJavaProperties(response.data)};
+ return tx;
+ }, function(){
+ var dialogOptions = {
+ headerText: 'missing_translation_file',
+ bodyText: 'missing_translation_using_default'
+ };
+
+ DialogService.showDialog({}, dialogOptions);
+ var p = $http.get(defaultUrl).then(function(response){
+ tx= {locale: locale, keys: dhis2.util.parseJavaProperties(response.data)};
+ return tx;
+ });
+ return p;
+ });
+ return promise;
+ };
+
+ var getLocale = function(){
+ var locale = 'en';
+
+ var promise = $http.get('../api/me/profile.json').then(function(response){
+ storage.set('USER_PROFILE', response.data);
+ if(response.data && response.data.settings && response.data.settings.keyUiLocale){
+ locale = response.data.settings.keyUiLocale;
+ }
+ return locale;
+ }, function(){
+ return locale;
+ });
+
+ return promise;
+ };
+ return function () {
+ var deferred = $q.defer(), translations;
+ var userProfile = storage.get('USER_PROFILE');
+ if(userProfile && userProfile.settings && userProfile.settings.keyUiLocale){
+ getTranslationStrings(userProfile.settings.keyUiLocale).then(function(response){
+ translations = response.keys;
+ deferred.resolve(translations);
+ });
+ return deferred.promise;
+ }
+ else{
+ getLocale().then(function(locale){
+ getTranslationStrings(locale).then(function(response){
+ translations = response.keys;
+ deferred.resolve(translations);
+ });
+ });
+ return deferred.promise;
+ }
+ };
+})
+
+/* Factory for loading external data */
+.factory('ExternalDataFactory', function($http) {
+
+ return {
+ get: function(fileName) {
+ var promise = $http.get( fileName ).then(function(response){
+ return response.data;
+ });
+ return promise;
+ }
+ };
+})
+
+/* service for getting calendar setting */
+.service('CalendarService', function(storage, $rootScope){
+
+ return {
+ getSetting: function() {
+
+ var dhis2CalendarFormat = {keyDateFormat: 'yyyy-MM-dd', keyCalendar: 'gregorian', momentFormat: 'YYYY-MM-DD'};
+ var storedFormat = storage.get('CALENDAR_SETTING');
+ if(angular.isObject(storedFormat) && storedFormat.keyDateFormat && storedFormat.keyCalendar){
+ if(storedFormat.keyCalendar === 'iso8601'){
+ storedFormat.keyCalendar = 'gregorian';
+ }
+
+ if(storedFormat.keyDateFormat === 'dd-MM-yyyy'){
+ dhis2CalendarFormat.momentFormat = 'DD-MM-YYYY';
+ }
+
+ dhis2CalendarFormat.keyCalendar = storedFormat.keyCalendar;
+ dhis2CalendarFormat.keyDateFormat = storedFormat.keyDateFormat;
+ }
+ $rootScope.dhis2CalendarFormat = dhis2CalendarFormat;
+ return dhis2CalendarFormat;
+ }
+ };
+})
+
+/* service for dealing with dates */
+.service('DateUtils', function($filter, CalendarService){
+
+ return {
+ getDate: function(dateValue){
+ if(!dateValue){
+ return;
+ }
+ var calendarSetting = CalendarService.getSetting();
+ dateValue = moment(dateValue, calendarSetting.momentFormat)._d;
+ return Date.parse(dateValue);
+ },
+ format: function(dateValue) {
+ if(!dateValue){
+ return;
+ }
+
+ var calendarSetting = CalendarService.getSetting();
+ dateValue = moment(dateValue, calendarSetting.momentFormat)._d;
+ dateValue = $filter('date')(dateValue, calendarSetting.keyDateFormat);
+ return dateValue;
+ },
+ formatToHrsMins: function(dateValue) {
+ var calendarSetting = CalendarService.getSetting();
+ var dateFormat = 'YYYY-MM-DD @ hh:mm A';
+ if(calendarSetting.keyDateFormat === 'dd-MM-yyyy'){
+ dateFormat = 'DD-MM-YYYY @ hh:mm A';
+ }
+ return moment(dateValue).format(dateFormat);
+ },
+ getToday: function(){
+ var calendarSetting = CalendarService.getSetting();
+ var tdy = $.calendars.instance(calendarSetting.keyCalendar).newDate();
+ var today = moment(tdy._year + '-' + tdy._month + '-' + tdy._day, 'YYYY-MM-DD')._d;
+ today = Date.parse(today);
+ today = $filter('date')(today, calendarSetting.keyDateFormat);
+ return today;
+ },
+ formatFromUserToApi: function(dateValue){
+ if(!dateValue){
+ return;
+ }
+ var calendarSetting = CalendarService.getSetting();
+ dateValue = moment(dateValue, calendarSetting.momentFormat)._d;
+ dateValue = Date.parse(dateValue);
+ dateValue = $filter('date')(dateValue, 'yyyy-MM-dd');
+ return dateValue;
+ },
+ formatFromApiToUser: function(dateValue){
+ if(!dateValue){
+ return;
+ }
+ var calendarSetting = CalendarService.getSetting();
+ dateValue = moment(dateValue, 'YYYY-MM-DD')._d;
+ return $filter('date')(dateValue, calendarSetting.keyDateFormat);
+ }
+ };
+})
+
+/* service for dealing with custom form */
+.service('CustomFormService', function(){
+
+ return {
+ getForProgramStage: function(programStage){
+
+ var htmlCode = programStage.dataEntryForm ? programStage.dataEntryForm.htmlCode : null;
+
+ if(htmlCode){
+
+ var programStageDataElements = [];
+
+ angular.forEach(programStage.programStageDataElements, function(prStDe){
+ programStageDataElements[prStDe.dataElement.id] = prStDe;
+ });
+
+ var inputRegex = /<input.*?\/>/g,
+ match,
+ inputFields = [];
+
+ while (match = inputRegex.exec(htmlCode)) {
+ inputFields.push(match[0]);
+ }
+
+ for(var i=0; i<inputFields.length; i++){
+ var inputField = inputFields[i];
+ var inputElement = $.parseHTML( inputField );
+ var attributes = {};
+
+ $(inputElement[0].attributes).each(function() {
+ attributes[this.nodeName] = this.value;
+ });
+
+ var fieldId = '', errorMessageId = '', newInputField, hasEventDate = false;
+ if(attributes.hasOwnProperty('id')){
+
+ if(attributes['id'] === 'executionDate'){
+ fieldId = 'eventDate';
+ errorMessageId = '"' + 'eventDate' + '"';
+ hasEventDate = true;
+
+ //name needs to be unique so that it can be used for validation in angularjs
+ if(attributes.hasOwnProperty('name')){
+ attributes['name'] = fieldId;
+ }
+
+ newInputField = '<input type="text" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '"' +
+ ' input-field-id="' + fieldId + '"' +
+ ' d2-date ' +
+ ' max-date="' + 0 + '"' +
+ ' placeholder="{{dhis2CalendarFormat.keyDateFormat}}" ' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' blur-or-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="{{true}}">';
+ }
+ else{
+ fieldId = attributes['id'].substring(4, attributes['id'].length-1).split("-")[1];
+ errorMessageId = 'prStDes.' + fieldId + '.dataElement.id';
+
+ //name needs to be unique so that it can be used for validation in angularjs
+ if(attributes.hasOwnProperty('name')){
+ attributes['name'] = fieldId;
+ }
+
+ //check data element type and generate corresponding angular input field
+ if(programStageDataElements[fieldId].dataElement.type === "int"){
+ newInputField = '<input type="text" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' d2-number-validation ' +
+ ' number-type="' + programStageDataElements[fieldId].dataElement.numberType + '" ' +
+ ' ng-model="currentEvent.' + fieldId + '"' +
+ ' input-field-id="' + fieldId + '"' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
+ ' ng-blur="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="{{prStDes.' + fieldId + '.compulsory}}">';
+ }
+ if(programStageDataElements[fieldId].dataElement.type === "string"){
+ if(programStageDataElements[fieldId].dataElement.optionSet){
+ var optionSetId = programStageDataElements[fieldId].dataElement.optionSet.id;
+ newInputField = '<input type="text" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '" ' +
+ ' input-field-id="' + fieldId + '"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\' || currentEvent[uid]==\'uid\'"' +
+ ' ng-required="{{prStDes.' + fieldId + '.compulsory}}"' +
+ ' typeahead="option.name as option.name for option in optionSets.'+optionSetId+'.options | filter:$viewValue | limitTo:20"' +
+ ' typeahead-editable="false" ' +
+ ' d2-typeahead-validation ' +
+ ' class="typeahead" ' +
+ ' placeholder=" " ' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-blur="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' typeahead-open-on-focus ng-required="prStDes.'+fieldId+'.compulsory"> ';
+ }
+ else{
+ newInputField = '<input type="text" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '" ' +
+ ' input-field-id="' + fieldId + '"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\' || currentEvent[uid]==\'uid\'"' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-blur="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="prStDes.' + fieldId + '.compulsory"> ';
+ }
+ }
+ if(programStageDataElements[fieldId].dataElement.type === "bool"){
+ newInputField = '<select ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '" ' +
+ ' input-field-id="' + fieldId + '"' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
+ ' ng-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="{{prStDes.' + fieldId + '.compulsory}}">' +
+ '<option value="">{{\'please_select\'| translate}}</option>' +
+ '<option value="false">{{\'no\'| translate}}</option>' +
+ '<option value="true">{{\'yes\'| translate}}</option>' +
+ '</select> ';
+ }
+ if(programStageDataElements[fieldId].dataElement.type === "date"){
+ var maxDate = programStageDataElements[fieldId].allowFutureDate ? '' : 0;
+ newInputField = '<input type="text" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '"' +
+ ' input-field-id="' + fieldId + '"' +
+ ' placeholder="{{dhis2CalendarFormat.keyDateFormat}}" ' +
+ ' d2-date ' +
+ ' max-date="' + maxDate + '"' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
+ ' blur-or-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="{{prStDes.' + fieldId + '.compulsory}}"> ';
+ }
+ if(programStageDataElements[fieldId].dataElement.type === "trueOnly"){
+ newInputField = '<input type="checkbox" ' +
+ this.getAttributesAsString(attributes) +
+ ' d2-validation ' +
+ ' ng-model="currentEvent.' + fieldId + '"' +
+ ' input-field-id="' + fieldId + '"' +
+ ' ng-class="getInputNotifcationClass(prStDes.' + fieldId + '.dataElement.id,true)"' +
+ ' ng-disabled="selectedEnrollment.status===\'CANCELLED\' || selectedEnrollment.status===\'COMPLETED\'"' +
+ ' ng-change="saveDatavalue(prStDes.'+ fieldId + ')"' +
+ ' ng-required="{{prStDes.' + fieldId + '.compulsory}}"> ';
+ }
+ }
+
+ newInputField = newInputField + ' <span ng-show="(outerForm.'+ fieldId +'.$dirty && outerForm.'+ fieldId +'.$invalid) || (outerForm.submitted && outerForm.'+ fieldId +'.$invalid) || (currentEvent.' + fieldId + ' && outerForm.' + fieldId + '.$invalid)" class="required">{{getErrorMessage(' + errorMessageId + ')}}</span> ';
+
+ htmlCode = htmlCode.replace(inputField, newInputField);
+ }
+ }
+ return {htmlCode: htmlCode, hasEventDate: hasEventDate};
+ }
+ return null;
+ },
+ getAttributesAsString: function(attributes){
+ if(attributes){
+ var attributesAsString = '';
+ for(var prop in attributes){
+ if(prop !== 'value'){
+ attributesAsString += prop + '="' + attributes[prop] + '" ';
+ }
+ }
+ return attributesAsString;
+ }
+ return null;
+ }
+ };
+})
+
+/* Context menu for grid*/
+.service('ContextMenuSelectedItem', function(){
+ this.selectedItem = '';
+
+ this.setSelectedItem = function(selectedItem){
+ this.selectedItem = selectedItem;
+ };
+
+ this.getSelectedItem = function(){
+ return this.selectedItem;
+ };
+})
+
+/* Error messages*/
+.service('ErrorMessageService', function(){
+ this.errorMessages = {};
+
+ this.setErrorMessages = function(errorMessages){
+ this.errorMessages = errorMessages;
+ };
+
+ this.getErrorMessages = function(){
+ return this.errorMessages;
+ };
+
+ this.get = function(id){
+ return this.errorMessages[id];
+ };
+})
+
+/* Modal service for user interaction */
+.service('ModalService', ['$modal', function($modal) {
+
+ var modalDefaults = {
+ backdrop: true,
+ keyboard: true,
+ modalFade: true,
+ templateUrl: 'views/modal.html'
+ };
+
+ var modalOptions = {
+ closeButtonText: 'Close',
+ actionButtonText: 'OK',
+ headerText: 'Proceed?',
+ bodyText: 'Perform this action?'
+ };
+
+ this.showModal = function(customModalDefaults, customModalOptions) {
+ if (!customModalDefaults)
+ customModalDefaults = {};
+ customModalDefaults.backdrop = 'static';
+ return this.show(customModalDefaults, customModalOptions);
+ };
+
+ this.show = function(customModalDefaults, customModalOptions) {
+ //Create temp objects to work with since we're in a singleton service
+ var tempModalDefaults = {};
+ var tempModalOptions = {};
+
+ //Map angular-ui modal custom defaults to modal defaults defined in service
+ angular.extend(tempModalDefaults, modalDefaults, customModalDefaults);
+
+ //Map modal.html $scope custom properties to defaults defined in service
+ angular.extend(tempModalOptions, modalOptions, customModalOptions);
+
+ if (!tempModalDefaults.controller) {
+ tempModalDefaults.controller = function($scope, $modalInstance) {
+ $scope.modalOptions = tempModalOptions;
+ $scope.modalOptions.ok = function(result) {
+ $modalInstance.close(result);
+ };
+ $scope.modalOptions.close = function(result) {
+ $modalInstance.dismiss('cancel');
+ };
+ };
+ }
+
+ return $modal.open(tempModalDefaults).result;
+ };
+
+}])
+
+/* Dialog service for user interaction */
+.service('DialogService', ['$modal', function($modal) {
+
+ var dialogDefaults = {
+ backdrop: true,
+ keyboard: true,
+ backdropClick: true,
+ modalFade: true,
+ templateUrl: 'views/dialog.html'
+ };
+
+ var dialogOptions = {
+ closeButtonText: 'close',
+ actionButtonText: 'ok',
+ headerText: 'dhis2_tracker',
+ bodyText: 'Perform this action?'
+ };
+
+ this.showDialog = function(customDialogDefaults, customDialogOptions) {
+ if (!customDialogDefaults)
+ customDialogDefaults = {};
+ customDialogDefaults.backdropClick = false;
+ return this.show(customDialogDefaults, customDialogOptions);
+ };
+
+ this.show = function(customDialogDefaults, customDialogOptions) {
+ //Create temp objects to work with since we're in a singleton service
+ var tempDialogDefaults = {};
+ var tempDialogOptions = {};
+
+ //Map angular-ui modal custom defaults to modal defaults defined in service
+ angular.extend(tempDialogDefaults, dialogDefaults, customDialogDefaults);
+
+ //Map modal.html $scope custom properties to defaults defined in service
+ angular.extend(tempDialogOptions, dialogOptions, customDialogOptions);
+
+ if (!tempDialogDefaults.controller) {
+ tempDialogDefaults.controller = function($scope, $modalInstance) {
+ $scope.dialogOptions = tempDialogOptions;
+ $scope.dialogOptions.ok = function(result) {
+ $modalInstance.close(result);
+ };
+ };
+ }
+
+ return $modal.open(tempDialogDefaults).result;
+ };
+
+}])
+
+.service('Paginator', function () {
+ this.page = 1;
+ this.pageSize = 50;
+ this.itemCount = 0;
+ this.pageCount = 0;
+ this.toolBarDisplay = 5;
+
+ this.setPage = function (page) {
+ if (page > this.getPageCount()) {
+ return;
+ }
+
+ this.page = page;
+ };
+
+ this.getPage = function(){
+ return this.page;
+ };
+
+ this.setPageSize = function(pageSize){
+ this.pageSize = pageSize;
+ };
+
+ this.getPageSize = function(){
+ return this.pageSize;
+ };
+
+ this.setItemCount = function(itemCount){
+ this.itemCount = itemCount;
+ };
+
+ this.getItemCount = function(){
+ return this.itemCount;
+ };
+
+ this.setPageCount = function(pageCount){
+ this.pageCount = pageCount;
+ };
+
+ this.getPageCount = function () {
+ return this.pageCount;
+ };
+
+ this.lowerLimit = function() {
+ var pageCountLimitPerPageDiff = this.getPageCount() - this.toolBarDisplay;
+
+ if (pageCountLimitPerPageDiff < 0) {
+ return 0;
+ }
+
+ if (this.getPage() > pageCountLimitPerPageDiff + 1) {
+ return pageCountLimitPerPageDiff;
+ }
+
+ var low = this.getPage() - (Math.ceil(this.toolBarDisplay/2) - 1);
+
+ return Math.max(low, 0);
+ };
+})
+
+.service('GridColumnService', function(){
+ return {
+ columnExists: function(cols, id) {
+ var colExists = false;
+ if(!angular.isObject(cols) || !id || angular.isObject(cols) && !cols.length){
+ return colExists;
+ }
+
+ for(var i=0; i<cols.length && !colExists; i++){
+ if(cols[i].id === id){
+ colExists = true;
+ }
+ }
+ return colExists;
+ }
+ };
+});