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');
69 console.debug('successfully connected to offline DB');
70 service.connectPromise = null;
75 // assumes that a single connection failure means
76 // a connection will never succeed.
77 service.cannotConnect = true;
78 console.error('Cannot connect to offline DB: ' + err);
82 // .connect() will throw an error if it detects that a connection
83 // attempt is already in progress; this can happen with PhantomJS
84 console.error('Cannot connect to offline DB: ' + e);
85 service.cannotConnect = true;
88 service.connectPromise = deferred.promise;
89 return service.connectPromise;
92 service.isCacheGood = function (type) {
94 return connectOrGo().then(function() {
95 var cacheDate = lf.offlineDB.getSchema().table('CacheDate');
98 select(cacheDate.cachedate).
100 where(cacheDate.type.eq(type)).
101 exec().then(function(results) {
102 if (results.length == 0) {
103 return $q.when(false);
106 var now = new Date();
108 // hard-coded 1 day offline cache timeout
109 return $q.when((now.getTime() - results[0]['cachedate'].getTime()) <= 86400000);
114 service.destroyPendingOfflineXacts = function () {
115 return connectOrGo().then(function() {
116 var table = lf.offlineDB.getSchema().table('OfflineXact');
124 service.havePendingOfflineXacts = function () {
125 return connectOrGo().then(function() {
126 var table = lf.offlineDB.getSchema().table('OfflineXact');
128 select(table.reason).
131 then(function(list) {
132 return $q.when(Boolean(list.length > 0))
137 service.retrievePendingOfflineXacts = function () {
138 return connectOrGo().then(function() {
139 var table = lf.offlineDB.getSchema().table('OfflineXact');
144 then(function(list) {
145 return $q.when(list.map(function(x) { return x.value }))
150 service.destroyOfflineBlocks = function () {
151 return connectOrGo().then(function() {
152 var table = lf.offlineDB.getSchema().table('OfflineBlocks');
162 service.addOfflineBlock = function (barcode, reason) {
163 return connectOrGo().then(function() {
164 var table = lf.offlineDB.getSchema().table('OfflineBlocks');
169 values([ table.createRow({ barcode : barcode, reason : reason }) ]).
175 // Returns a promise with true for blocked, false for not blocked
176 service.testOfflineBlock = function (barcode) {
177 return connectOrGo().then(function() {
178 var table = lf.offlineDB.getSchema().table('OfflineBlocks');
180 select(table.reason).
182 where(table.barcode.eq(barcode)).
183 exec().then(function(list) {
184 if(list.length > 0) return $q.when(list[0].reason);
185 return $q.when(null);
190 service.addOfflineXact = function (obj) {
191 return connectOrGo().then(function() {
192 var table = lf.offlineDB.getSchema().table('OfflineXact');
197 values([ table.createRow({ value : obj }) ]).
203 service.setStatCatsCache = function (statcats) {
204 if (lf.isOffline) return $q.when();
206 return connectOrGo().then(function() {
207 var table = lf.offlineDB.getSchema().table('StatCat');
210 angular.forEach(statcats, function (val) {
211 rlist.push(table.createRow({
213 value : egCore.idl.toHash(val)
224 service.getStatCatsCache = function () {
225 return connectOrGo().then(function() {
227 var table = lf.offlineDB.getSchema().table('StatCat');
232 exec().then(function(list) {
233 angular.forEach(list, function (s) {
234 var sc = egCore.idl.fromHash('actsc', s.value);
236 if (angular.isArray(sc.default_entries())) {
238 sc.default_entries().map( function (k) {
239 return egCore.idl.fromHash('actsced', k);
244 if (angular.isArray(sc.entries())) {
246 sc.entries().map( function (k) {
247 return egCore.idl.fromHash('actsce', k);
254 return $q.when(result);
260 service.setSettingsCache = function (settings) {
261 if (lf.isOffline) return $q.when();
263 return connectOrGo().then(function() {
265 var table = lf.offlineDB.getSchema().table('Setting');
268 angular.forEach(settings, function (val, key) {
272 value : JSON.stringify(val)
285 service.getSettingsCache = function (settings) {
286 return connectOrGo().then(function() {
288 var table = lf.offlineDB.getSchema().table('Setting');
290 var search_pred = table.name.isNotNull();
291 if (settings && settings.length) {
292 search_pred = table.name.in(settings);
296 select(table.name, table.value).
299 exec().then(function(list) {
300 angular.forEach(list, function (s) {
301 s.value = JSON.parse(s.value)
303 return $q.when(list);
308 service.setListInOfflineCache = function (type, list) {
309 if (lf.isOffline) return $q.when();
311 return connectOrGo().then(function() {
313 service.isCacheGood(type).then(function(good) {
315 var object = lf.offlineDB.getSchema().table('Object');
316 var cacheDate = lf.offlineDB.getSchema().table('CacheDate');
317 var pkey = egCore.idl.classes[type].pkey;
319 angular.forEach(list, function(item) {
320 var row = object.createRow({
322 id : '' + item[pkey](),
323 object : egCore.idl.toHash(item)
325 lf.offlineDB.insertOrReplace().into(object).values([row]).exec();
328 var row = cacheDate.createRow({
330 cachedate : new Date()
333 console.log('egLovefield saving ' + type + ' list');
334 lf.offlineDB.insertOrReplace().into(cacheDate).values([row]).exec();
340 service.getListFromOfflineCache = function(type) {
341 return connectOrGo().then(function() {
343 var object = lf.offlineDB.getSchema().table('Object');
346 select(object.object).
348 where(object.type.eq(type)).
349 exec().then(function(results) {
350 return $q.when(results.map(function(item) {
351 return egCore.idl.fromHash(type,item['object'])
357 service.reconstituteList = function(type) {
359 console.log('egLovefield reading ' + type + ' list');
360 return service.getListFromOfflineCache(type).then(function (list) {
361 egCore.env.absorbList(list, type, true)
362 return $q.when(true);
365 return $q.when(false);
368 service.reconstituteTree = function(type) {
370 console.log('egLovefield reading ' + type + ' tree');
372 var pkey = egCore.idl.classes[type].pkey;
373 var parent_field = 'parent';
376 parent_field = 'parent_ou';
379 return service.getListFromOfflineCache(type).then(function (list) {
382 angular.forEach(list, function (item) {
384 // Special case for aou, to reconstitue ou_type
386 if (item.ou_type()) {
387 item.ou_type( egCore.idl.fromHash('aout', item.ou_type()) );
391 hash[''+item[pkey]()] = item;
392 if (!item[parent_field]()) {
394 } else if (angular.isObject(item[parent_field]())) {
395 // un-objectify the parent
397 item[parent_field]()[pkey]()
402 angular.forEach(list, function (item) {
403 item.children([]); // just clear it out if there's junk in there
405 item.children( list.filter(function (kid) {
406 return kid[parent_field]() == item[pkey]();
410 angular.forEach(list, function (item) {
411 if (item[parent_field]()) {
412 item[parent_field]( hash[''+item[parent_field]()] );
416 egCore.env.absorbTree(top, type, true)
420 return $q.when(false);