← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 16674: tracker capture - report for overdue events

 

------------------------------------------------------------
revno: 16674
committer: Abyot Asalefew Gizaw <abyota@xxxxxxxxx>
branch nick: dhis2
timestamp: Tue 2014-09-09 15:26:15 +0200
message:
  tracker capture - report for overdue events
modified:
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/report/overdue-events-controller.js
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/report/overdue-events.html
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/report/upcoming-events-controller.js


--
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-tracker-capture/components/report/overdue-events-controller.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/report/overdue-events-controller.js	2014-08-27 12:55:29 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/report/overdue-events-controller.js	2014-09-09 13:26:15 +0000
@@ -1,6 +1,216 @@
 trackerCapture.controller('OverdueEventsController',
-        function(TranslationService) {
-
-    TranslationService.translate();   
-
+         function($scope,
+                $modal,
+                $location,
+                orderByFilter,
+                DateUtils,
+                EventUtils,
+                TEIService,
+                TEIGridService,
+                TranslationService,
+                AttributesFactory,
+                ProgramFactory,
+                DHIS2EventFactory,
+                storage) {
+
+    TranslationService.translate();
+    
+    $scope.today = DateUtils.format(moment());
+    
+    $scope.ouModes = [{name: 'SELECTED'}, {name: 'CHILDREN'}, {name: 'DESCENDANTS'}, {name: 'ACCESSIBLE'}];         
+    $scope.selectedOuMode = $scope.ouModes[0];
+    $scope.report = {};
+    $scope.displayMode = {};
+    
+    //watch for selection of org unit from tree
+    $scope.$watch('selectedOrgUnit', function() {        
+        if( angular.isObject($scope.selectedOrgUnit)){            
+            storage.set('SELECTED_OU', $scope.selectedOrgUnit);            
+            $scope.loadPrograms($scope.selectedOrgUnit);
+        }
+    });
+    
+    //load programs associated with the selected org unit.
+    $scope.loadPrograms = function(orgUnit) {
+        $scope.selectedOrgUnit = orgUnit;        
+        if (angular.isObject($scope.selectedOrgUnit)){
+            ProgramFactory.getAll().then(function(programs){
+                $scope.programs = programs;                
+                if($scope.programs.length === 1){
+                    $scope.selectedProgram = $scope.programs[0];
+                } 
+            });
+        }        
+    };
+    
+    //watch for selection of program
+    $scope.$watch('selectedProgram', function() {   
+        $scope.reportFinished = false;
+        $scope.reportStarted = false;
+    });
+    
+    $scope.generateReport = function(program, report, ouMode){
+
+        $scope.selectedProgram = program;
+        $scope.report = report;
+        $scope.selectedOuMode = ouMode;
+        
+        //check for form validity
+        $scope.outerForm.submitted = true;        
+        if( $scope.outerForm.$invalid || !$scope.selectedProgram){
+            return false;
+        }
+        
+        $scope.reportFinished = false;
+        $scope.reportStarted = true;        
+        $scope.programStages = [];
+        $scope.filterTypes = {};
+        $scope.filterText = {};
+        
+        angular.forEach($scope.selectedProgram.programStages, function(stage){
+            $scope.programStages[stage.id] = stage;
+        });
+            
+        AttributesFactory.getByProgram($scope.selectedProgram).then(function(atts){            
+            $scope.gridColumns = TEIGridService.generateGridColumns(atts, $scope.selectedOuMode.name);
+
+            $scope.gridColumns.push({name: 'event_name', id: 'event_name', type: 'string', displayInListNoProgram: false, showFilter: false, show: true});
+            $scope.filterTypes['event_name'] = 'string';                
+
+            $scope.gridColumns.push({name: 'due_date', id: 'due_date', type: 'date', displayInListNoProgram: false, showFilter: false, show: true});
+            $scope.filterTypes['due_date'] = 'date';
+            $scope.filterText['due_date']= {};                
+        });  
+        
+        //fetch TEIs for the selected program and orgunit/mode
+        TEIService.search($scope.selectedOrgUnit.id, 
+                            $scope.selectedOuMode.name,
+                            null,
+                            'program=' + $scope.selectedProgram.id,
+                            null,
+                            $scope.pager,
+                            false).then(function(data){                     
+            
+            //process tei grid
+            var teis = TEIGridService.format(data,true);     
+            $scope.teiList = [];            
+            DHIS2EventFactory.getByOrgUnitAndProgram($scope.selectedOrgUnit.id, $scope.selectedOuMode.name, $scope.selectedProgram.id, null, null).then(function(eventList){
+                $scope.dhis2Events = [];
+                angular.forEach(eventList, function(ev){
+                    if(ev.dueDate){
+                        ev.dueDate = DateUtils.format(ev.dueDate);
+                        
+                        if( ev.trackedEntityInstance && 
+                            !ev.eventDate && 
+                            ev.dueDate < $scope.today){
+                        
+                            ev.name = $scope.programStages[ev.programStage].name;
+                            ev.programName = $scope.selectedProgram.name;
+                            ev.statusColor = EventUtils.getEventStatusColor(ev); 
+                            ev.dueDate = DateUtils.format(ev.dueDate);
+
+                            if($scope.dhis2Events[ev.trackedEntityInstance]){
+                                if(teis.rows[ev.trackedEntityInstance]){
+                                    $scope.teiList.push(teis.rows[ev.trackedEntityInstance]);
+                                    delete teis.rows[ev.trackedEntityInstance];
+                                }                     
+                                $scope.dhis2Events[ev.trackedEntityInstance].push(ev);
+                            }
+                            else{
+                                if(teis.rows[ev.trackedEntityInstance]){
+                                    $scope.teiList.push(teis.rows[ev.trackedEntityInstance]);
+                                    delete teis.rows[ev.trackedEntityInstance];
+                                }  
+                                $scope.dhis2Events[ev.trackedEntityInstance] = [ev];
+                            }
+                            ev = EventUtils.setEventOrgUnitName(ev);
+                        }                        
+                    }
+                });
+                
+                //incase a TEI happens to have more than one overdue, sort using duedate
+                for(var tei in $scope.dhis2Events){                    
+                    $scope.dhis2Events[tei] = orderByFilter($scope.dhis2Events[tei], '-dueDate');
+                    $scope.dhis2Events[tei].reverse();
+                }
+                
+                //make upcoming event name and its due date part of the grid column
+                for(var i=0; i<$scope.teiList.length; i++){
+                    $scope.teiList[i].event_name = $scope.dhis2Events[$scope.teiList[i].id][0].name;
+                    $scope.teiList[i].due_date = $scope.dhis2Events[$scope.teiList[i].id][0].dueDate;
+                    $scope.teiList[i].followup = $scope.dhis2Events[$scope.teiList[i].id][0].followup;
+                }
+               
+                $scope.reportFinished = true;
+                $scope.reportStarted = false;                
+            });
+        });
+    };
+    
+    $scope.showHideColumns = function(){
+        
+        $scope.hiddenGridColumns = 0;
+        
+        angular.forEach($scope.gridColumns, function(gridColumn){
+            if(!gridColumn.show){
+                $scope.hiddenGridColumns++;
+            }
+        });
+        
+        var modalInstance = $modal.open({
+            templateUrl: 'views/column-modal.html',
+            controller: 'ColumnDisplayController',
+            resolve: {
+                gridColumns: function () {
+                    return $scope.gridColumns;
+                },
+                hiddenGridColumns: function(){
+                    return $scope.hiddenGridColumns;
+                }
+            }
+        });
+
+        modalInstance.result.then(function (gridColumns) {
+            $scope.gridColumns = gridColumns;
+        }, function () {
+        });
+    };
+    
+    $scope.sortTEIGrid = function(gridHeader){
+        if ($scope.sortHeader === gridHeader.id){
+            $scope.reverse = !$scope.reverse;
+            return;
+        }        
+        $scope.sortHeader = gridHeader.id;
+        $scope.reverse = false;    
+    };
+    
+    $scope.searchInGrid = function(gridColumn){
+        
+        $scope.currentFilter = gridColumn;
+       
+        for(var i=0; i<$scope.gridColumns.length; i++){
+            
+            //toggle the selected grid column's filter
+            if($scope.gridColumns[i].id === gridColumn.id){
+                $scope.gridColumns[i].showFilter = !$scope.gridColumns[i].showFilter;
+            }            
+            else{
+                $scope.gridColumns[i].showFilter = false;
+            }
+        }
+    };    
+    
+    $scope.removeStartFilterText = function(gridColumnId){
+        $scope.filterText[gridColumnId].start = undefined;
+    };
+    
+    $scope.removeEndFilterText = function(gridColumnId){
+        $scope.filterText[gridColumnId].end = undefined;
+    };
+    
+    $scope.showDashboard = function(tei){
+        $location.path('/dashboard').search({tei: tei.id,                                            
+                                            program: $scope.selectedProgram ? $scope.selectedProgram.id: null});
+    };
 });
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/report/overdue-events.html'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/report/overdue-events.html	2014-08-27 15:40:36 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/report/overdue-events.html	2014-09-09 13:26:15 +0000
@@ -4,8 +4,8 @@
 <div id="leftBar">   
     <div class="left-bar-menu" ng-controller="LeftBarMenuController">
         <ul class="nav nav-pills nav-stacked">
-            <li><a href ng-click="showHome()">{{'registration_and_data_entry' | translate}}</a></li>
-            <li><a href ng-click="showReportTypes()">{{'reports' | translate}}</a></li>            
+            <li><a href ng-click="showHome()">{{'registration_and_data_entry'| translate}}</a></li>
+            <li><a href ng-click="showReportTypes()">{{'reports'| translate}}</a></li>            
         </ul>
     </div>  
     <div id="orgUnitTree" style="margin-top:20px">
@@ -18,55 +18,172 @@
     <!--- selected org unit ends  -->
 </div>
 
-<div id="mainPage" class="bordered-div">
-    <h2>{{'overdue_events' | translate}}</h2>
+<div id="mainPage" class="page">
+
+    <!-- top bar begins -->
+    <div class="row top-bar">        
+        <div class="col-sm-12">            
+            {{'overdue_events'| translate}}
+            <div class="pull-right">
+                <div class="btn-group" dropdown is-open="status.isopen">
+                    <button type="button" class="btn btn-default dropdown-toggle" ng-disabled="!teiList.length">
+                        <i class="fa fa-cog" title="{{'settings'| translate}}"></i>
+                    </button>
+                    <ul class="dropdown-menu pull-right" role="menu">
+                        <li ng-show="teiList.length > 0"><a href ng-click="showHideColumns()">{{'show_hide_columns'| translate}}</a></li>
+                    </ul>
+                </div>
+            </div>            
+        </div>        
+    </div>
+    <!-- top bar ends -->
+
+    <!--input form begins -->
     <form name="outerForm" novalidate>               
         <div class="row">
-            <div class="col-sm-12 col-md-8">
+            <div class="col-sm-8 col-md-6">
                 <table class="table table-borderless table-striped">
                     <tr>
-                        <td class='col-sm-6 col-md-4 vertical-center'>
-                            {{'program' | translate}}
+                        <td class='col-sm-4 col-md-3 vertical-center'>
+                            {{'program'| translate}}
                         </td>
-                        <td class='col-sm-6 col-md-4'>
+                        <td class='col-sm-4 col-md-3'>
                             <select ng-model="selectedProgram"
                                     class="form-control"
                                     ng-options="program as program.name for program in programs | orderBy: 'name'" 
                                     ng-disabled="programs.length < 1">
-                                <option value="">{{programs.length > 0 ? 'please_select_a_program' : 'no_program_exists' | translate}}</option>
+                                <option value="">{{programs.length > 0 ? 'please_select_a_program' : 'no_program_exists'| translate}}</option>
                             </select>
                         </td>
                     </tr>
                     <tr>
-                        <td class='col-sm-6 col-md-4 vertical-center'>{{'org_unit'| translate}}</td>
-                        <td class='col-sm-6 col-md-4'>                 
+                        <td class='col-sm-4 col-md-3 vertical-center'>{{'org_unit'| translate}}</td>
+                        <td class='col-sm-4 col-md-3'>                 
                             <label><input type="radio" ng-model="selectedOuMode.name" name="selected" value="SELECTED"> {{'SELECTED'| translate}}</label><br/>
                             <label><input type="radio" ng-model="selectedOuMode.name" name="children" value="CHILDREN"> {{'CHILDREN'| translate}}</label><br/>
                             <label><input type="radio" ng-model="selectedOuMode.name" name="descendants" value="DESCENDANTS"> {{'DESCENDANTS'| translate}}</label><br/>
                             <label><input type="radio" ng-model="selectedOuMode.name" name="accessible" value="ACCESSIBLE"> {{'ACCESSIBLE'| translate}}</label>
                         </td>
                     </tr>
+                    <tr>
+                        <label>                    
+                            <td class='col-sm-4 col-md-3 vertical-center'>
+                                {{'filter'| translate}}
+                            </td>
+                            <td>
+                                <label>
+                                    <input type="checkbox" ng-change="markForFollowup()" ng-model="displayMode.onlyMarkedFollowup"/>  {{'only_marked_for_followup' | translate}}
+                                </label>                                
+                            </td>
+                        </label>
+                    </tr>
                 </table>
             </div>
         </div>
-        <div class="row">
+        <div class="row">            
             <div class="col-sm-8 col-md-6">
-                <table class="table-borderless">
-                    <tr>
-                        <td>
-                            <input type="text" name="reportStartDate" placeholder="{{'start_date'| translate}} (yyyy-mm-dd)" class="form-control" ng-date ng-model="report.startDate" max="today" ng-required="true"/> 
-                            <span ng-show="outerForm.submitted && outerForm.reportStartDate.$invalid" style="color:red;font-size:12px">{{'required'| translate}} (yyyy-mm-dd)</span>
-                        </td>
-                        <td>
-                            <input type="text" name="reportEndDate" placeholder="{{'end_date'| translate}} (yyyy-mm-dd)" class="form-control" ng-date ng-model="report.endDate" max="today" ng-required="true"/>
-                            <span ng-show="outerForm.submitted && outerForm.reportEndDate.$invalid" style="color:red;font-size:12px">{{'required'| translate}} (yyyy-mm-dd)</span>
-                        </td>
-                    </tr>
-                </table>                
-            </div>
-            <div class="col-md-6 trim">
-                <button type="button" class="btn btn-primary" ng-click="generateReport()" ng-disabled="!selectedProgram">{{'go'| translate}}</button>               
+                <button type="button" class="btn btn-primary" ng-click="generateReport(selectedProgram, report, selectedOuMode)" ng-disabled="!selectedProgram">{{'go'| translate}}</button>               
+            </div>
+        </div>
+
+        <div class="row" ng-if="programs.length < 1">        
+            <div class="col-sm-8 col-md-6 vertical-spacing">
+                <div class="alert alert-warning">{{'no_program_exists_report'| translate}}</div> 
+            </div>
+        </div>
+        <div class="row" ng-if="programs.length > 0 && !selectedProgram">        
+            <div class="col-sm-8 col-md-6 vertical-spacing">
+                <div class="alert alert-warning">{{'please_select_program_report'| translate}}</div> 
             </div>
         </div>
     </form>
-</div>
+    <!--input form ends -->
+
+    <img src="../images/ajax-loader-bar.gif" ng-if="reportStarted && !reportFinished"/>
+
+    <!-- upcoming events list begins -->
+    <div ng-if="reportFinished">
+
+        <div ng-switch="teiList.length">                    
+            <div ng-switch-when="undefined">
+                <div class="alert alert-warning vertical-spacing">
+                    {{'no_data_found'| translate}}
+                </div>
+            </div>
+            <div ng-switch-when="0">  
+                <div class="alert alert-warning vertical-spacing">
+                    {{'no_data_found'| translate}}
+                </div>
+            </div>    
+            <div ng-switch-default>
+                <!-- report begins -->
+                <div class="vertical-spacing">   
+                    <table class="listTable dhis2-table-striped-border dhis2-table-hover">               
+                        <thead>                        
+                            <tr>
+                                <th ng-show="gridColumn.show" ng-repeat="gridColumn in gridColumns">
+
+                                    <!-- sort icon begins -->
+                                    <span ng-click="sortTEIGrid(gridColumn)">
+                                        {{gridColumn.name| translate}}
+                                        <i ng-if="sortHeader == gridColumn.id && reverse" class="fa fa-sort-desc"></i>
+                                        <i ng-if="sortHeader == gridColumn.id && !reverse" class="fa fa-sort-asc"></i>
+                                    </span>
+                                    <!-- sort icon ends -->
+
+                                    <!-- filter icon begins -->
+                                    <span class='pull-right'>
+                                        <span ng-show="gridColumn.type != 'date' && gridColumn.type != 'int'">
+                                            <a href ng-click="searchInGrid(gridColumn)" title="{{'search'| translate}}"><span ng-class="{true: 'filter - without - content', false: 'filter - with - content'} [filterText[gridColumn.id] == undefined || filterText[gridColumn.id] == '']"><i class="fa fa-search"></i></span></a>
+                                        </span>
+                                        <span ng-show="gridColumn.type === 'date' || gridColumn.type === 'int'">
+                                            <a href ng-click="searchInGrid(gridColumn)" title="{{'search'| translate}}"><span ng-class="{true: 'filter - without - content', false: 'filter - with - content'} [(filterText[gridColumn.id].start == undefined || filterText[gridColumn.id].start == '') && (filterText[gridColumn.id].end == undefined || filterText[gridColumn.id].end == '')]"><i class="fa fa-search"></i></span></a>
+                                        </span>                                                    
+                                    </span>
+                                    <!-- filter icon ends -->
+
+                                    <!-- filter input field begins -->
+                                    <span ng-show="gridColumn.showFilter">  
+                                        <span ng-switch="gridColumn.type">
+                                            <span ng-switch-when="int">
+                                                <input style="width: 45%;" placeholder="{{'lower_limit'| translate}}" type="number" ng-model="filterText[gridColumn.id].start" ng-blur="searchInGrid(gridColumn)">
+                                                <input style="width: 45%;" placeholder="{{'upper_limit'| translate}}" type="number" ng-model="filterText[gridColumn.id].end" ng-blur="searchInGrid(gridColumn)">
+                                            </span>
+                                            <span ng-switch-when="date">
+                                                <input style="width: 70%;" placeholder="{{'start_date'| translate}}" type="text" ng-model="filterText[gridColumn.id].start" data-ng-date readonly="readonly">
+                                                <span ng-hide="filterText[gridColumn.id].start == undefined || filterText[gridColumn.id].start == ''">
+                                                    <a href ng-click='removeStartFilterText(gridColumn.id)'><span class='black'><i class="fa fa-trash-o"></i></span></a>                                                        
+                                                </span>
+                                                <input style="width: 70%;" placeholder="{{'end_date'| translate}}" type="text" ng-model="filterText[gridColumn.id].end" data-ng-date readonly="readonly">
+                                                <span ng-hide="filterText[gridColumn.id].end == undefined || filterText[gridColumn.id].end == ''">
+                                                    <a href ng-click='removeEndFilterText(gridColumn.id)'><span class='black'><i class="fa fa-trash-o"></i></span></a>                                                        
+                                                </span> 
+                                            </span>
+                                            <span ng-switch-default>
+                                                <input type="text" style="width: 90%;" ng-model="filterText[gridColumn.id]" ng-blur="searchInGrid(gridColumn)">
+                                            </span> 
+                                        </span>                                                    
+                                    </span>
+                                    <!-- filter input field ends -->
+
+                                </th>
+                            </tr>                        
+                        </thead>
+                        <tbody id="list">
+                            <tr ng-repeat="tei in teiList| orderBy:sortHeader:reverse | gridFilter:filterText:filterTypes"
+                                ng-click="showDashboard(tei)"
+                                title="{{'go_to_dashboard'| translate}}">
+                                <td ng-show="gridColumn.show"                                            
+                                    ng-repeat="gridColumn in gridColumns" ng-if='displayMode.onlyMarkedFollowup ? tei.followup:true'>                                                
+                                    {{tei[gridColumn.id]}}                                                
+                                </td>                                
+                            </tr>
+                        </tbody>        
+                    </table>                    
+                </div>
+                <!-- report ends -->
+            </div>
+        </div> 
+    </div>
+    <!-- upcoming events list ends -->
+</div>
\ No newline at end of file

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/report/upcoming-events-controller.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/report/upcoming-events-controller.js	2014-09-09 12:54:28 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-tracker-capture/components/report/upcoming-events-controller.js	2014-09-09 13:26:15 +0000
@@ -11,7 +11,6 @@
                 AttributesFactory,
                 ProgramFactory,
                 DHIS2EventFactory,
-                ContextMenuSelectedItem,
                 storage) {
 
     TranslationService.translate();
@@ -46,10 +45,8 @@
     
     //watch for selection of program
     $scope.$watch('selectedProgram', function() {   
-        if( angular.isObject($scope.selectedProgram)){            
-            $scope.reportFinished = false;
-            $scope.reportStarted = false;
-        }
+        $scope.reportFinished = false;
+        $scope.reportStarted = false;
     });
     
     $scope.generateReport = function(program, report, ouMode){