1 var osb = lf.schema.create('offline', 2);
3 osb.createTable('Object').
4 addColumn('type', lf.Type.STRING). // class hint
5 addColumn('id', lf.Type.STRING). // obj id
6 addColumn('object', lf.Type.OBJECT).
7 addPrimaryKey(['type','id']);
9 osb.createTable('CacheDate').
10 addColumn('type', lf.Type.STRING). // class hint
11 addColumn('cachedate', lf.Type.DATE_TIME). // when was it last updated
12 addPrimaryKey(['type']);
14 osb.createTable('Setting').
15 addColumn('name', lf.Type.STRING).
16 addColumn('value', lf.Type.STRING).
17 addPrimaryKey(['name']);
19 osb.createTable('StatCat').
20 addColumn('id', lf.Type.INTEGER).
21 addColumn('value', lf.Type.OBJECT).
22 addPrimaryKey(['id']);
24 osb.createTable('OfflineXact').
25 addColumn('seq', lf.Type.INTEGER).
26 addColumn('value', lf.Type.OBJECT).
27 addPrimaryKey(['seq'], true);
29 osb.createTable('OfflineBlocks').
30 addColumn('barcode', lf.Type.STRING).
31 addColumn('reason', lf.Type.STRING).
32 addPrimaryKey(['barcode']);
35 * Core Service - egLovefield
37 * Lovefield wrapper factory for low level offline stuff
40 angular.module('egCoreMod')
42 .factory('egLovefield', ['$q','$rootScope','egCore','$timeout',
43 function($q , $rootScope , egCore , $timeout) {
47 function connectOrGo() {
49 if (lf.offlineDB) { // offline DB connected
53 if (service.cannotConnect) { // connection will never happen
57 if (service.connectPromise) { // connection in progress
58 return service.connectPromise;
61 // start a new connection attempt
63 var deferred = $q.defer();
65 console.debug('attempting offline DB connection');
68 console.debug('successfully connected to offline DB');
69 service.connectPromise = null;
74 // assumes that a single connection failure means
75 // a connection will never succeed.
76 service.cannotConnect = true;
77 console.error('Cannot connect to offline DB: ' + err);
81 service.connectPromise = deferred.promise;
82 return service.connectPromise;
85 service.isCacheGood = function (type) {
87 return connectOrGo().then(function() {
88 var cacheDate = lf.offlineDB.getSchema().table('CacheDate');
91 select(cacheDate.cachedate).
93 where(cacheDate.type.eq(type)).
94 exec().then(function(results) {
95 if (results.length == 0) {
96 return $q.when(false);
101 // hard-coded 1 day offline cache timeout
102 return $q.when((now.getTime() - results[0]['cachedate'].getTime()) <= 86400000);
107 service.destroyPendingOfflineXacts = function () {
108 return connectOrGo().then(function() {
109 var table = lf.offlineDB.getSchema().table('OfflineXact');
117 service.havePendingOfflineXacts = function () {
118 return connectOrGo().then(function() {
119 var table = lf.offlineDB.getSchema().table('OfflineXact');
121 select(table.reason).
124 then(function(list) {
125 return $q.when(Boolean(list.length > 0))
130 service.retrievePendingOfflineXacts = function () {
131 return connectOrGo().then(function() {
132 var table = lf.offlineDB.getSchema().table('OfflineXact');
137 then(function(list) {
138 return $q.when(list.map(function(x) { return x.value }))
143 service.destroyOfflineBlocks = function () {
144 return connectOrGo().then(function() {
145 var table = lf.offlineDB.getSchema().table('OfflineBlocks');
155 service.addOfflineBlock = function (barcode, reason) {
156 return connectOrGo().then(function() {
157 var table = lf.offlineDB.getSchema().table('OfflineBlocks');
162 values([ table.createRow({ barcode : barcode, reason : reason }) ]).
168 // Returns a promise with true for blocked, false for not blocked
169 service.testOfflineBlock = function (barcode) {
170 return connectOrGo().then(function() {
171 var table = lf.offlineDB.getSchema().table('OfflineBlocks');
173 select(table.reason).
175 where(table.barcode.eq(barcode)).
176 exec().then(function(list) {
177 if(list.length > 0) return $q.when(list[0].reason);
178 return $q.when(null);
183 service.addOfflineXact = function (obj) {
184 return connectOrGo().then(function() {
185 var table = lf.offlineDB.getSchema().table('OfflineXact');
190 values([ table.createRow({ value : obj }) ]).
196 service.setStatCatsCache = function (statcats) {
197 if (lf.isOffline) return $q.when();
199 return connectOrGo().then(function() {
200 var table = lf.offlineDB.getSchema().table('StatCat');
203 angular.forEach(statcats, function (val) {
204 rlist.push(table.createRow({
206 value : egCore.idl.toHash(val)
217 service.getStatCatsCache = function () {
218 return connectOrGo().then(function() {
220 var table = lf.offlineDB.getSchema().table('StatCat');
225 exec().then(function(list) {
226 angular.forEach(list, function (s) {
227 var sc = egCore.idl.fromHash('actsc', s.value);
229 if (angular.isArray(sc.default_entries())) {
231 sc.default_entries().map( function (k) {
232 return egCore.idl.fromHash('actsced', k);
237 if (angular.isArray(sc.entries())) {
239 sc.entries().map( function (k) {
240 return egCore.idl.fromHash('actsce', k);
247 return $q.when(result);
253 service.setSettingsCache = function (settings) {
254 if (lf.isOffline) return $q.when();
256 return connectOrGo().then(function() {
258 var table = lf.offlineDB.getSchema().table('Setting');
261 angular.forEach(settings, function (val, key) {
265 value : JSON.stringify(val)
278 service.getSettingsCache = function (settings) {
279 return connectOrGo().then(function() {
281 var table = lf.offlineDB.getSchema().table('Setting');
283 var search_pred = table.name.isNotNull();
284 if (settings && settings.length) {
285 search_pred = table.name.in(settings);
289 select(table.name, table.value).
292 exec().then(function(list) {
293 angular.forEach(list, function (s) {
294 s.value = JSON.parse(s.value)
296 return $q.when(list);
301 service.setListInOfflineCache = function (type, list) {
302 if (lf.isOffline) return $q.when();
304 return connectOrGo().then(function() {
306 service.isCacheGood(type).then(function(good) {
308 var object = lf.offlineDB.getSchema().table('Object');
309 var cacheDate = lf.offlineDB.getSchema().table('CacheDate');
310 var pkey = egCore.idl.classes[type].pkey;
312 angular.forEach(list, function(item) {
313 var row = object.createRow({
315 id : '' + item[pkey](),
316 object : egCore.idl.toHash(item)
318 lf.offlineDB.insertOrReplace().into(object).values([row]).exec();
321 var row = cacheDate.createRow({
323 cachedate : new Date()
326 console.log('egLovefield saving ' + type + ' list');
327 lf.offlineDB.insertOrReplace().into(cacheDate).values([row]).exec();
333 service.getListFromOfflineCache = function(type) {
334 return connectOrGo().then(function() {
336 var object = lf.offlineDB.getSchema().table('Object');
339 select(object.object).
341 where(object.type.eq(type)).
342 exec().then(function(results) {
343 return $q.when(results.map(function(item) {
344 return egCore.idl.fromHash(type,item['object'])
350 service.reconstituteList = function(type) {
352 console.log('egLovefield reading ' + type + ' list');
353 return service.getListFromOfflineCache(type).then(function (list) {
354 egCore.env.absorbList(list, type, true)
355 return $q.when(true);
358 return $q.when(false);
361 service.reconstituteTree = function(type) {
363 console.log('egLovefield reading ' + type + ' tree');
365 var pkey = egCore.idl.classes[type].pkey;
366 var parent_field = 'parent';
369 parent_field = 'parent_ou';
372 return service.getListFromOfflineCache(type).then(function (list) {
375 angular.forEach(list, function (item) {
377 // Special case for aou, to reconstitue ou_type
379 if (item.ou_type()) {
380 item.ou_type( egCore.idl.fromHash('aout', item.ou_type()) );
384 hash[''+item[pkey]()] = item;
385 if (!item[parent_field]()) {
387 } else if (angular.isObject(item[parent_field]())) {
388 // un-objectify the parent
390 item[parent_field]()[pkey]()
395 angular.forEach(list, function (item) {
396 item.children([]); // just clear it out if there's junk in there
398 if (item[parent_field]()) {
399 item[parent_field]( hash[''+item[parent_field]()] );
402 item.children( list.filter(function (kid) {
403 return kid[parent_field]() == item[pkey]();
407 egCore.env.absorbTree(top, type, true)
411 return $q.when(false);