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 osb.connect().then(function (db) {
37 lf.connecting = false;
41 * Core Service - egLovefield
43 * Lovefield wrapper factory for low level offline stuff
46 angular.module('egCoreMod')
48 .factory('egLovefield', ['$q','$rootScope','egCore','$timeout',
49 function($q , $rootScope , egCore , $timeout) {
53 function connectOrGo (resolver) {
58 // apparently, this might take a while...
59 if (lf.connecting) return $timeout(function() {
60 return connectOrGo(resolver);
63 console.log('egLovefield connecting to offline DB');
66 return osb.connect().then(function (db) {
71 alert('attempted reconnect failure: ' + err.toString());
75 service.isCacheGood = function (type) {
77 return connectOrGo(function() {
78 var cacheDate = lf.offlineDB.getSchema().table('CacheDate');
81 select(cacheDate.cachedate).
83 where(cacheDate.type.eq(type)).
84 exec().then(function(results) {
85 if (results.length == 0) {
86 return $q.when(false);
91 // hard-coded 1 day offline cache timeout
92 return $q.when((now.getTime() - results[0]['cachedate'].getTime()) <= 86400000);
97 service.destroyPendingOfflineXacts = function () {
98 return connectOrGo(function() {
99 var table = lf.offlineDB.getSchema().table('OfflineXact');
107 service.havePendingOfflineXacts = function () {
108 return connectOrGo(function() {
109 var table = lf.offlineDB.getSchema().table('OfflineXact');
111 select(table.reason).
114 then(function(list) {
115 return $q.when(Boolean(list.length > 0))
120 service.retrievePendingOfflineXacts = function () {
121 return connectOrGo(function() {
122 var table = lf.offlineDB.getSchema().table('OfflineXact');
127 then(function(list) {
128 return $q.when(list.map(function(x) { return x.value }))
133 service.destroyOfflineBlocks = function () {
134 return connectOrGo(function() {
135 var table = lf.offlineDB.getSchema().table('OfflineBlocks');
145 service.addOfflineBlock = function (barcode, reason) {
146 return connectOrGo(function() {
147 var table = lf.offlineDB.getSchema().table('OfflineBlocks');
152 values([ table.createRow({ barcode : barcode, reason : reason }) ]).
158 // Returns a promise with true for blocked, false for not blocked
159 service.testOfflineBlock = function (barcode) {
160 return connectOrGo(function() {
161 var table = lf.offlineDB.getSchema().table('OfflineBlocks');
163 select(table.reason).
165 where(table.barcode.eq(barcode)).
166 exec().then(function(list) {
167 if(list.length > 0) return $q.when(list[0].reason);
168 return $q.when(null);
173 service.addOfflineXact = function (obj) {
174 return connectOrGo(function() {
175 var table = lf.offlineDB.getSchema().table('OfflineXact');
180 values([ table.createRow({ value : obj }) ]).
186 service.setStatCatsCache = function (statcats) {
187 if (lf.isOffline) return $q.when();
189 return connectOrGo(function() {
190 var table = lf.offlineDB.getSchema().table('StatCat');
193 angular.forEach(statcats, function (val) {
194 rlist.push(table.createRow({
196 value : egCore.idl.toHash(val)
207 service.getStatCatsCache = function () {
208 return connectOrGo(function() {
210 var table = lf.offlineDB.getSchema().table('StatCat');
215 exec().then(function(list) {
216 angular.forEach(list, function (s) {
217 var sc = egCore.idl.fromHash('actsc', s.value);
219 if (angular.isArray(sc.default_entries())) {
221 sc.default_entries().map( function (k) {
222 return egCore.idl.fromHash('actsced', k);
227 if (angular.isArray(sc.entries())) {
229 sc.entries().map( function (k) {
230 return egCore.idl.fromHash('actsce', k);
237 return $q.when(result);
243 service.setSettingsCache = function (settings) {
244 if (lf.isOffline) return $q.when();
246 return connectOrGo(function() {
248 var table = lf.offlineDB.getSchema().table('Setting');
251 angular.forEach(settings, function (val, key) {
255 value : JSON.stringify(val)
268 service.getSettingsCache = function (settings) {
269 return connectOrGo(function() {
271 var table = lf.offlineDB.getSchema().table('Setting');
273 var search_pred = table.name.isNotNull();
274 if (settings && settings.length) {
275 search_pred = table.name.in(settings);
279 select(table.name, table.value).
282 exec().then(function(list) {
283 angular.forEach(list, function (s) {
284 s.value = JSON.parse(s.value)
286 return $q.when(list);
291 service.setListInOfflineCache = function (type, list) {
292 if (lf.isOffline) return $q.when();
294 return connectOrGo(function() {
296 service.isCacheGood(type).then(function(good) {
298 var object = lf.offlineDB.getSchema().table('Object');
299 var cacheDate = lf.offlineDB.getSchema().table('CacheDate');
300 var pkey = egCore.idl.classes[type].pkey;
302 angular.forEach(list, function(item) {
303 var row = object.createRow({
305 id : '' + item[pkey](),
306 object : egCore.idl.toHash(item)
308 lf.offlineDB.insertOrReplace().into(object).values([row]).exec();
311 var row = cacheDate.createRow({
313 cachedate : new Date()
316 console.log('egLovefield saving ' + type + ' list');
317 lf.offlineDB.insertOrReplace().into(cacheDate).values([row]).exec();
323 service.getListFromOfflineCache = function(type) {
324 return connectOrGo(function() {
326 var object = lf.offlineDB.getSchema().table('Object');
329 select(object.object).
331 where(object.type.eq(type)).
332 exec().then(function(results) {
333 return $q.when(results.map(function(item) {
334 return egCore.idl.fromHash(type,item['object'])
340 service.reconstituteList = function(type) {
342 console.log('egLovefield reading ' + type + ' list');
343 return service.getListFromOfflineCache(type).then(function (list) {
344 egCore.env.absorbList(list, type, true)
345 return $q.when(true);
348 return $q.when(false);
351 service.reconstituteTree = function(type) {
353 console.log('egLovefield reading ' + type + ' tree');
355 var pkey = egCore.idl.classes[type].pkey;
356 var parent_field = 'parent';
359 parent_field = 'parent_ou';
362 return service.getListFromOfflineCache(type).then(function (list) {
365 angular.forEach(list, function (item) {
367 // Special case for aou, to reconstitue ou_type
369 if (item.ou_type()) {
370 item.ou_type( egCore.idl.fromHash('aout', item.ou_type()) );
374 hash[''+item[pkey]()] = item;
375 if (!item[parent_field]()) {
377 } else if (angular.isObject(item[parent_field]())) {
378 // un-objectify the parent
380 item[parent_field]()[pkey]()
385 angular.forEach(list, function (item) {
386 item.children([]); // just clear it out if there's junk in there
388 if (item[parent_field]()) {
389 item[parent_field]( hash[''+item[parent_field]()] );
392 item.children( list.filter(function (kid) {
393 return kid[parent_field]() == item[pkey]();
397 egCore.env.absorbTree(top, type, true)
401 return $q.when(false);