← Back to team overview

dhis2-devs team mailing list archive

[Branch ~dhis2-devs-core/dhis2/trunk] Rev 17549: some cleanup; replaced localstorage based storagemanger for offline data storage with indexeddb

 

------------------------------------------------------------
revno: 17549
committer: Abyot Asalefew Gizaw <abyota@xxxxxxxxx>
branch nick: dhis2
timestamp: Thu 2014-11-20 12:36:44 +0100
message:
  some cleanup; replaced localstorage based storagemanger for offline data storage with indexeddb
modified:
  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/event-capture.js
  dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/services.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-event-capture/scripts/controllers.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/controllers.js	2014-11-19 19:47:21 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/controllers.js	2014-11-20 11:36:44 +0000
@@ -17,7 +17,7 @@
                 DHIS2EventFactory,
                 DHIS2EventService,
                 GeoJsonFactory,
-                ContextMenuSelectedItem,
+                ContextMenuSelectedItem,                
                 DateUtils,
                 ModalService,
                 DialogService) {   
@@ -56,10 +56,9 @@
     $scope.$watch('selectedOrgUnit', function(newObj, oldObj) {
         
         $scope.dhis2Events = [];
-        if( angular.isObject($scope.selectedOrgUnit)){            
-            //storage.set('SELECTED_OU', $scope.selectedOrgUnit);            
+        if( angular.isObject($scope.selectedOrgUnit)){
+            
             //apply translation - by now user's profile is fetched from server.
-
             TranslationService.translate();            
             $scope.loadPrograms();
         }
@@ -71,8 +70,7 @@
     
     //load programs associated with the selected org unit.
     $scope.loadPrograms = function() {
-
-        //$scope.selectedOrgUnit = orgUnit;
+        
         $scope.selectedProgram = null;
         $scope.selectedProgramStage = null;
         $scope.dhis2Events = [];
@@ -99,12 +97,10 @@
                 if(angular.isObject($scope.programs) && $scope.programs.length === 1){
                     $scope.selectedProgram = $scope.programs[0];
                     $scope.loadEvents();
-                }
-                
-            });       
-        }        
-    
-    };    
+                }                
+            });
+        }    
+    };
         
     //get events for the selected program (and org unit)
     $scope.loadEvents = function(){   
@@ -141,8 +137,7 @@
                     angular.forEach($scope.selectedProgramStage.programStageSections, function(section){
                         section.open = true;
                     });
-
-                    //$scope.customForm = CustomFormService.processCustomForm($scope.selectedProgramStage);
+                    
                     $scope.customForm = $scope.selectedProgramStage.dataEntryForm ? $scope.selectedProgramStage.dataEntryForm.htmlCode : null; 
 
                     $scope.prStDes = [];  
@@ -186,7 +181,7 @@
 
                     //Load events for the selected program stage and orgunit
                     DHIS2EventFactory.getByStage($scope.selectedOrgUnit.id, $scope.selectedProgramStage.id, $scope.pager ).then(function(data){
-
+                                            
                         if(data.events){
                             $scope.eventLength = data.events.length;
                         }                
@@ -264,11 +259,6 @@
 
                                     delete $scope.dhis2Events[i].dataValues;
                                 }
-                                /*else{//event is empty, remove from grid
-                                    var index = $scope.dhis2Events.indexOf($scope.dhis2Events[i]);                           
-                                    $scope.dhis2Events.splice(index,1);
-                                    i--;                           
-                                }*/
                             }
 
                             if($scope.noteExists){
@@ -276,8 +266,7 @@
                             }
                         }                
                         $scope.eventFetched = true;
-                    });            
-
+                    });
                 });
             });
         }        
@@ -386,10 +375,9 @@
     };    
     
     $scope.showEditEventInGrid = function(){
-        $scope.currentEvent = ContextMenuSelectedItem.getSelectedItem();  
+        $scope.currentEvent = ContextMenuSelectedItem.getSelectedItem();
         $scope.currentEventOrginialValue = angular.copy($scope.currentEvent);        
-        $scope.editingEventInGrid = !$scope.editingEventInGrid;              
-        //$scope.currentEvent['uid'] = $scope.currentEvent.event;
+        $scope.editingEventInGrid = !$scope.editingEventInGrid;
         
         $scope.outerForm.$valid = true;
     };
@@ -439,10 +427,7 @@
             if(val){
                 valueExists = true;            
                 if($scope.prStDes[dataElement].dataElement.type === 'string'){
-                    if($scope.prStDes[dataElement].dataElement.optionSet){
-                        /*if($scope.optionCodesByName[  '"' + val + '"']){
-                            val = $scope.optionCodesByName[  '"' + val + '"'];
-                        }*/
+                    if($scope.prStDes[dataElement].dataElement.optionSet){                        
                         val = OptionSetService.getNameOrCode($scope.optionSets[$scope.prStDes[dataElement].dataElement.optionSet.id].options,val); //$scope.optionSets[].options$scope.optionCodesByName[  '"' + val + '"'];
                     }
                 }
@@ -555,10 +540,7 @@
             var val = $scope.currentEvent[dataElement];
             
             if(val && $scope.prStDes[dataElement].dataElement.type === 'string'){
-                if($scope.prStDes[dataElement].dataElement.optionSet){                        
-                    /*if($scope.optionCodesByName[  '"' + val + '"']){
-                        val = $scope.optionCodesByName[  '"' + val + '"'];
-                    }*/ 
+                if($scope.prStDes[dataElement].dataElement.optionSet){                    
                     val = OptionSetService.getNameOrCode($scope.optionSets[$scope.prStDes[dataElement].dataElement.optionSet.id].options,val); 
                 }    
             }
@@ -578,7 +560,6 @@
                             dataValues: dataValues
                         };
 
-        
         if($scope.selectedProgramStage.captureCoordinates){
             updatedEvent.coordinate = {latitude: $scope.currentEvent.coordinate.latitude ? $scope.currentEvent.coordinate.latitude : '',
                                      longitude: $scope.currentEvent.coordinate.longitude ? $scope.currentEvent.coordinate.longitude : ''};             
@@ -644,10 +625,7 @@
         if( newValue != oldValue ){
             
             if($scope.prStDes[dataElement].dataElement.type === 'string'){
-                if($scope.prStDes[dataElement].dataElement.optionSet){
-                    /*if($scope.optionCodesByName[  '"' + newValue + '"']){
-                        newValue = $scope.optionCodesByName[  '"' + newValue + '"'];
-                    }*/
+                if($scope.prStDes[dataElement].dataElement.optionSet){                    
                     newValue = OptionSetService.getNameOrCode($scope.optionSets[$scope.prStDes[dataElement].dataElement.optionSet.id].options, newValue);//$scope.optionCodesByName[  '"' + newValue + '"'];
                 }
             }            

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/event-capture.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/event-capture.js	2014-11-19 19:47:21 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/event-capture.js	2014-11-20 11:36:44 +0000
@@ -4,9 +4,6 @@
 // whether current user has any organisation units
 dhis2.ec.emptyOrganisationUnits = false;
 
-// Instance of the StorageManager
-dhis2.ec.storageManager = new StorageManager();
-
 var EC_STORE_NAME = "dhis2ec";
 var i18n_no_orgunits = 'No organisation unit attached to current user, no data entry possible';
 var i18n_offline_notification = 'You are offline, data will be stored locally';
@@ -50,7 +47,11 @@
         {
             name: 'optionSets',
             adapters: adapters
-        }            
+        },
+        {
+            name: 'events',
+            adapters: adapters
+        }
     ]        
 });
 
@@ -89,27 +90,29 @@
     });
     
     $(document).bind('dhis2.online', function(event, loggedIn)
-    {        
+    {
         if (loggedIn)
-        {
-            if (dhis2.ec.storageManager.hasLocalData())
-            {
-                var message = i18n_need_to_sync_notification
+        {   
+            var OfflineStorageService = angular.element('body').injector().get('OfflineStorageService');
+            
+            OfflineStorageService.hasLocalData().then(function(localData){
+                if(localData){
+                    var message = i18n_need_to_sync_notification
                         + ' <button id="sync_button" type="button">' + i18n_sync_now + '</button>';
 
-                setHeaderMessage(message);
+                    setHeaderMessage(message);
 
-                $('#sync_button').bind('click', uploadLocalData);
-            }
-            else
-            {
-                if (dhis2.ec.emptyOrganisationUnits) {
-                    setHeaderMessage(i18n_no_orgunits);
-                }
-                else {
-                    setHeaderDelayMessage(i18n_online_notification);
-                }
-            }
+                    $('#sync_button').bind('click', uploadLocalData);
+                }
+                else{
+                    if (dhis2.ec.emptyOrganisationUnits) {
+                        setHeaderMessage(i18n_no_orgunits);
+                    }
+                    else {
+                        setHeaderDelayMessage(i18n_online_notification);
+                    }
+                }
+            });
         }
         else
         {
@@ -532,264 +535,14 @@
 
 function uploadLocalData()
 {
-    if ( !dhis2.ec.storageManager.hasLocalData() )
-    {
-        return;
-    }
-
-    setHeaderWaitMessage( i18n_uploading_data_notification );
-    
-    var events = dhis2.ec.storageManager.getEventsAsArray();   
-    
-    _.each( _.values( events ), function( event ) {
-        
-        if( event.hasOwnProperty('src')){ 
-            delete event.src;            
-        }       
-        delete event.event;
-    });    
-    
-    events = {events: events};
-    
-    //jackson insists for valid json, where properties are bounded with ""    
-    events = JSON.stringify(events);  
-    
-    $.ajax( {
-        url: '../api/events',
-        type: 'POST',
-        data: events,
-        contentType: 'application/json',              
-        success: function()
-        {
-            dhis2.ec.storageManager.clear();
-            log( 'Successfully uploaded local events' );      
-            setHeaderDelayMessage( i18n_sync_success );
-            selection.responseReceived(); //notify angular 
-        },
-        error: function( xhr )
-        {
-            if ( 409 == xhr.status ) // Invalid event
-            {
-                // there is something wrong with the data - ignore for now.
-
-                dhis2.ec.storageManager.clear();
-            }
-            else // Connection lost during upload
-            {
-                var message = i18n_sync_failed
-                    + ' <button id="sync_button" type="button">' + i18n_sync_now + '</button>';
-
-                setHeaderMessage( message );
-                $( '#sync_button' ).bind( 'click', uploadLocalData );
-            }
-        }
-    } );
-}
-
-// -----------------------------------------------------------------------------
-// StorageManager
-// -----------------------------------------------------------------------------
-
-/**
- * This object provides utility methods for localStorage and manages data entry
- * forms and data values.
- */
-function StorageManager()
-{
-    var MAX_SIZE = new Number(2600000);
-
-    /**
-     * Returns the total number of characters currently in the local storage.
-     *
-     * @return number of characters.
-     */
-    this.totalSize = function()
-    {
-        var totalSize = new Number();
-
-        for (var i = 0; i < localStorage.length; i++)
-        {
-            var value = localStorage.key(i);
-
-            if (value)
-            {
-                totalSize += value.length;
-            }
-        }
-
-        return totalSize;
-    };
-
-    /**
-     * Return the remaining capacity of the local storage in characters, ie. the
-     * maximum size minus the current size.
-     */
-    this.remainingStorage = function()
-    {
-        return MAX_SIZE - this.totalSize();
-    };
-    
-    /**
-     * Clears stored events. 
-     */
-    this.clear = function ()
-    {
-        localStorage.removeItem(EVENT_VALUES);        
-    };    
-    
-    /**
-     * Saves an event
-     *
-     * @param event The event in json format.
-     */
-    this.saveEvent = function(event)
-    {
-        //var newEvent = event;
-        
-        if( !event.hasOwnProperty('src') )
-        {
-            if( !event.event){
-                event.event = this.generatePseudoUid();
-                event.src = 'local';
-            }            
-        }        
-
-        var events = {};
-
-        if (localStorage[EVENT_VALUES] != null)
-        {
-            events = JSON.parse(localStorage[EVENT_VALUES]);
-        }
-
-        events[event.event] = event;
-
-        try
-        {
-            localStorage[EVENT_VALUES] = JSON.stringify(events);
-
-            log('Successfully stored event - locally');
-        }
-        catch (e)
-        {
-            log('Max local storage quota reached, not storing data value locally');
-        }
-    };
-    
-    /**
-     * Gets the value for the event with the given arguments, or null if it
-     * does not exist.
-     *
-     * @param id the event identifier.
-     *
-     */
-    this.getEvent = function(id)
-    {
-        if (localStorage[EVENT_VALUES] != null)
-        {
-            var events = JSON.parse(localStorage[EVENT_VALUES]);
-
-            return events[id];
-        }
-
-        return null;
-    };
-
-    /**
-     * Removes the given event from localStorage.
-     *
-     * @param event and identifiers in json format.
-     */
-    this.clearEvent = function(event)
-    {
-        var events = this.getAllEvents();
-
-        if (events != null && events[event.event] != null)
-        {
-            delete events[event.event];
-            localStorage[EVENT_VALUES] = JSON.stringify(events);
-        }
-    };
-    
-    /**
-     * Returns events matching the arguments provided
-     * 
-     * @param orgUnit 
-     * @param programStage
-     * 
-     * @return a JSON associative array.
-     */
-    this.getEvents = function(orgUnit, programStage)
-    {
-        var events = this.getEventsAsArray();
-        var match = [];
-        for( var i=0; i<events.length; i++){
-            if(events[i].orgUnit == orgUnit && events[i].programStage == programStage ){
-                match.push(events[i]);
-            }
-        }
-        
-        var pager = {pageSize: 50, page: 1, toolBarDisplay: 5, pageCount: 1};  
-        return {events: match, pager: pager};
-    };
-    
-    /**
-     *
-     * @return a JSON associative array.
-     */
-    this.getAllEvents = function()
-    {
-        return localStorage[EVENT_VALUES] != null ? JSON.parse( localStorage[EVENT_VALUES] ) : null;
-    };    
-
-    /**
-     * Returns all event objects in an array. Returns an empty array if no
-     * event exist. Items in array are guaranteed not to be undefined.
-     */
-    this.getEventsAsArray = function()
-    {
-        var values = new Array();
-        var events = this.getAllEvents();
-
-        if (undefined == events)
-        {
-            return values;
-        }
-
-        for (i in events)
-        {
-            if (events.hasOwnProperty(i) && undefined !== events[i])
-            {
-                values.push(events[i]);
-            }
-        }
-
-        return values;
-    };
-    
-    /**
-     * Indicates whether there exists data values or complete data set
-     * registrations in the local storage.
-     *
-     * @return true if local data exists, false otherwise.
-     */
-    this.hasLocalData = function()
-    {
-        var events = this.getAllEvents();        
-
-        if (events == null)
-        {
-            return false;
-        }
-        if (Object.keys(events).length < 1)
-        {
-            return false;
-        }    
-
-        return true;
-    };
-    
-    this.generatePseudoUid = function () 
-    {
-        return Math.random().toString(36).substr(2, 11);
-    };
-}
+    var OfflineStorageService = angular.element('body').injector().get('OfflineStorageService');
+    setHeaderWaitMessage(i18n_uploading_data_notification);
+     
+    OfflineStorageService.uploadLocalData().then(function(){
+        dhis2.ec.store.removeAll( 'events' );
+        log( 'Successfully uploaded local events' );      
+        setHeaderDelayMessage( i18n_sync_success );
+        selection.responseReceived(); //notify angular
+    });
+}
+

=== modified file 'dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/services.js'
--- dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/services.js	2014-11-19 19:47:21 +0000
+++ dhis-2/dhis-web/dhis-web-apps/src/main/webapp/dhis-web-event-capture/scripts/services.js	2014-11-20 11:36:44 +0000
@@ -9,13 +9,56 @@
     var store = new dhis2.storage.Store({
         name: 'dhis2ec',
         adapters: [dhis2.storage.IndexedDBAdapter, dhis2.storage.DomSessionStorageAdapter, dhis2.storage.InMemoryAdapter],
-        objectStores: ['ecPrograms', 'programStages', 'geoJsons', 'optionSets']
+        objectStores: ['ecPrograms', 'programStages', 'geoJsons', 'optionSets', 'events']
     });
     return{
         currentStore: store
     };
 })
 
+.factory('OfflineStorageService', function($http, $q, $rootScope, StorageService){
+    return {        
+        hasLocalData: function() {
+            var def = $q.defer();
+            StorageService.currentStore.open().done(function(){
+                StorageService.currentStore.getKeys('events').done(function(events){
+                    $rootScope.$apply(function(){
+                        def.resolve( events.length > 0 );
+                    });                    
+                });
+            });            
+            return def.promise;
+        },
+        getLocalData: function(){
+            var def = $q.defer();            
+            StorageService.currentStore.open().done(function(){
+                StorageService.currentStore.getAll('events').done(function(events){
+                    $rootScope.$apply(function(){
+                        def.resolve({events: events});
+                    });                    
+                });
+            });            
+            return def.promise;
+        },
+        uploadLocalData: function(){            
+            var def = $q.defer();
+            this.getLocalData().then(function(localData){                
+                var evs = {events: []};
+                angular.forEach(localData.events, function(ev){
+                    ev.event = ev.id;
+                    delete ev.id;
+                    evs.events.push(ev);
+                });
+
+                $http.post('../api/events', evs).then(function(evResponse){                            
+                    def.resolve();
+                });                      
+            });
+            return def.promise;
+        }
+    };
+})
+
 .service('DateUtils', function($filter, CalendarService){
     
     return {
@@ -106,8 +149,7 @@
 .factory('GeoJsonFactory', function($q, $rootScope, StorageService) { 
     return {
         getAll: function(){
-            
-            //console.log('I am trying to fetch geojsons');
+
             var def = $q.defer();
             
             StorageService.currentStore.open().done(function(){
@@ -228,7 +270,7 @@
 })
 
 /* factory for handling events */
-.factory('DHIS2EventFactory', function($http) {   
+.factory('DHIS2EventFactory', function($http, $q, StorageService, $rootScope) {   
     
     return {
         getByStage: function(orgUnit, programStage, pager){
@@ -239,59 +281,77 @@
             var promise = $http.get( url ).then(function(response){                    
                 return response.data;        
             }, function(){     
-                return dhis2.ec.storageManager.getEvents(orgUnit, programStage);                
+                //return dhis2.ec.storageManager.getEvents(orgUnit, programStage);                
+
+                var def = $q.defer();
+                StorageService.currentStore.open().done(function(){
+                    StorageService.currentStore.getAll('events').done(function(evs){
+                        var result = {events: [], pager: {pageSize: '', page: 1, toolBarDisplay: 5, pageCount: 1}};
+                        angular.forEach(evs, function(ev){                            
+                            if(ev.programStage === programStage && ev.orgUnit === orgUnit){
+                                ev.event = ev.id;
+                                result.events.push(ev);
+                            }
+                        }); 
+                        $rootScope.$apply(function(){
+                            def.resolve( result );
+                        });                    
+                    });
+                });            
+                return def.promise;
             });            
             
             return promise;
-        },
-        
+        },        
         get: function(eventUid){            
             var promise = $http.get('../api/events/' + eventUid + '.json').then(function(response){               
                 return response.data;                
             }, function(){
-                return dhis2.ec.storageManager.getEvent(eventUid);
+                //return dhis2.ec.storageManager.getEvent(eventUid);
+                var p = dhis2.ec.store.get('events', eventUid).then(function(ev){
+                    ev.event = eventUid;
+                    return ev;
+                });
+                return p;
             });            
             return promise;
-        },
-        
-        create: function(dhis2Event){            
-            var e = angular.copy(dhis2Event);            
-            dhis2.ec.storageManager.saveEvent(e);            
-        
+        },        
+        create: function(dhis2Event){
             var promise = $http.post('../api/events.json', dhis2Event).then(function(response){
-                dhis2.ec.storageManager.clearEvent(e);
                 return response.data;
-            }, function(){
-                return {importSummaries: [{status: 'SUCCESS', reference: e.event}]};
+            }, function(){            
+                dhis2Event.id = dhis2.util.uid();  
+                dhis2Event.event = dhis2Event.id;
+                dhis2.ec.store.set( 'events', dhis2Event );                
+                return {importSummaries: [{status: 'SUCCESS', reference: dhis2Event.id}]};
             });
             return promise;            
-        },
-        
+        },        
         delete: function(dhis2Event){
-            dhis2.ec.storageManager.clearEvent(dhis2Event);
             var promise = $http.delete('../api/events/' + dhis2Event.event).then(function(response){
                 return response.data;
-            }, function(){                
+            }, function(){
+                dhis2.ec.store.remove( 'events', dhis2Event.event );
             });
             return promise;           
-        },
-    
-        update: function(dhis2Event){  
-            dhis2.ec.storageManager.saveEvent(dhis2Event);
-            var promise = $http.put('../api/events/' + dhis2Event.event, dhis2Event).then(function(response){
-                dhis2.ec.storageManager.clearEvent(dhis2Event);
+        },    
+        update: function(dhis2Event){
+            var promise = $http.put('../api/events/' + dhis2Event.event, dhis2Event).then(function(response){              
                 return response.data;
             }, function(){
+                dhis2.ec.store.remove('events', dhis2Event.event);
+                dhis2Event.id = dhis2Event.event;
+                dhis2.ec.store.set('events', dhis2Event);
             });
             return promise;
-        },
-        
-        updateForSingleValue: function(singleValue, fullValue){            
-            dhis2.ec.storageManager.saveEvent(fullValue);            
+        },        
+        updateForSingleValue: function(singleValue, fullValue){        
             var promise = $http.put('../api/events/' + singleValue.event + '/' + singleValue.dataValues[0].dataElement, singleValue ).then(function(response){
-                dhis2.ec.storageManager.clearEvent(fullValue);
-                return response.data;
-            }, function(){                
+                 return response.data;
+            }, function(){
+                dhis2.ec.store.remove('events', fullValue.event);
+                fullValue.id = fullValue.event;
+                dhis2.ec.store.set('events', fullValue);
             });
             return promise;
         }
@@ -323,8 +383,13 @@
             });
 
             e.dataValues = dvs;
+            
+            if(event.coordinate){
+                e.coordinate = {latitude: event.coordinate.latitude ? event.coordinate.latitude : '',
+                                     longitude: event.coordinate.longitude ? event.coordinate.longitude : ''};
+            }
 
-            return e;  
+            return e;
         }        
     };
 })